From 55c00e34a02064f55683570b4150f615a20e07fc Mon Sep 17 00:00:00 2001 From: JackSun-qc Date: Tue, 12 Apr 2022 20:16:58 +0800 Subject: [PATCH] update: 1. ali & quec cloud; 2. location; 3. low energy trc; 4. remote; 5. settings; 6. tracker; 7. readme --- code/aliyunIot.py | 398 +++++++++++++++++++++---------------------- code/battery.py | 11 +- code/common.py | 9 +- code/location.py | 390 ++++++++++++++++++++++-------------------- code/main.py | 19 +-- code/mpower.py | 40 +---- code/quecthing.py | 232 ++++++++++--------------- code/remote.py | 25 ++- code/settings.py | 6 +- code/settings_app.py | 12 +- code/settings_sys.py | 107 ++++++++++++ code/test_tracker.py | 48 +++--- code/tracker.py | 193 +++++++++++++++------ readme.md | 5 +- 14 files changed, 812 insertions(+), 683 deletions(-) diff --git a/code/aliyunIot.py b/code/aliyunIot.py index 85e2975..a0834e6 100644 --- a/code/aliyunIot.py +++ b/code/aliyunIot.py @@ -25,155 +25,161 @@ from usr.common import numiter from usr.common import option_lock from usr.common import CloudObservable from usr.logging import getLogger -from usr.location import GPSParsing log = getLogger(__name__) -object_model = { - "event": [ - "sos_alert", - "fault_alert", - "low_power_alert", - "sim_abnormal_alert", - "disassemble_alert", - "drive_behavior_alert", - "over_speed_alert", - ], - "property": [ - "power_switch", - "energy", - "phone_num", - "loc_method", - "work_mode", - "work_cycle_period", - "local_time", - "low_power_alert_threshold", - "low_power_shutdown_threshold", - "sw_ota", - "sw_ota_auto_upgrade", - "sw_voice_listen", - "sw_voice_record", - "sw_fault_alert", - "sw_low_power_alert", - "sw_over_speed_alert", - "sw_sim_abnormal_alert", - "sw_disassemble_alert", - "sw_drive_behavior_alert", - "drive_behavior_code", - "power_restart", - "over_speed_threshold", - "device_module_status", - "gps_mode", - "user_ota_action", - "ota_status", - "GeoLocation", - "voltage", - ], -} - _gps_read_lock = _thread.allocate_lock() +class AliObjectModule(object): + + def __init__(self): + self.event = {} + self.property = {} + + def add_item(self, name, data_type, struct_info={}): + om_data = { + "name": name, + "data_type": data_type, + "struct_info": struct_info, + } + if data_type == "event": + if self.event.get(name) is None: + self.event[name] = om_data + return True + elif data_type == "property": + if self.property.get(name) is None: + self.property[name] = om_data + return True + return False + + def update_item(self, name, data_type, struct_info={}): + if self.items.get(name) is not None: + self.del_item(name, data_type) + self.add_item(name, data_type, struct_info) + return True + return False + + def del_item(self, name, data_type): + if data_type == "event": + if self.event.get(name) is not None: + self.event.pop(name) + elif data_type == "property": + if self.property.get(name) is not None: + self.property.pop(name) + else: + return False + + return True + + class AliYunIot(CloudObservable): def __init__(self, pk, ps, dk, ds, server, burning_method=0, life_time=120, mcu_name="", mcu_version="", firmware_name="", firmware_version=""): super().__init__() - self.pk = pk - self.ps = ps - self.dk = dk - self.ds = ds - self.server = server - self.burning_method = burning_method - self.life_time = life_time - self.mcu_name = mcu_name - self.mcu_version = mcu_version - self.firmware_name = firmware_name - self.firmware_version = firmware_version + self.__pk = pk + self.__ps = ps + self.__dk = dk + self.__ds = ds + self.__server = server + self.__burning_method = burning_method + self.__life_time = life_time + self.__mcu_name = mcu_name + self.__mcu_version = mcu_version + self.__firmware_name = firmware_name + self.__firmware_version = firmware_version + self.__object_model = None - self.ali = None - self.post_res = {} - self.breack_flag = 0 - self.ali_timer = osTimer() + self.__ali = None + self.__post_res = {} + self.__breack_flag = 0 + self.__ali_timer = osTimer() - self.id_iter = numiter() - self.id_lock = _thread.allocate_lock() + self.__id_iter = numiter() + self.__id_lock = _thread.allocate_lock() - self.ica_topic_property_post = "/sys/%s/%s/thing/event/property/post" % (self.pk, self.dk) - self.ica_topic_property_post_reply = "/sys/%s/%s/thing/event/property/post_reply" % (self.pk, self.dk) - self.ica_topic_property_set = "/sys/%s/%s/thing/service/property/set" % (self.pk, self.dk) - self.ica_topic_property_get = "/sys/%s/%s/thing/service/property/get" % (self.pk, self.dk) - self.ica_topic_property_query = "/sys/%s/%s/thing/service/property/query" % (self.pk, self.dk) - self.ica_topic_event_post = "/sys/%s/%s/thing/event/{}/post" % (self.pk, self.dk) - self.ica_topic_event_post_reply = "/sys/%s/%s/thing/event/{}/post_reply" % (self.pk, self.dk) - self.ota_topic_device_inform = "/ota/device/inform/%s/%s" % (self.pk, self.dk) - self.ota_topic_device_upgrade = "/ota/device/upgrade/%s/%s" % (self.pk, self.dk) - self.ota_topic_device_progress = "/ota/device/progress/%s/%s" % (self.pk, self.dk) - self.ota_topic_firmware_get = "/sys/%s/%s/thing/ota/firmware/get" % (self.pk, self.dk) - self.ota_topic_firmware_get_reply = "/sys/%s/%s/thing/ota/firmware/get_reply" % (self.pk, self.dk) + self.ica_topic_property_post = "/sys/%s/%s/thing/event/property/post" % (self.__pk, self.__dk) + self.ica_topic_property_post_reply = "/sys/%s/%s/thing/event/property/post_reply" % (self.__pk, self.__dk) + self.ica_topic_property_set = "/sys/%s/%s/thing/service/property/set" % (self.__pk, self.__dk) + self.ica_topic_property_get = "/sys/%s/%s/thing/service/property/get" % (self.__pk, self.__dk) + self.ica_topic_property_query = "/sys/%s/%s/thing/service/property/query" % (self.__pk, self.__dk) + self.ica_topic_event_post = "/sys/%s/%s/thing/event/{}/post" % (self.__pk, self.__dk) + self.ica_topic_event_post_reply = "/sys/%s/%s/thing/event/{}/post_reply" % (self.__pk, self.__dk) + self.ota_topic_device_inform = "/ota/device/inform/%s/%s" % (self.__pk, self.__dk) + self.ota_topic_device_upgrade = "/ota/device/upgrade/%s/%s" % (self.__pk, self.__dk) + self.ota_topic_device_progress = "/ota/device/progress/%s/%s" % (self.__pk, self.__dk) + self.ota_topic_firmware_get = "/sys/%s/%s/thing/ota/firmware/get" % (self.__pk, self.__dk) + self.ota_topic_firmware_get_reply = "/sys/%s/%s/thing/ota/firmware/get_reply" % (self.__pk, self.__dk) # TODO: To Download OTA File For MQTT Association (Not Support Now.) - self.ota_topic_file_download = "/sys/%s/%s/thing/file/download" % (self.pk, self.dk) - self.ota_topic_file_download_reply = "/sys/%s/%s/thing/file/download_reply" % (self.pk, self.dk) + self.ota_topic_file_download = "/sys/%s/%s/thing/file/download" % (self.__pk, self.__dk) + self.ota_topic_file_download_reply = "/sys/%s/%s/thing/file/download_reply" % (self.__pk, self.__dk) + + self.rrpc_topic_request = "/sys/%s/%s/rrpc/request/+" % (self.__pk, self.__dk) + self.rrpc_topic_response = "/sys/%s/%s/rrpc/response/{}" % (self.__pk, self.__dk) def __get_id(self): - with self.id_lock: + with self.__id_lock: try: - msg_id = next(self.id_iter) + msg_id = next(self.__id_iter) except StopIteration: - self.id_iter = numiter() - msg_id = next(self.id_iter) + self.__id_iter = numiter() + msg_id = next(self.__id_iter) return str(msg_id) def __put_post_res(self, msg_id, res): - self.post_res[msg_id] = res + self.__post_res[msg_id] = res def __ali_timer_cb(self, args): - self.breack_flag = 1 + self.__breack_flag = 1 @option_lock(_gps_read_lock) def __get_post_res(self, msg_id): - self.ali_timer.start(5 * 1000, 0, self.__ali_timer_cb) - while self.post_res.get(msg_id) is None: - if self.breack_flag: - self.post_res[msg_id] = False + self.__ali_timer.start(5 * 1000, 0, self.__ali_timer_cb) + while self.__post_res.get(msg_id) is None: + if self.__breack_flag: + self.__post_res[msg_id] = False break utime.sleep_ms(50) - self.ali_timer.stop() - self.breack_flag = 0 - res = self.post_res.pop(msg_id) + self.__ali_timer.stop() + self.__breack_flag = 0 + res = self.__post_res.pop(msg_id) return res def __ali_subcribe_topic(self): - if self.ali.subscribe(self.ica_topic_property_post, qos=0) == -1: + if self.__ali.subscribe(self.ica_topic_property_post, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ica_topic_property_post) - if self.ali.subscribe(self.ica_topic_property_post_reply, qos=0) == -1: + if self.__ali.subscribe(self.ica_topic_property_post_reply, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ica_topic_property_post_reply) - if self.ali.subscribe(self.ica_topic_property_set, qos=0) == -1: + if self.__ali.subscribe(self.ica_topic_property_set, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ica_topic_property_set) - if self.ali.subscribe(self.ica_topic_property_get, qos=0) == -1: + if self.__ali.subscribe(self.ica_topic_property_get, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ica_topic_property_get) - if self.ali.subscribe(self.ica_topic_property_query, qos=0) == -1: + if self.__ali.subscribe(self.ica_topic_property_query, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ica_topic_property_query) - for tsl_event_identifier in object_model["event"]: + for tsl_event_identifier in self.__object_model.event.keys(): post_topic = self.ica_topic_event_post.format(tsl_event_identifier) - if self.ali.subscribe(post_topic, qos=0) == -1: + if self.__ali.subscribe(post_topic, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % post_topic) post_reply_topic = self.ica_topic_event_post_reply.format(tsl_event_identifier) - if self.ali.subscribe(post_reply_topic, qos=0) == -1: + if self.__ali.subscribe(post_reply_topic, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % post_reply_topic) - if self.ali.subscribe(self.ota_topic_device_upgrade, qos=0) == -1: + if self.__ali.subscribe(self.ota_topic_device_upgrade, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ota_topic_device_upgrade) - if self.ali.subscribe(self.ota_topic_firmware_get_reply, qos=0) == -1: + if self.__ali.subscribe(self.ota_topic_firmware_get_reply, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ota_topic_firmware_get_reply) # TODO: To Download OTA File For MQTT Association (Not Support Now.) - if self.ali.subscribe(self.ota_topic_file_download_reply, qos=0) == -1: + if self.__ali.subscribe(self.ota_topic_file_download_reply, qos=0) == -1: log.error("Topic [%s] Subscribe Falied." % self.ota_topic_file_download_reply) + if self.__ali.subscribe(self.rrpc_topic_request, qos=0) == -1: + log.error("Topic [%s] Subscribe Falied." % self.rrpc_topic_request) + def __ali_sub_cb(self, topic, data): topic = topic.decode() data = ujson.loads(data) @@ -201,142 +207,136 @@ class AliYunIot(CloudObservable): self.__put_post_res(data["id"], True if int(data["code"]) == 200 else False) if data["code"] == 200: self.notifyObservers(self, *("ota_file_download", data["data"])) + elif topic.find('/rrpc/request/') != -1: + self.notifyObservers(self, *('rrpc_request', topic, data)) else: pass - def get_loc_data(self, loc_method, loc_data): - res = {"GeoLocation": {}} - - if loc_method == 0x1: - gps_parsing = GPSParsing() - gga_data = gps_parsing.read_GxGGA(loc_data) - data = {} - if gga_data: - Latitude_re = ure.search(r",[0-9]+\.[0-9]+,[NS],", gga_data) - if Latitude_re: - data["Latitude"] = round(float(Latitude_re.group(0)[1:-3]), 2) - Longtitude_re = ure.search(r",[0-9]+\.[0-9]+,[EW],", gga_data) - if Longtitude_re: - data["Longtitude"] = round(float(Longtitude_re.group(0)[1:-3]), 2) - Altitude_re = ure.search(r"-*[0-9]+\.[0-9]+,M,", gga_data) - if Altitude_re: - data["Altitude"] = round(float(Altitude_re.group(0)[:-3]), 2) - if data: - data["CoordinateSystem"] = 1 - res = {"GeoLocation": data} - elif loc_method in (0x2, 0x4): - if loc_data: - res["GeoLocation"] = { - "Longtitude": round(loc_data[0], 2), - "Latitude": round(loc_data[1], 2), - # "Altitude": 0.0, - "CoordinateSystem": 1 + def __data_format(self, data): + res = {"event": [], "property": [], "msg_ids": [], "event_topic": {}} + property_params = {} + event_params = {} + # Format Publish Params. + for k, v in data.items(): + if k in self.__object_model.property.keys(): + property_params[k] = { + "value": v, + "time": utime.mktime(utime.localtime()) * 1000 } + elif k in self.__object_model.event.keys(): + event_params[k] = { + "value": {}, + "time": utime.mktime(utime.localtime()) * 1000 + } + else: + log.error("Publish Key [%s] is not in property and event" % k) + + if property_params: + msg_id = self.__get_id() + publish_data = { + "id": msg_id, + "version": "1.0", + "sys": { + "ack": 1 + }, + "params": property_params, + "method": "thing.event.property.post" + } + res["property"].append(publish_data) + res["msg_ids"].append(msg_id) + + if event_params: + for event in event_params.keys(): + topic = self.ica_topic_event_post.format(event) + msg_id = self.__get_id() + publish_data = { + "id": msg_id, + "version": "1.0", + "sys": { + "ack": 1 + }, + "params": event_params[event], + "method": "thing.event.%s.post" % event + } + res["event"].append(publish_data) + res["event_topic"][msg_id] = topic + res["msg_ids"].append(msg_id) return res - def cloud_init(self, enforce=False): - log.debug("[cloud_init start] enforce: %s" % enforce) - if enforce is False and self.ali is not None: - log.debug("self.ali.getAliyunSta(): %s" % self.ali.getAliyunSta()) - if self.ali.getAliyunSta() == 0: + def set_object_model(self, object_model): + if object_model and isinstance(object_model, AliObjectModule): + self.__object_model = object_model + return True + return False + + def init(self, enforce=False): + log.debug("[init start] enforce: %s" % enforce) + if enforce is False and self.__ali is not None: + log.debug("self.__ali.getAliyunSta(): %s" % self.__ali.getAliyunSta()) + if self.__ali.getAliyunSta() == 0: return True - if self.burning_method == 0: - self.dk = None - elif self.burning_method == 1: - self.ps = None + if self.__burning_method == 0: + self.__dk = None + elif self.__burning_method == 1: + self.__ps = None - log.debug("aLiYun init. self.pk: %s, self.ps: %s, self.dk: %s, self.ds: %s, self.server: %s" % (self.pk, self.ps, self.dk, self.ds, self.server)) - self.ali = aLiYun(self.pk, self.ps, self.dk, self.ds, self.server) + log.debug("aLiYun init. self.__pk: %s, self.__ps: %s, self.__dk: %s, self.__ds: %s, self.__server: %s" % (self.__pk, self.__ps, self.__dk, self.__ds, self.__server)) + self.__ali = aLiYun(self.__pk, self.__ps, self.__dk, self.__ds, self.__server) log.debug("aLiYun setMqtt.") clientId = modem.getDevImei() log.debug("aLiYun clientId(IMEI): %s" % clientId) - setMqttres = self.ali.setMqtt(clientId, clean_session=False, keepAlive=self.life_time, reconn=True) + setMqttres = self.__ali.setMqtt(clientId, clean_session=False, keepAlive=self.__life_time, reconn=True) log.debug("aLiYun setMqttres: %s" % setMqttres) if setMqttres != -1: - self.ali.setCallback(self.__ali_sub_cb) + self.__ali.setCallback(self.__ali_sub_cb) self.__ali_subcribe_topic() - self.ali.start() + self.__ali.start() else: log.error("setMqtt Falied!") return False - log.debug("self.ali.getAliyunSta(): %s" % self.ali.getAliyunSta()) - if self.ali.getAliyunSta() == 0: + log.debug("self.__ali.getAliyunSta(): %s" % self.__ali.getAliyunSta()) + if self.__ali.getAliyunSta() == 0: return True else: return False - def cloud_close(self): - self.ali.disconnect() + def close(self): + self.__ali.disconnect() def post_data(self, data): - msg_ids = [] - if self.ali.getAliyunSta() == 0: + if self.__ali.getAliyunSta() == 0: try: - property_params = {} - event_params = {} - # Format Publish Params. - for k, v in data.items(): - if k in object_model["property"]: - property_params[k] = { - "value": v, - "time": utime.mktime(utime.localtime()) * 1000 - } - elif k in object_model["event"]: - event_params[k] = { - "value": {}, - "time": utime.mktime(utime.localtime()) * 1000 - } - else: - log.error("Publish Key [%s] is not in property and event" % k) + publish_data = self.__data_format(data) # Publish Property Data. - if property_params: - msg_id = self.__get_id() - publish_data = { - "id": msg_id, - "version": "1.0", - "sys": { - "ack": 1 - }, - "params": property_params, - "method": "thing.event.property.post" - } - self.ali.publish(self.ica_topic_property_post, ujson.dumps(publish_data), qos=0) - msg_ids.append(msg_id) + for item in publish_data["property"]: + self.__ali.publish(self.ica_topic_property_post, ujson.dumps(item), qos=0) # Publish Event Data. - if event_params: - for event in event_params.keys(): - topic = self.ica_topic_event_post.format(event) - msg_id = self.__get_id() - publish_data = { - "id": msg_id, - "version": "1.0", - "sys": { - "ack": 1 - }, - "params": event_params[event], - "method": "thing.event.%s.post" % event - } - self.ali.publish(topic, ujson.dumps(publish_data), qos=0) - msg_ids.append(msg_id) - - pub_res = [self.__get_post_res(msg_id) for msg_id in msg_ids] + for item in publish_data["event"]: + self.__ali.publish(publish_data["event_topic"][item["id"]], ujson.dumps(item), qos=0) + pub_res = [self.__get_post_res(msg_id) for msg_id in publish_data["msg_ids"]] return True if False not in pub_res else False except Exception: log.error("AliYun publish topic %s failed. data: %s" % (data.get("topic"), data.get("data"))) return False + def rrpc_response(self, message_id, data): + topic = self.rrpc_topic_response.format(message_id) + pub_data = ujson.dumps(data) if isinstance(data, dict) else data + self.__ali.publish(topic, pub_data, qos=0) + return True + def device_report(self): - muc_res = self.ota_device_inform(self.mcu_version, module=self.mcu_name) - fw_res = self.ota_device_inform(self.firmware_version, module=self.firmware_name) + muc_res = self.ota_device_inform(self.__mcu_version, module=self.__mcu_name) + fw_res = self.ota_device_inform(self.__firmware_version, module=self.__firmware_name) return True if muc_res and fw_res else False def ota_request(self): - sota_res = self.ota_firmware_get(self.mcu_name) - fota_res = self.ota_firmware_get(self.firmware_name) + sota_res = self.ota_firmware_get(self.__mcu_name) + fota_res = self.ota_firmware_get(self.__firmware_name) return True if sota_res and fota_res else False def ota_action(self, action, module=None): @@ -361,7 +361,7 @@ class AliYunIot(CloudObservable): "module": module, }, } - publish_res = self.ali.publish(self.ota_topic_device_inform, ujson.dumps(publish_data), qos=0) + publish_res = self.__ali.publish(self.ota_topic_device_inform, ujson.dumps(publish_data), qos=0) log.debug("version: %s, module: %s, publish_res: %s" % (version, module, publish_res)) return publish_res @@ -375,7 +375,7 @@ class AliYunIot(CloudObservable): "module": module, } } - publish_res = self.ali.publish(self.ota_topic_device_progress, ujson.dumps(publish_data), qos=0) + publish_res = self.__ali.publish(self.ota_topic_device_progress, ujson.dumps(publish_data), qos=0) if publish_res: return self.__get_post_res(msg_id) else: @@ -392,7 +392,7 @@ class AliYunIot(CloudObservable): }, "method": "thing.ota.firmware.get" } - publish_res = self.ali.publish(self.ota_topic_firmware_get, ujson.dumps(publish_data), qos=0) + publish_res = self.__ali.publish(self.ota_topic_firmware_get, ujson.dumps(publish_data), qos=0) log.debug("module: %s, publish_res: %s" % (module, publish_res)) if publish_res: return self.__get_post_res(msg_id) @@ -407,7 +407,7 @@ class AliYunIot(CloudObservable): "version": "1.0", "params": params } - publish_res = self.ali.publish(self.ota_topic_file_download, ujson.dumps(publish_data), qos=0) + publish_res = self.__ali.publish(self.ota_topic_file_download, ujson.dumps(publish_data), qos=0) if publish_res: return self.__get_post_res(msg_id) else: diff --git a/code/battery.py b/code/battery.py index cc95676..94c0555 100644 --- a/code/battery.py +++ b/code/battery.py @@ -69,19 +69,18 @@ class Battery(object): else: return self.__get_soc_from_dict(20, volt_arg) - def get_temp(self): - return self.__temp - def set_temp(self, temp): - # TODO: Get temp from sensor + # Set now temperature. if isinstance(temp, int) or isinstance(temp, float): self.__temp = temp return True return False def get_voltage(self): - return Power.getVbatt() + # Get voltage from vbat + # TODO: Get voltage by ADC + return int(sum([Power.getVbatt() for i in range(100)]) / 100) def get_energy(self): - self.__energy = self.__get_soc(self.get_temp(), self.get_voltage()) + self.__energy = self.__get_soc(self.__temp, self.get_voltage()) return self.__energy diff --git a/code/common.py b/code/common.py index 5293d48..971052d 100644 --- a/code/common.py +++ b/code/common.py @@ -88,7 +88,7 @@ class Observable(Singleton): class CloudObserver(object): - def do_event(self, observable, *args, **kwargs): + def execute(self, observable, *args, **kwargs): pass @@ -105,9 +105,12 @@ class CloudObservable(Singleton): def notifyObservers(self, *args, **kwargs): for o in self.__observers: - o.do_event(self, *args, **kwargs) + o.execute(self, *args, **kwargs) - def cloud_init(self, enforce=False): + def init(self, enforce=False): + pass + + def close(self): pass def post_data(self, data): diff --git a/code/location.py b/code/location.py index 5f2f936..169505d 100644 --- a/code/location.py +++ b/code/location.py @@ -13,7 +13,6 @@ # limitations under the License. import ure -import utime import osTimer import _thread import cellLocator @@ -50,9 +49,9 @@ class _gps_mode(object): external = 0x2 -class GPSParsing(object): +class GPSMatch(object): - def read_GxRMC(self, gps_data): + def GxRMC(self, gps_data): rmc_re = ure.search( r"\$G[NP]RMC,\d+\.\d+,[AV],\d+\.\d+,[NS],\d+\.\d+,[EW],\d+\.\d+,\d+\.\d+,\d+,\d*\.*\d*,[EW]*,[ADEN]*,[SCUV]*\**(\d|\w)*", gps_data) @@ -60,7 +59,7 @@ class GPSParsing(object): return rmc_re.group(0) return "" - def read_GxGGA(self, gps_data): + def GxGGA(self, gps_data): gga_re = ure.search( r"\$G[BLPN]GGA,\d+\.\d+,\d+\.\d+,[NS],\d+\.\d+,[EW],[0126],\d+,\d+\.\d+,-*\d+\.\d+,M,-*\d+\.\d+,M,\d*,\**(\d|\w)*", gps_data) @@ -68,232 +67,263 @@ class GPSParsing(object): return gga_re.group(0) return "" - def read_GxGGA_satellite_num(self, gps_data): - gga_data = self.read_GxGGA(gps_data) - if gga_data: - satellite_num_re = ure.search(r",[EW],[0126],\d+,", gga_data) - if satellite_num_re: - return satellite_num_re.group(0).split(",")[-2] - return "" - - def read_GxVTG(self, gps_data): + def GxVTG(self, gps_data): vtg_re = ure.search(r"\$G[NP]VTG,\d+\.\d+,T,\d*\.*\d*,M,\d+\.\d+,N,\d+\.\d+,K,[ADEN]*\*(\d|\w)*", gps_data) if vtg_re: return vtg_re.group(0) return "" - def read_GxVTG_speed(self, gps_data): - vtg_data = self.read_GxVTG(gps_data) - if vtg_data: - speed_re = ure.search(r",N,\d+\.\d+,K,", vtg_data) - if speed_re: - return speed_re.group(0)[3:-3] - return "" - - def read_GxGSV(self, gps_data): + def GxGSV(self, gps_data): gsv_re = ure.search(r"\$G[NP]GSV,\d+,\d+,\d+,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*,\d*\**(\d|\w)*", gps_data) if gsv_re: return gsv_re.group(0) return "" - def read_GxGSV_satellite_num(self, gps_data): - gsv_data = self.read_GxGSV(gps_data) + +class GPSParse(object): + + def GxGGA_satellite_num(self, gga_data): + if gga_data: + satellite_num_re = ure.search(r",[EW],[0126],\d+,", gga_data) + if satellite_num_re: + return satellite_num_re.group(0).split(",")[-2] + return "" + + def GxVTG_speed(self, vtg_data): + if vtg_data: + speed_re = ure.search(r",N,\d+\.\d+,K,", vtg_data) + if speed_re: + return speed_re.group(0)[3:-3] + return "" + + def GxGSV_satellite_num(self, gsv_data): if gsv_data: satellite_num_re = ure.search(r"\$G[NP]GSV,\d+,\d+,\d+,", gsv_data) if satellite_num_re: return satellite_num_re.group(0).split(",")[-2] return "" + def GxGGA_latitude(self, gga_data): + if gga_data: + latitude_re = ure.search(r",[0-9]+\.[0-9]+,[NS],", gga_data) + if latitude_re: + return latitude_re.group(0)[1:-3] + return "" + + def GxGGA_longtitude(self, gga_data): + if gga_data: + longtitude_re = ure.search(r",[0-9]+\.[0-9]+,[EW],", gga_data) + if longtitude_re: + return longtitude_re.group(0)[1:-3] + return "" + + def GxGGA_altitude(self, gga_data): + if gga_data: + altitude_re = ure.search(r",-*[0-9]+\.[0-9]+,M,", gga_data) + if altitude_re: + return altitude_re.group(0)[1:-3] + return "" + class GPS(Singleton): def __init__(self, gps_cfg, gps_mode): - self.gps_cfg = gps_cfg - self.gps_mode = gps_mode - self.uart_obj = None - self.gnss_obj = quecgnss - self.gps_parsing = GPSParsing() + self.__gps_cfg = gps_cfg + self.__gps_mode = gps_mode + self.__external_obj = None + self.__internal_obj = quecgnss + self.__gps_match = GPSMatch() + self.__gps_parse = GPSParse() - self.__uart_retrieve_queue = None + self.__external_retrieve_queue = None self.__first_break = 0 - self.__second_break = 0 + self.__break = 0 + self.__gps_data = "" + self.__rmc_data = "" + self.__gga_data = "" + self.__vtg_data = "" + self.__gsv_data = "" self.__gps_timer = osTimer() + self.__gps_clean_timer = osTimer() - if self.gps_mode & _gps_mode.external: - self._uart_init() - elif self.gps_mode & _gps_mode.internal: - self._gnss_init() + if self.__gps_mode & _gps_mode.external: + self.__external_init() + elif self.__gps_mode & _gps_mode.internal: + self.__internal_init() - def _uart_init(self): - self.__uart_retrieve_queue = Queue(maxsize=8) - self._uart_open() + def __first_gps_timer_callback(self, args): + self.__first_break = 1 + if self.__external_retrieve_queue is not None: + self.__external_retrieve_queue.put(0) - def _uart_open(self): - self.uart_obj = UART( - self.gps_cfg["UARTn"], self.gps_cfg["buadrate"], self.gps_cfg["databits"], - self.gps_cfg["parity"], self.gps_cfg["stopbits"], self.gps_cfg["flowctl"] + def __gps_timer_callback(self, args): + self.__break = 1 + if self.__external_retrieve_queue is not None: + self.__external_retrieve_queue.put(0) + + def __gps_clean_cb(self, args): + if self.__break == 0: + self.__gps_data = "" + self.__rmc_data = "" + self.__gga_data = "" + self.__vtg_data = "" + self.__gsv_data = "" + + def __external_init(self): + self.__external_retrieve_queue = Queue(maxsize=8) + self.__external_open() + + def __external_open(self): + self.__external_obj = UART( + self.__gps_cfg["UARTn"], self.__gps_cfg["buadrate"], self.__gps_cfg["databits"], + self.__gps_cfg["parity"], self.__gps_cfg["stopbits"], self.__gps_cfg["flowctl"] ) - self.uart_obj.set_callback(self._uart_retrieve_cb) + self.__external_obj.set_callback(self.__external_retrieve_cb) - def _uart_close(self): - self.uart_obj.close() + def __external_close(self): + self.__external_obj.close() - def _uart_retrieve_cb(self, args): + def __external_retrieve_cb(self, args): """ GPS data retrieve callback from UART When data comes, send a message to queue of data length """ toRead = args[2] - log.debug("GPS _uart_retrieve_cb args: %s" % str(args)) + log.debug("GPS __external_retrieve_cb args: %s" % str(args)) if toRead: - if self.__uart_retrieve_queue.size() >= 8: - self.__uart_retrieve_queue.get() - self.__uart_retrieve_queue.put(toRead) + if self.__external_retrieve_queue.size() >= 8: + self.__external_retrieve_queue.get() + self.__external_retrieve_queue.put(toRead) - def _gnss_init(self): - if self.gnss_obj: - if self.gnss_obj.init() != 0: - self._gnss_open() + def __internal_init(self): + if self.__internal_obj: + if self.__internal_obj.init() != 0: + self.__insternal_open() log.error("GNSS INIT Failed.") else: log.debug("GNSS INIT Success.") else: log.error("Module quecgnss Import Error.") - def _gnss_open(self): - if self.gnss_obj.get_state() == 0: - self.gnss_obj.gnssEnable(1) + def __insternal_open(self): + if self.__internal_obj.get_state() == 0: + self.__internal_obj.gnssEnable(1) - def _gnss_close(self): - self.gnss_obj.gnssEnable(0) - - def _first_gps_timer_callback(self, args): - self.__first_break = 1 - if self.__uart_retrieve_queue is not None: - self.__uart_retrieve_queue.put(0) - - def _second_gps_timer_callback(self, args): - self.__second_break = 1 - if self.__uart_retrieve_queue is not None: - self.__uart_retrieve_queue.put(0) - - def _uart_read(self): - self._uart_open() - log.debug("_uart_read start") - - while self.__first_break == 0: - self.__gps_timer.start(50, 0, self._first_gps_timer_callback) - nread = self.__uart_retrieve_queue.get() - log.debug("__first_break nread: %s" % nread) - data = self.uart_obj.read(nread).decode() - self.__gps_timer.stop() - self.__first_break = 0 - - data = "" - rmc_data = "" - gga_data = "" - vtg_data = "" - gsv_data = "" - while self.__second_break == 0: - get_flag = False - self.__gps_timer.start(1500, 0, self._second_gps_timer_callback) - nread = self.__uart_retrieve_queue.get() - log.debug("__second_break nread: %s" % nread) - if nread: - if not rmc_data: - rmc_data = self.gps_parsing.read_GxRMC(data) - get_flag = True - if not gga_data: - gga_data = self.gps_parsing.read_GxGGA(data) - get_flag = True - if not vtg_data: - vtg_data = self.gps_parsing.read_GxVTG(data) - get_flag = True - if not gsv_data: - gsv_data = self.gps_parsing.read_GxGSV(data) - get_flag = True - if get_flag: - data += self.uart_obj.read(nread).decode() - if rmc_data and gga_data and vtg_data and gsv_data: - self.__second_break = 1 - self.__gps_timer.stop() - log.debug("__second_break(_uart_read) data: %s" % data) - self.__second_break = 0 - - self._uart_close() - return data - - def _quecgnss_read(self): - self._gnss_init() - - while self.__first_break == 0: - self.__gps_timer.start(50, 0, self._first_gps_timer_callback) - data = quecgnss.read(1024) - self.__gps_timer.stop() - self.__first_break = 0 - - data = "" - rmc_data = "" - gga_data = "" - vtg_data = "" - gsv_data = "" - count = 0 - while self.__second_break == 0: - get_flag = False - self.__gps_timer.start(1500, 0, self._second_gps_timer_callback) - gnss_data = quecgnss.read(1024) - if gnss_data and gnss_data[1]: - if not rmc_data: - rmc_data = self.gps_parsing.read_GxRMC(data) - get_flag = True - if not gga_data: - gga_data = self.gps_parsing.read_GxGGA(data) - get_flag = True - if not vtg_data: - vtg_data = self.gps_parsing.read_GxVTG(data) - get_flag = True - if not gsv_data: - gsv_data = self.gps_parsing.read_GxGSV(data) - get_flag = True - if get_flag: - data += gnss_data[1].decode() if len(gnss_data) > 1 and gnss_data[1] else "" - if rmc_data and gga_data and vtg_data and gsv_data: - self.__second_break = 1 - self.__gps_timer.stop() - - if count > 5: - self.__second_break = 1 - count += 1 - utime.sleep_ms(300) - self.__second_break = 0 - - self._gnss_close() - return data + def __internal_close(self): + self.__internal_obj.gnssEnable(0) @option_lock(_gps_read_lock) + def __external_read(self): + self.__external_open() + log.debug("__external_read start") + + while self.__break == 0: + self.__gps_timer.start(50, 0, self.__gps_timer_callback) + nread = self.__external_retrieve_queue.get() + log.debug("[first] nread: %s" % nread) + self.__gps_data = self.__external_obj.read(nread).decode() + self.__break = 0 + + self.__gps_data = "" + self.__rmc_data = "" + self.__gga_data = "" + self.__vtg_data = "" + self.__gsv_data = "" + self.__gps_clean_timer.start(1050, 1, self.__gps_clean_cb) + while self.__break == 0: + self.__gps_timer.start(1500, 0, self.__gps_timer_callback) + nread = self.__external_retrieve_queue.get() + log.debug("[second] nread: %s" % nread) + if nread: + self.__gps_data += self.__external_obj.read(nread).decode() + if not self.__rmc_data: + self.__rmc_data = self.__gps_match.GxRMC(self.__gps_data) + if not self.__gga_data: + self.__gga_data = self.__gps_match.GxGGA(self.__gps_data) + if not self.__vtg_data: + self.__vtg_data = self.__gps_match.GxVTG(self.__gps_data) + if not self.__gsv_data: + self.__gsv_data = self.__gps_match.GxGSV(self.__gps_data) + if self.__rmc_data and self.__gga_data and self.__vtg_data and self.__gsv_data: + self.__break = 1 + self.__gps_timer.stop() + self.__gps_clean_timer.stop() + self.__break = 0 + + self.__external_close() + log.debug("__external_read data: %s" % self.__gps_data) + return self.__gps_data + + @option_lock(_gps_read_lock) + def __internal_read(self): + self.__external_open() + + while self.__break == 0: + self.__gps_timer.start(50, 0, self.__gps_timer_callback) + self.__gps_data = quecgnss.read(1024) + self.__gps_timer.stop() + self.__break = 0 + + self.__gps_data = "" + self.__rmc_data = "" + self.__gga_data = "" + self.__vtg_data = "" + self.__gsv_data = "" + self.__gps_clean_timer.start(1050, 1, self.__gps_clean_cb) + while self.__break == 0: + self.__gps_timer.start(1500, 0, self.__gps_timer_callback) + gnss_data = quecgnss.read(1024) + if gnss_data and gnss_data[1]: + self.__gps_data += gnss_data[1].decode() if len(gnss_data) > 1 and gnss_data[1] else "" + if not self.__rmc_data: + self.__rmc_data = self.__gps_match.GxRMC(self.__gps_data) + if not self.__gga_data: + self.__gga_data = self.__gps_match.GxGGA(self.__gps_data) + if not self.__vtg_data: + self.__vtg_data = self.__gps_match.GxVTG(self.__gps_data) + if not self.__gsv_data: + self.__gsv_data = self.__gps_match.GxGSV(self.__gps_data) + if self.__rmc_data and self.__gga_data and self.__vtg_data and self.__gsv_data: + self.__break = 1 + self.__gps_timer.stop() + self.__gps_clean_timer.stop() + self.__break = 0 + + self.__internal_close() + return self.__gps_data + def read(self): res = -1 gps_data = "" - if self.gps_mode & _gps_mode.external: - gps_data = self._uart_read() - elif self.gps_mode & _gps_mode.internal: - gps_data = self._quecgnss_read() + if self.__gps_mode & _gps_mode.external: + gps_data = self.__external_read() + elif self.__gps_mode & _gps_mode.internal: + gps_data = self.__internal_read() # TODO: Disable Output Satellite Num: if gps_data: - gga_satellite = self.gps_parsing.read_GxGGA_satellite_num(gps_data) + gga_satellite = self.__gps_parse.GxGGA_satellite_num(self.__gps_match.GxGGA(gps_data)) log.debug("GxGGA Satellite Num %s" % gga_satellite) - gsv_satellite = self.gps_parsing.read_GxGSV_satellite_num(gps_data) + gsv_satellite = self.__gps_parse.GxGSV_satellite_num(self.__gps_match.GxGSV(gps_data)) log.debug("GxGSV Satellite Num %s" % gsv_satellite) res = 0 return (res, gps_data) - def start(self): + def read_latitude(self, gps_data): + return self.__gps_parse.GxGGA_latitude(self.__gps_match.GxGGA(gps_data)) + + def read_longtitude(self, gps_data): + return self.__gps_parse.GxGGA_longtitude(self.__gps_match.GxGGA(gps_data)) + + def read_altitude(self, gps_data): + return self.__gps_parse.GxGGA_altitude(self.__gps_match.GxGGA(gps_data)) + + def on(self): # TODO: Set GPS ON return True - def stop(self): + def off(self): # TODO: Set GPS OFF return True @@ -342,7 +372,7 @@ class Location(Singleton): wifiLoc = None def __init__(self, gps_mode, locator_init_params): - self.gps_mode = gps_mode + self.__gps_mode = gps_mode self.locator_init_params = locator_init_params def __locater_init(self, loc_method): @@ -350,7 +380,7 @@ class Location(Singleton): if loc_method & _loc_method.gps: if self.gps is None: if self.locator_init_params.get("gps_cfg"): - self.gps = GPS(self.locator_init_params["gps_cfg"], self.gps_mode) + self.gps = GPS(self.locator_init_params["gps_cfg"], self.__gps_mode) else: raise ValueError("Invalid gps init parameters.") else: @@ -389,13 +419,11 @@ class Location(Singleton): return self.wifiLoc.read()[1] return () - def read(self, loc_method, read_all=False): + def read(self, loc_method): """ - 1. If read_all Is False - 1.1. Get GPS If loc_method Include GPS And GPS Data Exist; - 1.2. Get Cell If loc_method Inculde Cell And Not GPS Data; - 1.3. Get Wifi If loc_method Include Wifi And Not Cell Data; - 2. If read_all Is True, Return loc_method Include All Loc Method Data. + 1. If loc_method include gps then get gps data; + 2. If loc_method inculde cell then get cell data; + 3. If loc_method Include wifi then get wifi data; Return Data Format: @@ -410,17 +438,11 @@ class Location(Singleton): if loc_method & _loc_method.gps: loc_data[_loc_method.gps] = self.__read_gps() - if read_all is False: - return loc_data if loc_method & _loc_method.cell: loc_data[_loc_method.cell] = self.__read_cell() - if read_all is False: - return loc_data if loc_method & _loc_method.wifi: loc_data[_loc_method.wifi] = self.__read_wifi() - if read_all is False: - return loc_data return loc_data diff --git a/code/main.py b/code/main.py index 06481de..eeba8fb 100644 --- a/code/main.py +++ b/code/main.py @@ -12,29 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. -from usr.tracker import Tracker -from usr.settings import PROJECT_NAME -from usr.settings import PROJECT_VERSION -from usr.settings import SYSNAME -from usr.settings import DEVICE_FIRMWARE_VERSION from usr.logging import getLogger +from usr.tracker import tracker_main +from usr.settings import PROJECT_NAME, PROJECT_VERSION, DEVICE_FIRMWARE_NAME, DEVICE_FIRMWARE_VERSION log = getLogger(__name__) def main(): log.info("PROJECT_NAME: %s, PROJECT_VERSION: %s" % (PROJECT_NAME, PROJECT_VERSION)) - log.info("SYSNAME: %s, DEVICE_FIRMWARE_VERSION: %s" % (SYSNAME, DEVICE_FIRMWARE_VERSION)) + log.info("DEVICE_FIRMWARE_NAME: %s, DEVICE_FIRMWARE_VERSION: %s" % (DEVICE_FIRMWARE_NAME, DEVICE_FIRMWARE_VERSION)) - tracker = Tracker() - # Start Device Check - tracker.device_check() - - # Start PowerManage - # Init Low Energy Work Mode - tracker.power_manage.low_energy_init() - # Start RTC - tracker.power_manage.start_rtc() + tracker_main() if __name__ == "__main__": diff --git a/code/mpower.py b/code/mpower.py index 944ef05..27b7b31 100644 --- a/code/mpower.py +++ b/code/mpower.py @@ -14,7 +14,6 @@ import pm import utime -import modem import _thread from queue import Queue @@ -22,12 +21,10 @@ from machine import RTC from usr.common import Observable from usr.logging import getLogger -from usr.settings import settings -from usr.settings import LOWENERGYMAP log = getLogger(__name__) -LOW_ENERGY_METHOD = ("CYCLE", "PM", "PSM", "POWERDOWN") +LOW_ENERGY_METHOD = ("NULL", "PM", "PSM", "POWERDOWN") class LowEnergyRTC(Observable): @@ -36,7 +33,6 @@ class LowEnergyRTC(Observable): super().__init__() self.__period = 60 - self.__work_mode = 0x1 self.__low_energy_method = "PM" self.__thread_id = None @@ -51,25 +47,6 @@ class LowEnergyRTC(Observable): self.enable_rtc(0) self.__low_energy_queue.put(self.__low_energy_method) - # TODO: Remove To Business Module - def __get_low_energy_method(self): - current_settings = settings.get() - device_model = modem.getDevModel() - support_methds = LOWENERGYMAP.get(device_model, []) - if support_methds: - if self.__period >= current_settings["sys"]["work_mode_timeline"]: - if "PSM" in support_methds: - self.__low_energy_method = "PSM" - elif "POWERDOWN" in support_methds: - self.__low_energy_method = "POWERDOWN" - elif "PM" in support_methds: - self.__low_energy_method = "PM" - else: - if "PM" in support_methds: - self.__low_energy_method = "PM" - - return self.__low_energy_method - def __low_energy_work(self, lowenergy_tag): while True: data = self.__low_energy_queue.get() @@ -83,6 +60,10 @@ class LowEnergyRTC(Observable): self.notifyObservers(self, *(data,)) + if lowenergy_tag: + wulk_res = pm.wakelock_unlock(self.__lpm_fd) + log.debug("pm.wakelock_unlock %s." % ("Success" if wulk_res == 0 else "Falied")) + def get_period(self): return self.__period @@ -92,15 +73,6 @@ class LowEnergyRTC(Observable): return True return False - def get_work_mode(self): - return self.__work_mode - - def set_work_mode(self, work_mode): - if work_mode in (0x1, 0x2): - self.__work_mode = work_mode - return True - return False - def get_low_energy_method(self): return self.__low_energy_method @@ -125,7 +97,7 @@ class LowEnergyRTC(Observable): self.__thread_id = _thread.start_new_thread(self.__low_energy_work, (True,)) self.__lpm_fd = pm.create_wakelock(self.__pm_lock_name, len(self.__pm_lock_name)) pm.autosleep(1) - elif self.__low_energy_method == "CYCLE": + elif self.__low_energy_method == "NULL": self.__thread_id = _thread.start_new_thread(self.__low_energy_work, (False,)) elif self.__low_energy_method in ("PSM", "POWERDOWN"): pass diff --git a/code/quecthing.py b/code/quecthing.py index e2f45e0..f4d2c80 100644 --- a/code/quecthing.py +++ b/code/quecthing.py @@ -22,77 +22,9 @@ from queue import Queue from usr.ota import SOTA from usr.common import CloudObservable from usr.logging import getLogger -from usr.location import GPSParsing log = getLogger(__name__) -object_model = [ - # property - (9, ("power_switch", "rw")), - (4, ("energy", "r")), - (23, ("phone_num", "rw")), - (24, ("loc_method", "rw")), - (25, ("work_mode", "rw")), - (26, ("work_cycle_period", "rw")), - (19, ("local_time", "r")), - (15, ("low_power_alert_threshold", "rw")), - (16, ("low_power_shutdown_threshold", "rw")), - (12, ("sw_ota", "rw")), - (13, ("sw_ota_auto_upgrade", "rw")), - (10, ("sw_voice_listen", "rw")), - (11, ("sw_voice_record", "rw")), - (27, ("sw_fault_alert", "rw")), - (28, ("sw_low_power_alert", "rw")), - (29, ("sw_over_speed_alert", "rw")), - (30, ("sw_sim_abnormal_alert", "rw")), - (31, ("sw_disassemble_alert", "rw")), - (32, ("sw_drive_behavior_alert", "rw")), - (21, ("drive_behavior_code", "r")), - (33, ("power_restart", "w")), - (34, ("over_speed_threshold", "rw")), - (36, ("device_module_status", "r")), - (37, ("gps_mode", "r")), - (38, ("user_ota_action", "w")), - (41, ("voltage", "r")), - (42, ("ota_status", "r")), - (43, ("current_speed", "r")), - - # event - (6, ("sos_alert", "r")), - (14, ("fault_alert", "r")), - (17, ("low_power_alert", "r")), - (18, ("sim_abnormal_alert", "r")), - (20, ("disassemble_alert", "r")), - (22, ("drive_behavior_alert", "r")), - (35, ("over_speed_alert", "r")), -] - -object_model_struct = { - "device_module_status": { - "net": 1, - "location": 2, - "temp_sensor": 3, - "light_sensor": 4, - "move_sensor": 5, - "mike": 6, - }, - "loc_method": { - "gps": 1, - "cell": 2, - "wifi": 3, - }, - "ota_status": { - "sys_current_version": 1, - "sys_target_version": 2, - "app_current_version": 3, - "app_target_version": 4, - "upgrade_module": 5, - "upgrade_status": 6, - }, -} - -object_model_code = {i[1][0]: i[0] for i in object_model} - EVENT_CODE = { 1: { @@ -163,22 +95,57 @@ EVENT_CODE = { } +class QuecObjectModule(object): + + def __init__(self): + self.items = {} + self.items_id = {} + + def add_item(self, eid, name, perm, data_type, struct_info={}): + om_data = { + "id": eid, + "name": name, + "perm": perm, + "data_type": data_type, + "struct_info": struct_info, + } + if self.items.get(name) is None: + self.items[name] = om_data + self.items_id[eid] = name + return True + return False + + def update_item(self, eid, name, perm, data_type, struct_info={}): + if self.items.get(name) is not None: + self.del_item(name) + self.add_item(eid, name, perm, data_type, struct_info) + return True + return False + + def del_item(self, name): + if self.items.get(name) is not None: + self.items_id.pop(self.items[name]["id"]) + self.items.pop(name) + return True + + class QuecThing(CloudObservable): def __init__(self, pk, ps, dk, ds, server, life_time=120, mcu_name="", mcu_version=""): super().__init__() - self.pk = pk - self.ps = ps - self.dk = dk - self.ds = ds - self.server = server - self.life_time = life_time - self.mcu_name = mcu_name - self.mcu_version = mcu_version + self.__pk = pk + self.__ps = ps + self.__dk = dk + self.__ds = ds + self.__server = server + self.__life_time = life_time + self.__mcu_name = mcu_name + self.__mcu_version = mcu_version + self.__object_model = {} - self.file_size = 0 - self.md5_value = "" - self.post_result_wait_queue = Queue(maxsize=16) - self.quec_timer = osTimer() + self.__file_size = 0 + self.__md5_value = "" + self.__post_result_wait_queue = Queue(maxsize=16) + self.__quec_timer = osTimer() def __rm_empty_data(self, data): for k, v in data.items(): @@ -189,19 +156,19 @@ class QuecThing(CloudObservable): self.__put_post_res(False) def __get_post_res(self): - self.quec_timer.start(5000, 0, self.__quec_timer_cb) - res = self.post_result_wait_queue.get() - self.quec_timer.stop() + self.__quec_timer.start(5000, 0, self.__quec_timer_cb) + res = self.__post_result_wait_queue.get() + self.__quec_timer.stop() return res def __put_post_res(self, res): - if self.post_result_wait_queue.size() >= 16: - self.post_result_wait_queue.get() - self.post_result_wait_queue.put(res) + if self.__post_result_wait_queue.size() >= 16: + self.__post_result_wait_queue.get() + self.__post_result_wait_queue.put(res) def __sota_download_info(self, size, md5_value): - self.file_size = size - self.md5_value = md5_value + self.__file_size = size + self.__md5_value = md5_value def __sota_upgrade_start(self, start_addr, need_download_size): download_size = 0 @@ -216,10 +183,10 @@ class QuecThing(CloudObservable): need_download_size -= readsize start_addr += readsize download_size += readsize - if (download_size == self.file_size): + if (download_size == self.__file_size): log.debug("File Download Success, Update Start.") self.ota_action(3) - if sota_mode.check_md5(self.md5_value): + if sota_mode.check_md5(self.__md5_value): if sota_mode.file_update(): sota_mode.sota_set_flag() log.debug("File Update Success, Power Restart.") @@ -265,12 +232,12 @@ class QuecThing(CloudObservable): # TODO: Data Type Passthrough (Not Support Now). res_data = ("raw_data", eventdata) elif errcode == 10210: - dl_data = [(dict(object_model)[k][0], v.decode() if isinstance(v, bytes) else v) for k, v in eventdata.items() if "w" in dict(object_model)[k][1]] + dl_data = [(self.__object_model.items_id[k], v.decode() if isinstance(v, bytes) else v) for k, v in eventdata.items()] res_data = ("object_model", dl_data) elif errcode == 10211: # eventdata[0] is pkgId. object_model_ids = eventdata[1] - object_model_val = [dict(object_model)[i][0] for i in object_model_ids if dict(object_model).get(i) is not None and "r" in dict(object_model)[i][1]] + object_model_val = [self.__object_model.items_id[i] for i in object_model_ids if self.__object_model.items_id.get(i)] res_data = ("query", object_model_val) pass elif event == 7: @@ -304,9 +271,15 @@ class QuecThing(CloudObservable): log.info("OTA File Info: componentNo: %s, length: %s, md5: %s, crc: %s" % file_info) self.__sota_upgrade_start(int(file_info[2]), int(file_info[3])) - def cloud_init(self, enforce=False): + def set_object_model(self, object_model): + if object_model and isinstance(object_model, QuecObjectModule): + self.__object_model = object_model + return True + return False + + def init(self, enforce=False): log.debug( - "[cloud_init start] enforce: %s QuecThing Work State: %s, quecIot.getConnmode(): %s" + "[init start] enforce: %s QuecThing Work State: %s, quecIot.getConnmode(): %s" % (enforce, quecIot.getWorkState(), quecIot.getConnmode()) ) if enforce is False: @@ -315,12 +288,12 @@ class QuecThing(CloudObservable): quecIot.init() quecIot.setEventCB(self.__event_cb) - quecIot.setProductinfo(self.pk, self.ps) - if self.dk or self.ds: - quecIot.setDkDs(self.dk, self.ds) - quecIot.setServer(1, self.server) - quecIot.setLifetime(self.life_time) - quecIot.setMcuVersion(self.mcu_name, self.mcu_version) + quecIot.setProductinfo(self.__pk, self.__ps) + if self.__dk or self.__ds: + quecIot.setDkDs(self.__dk, self.__ds) + quecIot.setServer(1, self.__server) + quecIot.setLifetime(self.__life_time) + quecIot.setMcuVersion(self.__mcu_name, self.__mcu_version) quecIot.setConnmode(1) count = 0 @@ -328,72 +301,53 @@ class QuecThing(CloudObservable): utime.sleep_ms(200) count += 1 - if not self.ds and self.dk: + if not self.__ds and self.__dk: count = 0 while count < 3: dkds = quecIot.getDkDs() if dkds: - self.dk, self.ds = dkds + self.__dk, self.__ds = dkds log.debug("dk: %s, ds: %s" % dkds) res_data = ( "object_model", - [("cloud_init_params", {"PK": self.pk, "PS": self.ps, "DK": self.dk, "DS": self.ds, "SERVER": self.server})] + [("init_params", {"PK": self.__pk, "PS": self.__ps, "DK": self.__dk, "DS": self.__ds, "SERVER": self.__server})] ) self.notifyObservers(self, *res_data) break count += 1 utime.sleep(count) - log.debug("[cloud_init over] QuecThing Work State: %s, quecIot.getConnmode(): %s" % (quecIot.getWorkState(), quecIot.getConnmode())) + log.debug("[init over] QuecThing Work State: %s, quecIot.getConnmode(): %s" % (quecIot.getWorkState(), quecIot.getConnmode())) if quecIot.getWorkState() == 8 and quecIot.getConnmode() == 1: return True else: return False - def cloud_close(self): + def close(self): return quecIot.setConnmode(0) - def get_loc_data(self, loc_method, loc_data): - if loc_method == 0x1: - res = {"gps": []} - gps_parsing = GPSParsing() - r = gps_parsing.read_GxRMC(loc_data) - if r: - res["gps"].append(r) - - r = gps_parsing.read_GxGGA(loc_data) - if r: - res["gps"].append(r) - - r = gps_parsing.read_GxVTG(loc_data) - if r: - res["gps"].append(r) - return res - elif loc_method == 0x2: - return {"non_gps": ["LBS"]} - elif loc_method == 0x4: - return {"non_gps": []} + def __data_format(self, k, v): + if isinstance(v, dict): + nv = {} + for ik, iv in v.items(): + struct_info = self.__object_model.items[k]["struct_info"] if isinstance(self.__object_model.items[k]["struct_info"], dict) else {} + if struct_info.get(ik): + nv[struct_info[ik]["id"]] = iv + else: + nv[ik] = iv + v = nv + # log.debug("k: %s, v: %s" % (k, v)) + return {self.__object_model.items.get(k): v} def post_data(self, data): res = True # log.debug("post_data: %s" % str(data)) for k, v in data.items(): - if object_model_code.get(k) is not None: + if self.__object_model.items.get(k) is not None: # Event Data Format From object_mode_code if v is not None: - if isinstance(v, dict): - nv = {} - for ik, iv in v.items(): - if object_model_code.get(ik): - nv[object_model_code.get(ik)] = iv - else: - if object_model_struct.get(k): - nv[object_model_struct[k].get(ik)] = iv - else: - nv[ik] = iv - v = nv - # log.debug("k: %s, v: %s" % (k, v)) - phymodelReport_res = quecIot.phymodelReport(1, {object_model_code.get(k): v}) + om_data = self.__data_format(k, v) + phymodelReport_res = quecIot.phymodelReport(1, om_data) if not phymodelReport_res: res = False break diff --git a/code/remote.py b/code/remote.py index e4d422d..30866b7 100644 --- a/code/remote.py +++ b/code/remote.py @@ -51,7 +51,7 @@ class RemoteSubcribe(CloudObserver): else: return False - def do_event(self, observable, *args, **kwargs): + def execute(self, observable, *args, **kwargs): """ 1. observable: Cloud Iot Object. 2. args[1]: Cloud DownLink Data Type. @@ -62,14 +62,14 @@ class RemoteSubcribe(CloudObserver): 2.5 ota_file_download: Download OTA File For MQTT Association (Not Support Now). 3. args[2]: Cloud DownLink Data(List Or Dict). """ - option_attr = args[1] - args = args[2] if not isinstance(args[2], dict) else () - kwargs = args[2] if isinstance(args[2], dict) else {} - if hasattr(self, option_attr): - option_fun = getattr(self, option_attr) - return option_fun(*args, **kwargs) + opt_attr = args[1] + opt_args = args[2] if not isinstance(args[2], dict) else () + opt_kwargs = args[2] if isinstance(args[2], dict) else {} + if hasattr(self, opt_attr): + option_fun = getattr(self, opt_attr) + return option_fun(*opt_args, **opt_kwargs) else: - log.error("RemoteSubcribe Has No Attribute [%s]." % option_attr) + log.error("RemoteSubcribe Has No Attribute [%s]." % opt_attr) return False @@ -83,16 +83,13 @@ class RemotePublish(Observable): self.__cloud = None def __cloud_conn(self, enforce=False): - return self.__cloud.cloud_init(enforce=enforce) if self.__cloud else False + return self.__cloud.init(enforce=enforce) if self.__cloud else False def __cloud_post(self, data): return self.__cloud.post_data(data) if self.__cloud else False - def get_cloud(self): - return self.__cloud - def set_cloud(self, cloud): - if hasattr(cloud, "cloud_init") and \ + if hasattr(cloud, "init") and \ hasattr(cloud, "post_data") and \ hasattr(cloud, "ota_request") and \ hasattr(cloud, "ota_action"): @@ -143,10 +140,10 @@ class RemotePublish(Observable): if hist["data"]: pt_count = 0 for i, data in enumerate(hist["data"]): + pt_count += 1 if not self.post_data(data): res = False break - pt_count += 1 hist["data"] = hist["data"][pt_count:] if hist["data"]: diff --git a/code/settings.py b/code/settings.py index 052ea88..8dd8828 100644 --- a/code/settings.py +++ b/code/settings.py @@ -25,7 +25,8 @@ from usr.settings_sys import default_values_sys # For Other Module To Import from usr.settings_sys import PROJECT_NAME, PROJECT_VERSION, \ - DEVICE_FIRMWARE_NAME, DEVICE_FIRMWARE_VERSION, ALERTCODE, LOWENERGYMAP + DEVICE_FIRMWARE_NAME, DEVICE_FIRMWARE_VERSION, ALERTCODE, LOWENERGYMAP, \ + quec_object_model, quec_object_model_struct, ali_object_model PROJECT_NAME PROJECT_VERSION @@ -33,6 +34,9 @@ DEVICE_FIRMWARE_NAME DEVICE_FIRMWARE_VERSION ALERTCODE LOWENERGYMAP +quec_object_model +quec_object_model_struct +ali_object_model tracker_settings_file = "/usr/tracker_settings.json" diff --git a/code/settings_app.py b/code/settings_app.py index 45e6ad1..d7c8442 100644 --- a/code/settings_app.py +++ b/code/settings_app.py @@ -14,9 +14,9 @@ class default_values_app(object): - ''' + """ App default settings - ''' + """ class _loc_method(object): none = 0x0 @@ -35,11 +35,11 @@ class default_values_app(object): suddenly_turn_left = 0x2 suddenly_turn_right = 0x3 - ''' - variables of App default settings below MUST NOT start with '_' - ''' + """ + variables of App default settings below MUST NOT start with "_" + """ - phone_num = '' + phone_num = "" loc_method = _loc_method.all diff --git a/code/settings_sys.py b/code/settings_sys.py index a760ce4..3d6307b 100644 --- a/code/settings_sys.py +++ b/code/settings_sys.py @@ -54,6 +54,113 @@ LOWENERGYMAP = { ], } +quec_object_model = { + # property + 9: ("power_switch", "rw"), + 4: ("energy", "r"), + 23: ("phone_num", "rw"), + 24: ("loc_method", "rw"), + 25: ("work_mode", "rw"), + 26: ("work_cycle_period", "rw"), + 19: ("local_time", "r"), + 15: ("low_power_alert_threshold", "rw"), + 16: ("low_power_shutdown_threshold", "rw"), + 12: ("sw_ota", "rw"), + 13: ("sw_ota_auto_upgrade", "rw"), + 10: ("sw_voice_listen", "rw"), + 11: ("sw_voice_record", "rw"), + 27: ("sw_fault_alert", "rw"), + 28: ("sw_low_power_alert", "rw"), + 29: ("sw_over_speed_alert", "rw"), + 30: ("sw_sim_abnormal_alert", "rw"), + 31: ("sw_disassemble_alert", "rw"), + 32: ("sw_drive_behavior_alert", "rw"), + 21: ("drive_behavior_code", "r"), + 33: ("power_restart", "w"), + 34: ("over_speed_threshold", "rw"), + 36: ("device_module_status", "r"), + 37: ("gps_mode", "r"), + 38: ("user_ota_action", "w"), + 41: ("voltage", "r"), + 42: ("ota_status", "r"), + 43: ("current_speed", "r"), + + # event + 6: ("sos_alert", "r"), + 14: ("fault_alert", "r"), + 17: ("low_power_alert", "r"), + 18: ("sim_abnormal_alert", "r"), + 20: ("disassemble_alert", "r"), + 22: ("drive_behavior_alert", "r"), + 35: ("over_speed_alert", "r"), +} + +quec_object_model_struct = { + "device_module_status": { + "net": 1, + "location": 2, + "temp_sensor": 3, + "light_sensor": 4, + "move_sensor": 5, + "mike": 6, + }, + "loc_method": { + "gps": 1, + "cell": 2, + "wifi": 3, + }, + "ota_status": { + "sys_current_version": 1, + "sys_target_version": 2, + "app_current_version": 3, + "app_target_version": 4, + "upgrade_module": 5, + "upgrade_status": 6, + }, +} + +ali_object_model = { + "event": [ + "sos_alert", + "fault_alert", + "low_power_alert", + "sim_abnormal_alert", + "disassemble_alert", + "drive_behavior_alert", + "over_speed_alert", + ], + "property": [ + "power_switch", + "energy", + "phone_num", + "loc_method", + "work_mode", + "work_cycle_period", + "local_time", + "low_power_alert_threshold", + "low_power_shutdown_threshold", + "sw_ota", + "sw_ota_auto_upgrade", + "sw_voice_listen", + "sw_voice_record", + "sw_fault_alert", + "sw_low_power_alert", + "sw_over_speed_alert", + "sw_sim_abnormal_alert", + "sw_disassemble_alert", + "sw_drive_behavior_alert", + "drive_behavior_code", + "power_restart", + "over_speed_threshold", + "device_module_status", + "gps_mode", + "user_ota_action", + "ota_status", + "GeoLocation", + "voltage", + ], +} + class default_values_sys(object): """ diff --git a/code/test_tracker.py b/code/test_tracker.py index c8e0e65..c6e34c2 100644 --- a/code/test_tracker.py +++ b/code/test_tracker.py @@ -22,7 +22,8 @@ from usr.quecthing import QuecThing from usr.mpower import LowEnergyRTC from usr.common import Observable, Observer from usr.remote import RemoteSubcribe, RemotePublish -from usr.settings import Settings, PROJECT_NAME, PROJECT_VERSION +from usr.settings import Settings, PROJECT_NAME, PROJECT_VERSION, \ + quec_object_model, quec_object_model_struct log = Logger(__name__) @@ -181,7 +182,7 @@ def test_location(): locator = Location(gps_mode, locator_init_params) for loc_method in range(1, 8): - loc_data = locator.read(loc_method, read_all=True) + loc_data = locator.read(loc_method) if loc_method & 0x1: assert loc_data.get(0x1) not in ("", (), None), "[test_location] FAILED: locator.read(%s) loc_data: %s." % (loc_method, loc_data) if loc_method & 0x2: @@ -219,8 +220,18 @@ def test_quecthing(): locator_init_params = current_settings["sys"]["locator_init_params"] locator = Location(gps_mode, locator_init_params) - msg = "[test_quecthing] %s: cloud.cloud_init()." - assert cloud.cloud_init(), msg % "FAILED" + msg = "[test_quecthing] %s: cloud.set_object_model(%s)." + assert cloud.set_object_model(quec_object_model), msg % ("FAILED", quec_object_model) + print(msg % ("SUCCESS", quec_object_model)) + res["success"] += 1 + + msg = "[test_quecthing] %s: cloud.set_object_model_struct(%s)." + assert cloud.set_object_model_struct(quec_object_model_struct), msg % ("FAILED", quec_object_model_struct) + print(msg % ("SUCCESS", quec_object_model_struct)) + res["success"] += 1 + + msg = "[test_quecthing] %s: cloud.init()." + assert cloud.init(), msg % "FAILED" print(msg % "SUCCESS") res["success"] += 1 @@ -254,8 +265,8 @@ def test_quecthing(): # assert cloud.ota_action() is True, msg % ("FAILED",) # print(msg % ("SUCCESS",)) - msg = "[test_quecthing] %s: cloud.cloud_close()." - assert cloud.cloud_close(), msg % "FAILED" + msg = "[test_quecthing] %s: cloud.close()." + assert cloud.close(), msg % "FAILED" print(msg % "SUCCESS") res["success"] += 1 @@ -352,17 +363,6 @@ def test_low_energy_rtc(): print(msg % "SUCCESS") res["success"] += 1 - work_mode = 0x1 - msg = "[test_low_energy_rtc] %s: low_energy_rtc.set_work_mode(%s)." - assert low_energy_rtc.set_work_mode(work_mode), msg % ("FAILED", work_mode) - print(msg % ("SUCCESS", work_mode)) - res["success"] += 1 - - msg = "[test_low_energy_rtc] %s: low_energy_rtc.get_work_mode()." - assert low_energy_rtc.get_work_mode() == work_mode, msg % "FAILED" - print(msg % "SUCCESS") - res["success"] += 1 - low_energy_method = "PM" msg = "[test_low_energy_rtc] %s: low_energy_rtc.set_low_energy_method(%s)." assert low_energy_rtc.set_low_energy_method(low_energy_method), msg % ("FAILED", low_energy_method) @@ -404,13 +404,13 @@ def test_tracker(): def main(): - test_logger() - test_settings() - test_battery() - test_history() - test_location() - test_quecthing() - test_remote() + # test_logger() + # test_settings() + # test_battery() + # test_history() + # test_location() + # test_quecthing() + # test_remote() test_low_energy_rtc() diff --git a/code/tracker.py b/code/tracker.py index 4ca60f6..c42ed39 100644 --- a/code/tracker.py +++ b/code/tracker.py @@ -14,6 +14,7 @@ import sim import utime +import modem import _thread import checkNet import dataCall @@ -26,10 +27,10 @@ from usr.remote import Remote from usr.battery import Battery from usr.mpower import LowEnergyRTC from usr.logging import getLogger -from usr.location import Location -# from usr.ota import OTAFileClear +from usr.location import Location, GPSMatch, GPSParse +from usr.ota import OTAFileClear from usr.common import numiter, Singleton -from usr.settings import ALERTCODE, SYSNAME, PROJECT_NAME, \ +from usr.settings import ALERTCODE, DEVICE_FIRMWARE_NAME, PROJECT_NAME, LOWENERGYMAP, \ settings, default_values_app, default_values_sys, Settings try: @@ -87,10 +88,6 @@ class Tracker(Singleton): self.__sensor = None self.__locator = None - # TODO: Remote To Main Function. - # fileClear = OTAFileClear() - # fileClear.file_clear() - self.num_iter = numiter() self.num_lock = _thread.allocate_lock() @@ -125,7 +122,7 @@ class Tracker(Singleton): if current_settings["app"]["sw_over_speed_alert"] is True: if self.locator.gps: gps_data = self.locator.gps.read() - speed = self.locator.gps.read_location_GxVTG_speed(gps_data) + speed = GPSParse.GxVTG_speed(GPSMatch().GxVTG(gps_data)) if speed and float(speed) >= current_settings["app"]["over_speed_threshold"]: alert_code = 30003 alert_info = {"local_time": self.__get_local_time()} @@ -152,8 +149,77 @@ class Tracker(Singleton): return alert_data - def get_controller(self): - return self.__controller + def __get_low_energy_method(self, period): + current_settings = self.__controller.settings_get() + device_model = modem.getDevModel() + support_methds = LOWENERGYMAP.get(device_model, []) + method = "NULL" + if support_methds: + if period >= current_settings["sys"]["work_mode_timeline"]: + if "PSM" in support_methds: + method = "PSM" + elif "POWERDOWN" in support_methds: + method = "POWERDOWN" + elif "PM" in support_methds: + method = "PM" + else: + if "PM" in support_methds: + method = "PM" + + return method + + def __get_ali_loc_data(self, loc_method, loc_data): + res = {"GeoLocation": {}} + + if loc_method == 0x1: + gps_match = GPSMatch() + gps_parse = GPSParse() + gga_data = gps_match.GxGGA(loc_data) + data = {} + if gga_data: + Latitude = gps_parse.GxGGA_latitude(gga_data) + if Latitude: + data["Latitude"] = float('%.2f' % float(Latitude)) + Longtitude = gps_parse.GxGGA_longtitude() + if Longtitude: + data["Longtitude"] = float('%.2f' % float(Longtitude)) + Altitude = gps_parse.GxGGA_altitude() + if Altitude: + data["Altitude"] = float('%.2f' % float(Altitude)) + if data: + data["CoordinateSystem"] = 1 + res = {"GeoLocation": data} + elif loc_method in (0x2, 0x4): + if loc_data: + res["GeoLocation"] = { + "Longtitude": round(loc_data[0], 2), + "Latitude": round(loc_data[1], 2), + # "Altitude": 0.0, + "CoordinateSystem": 1 + } + + return res + + def __get_quec_loc_data(self, loc_method, loc_data): + if loc_method == 0x1: + res = {"gps": []} + gps_match = GPSMatch() + r = gps_match.GxRMC(loc_data) + if r: + res["gps"].append(r) + + r = gps_match.GxGGA(loc_data) + if r: + res["gps"].append(r) + + r = gps_match.GxVTG(loc_data) + if r: + res["gps"].append(r) + return res + elif loc_method == 0x2: + return {"non_gps": ["LBS"]} + elif loc_method == 0x4: + return {"non_gps": []} def set_controller(self, controller): if isinstance(controller, Controller): @@ -161,36 +227,24 @@ class Tracker(Singleton): return True return False - def get_devicecheck(self): - return self.__devicecheck - def set_devicecheck(self, devicecheck): if isinstance(devicecheck, DeviceCheck): self.__devicecheck = devicecheck return True return False - def get_battery(self): - return self.__battery - def set_battery(self, battery): if isinstance(battery, Battery): self.__battery = battery return True return False - def get_sensor(self): - return self.__sensor - def set_sensor(self, sensor): if isinstance(sensor, Sensor): self.__sensor = sensor return True return False - def get_locator(self): - return self.__locator - def set_locator(self, locator): if isinstance(locator, Location): self.__locator = locator @@ -253,19 +307,19 @@ class Tracker(Singleton): "local_time": self.__get_local_time(), } - # Get Cloud Location Data + # Get cloud location data loc_info = self.locator.read(current_settings["app"]["loc_method"]) if self.locator else None if loc_info: loc_method_dict = {1: "GPS", 2: "CELL", 4: "WIFI"} log.debug("Location Data loc_method: %s" % loc_method_dict.get(loc_info[0], loc_info[0])) device_data.update(loc_info[1]) - # Get GPS Speed + # Get gps speed over_speed_check_res = self.__device_speed_check() log.debug("over_speed_check_res: %s" % str(over_speed_check_res)) device_data.update(over_speed_check_res) - # Get Battery Energy + # Get battery energy energy = self.battery.energy() device_data.update({ "energy": energy, @@ -275,19 +329,19 @@ class Tracker(Singleton): alert_data = self.__get_alert_data(30002, {"local_time": self.__get_local_time()}) device_data.update(alert_data) - # Get OTA Status & Drive Behiver Code + # Get ota status & drive behiver code device_data.update({ "ota_status": current_settings["sys"]["ota_status"], "drive_behavior_code": current_settings["sys"]["drive_behavior_code"], }) - # Get APP Settings Info + # Get app settings info device_data.update(current_settings["app"]) - # Format Loc Method + # Format loc method device_data.update({"loc_method": self.__format_loc_method(current_settings["app"]["loc_method"])}) - # TODO: Add Other Machine Info. + # TODO: Add other machine info. return device_data @@ -301,7 +355,7 @@ class Tracker(Singleton): log.debug("[x] post data topic [%s]" % topic) post_res = self.__controller.remote_post_data(device_data) - # OTA Status RST + # OTA status rst current_settings = settings.get() ota_status_info = current_settings["sys"]["ota_status"] if ota_status_info["upgrade_status"] in (3, 4): @@ -323,7 +377,7 @@ class Tracker(Singleton): if current_settings["sys"]["user_ota_action"] != -1: self.__controller.settings_set("user_ota_action", -1) - # Do Cloud Event Down Command By Controller + # Do cloud event downlink option by controller def event_option(self, *args, **kwargs): # TODO: Data Type Passthrough (Not Support Now). return False @@ -392,7 +446,7 @@ class Tracker(Singleton): ota_status_info = current_settings["sys"]["ota_status"] if ota_status_info["sys_target_version"] == "--" and ota_status_info["app_target_version"] == "--": ota_info = {} - if upgrade_info[0] == SYSNAME: + if upgrade_info[0] == DEVICE_FIRMWARE_NAME: ota_info["upgrade_module"] = 1 ota_info["sys_target_version"] = upgrade_info[2] elif upgrade_info[0] == PROJECT_NAME: @@ -410,11 +464,38 @@ class Tracker(Singleton): def work_cycle_period(self, period): # Reset work_cycle_period & Reset RTC self.__controller.low_energy_rtc_enable(0) + + self.__controller.low_energy_rtc_set_period(period) + method = self.__get_low_energy_method(period) + self.__controller.low_energy_rtc_set_method(method) + + self.__controller.low_energy_rtc_init() self.__controller.low_energy_rtc_start() def cloud_init_params(self, params): self.__controller.settings_set("cloud_init_params", params) - self.__controllers.save() + self.__controller.settings_save() + + def low_engery_rtc_option(self, low_energy_method): + current_settings = self.__controller.settings_get() + if current_settings["app"]["work_mode"] == default_values_app._work_mode.intelligent: + speed_info = self.__device_speed_check() + if speed_info.get("current_speed") > 0: + self.device_data_report() + else: + self.device_data_report() + + self.__controller.low_energy_rtc_start() + + if low_energy_method == "PSM": + # TODO: PSM option. + pass + elif low_energy_method == "POWERDOWN": + self.__controller.power_down() + + def update(self, observable, *args, **kwargs): + if isinstance(observable, LowEnergyRTC): + self.low_engery_rtc_option(args[1]) class DeviceCheck(object): @@ -477,9 +558,7 @@ class Controller(Singleton): self.__power_key = None self.__usb = None self.__data_call = None - - def get_remote(self): - return self.__remote + self.__ota_file_clear = None def set_remote(self, remote): if isinstance(remote, Remote): @@ -493,36 +572,24 @@ class Controller(Singleton): return True return False - def get_low_energy_rtc(self): - return self.__low_energy_rtc - def set_low_energy_rtc(self, low_energy_rtc): if isinstance(low_energy_rtc, LowEnergyRTC): self.__low_energy_rtc = low_energy_rtc return True return False - def get_energy_led(self): - return self.__energy_led - def set_energy_led(self, energy_led): if isinstance(energy_led, LED): self.__energy_led = energy_led return True return False - def get_running_led(self): - return self.__running_led - def set_running_led(self, running_led): if isinstance(running_led, LED): self.__running_led = running_led return True return False - def get_power_key(self): - return self.__power_key - def set_power_key(self, power_key, power_key_cb): if isinstance(power_key, PowerKey): self.__power_key = power_key @@ -530,9 +597,6 @@ class Controller(Singleton): return True return False - def get_usb(self): - return self.__usb - def set_usb(self, usb, usb_cb): if isinstance(usb, USB): self.__usb = usb @@ -541,9 +605,6 @@ class Controller(Singleton): return True return False - def get_data_call(self): - return self.__data_call - def set_data_call(self, data_call, data_call_cb): if isinstance(data_call, dataCall): self.__data_call = data_call @@ -552,6 +613,12 @@ class Controller(Singleton): return True return False + def set_ota_file_clear(self, ota_file_clear): + if isinstance(ota_file_clear, OTAFileClear): + self.__ota_file_clear = ota_file_clear + return True + return False + def settings_get(self): return self.__settings.get() @@ -584,8 +651,26 @@ class Controller(Singleton): def remote_ota_action(self, action, module): return self.__remote.cloud_ota_action(action, module) + def low_energy_rtc_init(self): + return self.__low_energy_rtc.low_energy_init() + def low_energy_rtc_start(self): return self.__low_energy_rtc.start_rtc() def low_energy_rtc_enable(self, enable): return self.__low_energy_rtc.enable_alarm(enable) + + def low_energy_rtc_set_period(self, period): + return self.__low_energy_rtc.set_period(period) + + def low_energy_rtc_set_method(self, method): + return self.__low_energy_rtc.set_low_energy_method(method) + + def ota_file_clean(self): + self.__ota_file_clear.file_clear() + + +def tracker_main(): + tracker = Tracker() + devicecheck = DeviceCheck() + tracker.set_devicecheck(devicecheck) diff --git a/readme.md b/readme.md index 2fc1ff5..80e6a40 100644 --- a/readme.md +++ b/readme.md @@ -1,11 +1,8 @@ - -# Tracker-v2.0.0 - ## 修订历史 | Version | **Date** | **Author** | **Change expression** | | :------ | ---------- | ---------- | --------------------- | -| 2.0.0 | 2022-03-15 | 孙健 | 初始版本 | +| 1.0.0 | 2022-03-15 | 孙健 | 初始版本 | ## Tracker介绍