Exemple #1
0
        def add_linkage_command_body(product_id, dev_id, command_list):
            lk = DevCommandQueueMng.get_exe_locker(dev_id)
            try:
                ts = time.time()
                MyLog.logger.info(f'添加联动指令, 等待获取锁({ts}), 设备id:{dev_id}')
                lk.acquire()
                MyLog.logger.info(f'添加联动指令, 获得锁({ts}), 设备id:{dev_id}')
                need_add_to_command_queue_list = []
                dev_command_queue = DevCommandQueueMng.get_dev_command_queue(
                    dev_id)
                if not dev_command_queue:
                    dict = {}
                    dict["dev_id"] = dev_id
                    dev_command_queue = DevCommandQueue(product_id, dev_id)
                    dict["dev_command_queue"] = dev_command_queue
                    g_dev_command_queue_list.append(dict)

                for command in command_list:
                    need_exe = True
                    current_running_command = dev_command_queue.get_current_running_command(
                        command.command)
                    if current_running_command:
                        MyLog.logger.info(
                            'command.command = %s, command.priority = %d, current_running_command.priority = %d'
                            % (command.command, command.priority,
                               current_running_command.priority))
                    if current_running_command and command.priority <= current_running_command.priority:
                        EventReport.report_rule_command_ignore_event(
                            dev_id, command.command, command.uuid,
                            current_running_command.uuid)
                        need_exe = False

                    if need_exe:
                        need_retry, service_has_recv, ret = DevCommandQueueMng.command_exe(
                            dev_id, command)
                        if service_has_recv:
                            dev_command_queue.clear_linkage_command(
                                command.command)
                            need_add_to_command_queue_list.append(command)

                if need_add_to_command_queue_list:
                    MyLog.logger.info(
                        'dev_command_queue.add_linkage_command_list size: %d' %
                        (len(need_add_to_command_queue_list)))
                    dev_command_queue.add_linkage_command_list(
                        need_add_to_command_queue_list)
                    name_list = dev_command_queue.get_all_command_name_list()
                    DevCommandQueueMng.__reset_dev_timer(dev_id)
                lk.release()
                MyLog.logger.info(f'添加联动指令, 释放锁({ts}), 设备id:{dev_id}')
            except Exception as e:
                msg = MyLog.color_red(
                    'add_linkage_command_body has exception: ' + str(e))
                MyLog.logger.error(msg)
                lk.release()
Exemple #2
0
        def add_manual_command_body(product_id, dev_id, command_list):
            lk = DevCommandQueueMng.get_exe_locker(dev_id)
            try:
                ts = time.time()
                MyLog.logger.info(f'添加手动指令, 等待获取锁({ts}), 设备id:{dev_id}')
                lk.acquire()
                MyLog.logger.info(f'添加手动指令, 获得锁({ts}), 设备id:{dev_id}')

                need_add_to_command_queue_list = []
                dev_command_queue = DevCommandQueueMng.get_dev_command_queue(
                    dev_id)
                if not dev_command_queue:
                    dict = {}
                    dict["dev_id"] = dev_id
                    dev_command_queue = DevCommandQueue(product_id, dev_id)
                    dict["dev_command_queue"] = dev_command_queue
                    g_dev_command_queue_list.append(dict)

                for command in command_list:
                    command.uuid = 'manual'
                    need_exe = True
                    current_running_command = dev_command_queue.get_current_running_command(
                        command.command)
                    # 同一优先级的临时手动命令需要更新执行
                    if current_running_command and current_running_command.effective and \
                            ((
                                     current_running_command.type == 'manual' and command.priority < current_running_command.priority) or \
                             (
                                     current_running_command.type != 'manual' and command.priority <= current_running_command.priority)):
                        EventReport.report_rule_command_ignore_event(
                            dev_id, command.command, command.uuid,
                            current_running_command.uuid)
                        need_exe = False

                    if need_exe:
                        need_retry, service_has_recv, ret = DevCommandQueueMng.command_exe(
                            dev_id, command, force=True)
                        if service_has_recv:
                            # 如果执行临时手动指令,则联动指令已被顶替失效,删除
                            dev_command_queue.clear_linkage_command(
                                command.command)

                    need_add_to_command_queue_list.append(command)
                if need_add_to_command_queue_list:
                    dev_command_queue.add_manual_command_list(
                        need_add_to_command_queue_list)
                    DevCommandQueueMng.__reset_dev_timer(dev_id)
                lk.release()
                MyLog.logger.info(f'添加手动指令, 释放锁({ts}), 设备id:{dev_id}')
            except Exception as e:
                msg = MyLog.color_red(
                    'add_manual_command_body has exception: ' + str(e))
                MyLog.logger.error(msg)
                lk.release()
Exemple #3
0
def clear_all_running_rule_endtime():
    g_lk.acquire()
    for rule in g_running_rule_endtime_list:
        g_running_rule_endtime_list.remove(rule)
        EventReport.report_rule_end_event(rule['uuid'])
        break
    g_lk.release()
    global g_running_rule_endtime_handle_timer
    if g_running_rule_endtime_handle_timer:
        g_running_rule_endtime_handle_timer.cancel()

    g_running_rule_endtime_handle_timer = Timer(0, running_rule_endtime_handle)
    g_running_rule_endtime_handle_timer.start()
Exemple #4
0
def remove_running_rule_endtime(uuid_list):
    g_lk.acquire()
    for uuid in uuid_list:
        for rule in g_running_rule_endtime_list:
            if rule['uuid'] == uuid:
                g_running_rule_endtime_list.remove(rule)
                EventReport.report_rule_end_event(rule['uuid'])
                break
    g_lk.release()
    global g_running_rule_endtime_handle_timer
    if g_running_rule_endtime_handle_timer:
        g_running_rule_endtime_handle_timer.cancel()

    g_running_rule_endtime_handle_timer = Timer(0, running_rule_endtime_handle)
    g_running_rule_endtime_handle_timer.start()
Exemple #5
0
    def add_timer_command(product_id, dev_id, command_list) -> None:
        MyLog.logger.info('添加定时指令 产品ID:%s, 设备ID:%s' % (product_id, dev_id))
        dev_command_queue = DevCommandQueueMng.get_dev_command_queue(dev_id)
        if not dev_command_queue:
            dict = {}
            dict["dev_id"] = dev_id
            dev_command_queue = DevCommandQueue(product_id, dev_id)
            dict["dev_command_queue"] = dev_command_queue
            g_dev_command_queue_list.append(dict)

        for command in command_list:
            current_running_command = dev_command_queue.get_current_running_command(
                command.command)
            if current_running_command and current_running_command.effective and command.priority <= current_running_command.priority:
                EventReport.report_rule_command_ignore_event(
                    dev_id, command.command, command.uuid,
                    current_running_command.uuid)

        dev_command_queue.add_timer_command_list(command_list)
Exemple #6
0
def running_rule_endtime_handle():
    MyLog.logger.info("运行中的规则结束处理")
    current_ts = time.time()
    smallest_ts = 0
    uuid_list = []
    to_del_rule = []
    g_lk.acquire()
    for rule in g_running_rule_endtime_list:
        MyLog.logger.info(f'rule:{rule}')
        if rule['end_ts'] < current_ts:
            MyLog.logger.info("规则(%s)结束" % (rule['uuid']))
            # g_running_rule_endtime_list.remove(rule) # 遍历列表过程中改变列表size!!!
            to_del_rule.append(rule)
            uuid_list.append(rule['uuid'])
            # 上报规则结束事件
            EventReport.report_rule_end_event(rule['uuid'])
        else:
            if smallest_ts == 0:
                smallest_ts = rule['end_ts']
            elif rule['end_ts'] < smallest_ts:
                smallest_ts = rule['end_ts']

    # to fix the bug referred above
    for del_rule in to_del_rule:
        g_running_rule_endtime_list.remove(del_rule)
    g_lk.release()

    if uuid_list:
        # 删除结束规则的指令
        DevCommandQueueMng.clear_command_by_rule_uuid(uuid_list)
        # 所有设备队列重新执行指令决策
        DevCommandQueueMng.all_dev_exe()

    global g_running_rule_endtime_handle_timer
    if g_running_rule_endtime_handle_timer:
        g_running_rule_endtime_handle_timer.cancel()

    ts = smallest_ts - current_ts
    if ts > 0:
        g_running_rule_endtime_handle_timer = Timer(
            ts, running_rule_endtime_handle)
        g_running_rule_endtime_handle_timer.start()
Exemple #7
0
    def command_exe(dev_id, command: CommandInfo, force=False):
        try:
            MyLog.logger.info(
                f'指令执行 设备id:{dev_id}, 指令名称:{command.command}, 规则:{command.uuid}, force:{force}'
            )
            # 先获取指令名称
            command_name = command.command
            # 从该设备的指令队列中查询该指令名称正在执行的指令
            dev_command_queue = DevCommandQueueMng.get_dev_command_queue(
                dev_id)
            running_command = dev_command_queue.get_current_running_command(
                command_name)
            need_exe = False
            need_report_rule_command_cover_event = False
            if force:
                need_exe = True
                if running_command.priority < command.priority:
                    need_report_rule_command_cover_event = True
            elif running_command:
                # 判断是否为同一个规则指令,如果不是才允许执行
                MyLog.logger.info('running_command: %s, command:%s' %
                                  (running_command.uuid, command.uuid))
                MyLog.logger.info(
                    f'running_command_effective:{running_command.effective}')
                if not running_command.effective or running_command.uuid != command.uuid:
                    need_exe = True
                else:
                    msg = MyLog.color_green(
                        '指令执行 设备id:%s, 指令名称:%s, 规则:%s 已经在执行中,不需要重新下发' %
                        (dev_id, command.command, command.uuid))
                    MyLog.logger.info(msg)
                if running_command.priority < command.priority:
                    need_report_rule_command_cover_event = True
            else:
                need_exe = True

            result = g_retValue.qjBoxOpcodeSucess.value
            need_retry = False
            service_has_recv = False
            if need_exe:
                if command.default_param:
                    # 执行默认参数
                    msg = MyLog.color_green(
                        '下发默认参数指令(%s)给设备(%s)服务, 指令优先级:%d' %
                        (command.command, dev_id, command.priority))
                    MyLog.logger.info(msg)
                    need_retry, service_has_recv, result, data = DevCall.call_service(
                        dev_id, command.command, command.type, default=True)
                    msg = MyLog.color_green('下发默认参数指令(%s)给设备(%s)服务, 返回:%d' %
                                            (command.command, dev_id, result))
                    MyLog.logger.info(msg)
                    EventReport.report_default_command_status_event(
                        dev_id, command.command, result)
                else:
                    # 执行规则配置参数
                    msg = MyLog.color_green(
                        '下发规则(%s)指令(%s)给设备(%s)服务, 指令优先级:%d' %
                        (command.uuid, command.command, dev_id,
                         command.priority))
                    MyLog.logger.info(msg)
                    need_retry, service_has_recv, result, data = DevCall.call_service(
                        dev_id, command.command, command.type, command.params)
                    msg = MyLog.color_green(
                        '下发规则(%s)指令(%s)给设备(%s)服务, 返回:%d' %
                        (command.uuid, command.command, dev_id, result))
                    MyLog.logger.info(msg)
                    # 上报ruleCommandStatus event
                    EventReport.report_rule_command_status_event(
                        command.uuid, dev_id, command.command, result)

                if service_has_recv:
                    dev_command_queue.set_current_running_command(
                        command_name, command)

                    # 更新规则指令状态
                    CmdRecorder.update_cmd(dev_id, command)

                    if need_report_rule_command_cover_event:
                        EventReport.report_rule_command_cover_event(
                            dev_id, command.command, running_command.uuid,
                            command.uuid)
            return need_retry, service_has_recv, result
        except BaseException as e:
            msg = MyLog.color_red('command_exe has except: ' + str(e))
            MyLog.logger.error(msg)
            return False, False, g_retValue.qjBoxOpcodeExcept.value
Exemple #8
0
    def outside_linkage(cls, services) -> int:
        try:
            keys = {'uuid', 'priority', 'script'}
            for service_dict in services:
                if not cls.__check_keys_exists(service_dict, keys):
                    # 返回参数错误
                    msg = MyLog.color_red('必要参数不存在')
                    MyLog.logger.error(msg)
                    return g_retValue.qjBoxOpcodeInputParamErr.value

                if type(service_dict['uuid']
                        ) != str or service_dict['uuid'] == '':
                    msg = MyLog.color_red('uuid param is invalid')
                    MyLog.logger.error(msg)
                    return g_retValue.qjBoxOpcodeInputParamErr.value

                if type(service_dict['script']
                        ) != str or service_dict['script'] == '':
                    msg = MyLog.color_red('script param is invalid')
                    MyLog.logger.error(msg)
                    return g_retValue.qjBoxOpcodeInputParamErr.value

                if type(service_dict['priority']) != int or service_dict[
                        'priority'] < 1 or service_dict['priority'] > 99:
                    msg = MyLog.color_red('priority param is invalid')
                    MyLog.logger.error(msg)
                    return g_retValue.qjBoxOpcodeInputParamErr.value

            for service_dict in services:
                uuid = service_dict['uuid']
                py_path = "/tmp/" + uuid + '.py'
                pyc_path = "/tmp/" + uuid + '.pyc'
                conver_to_py(service_dict['script'], py_path)
                if not os.path.exists(py_path):
                    msg = MyLog.color_red(
                        "outside_linkage: py(%s) is not exist" % (py_path))
                    MyLog.logger.error(msg)
                    continue
                # 执行脚本
                file = importlib.import_module(uuid)
                importlib.reload(file)
                # dev_command_list = [{'product_id': '', 'dev_id': "", "command_list":[{'service':'', 'param':'', 'time':10 }]}]
                dev_command_list, event_list, attr_list = file.script_fun()
                MyLog.logger.debug('dev_command_list size: %d' %
                                   (len(dev_command_list)))
                if dev_command_list or event_list:
                    current_ts = time.time()
                    # 上报规则开始执行
                    EventReport.report_rule_start_event(uuid)
                    continue_time = 1
                    for dev_command in dev_command_list:
                        command_info_list = []
                        for command in dev_command['command_list']:
                            if continue_time < command['time']:
                                continue_time = command['time']
                            command_info = CommandInfo(
                                uuid, command['service'], command['param'],
                                current_ts, current_ts + command['time'],
                                service_dict['priority'], 'linkage')
                            MyLog.logger.debug("append command priority = %d" %
                                               (service_dict['priority']))
                            command_info_list.append(command_info)
                        if command_info_list:
                            MyLog.logger.debug('#add_linkage_command')
                            DevCommandQueueMng.add_linkage_command(
                                dev_command['product_id'],
                                dev_command['dev_id'], command_info_list)

                    end_ts = current_ts + continue_time
                    uuid_endtime_list = [{'uuid': uuid, 'end_ts': end_ts}]
                    add_running_rule_endtime(uuid_endtime_list)

                    for custom_event in event_list:
                        EventReport.report_linkage_custom_event(
                            custom_event['event_id'],
                            custom_event['src_dev_list'])
                if os.path.exists(py_path):
                    os.remove(py_path)
                if os.path.exists(pyc_path):
                    os.remove(pyc_path)
                return g_retValue.qjBoxOpcodeSucess.value
        except Exception as e:
            msg = MyLog.color_red('outside_linkage in rule_mng has except: ' +
                                  str(e))
            MyLog.logger.error(msg)
            return g_retValue.qjBoxOpcodeExcept.value
Exemple #9
0
    def run_linkage_rule_by_devid(cls, dev_id, attrs) -> None:
        try:
            MyLog.logger.info(
                f'##########run_linkage_rule_by_devid({dev_id} attrs: {attrs})############'
            )
            uuid_list = SqliteInterface.get_current_linkage_rule_by_src_devid(
                dev_id)
            msg = f"get_current_linkage_rule_by_src_devid({dev_id}, sizeof uuid_list = {len(uuid_list)})"
            MyLog.logger.debug(msg)
            for uuid in uuid_list:
                py_path = RULE_PY_SCRIPT_FOLDER + "/" + uuid + '.py'
                if not os.path.exists(py_path):
                    msg = MyLog.color_red(
                        "run_linkage_rule_by_devid: py(%s) is not exist" %
                        (py_path))
                    MyLog.logger.error(msg)
                    continue
                # 执行脚本
                py_import_path = RULE_PY_MODEL_PATH + uuid
                MyLog.logger.debug('py_import_path: ' + py_import_path)
                file = importlib.import_module(py_import_path)
                importlib.reload(file)
                MyLog.logger.debug('run script fun')
                # dev_command_list = [{'product_id': '', 'dev_id': "", "command_list":[{'service':'', 'param':'', 'time':10 }]}]
                dev_command_list, event_list, attr_list = file.script_fun()
                msg = f'dev_command_list size: {len(dev_command_list)}, event_list size: {len(event_list)}'
                MyLog.logger.debug(msg)

                # 如果相同的联动策略已经在运行中了,那么这个策略的所有服务都被忽略
                if find_running_rule_by_uuid(uuid):
                    for dev_commands_dict in dev_command_list:
                        __, dev_id, service_list = dev_commands_dict.values()
                        for command_dict in service_list:
                            MyLog.logger.debug(
                                f'dev_id:{dev_id},cmd:{command_dict["service"]},uuid:{uuid}'
                            )
                            EventReport.report_rule_command_ignore_event(
                                dev_id, command_dict['service'], uuid, uuid)
                    continue

                if attrs:
                    allow_exe = RuleMng.attrs_has_one_in_changed(
                        dev_id, attr_list, attrs)
                else:
                    allow_exe = True
                MyLog.logger.debug(f'allow exe: {allow_exe}')

                if allow_exe and (dev_command_list or event_list):
                    priority = SqliteInterface.get_priority_by_uuid(uuid)
                    if priority < 0:
                        continue
                    current_ts = time.time()
                    # 上报规则开始执行
                    EventReport.report_rule_start_event(uuid)

                    continue_time = 1
                    for dev_command in dev_command_list:
                        command_info_list = []
                        for command in dev_command['command_list']:
                            if continue_time < command['time']:
                                continue_time = command['time']
                            command_info = CommandInfo(
                                uuid, command['service'], command['param'],
                                current_ts, current_ts + command['time'],
                                priority, 'linkage')
                            command_info_list.append(command_info)
                        if command_info_list:
                            DevCommandQueueMng.add_linkage_command(
                                dev_command['product_id'],
                                dev_command['dev_id'], command_info_list)

                    end_ts = current_ts + continue_time
                    uuid_endtime_list = [{'uuid': uuid, 'end_ts': end_ts}]
                    add_running_rule_endtime(uuid_endtime_list)

                    for custom_event in event_list:
                        EventReport.report_linkage_custom_event(
                            custom_event['event_id'],
                            custom_event['src_dev_list'])
            MyLog.logger.info(
                f'##########run_linkage_rule_by_devid finished({dev_id} attrs: {attrs})############'
            )
        except Exception as e:
            msg = MyLog.color_red('run_linkage_rule_by_devid has except: ' +
                                  str(e))
            MyLog.logger.error(msg)
Exemple #10
0
    def timer_rule_decision(cls) -> None:
        try:
            MyLog.logger.info('进行定时规则决策')
            # 计算出下一次最近的执行时间戳,启动定时器
            next_decision_time = cls.get_closest_timestamp()
            if next_decision_time > 0.0:
                RuleMng.start_new_rule_decision_timer(next_decision_time)
            # 获取符合要求的uuid列表
            uuid_list = SqliteInterface.get_current_timer_rule()
            # 执行规则,将规则指令下发给指令管理器
            MyLog.logger.info('uuid_list size: ' + str(len(uuid_list)))
            dev_id_list = []
            rule_endtime_list = []
            for uuid in uuid_list:
                MyLog.logger.info('===开始执行规则(%s)===' % (uuid))
                priority = SqliteInterface.get_priority_by_uuid(uuid)
                if priority < 0:
                    continue
                py_model = RULE_PY_MODEL_PATH + uuid
                # 如果已经添加到了g_running_rule_endtime_list里,说明这个定时策略早就开始执行了
                if not find_running_rule_by_uuid(uuid):
                    EventReport.report_rule_start_event(uuid)

                    # 记录规则结束时间戳到全局变量g_running_rule,等待结束上报结束事件
                    start_ts, end_ts = cls.get_rule_timestamp(uuid)
                    MyLog.logger.info('规则(%s)结束时间戳:%d' % (uuid, end_ts))
                    if end_ts > 0:
                        rule_endtime_list.append({
                            'uuid': uuid,
                            "end_ts": end_ts
                        })
                # 执行脚本
                file = importlib.import_module(py_model)
                importlib.reload(file)
                # dev_command_list = [{'product_id': '', 'dev_id': "", "command_list":[{'service':'', 'param': , 'time': 10}]}]
                # event_list = event_list = [{"event_id":"", "src_dev_list":[{"productId":"p_id", "deviceId":"d_id"}]}]
                dev_command_list, event_list, attr_list = file.script_fun()
                ts = time.time()
                for dev_command in dev_command_list:
                    command_info_list = []
                    for command in dev_command['command_list']:
                        command_info = CommandInfo(uuid, command['service'],
                                                   command['param'], ts,
                                                   ts + command['time'],
                                                   priority, 'timer')
                        command_info_list.append(command_info)
                    if command_info_list:
                        # 如果已经添加到了g_running_rule_endtime_list里,说明联动事件已经添加到命令队列里了
                        if not find_running_rule_by_uuid(uuid):
                            DevCommandQueueMng.add_timer_command(
                                dev_command['product_id'],
                                dev_command['dev_id'], command_info_list)
                        # dev_id_list.append(dev_command['dev_id'])
                        DevCommandQueueMng.dev_exe_by_command_list(
                            dev_command['dev_id'], command_info_list)

                # 如果已经添加到了g_running_rule_endtime_list里,说明联动事件已经上报过了
                if not find_running_rule_by_uuid(uuid):
                    for custom_event in event_list:
                        EventReport.report_linkage_custom_event(
                            custom_event['event_id'],
                            custom_event['src_dev_list'])
                MyLog.logger.info('===结束执行规则(%s)===' % (uuid))

            add_running_rule_endtime(rule_endtime_list)
        except Exception as e:
            msg = MyLog.color_red("timer_rule_decision has except: " + str(e))
            MyLog.logger.error(msg)