# -*- coding: utf-8 -*- # !/usr/bin/env python import getopt import time import uuid 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) try: options, args = getopt.getopt(sys.argv[1:], 'v:s:e:m:r:p:b:d:a:f:', ['version=', 'server=', '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 = 'ASR1802' parallel = 5 server = '' dealer = None agent = None postfix = '' driver_code = '100000' 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: print 'not assign platform info.' 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.dealer.models import Dealer from apps.web.device.models import Device, DeviceDict from apps.web.core.networking import MessageSender 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) print 'version regex is: {}'.format(version_regex) print 'version check is: {}'.format(version_check) upgrade_soft_ver = 'v{version}'.format(version = upgrade_version) upgrade_core_ver = 'Luat_V{platform_version}_{platform}_720D'.format( platform_version = '{0:0>4}'.format(platform_version), platform = platform) update_key = DeviceUpgradeLog.make_update_key(upgrade_core_ver, upgrade_soft_ver) print 'update key is: {}'.format(update_key) print 'upgrade soft ver is: {}'.format(upgrade_soft_ver) print 'upgrade core ver is: {}'.format(upgrade_core_ver) 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) print 'update key is: {}'.format(update_key) 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 and msgDict['core_ver'] == upgrade_core_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 dealers: objs = Device.get_collection().find( {'ownerId': {'$in': dealers}, 'devType.code': {'$lt': '100100'}, 'softVer': {'$regex': version_regex}}) else: objs = Device.get_collection().find( {'ownerId': {'$nin': [None, '']}, 'devType.code': {'$lt': '100100'}, 'softVer': {'$regex': version_regex}}) count = 0 devNoList = [] for obj in objs: now_soft_ver = str(obj['softVer']) now_core_ver = str(obj.get('coreVer','')) 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: common_flag = (now_soft_ver.startswith(version_check) and ( now_soft_ver != upgrade_soft_ver or now_core_ver != upgrade_core_ver)) if common_flag: 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'].get( 'code', ''), obj.get('driverCode', ''), now_soft_ver) else: print 'dev version is: {}. need to upgrade.'.format(dev_no, obj['devType'].get( 'code', None), obj.get('driverCode', ''), now_soft_ver) fw_url_tmpl = 'http://{server}/uploaded/version/4g/SmartBox4G_{version}_Luat_V{platform_version}_{platform}_720D_100000'.format( server = server, version = upgrade_version, platform_version = '{0:0>4}'.format(platform_version), platform = platform) if postfix: fw_url_tmpl = fw_url_tmpl + '_' + postfix fw_url_tmpl = fw_url_tmpl + '_{full}.bin' # r = requests.get(version_path, timeout = 15) # if r.status_code == 404: # print '{} version is not exist'.format(driver_code) 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: continue 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') cmdPara = {'cmd': Const.CMD_CODE_SET_DEVINFO, 'IMEI': devNo, 'ota_set': {'fw_url': version_path}} print cmdPara log = DeviceUpgradeLog.new_log(dev = dev, coreVer = upgrade_core_ver, softVer = upgrade_soft_ver, driverCode = driver_code, updatePara = cmdPara) 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: log.set_stauts(DeviceUpgradeLog.Status.RUNNING) count = count + 1 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(1) 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')