# -*- coding: utf-8 -*- # !/usr/bin/env python import getopt import time import uuid import requests import sys import os PROJECT_ROOT = os.path.join(os.path.abspath(os.path.split(os.path.realpath(__file__))[0] + "/.."), '..') sys.path.insert(0, PROJECT_ROOT) def translate_driver_code(driver_code): if driver_code == '100205': return '100210' return driver_code def valid_code(driver_code, registerd_code): if driver_code == '100205' or driver_code == '100210': if registerd_code not in ['100205', '100210']: return False else: return True return driver_code == registerd_code try: options, args = getopt.getopt(sys.argv[1:], 'cv:s:e:m:r:p:b:d:a:f:', ['com', 'version=', 'server=', 'env=', 'max-count=', 'platform-version=', 'platform=', 'parallel=', 'dealer=', 'agent=', 'postfix=']) except getopt.GetoptError as e: print(str(e)) sys.exit() upgrade_version = '' system_env = 'testing' max_count = 10 platform_version = '' platform = '' parallel = 5 server = '' dealer = None agent = None postfix = '' def get_fw_url_tmpl(server, platform, platform_version): if platform == '8955': fw_url_tmpl = 'http://{server}/uploaded/version/2g/SmartBox_{version}_Luat_V{platform_version}_{platform}_SSL'.format( server = server, version = upgrade_version, platform_version = '{0:0>4}'.format(platform_version), platform = platform) elif platform == 'ASR1802': fw_url_tmpl = 'http://{server}/uploaded/version/4g/SmartBox_{version}_Luat_V{platform_version}_{platform}_720D'.format( server = server, version = upgrade_version, platform_version = '{0:0>4}'.format(platform_version), platform = platform) else: assert False, 'incorrect platform type.' fw_url_tmpl = fw_url_tmpl + '_{driver_code}' if postfix: fw_url_tmpl = fw_url_tmpl + '_' + postfix if platform == 'ASR1802': fw_url_tmpl = fw_url_tmpl + '_{full}' fw_url_tmpl = fw_url_tmpl + '.bin' return fw_url_tmpl for name, value in options: if name in ('-v', '--version'): upgrade_version = value if name in ('-e', '--env'): system_env = value if name in ('-m', '--max-count'): max_count = int(value) if name in ('-r', '--platform-version'): platform_version = value if name in ('-p', '--platform'): platform = value if name in ('-b', '--parallel'): parallel = int(value) if name in ('-s', '--server'): server = value if name in ('-d', '--dealer'): dealer = value if name in ('-a', '--agent'): agent = value if name in ('-f', '--postfix'): postfix = value if not server: print 'server is null.' sys.exit(2) if not platform_version or not platform: print 'not assign platform info.' sys.exit(2) if platform not in ('8955', 'ASR1802'): print 'incorrect platform type.' sys.exit(2) if not upgrade_version: print 'error version = {version}'.format(version = upgrade_version) sys.exit(2) master, major, minor = upgrade_version.split('.') if not master or not major or not minor: print 'error version = {version}'.format(version = upgrade_version) sys.exit(2) if not system_env: print 'error system env = {env}'.format(env = system_env) sys.exit(2) import os os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'configs.{env}'.format(env = system_env)) from django.conf import settings from script.base import init_env import simplejson as json init_env(interactive = False) from apps.web.core.networking import MessageSender from apps.web.dealer.models import Dealer from apps.web.device.models import Device, DeviceDict from apps.web.constant import Const, DeviceOnlineStatus from apps.web.core.mqtt_client import MqttClient from script.device_upgrade import DeviceUpgradeLog version_regex = 'v{master}\.{major}\.'.format(master = master, major = major) version_check = 'v{master}.{major}.'.format(master = master, major = major) upgrade_soft_ver = 'v{version}'.format(version = upgrade_version) if platform == 'ASR1802': upgrade_core_ver = 'Luat_V{platform_version}_{platform}_720D'.format( platform_version = '{0:0>4}'.format(platform_version), platform = platform) else: upgrade_core_ver = 'Luat_V{platform_version}_{platform}_SSL'.format( platform_version = '{0:0>4}'.format(platform_version), platform = platform) upate_key_prefix = int(time.time()) # upate_key_prefix = '20200107' fw_url_tmpl = get_fw_url_tmpl(server, platform, platform_version) print 'version regex is: {}'.format(version_regex) print 'version check is: {}'.format(version_check) print 'upgrade soft version is: {}'.format(upgrade_soft_ver) print 'update key prefix is: {}'.format(upate_key_prefix) print 'fw url tmpl is: {}'.format(fw_url_tmpl) mqttc1883 = None mqttc1884 = None doing_dict = {} exists_code = set() no_exists_code = set() try: def on_connect(client, userdata, flags, rc): pass def on_message(mqttc, obj, msg): # type: (MqttClient, obj, json)->None msgDict = json.loads(bytes.decode(msg.payload)) imei = msgDict['IMEI'] print 'msg dict is: {}'.format(msgDict) update_key = DeviceUpgradeLog.make_update_key(imei, upate_key_prefix, upgrade_core_ver, upgrade_soft_ver) print 'update key is: {}'.format(update_key) log = DeviceUpgradeLog.objects( updateKey = update_key ).first() # type: DeviceUpgradeLog if not log: print 'not has log record' if msgDict['cmd'] == 209: print('209 has received. msg = %s' % str(msgDict)) if msgDict['result']: if log: log.set_stauts(DeviceUpgradeLog.Status.UPGRADED) else: if log: log.set_stauts(DeviceUpgradeLog.Status.FAILURE) mqttc.unsubscribe('server/%s/209' % imei) doing_dict.pop(imei, None) elif msgDict['cmd'] == 200: if msgDict['soft_ver'] == upgrade_soft_ver: log.set_stauts(DeviceUpgradeLog.Status.SUCCESS) else: log.set_stauts(DeviceUpgradeLog.Status.FAILURE) mqttc.unsubscribe('server/%s/200' % imei) def on_disconnect(client, userdata, self): print('exit. client = %s' % str(client)) mqttc1883 = MqttClient(client_id = 'webapp_' + str(uuid.uuid1())) try: mqttc1883.on_message = on_message mqttc1883.on_connect = on_connect mqttc1883.on_disconnect = on_disconnect mqttc1883.username_pw_set(settings.MQTT_USER, settings.MQTT_PSWD) mqttc1883.connect(settings.MQTT_HOSTNAME, 1883, 60) mqttc1883.loop_start() except Exception as e: print(e) mqttc1884 = MqttClient(client_id = 'webapp_' + str(uuid.uuid1())) try: mqttc1884.on_message = on_message mqttc1884.on_connect = on_connect mqttc1884.on_disconnect = on_disconnect mqttc1884.username_pw_set(settings.MQTT_USER, settings.MQTT_PSWD) mqttc1884.connect(settings.MQTT_HOSTNAME, 1884, 60) mqttc1884.loop_start() except Exception as e: print(e) if dealer: dealers = [dealer] elif agent: dealers = [dealer['_id'] for dealer in Dealer.get_collection().find({'agentId': agent})] else: dealers = None if version_check == 'v1.8.': if dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, '$or': [{'softVer': {'$regex': 'v1\.8\.'}}, {'softVer': {'$regex': 'v1\.7.'}}], 'softVer': {'$ne': 'v1.8.112'}}) else: objs = Device.get_collection().find( {'$or': [{'softVer': {'$regex': 'v1\.8\.'}}, {'softVer': {'$regex': 'v1\.7\.'}}], 'softVer': {'$ne': 'v1.8.112'}}) elif version_check == 'v4.0.': if dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, '$or': [{'softVer': {'$regex': 'v3\.0\.'}}, {'softVer': {'$regex': 'v4\.0.'}}], 'softVer': {'$ne': upgrade_soft_ver}}) else: objs = Device.get_collection().find( {'$or': [{'softVer': {'$regex': 'v3\.0\.'}}, {'softVer': {'$regex': 'v4\.0\.'}}], 'softVer': {'$ne': upgrade_soft_ver}}) elif version_check == 'v5.13.': if dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, 'driverCode': {'$in': ['100210', '100205']}, 'coreVer': {'$gte': 'Luat_V0033_8955_SSL'}, 'devType.code': {'$in': ['100210', '100205']}, '$and': [ { '$or': [{'softVer': {'$regex': 'v4\.1\.'}}, {'softVer': {'$regex': 'v5\.13\.'}}] }, { 'softVer': {'$ne': upgrade_soft_ver} } ] }) else: objs = Device.get_collection().find( {'driverCode': {'$in': ['100210', '100205']}, 'devType.code': {'$in': ['100210', '100205']}, 'coreVer': {'$gte': 'Luat_V0033_8955_SSL'}, '$and': [ { '$or': [{'softVer': {'$regex': 'v4\.1\.'}}, {'softVer': {'$regex': 'v5\.13\.'}}] }, { 'softVer': {'$ne': upgrade_soft_ver} } ] }) elif version_check == 'v5.1.': if dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, 'driverCode': {'$in': ['100210', '100205']}, 'coreVer': {'$gte': 'Luat_V0033_8955_SSL'}, 'devType.code': {'$in': ['100210', '100205']}, '$and': [ { '$or': [{'softVer': {'$regex': 'v40\.1\.'}}, {'softVer': {'$regex': 'v5\.1\.'}}] }, { 'softVer': {'$ne': upgrade_soft_ver} } ] }) else: objs = Device.get_collection().find( {'driverCode': {'$in': ['100210', '100205']}, 'devType.code': {'$in': ['100210', '100205']}, 'coreVer': {'$gte': 'Luat_V0033_8955_SSL'}, '$and': [ { '$or': [{'softVer': {'$regex': 'v40\.1\.'}}, {'softVer': {'$regex': 'v5\.1\.'}}] }, { 'softVer': {'$ne': upgrade_soft_ver} } ] }) elif version_check == 'v5.12.': if dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, 'driverCode': {'$in': ['100210', '100205']}, 'coreVer': {'$gte': 'Luat_V0033_8955_SSL'}, 'devType.code': {'$in': ['100210', '100205']}, '$and': [ { '$or': [{'softVer': {'$regex': 'v4\.12\.'}}, {'softVer': {'$regex': 'v5\.12\.'}}] }, { 'softVer': {'$ne': upgrade_soft_ver} } ] }) else: objs = Device.get_collection().find( {'driverCode': {'$in': ['100210', '100205']}, 'devType.code': {'$in': ['100210', '100205']}, 'coreVer': {'$gte': 'Luat_V0033_8955_SSL'}, '$and': [ { '$or': [{'softVer': {'$regex': 'v4\.12\.'}}, {'softVer': {'$regex': 'v5\.12\.'}}] }, { 'softVer': {'$ne': upgrade_soft_ver} } ] }) else: if dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, 'driverCode': {'$in': ['100210', '100205']}, 'devType.code': {'$in': ['100210', '100205']}, '$and': [{'softVer': {'$regex': version_regex}}, {'softVer': {'$ne': upgrade_soft_ver}}]}).limit(100) else: objs = Device.get_collection().find( {'driverCode': {'$in': ['100210', '100205']}, 'devType.code': {'$in': ['100210', '100205']}, '$and': [{'softVer': {'$regex': version_regex}}, {'softVer': {'$ne': upgrade_soft_ver}}]}).limit(100) count = 0 # 做一下保护, 避免查询语句错误 devNoList = [] for obj in objs: now_soft_ver = str(obj['softVer']) dev_no = str(obj['devNo']) exist_log = DeviceUpgradeLog.objects(status_in = ['running', 'upgraded', 'failure']).first() if exist_log: print 'ignore this round for dev<{}>'.format(dev_no) continue need_upgrade = True try: if version_check == 'v1.8.': if now_soft_ver.startswith('v1.8.') or now_soft_ver.startswith('v1.7.'): devNoList.append(dev_no) continue elif version_check == 'v4.0.': if now_soft_ver.startswith('v3.0.') or now_soft_ver.startswith('v4.0.'): devNoList.append(dev_no) continue elif version_check == 'v5.13.': if now_soft_ver.startswith('v4.1.') or ( now_soft_ver.startswith('v5.13.') and now_soft_ver != upgrade_soft_ver): devNoList.append(dev_no) continue elif version_check == 'v5.1.': if now_soft_ver.startswith('v40.1.') or ( now_soft_ver.startswith('v5.1.') and now_soft_ver != upgrade_soft_ver): devNoList.append(dev_no) continue elif version_check == 'v5.12.': if now_soft_ver.startswith('v4.12.') or ( now_soft_ver.startswith('v5.12.') and now_soft_ver != upgrade_soft_ver): devNoList.append(dev_no) continue else: if now_soft_ver.startswith(version_check): devNoList.append(dev_no) continue need_upgrade = False finally: if not need_upgrade: print 'dev version is: {}. no need to upgrade'.format(dev_no, obj['devType']['code'], obj['driverCode'], now_soft_ver) else: print 'dev version is: {}. need to upgrade.'.format(dev_no, obj['devType']['code'], obj['driverCode'], now_soft_ver) for devNo in devNoList: try: if max_count != -1 and count >= max_count: print 'max count reach.' break dev = Device.get_dev(devNo) # type: DeviceDict if dev.online != DeviceOnlineStatus.DEV_STATUS_ONLINE: print '{imei} is offline.'.format(imei = devNo) continue if 'driverCode' not in dev or not dev['driverCode'] or dev['driverCode'] == '100000': print '{imei} is pulse device.'.format(imei = devNo) continue driver_code = translate_driver_code(dev['driverCode']) now_register_code = dev['devType']['code'] if not valid_code(driver_code, now_register_code): print '{} registered problem. {} != {}'.format(devNo, driver_code, now_register_code) continue if driver_code in no_exists_code: print '{} not have version.'.format(driver_code) continue if ':1884' in dev['server']: mqttc1884.subscribe('server/%s/209' % devNo, Const.MQTT_QOS) mqttc1884.subscribe('server/%s/200' % devNo, Const.MQTT_QOS) elif ':1883' in dev['server']: mqttc1883.subscribe('server/%s/209' % devNo, Const.MQTT_QOS) mqttc1883.subscribe('server/%s/200' % devNo, Const.MQTT_QOS) else: print('%s %s %s\n' % (str(dev['devNo']), str(dev['logicalCode']), str(dev['softVer']))) continue if platform == 'ASR1802': if upgrade_core_ver == dev['coreVer']: version_path = fw_url_tmpl.format(driver_code = driver_code, full = 'inc') else: version_path = fw_url_tmpl.format(driver_code = driver_code, full = 'full') else: version_path = fw_url_tmpl.format(driver_code = driver_code) print 'version path is: {}'.format(version_path) if driver_code not in exists_code: r = requests.get(version_path, timeout = 15) if r.status_code == 404: print '{} version is not exist'.format(driver_code) no_exists_code.add(driver_code) continue else: exists_code.add(version_path) cmdPara = {'IMEI': devNo, 'ota_set': {'fw_url': version_path}} print cmdPara try: log = DeviceUpgradeLog.new_log(dev = dev, update_key_prefix = upate_key_prefix, coreVer = upgrade_core_ver, softVer = upgrade_soft_ver, driverCode = driver_code) except Exception, e: print str(e) continue result = MessageSender.send(device = dev, cmd = Const.CMD_CODE_SET_DEVINFO, payload = cmdPara, timeout = 15) if result['rst'] != 0: log.set_stauts(DeviceUpgradeLog.Status.FAILURE) continue else: count = count + 1 log.set_stauts(DeviceUpgradeLog.Status.RUNNING) doing_dict[devNo] = int(time.time()) while True: if len(doing_dict) > parallel: print('queue is full.') for imei in list(doing_dict.keys()): start_time = doing_dict[imei] if (int(time.time()) - start_time) > 5 * 60: doing_dict.pop(imei, None) time.sleep(5) else: print('queue is not full') break except Exception, e: print 'some exception =%s' % e finally: while len(doing_dict) > 0: for imei in list(doing_dict.keys()): start_time = doing_dict[imei] if (int(time.time()) - start_time) > 5 * 60: doing_dict.pop(imei, None) time.sleep(1) if mqttc1883: mqttc1883.loop_stop() mqttc1883.disconnect() mqttc1883.close() if mqttc1884: mqttc1884.loop_stop() mqttc1884.disconnect() mqttc1884.close() print('finished')