def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str): if object_expr in self.problematic: return items, errors = self.get_obj_attributes(object_expr) for name, rep, typ, obj in sorted(items, key=lambda x: x[0]): if name.startswith("__"): continue resetWDT() sleep_us(1) if typ in ["<class 'function'>", "<class 'bound_method'>"]: s = indent + "def " + name + "():\n" s += indent + " pass\n\n" fp.write(s) elif typ in ["<class 'str'>", "<class 'int'>", "<class 'float'>"]: s = indent + name + " = " + rep + "\n" fp.write(s) elif typ == "<class 'type'>" and indent == "": s = "\n" + indent + "class " + name + ":\n" s += indent + " ''\n" fp.write(s) self.write_object_stub(fp, obj, "{0}.{1}".format(obj_name, name), indent + " ") else: fp.write(indent + name + " = None\n") del items del errors try: del name, rep, typ, obj except (OSError, KeyError): pass
def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str): "Write a module/object stub to an open file. Can be called recursive." if object_expr in self.problematic: self._log.warning( "SKIPPING problematic module:{}".format(object_expr)) return self._log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: self._log.error(errors) for name, rep, typ, obj in sorted(items, key=lambda x: x[0]): if name.startswith("__"): #skip internals continue # allow the scheduler to run on LoBo based FW resetWDT() sleep_us(1) self._log.debug("DUMPING {}{}{}:{}".format(indent, object_expr, name, typ)) if typ in ["<class 'function'>", "<class 'bound_method'>"]: s = indent + "def " + name + "():\n" #todo: add self, and optional params s += indent + " pass\n\n" fp.write(s) self._log.debug('\n' + s) elif typ in ["<class 'str'>", "<class 'int'>", "<class 'float'>"]: s = indent + name + " = " + rep + "\n" fp.write(s) self._log.debug('\n' + s) #new class elif typ == "<class 'type'>" and indent == "": # full expansion only on toplevel # stub style : Empty comment ... + hardcoded 4 spaces s = "\n" + indent + "class " + name + ":\n" # What about superclass? s += indent + " ''\n" fp.write(s) self._log.debug('\n' + s) self._log.debug("# recursion..") self.write_object_stub(fp, obj, "{0}.{1}".format(obj_name, name), indent + " ") else: # keep only the name fp.write(indent + name + " = None\n") del items del errors try: del name, rep, typ, obj # pylint: disable=undefined-loop-variable except (OSError, KeyError): #lgtm [py/unreachable-statement] pass
async def task_check_software_updates(self, once=False): while True: machine.resetWDT() if check_software_update(): schedule_software_update() machine.resetWDT() if once: break await uasyncio.sleep(3600)
async def bg_leds(self): while True: machine.resetWDT() if self._network._wlan: await self.blink(("status", ), 1 if self._network._wlan.mode == AP_IF else 2, 100) elif self._network.gsm: await self.blink(("status", ), 4 if self._network.online() else 3, 100) await uasyncio.sleep(2) gc.collect()
def off(self): if self.gsm: import gsm machine.resetWDT() gsm.stop() if self._gsm_pwr_key: self._gsm_pwr_key.value(0) if self._gsm_rst: self._gsm_rst.value(0) #if self._gsm_pwr: # self._gsm_pwr.value(0) if self._gsm_modem_on: for uart_pin_type in ('tx', 'rx'): machine.Pin(self._conf['gsm_modem'][uart_pin_type], machine.Pin.OUT, value=0) self._gsm_modem_on.value(0)
def gsm_start(self, apn_settings): import gsm gsm.debug(True) # see more logs, investigate issues, etc. gsm.start(tx=self._conf['gsm_modem']['tx'], rx=self._conf['gsm_modem']['rx'], **apn_settings) sys.stdout.write('Waiting for AT command response...') for retry in range(20): machine.resetWDT() if gsm.atcmd('AT'): return True else: sys.stdout.write('.') utime.sleep(5) else: sys.stdout.write("Modem not responding!") machine.reset()
async def post(self, url, data): while self._srv_req_pending: await uasyncio.sleep_ms(50) machine.resetWDT() rsp = None result = None try: LOG.info("url: %s\ndata: %s" % (url, data)) rsp = urequests.post(url, json=data) machine.resetWDT() if rsp.status_code != 200: self.log_exception(None, url, data, rsp.status_code) rsp.close() rsp = None self._srv_last_contact = utime.time() except Exception as exc: self.log_exception(exc, url, data) finally: self._srv_req_pending = False machine.resetWDT() if rsp: try: result = ujson.load(rsp.raw) except Exception as exc: LOG.exc(exc, 'Server response reading error') print(rsp.raw.read()) finally: rsp.close() rsp = None LOG.info("return: %s" % result) return result
async def srv_post(self, url, data, retry=False): if self.busy: return False data['device_id'] = self.id['id'] data['token'] = self.id['token'] manage_memory() machine.resetWDT() result = await self._http.post(self.server_uri + url, data) if retry: while not result: machine.resetWDT() result = await self._http.post(self.server_uri + url, data) machine.resetWDT() manage_memory() return result
def perform_software_update(): global HTTP_CLIENT if not HTTP_CLIENT: HTTP_CLIENT = HttpClient() machine.WDT() manage_memory() version_data = load_version() device_type = get_device_type() srv_url = updates_url() srv_index = load_srv_json('index', srv_url=srv_url) machine.resetWDT() srv_versions = load_srv_json('devices', srv_url=srv_url) machine.resetWDT() if srv_index: for path, entry in srv_index.items(): if 'devices_types' in entry and 'base' not in entry[ 'devices_types'] and device_type not in entry[ 'devices_types']: continue if path in version_data['files'] and version_data['files'][ path] == entry['hash']: continue local_path = entry['path'] if 'path' in entry else path print(local_path) ensure_file_path(local_path) file_url = srv_url + 'software/' + path print(file_url) while version_data['files'].get(path) != entry['hash']: if HTTP_CLIENT.get_to_file(file_url, 'file_buf'): try: uos.remove(local_path) except OSError: pass uos.rename('file_buf', local_path) if version_data['hash']: version_data['hash'] = None version_data['files'][path] = entry['hash'] save_version(version_data) print('complete') machine.resetWDT() version_data['hash'] = srv_versions[device_type] version_data['update'] = False save_version(version_data) machine.reset()
async def wdt_feed(): await uasyncio.sleep(10) machine.resetWDT()
def __init__(self): self._conf = {} conf = load_json('conf.json') if conf: for conf_item in ('wlan_enabled_switch', 'gsm_modem'): if conf_item in conf: self._conf[conf_item] = conf[conf_item] self._wlan = None self._wlan_enabled_switch = None self.gsm = False self._gsm_settings = {} enable_wlan = False if self._conf.get('wlan_enabled_switch'): self._wlan_enabled_switch = machine.Pin( self._conf['wlan_enabled_switch'], handler=wlan_enabled_switch_handler, trigger=machine.Pin.IRQ_FALLING) enable_wlan = self._wlan_enabled_switch.value() machine.RTC().wake_on_ext0(self._wlan_enabled_switch, 1) if not enable_wlan and self._conf.get('gsm_modem'): import gsm self._gsm_modem_on = None if self._conf['gsm_modem'].get('on'): self._gsm_modem_on = machine.Pin(self._conf['gsm_modem']['on'], machine.Pin.OUT, value=1) if self._conf['gsm_modem'].get('on_rev'): self._gsm_modem_on = machine.Pin( self._conf['gsm_modem']['on_rev'], machine.Pin.OUT, value=0) self.gsm = True self._gsm_settings = load_json('gsm_settings.json') or {} gsm_apns = load_json('gsm_apns.json') apn_settings = {} self._gsm_pwr = machine.Pin(self._conf['gsm_modem']['pwr'], machine.Pin.INOUT, value=0)\ if self._conf['gsm_modem'].get('pwr') else None if self._gsm_pwr: utime.sleep(2) self._gsm_rst = machine.Pin(self._conf['gsm_modem']['rst'], machine.Pin.OUT, value=1)\ if self._conf['gsm_modem'].get('rst') else None self._gsm_pwr_key = machine.Pin(self._conf['gsm_modem']['pwr_key'], machine.Pin.OUT)\ if self._conf['gsm_modem'].get('pwr_key') else None self.gsm_pwr_key_cycle() if not self._gsm_settings.get('network'): self.gsm_start({'apn': ''}) machine.resetWDT() network_cmd = gsm.atcmd('AT+COPS?', timeout=1000, response='OK') network_name = [ key for key in gsm_apns.keys() if key in network_cmd ] if network_name: self._gsm_settings['network'] = network_name[0] save_json(self._gsm_settings, 'gsm_settings.json') gsm.stop() else: LOG.info('Network apn data not found. Trying empty apn.') if self._gsm_settings.get('network'): apn_settings = gsm_apns[self._gsm_settings['network']] if apn_settings: self.gsm_start(apn_settings) machine.resetWDT() self.gsm_connect() machine.resetWDT() else: self._wlan = WlanController()
def write_object_stub(self, fp, object_expr: object, obj_name: str, indent: str, in_class: int = 0): "Write a module/object stub to an open file. Can be called recursive." gc.collect() if object_expr in self.problematic: self._log.warning( "SKIPPING problematic module:{}".format(object_expr)) return # self._log.debug("DUMP : {}".format(object_expr)) items, errors = self.get_obj_attributes(object_expr) if errors: self._log.error(errors) for item_name, item_repr, item_type_txt, item_instance in items: # name_, repr_(value), type as text, item_instance # do not create stubs for these primitives if item_name in [ "classmethod", "staticmethod", "BaseException", "Exception" ]: continue # allow the scheduler to run on LoBo based FW resetWDT() sleep_us(1) # Class expansion only on first 3 levels (bit of a hack) if item_type_txt == "<class 'type'>" and len( indent) <= _MAX_CLASS_LEVEL * 4: self._log.debug("{0}class {1}:".format(indent, item_name)) superclass = "" is_exception = item_name.endswith( "Exception") or item_name.endswith("Error") if is_exception: superclass = "Exception" s = "\n{}class {}({}):\n".format(indent, item_name, superclass) s += indent + " ''\n" if not is_exception: # Add __init__ s += indent + " def __init__(self, *argv, **kwargs) -> None:\n" s += indent + " ''\n" s += indent + " ...\n" fp.write(s) # self._log.debug("\n" + s) self._log.debug("# recursion over class {0}".format(item_name)) self.write_object_stub( fp, item_instance, "{0}.{1}".format(obj_name, item_name), indent + " ", in_class + 1, ) # Class Methods and functions elif "method" in item_type_txt or "function" in item_type_txt or item_name == "__init__": self._log.debug( "# def {1} function or method, type = '{0}'".format( item_type_txt, item_name)) # module Function or class method # will accept any number of params # return type Any ret = "Any" first = "" # Self parameter only on class methods/functions if in_class > 0: first = "self, " # __init__ returns None if item_name == "__init__": ret = "None" # class method - add function decoration if "bound_method" in item_type_txt or "bound_method" in item_repr: s = "{}@classmethod\n".format(indent) s += "{}def {}(cls, *args) -> {}:\n".format( indent, item_name, ret) else: s = "{}def {}({}*args) -> {}:\n".format( indent, item_name, first, ret) # s += indent + " ''\n" # EMPTY DOCSTRING s += indent + " ...\n\n" fp.write(s) self._log.debug("\n" + s) # constants of known types & values elif item_type_txt == "<class 'module'>": # Skip imported modules # fp.write("# import {}\n".format(item_name)) pass elif item_type_txt.startswith("<class '"): t = item_type_txt[8:-2] s = "" if t in ["str", "int", "float", "bool", "bytearray", "bytes"]: # known type: use actual value s = "{0}{1} = {2} # type: {3}\n".format( indent, item_name, item_repr, t) elif t in ["dict", "list", "tuple"]: # dict, list , tuple: use empty value ev = {"dict": "{}", "list": "[]", "tuple": "()"} s = "{0}{1} = {2} # type: {3}\n".format( indent, item_name, ev[t], t) else: # something else if not t in ["object", "set", "frozenset"]: # Possibly default others to item_instance object ? # https://docs.python.org/3/tutorial/classes.html#item_instance-objects t = "Any" # Requires Python 3.6 syntax, which is OK for the stubs/pyi s = "{0}{1} : {2} ## {3} = {4}\n".format( indent, item_name, t, item_type_txt, item_repr) fp.write(s) self._log.debug("\n" + s) else: # keep only the name self._log.debug( "# all other, type = '{0}'".format(item_type_txt)) fp.write("# all other, type = '{0}'\n".format(item_type_txt)) fp.write(indent + item_name + " # type: Any\n") del items del errors try: del item_name, item_repr, item_type_txt, item_instance # pylint: disable=undefined-loop-variable except (OSError, KeyError, NameError): # lgtm [py/unreachable-statement] pass
def start(self): WDT(True) self.ntp_sync() if self.deepsleep(): loop = uasyncio.get_event_loop() for module_type in self.modules: if module_type == 'rtc': loop.run_until_complete( self.modules['rtc'].adjust_time(once=True)) machine.resetWDT() elif module_type == 'climate': loop.run_until_complete( self.modules['climate'].read(once=True)) machine.resetWDT() if self.online(): loop.run_until_complete( self.post_sensor_data(once=True)) machine.resetWDT() if self.modules['climate'].light: loop.run_until_complete( self.modules['climate'].adjust_light(once=True)) machine.resetWDT() if self.online(): if self.id.get('updates'): loop.run_until_complete(self.check_updates(once=True)) machine.resetWDT() if not self.id.get('disable_software_updates'): loop.run_until_complete( self.task_check_software_updates(once=True)) machine.resetWDT() if self.deepsleep(): if self._network: self._network.off() machine.deepsleep(self.deepsleep() * 60000) self.start_async()
def __init__(self, network_controller): LOG.info("LenferDevice init") self._schedule = None self._network = network_controller self.mode = None self.status = { "wlan": None, "factory_reset": False, "wlan_switch": False, "ssid_failure": False, "ssid_delay": False, "srv_req_pending": False } self.log_queue = [] self.busy = False self._conf = load_json('conf.json') self.settings = load_json('settings.json') self._http = HttpClient() if not self.settings: self.load_def_settings() if self.settings.get('mode'): self.mode = self.settings['mode'] if self._conf.get('wlan_switch'): self._wlan_switch_button = Pin(self._conf['wlan_switch'], Pin.IN, Pin.PULL_UP, handler=self.wlan_switch_irq, trigger=Pin.IRQ_FALLING) if self._conf.get('factory_reset'): self._factory_reset_button = Pin(self._conf['factory_reset'], Pin.IN, handler=self.factory_reset_irq, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING) self.modules = {} self.i2c = [ I2C(scl=Pin(i2c_conf['scl']), sda=Pin(i2c_conf['sda'])) for i2c_conf in self._conf['i2c'] ] LOG.info('I2C init') self.leds = { led: Pin(pin_no, Pin.OUT) for led, pin_no in self._conf['leds'].items() } self.id = load_json('id.json') if 'debug' in self.id and self.id['debug']: self.server_uri = SERVER_URI_DEV else: self.server_uri = SERVER_URI for led in self.leds.values(): led.value(0) self.schedule = Schedule() manage_memory() machine.resetWDT() if 'rtc' in self._conf['modules'] and self.module_enabled( self._conf['modules']['rtc']): try: from timers import RtcController self.modules['rtc'] = RtcController( self, self._conf['modules']['rtc']) self.modules['rtc'].get_time(set_rtc=True) LOG.info('RTC init') except Exception as exc: LOG.exc(exc, 'RTC initialization error') machine.resetWDT() manage_memory() if 'climate' in self._conf['modules'] and self.module_enabled( self._conf['modules']['climate']): try: from climate import ClimateController self.modules['climate'] = ClimateController( self, self._conf['modules']['climate']) LOG.info('ClimateController init') except Exception as exc: LOG.exc(exc, 'Climate initialization error') if self._conf['modules']['climate'].get('obligatory'): LOG.error( 'Obligatory module initialization fail -- machine reset' ) machine.reset() machine.resetWDT() manage_memory() if 'power_monitor' in self._conf['modules'] and self.module_enabled( self._conf['modules']['power_monitor']): try: from power_monitor_controller import PowerMonitor self.modules['power_monitor'] = PowerMonitor( self, self._conf['modules']['power_monitor']) LOG.info('PowerMonitor init') except Exception as exc: LOG.exc(exc, 'PowerMonitor initialization error') if self._conf['modules']['power_monitor'].get('obligatory'): LOG.error( 'Obligatory module initialization fail -- machine reset' ) machine.reset() machine.resetWDT() manage_memory() if 'feeder' in self._conf['modules'] and self.module_enabled( self._conf['modules']['feeder']): try: from feeder import FeederController self.modules['feeder'] = FeederController( self, self._conf['modules']['feeder']) LOG.info('Feeder init') except Exception as exc: LOG.exc(exc, 'Feeder initialization error') machine.resetWDT() manage_memory() if 'gate' in self._conf['modules'] and self.module_enabled( self._conf['modules']['gate']): try: from gate_controller import GateController self.modules['gate'] = GateController( self, self._conf['modules']['gate']) LOG.info('Gate init') except Exception as exc: LOG.exc(exc, 'Gate initialization error') machine.resetWDT() manage_memory() if 'relay_switch' in self._conf['modules'] and self.module_enabled( self._conf['modules']['relay_switch']): try: from relay_switch import RelaySwitchController self.modules['relay_switch'] = RelaySwitchController( self, self._conf['modules']['relay_switch']) LOG.info('Relay init') except Exception as exc: LOG.exc(exc, 'RelaySwitch initialization error') machine.resetWDT() manage_memory() LOG.info(self.modules)