diff --git a/code/location.py b/code/location.py index 95ee635..1a619a7 100644 --- a/code/location.py +++ b/code/location.py @@ -1,6 +1,7 @@ import ure -import _thread +# import _thread +import osTimer import cellLocator import usr.settings as settings @@ -35,7 +36,10 @@ def gps_data_retrieve_cb(para_list): ''' global gps_data_retrieve_queue toRead = para_list[2] + log.debug('gps_data_retrieve_cb para_list: %s' % str(para_list)) if toRead: + if gps_data_retrieve_queue.size() >= 8: + gps_data_retrieve_queue.get() gps_data_retrieve_queue.put(toRead) @@ -51,15 +55,20 @@ def gps_data_retrieve_thread(argv): self = argv while True: - toRead = gps_data_retrieve_queue.get() - if toRead: - self.gps_data = self.uart_read(toRead).decode() + current_settings = settings.settings.get() + if current_settings['sys']['gps_mode'] & settings.default_values_sys._gps_mode.external: + self.gps_data = self.uart_read().decode() + elif current_settings['sys']['gps_mode'] & settings.default_values_sys._gps_mode.internal: + self.gps_data = self.quecgnss_read() class GPS(Singleton): def __init__(self, gps_cfg): self.gps_data = '' self.gps_cfg = gps_cfg + self.gps_timer = osTimer() + self.gps_over_timer = osTimer() + self.break_flag = 0 current_settings = settings.settings.get() if current_settings['sys']['gps_mode'] & settings.default_values_sys._gps_mode.external: self.uart_init() @@ -78,90 +87,117 @@ class GPS(Singleton): ) self.uart_obj.set_callback(gps_data_retrieve_cb) gps_data_retrieve_queue = Queue(maxsize=8) - _thread.start_new_thread(gps_data_retrieve_thread, (self,)) + # _thread.start_new_thread(gps_data_retrieve_thread, (self,)) - def uart_read(self, nread): + def gps_timer_callback(self, args): + self.break_flag = 1 + + def gps_over_timer_cb(self, args): + global gps_data_retrieve_queue + gps_data_retrieve_queue.put(0) + + def uart_read(self): + log.debug('start uart_read') + global gps_data_retrieve_queue + while self.break_flag == 0: + self.gps_timer.start(200, 1, self.gps_timer_callback) + self.gps_over_timer.start(20000, 1, self.gps_over_timer_cb) + nread = gps_data_retrieve_queue.get() + self.gps_timer.stop() + self.gps_over_timer.stop() + + log.debug('uart_read nread') + self.break_flag = 0 return self.uart_obj.read(nread).decode() def quecgnss_read(self): if quecgnss.get_state() == 0: quecgnss.gnssEnable(1) - data = quecgnss.read(4096) - self.gps_data = data[1].decode() + while self.break_flag == 0: + self.gps_timer.start(500, 1, self.gps_timer_callback) + quecgnss.read(4096) + self.gps_timer.stop() - return self.gps_data + self.break_flag = 0 + data = None + while not data: + data = quecgnss.read(4096) + + return data[1].decode() def read(self): + current_settings = settings.settings.get() + if current_settings['sys']['gps_mode'] & settings.default_values_sys._gps_mode.external: + self.gps_data = self.uart_read().decode() + elif current_settings['sys']['gps_mode'] & settings.default_values_sys._gps_mode.internal: + self.gps_data = self.quecgnss_read() + return self.gps_data - def read_location_GxRMC(self): - gps_data = self.read() + def read_location_GxRMC(self, gps_data): rmc_re = ure.search( r"\$G[NP]RMC,[0-9]+\.[0-9]+,A,[0-9]+\.[0-9]+,[NS],[0-9]+\.[0-9]+,[EW],[0-9]+\.[0-9]+,[0-9]+\.[0-9]+,[0-9]+,,,[ADE],[SCUV]\*[0-9]+", gps_data) if rmc_re: return rmc_re.group(0) - else: - return "" + return "" - def read_location_GxGGA(self): - gps_data = self.read() + def read_location_GxGGA(self, gps_data): gga_re = ure.search( r"\$G[BLPN]GGA,[0-9]+\.[0-9]+,[0-9]+\.[0-9]+,[NS],[0-9]+\.[0-9]+,[EW],[126],[0-9]+,[0-9]+\.[0-9]+,-*[0-9]+\.[0-9]+,M,-*[0-9]+\.[0-9]+,M,,\*[0-9]+", gps_data) if gga_re: return gga_re.group(0) - else: - return "" + return "" - def read_location_GxVTG(self): - gps_data = self.read() + def read_location_GxVTG(self, gps_data): vtg_re = ure.search(r"\$G[NP]VTG,[0-9]+\.[0-9]+,T,([0-9]+\.[0-9]+)??,M,[0-9]+\.[0-9]+,N,[0-9]+\.[0-9]+,K,[ADEN]\*\w*", gps_data) if vtg_re: return vtg_re.group(0) - else: - return "" + return "" - def read_location_GxVTG_speed(self): - vtg_data = self.read_location_GxVTG() + def read_location_GxVTG_speed(self, gps_data): + vtg_data = self.read_location_GxVTG(gps_data) if vtg_data: speed_re = ure.search(r",N,[0-9]+\.[0-9]+,K,", vtg_data) if speed_re: return speed_re.group(0)[3:-3] - return "" def read_quecIot(self): data = [] - r = self.read_location_GxRMC() + gps_data = self.read() + log.debug('read_quecIot gps_data: %s' % gps_data) + r = self.read_location_GxRMC(gps_data) if r: data.append(r) - r = self.read_location_GxGGA() + r = self.read_location_GxGGA(gps_data) if r: data.append(r) - r = self.read_location_GxVTG() + r = self.read_location_GxVTG(gps_data) if r: data.append(r) return {'gps': data} def read_aliyun(self): - gga_data = self.read_location_GxGGA() - gps_data = {'CoordinateSystem': 1} + gps_data = self.read() + gga_data = self.read_location_GxGGA(gps_data) + data = {'CoordinateSystem': 1} if gga_data: Latitude_re = ure.search(r",[0-9]+\.[0-9]+,[NS],", gga_data) if Latitude_re: - gps_data['Latitude'] = round(float(Latitude_re.group(0)[1:-3]), 2) + 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: - gps_data['Longtitude'] = round(float(Longtitude_re.group(0)[1:-3]), 2) + 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: - gps_data['Altitude'] = round(float(Altitude_re.group(0)[:-3]), 2) - gps_info = {'GeoLocation': gps_data} + data['Altitude'] = round(float(Altitude_re.group(0)[:-3]), 2) + gps_info = {'GeoLocation': data} return gps_info diff --git a/code/main.py b/code/main.py index d4bd10e..3f2e91b 100644 --- a/code/main.py +++ b/code/main.py @@ -1,5 +1,7 @@ from usr.tracker import Tracker +from usr.settings import settings +from usr.settings import default_values_sys from usr.logging import getLogger log = getLogger(__name__) @@ -10,8 +12,19 @@ PROJECT_VERSION = '2.0.0' def main(): + log.info('PROJECT_NAME: %s' % PROJECT_NAME) + log.info('PROJECT_VERSION: %s' % PROJECT_VERSION) + current_settings = settings.get() tracker = Tracker() - log.info(tracker.locator.read()) + # Start Device Check + tracker.device_check() + # Start OTA Check + if current_settings['sys']['cloud'] == default_values_sys._cloud.quecIot and \ + current_settings['app']['sw_ota'] is True: + tracker.remote.check_ota() + + # Start PowerManage + tracker.power_manage.start_rtc() if __name__ == '__main__': diff --git a/code/mpower.py b/code/mpower.py new file mode 100644 index 0000000..cab4102 --- /dev/null +++ b/code/mpower.py @@ -0,0 +1,122 @@ +import pm +import utime +import modem +import _thread + +from queue import Queue +from machine import RTC + +from usr.common import Singleton +from usr.logging import getLogger +from usr.settings import settings +from usr.settings import LOWENERGYMAP +from usr.settings import SettingsError +from usr.settings import default_values_app + +try: + from misc import USB +except ImportError: + USB = None + +log = getLogger(__name__) + + +class PowerManage(Singleton): + + def __init__(self, tracker, callback=None): + self.tracker = tracker + self.callback = callback + + self.lpm_fd = None + self.low_energy_queue = Queue(maxsize=8) + + self.period = None + self.low_energy_method = None + self.set_period() + self.get_low_energy_method() + self.low_energy_init() + + self.rtc = RTC() + self.rtc.register_callback(self.rtc_callback) + + def set_period(self, seconds=None): + if seconds is None: + current_settings = settings.get() + seconds = current_settings['app']['work_cycle_period'] + self.period = seconds + + def start_rtc(self): + log.debug('start PowerManage start_rtc') + current_settings = settings.get() + if current_settings['app']['work_mode'] == default_values_app._work_mode.intelligent: + if self.tracker.locator.gps: + gps_data = self.tracker.locator.gps.read() + speed = self.tracker.locator.gps.read_location_GxVTG_speed(gps_data) + if not speed: + return + elif float(speed) <= 0: + return + + self.set_period() + atime = utime.localtime(utime.mktime(utime.localtime()) + self.period) + alarm_time = [atime[0], atime[1], atime[2], atime[6], atime[3], atime[4], atime[5], 0] + self.rtc.set_alarm(alarm_time) + log.debug('rtc set_alarm') + self.rtc.enable_alarm(1) + + def rtc_callback(self, args): + log.debug('start rtc_callback') + self.rtc.enable_alarm(0) + if self.low_energy_method == 'PM': + self.low_energy_queue.put('wakelock_unlock') + elif self.low_energy_method == 'PSM': + pass + elif self.low_energy_method == 'POWERDOWN': + self.low_energy_queue.put('power_dwon') + + def get_low_energy_method(self): + device_model = modem.getDevModel() + support_methds = LOWENERGYMAP.get(device_model) + if not support_methds: + raise SettingsError('This Model %s Not Set LOWENERGYMAP.' % device_model) + + if self.period >= 3600: + if "POWERDOWN" in support_methds: + self.low_energy_method = "POWERDOWN" + elif "PSM" in support_methds: + self.low_energy_method = "PSM" + elif "PM" in support_methds: + self.low_energy_method = "PM" + elif 60 <= self.period < 3600: + if "PSM" in support_methds: + self.low_energy_method = "PSM" + elif "PM" in support_methds: + self.low_energy_method = "PM" + elif self.period < 60: + if "PM" in support_methds: + self.low_energy_method = "PM" + + return self.low_energy_method + + def low_energy_init(self): + if self.low_energy_method == 'POWERDOWN': + pass + elif self.low_energy_method == 'PM': + _thread.start_new_thread(self.low_energy_work, ()) + self.lpm_fd = pm.create_wakelock("tracker_lock", len("tracker_lock")) + pm.autosleep(1) + elif self.low_energy_method == 'PSM': + # TODO: PSM LOW ENERGY + pass + + def low_energy_work(self): + while True: + data = self.low_energy_queue.get() + if data: + if self.lpm_fd is None: + self.lpm_fd = pm.create_wakelock("tracker_lock", len("tracker_lock")) + pm.autosleep(1) + pm.wakelock_lock(self.lpm_fd) + + over_speed_check_res = self.tracker.get_over_speed_check() + self.tracker.device_data_report(event_data=over_speed_check_res, msg=data) diff --git a/code/quecthing.py b/code/quecthing.py index c353fc5..9e6eed8 100644 --- a/code/quecthing.py +++ b/code/quecthing.py @@ -113,6 +113,7 @@ class QuecThing(object): break self.rm_empty_data(data) + log.info('post_data res: %s' % res) return res def eventCB(self, data): diff --git a/code/remote.py b/code/remote.py index 29ea12c..76b80f0 100644 --- a/code/remote.py +++ b/code/remote.py @@ -50,7 +50,7 @@ class Controller(Singleton): if flag is True: self.tracker.device_data_report() elif flag is False: - self.tracker.device_data_report(power_switch=False, callback='power_down') + self.tracker.device_data_report(power_switch=False, msg='power_down') else: raise ControllerError('Controller switch permission error %s.' % perm) @@ -180,12 +180,13 @@ def uplink_process(argv): while True: # Put all data in uplink_queue to hist-dictionary. if self.uplink_queue.size(): data = self.uplink_queue.get() - if data[1]: - if hist.get('hist_data') is None: - hist['hist_data'] = [] - hist['hist_data'].append(data[1]) - need_refresh = True - sys_bus.publish(data[0], 'false') + if data: + if data[1]: + if hist.get('hist_data') is None: + hist['hist_data'] = [] + hist['hist_data'].append(data[1]) + need_refresh = True + sys_bus.publish(data[0], 'false') else: break finally: @@ -208,7 +209,7 @@ def uplink_process(argv): if data: if data[1]: if not self.cloud.post_data(data[1]): - self.add_history(data) + self.add_history(data[1]) sys_bus.publish(data[0], 'false') else: sys_bus.publish(data[0], 'true') diff --git a/code/settings.py b/code/settings.py index 0c34a56..d89a937 100644 --- a/code/settings.py +++ b/code/settings.py @@ -42,6 +42,23 @@ DRIVE_BEHAVIOR_CODE = { 40004: 'quick_turn_right', } +LOWENERGYMAP = { + "EC200U": [ + "POWERDOWN", + "PM", + ], + "EC200U": [ + "POWERDOWN", + "PM", + ], + "EC600N": [ + "PM", + ], + "EC800G": [ + "PM" + ], +} + tracker_settings_file = '/usr/tracker_settings.json' _settings_lock = _thread.allocate_lock() @@ -89,7 +106,6 @@ class default_values_app(object): none = 0x0 cycle = 0x1 intelligent = 0x2 - lowenergy = 0x3 class _drive_behavior(object): suddenly_start = 0 @@ -105,9 +121,9 @@ class default_values_app(object): loc_method = _loc_method.gps - work_mode = _work_mode.lowenergy + work_mode = _work_mode.cycle - work_cycle_period = 10 + work_cycle_period = 60 low_power_alert_threshold = 20 @@ -325,7 +341,7 @@ class Settings(Singleton): elif opt == 'work_mode': if not isinstance(val, int): return False - if val > default_values_app._work_mode.lowenergy: + if val > default_values_app._work_mode.intelligent: return False self.current_settings['app'][opt] = val return True diff --git a/code/test_tracker.py b/code/test_tracker.py index d6083ba..147b669 100644 --- a/code/test_tracker.py +++ b/code/test_tracker.py @@ -4,7 +4,9 @@ import utime import _thread from queue import Queue +from machine import RTC from machine import UART +# from misc import Power import usr.settings as settings @@ -102,16 +104,20 @@ def test_tracker(): log.info('[.] sleep 3') utime.sleep(3) - log.info('[.] test tracker.device_check()') - device_check_res = tracker.device_check() - log.info('[.] device_check_res:', device_check_res) + # log.info('[.] test tracker.device_data_report()') + # device_data_report_res = tracker.device_data_report() + # log.info('[.] device_data_report_res:', device_data_report_res) # log.info('[.] sleep 3') # utime.sleep(3) - # log.info('[.] test tracker.loc_report()') - # loc_report_res = tracker.loc_report() - # log.info('[.] loc_report_res:', loc_report_res) + log.info('[.] test tracker.power_manage.start_rtc()') + tracker.power_manage.start_rtc() + log.info('[.] end tracker.power_manage.start_rtc()') + + # log.info('[.] test tracker.device_check()') + # device_check_res = tracker.device_check() + # log.info('[.] device_check_res:', device_check_res) # log.info('[.] test tracker.remote.check_ota()') # tracker.remote.check_ota() @@ -200,6 +206,31 @@ def test_pm(): pm.delete_wakelock(lpm_fd) +def test_rtc(): + rtc_queue = Queue(maxsize=8) + + def rtc_cb(df): + global rtc_queue + print('rtc call back test. [%s]' % df) + rtc_queue.put('rtc') + + rtc = RTC() + log.debug('rtc.datatime: %s' % str(rtc.datetime())) + rtc.register_callback(rtc_cb) + + atime = utime.localtime(utime.mktime(utime.localtime()) + 10) + alarm_time = (atime[0], atime[1], atime[2], 0, atime[3], atime[4], atime[5], 0) + log.debug('rtc.set_alarm alarm_time: %s' % str(alarm_time)) + rtc.set_alarm(alarm_time) + log.debug('rtc.enable_alarm') + rtc.enable_alarm(1) + rtc_data = rtc_queue.get() + log.debug('rtc_data: %s' % rtc_data) + + # log.debug('Power.powerDown') + # Power.powerDown() + + def main(): # test_quecthing() # test_settings() @@ -210,6 +241,7 @@ def main(): # test_aliyuniot() test_tracker() # test_pm() + # test_rtc() if __name__ == '__main__': main() diff --git a/code/timer.py b/code/timer.py index 87465d0..6263502 100644 --- a/code/timer.py +++ b/code/timer.py @@ -47,29 +47,17 @@ class TrackerTimer(Singleton): self.gnss_count = 0 self.gnss_timer() - if current_settings['app']['sw_ota'] is False: - self.quec_ota = 0 - if current_settings['sys']['cloud'] == settings.default_values_sys._cloud.quecIot and \ - self.quec_ota >= 3600: - self.quec_ota = 0 - self.quecthing_ota_timer() - def loc_timer(self): current_settings = settings.settings.get() if current_settings['app']['work_mode'] == settings.default_values_app._work_mode.intelligent: - if not self.tracker.locator.gps: + if self.tracker.locator.gps: if not self.tracker.locator.gps.read_location_GxVTG_speed(): return elif float(self.tracker.locator.gps.read_location_GxVTG_speed()) <= 0: return else: return - elif current_settings['app']['work_mode'] == settings.default_values_app._work_mode.lowenergy: - self.tracker.low_energy_queue.put(True) - return - - over_speed_check_res = self.tracker.get_over_speed_check() - self.tracker.device_data_report(event_data=over_speed_check_res) + self.tracker.low_energy_queue.put(True) def battery_timer(self): current_settings = settings.settings.get() @@ -82,16 +70,13 @@ class TrackerTimer(Singleton): alert_data = self.tracker.get_alert_data(30002, {'local_time': utime.mktime(utime.localtime())}) self.tracker.device_data_report(event_data=alert_data) if energy <= current_settings['app']['low_power_shutdown_threshold']: - self.tracker.device_data_report(power_switch=False, callback='power_down') + self.tracker.device_data_report(power_switch=False, msg='power_down') elif is_charge == 1: self.tracker.energy_led_show(energy) def gnss_timer(self): self.tracker.locator.gps.quecgnss_read() - def quecthing_ota_timer(self): - self.tracker.remote.check_ota() - class LEDTimer(Singleton): def __init__(self, tracker): diff --git a/code/tracker.py b/code/tracker.py index 35d6a69..cb9331e 100644 --- a/code/tracker.py +++ b/code/tracker.py @@ -6,7 +6,6 @@ import checkNet import dataCall from misc import Power -from queue import Queue import usr.settings as settings @@ -16,9 +15,11 @@ from usr.remote import Remote from usr.battery import Battery from usr.common import numiter from usr.common import Singleton +from usr.mpower import PowerManage from usr.logging import getLogger from usr.location import Location, GPS -from usr.timer import TrackerTimer, LEDTimer +# from usr.timer import TrackerTimer +from usr.timer import LEDTimer try: from misc import USB @@ -42,17 +43,14 @@ class Tracker(Singleton): self.locator = Location() self.battery = Battery() self.remote = Remote(self) + self.power_manage = PowerManage(self) - self.tracker_timer = TrackerTimer(self) + # self.tracker_timer = TrackerTimer(self) self.led_timer = LEDTimer(self) - self.low_energy_queue = Queue(maxsize=8) self.num_iter = numiter() self.num_lock = _thread.allocate_lock() - self.lpm_fd = None - _thread.start_new_thread(self.low_energy_work, ()) - if PowerKey is not None: self.power_key = PowerKey() self.power_key.powerKeyEventRegister(self.pwk_callback) @@ -76,22 +74,29 @@ class Tracker(Singleton): return alert_data def get_device_data(self, power_switch=True): + log.debug('start get_device_data') device_data = {} loc_info = self.locator.read() + log.debug('loc_info: %s' % str(loc_info)) if loc_info: device_data.update(loc_info[1]) - # TODO: Other Machine Info. current_settings = settings.settings.get() + + energy = self.battery.energy() + if energy <= current_settings['app']['low_power_alert_threshold']: + alert_data = self.get_alert_data(30002, {'local_time': utime.mktime(utime.localtime())}) + device_data.update(alert_data) + + # TODO: Other Machine Info. device_data.update({ 'power_switch': power_switch, - 'energy': self.battery.energy(), + 'energy': energy, 'local_time': utime.mktime(utime.localtime()), 'ota_status': current_settings['sys']['ota_status'], }) device_data.update(current_settings['app']) - return device_data def get_device_check(self): @@ -126,12 +131,11 @@ class Tracker(Singleton): def get_over_speed_check(self): alert_data = {} - - if self.locator.gps: - speed = self.locator.gps.read_location_GxVTG_speed() - if speed: - current_settings = settings.settings.get() - if float(speed) > current_settings['app']['over_speed_threshold']: + current_settings = settings.settings.get() + if current_settings['app']['work_mode'] == settings.default_values_app._work_mode.intelligent: + if self.locator.gps: + speed = self.locator.gps.read_location_GxVTG_speed() + if speed and float(speed) >= current_settings['app']['over_speed_threshold']: alert_code = 30003 alert_info = {'local_time': utime.mktime(utime.localtime())} alert_data = self.get_alert_data(alert_code, alert_info) @@ -149,25 +153,31 @@ class Tracker(Singleton): return str(num) def data_report_cb(self, topic, msg): - if topic.startswith('wakelock_unlock'): - pm.wakelock_unlock(self.lpm_fd) - elif topic.startswith('power_down'): + sys_bus.unsubscribe(topic) + + if topic.endswith('/wakelock_unlock'): + pm.wakelock_unlock(self.power_manage.lpm_fd) + elif topic.endswith('/power_down'): self.energy_led.period = None self.energy_led.switch(0) self.running_led.period = None self.running_led.switch(0) Power.powerDown() - sys_bus.unsubscribe(topic) + if self.power_manage.callback: + self.power_manage.callback() + self.power_manage.start_rtc() - def device_data_report(self, power_switch=True, event_data={}, callback=''): + def device_data_report(self, power_switch=True, event_data={}, msg=''): + log.debug('start device_data_report') device_data = self.get_device_data(power_switch) if event_data: device_data.update(event_data) num = self.get_num() - topic = callback + '_' + num if callback else num + topic = num + '/' + msg if msg else num sys_bus.subscribe(topic, self.data_report_cb) + log.debug("topic: %s, device_data: %s" % (topic, device_data)) self.remote.post_data(topic, device_data) def device_check(self): @@ -210,30 +220,15 @@ class Tracker(Singleton): def nw_callback(self, args): net_check_res = self.check.net_check() if args[1] != 1: + # TODO: Check Internet disconected then do something if net_check_res[0] == 0 or (net_check_res[0] == 1 and net_check_res[1] == 0): alert_code = 30004 alert_info = {'local_time': utime.mktime(utime.localtime())} alert_data = self.get_alert_data(alert_code, alert_info) self.device_data_report(event_data=alert_data) - - def low_energy_work(self): - while True: - data = self.low_energy_queue.get() - if data: - current_settings = settings.settings.get() - if current_settings['app']['work_mode'] == settings.default_values_app._work_mode.lowenergy: - if self.lpm_fd is None: - self.lpm_fd = pm.create_wakelock("tracker_lock", len("tracker_lock")) - pm.autosleep(1) - pm.wakelock_lock(self.lpm_fd) - over_speed_check_res = self.get_over_speed_check() - - self.device_data_report(event_data=over_speed_check_res, callback='wakelock_unlock') - else: - if self.lpm_fd is not None: - pm.autosleep(0) - pm.delete_wakelock(self.lpm_fd) - self.lpm_fd = None + else: + # TODO: Check Internet conected then do something + pass class SelfCheck(object):