Пример #1
0
    def set_time_filter(self, value):
        """
        Interval in seconds before a new position should be sent to server
        """
        from cp_lib.parse_duration import TimeDuration

        # handle the "null" or 0 times, as disable
        value = self._test_value_as_none(value)

        if value is None:
            # then disable the distance filter
            if self.time_filter is not None:
                self.logger.debug("Disable time_filter")
            self.time_filter = None
        else:
            try:
                duration = TimeDuration(value)
            except AttributeError:
                raise ValueError("Bad Time Filter Value:{}".format(value))

            value = duration.get_seconds()

            # test Min/Max, clamp or throw ValueError
            value = self._test_value_limits(value, self.TIME_FILTER_LIMITS)
            if value != self.time_filter:
                self.time_filter = value
                self.logger.debug("Set time_filter = {} sec".format(value))
        return
Пример #2
0
    def main(self, app_main):
        """
        :param str app_main: the file name, such as "network.tcp_echo"
        :return int: code for sys.exit()
        """

        # in windows, safer to use time.clock(), but is useless in Linux
        start_time = time.time()

        logging.info("Router APP starting: {}".format(app_main))

        # follow SDK design to load settings, should be in root of tar.gzip
        self.settings = load_settings_json()

        # delay until all desired conditions are met
        self.start_delay()

        app_mod = importlib.import_module(app_main)
        app_base = app_mod.RouterApp(app_main)

        if True:
            # app_mod = importlib.import_module(app_main, "RouterApp")
            # app_mod = importlib.import_module("network.tcp_echo.tcp_echo")
            # print(app_mod)
            result = app_base.run()
        else:
            result = 0

        # see if we should delay before existing
        exit_delay = self.DEFAULT_EXIT_DELAY
        if self.SECTION_STARTUP in self.settings:
            # then we do have a [startup] section in settings.json

            if self.SETS_EXIT_DELAY in self.settings[self.SECTION_STARTUP]:
                # how many seconds to wait for boot conditions to be satisfied
                # here is string, we don't care what yet
                exit_delay = self.settings[self.SECTION_STARTUP][
                    self.SETS_EXIT_DELAY].lower()

        if exit_delay in ('forever', 'loop', 'true'):
            # we loop forever - use 'uninstall' action to stop
            while True:
                app_base.logger.debug("App Finished - Looping forever")
                time.sleep(self.EXIT_DELAY_PERIOD)

        elif exit_delay in (None, 'none', 'null', 'false'):
            # default - no delay at all
            app_base.logger.info("App exited - MAIN Exiting without delay")

        else:
            # if this throws exception, well we exit anyway
            # use time_duration to handle "300" or "5 min"
            time_duration = TimeDuration(exit_delay)
            exit_delay = time_duration.get_seconds()

            time_diff = time.time() - start_time
            if time_diff >= exit_delay:
                # app took longer than 'min delay', so just exist
                app_base.logger.info("No need for exit delay")
            else:
                # else, app was short/fast, delay to reduce restart thrashing
                app_base.logger.info(
                    "Exit Delay for at least {} seconds".format(exit_delay))
                while time_diff < exit_delay:
                    app_base.logger.debug(
                        "Exit Delay, wait at least %d seconds more" %
                        int(exit_delay - time_diff))
                    time.sleep(self.EXIT_DELAY_PERIOD)
                    time_diff = time.time() - start_time
                app_base.logger.info("Exit Delay finished")

        return result
Пример #3
0
    def start_delay(self):
        """
        Delay up to config seconds, waiting for boot conditions to be true

        :return: None
        """
        # we only delay if at least ONE condition is still not satisfied
        wait_conditions = 0

        time_duration = TimeDuration()

        # start with the defaults
        # use time_duration to handle "300" or "5 min"
        time_duration.parse_time_duration_to_seconds(self.DEF_BOOT_DELAY_SEC)
        delay_seconds = time_duration.get_seconds()
        delay_for_valid_time = self.DEF_DELAY_FOR_TIME
        delay_for_uplink = self.DEF_DELAY_FOR_WAN

        if self.SECTION_STARTUP in self.settings:
            # then we do have a [startup] section in settings.json

            if self.SET_BOOT_DELAY_SEC in self.settings[self.SECTION_STARTUP]:
                # how many seconds to wait for boot conditions to be satisfied
                time_duration.parse_time_duration_to_seconds(self.settings[
                    self.SECTION_STARTUP][self.SET_BOOT_DELAY_SEC])
                delay_seconds = time_duration.get_seconds()

            if self.SET_DELAY_FOR_TIME in self.settings[self.SECTION_STARTUP]:
                # see if we delay until time.time() is returning valid info,
                # which prevents initial time-series data from being
                # generated with bogus 1-1-1970 time-stamps
                delay_for_valid_time = \
                    self.settings[self.SECTION_STARTUP][self.SET_DELAY_FOR_TIME]

            if self.SET_DELAY_FOR_WAN in self.settings[self.SECTION_STARTUP]:
                # see if we delay until router has a valid WAN uplink, which
                # prevents cloud clients from mistakenly flipping into
                # FAULT/RECOVERY modes because they tried to connect to fast
                delay_for_uplink = self.settings[self.SECTION_STARTUP][
                    self.SET_DELAY_FOR_WAN]

        if delay_for_valid_time:
            wait_conditions += 1

        if delay_for_uplink:
            wait_conditions += 1

        # we cannot use clock() because under Linux it means nothing
        # TODO - what happens when time() jumps?
        start_time = time.time()
        while (wait_conditions > 0) and \
                (time.time() - start_time) < delay_seconds:
            # loop until end of time period, or all conditions are okay

            if delay_for_valid_time and hw_status.router_time_is_valid():
                # then check on time, if okay neutralize our conditions
                delay_for_valid_time = False
                wait_conditions -= 1
            else:
                logging.debug("Delay - waiting for valid time")

            if delay_for_uplink and hw_status.router_wan_online():
                # then check on wan-uplink, is okay neutralize our conditions
                delay_for_uplink = False
                wait_conditions -= 1
            else:
                logging.debug("Delay - waiting for WAN uplink")

            if wait_conditions > 0:
                time.sleep(self.BOOT_DELAY_SLEEP)
            # else we'll break / leave the WHILE loop

        return
Пример #4
0
def run_router_app(app_base):
    """

    :param CradlepointAppBase app_base: prepared resources: logger, cs_client
    :return:
    """
    # logger.debug("Settings({})".format(sets))

    # first, confirm no other function using serial
    value = SerialRedirectorConfig(app_base)
    value.refresh()
    if value.enabled():
        app_base.logger.error("Serial Redirector Function is Active!")
        app_base.logger.error("Aborting SDK application")
        return -3
    app_base.logger.debug("Good: Serial Redirector Function is Disabled.")

    value = SerialGpsConfig(app_base)
    value.refresh()
    if value.enabled():
        app_base.logger.error("Serial GPS Echo Function is Active!")
        app_base.logger.error("Aborting SDK application")
        return -4
    app_base.logger.debug("Good: Serial GPS Function is Disabled.")

    value = SerialGPIOConfig(app_base)
    value.refresh()
    if value.enabled():
        app_base.logger.error("Serial GPIO Function is Active!")
        app_base.logger.error("Aborting SDK application")
        return -5
    app_base.logger.debug("Good: Serial GPIO Function is Disabled.")

    server_loop = ModbusBridge()
    server_loop.logger = app_base.logger

    if "modbus_ip" in app_base.settings:
        temp = app_base.settings["modbus_ip"]
        if "host_ip" in temp:
            # assume is string of correct format
            server_loop.host_ip = clean_string(temp["host_ip"])

        if "host_port" in temp:
            # force to integer
            server_loop.host_port = parse_integer(temp["host_port"])

        if "idle_timeout" in temp:
            # support seconds, or like '5 min'
            duration = TimeDuration(clean_string(temp["idle_timeout"]))
            server_loop.idle_timeout = duration.get_seconds()

        if "protocol" in temp:
            value = validate_ia_protocol(clean_string(temp["protocol"]))
            if value not in (IA_PROTOCOL_MBTCP, IA_PROTOCOL_MBRTU,
                             IA_PROTOCOL_MBASC):
                raise ValueError("Invalid IP-packed Modbus Protocol {}".format(
                    type(value)))
            server_loop.host_protocol = value

    if "modbus_serial" in app_base.settings:
        temp = app_base.settings["modbus_serial"]
        if "port_name" in temp:
            server_loop.serial_name = clean_string(temp["port_name"])

        if "baud_rate" in temp:
            server_loop.serial_baud = parse_integer(temp["baud_rate"])

        if "parity" in temp:
            server_loop.serial_baud = parse_integer(temp["baud_rate"])

        if "protocol" in temp:
            value = validate_ia_protocol(clean_string(temp["protocol"]))
            # confirm is serial, so RTU or ASCII
            if value not in (IA_PROTOCOL_MBRTU, IA_PROTOCOL_MBASC):
                raise ValueError("Invalid Serial Modbus Protocol {}".format(
                    type(value)))
            server_loop.serial_protocol = value

    # this should run forever
    try:
        result = server_loop.run_loop()

    except KeyboardInterrupt:
        result = 0

    return result
Пример #5
0
    from cp_lib.load_settings_ini import copy_config_ini_to_json, \
        load_sdk_ini_as_dict
    from cp_lib.parse_duration import TimeDuration

    copy_config_ini_to_json()

    app_path = "demo/gps_replay"
    my_app = CradlepointAppBase(app_path, call_router=False)
    # force a heavy reload of INI (app base normally only finds JSON)
    my_app.settings = load_sdk_ini_as_dict(app_path)

    if len(sys.argv) == 2:
        # assume is numeric seconds
        shifter = parse_float(sys.argv[1])

    elif len(sys.argv) >= 3:
        # assume is tagged time, like "15 min"
        period = TimeDuration(sys.argv[1] + ' ' + sys.argv[2])
        shifter = parse_float(period.get_seconds())

    else:
        my_app.logger.warning("You need to append the time in seconds")
        sys.exit(-1)

    my_app.logger.info("Time shifter = {} seconds".format(shifter))

    _result = run_router_app(my_app, shifter)

    my_app.logger.info("Exiting, status code is {}".format(_result))
    sys.exit(_result)
Пример #6
0
    def __init__(self, name, app_base):
        """
        prep our thread, but do not start yet

        :param str name: name for the thread
        :param CradlepointAppBase app_base: prepared resources: logger, etc
        """
        threading.Thread.__init__(self, name=name)

        self.app_base = app_base
        self.app_base.logger.info("started INIT")

        # how long to delay between checking the GPIO
        self.loop_delay = self.app_base.settings["power_loss"].get(
            "check_input_delay", 15)
        # support things like '1 min' or 15
        duration = TimeDuration(self.loop_delay)
        self.loop_delay = float(duration.get_seconds())

        # how long to wait, to double-check LOSS
        self.loss_delay = self.app_base.settings["power_loss"].get(
            "loss_delay", 1)
        self.loss_delay = duration.parse_time_duration_to_seconds(
            self.loss_delay)

        # how long to wait, to double-check RESTORE
        self.restore_delay = self.app_base.settings["power_loss"].get(
            "restore_delay", 1)
        self.restore_delay = duration.parse_time_duration_to_seconds(
            self.restore_delay)

        # when GPIO matches this state, then power is lost
        self.state_in_alarm = self.app_base.settings["power_loss"].get(
            "match_on_power_loss", False)
        # support 'true', '1' etc - but finally is True/False
        self.state_in_alarm = parse_boolean(self.state_in_alarm)

        # when 'power is lost', send to LED
        self.led_in_alarm = self.app_base.settings["power_loss"].get(
            "led_on_power_loss", None)
        try:
            # see if the setting is None, to disable
            self.led_in_alarm = parse_none(self.led_in_alarm)

        except ValueError:
            # support 'true', '1' etc - but finally is True/False
            self.led_in_alarm = parse_boolean(self.led_in_alarm)

        # when GPIO matches this state, then power is lost
        self.site_name = self.app_base.settings["power_loss"].get(
            "site_name", "My Site")

        # create an event to manage our stopping
        # (Note: on CP router, this isn't strictly true, as when the parent is
        # stopped/halted, the child dies as well. However, you may want
        # your sub task to clean up before it exists
        self.keep_running = threading.Event()
        self.keep_running.set()

        # hold the .get_power_loss_status()
        self.last_state = None

        # special tweak to announce 'first poll' more smartly
        self.starting_up = True

        self.email_settings = dict()
        self.prep_email_settings()

        return