def sync_manual(self):
        '''
        手动同步, 与ats进行同步
        {
            cmd: "get_time_table",
            data: {
                "date": '2019-08-13'
            }
        },
        {
            cmd: "get_cur_train_info",
            data: {
                "location": 99, # 99 高大路, 98板桥
            }
        }
        :return:
        '''
        today_obj = pendulum.today("UTC").add(hours=8)
        today_str = today_obj.format("YYYY-MM-DD")
        ban_qiao = self.env.ref("metro_park_base_data_10.ban_qiao").id
        gao_da_lu = self.env.ref("metro_park_base_data_10.gao_da_lu").id

        self.env["metro_park_dispatch.msg_client"] \
            .get_time_tables([{
                "location": ban_qiao,
                "date": today_str
            }, {
                "location": gao_da_lu,
                "date": today_str
            }])

        LogManage.put_log(content='手动同步', mode='manual_sync')
        raise exceptions.Warning("命令已发送,请等待ats回传信息")
示例#2
0
 def add_plan_operation_log(self, location):
     '''
     添加信号楼日志
     :return:
     '''
     LogManage.put_log(content="消息回调处理异常{error}".format(error=callback_error),
                       mode="socketio_log")
示例#3
0
 async def disconnect():
     '''
     断开连接
     :return:
     '''
     _logger.info('the app server connect is dropped!')
     LogManage.put_log(content="socketio 客户端断开!",
                       mode="socketio_client_log")
示例#4
0
 async def on_connect():
     '''
     连接成功
     :return:
     '''
     _logger.info('connect to app server success!')
     LogManage.put_log(content="socketio 客户端已经联接",
                       mode="socketio_client_log")
示例#5
0
async def execute_msg(msg):
    '''
    后台任务发送消息
    :return:
    '''
    count = 0
    try:
        if msg["msg_type"] and msg["data"]:
            _logger.info("begin deal socketio msg...!")
            room = msg.get("room", None)
            callback_info = msg.get("callback_info", None)
            if callback_info:
                def call_back(_callback_info, *args, **kwargs):
                    try:
                        res_ids = _callback_info.get('ids', [])
                        context = _callback_info.get('context', [])
                        model_env.deal_event(data={
                            "msg_type": "call",
                            "uid": _callback_info.get("uid", None),
                            "room": room,
                            "model": _callback_info["model"],
                            "name": _callback_info["name"],
                            'res_ids': res_ids,
                            "args": args,
                            "kwargs": kwargs,
                            'context': context
                        })
                    except Exception as callback_error:
                        import traceback
                        traceback.print_exc()
                        _logger.error(callback_error)
                        LogManage.put_log(content="消息回调处理异常{error}".format(error=callback_error),
                                          mode="socketio_log")

                await sio.emit(msg["msg_type"],
                               data=msg["data"],
                               to=msg.get("sid", None),
                               callback=partial(call_back, copy.deepcopy(callback_info)),
                               room=room)
            else:
                await sio.emit(msg["msg_type"],
                               data=msg["data"], to=msg.get('sid', None), room=room)
            _logger.info("deal socketio msg finished...!")
            # 用于查看后台是否正常运行
            if count > 50:
                count = 0
                LogManage.put_log(content="socketio 后台服务处理数据完成!", mode="socketio_log")
            else:
                count += 1
    except Exception as tmp_error:
        import traceback
        traceback.print_exc()
        _logger.error(tmp_error)
        LogManage.put_log(content="消息处理异常{error}".format(error=tmp_error),
                          mode="socketio_log")
示例#6
0
 def _update_last_login(self):
     '''
     登录成功之后将当日失败次数清零,清空失败起始时间,限制时间回到1分
     :return:
     '''
     super()._update_last_login()
     LogManage.put_log(content='用户登录系统', mode='login')
     self.env.user.write({
         'today_continuous_error_count': 0,
         'no_login_minute': 1,
         'no_login_start_time': None
     })
示例#7
0
    async def inner_run():
        '''
        内部运行
        :return:
        '''
        socket_host = config.options.get('socket_io_app_server',
                                         '') or '0.0.0.0:9080'
        url = 'http://' + socket_host
        _logger.info('connect to socketio server, address %s' % url)
        LogManage.put_log(content='connect to socketio server, address %s' %
                          url,
                          mode="socketio_client_log")

        # 服务端有可能还没启动,client_io在第一次连接成功以后才会重联
        connected = False
        await client_io.connect(url)
        await client_io.wait()
        LogManage.put_log(content="客户退退出!", mode="socketio_client_log")
示例#8
0
 def get_sio_cookies(cls, environ):
     '''
     从sio取得cookie
     :param environ:
     :return:
     '''
     try:
         cookie = {}
         if 'HTTP_COOKIE' in environ and environ['HTTP_COOKIE']:
             http_cookie = environ['HTTP_COOKIE'].strip().split(';')
             for ck in http_cookie:
                 k, v = ck.strip().split('=')
                 cookie[k] = v
             return cookie
         return None
     except Exception as tmp_error:
         _logger.info(
             "can not get cookie: {environ}".format(environ=environ))
         LogManage.put_log(content='处理cookie发生错误 {error}'.format(error=tmp_error),
                           mode="socketio_log")
示例#9
0
 def call_back(_callback_info, *args, **kwargs):
     try:
         res_ids = _callback_info.get('ids', [])
         context = _callback_info.get('context', [])
         model_env.deal_event(data={
             "msg_type": "call",
             "uid": _callback_info.get("uid", None),
             "room": room,
             "model": _callback_info["model"],
             "name": _callback_info["name"],
             'res_ids': res_ids,
             "args": args,
             "kwargs": kwargs,
             'context': context
         })
     except Exception as callback_error:
         import traceback
         traceback.print_exc()
         _logger.error(callback_error)
         LogManage.put_log(content="消息回调处理异常{error}".format(error=callback_error),
                           mode="socketio_log")
示例#10
0
 def init_cur_train(self):
     '''
     初始化现车, 这里应当是调用ats的现车信息
     :return:
     '''
     trains = self.env['metro_park_maintenance.train_dev'].search([])
     train_cache = {train.id: train for train in trains}
     train_ids = trains.ids
     records = self.search([])
     # 当前车辆的id
     cur_train_ids = records.mapped("train.id")
     vals = []
     for tmp_id in train_ids:
         if tmp_id not in cur_train_ids:
             val = {
                 'train': tmp_id,
                 'train_status': 'wait',
                 'cur_location': train_cache[tmp_id].location.id,
                 'old_status': 'wait',
             }
             vals.append(val)
     self.create(vals)
     LogManage.put_log(content='同步车辆', mode='synchronous_vehicles')
示例#11
0
    def notify_train_position_changed(self, rail_location=None):
        '''
        模拟车辆到达
        :return:
        '''
        self.ensure_one()

        if self.cur_switch or self.cur_rail:
            alias = self.cur_location.alias
            state = self.make_position_info()
            self.trigger_up_event('funenc_socketio_server_msg',
                                  data={
                                      "msg_type": "update_train_position",
                                      "location_alias": alias,
                                      "msg_data": [state]
                                  })
            LogManage.put_log(content='通知车{name}到达位置{position}'.format(
                name=state["name"], position=state["position"]),
                              mode='cur_train_position_change')
        else:
            try:
                # 可能是后台来的,没法区分用户
                alias = self.env.user.cur_location.alias or rail_location
                state = self.make_position_info()
                self.trigger_up_event('funenc_socketio_server_msg',
                                      data={
                                          "msg_type": "update_train_position",
                                          "location_alias": alias,
                                          "msg_data": [state]
                                      })
                LogManage.put_log(
                    content='通知移除{name}位置'.format(name=state["name"]),
                    mode='cur_train_position_change')
            except Exception as error:
                _logger.info(
                    "update position error!{error}".format(error=error))
示例#12
0
 def get_uid_id_from_sio(cls, environ):
     '''
     取得session_id, 用于从odoo查询用户信息
     :param environ:
     :return:
     '''
     cookies = cls.get_sio_cookies(environ)
     if cookies:
         session_id = cookies.get("session_id", None)
         if not session_id:
             return False
         try:
             session_info = root.session_store.get(session_id)
             if not session_info:
                 _logger.info("the user is login out!")
                 return False
         except Exception as tmp_error:
             _logger.info("get session store error, {error}".format(error=tmp_error))
             LogManage.put_log(content='get session store error {error}'.format(error=tmp_error),
                               mode="socketio_log")
         uid = session_info.get('context', {}).get("uid", False)
         return uid
     else:
         return False
示例#13
0
    def deal_event(self, data=None):
        """
            处理事件消息,类似rpc
        :param data:
        :return:
        """
        LogManage.put_log(content="收到中转服务器请求", mode="socketio_client_log")
        try:
            with api.Environment.manage(), self.db_registry.cursor() as cr:
                env = api.Environment(cr, SUPERUSER_ID, {})
                model_name = data.get('model', False)
                model = env[model_name]

                args = data.get('args', [])
                kwargs = data.get('kwargs', {})
                data_rec = getattr(model, data.get('method'))(*args, **kwargs)
                LogManage.put_log(content="socketio客户端数据处理完成",
                                  mode="socketio_client_log")
                return data_rec
        except Exception as error:
            LogManage.put_log(content="处理中转服务器请求出错{error}".format(error=error),
                              mode="socketio_client_log")
            return False
示例#14
0
    def update_position(self, location, dev_no, rail_no):
        '''
        更新现车位置
        :param location:
        :param dev_no:
        :param rail_no:
        :return:
        '''
        run_train = self.search([("train.dev_no", "=", dev_no)])
        if not run_train:
            # 没有就创建车辆
            run_train = self.create_run_train(dev_no, run_train)

        # 为了防止车号被行调删除(出现过被正线行调强行删除的情况,真是坑),直接返回,使用联锁进行判断
        if not rail_no:
            return run_train.id

        rail = self.env["metro_park_base.rails_sec"]\
            .search([('no', '=', rail_no), ('location', '=', location)])
        if rail:
            # 由于ATS B股可能会出错,所以这里避开
            if rail.port and rail.port == "B":
                return run_train.id

            rail_type_back_sec_id = self.env.ref(
                "metro_park_base.rail_type_back_sec").id
            rail_type_out_sec_id = self.env.ref(
                "metro_park_base.rail_type_out_sec").id

            LogManage.put_log(
                content='车{name}到达出{position}, ATS记录,不改变位置'.format(
                    name=run_train["train_no"], position=rail["no"]),
                mode='cur_train_position_change')

            # 到达迁出线时删除车号
            if rail.rail_type.id == rail_type_back_sec_id \
                    or rail.rail_type.id == rail_type_out_sec_id:

                # 两个都给清除掉
                run_train.cur_switch = False
                run_train.cur_rail = False

                # 提前提交,防止别的线程访问不到数据, 这里是因为socketio的这个机制是要等侍回调返回,
                # 而别的地方使用的是另外的cursor,所以会访问不到数据
                self._cr.commit()
                run_train.notify_train_position_changed(rail.location.alias)

                # 通知前端位置发生变化, 清除了无法知道位置
                LogManage.put_log(
                    content='车{name}到达{position}, 清除位置, ATS'.format(
                        name=run_train["train_no"], position=rail["no"]),
                    mode='cur_train_position_change')
            else:
                # 只有在转换轨道的时候才更新位置
                rail_type_exchange_id = \
                    self.env.ref("metro_park_base.rail_type_exchange").id
                if rail.rail_type.id == rail_type_exchange_id:
                    # 有可能联锁占压判断以后,它发又车还原回去了,所以只能车原来在转换轨道的时候发送
                    # 出去的时候无所谓,出去全部由mdias判断, 转换轨不设置车位置,所以车辆的当状轨道
                    # 和道岔只能为空
                    if not (run_train.cur_rail and run_train.cur_switch):
                        run_train.cur_rail = rail.id
                        run_train.cur_switch = False
                        # 到达转换轨
                        LogManage.put_log(
                            content='车{name}到达{position}, 到达转换轨-ATS'.format(
                                name=run_train["train_no"],
                                position=rail["no"]),
                            mode='cur_train_position_change')
                        # 提前提交,防止别的线程访问不到数据
                        self._cr.commit()
                        # 通知前端位置发生变化
                        run_train.notify_train_position_changed()
                    else:
                        LogManage.put_log(
                            content='车{name}到达{position}, 但原车已经在在场内-ATS'.
                            format(name=run_train["train_no"],
                                   position=rail["no"]),
                            mode='cur_train_position_change')
                else:
                    # 记录, 用于联锁推断不出来的时候使用ats来更正
                    run_train.ats_position = rail_no

        return run_train.id
示例#15
0
    def on_ok(self):
        '''
        导入运行图
        :return:
        '''
        cur_location = self.env.user.cur_location
        if not cur_location:
            raise exceptions.ValidationError("当前用户没有配置位置信息。")

        main_line = self.env.ref(
            "metro_park_base_data_6.main_line_location").id
        hui_long = self.env.ref("metro_park_base_data_6.hui_long").id
        pi_tong = self.env.ref("metro_park_base_data_6.pi_tong").id

        time_table_model = self.env['metro_park_base.time_table']
        locations_model = self.env['metro_park_base.location']
        time_table_data_model = self.env['metro_park_base.time_table_data']

        # 分为从时刻表导入和从运行图概要导入
        if self.type == 'run_plan':
            time_table = time_table_model.create({
                'no':
                self.no,
                'time_table_type':
                self.time_table_type,
            })

            datas = self.read_excel()

            # 检查表头
            if len(datas) < 2:
                raise exceptions.ValidationError('数据表格式不正确,行数小于2')

            # 检查表头
            header_row = datas[0]
            if header_row[INDEX_COL] != '序号':
                raise exceptions.Warning('表头"序号"不正确, 请修正后再导入!')

            if header_row[TRAIN_NO_COL] != '车底ID':
                raise exceptions.Warning('表头"车底ID"不正确, 请修正后再导入!')

            if header_row[PLAN_OUT_LOCATION_COL] != '出库位置':
                raise exceptions.Warning('表头"出库位置"不正确, 请修正后再导入!')

            if header_row[PLAN_OUT_TIME_COL] != '出车场时间':
                raise exceptions.Warning('表头"出车场时间"不正确, 请修正后再导入!')

            if header_row[PLAN_BACK_LOCATION_COL] != '入库位置':
                raise exceptions.Warning('表头"入库位置"不正确, 请修正后再导入!')

            if header_row[PLAN_BACK_TIME_COL] != '回车场时间':
                raise exceptions.Warning('表头"回车场时间"时间不正确, 请修正后再导入!')

            # 取得所有的场段名称
            valid_rows = []
            locations_ar = []
            for row in datas:
                if len(row) > 1:
                    index = row[0]
                    if re.match(r'^\d+(.0)?$', str(index)):
                        valid_rows.append(row)
                        locations_ar.append(row[PLAN_OUT_LOCATION_COL])
                        locations_ar.append(row[PLAN_BACK_LOCATION_COL])

            locations = locations_model.search([('name', 'in', locations_ar)])
            if len(locations) == 0:
                raise exceptions.ValidationError("没有找到位置数据!")

            location_cache = {
                location['name']: location['id']
                for location in locations
            }

            vals = []
            for row in valid_rows:
                out_location = row[PLAN_OUT_LOCATION_COL].strip()
                back_location = row[PLAN_BACK_LOCATION_COL].strip()
                # 只要有一个就添加数据
                if out_location in location_cache or back_location in location_cache:
                    if out_location not in location_cache:
                        out_location = main_line
                    else:
                        out_location = location_cache.get(out_location)
                    if back_location not in location_cache:
                        back_location = main_line
                    else:
                        back_location = location_cache.get(back_location)

                    # 转换为utc时间
                    plan_out_time = pendulum.parse('2019-01-01 ' +
                                                   str(row[PLAN_OUT_TIME_COL]))
                    plan_out_time = plan_out_time.subtract(hours=8)

                    plan_back_time = pendulum.parse(
                        '2019-01-01 ' + str(row[PLAN_BACK_TIME_COL]))
                    plan_back_time = plan_back_time.subtract(hours=8)

                    # 时间格式检验
                    vals.append({
                        'sequence':
                        int(row[INDEX_COL]),
                        'train_no':
                        str(row[TRAIN_NO_COL]),
                        'out_location':
                        out_location,
                        'plan_out_time':
                        plan_out_time.format(
                            'YYYY-MM-DD HH:mm:ss'),  # 这里时间查询时要注意
                        'plan_in_time':
                        plan_back_time.format(
                            'YYYY-MM-DD HH:mm:ss'),  # 这里时间查询时要注意
                        'back_location':
                        back_location,
                        'time_table_id':
                        time_table['id']
                    })

            if len(vals) == 0:
                raise exceptions.ValidationError('没有导入任何数据,请检查文件是否正确')

            time_table_data_model.create(vals)
            LogManage.put_log(content='导入运行图', mode='import_diagram')
            return False
        else:
            time_table = time_table_model.create({
                'no':
                self.no,
                'time_table_type':
                self.time_table_type,
            })

            bin_data = base64.b64decode(self.xls_file)
            workbook = xlrd.open_workbook(file_contents=bin_data)
            sheet = workbook.sheet_by_index(0)
            vals = []
            for i in range(1, sheet.nrows):
                data = sheet.row_values(i)
                if data[4] == "回龙停车场":
                    out_location = hui_long
                elif data[4] == "郫筒":
                    out_location = pi_tong
                else:
                    out_location = main_line
                if data[5] == "回龙停车场":
                    back_location = hui_long
                elif data[5] == "郫筒":
                    back_location = pi_tong
                else:
                    back_location = main_line
                plan_out_time = pendulum.parse('2019-01-01 ' + str(data[6]))
                plan_out_time = plan_out_time.subtract(hours=8)

                plan_back_time = pendulum.parse('2019-01-01 ' + str(data[8]))
                if plan_back_time.hour < 3:
                    plan_back_time = pendulum.parse('2019-01-03 ' +
                                                    str(data[8]))
                plan_back_time = plan_back_time.subtract(hours=8)

                vals.append({
                    'sequence':
                    data[0],
                    'train_no':
                    data[1],
                    'out_location':
                    out_location,
                    'plan_out_time':
                    plan_out_time.format('YYYY-MM-DD HH:mm:ss'),  # 这里时间查询时要注意
                    'plan_in_time':
                    plan_back_time.format('YYYY-MM-DD HH:mm:ss'),  # 这里时间查询时要注意
                    'back_location':
                    back_location,
                    'time_table_id':
                    time_table['id'],
                    'miles':
                    data[11]
                })
            if len(vals) == 0:
                raise exceptions.ValidationError('没有导入任何数据,请检查文件是否正确')

            time_table_data_model.create(vals)
            LogManage.put_log(content='导入车底运用指标', mode='import_diagram')
示例#16
0
    def receive_train(self):
        '''
        接车, 开始排列进路, 进路开始排了才是
        :return:
        '''
        location = self.get_location_spell()

        data = self.get_plan_data()
        if data:
            if data["instructs"] == []:
                try:
                    # 添加日志
                    log_record = self.env[
                        "metro_park_dispatch.train_in_out_log"].create([{
                            "type":
                            "out_plan",
                            "train_dev":
                            self.train_id.train.id,
                            "operation":
                            "收车计划勾计划为空:{out_instructs}".format(
                                out_instructs=str(data["instructs"]))
                        }])
                    data["log_id"] = log_record.id
                except Exception as error:
                    _logger.info("log error {error}".format(error=error))
            else:
                try:
                    # 添加日志
                    log_record = self.env[
                        "metro_park_dispatch.train_in_out_log"].create([{
                            "type":
                            "out_plan",
                            "train_dev":
                            self.train_id.train.id,
                            "operation":
                            "收车计划勾计划:{out_instructs}".format(
                                out_instructs=str(data["instructs"]))
                        }])
                    data["log_id"] = log_record.id
                except Exception as error:
                    _logger.info("log error {error}".format(error=error))
            self.state = 'preparing'
            try:
                # 添加日志
                log_record = self.env[
                    "metro_park_dispatch.train_in_out_log"].create([{
                        "type":
                        "out_plan",
                        "train_dev":
                        self.train_id.train.id,
                        "operation":
                        "推送收车计划:{start_rail}-{end_rail}到信号楼".format(
                            start_rail=self.real_start_rail.no,
                            end_rail=self.plan_back_rail.no)
                    }])
                data["log_id"] = log_record.id
            except Exception as error:
                _logger.info("log error {error}".format(error=error))

            # 之前出现指令重复的情况,防止重复
            cache = dict()
            instructs = data["instructs"]
            new_instructs = []
            for instruct in instructs:
                if instruct["start_rail"] not in cache:
                    new_instructs.append(instruct)
                    cache[instruct["start_rail"]] = True
            data["instructs"] = new_instructs

            # 添加计划, 信号楼如果已经有了则只是更新信息
            try:
                self._cr.commit()
                self.trigger_up_event(
                    "funenc_socketio_server_msg",
                    data={
                        "msg_type": "add_plan",
                        "msg_data": [data],
                        "location": location
                    },
                    room="xing_hao_lou",
                    callback_name="_send_add_plan_success_callback")
            except Exception as error:
                LogManage.put_log(
                    content='推送添加收车计划失败{error}'.format(error=error),
                    mode='train_plan_log')

            # 添加日志
            excute_record = None
            try:
                # 这个必需要加,不然回调处理record回出错,
                # 回调应当是一直在等侍,但回调函数在另一线程
                excute_record = self.env[
                    "metro_park_dispatch.train_in_out_log"].create([{
                        "type":
                        "out_plan",
                        "train_dev":
                        self.train_id.train.id,
                        "operation":
                        "推送执行收车计划:{start_rail}-{end_rail}到信号楼".format(
                            start_rail=self.real_start_rail.no,
                            end_rail=self.plan_back_rail.no)
                    }])
            except Exception as error:
                _logger.info("log error {error}".format(error=error))

            # 执行计划,发送给信号楼
            try:
                # 这个必需要加,不然回调处理record回出错,
                # 回调应当是一直在等侍,但回调函数在另一线程
                self._cr.commit()
                self.trigger_up_event(
                    "funenc_socketio_server_msg",
                    data={
                        "msg_type": "excute_plan",
                        "location": location,
                        "msg_data": {
                            "id": self.id,
                            "type": 'train_back',
                            "location": location,
                            "log_id":
                            excute_record.id if excute_record else None
                        }
                    },
                    room="xing_hao_lou",
                    callback_name="_send_execute_plan_success_callback")
            except Exception as error:
                _logger.info("log error {error}".format(error=error))
                LogManage.put_log(
                    content='推送执行收车计划失败{error}'.format(error=error),
                    mode='train_plan_log')