Exemple #1
0
def get_outlets():
    if not config.outlets:
        cpi.cpiexec.pwr_init_complete = True
    if config.outlets and not cpi.cpiexec.pwr_init_complete:
        utils.spinner('Waiting for Power Threads To Complete', cpi.cpiexec.wait_for_threads)
        if cpi.pwr:
            return cpi.pwr.data
Exemple #2
0
    def trigger_udev(self):
        '''reload/trigger udev (udevadm)

        Returns:
            No return unless there is an error.
            Returns {str} if an error occurs.
        '''
        cmd = 'sudo udevadm control --reload && sudo udevadm trigger && systemctl is-active ser2net >/dev/null 2>&1'\
              '&& sudo systemctl stop ser2net && sleep 1 && sudo systemctl start ser2net'
        error = utils.spinner(
            'Triggering reload of udev & ser2net due to name change',
            utils.do_shell_cmd,
            cmd,
            shell=True)
        if not error:
            self.udev_pending = False
        else:
            log.show(
                'Failed to reload udev rules, you may need to rectify manually for adapter names to display correctly'
            )
            log.show(
                f'Check /var/log/syslog for errors, the rules file ({self.rules_file}) and reattempt {cmd} manually'
            )
            log.show(error)
Exemple #3
0
    def menu_exec(self, choice, menu_actions, calling_menu="main_menu"):
        '''Execute Menu Selection.  This method needs to be overhauled.

        The ConsolePiAction object defined but not used in __init__ is part of the plan for overhaul
        menu will build insance of the object for each selection. That will be used to determine what
        action to perform and what to do after etc.
        '''
        pwr = self.pwr

        if not config.debug and calling_menu not in ["dli_menu", "power_menu"]:
            os.system("clear")

        if (
            not choice.lower
            or choice.lower in menu_actions
            and menu_actions[choice.lower] is None
        ):
            (
                self.menu.rows,
                self.menu.cols,
            ) = (
                utils.get_tty_size()
            )  # re-calc tty size in case they've adjusted the window
            return

        else:
            ch = choice.lower
            try:  # Invalid Selection
                if isinstance(menu_actions[ch], dict):
                    if menu_actions[ch].get("cmd"):
                        # TimeStamp for picocom session log file if defined
                        menu_actions[ch]["cmd"] = menu_actions[ch]["cmd"].replace(
                            "{{timestamp}}", time.strftime("%F_%H.%M")
                        )

                        # -- // AUTO POWER ON LINKED OUTLETS \\ --
                        if (
                            config.power and "pwr_key" in menu_actions[ch]
                        ):
                            self.exec_auto_pwron(menu_actions[ch]["pwr_key"])

                        # -- // Print pre-connect messsge if provided \\ --
                        if menu_actions[ch].get("pre_msg"):
                            print(menu_actions[ch]["pre_msg"])

                        # --// execute the command \\--
                        try:
                            _error = None
                            if "exec_kwargs" in menu_actions[ch]:
                                c = menu_actions[ch]["cmd"]
                                _error = utils.do_shell_cmd(
                                    c, **menu_actions[ch]["exec_kwargs"]
                                )
                                if _error and self.autopwr_wait:
                                    # TODO simplify this after moving to action object
                                    _method = "ssh -t" if "ssh" in c else "telnet"
                                    if "ssh" in _method:
                                        _h = (
                                            c.split(f"{_method} ")[1]
                                            .split(" -p")[0]
                                            .split("@")[1]
                                        )
                                        _p = int(c.split("-p ")[1])
                                    elif _method == "telnet":
                                        c_list = c.split()
                                        _h = c_list[-2]
                                        _p = int(c_list[-1])

                                    def wait_for_boot():
                                        while True:
                                            try:
                                                if utils.is_reachable(_h, _p, silent=True):
                                                    break
                                                else:
                                                    time.sleep(3)
                                            except KeyboardInterrupt:
                                                self.autopwr_wait = False
                                                log.show("Connection Aborted")
                                                break

                                    print(
                                        "\nInitial Attempt Failed, but host is linked to an outlet that was"
                                    )
                                    print("off. Host may still be booting\n")
                                    utils.spinner(
                                        f"Waiting for {_h} to boot, CTRL-C to Abort",
                                        wait_for_boot,
                                    )
                                    if self.autopwr_wait:
                                        _error = utils.do_shell_cmd(c, **menu_actions[ch]["exec_kwargs"])
                                        self.autopwr_wait = False
                            else:
                                c = shlex.split(menu_actions[ch]["cmd"])
                                result = subprocess.run(c, stderr=subprocess.PIPE)
                                _stderr = result.stderr.decode("UTF-8")
                                if _stderr or result.returncode == 1:
                                    _error = utils.error_handler(c, _stderr)

                            if _error:
                                log.show(_error)

                            # -- // resize the terminal to handle serial connections that jack the terminal size \\ --
                            c = " ".join([str(i) for i in c])
                            if "picocom" in c:
                                os.system(
                                    "/etc/ConsolePi/src/consolepi-commands/resize >/dev/null"
                                )

                        except KeyboardInterrupt:
                            log.show("Aborted last command based on user input")

                    elif "function" in menu_actions[ch]:
                        args = (
                            menu_actions[ch]["args"]
                            if "args" in menu_actions[ch]
                            else []
                        )
                        kwargs = (
                            menu_actions[ch]["kwargs"]
                            if "kwargs" in menu_actions[ch]
                            else {}
                        )
                        confirmed, spin_text, name = self.confirm_and_spin(
                            menu_actions[ch], *args, **kwargs
                        )
                        if confirmed:
                            # update kwargs with name from confirm_and_spin method
                            if menu_actions[ch]["function"].__name__ == "pwr_rename":
                                kwargs["name"] = name

                            # // -- CALL THE FUNCTION \\--
                            if (
                                spin_text
                            ):  # start spinner if spin_text set by confirm_and_spin
                                with Halo(text=spin_text, spinner="dots2"):
                                    response = menu_actions[ch]["function"](
                                        *args, **kwargs
                                    )
                            else:  # no spinner
                                response = menu_actions[ch]["function"](*args, **kwargs)

                            # --// Power Menus \\--
                            if calling_menu in ["power_menu", "dli_menu"]:
                                if menu_actions[ch]["function"].__name__ == "pwr_all":
                                    with Halo(
                                        text="Refreshing Outlet States", spinner="dots"
                                    ):
                                        self.outlet_update(
                                            refresh=True, upd_linked=True
                                        )  # TODO can I move this to Outlets Class
                                else:
                                    _grp = menu_actions[ch]["key"]
                                    _type = menu_actions[ch]["args"][0]
                                    _addr = menu_actions[ch]["args"][1]
                                    # --// EVAL responses for dli outlets \\--
                                    if _type == "dli":
                                        host_short = utils.get_host_short(_addr)
                                        _port = menu_actions[ch]["kwargs"]["port"]
                                        # --// Operations performed on ALL outlets \\--
                                        if (
                                            isinstance(response, bool)
                                            and _port is not None
                                        ):
                                            if (
                                                menu_actions[ch]["function"].__name__
                                                == "pwr_toggle"
                                            ):
                                                self.spin.start(
                                                    "Request Sent, Refreshing Outlet States"
                                                )
                                                # threading.Thread(target=self.get_dli_outlets,
                                                # kwargs={'upd_linked': True, 'refresh': True}, name='pwr_toggle_refresh').start()
                                                upd_linked = (
                                                    True
                                                    if calling_menu == "power_menu"
                                                    else False
                                                )  # else dli_menu
                                                threading.Thread(
                                                    target=self.outlet_update,
                                                    kwargs={
                                                        "upd_linked": upd_linked,
                                                        "refresh": True,
                                                    },
                                                    name="pwr_toggle_refresh",
                                                ).start()
                                                if _grp in pwr.data["defined"]:
                                                    pwr.data["defined"][_grp]["is_on"][
                                                        _port
                                                    ]["state"] = response
                                                elif _port != "all":
                                                    pwr.data["dli_power"][_addr][_port][
                                                        "state"
                                                    ] = response
                                                else:  # dli toggle all
                                                    for t in threading.enumerate():
                                                        if (
                                                            t.name
                                                            == "pwr_toggle_refresh"
                                                        ):
                                                            t.join()  # if refresh thread is running join ~
                                                            # wait for it to complete.
                                                            # TODO Don't think this works or below
                                                            # wouldn't have been necessary.

                                                            # toggle all returns True (ON) or False (OFF) if command
                                                            # successfully sent.  In reality the ports
                                                            # may not be in the  state yet, but dli is working it.
                                                            # Update menu items to reflect end state
                                                            for p in pwr.data[
                                                                "dli_power"
                                                            ][_addr]:
                                                                pwr.data["dli_power"][
                                                                    _addr
                                                                ][p]["state"] = response
                                                            break
                                                self.spin.stop()
                                            # Cycle operation returns False if outlet is off, only valid on powered outlets
                                            elif (
                                                menu_actions[ch]["function"].__name__
                                                == "pwr_cycle"
                                                and not response
                                            ):
                                                log.show(
                                                    f"{host_short} Port {_port} is Off.  Cycle is not valid"
                                                )
                                            elif (
                                                menu_actions[ch]["function"].__name__
                                                == "pwr_rename"
                                            ):
                                                if response:
                                                    _name = pwr._dli[_addr].name(_port)
                                                    if _grp in pwr.data.get(
                                                        "defined", {}
                                                    ):
                                                        pwr.data["defined"][_grp][
                                                            "is_on"
                                                        ][_port]["name"] = _name
                                                    else:
                                                        threading.Thread(
                                                            target=self.outlet_update,
                                                            kwargs={
                                                                "upd_linked": True,
                                                                "refresh": True,
                                                            },
                                                            name="pwr_rename_refresh",
                                                        ).start()
                                                    pwr.data["dli_power"][_addr][_port][
                                                        "name"
                                                    ] = _name
                                        # --// str responses are errors append to error_msgs \\--
                                        # TODO refactor response to use new cpi.response(...)
                                        elif (
                                            isinstance(response, str)
                                            and _port is not None
                                        ):
                                            log.show(response)
                                        # --// Can Remove After Refactoring all responses to bool or str \\--
                                        elif isinstance(response, int):
                                            if (
                                                menu_actions[ch]["function"].__name__
                                                == "pwr_cycle"
                                                and _port == "all"
                                            ):
                                                if response != 200:
                                                    log.show(
                                                        "Error Response Returned {}".format(
                                                            response
                                                        )
                                                    )
                                            # This is a catch as for the most part I've tried to refactor so the pwr library
                                            # returns port state on success (True/False)
                                            else:
                                                if response in [200, 204]:
                                                    log.show(
                                                        "DEV NOTE: check pwr library ret=200 or 204"
                                                    )
                                                else:
                                                    _action = menu_actions[ch][
                                                        "function"
                                                    ].__name__
                                                    log.show(
                                                        f"Error returned from dli {host_short} when "
                                                        f"attempting to {_action} port {_port}"
                                                    )
                                    # --// EVAL responses for espHome outlets \\--
                                    elif _type == "esphome":
                                        host_short = utils.get_host_short(_addr)
                                        _port = menu_actions[ch]["kwargs"]["port"]
                                        # --// Operations performed on ALL outlets \\--
                                        if (isinstance(response, bool) and _port is not None):
                                            pwr.data['defined'][_grp]['is_on'][_port]['state'] = response
                                            if (
                                                menu_actions[ch]["function"].__name__
                                                == "pwr_cycle"
                                                and not response
                                            ):
                                                _msg = f"{_grp}({host_short})" if _grp != host_short else f"{_grp}"
                                                if _msg != _port:
                                                    _msg = f"{_msg} Port {_port} is Off. Cycle is not valid"
                                                else:
                                                    _msg = f"{_msg} is Off. Cycle is not valid"
                                                log.show(_msg)
                                        elif (isinstance(response, str) and _port is not None):
                                            log.show(response)

                                    # --// EVAL responses for GPIO and tasmota outlets \\--
                                    else:
                                        if (
                                            menu_actions[ch]["function"].__name__
                                            == "pwr_toggle"
                                        ):
                                            if _grp in pwr.data.get("defined", {}):
                                                if isinstance(response, bool):
                                                    pwr.data["defined"][_grp][
                                                        "is_on"
                                                    ] = response
                                                else:
                                                    pwr.data["defined"][_grp][
                                                        "errors"
                                                    ] = response
                                        elif (
                                            menu_actions[ch]["function"].__name__
                                            == "pwr_cycle"
                                            and not response
                                        ):
                                            log.show(
                                                "Cycle is not valid for Outlets in the off state"
                                            )
                                        elif (
                                            menu_actions[ch]["function"].__name__
                                            == "pwr_rename"
                                        ):
                                            log.show(
                                                "rename not yet implemented for {} outlets".format(
                                                    _type
                                                )
                                            )
                            elif calling_menu in ["key_menu", "rename_menu"]:
                                if response:
                                    log.show(response)
                        else:  # not confirmed
                            log.show("Operation Aborted by User")
                elif menu_actions[ch].__name__ in ["power_menu", "dli_menu"]:
                    menu_actions[ch](calling_menu=calling_menu)
                else:
                    menu_actions[ch]()
            except KeyError as e:
                if len(choice.orig) <= 2 or not self.exec_shell_cmd(choice.orig):
                    log.show(f"Invalid selection {e}, please try again.")
        return True
Exemple #4
0
                if sys.argv[3] in remotes:
                    print('Removing ' + sys.argv[3] + ' from local cloud cache')
                    remotes.pop(sys.argv[3])
                    cpi.remotes.update_local_cloud_file(remote_consoles=remotes, current_remotes=remotes)
                    print('Remotes remaining in local cache')
                    jprint(remotes)
                    print('{} Removed from local cache'.format(sys.argv[3]))
                else:
                    print(f'!! {sys.argv[3]} Not Found in Local Cache')
    elif sys.argv[1] == 'local':
        jprint(details)
    else:
        try:
            print(f'\nRemote Cache data for {sys.argv[1]}:')
            jprint(remotes[sys.argv[1]])
        except KeyError:
            dump['outlets'] = get_outlets()
            jprint(dump)
            print('!!!  {} Not Found entire data set above   !!!'.format(sys.argv[1]))

else:
    dump['outlets'] = get_outlets()
    jprint(dump)

if log.error_msgs:
    print('!! ', end='')
    print('\n!! '.join(log.error_msgs))

if config.outlets and not cpi.cpiexec.pwr_init_complete:
    utils.spinner('Exiting... Waiting for Power Threads To Complete', cpi.cpiexec.wait_for_threads)
def get_outlets():
    if not cpi.cpiexec.pwr_init_complete:
        utils.spinner('Waiting for Power Threads To Complete', cpi.cpiexec.wait_for_threads)
        return cpi.pwr.data