2022-03-24 16:01:12 +08:00
|
|
|
# Copyright (c) Quectel Wireless Solution, Co., Ltd.All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
|
2022-03-31 13:41:08 +08:00
|
|
|
import uos
|
2022-03-26 19:09:18 +08:00
|
|
|
import utime
|
2022-03-17 16:44:47 +08:00
|
|
|
import osTimer
|
2022-03-03 09:53:51 +08:00
|
|
|
import quecIot
|
2022-03-31 13:41:08 +08:00
|
|
|
import uhashlib
|
|
|
|
import ubinascii
|
|
|
|
import uzlib
|
|
|
|
import ql_fs
|
|
|
|
import app_fota_download
|
2022-03-18 17:53:46 +08:00
|
|
|
|
2022-03-17 16:44:47 +08:00
|
|
|
from queue import Queue
|
2022-03-18 17:53:46 +08:00
|
|
|
|
2022-03-03 09:53:51 +08:00
|
|
|
from usr.logging import getLogger
|
2022-03-17 16:44:47 +08:00
|
|
|
from usr.settings import settings
|
2022-03-03 09:53:51 +08:00
|
|
|
|
2022-03-04 13:21:48 +08:00
|
|
|
log = getLogger(__name__)
|
|
|
|
|
2022-03-04 17:09:04 +08:00
|
|
|
object_model = [
|
2022-03-18 17:53:46 +08:00
|
|
|
# property
|
2022-03-07 16:46:44 +08:00
|
|
|
(9, ('power_switch', 'rw')),
|
2022-03-07 14:47:10 +08:00
|
|
|
(4, ('energy', 'r')),
|
|
|
|
(23, ('phone_num', 'rw')),
|
|
|
|
(24, ('loc_method', 'rw')),
|
2022-03-21 19:40:33 +08:00
|
|
|
(25, ('work_mode', 'rw')),
|
|
|
|
(26, ('work_cycle_period', 'rw')),
|
2022-03-07 14:47:10 +08:00
|
|
|
(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')),
|
2022-03-25 11:56:14 +08:00
|
|
|
(30, ('sw_sim_abnormal_alert', 'rw')),
|
2022-03-07 14:47:10 +08:00
|
|
|
(31, ('sw_disassemble_alert', 'rw')),
|
|
|
|
(32, ('sw_drive_behavior_alert', 'rw')),
|
|
|
|
(21, ('drive_behavior_code', 'r')),
|
2022-03-09 09:51:40 +08:00
|
|
|
(33, ('power_restart', 'w')),
|
|
|
|
(34, ('over_speed_threshold', 'rw')),
|
2022-03-28 20:29:01 +08:00
|
|
|
(36, ('device_module_status', 'r')),
|
2022-03-11 17:18:18 +08:00
|
|
|
(37, ('gps_mode', 'r')),
|
2022-03-16 11:38:50 +08:00
|
|
|
(38, ('user_ota_action', 'w')),
|
|
|
|
(39, ('ota_status', 'r')),
|
2022-03-29 13:24:17 +08:00
|
|
|
(41, ('voltage', 'r')),
|
2022-03-18 17:53:46 +08:00
|
|
|
|
|
|
|
# event
|
|
|
|
(6, ('sos_alert', 'r')),
|
|
|
|
(14, ('fault_alert', 'r')),
|
|
|
|
(17, ('low_power_alert', 'r')),
|
2022-03-25 11:56:14 +08:00
|
|
|
(18, ('sim_abnormal_alert', 'r')),
|
2022-03-18 17:53:46 +08:00
|
|
|
(20, ('disassemble_alert', 'r')),
|
|
|
|
(22, ('drive_behavior_alert', 'r')),
|
|
|
|
(35, ('over_speed_alert', 'r')),
|
2022-03-04 17:09:04 +08:00
|
|
|
]
|
2022-03-03 09:53:51 +08:00
|
|
|
|
2022-03-28 20:29:01 +08:00
|
|
|
object_model_struct = {
|
|
|
|
'device_module_status': {
|
2022-03-29 17:11:32 +08:00
|
|
|
'net': 1,
|
|
|
|
'location': 2,
|
|
|
|
'temp_sensor': 3,
|
|
|
|
'light_sensor': 4,
|
|
|
|
'move_sensor': 5,
|
|
|
|
'mike': 6,
|
2022-03-29 13:24:17 +08:00
|
|
|
},
|
|
|
|
'loc_method': {
|
|
|
|
'gps': 1,
|
|
|
|
'cell': 2,
|
|
|
|
'wifi': 3,
|
2022-03-28 20:29:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-08 17:12:38 +08:00
|
|
|
object_model_code = {i[1][0]: i[0] for i in object_model}
|
|
|
|
|
2022-03-04 19:29:23 +08:00
|
|
|
|
2022-03-03 09:53:51 +08:00
|
|
|
class QuecThing(object):
|
2022-03-04 13:21:48 +08:00
|
|
|
def __init__(self, pk, ps, dk, ds, downlink_queue):
|
2022-03-31 13:41:08 +08:00
|
|
|
self.pk = pk
|
|
|
|
self.ps = ps
|
|
|
|
self.dk = dk
|
|
|
|
self.ds = ds
|
|
|
|
self.init_res = {}
|
|
|
|
self.fileSize = 0
|
|
|
|
self.needDownloadSize = 0
|
|
|
|
self.crcValue = 0
|
|
|
|
self.downloadSize = 0
|
|
|
|
self.fileFp = 0
|
|
|
|
self.startAddr = 0
|
2022-03-03 09:53:51 +08:00
|
|
|
self.downlink_queue = downlink_queue
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue = Queue(maxsize=16)
|
|
|
|
self.quec_timer = osTimer()
|
2022-03-31 13:41:08 +08:00
|
|
|
self.queciot_init()
|
|
|
|
|
|
|
|
fileClear = OTAFileClear()
|
|
|
|
fileClear.file_clear()
|
|
|
|
|
|
|
|
def queciot_init(self):
|
|
|
|
if quecIot.getWorkState() == 8 and quecIot.getConnmode() == 1:
|
|
|
|
return
|
2022-03-16 11:38:50 +08:00
|
|
|
|
2022-03-17 13:25:59 +08:00
|
|
|
quecIot.init()
|
2022-03-03 09:53:51 +08:00
|
|
|
quecIot.setEventCB(self.eventCB)
|
2022-03-31 13:41:08 +08:00
|
|
|
quecIot.setProductinfo(self.pk, self.ps)
|
|
|
|
quecIot.setDkDs(self.dk, self.ds)
|
2022-03-03 09:53:51 +08:00
|
|
|
quecIot.setServer(1, "iot-south.quectel.com:2883")
|
|
|
|
quecIot.setConnmode(1)
|
2022-03-31 13:41:08 +08:00
|
|
|
|
|
|
|
count = 0
|
|
|
|
while quecIot.getWorkState() != 8 and count < 10:
|
|
|
|
if self.init_res.get('subscription') is not None:
|
|
|
|
self.init_res.pop('subscription')
|
|
|
|
break
|
|
|
|
utime.sleep_ms(200)
|
|
|
|
|
|
|
|
if not self.ds and self.dk:
|
2022-03-26 19:09:18 +08:00
|
|
|
count = 0
|
|
|
|
while count < 3:
|
|
|
|
ndk, nds = quecIot.getDkDs()
|
|
|
|
if nds:
|
|
|
|
break
|
|
|
|
count += 1
|
|
|
|
utime.sleep(count)
|
|
|
|
current_settings = settings.get()
|
|
|
|
cloud_init_params = current_settings['sys']['cloud_init_params']
|
|
|
|
cloud_init_params['DS'] = nds
|
2022-03-31 13:41:08 +08:00
|
|
|
self.dk = ndk
|
|
|
|
self.ds = nds
|
2022-03-26 19:09:18 +08:00
|
|
|
settings.set('cloud_init_params', cloud_init_params)
|
|
|
|
settings.save()
|
2022-03-03 09:53:51 +08:00
|
|
|
|
2022-03-17 17:43:52 +08:00
|
|
|
def get_post_res(self):
|
2022-03-17 16:44:47 +08:00
|
|
|
current_settings = settings.get()
|
2022-03-25 18:42:11 +08:00
|
|
|
self.quec_timer.start(current_settings['sys']['checknet_timeout'] * 1000, 1, self.quec_timer_cb)
|
2022-03-17 17:43:52 +08:00
|
|
|
res = self.post_result_wait_queue.get()
|
|
|
|
self.quec_timer.stop()
|
|
|
|
return res
|
2022-03-17 16:44:47 +08:00
|
|
|
|
2022-03-25 18:42:11 +08:00
|
|
|
def quec_timer_cb(self, args):
|
|
|
|
# Power.powerRestart()
|
|
|
|
self.post_result_wait_queue.put(False)
|
|
|
|
|
2022-03-04 17:09:04 +08:00
|
|
|
@staticmethod
|
|
|
|
def rm_empty_data(data):
|
|
|
|
for k, v in data.items():
|
|
|
|
if not v:
|
|
|
|
del data[k]
|
|
|
|
|
2022-03-23 14:21:45 +08:00
|
|
|
def post_data(self, data):
|
2022-03-31 13:41:08 +08:00
|
|
|
self.queciot_init()
|
2022-03-23 14:21:45 +08:00
|
|
|
res = True
|
2022-03-29 17:11:32 +08:00
|
|
|
# log.debug('post_data: %s' % str(data))
|
2022-03-23 14:21:45 +08:00
|
|
|
for k, v in data.items():
|
|
|
|
if object_model_code.get(k) is not None:
|
|
|
|
# Event Data Format From object_mode_code
|
2022-03-28 20:29:01 +08:00
|
|
|
if v is not None:
|
2022-03-08 17:12:38 +08:00
|
|
|
if isinstance(v, dict):
|
2022-03-28 20:29:01 +08:00
|
|
|
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
|
2022-03-29 17:11:32 +08:00
|
|
|
# log.debug('k: %s, v: %s' % (k, v))
|
2022-03-17 13:25:59 +08:00
|
|
|
phymodelReport_res = quecIot.phymodelReport(1, {object_model_code.get(k): v})
|
2022-03-23 14:21:45 +08:00
|
|
|
if not phymodelReport_res:
|
|
|
|
res = False
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
elif k == 'gps':
|
|
|
|
locReportOutside_res = quecIot.locReportOutside(v)
|
|
|
|
if not locReportOutside_res:
|
|
|
|
res = False
|
|
|
|
break
|
|
|
|
elif k == 'non_gps':
|
|
|
|
locReportInside_res = quecIot.locReportInside(v)
|
|
|
|
if not locReportInside_res:
|
|
|
|
res = False
|
|
|
|
break
|
2022-03-04 17:09:04 +08:00
|
|
|
else:
|
2022-03-23 14:21:45 +08:00
|
|
|
v = {}
|
|
|
|
continue
|
|
|
|
|
|
|
|
res = self.get_post_res()
|
|
|
|
if res:
|
|
|
|
v = {}
|
2022-03-04 17:09:04 +08:00
|
|
|
else:
|
2022-03-23 14:21:45 +08:00
|
|
|
res = False
|
|
|
|
break
|
|
|
|
|
|
|
|
self.rm_empty_data(data)
|
|
|
|
return res
|
2022-03-03 09:53:51 +08:00
|
|
|
|
|
|
|
def eventCB(self, data):
|
2022-03-29 13:24:17 +08:00
|
|
|
log.info("event: %s" % str(data))
|
2022-03-03 09:53:51 +08:00
|
|
|
event = data[0]
|
|
|
|
errcode = data[1]
|
|
|
|
if len(data) > 2:
|
|
|
|
data = data[2]
|
|
|
|
|
|
|
|
if event == 1:
|
|
|
|
if errcode == 10200:
|
|
|
|
log.info('Device authentication succeeded.')
|
|
|
|
elif errcode == 10422:
|
2022-03-14 11:37:29 +08:00
|
|
|
log.error('Device has been authenticated (connect failed).')
|
2022-03-03 09:53:51 +08:00
|
|
|
elif event == 2:
|
|
|
|
if errcode == 10200:
|
|
|
|
log.info('Access succeeded.')
|
2022-03-31 13:41:08 +08:00
|
|
|
self.init_res['access'] = True
|
2022-03-14 11:37:29 +08:00
|
|
|
if errcode == 10450:
|
|
|
|
log.error('Device internal error (connect failed).')
|
2022-03-31 13:41:08 +08:00
|
|
|
self.init_res['access'] = False
|
2022-03-03 09:53:51 +08:00
|
|
|
elif event == 3:
|
|
|
|
if errcode == 10200:
|
|
|
|
log.info('Subscription succeeded.')
|
2022-03-31 13:41:08 +08:00
|
|
|
self.init_res['subscription'] = True
|
|
|
|
quecIot.otaRequest(0)
|
|
|
|
if data != (3, 10200):
|
|
|
|
ota_info = data.decode()
|
|
|
|
file_info = ota_info.split(',')
|
|
|
|
log.info(
|
|
|
|
"OTA File Info: componentNo: %s, sourceVersion: %s, targetVersion: %s, "
|
|
|
|
"batteryLimit: %s, minSignalIntensity: %s, minSignalIntensity: %s" % tuple(file_info)
|
|
|
|
)
|
|
|
|
if errcode == 10300:
|
|
|
|
log.info('Subscription failed.')
|
|
|
|
self.init_res['subscription'] = False
|
2022-03-03 09:53:51 +08:00
|
|
|
elif event == 4:
|
|
|
|
if errcode == 10200:
|
|
|
|
log.info('Data sending succeeded.')
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue.put(True)
|
2022-03-03 09:53:51 +08:00
|
|
|
elif errcode == 10210:
|
|
|
|
log.info('Object model data sending succeeded.')
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue.put(True)
|
2022-03-03 09:53:51 +08:00
|
|
|
elif errcode == 10220:
|
|
|
|
log.info('Location data sending succeeded.')
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue.put(True)
|
2022-03-03 09:53:51 +08:00
|
|
|
elif errcode == 10300:
|
|
|
|
log.info('Data sending failed.')
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue.put(False)
|
2022-03-03 09:53:51 +08:00
|
|
|
elif errcode == 10310:
|
2022-03-14 11:37:29 +08:00
|
|
|
log.error('Object model data sending failed.')
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue.put(False)
|
2022-03-03 09:53:51 +08:00
|
|
|
elif errcode == 10320:
|
2022-03-14 11:37:29 +08:00
|
|
|
log.error('Location data sending failed.')
|
2022-03-17 16:44:47 +08:00
|
|
|
self.post_result_wait_queue.put(False)
|
2022-03-03 09:53:51 +08:00
|
|
|
elif event == 5:
|
|
|
|
if errcode == 10200:
|
|
|
|
log.info('Recving raw data.')
|
|
|
|
log.info(data)
|
2022-03-06 17:15:19 +08:00
|
|
|
# TODO: To Check data format.
|
2022-03-06 17:24:49 +08:00
|
|
|
self.downlink_queue.put(('raw_data', data))
|
2022-03-03 09:53:51 +08:00
|
|
|
if errcode == 10210:
|
|
|
|
log.info('Recving object model data.')
|
2022-03-07 14:47:10 +08:00
|
|
|
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))
|
2022-03-03 09:53:51 +08:00
|
|
|
elif errcode == 10211:
|
|
|
|
log.info('Recving object model query command.')
|
2022-03-06 17:15:19 +08:00
|
|
|
# TODO: Check pkgId for other uses.
|
|
|
|
# log.info('pkgId: %s' % data[0])
|
|
|
|
object_model_ids = data[1]
|
2022-03-07 14:47:10 +08:00
|
|
|
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))
|
2022-03-03 09:53:51 +08:00
|
|
|
elif event == 6:
|
|
|
|
if errcode == 10200:
|
|
|
|
log.info('Logout succeeded.')
|
|
|
|
elif event == 7:
|
|
|
|
if errcode == 10700:
|
|
|
|
log.info('New OTA plain.')
|
2022-03-31 13:41:08 +08:00
|
|
|
ota_info = data.decode()
|
|
|
|
file_info = ota_info.split(',')
|
|
|
|
log.info(
|
|
|
|
"OTA File Info: componentNo: %s, sourceVersion: %s, targetVersion: %s, "
|
|
|
|
"batteryLimit: %s, minSignalIntensity: %s, useSpace: %s" % tuple(file_info)
|
|
|
|
)
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('ota_plain', data))
|
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 1)]))
|
2022-03-16 11:38:50 +08:00
|
|
|
elif errcode == 10701:
|
|
|
|
log.info('The module starts to download.')
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 2)]))
|
2022-03-31 13:41:08 +08:00
|
|
|
if data != (7, 10701):
|
|
|
|
ota_info = data.decode()
|
|
|
|
file_info = ota_info.split(',')
|
|
|
|
self.sota_download_info(int(file_info[1]), file_info[2], int(file_info[3]))
|
2022-03-16 11:38:50 +08:00
|
|
|
elif errcode == 10702:
|
|
|
|
log.info('Package download.')
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 2)]))
|
2022-03-16 11:38:50 +08:00
|
|
|
elif errcode == 10703:
|
|
|
|
log.info('Package download complete.')
|
2022-03-31 13:41:08 +08:00
|
|
|
if data != (7, 10703):
|
|
|
|
ota_info = data.decode()
|
|
|
|
file_info = ota_info.split(',')
|
|
|
|
log.info("OTA File Info: componentNo: %s, length: %s, md5: %s, crc: %s" % tuple(file_info))
|
|
|
|
self.sota_download_success(file_info[2], file_info[3])
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 2)]))
|
2022-03-16 11:38:50 +08:00
|
|
|
elif errcode == 10704:
|
|
|
|
log.info('Package updating.')
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 2)]))
|
2022-03-16 11:38:50 +08:00
|
|
|
elif errcode == 10705:
|
|
|
|
log.info('Firmware update complete.')
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 3)]))
|
2022-03-16 11:38:50 +08:00
|
|
|
elif errcode == 10706:
|
|
|
|
log.info('Failed to update firmware.')
|
2022-03-22 20:19:27 +08:00
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 4)]))
|
2022-03-31 13:41:08 +08:00
|
|
|
elif errcode == 10707:
|
|
|
|
log.info('Received confirmation broadcast.')
|
2022-03-16 11:38:50 +08:00
|
|
|
|
|
|
|
def dev_info_report(self):
|
|
|
|
quecIot.devInfoReport([i for i in range(1, 13)])
|
|
|
|
|
|
|
|
def ota_action(self, val=1):
|
|
|
|
quecIot.otaAction(val)
|
2022-03-31 13:41:08 +08:00
|
|
|
|
|
|
|
def sota_download_info(self, size, md5_value, crc):
|
|
|
|
self.file_size = size
|
|
|
|
self.crc_value = crc
|
|
|
|
self.download_size = 0
|
|
|
|
self.update_mode = UpdateCtx()
|
|
|
|
self.md5_value = md5_value
|
|
|
|
|
|
|
|
def read_sota_file(self):
|
|
|
|
while self.need_download_size != 0:
|
|
|
|
readsize = 4096
|
|
|
|
if (readsize > self.need_download_size):
|
|
|
|
readsize = self.need_download_size
|
|
|
|
updateFile = quecIot.mcuFWDataRead(self.start_addr, readsize)
|
|
|
|
self.update_mode.write_update_data(updateFile)
|
|
|
|
log.debug("Download File Size: %s" % readsize)
|
|
|
|
self.need_download_size -= readsize
|
|
|
|
self.start_addr += readsize
|
|
|
|
self.download_size += readsize
|
|
|
|
if (self.download_size == self.file_size):
|
|
|
|
log.debug("File Download Success, Update Start.")
|
|
|
|
quecIot.otaAction(3)
|
|
|
|
file_update_res = self.update_mode.file_update(self.md5_value)
|
|
|
|
if file_update_res:
|
|
|
|
log.debug("File Update Success, Power Restart.")
|
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 3)]))
|
|
|
|
self.downlink_queue.put(('object_model', [('power_restart', 1)]))
|
|
|
|
else:
|
|
|
|
log.debug("File Update Failed.")
|
|
|
|
self.downlink_queue.put(('object_model', [('ota_status', 4)]))
|
|
|
|
else:
|
|
|
|
quecIot.otaAction(2)
|
|
|
|
|
|
|
|
def sota_download_success(self, start, down_loaded_size):
|
|
|
|
self.need_download_size = down_loaded_size
|
|
|
|
self.start_addr = start
|
|
|
|
self.read_sota_file()
|
|
|
|
|
|
|
|
|
|
|
|
class UpdateCtx(object):
|
|
|
|
def __init__(self, parent_dir="/usr/.updater/usr/"):
|
|
|
|
self.fp = open("/usr/sotaFile.tar.gz", "wb+")
|
|
|
|
self.file_list = []
|
|
|
|
self.parent_dir = parent_dir
|
|
|
|
self.unzipFp = 0
|
|
|
|
self.hash_obj = uhashlib.md5()
|
|
|
|
|
|
|
|
def write_update_data(self, data):
|
|
|
|
self.fp.write(data)
|
|
|
|
self.hash_obj.update(data)
|
|
|
|
|
|
|
|
def __get_file_size(self, data):
|
|
|
|
size = data.decode('ascii')
|
|
|
|
size = size.rstrip('\0')
|
|
|
|
if (len(size) == 0):
|
|
|
|
return 0
|
|
|
|
size = int(size, 8)
|
|
|
|
return size
|
|
|
|
|
|
|
|
def __get_file_name(self, name):
|
|
|
|
fileName = name.decode('ascii')
|
|
|
|
fileName = fileName.rstrip('\0')
|
|
|
|
return fileName
|
|
|
|
|
|
|
|
def file_update(self, md5_value):
|
|
|
|
md5Data = ubinascii.hexlify(self.hash_obj.digest())
|
|
|
|
md5Data = md5Data.decode('ascii')
|
|
|
|
md5Value = eval(md5_value)
|
|
|
|
log.debug("DMP Calc MD5 Value: %s, Device Calc MD5 Value: %s" % (md5Value, md5Data))
|
|
|
|
if (md5Value != md5Data):
|
|
|
|
log.error("MD5 Verification Failed")
|
|
|
|
return
|
|
|
|
|
|
|
|
log.debug("MD5 Verification Success.")
|
|
|
|
self.fp.seek(10)
|
|
|
|
self.unzipFp = uzlib.DecompIO(self.fp, -15)
|
|
|
|
log.debug('Unzip File Success.')
|
|
|
|
ql_fs.mkdirs(self.parent_dir)
|
|
|
|
try:
|
|
|
|
while True:
|
|
|
|
data = self.unzipFp.read(0x200)
|
|
|
|
if not data:
|
|
|
|
log.debug("Read File Size Zore.")
|
|
|
|
break
|
|
|
|
size = self.__get_file_size(data[124:135])
|
|
|
|
fileName = self.__get_file_name(data[:100])
|
|
|
|
log.debug("File Name: %s, File Size: %s" % (fileName, size))
|
|
|
|
if not size:
|
|
|
|
if len(fileName):
|
|
|
|
log.debug("Create File Dir: %s" % self.parent_dir + fileName)
|
|
|
|
ql_fs.mkdirs(self.parent_dir + fileName)
|
|
|
|
else:
|
|
|
|
log.debug("Have No File Unzip.")
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
log.debug("File %s Write Size %s" % (self.parent_dir + fileName, size))
|
|
|
|
fp = open(self.parent_dir + fileName, "wb+")
|
|
|
|
fileSize = size
|
|
|
|
while fileSize:
|
|
|
|
data = self.unzipFp.read(0x200)
|
|
|
|
if (fileSize < 0x200):
|
|
|
|
fp.write(data[:fileSize])
|
|
|
|
fileSize = 0
|
|
|
|
fp.close()
|
|
|
|
self.file_list.append({"fileName": "/usr/" + fileName, "size": size})
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
fileSize -= 0x200
|
|
|
|
fp.write(data)
|
|
|
|
|
|
|
|
for fileName in self.file_list:
|
|
|
|
app_fota_download.update_download_stat("/usr/.updater" + fileName["fileName"], fileName["fileName"], fileName["size"])
|
|
|
|
app_fota_download.set_update_flag()
|
|
|
|
self.fp.close()
|
|
|
|
log.debug("Remove /usr/sotaFile.tar.gz")
|
|
|
|
uos.remove("/usr/sotaFile.tar.gz")
|
|
|
|
except Exception as e:
|
|
|
|
log.error("Unpack Error: %s" % e)
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
class OTAFileClear(object):
|
|
|
|
def __init__(self):
|
|
|
|
self.usrList = uos.ilistdir("/usr/")
|
|
|
|
|
|
|
|
def __remove_updater_dir(self, path):
|
|
|
|
dirList = uos.ilistdir(path)
|
|
|
|
for fileInfo in dirList:
|
|
|
|
if fileInfo[1] == 0x4000:
|
|
|
|
self.__remove_updater_dir("%s/%s" % (path, fileInfo[0]))
|
|
|
|
else:
|
|
|
|
log.debug("remove file name: %s/%s" % (path, fileInfo[0]))
|
|
|
|
uos.remove("%s/%s" % (path, fileInfo[0]))
|
|
|
|
|
|
|
|
log.debug("remove dir name: %s" % path)
|
|
|
|
uos.remove(path)
|
|
|
|
|
|
|
|
def file_clear(self):
|
|
|
|
for fileInfo in self.usrList:
|
|
|
|
if fileInfo[0] == ".updater":
|
|
|
|
self.__remove_updater_dir("/usr/.updater")
|
|
|
|
elif fileInfo[0] == "sotaFile.tar.gz":
|
|
|
|
log.debug("remove update file sotaFile.tar.gz")
|
|
|
|
uos.remove("/usr/sotaFile.tar.gz")
|