From 2d97ba5bd85f59fd9f78f4ef439b55ff69077902 Mon Sep 17 00:00:00 2001 From: JackSun-qc Date: Mon, 7 Mar 2022 14:47:10 +0800 Subject: [PATCH] update: 1. settings option thread lock; 2. move cloud init params to settings; 3. down link option. --- code/main.py | 2 + code/quecthing.py | 60 ++++++++++----------- code/remote.py | 131 +++++++++++++++++++++++++--------------------- code/settings.py | 81 +++++++++++++++++++++++++++- 4 files changed, 183 insertions(+), 91 deletions(-) diff --git a/code/main.py b/code/main.py index cdee147..1cb7199 100644 --- a/code/main.py +++ b/code/main.py @@ -6,6 +6,8 @@ from usr.logging import getLogger log = getLogger(__name__) +version = '1.0.0' + tracker = None diff --git a/code/quecthing.py b/code/quecthing.py index 439cd90..39b9cee 100644 --- a/code/quecthing.py +++ b/code/quecthing.py @@ -10,32 +10,32 @@ DATA_LOCA_GPS = 0x2 log = getLogger(__name__) object_model = [ - (9, 'switch'), - (4, 'energy'), - (23, 'phone_num'), - (24, 'loc_method'), - (25, 'loc_mode'), - (26, 'loc_cycle_period'), - (19, 'local_time'), - (15, 'low_power_alert_threshold'), - (16, 'low_power_shutdown_threshold'), - (12, 'sw_ota'), - (13, 'sw_ota_auto_upgrade'), - (10, 'sw_voice_listen'), - (11, 'sw_voice_record'), - (27, 'sw_fault_alert'), - (28, 'sw_low_power_alert'), - (29, 'sw_over_speed_alert'), - (30, 'sw_sim_out_alert'), - (31, 'sw_disassemble_alert'), - (32, 'sw_drive_behavior_alert'), - (21, 'drive_behavior_code'), - (6, 'sos_alert'), - (14, 'fault_alert'), - (17, 'low_power_alert'), - (18, 'sim_out_alert'), - (22, 'drive_behavior_alert'), - (20, 'disassemble_alert') + (9, ('switch', 'rw')), + (4, ('energy', 'r')), + (23, ('phone_num', 'rw')), + (24, ('loc_method', 'rw')), + (25, ('loc_mode', 'rw')), + (26, ('loc_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_out_alert', 'rw')), + (31, ('sw_disassemble_alert', 'rw')), + (32, ('sw_drive_behavior_alert', 'rw')), + (21, ('drive_behavior_code', 'r')), + (6, ('sos_alert', 'rw')), + (14, ('fault_alert', 'rw')), + (17, ('low_power_alert', 'rw')), + (18, ('sim_out_alert', 'rw')), + (22, ('drive_behavior_alert', 'rw')), + (20, ('disassemble_alert', 'rw')) ] @@ -136,15 +136,15 @@ class QuecThing(object): self.downlink_queue.put(('raw_data', data)) if errcode == 10210: log.info('Recving object model data.') - dl_data = [(dict(object_model)[k], v.decode() if isinstance(v, bytes) else v) for k, v in data.items()] - self.downlink_queue.put(('set', dl_data)) + dl_data = [(dict(object_model)[k][0], v.decode() if isinstance(v, bytes) else v) for k, v in data.items() if 'w' in dict(object_model)[k][1]] + self.downlink_queue.put(('object_model', dl_data)) elif errcode == 10211: log.info('Recving object model query command.') # TODO: Check pkgId for other uses. # log.info('pkgId: %s' % data[0]) object_model_ids = data[1] - object_model_val = [dict(object_model).get(i) for i in object_model_ids if object_model_ids.get(i) is not None] - self.downlink_queue.put(('get', object_model_val)) + 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]] + self.downlink_queue.put(('query', object_model_val)) elif event == 6: if errcode == 10200: log.info('Logout succeeded.') diff --git a/code/remote.py b/code/remote.py index 28e351a..b1996bc 100644 --- a/code/remote.py +++ b/code/remote.py @@ -6,7 +6,6 @@ import uos import _thread from queue import Queue import usr.settings as settings -import usr.dev_info as dev_info from usr.logging import getLogger log = getLogger(__name__) @@ -26,41 +25,74 @@ class RemoteError(Exception): return repr(self.value) -class DownLinkOption(object): - def __init__(self, remote_obj): - self.remote_obj = remote_obj +class Controller(object): + def __init__(self, remote): + self.remote = remote - def remote_post_data(self, key, val): - # TODO: Self funtion over to post or not. - self.remote_obj.post_data(self.remote_obj.DATA_NON_LOCA, {key: val}) + def switch(self, perm, flag=None, *args): + if perm == 'r': + # TODO: PowerStatus + pass + elif perm == 'w': + if flag is True: + # TODO: PowerUp + pass + elif flag is False: + # TODO: PowerDown + pass + else: + pass + else: + raise RemoteError('Controller switch permission error %s.' % perm) - def get_switch(self, *args): - return True - - def set_switch(self, *args): - if args[0] is False: - # TODO: How to checkout msg that is posted over before power down. + def energy(self, perm, *args): + if perm == 'r': + # TODO: How to get energy from Power.getVbatt(). pass else: - return True + raise RemoteError('Controller energy permission error %s.' % perm) - def get_energy(self, *args): - # TODO: How to get energy from Power.getVbatt(). - pass - - def get_app_settings(self, *args): - return settings.current_settings['app'][args[0]] - - def set_app_settings(self, *args): - if settings.set(args[0], args[1]): - settings.save() - return args[1] + def drive_behavior_code(self, perm, *args): + if perm == 'r': + pass else: - return self.get_app_settings(args[0]) + raise RemoteError('Controller drive_behavior_code permission error %s.' % perm) - def get_drive_behavior_code(self, *args): + +class DownLinkOption(object): + def __init__(self, remote): + self.remote = remote + self.controller = Controller(self.remote) + + def row_data(self, *args, **kwargs): pass + def object_model(self, *args, **kwargs): + setting_flag = 0 + + for arg in args: + if hasattr(settings.default_values_app, arg[0]): + set_res = settings.set(arg[0], arg[1]) + log.debug('key: %s, val: %s, set_res: %s', (arg[0], arg[1], set_res)) + if setting_flag == 0: + setting_flag = 1 + elif hasattr(self.controller, arg[0]): + getattr(self.controller, arg[0])(*('w', arg[1])) + else: + pass + + if setting_flag: + settings.save() + + def query(self, *args, **kwargs): + for arg in args: + if hasattr(settings.default_values_app, arg): + settings.query(self.remote, 'app', arg) + elif hasattr(self.controller, arg): + getattr(self.controller, arg)(*('r')) + else: + pass + def downlink_process(argv): self = argv @@ -73,39 +105,17 @@ def downlink_process(argv): TODO: ===================== ''' data = self.downlink_queue.get() + log.debug('downlink_queue data:', data) - DownLinkOptionObj = DownLinkOption(remote_obj=self) - for option_type, option_data in data: - for item in option_data: - model_obj_name = '' - args = () - option_attr = '' - if option_type == 'set': - model_obj_name = item[0] - if hasattr(settings.default_values_app, model_obj_name): - option_attr = 'set_app_settings' - args = item - else: - option_attr = 'set_' + model_obj_name - args = (item[1],) - elif option_type == 'get': - model_obj_name = item - if hasattr(settings.default_values_app, model_obj_name): - option_attr = 'get_app_settings' - args = (item,) - else: - option_attr = 'get_' + model_obj_name - else: - # TODO: row data - pass - - if hasattr(DownLinkOptionObj, option_attr): - option_fun = getattr(DownLinkOptionObj, option_attr) - option_fun_res = option_fun(*args) - self.post_data(self.DATA_NON_LOCA, {model_obj_name: option_fun_res}) - else: - # TODO: Raise Error OR Conntinue - raise RemoteError('DownLinkOption has no accribute %s.' % option_fun) + DownLinkOptionObj = DownLinkOption(remote=self) + option_attr = data[0] + args = data[1] + if hasattr(DownLinkOptionObj, option_attr): + option_fun = getattr(DownLinkOptionObj, option_attr) + option_fun(*args) + else: + # TODO: Raise Error OR Conntinue + raise RemoteError('DownLinkOption has no accribute %s.' % option_attr) ''' TODO: processing for settings or control commands from downlink channel ''' @@ -203,8 +213,9 @@ class Remote(object): def __init__(self): self.downlink_queue = Queue(maxsize=64) self.uplink_queue = Queue(maxsize=64) + cloud_init_params = settings.current_settings['sys']['cloud_init_params'] if current_settings['sys']['cloud'] == settings.default_values_sys._cloud.quecIot: - self.cloud = QuecThing(dev_info.quecIot['PK'], dev_info.quecIot['PS'], dev_info.quecIot['DK'], dev_info.quecIot['DS'], self.downlink_queue) + self.cloud = QuecThing(cloud_init_params['PK'], cloud_init_params['PS'], cloud_init_params['DK'], cloud_init_params['DS'], self.downlink_queue) self.DATA_NON_LOCA = DATA_NON_LOCA self.DATA_LOCA_NON_GPS = DATA_LOCA_NON_GPS self.DATA_LOCA_GPS = DATA_LOCA_GPS diff --git a/code/settings.py b/code/settings.py index 9cd1172..83a467c 100644 --- a/code/settings.py +++ b/code/settings.py @@ -3,6 +3,8 @@ import ql_fs import ujson import uos import ure +import _thread +import quecIot from machine import UART from usr.logging import getLogger @@ -14,6 +16,23 @@ current_settings = {} current_settings_app = {} current_settings_sys = {} +_settings_lock = _thread.allocate_lock() + + +def settings_lock(func): + def wrapperd_fun(*args, **kwargs): + if not _settings_lock.locked(): + if _settings_lock.acquire(): + source_fun = func(*args, **kwargs) + _settings_lock.release() + return source_fun + else: + log.warn('%s for _settings_lock acquire falied. args: %s' % (func.__name__, args)) + else: + log.warn('%s for _settings_lock is locked. args: %s' % (func.__name__, args)) + + return wrapperd_fun + class default_values_app(object): ''' @@ -97,6 +116,29 @@ class default_values_sys(object): cloud = _cloud.quecIot + cloud_init_params = {} + + _quecIot = { + 'PK': 'p11275', + 'PS': 'Q0ZQQndaN3pCUFd6', + 'DK': 'trackdev0304', + 'DS': '8eba9389af434974c3c846d1922d949f', + } + + _AliYun = { + 'PK': '', + 'PS': '', + 'DK': '', + 'DS': '', + } + + _JTT808 = { + 'PK': '', + 'PS': '', + 'DK': '', + 'DS': '', + } + locator_init_params = {} _gps_cfg = { @@ -134,11 +176,39 @@ class default_values_sys(object): return locator_init_params + @staticmethod + def _get_cloud_init_params(cloud): + global current_settings + cloud_init_params = current_settings.get('sys', {}).get('cloud_init_params', {}) + if cloud & default_values_sys._cloud.quecIot: + cloud_init_params = default_values_sys._quecIot + cloud_init_params = default_values_sys._quecIot_init_params(cloud_init_params) + if cloud & default_values_sys._cloud.AliYun: + cloud_init_params = default_values_sys._AliYun + if cloud & default_values_sys._cloud.JTT808: + cloud_init_params = default_values_sys._JTT808 + + return cloud_init_params + + @staticmethod + def _quecIot_init_params(cloud_init_params): + if not cloud_init_params['DK'] or not cloud_init_params['DS']: + if quecIot.init(): + if quecIot.setProductinfo(pk, ps): + if quecIot.setDkDs(dk, ds): + ndk, nds = quecIot.getDkDs() + cloud_init_params['DK'] = ndk + cloud_init_params['DS'] = nds + return cloud_init_params + + +@settings_lock def init(): global current_settings default_values_sys.locator_init_params = default_values_sys._get_locator_init_params(default_values_app.loc_method) + default_values_sys.cloud_init_params = default_values_sys._get_cloud_init_params(default_values_sys.cloud) default_settings_app = {k: v for k, v in default_values_app.__dict__.items() if not k.startswith('_')} default_settings_sys = {k: v for k, v in default_values_sys.__dict__.items() if not k.startswith('_')} @@ -153,11 +223,19 @@ def init(): current_settings = ujson.load(f) +@settings_lock def get(): global current_settings return current_settings +@settings_lock +def query(remote, set_type, set_key): + global current_settings + remote.post_data(remote.DATA_NON_LOCA, {set_key: current_settings.get(set_type, {}).get(set_key)}) + + +@settings_lock def set(opt, val): global current_settings @@ -216,16 +294,17 @@ def set(opt, val): else: return False - else: return False +@settings_lock def save(): with open(tracker_settings_file, 'w') as f: ujson.dump(current_settings, f) +@settings_lock def reset(): uos.remove(tracker_settings_file)