# -*- coding: utf-8 -*- # !/usr/bin/env python import getopt import time import uuid import requests import sys import os from script.device_upgrade import DeviceUpgradeLog PROJECT_ROOT = os.path.join(os.path.abspath(os.path.split(os.path.realpath(__file__))[0] + "/.."), '..') sys.path.insert(0, PROJECT_ROOT) try: options, args = getopt.getopt(sys.argv[1:], 'd:s:v:e:m:r:b:d:a:f:', ['driver=', 'server=', 'version=', 'env=', 'max-count=', 'platform-version=', '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 = '8955' parallel = 5 server = '' dealer = None agent = None postfix = '' driver_code = '000000' def get_fw_url_tmpl(server, platform, platform_version): if platform == '8955': fw_url_tmpl = 'http://{server}/uploaded/version/2g/SMART_BOX_{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 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 ('-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) if not driver_code: print 'not assign driver code parameter.' 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 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) update_key = DeviceUpgradeLog.make_update_key(upgrade_core_ver, upgrade_soft_ver) 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 is: {}'.format(update_key) print 'fw url tmpl is: {}'.format(fw_url_tmpl) print 'driver code is: {}'.format(driver_code) 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) log = DeviceUpgradeLog.objects( updateKey = update_key, devNo = imei ).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) version_path = fw_url_tmpl.format(driver_code = driver_code) print 'version path is: {}'.format(version_path) r = requests.get(version_path, timeout = 15) if r.status_code == 404: print '{} version is not exist'.format(driver_code) sys.exit(1) 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': 'v1.5'}, {'softVer': 'v1.7'}, {'softVer': {'$regex': 'v1\.5\.'}}, {'softVer': {'$regex': 'v1\.7.'}}]}) else: objs = Device.get_collection().find( {'$or': [{'softVer': 'v1.5'}, {'softVer': 'v1.7'}, {'softVer': {'$regex': 'v1\.5\.'}}, {'softVer': {'$regex': 'v1\.7\.'}}]}) else: print 'not mcu version' sys.exit(1) # if version_check == 'v1.8.': # if dealers: # objs = Device.get_collection().find( # {'ownerId': {'$in': dealers}, # '$or': [{'softVer': {'$regex': 'v1\.5\.'}}, {'softVer': {'$regex': 'v1\.8\.'}}, {'softVer': {'$regex': 'v1\.7.'}}], # 'softVer': {'$ne': version_regex}}) # else: # objs = Device.get_collection().find( # {'$or': [{'softVer': {'$regex': 'v1\.5\.'}}, {'softVer': {'$regex': 'v1\.8\.'}}, {'softVer': {'$regex': 'v1\.7\.'}}], # 'softVer': {'$ne': version_regex}}) # else: # print 'not mcu version' # sys.exit(1) count = 0 # 做一下保护, 避免查询语句错误 devNoList = [] for obj in objs: now_soft_ver = str(obj['softVer']) dev_no = str(obj['devNo']) exist_log = DeviceUpgradeLog.objects( updateKey = update_key, devNo = dev_no).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.') or now_soft_ver.startswith('v1.5.') or now_soft_ver == 'v1.7' or now_soft_ver == 'v1.5': # if now_soft_ver == 'v1.7' or now_soft_ver == 'v1.5': devNoList.append(dev_no) continue else: continue need_upgrade = False finally: if not need_upgrade: print 'dev version is: {}. no need to upgrade'.format(dev_no, '', '', now_soft_ver) else: print 'dev version is: {}. need to upgrade.'.format(dev_no, '', '', 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 ':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 cmdPara = {'IMEI': devNo, 'ota_set': {'fw_url': version_path}} print cmdPara try: log = DeviceUpgradeLog.new_log(dev = dev, coreVer = upgrade_core_ver, softVer = upgrade_soft_ver, driverCode = driver_code, updatePara = cmdPara) 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) > 2 * 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) > 2 * 60: doing_dict.pop(imei, None) time.sleep(5) if mqttc1883: mqttc1883.loop_stop() mqttc1883.disconnect() mqttc1883.close() if mqttc1884: mqttc1884.loop_stop() mqttc1884.disconnect() mqttc1884.close() print('finished')