Ejemplo n.º 1
0
    def query_etc_deduct_status(order_id: str) -> dict:
        """
        查询etc扣费状态
        :param order_id: 订单号
        """
        result = {
            "flag": False,
            "errorCode": "",
            "errorMessage": "",
            "data": None
        }

        _, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                          sqlite_database='etc_deduct.sqlite')
        etc_request_orm: ETCRequestInfoOrm = db_session.query(
            ETCRequestInfoOrm).filter(
                ETCRequestInfoOrm.trans_order_no == order_id).order_by(
                    desc(ETCRequestInfoOrm.create_time)).first()
        if etc_request_orm:
            deduct_status = etc_request_orm.deduct_status
            result['data'] = deduct_status
            if deduct_status == EtcDeductStatus.SUCCESS:
                result['flag'] = True
            elif deduct_status == EtcDeductStatus.DEDUCTING:
                create_time = etc_request_orm.create_time
                if (datetime.now() - create_time
                    ).seconds > 10:  # 超过10s还是DEDUCTING,认为没有检测到obu
                    result['data'] = EtcDeductStatus.NO_DETECT_OBU
        else:
            msg = '没有此订单号: {}'.format(order_id)
            result['data'] = msg
            result['errorMessage'] = msg
        return result
Ejemplo n.º 2
0
 def etc_request_info_to_db(body: OBUModel):
     """
     请求体body入库
     """
     db_engine, db_session = create_db_session(
         sqlite_dir=CommonConf.SQLITE_DIR,
         sqlite_database='etc_deduct.sqlite')
     # etc_deduct_info_json入库
     DBClient.add(db_session=db_session,
                  orm=ETCRequestInfoOrm(
                      id=CommonUtil.random_str(32).lower(),
                      lane_num=body.lane_num,
                      trans_order_no=body.trans_order_no,
                      park_code=body.park_code,
                      plate_no=body.plate_no,
                      plate_color_code=body.plate_color_code,
                      plate_type_code=body.plate_type_code,
                      entrance_time=body.entrance_time,
                      park_record_time=body.park_record_time,
                      exit_time=body.exit_time,
                      deduct_amount=body.deduct_amount,
                      receivable_total_amount=body.receivable_total_amount,
                      discount_amount=body.discount_amount,
                      flag=0,
                  ))
     db_session.close()
     db_engine.dispose()
Ejemplo n.º 3
0
    def etc_toll(rsu_client: RsuSocket):
        # TimingJob.start_scheduler(rsu_client)
        while True:
            time.sleep(random.choice(range(1, 4)))
            now = datetime.now()
            # 查询天线的计费状态,charge=1开启计费,charge=0关闭计费
            rsu_charge = DBRsuCharge.query_rsu_charge()

            # 有接收到数据,表明天线还在工作,更新心跳时间
            rsu_client.rsu_heartbeat_time = datetime.now()
            DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库

            # 查询数据库订单
            _, db_session = create_db_session(
                sqlite_dir=CommonConf.SQLITE_DIR,
                sqlite_database='etc_deduct.sqlite')
            query_item: ETCRequestInfoOrm = db_session.query(
                ETCRequestInfoOrm).filter(
                    and_(
                        ETCRequestInfoOrm.lane_num == rsu_client.lane_num,
                        ETCRequestInfoOrm.create_time >
                        (datetime.now() - timedelta(seconds=10)),
                        ETCRequestInfoOrm.flag == 0)).first()
            # TODO  收到etc扣费请求,但是车上没有obu
            logger.info('当前时间:{}'.format(datetime.now()))
            # 找到订单开始扣费
            if query_item:
                logger.info('开始扣费。。。。。。')
                logger.info('{}, {}'.format(query_item.create_time,
                                            query_item.flag))
                etc_result = EtcToll.toll(query_item, rsu_client)

                etc_result['flag'] = False if random.randint(0,
                                                             3) == 0 else True
                query_item.flag = 1

                if etc_result['flag']:
                    logger.info(
                        '...................扣费成功........................')
                    query_item.deduct_status = EtcDeductStatus.SUCCESS
                else:
                    logger.info(
                        '...................扣费失败........................')
                    query_item.deduct_status = EtcDeductStatus.FAIL
                # 数据修改好后提交
                try:
                    db_session.commit()
                except:
                    db_session.rollback()
                    logger.error(traceback.format_exc())

            else:
                # 没有查询到订单,pass
                pass
            db_session.close()
Ejemplo n.º 4
0
    def check_rsu_heartbeat(callback):
        """
        检测天线心跳状态, 心跳停止过长,重启天线
        @return:
        """
        # 定义要上传的天线心跳字典
        upload_rsu_heartbeat_dict = dict(park_code=CommonConf.ETC_CONF_DICT['etc'][0]['park_code'],
                                         dev_code=CommonConf.ETC_CONF_DICT['dev_code'],  # 设备编号,运行本代码的机器编号,非天线
                                         status_code='11',  # 11:正常,00:暂停收费,01:故障, 默认正常
                                         rsu_broke_list=[],
                                         black_file_version='0',
                                         black_file_version_incr='0'
                                         )
        db_engine, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                                  sqlite_database='etc_deduct.sqlite')
        rsu_info_orms = db_session.query(RSUInfoOrm).all()
        rsu_pids = list()
        now = datetime.datetime.now()
        for rsu_infor_orm in rsu_info_orms:
            rsu_pids.append(rsu_infor_orm.pid)
            time_diff_seconds = (now - rsu_infor_orm.heartbeat_latest).seconds
            # 查看天线状态,status=0需要重启etc扣费,一般socket监听超时会更新RSUInfoOrm的status为0
            if (rsu_infor_orm.status == 0) or (time_diff_seconds >= 60):
                logger.error('park_code: {}, lane_num: {} 的最新心跳时间: {},距离当前已过:{}s'.format(
                    rsu_infor_orm.park_code,
                    rsu_infor_orm.lane_num,
                    rsu_infor_orm.heartbeat_latest,
                    time_diff_seconds))
                upload_rsu_heartbeat_dict['rsu_broke_list'].append(rsu_infor_orm.sn)

        if upload_rsu_heartbeat_dict['rsu_broke_list']:
            upload_rsu_heartbeat_dict['status_code'] = '01'
            logger.error('天线 {} 出现故障'.format(','.join(upload_rsu_heartbeat_dict['rsu_broke_list'])))
            # 结束进程
            logger.info('*********************kill pid: {}*************************************'.format(
                ','.join([str(item) for item in rsu_pids])))
            CommonUtil.kill_process_by_pid(rsu_pids)
            logger.info("==================重启天线服务================")
            RsuStatus.restart_rsu_control()
            # rsu_script_filename = 'main2.py'
            # # 找出进程号
            # pids = CommonUtil.query_pids(rsu_script_filename)
            # if pids:
            #     os.system('kill -9 {}'.format(pids)) # 杀死进程
            #     logger.info('kill -9 {}'.format(pids))
            # # 重启天线
            # rsu_script_path = os.path.join(CommonConf.ROOT_DIR, rsu_script_filename)
            # os.system('nohup python3 {} &'.format(rsu_script_path))
        else:
            logger.info('。。。。。。。。。天线心跳正常。。。。。。。。。')

        callback(upload_rsu_heartbeat_dict)
Ejemplo n.º 5
0
 def update_rsu_heartbeat(rsu_client: RsuSocket):
     """
     更新天线心跳时间
     """
     db_engine, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                               sqlite_database='etc_deduct.sqlite')
     query_item: RSUInfoOrm = db_session.query(RSUInfoOrm).filter(RSUInfoOrm.lane_num == rsu_client.lane_num).first()
     query_item.heartbeat_latest = rsu_client.rsu_heartbeat_time
     # 数据修改好后提交
     try:
         db_session.commit()
     except:
         db_session.rollback()
     db_session.close()
Ejemplo n.º 6
0
def clear_table():
    """
    清空数据表
    """
    _, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                      sqlite_database='etc_deduct.sqlite')
    try:
        db_session.query(RSUInfoOrm).delete()
        db_session.commit()
    except:
        db_session.rollback()
        logger.error(traceback.format_exc())
    finally:
        db_session.close()
Ejemplo n.º 7
0
    def check_rsu_heartbeat(callback):
        """
        检测天线心跳状态, 心跳停止过长,重启天线
        @return:
        """
        # 定义要上传的天线心跳字典
        upload_rsu_heartbeat_dict = dict(
            park_code=CommonConf.ETC_CONF_DICT['etc'][0]['park_code'],
            dev_code=CommonConf.
            ETC_CONF_DICT['dev_code'],  # 设备编号,运行本代码的机器编号,非天线
            status_code='11',  # 11:正常,00:暂停收费,01:故障, 默认正常
            rsu_broke_list=[],
            black_file_version='0',
            black_file_version_incr='0')
        db_engine, db_session = create_db_session(
            sqlite_dir=CommonConf.SQLITE_DIR,
            sqlite_database='etc_deduct.sqlite')
        rsu_info_orms = db_session.query(RSUInfoOrm).all()
        now = datetime.datetime.now()
        rsu_pids = list()
        for rsu_infor_orm in rsu_info_orms:
            rsu_pids.append(rsu_infor_orm.pid)
            time_diff_seconds = (now - rsu_infor_orm.heartbeat_latest).seconds
            # 如果三分钟没有心跳,需要重启etc扣费
            # if time_diff_seconds >= CommonConf.ETC_HEARTBEAT_TIME_OUT or rsu_infor_orm.status == 0:
            if rsu_infor_orm.status == 0:
                logger.error(
                    'park_code: {}, lane_num: {} 的最新心跳时间: {},距离当前已过:{}s'.
                    format(rsu_infor_orm.park_code, rsu_infor_orm.lane_num,
                           rsu_infor_orm.heartbeat_latest, time_diff_seconds))
                upload_rsu_heartbeat_dict['rsu_broke_list'].append(
                    rsu_infor_orm.sn)

        if upload_rsu_heartbeat_dict['rsu_broke_list']:
            upload_rsu_heartbeat_dict['status_code'] = '01'
            logger.error('天线 {} 出现故障'.format(','.join(
                upload_rsu_heartbeat_dict['rsu_broke_list'])))
            # 结束进程
            logger.info(
                '*********************kill pid: {}*************************************'
                .format(','.join([str(item) for item in rsu_pids])))
            CommonUtil.kill_process_by_pid(rsu_pids)
            logger.info("==================重启天线服务================")
            # TODO
            RsuStatus.restart_rsu_control()
        else:
            logger.info('。。。。。。。。。天线心跳正常。。。。。。。。。')

        callback(upload_rsu_heartbeat_dict)
Ejemplo n.º 8
0
    def rsu_info_to_db(lane_num, park_code, sn):
        """
        天线数据入库
        """
        db_engine, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                                  sqlite_database='etc_deduct.sqlite')

        DBClient.add(db_session=db_session,
                     orm=RSUInfoOrm(id=CommonUtil.random_str(32).lower(),
                                    lane_num=lane_num,
                                    park_code=park_code,
                                    sn=sn,
                                    heartbeat_latest=datetime.now()
                                    ))
        db_session.close()
        db_engine.dispose()
Ejemplo n.º 9
0
 def upload_vehicle_plate_no(park_code, plate_no, plate_color):
     """
     上传车辆信息
     @param vehicle_info_json:
     @return:
     """
     params = dict(park_code=park_code,
                   plate_no=plate_no,
                   plate_color_code=str(int(plate_color, 16)),
                   record_time=CommonUtil.timestamp_format(
                       int(time.time()), format='%Y%m%d%H%M%S'))
     vehicle_info_dict = dict(method='passThrough', params=params)
     vehicle_info_json = json.dumps(vehicle_info_dict, ensure_ascii=False)
     # # 如果上传成功upload_flag=1, 上传失败upload_flag=0, 默认上传失败
     upload_flag = 0
     # 业务编码报文
     # 将data 值base64 后,使用SHA256WithRSA 计算签名
     sign = XlapiSignature.to_sign_with_private_key(
         vehicle_info_json, private_key=ThirdEtcApi.PRIVATE_KEY)
     upload_body = dict(appid=ThirdEtcApi.APPID,
                        data=vehicle_info_json,
                        sign=sign.decode(encoding='utf8'))
     logger.info('上传车辆信息: {}'.format(vehicle_info_json))
     try:
         res = http_session.post(ThirdEtcApi.ETC_UPLOAD_URL,
                                 data=upload_body)
         if res.json()['code'] == '000000':
             upload_flag = 1
         logger.info(res.json())
     except:
         logger.error(traceback.format_exc())
     upload_fail_count = 0 if upload_flag else 1
     if not upload_flag:
         db_engine, db_session = create_db_session(
             sqlite_dir=CommonConf.SQLITE_DIR,
             sqlite_database='etc_deduct.sqlite')
         # etc_deduct_info_json入库
         DBClient.add(db_session=db_session,
                      orm=VehicleInfoOrm(
                          id=CommonUtil.random_str(32).lower(),
                          vehicle_info=vehicle_info_json,
                          upload_flag=upload_flag,
                          upload_fail_count=upload_fail_count))
         db_session.close()
         db_engine.dispose()
     return upload_flag, upload_fail_count
Ejemplo n.º 10
0
 def update_rsu_pid_status(rsu_client: RsuSocket, status):
     """
     :param status: 1 表示天线正常工作, 0表示异常
     """
     logger.info('lane_num: {} 出现异常'.format(rsu_client.lane_num))
     db_engine, db_session = create_db_session(
         sqlite_dir=CommonConf.SQLITE_DIR,
         sqlite_database='etc_deduct.sqlite')
     query_item: RSUInfoOrm = db_session.query(RSUInfoOrm).filter(
         RSUInfoOrm.lane_num == rsu_client.lane_num).first()
     query_item.status = status
     # 数据修改好后提交
     try:
         db_session.commit()
     except:
         db_session.rollback()
     db_session.close()
Ejemplo n.º 11
0
    def query_rsu_charge():
        """
        查询是否启用天线扣费状态, rsu_charge_on_off的chage=1,开启扣费模式, charge=0,关闭扣费模式
        """
        db_engine, db_session = create_db_session(
            sqlite_dir=CommonConf.SQLITE_DIR,
            sqlite_database='etc_deduct.sqlite')
        query_item: RsuChargeOnOffOrm = db_session.query(
            RsuChargeOnOffOrm).first()
        if not query_item:
            query_item = RsuChargeOnOffOrm(
                id=CommonUtil.random_str(32).lower(),
                charge=1,
                update_time=datetime.now())
            DBClient.add(db_session=db_session, orm=query_item)

        return query_item.charge
Ejemplo n.º 12
0
 def etc_upload_and_addto_db(handle_data_result, body: dict):
     """
     通知抬杆, 上传etc数据,并将etc数据存入本地
     :param handle_data_result:
     :param body:
     :return:
     """
     params = handle_data_result['data']
     exit_time = handle_data_result['exit_time']
     park_code = body['park_code']
     etc_deduct_info_dict = {"method": "etcPayUpload",
                             "params": params}
     # 业务编码报文json格式
     etc_deduct_info_json = json.dumps(etc_deduct_info_dict, ensure_ascii=False)
     logger.info('=' * 160)
     logger.info(etc_deduct_info_json)
     # 进行到此步骤,表示etc扣费成功,如果etc_deduct_notify_url不为空,通知抬杆
     if CommonConf.ETC_CONF_DICT['thirdApi']['etc_deduct_notify_url']:
         payTime = CommonUtil.timeformat_convert(exit_time, format1='%Y%m%d%H%M%S', format2='%Y-%m-%d %H:%M:%S')
         res_etc_deduct_notify_flag = ThirdEtcApi.etc_deduct_notify(park_code, body['trans_order_no'],
                                                                    body['discount_amount'], body['deduct_amount'],
                                                                    payTime)
     else:
         res_etc_deduct_notify_flag = True
     logger.info('=' * 160)
     if res_etc_deduct_notify_flag:
         # 接收到强哥返回值后,上传etc扣费数据
         logger.info('=' * 160)
         upload_flag, upload_fail_count = ThirdEtcApi.etc_deduct_upload(etc_deduct_info_json)
         db_engine, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                                   sqlite_database='etc_deduct.sqlite')
         # etc_deduct_info_json入库
         DBClient.add(db_session=db_session,
                      orm=ETCFeeDeductInfoOrm(id=CommonUtil.random_str(32).lower(),
                                              trans_order_no=body['trans_order_no'],
                                              etc_info=etc_deduct_info_json,
                                              upload_flag=upload_flag,
                                              upload_fail_count=upload_fail_count))
         db_session.close()
         db_engine.dispose()
Ejemplo n.º 13
0
 def update_rsu_charge_on_off(charge=1, update_time=datetime.now()):
     """
     更新表rsu_charge_on_off
     """
     _, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                       sqlite_database='etc_deduct.sqlite')
     query_item: RsuChargeOnOffOrm = db_session.query(
         RsuChargeOnOffOrm).first()
     if query_item:
         query_item.charge = charge
         query_item.update_time = update_time
         # 数据修改好后提交
         try:
             db_session.commit()
         except:
             db_session.rollback()
         db_session.close()
     else:
         DBClient.add(db_session=db_session,
                      orm=RsuChargeOnOffOrm(
                          id=CommonUtil.random_str(32).lower(),
                          charge=charge,
                          update_time=update_time))
Ejemplo n.º 14
0
 def etc_request_info_to_db(body: OBUModel):
     """
     请求体body入库
     """
     if CommonConf.ETC_CONF_DICT['wugan'] == 'true':
         is_white = WuGan.is_white(
             park_code=CommonConf.ETC_CONF_DICT['etc'][0]['park_code'],
             plate_no=body.plate_no,
             plate_color_code=body.plate_color_code)
         is_white = 1 if is_white else 0
     else:
         is_white = 0
     db_engine, db_session = create_db_session(
         sqlite_dir=CommonConf.SQLITE_DIR,
         sqlite_database='etc_deduct.sqlite')
     # etc_deduct_info_json入库
     DBClient.add(db_session=db_session,
                  orm=ETCRequestInfoOrm(
                      id=CommonUtil.random_str(32).lower(),
                      lane_num=body.lane_num,
                      trans_order_no=body.trans_order_no,
                      park_code=body.park_code,
                      plate_no=body.plate_no,
                      plate_color_code=body.plate_color_code,
                      plate_type_code=body.plate_type_code,
                      entrance_time=body.entrance_time,
                      park_record_time=body.park_record_time,
                      exit_time=body.exit_time,
                      deduct_amount=body.deduct_amount,
                      receivable_total_amount=body.receivable_total_amount,
                      discount_amount=body.discount_amount,
                      is_white=is_white,
                      flag=0,
                      deduct_status=EtcDeductStatus.DEDUCTING,
                  ))
     db_session.close()
     db_engine.dispose()
Ejemplo n.º 15
0
    def etc_toll(rsu_client: RsuSocket):
        cache_time = datetime.now()
        while True:
            now = datetime.now()
            # 查询天线的计费状态,charge=1开启计费,charge=0关闭计费
            rsu_charge = DBRsuCharge.query_rsu_charge()
            if rsu_charge == 0:
                rsu_client.rsu_heartbeat_time = now  # 更新心跳
                DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
                time.sleep(30)
                continue

            # socket监听,接受数据
            try:
                msg_str = rsu_client.recv_msg_max_wait_time()
            except:
                err_msg = traceback.format_exc()
                logger.error(err_msg)
                time.sleep(10)
                DBOPeration.update_rsu_pid_status(rsu_client, 0)
                rsu_client.close_socket()
                rsu_client.init_rsu()
                continue
            # 有接收到数据,表明天线还在工作,更新心跳时间
            rsu_client.rsu_heartbeat_time = datetime.now()
            if CommonConf.ETC_MAKER == 'soulin':
                if msg_str[6:16] == 'b2ffffffff':  # 心跳指令
                    logger.info('lane_num:{}  心跳指令:{}, 天线时间:{}, 当前时间:{}'.format(rsu_client.lane_num, msg_str,
                                                                                rsu_client.rsu_heartbeat_time,
                                                                                datetime.now()))
                    DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
                    continue
                # # 检测到obu, 检测到obu时,会狂发b2指令,频繁的更新数据库,所以此种情况下不要更新天线心跳时间
                # if msg_str[6: 8] == 'b2':
                #     logger.info('lane_num:{}  检测到obu: {}'.format(rsu_client.lane_num, msg_str))
                # else:
                #     logger.info('lane_num:{}  接收到指令: {}'.format(rsu_client.lane_num, msg_str))
            elif CommonConf.ETC_MAKER == 'jinyi':
                if msg_str[8: 12] == 'b200':  # 心跳指令
                    logger.info('lane_num:{}  心跳指令:{}, 天线时间:{}, 当前时间:{}'.format(rsu_client.lane_num, msg_str,
                                                                                rsu_client.rsu_heartbeat_time,
                                                                                datetime.now()))
                    DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
                    continue
                elif msg_str[8: 12] == 'b201':
                    logger.error('射频初始化异常: {}'.format(msg_str))
                    break
                elif msg_str[8: 12] == 'b202':
                    logger.error('PSAM卡初始化异常或无卡: {}'.format(msg_str))
                    break
            elif CommonConf.ETC_MAKER == 'wanji':
                if msg_str[16: 20] == 'b100':
                    logger.info('lane_num:{}  心跳指令:{}, 天线时间:{}, 当前时间:{}'.format(rsu_client.lane_num, msg_str,
                                                                                rsu_client.rsu_heartbeat_time,
                                                                                datetime.now()))
                    DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
                    continue
                elif msg_str[16: 18] == 'b1':
                    logger.error('心跳出错:{}'.format(msg_str))
                    continue
            # 检测到obu会狂发指令,通过添加if语句可以控制每隔一秒打印日志
            if (datetime.now() - cache_time).seconds >= 1:
                logger.info('lane_num:{}  检测到obu: {}'.format(rsu_client.lane_num, msg_str))
                cache_time = datetime.now()

            # 查询数据库订单
            _, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                              sqlite_database='etc_deduct.sqlite')
            query_item: ETCRequestInfoOrm = db_session.query(ETCRequestInfoOrm).filter(
                and_(ETCRequestInfoOrm.lane_num == rsu_client.lane_num,
                     ETCRequestInfoOrm.create_time > (datetime.now() - timedelta(seconds=10)),
                     ETCRequestInfoOrm.flag == 0)).first()
            # 找到订单开始扣费
            if query_item:
                logger.info('开始扣费。。。。。。')
                logger.info('{}, {}'.format(query_item.create_time, query_item.flag))
                logger.info('{}'.format(query_item.park_code))
                try:
                    EtcToll.toll(query_item, rsu_client, db_session)
                except:
                    logger.error(traceback.format_exc())

            else:
                db_session.close()
Ejemplo n.º 16
0
            db_engine, db_session = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                                      sqlite_database='etc_deduct.sqlite')
            # etc_deduct_info_json入库
            DBClient.add(db_session=db_session,
                         orm=ETCFeeDeductInfoOrm(id=CommonUtil.random_str(32).lower(),
                                                 trans_order_no=body['trans_order_no'],
                                                 etc_info=etc_deduct_info_json,
                                                 upload_flag=upload_flag,
                                                 upload_fail_count=upload_fail_count))
            db_session.close()
            db_engine.dispose()


if __name__ == '__main__':
    # 查询数据库订单
    _, db_session1 = create_db_session(sqlite_dir=CommonConf.SQLITE_DIR,
                                       sqlite_database='etc_deduct.sqlite')
    query_item1: ETCRequestInfoOrm = db_session1.query(ETCRequestInfoOrm).filter(
        and_(ETCRequestInfoOrm.lane_num == '002',
             ETCRequestInfoOrm.create_time > (datetime.now() - timedelta(seconds=12000)),
             ETCRequestInfoOrm.flag == 0)).order_by(ETCRequestInfoOrm.create_time.desc()).first()

    # 找到订单开始扣费
    if query_item1:
        logger.info('开始扣费。。。。。。')
        logger.info('{}, {}'.format(query_item1.create_time, query_item1.flag))
        query_item1.flag = 3
        # 数据修改好后提交
        try:
            db_session1.commit()
        except:
            db_session1.rollback()
Ejemplo n.º 17
0
    def etc_toll(rsu_client: RsuSocket):
        # TimingJob.start_scheduler(rsu_client)
        while True:
            now = datetime.now()
            # 查询天线的计费状态,charge=1开启计费,charge=0关闭计费
            rsu_charge = DBRsuCharge.query_rsu_charge()
            if rsu_charge == 0:
                rsu_client.rsu_heartbeat_time = now  # 更新心跳
                DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
                time.sleep(30)
                continue

            # if 0 <= now.hour <= 4:  # 0:00-5:00和22:00-24:00关闭天线
            #     if rsu_client.rsu_on_or_off == StatusFlagConfig.RSU_ON:
            #         logger.info('-------------关闭天线---------------')
            #         rsu_client.close_socket()
            #         rsu_client.rsu_on_or_off = StatusFlagConfig.RSU_OFF
            #
            #     rsu_client.rsu_heartbeat_time = now  # 更新心跳
            #     DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
            #     time.sleep(60)
            #     logger.info('。。。当前天线处于休眠状态。。。')
            #     continue
            # elif rsu_client.rsu_on_or_off == StatusFlagConfig.RSU_OFF:   # 其它时间段打开天线
            #     logger.info('-------------打开天线---------------')
            #     rsu_client.init_rsu()
            #     rsu_client.rsu_on_or_off = StatusFlagConfig.RSU_ON

            # socket监听,接受数据
            try:
                msg_str = rsu_client.recv_msg_max_wait_time()
            except:
                err_msg = traceback.format_exc()
                logger.error(err_msg)
                if err_msg.find('远程主机强迫关闭了一个现有的连接') != -1 or err_msg.find(
                        '你的主机中的软件中止了一个已建立的连接') != -1:
                    time.sleep(30)
                else:
                    time.sleep(10)
                DBOPeration.update_rsu_pid_status(rsu_client, 0)
                rsu_client.close_socket()
                rsu_client.init_rsu()
                continue
            # 有接收到数据,表明天线还在工作,更新心跳时间
            rsu_client.rsu_heartbeat_time = datetime.now()
            if msg_str[6:16] == 'b2ffffffff':  # 心跳指令
                logger.info('lane_num:{}  心跳指令:{}, 天线时间:{}, 当前时间:{}'.format(
                    rsu_client.lane_num, msg_str,
                    rsu_client.rsu_heartbeat_time, datetime.now()))
                DBOPeration.update_rsu_heartbeat(rsu_client)  # 心跳更新入库
                continue
            # 检测到obu, 检测到obu时,会狂发b2指令,频繁的更新数据库,所以此种情况下不要更新天线心跳时间
            if msg_str[6:8] == 'b2':
                logger.info('lane_num:{}  检测到obu: {}'.format(
                    rsu_client.lane_num, msg_str))
            else:
                logger.info('lane_num:{}  接收到指令: {}'.format(
                    rsu_client.lane_num, msg_str))
            # 查询数据库订单
            _, db_session = create_db_session(
                sqlite_dir=CommonConf.SQLITE_DIR,
                sqlite_database='etc_deduct.sqlite')
            query_item: ETCRequestInfoOrm = db_session.query(
                ETCRequestInfoOrm).filter(
                    and_(
                        ETCRequestInfoOrm.lane_num == rsu_client.lane_num,
                        ETCRequestInfoOrm.create_time >
                        (datetime.now() - timedelta(seconds=10)),
                        ETCRequestInfoOrm.flag == 0)).first()
            # TODO  收到etc扣费请求,但是车上没有obu
            # 找到订单开始扣费
            if query_item:
                logger.info('开始扣费。。。。。。')
                logger.info('{}, {}'.format(query_item.create_time,
                                            query_item.flag))
                etc_result = EtcToll.toll(query_item, rsu_client)
                query_item.flag = 1

                if etc_result['flag']:
                    logger.info(
                        '...................扣费成功........................')
                    query_item.deduct_status = EtcDeductStatus.SUCCESS
                else:
                    logger.info(
                        '...................扣费失败........................')
                    query_item.deduct_status = EtcDeductStatus.FAIL
                # 数据修改好后提交
                try:
                    db_session.commit()
                except:
                    db_session.rollback()
                    logger.error(traceback.format_exc())

            else:
                # 没有查询到订单,pass
                pass
            db_session.close()
Ejemplo n.º 18
0
    def handle_data(self, body: VehicleOweOrm):
        """
        处理self.command_recv_set,也就是收到的天线的信息
        :param body: 接收到的数据
        :return:
        """
        # 结果存储
        result = dict(flag=False, data=None, error_msg=None)
        # TODO 待待删打印信息
        # self.command_recv_set.print_obu_info()
        # TODO 判断card_net和card_sn 物理卡号是否存在于黑名单中
        # card_sn_in_blacklist_flag, error_msg = self.card_sn_in_blacklist()
        # # 物理卡号存在于黑名单中直接返回
        # if card_sn_in_blacklist_flag:
        #     result['error_msg'] = error_msg
        #     return result
        # 入场时间戳格式化 yyyyMMddHHmmss
        entrance_time = body.entrance_time
        # 出场时间
        exit_time = body.exit_time
        # 交易时间格式化(yyyyMMddHHmmss)
        trans_time = self.command_recv_set.info_b5['TransTime']
        # 计算停车时长
        park_record_time = body.park_record_time
        # 交易后余额
        balance = self.command_recv_set.info_b5['CardRestMoney']
        # 交易前余额 1999918332 单位分
        trans_before_balance = self.command_recv_set.info_b4['CardRestMoney']
        if CommonConf.ETC_CONF_DICT['debug'] == 'true':
            deduct_amount = 0.01
        else:
            deduct_amount = body.deduct_amount

        card_net_no = self.command_recv_set.info_b4['CardNetNo']  # 网络编号
        # ETC 卡片类型 16 储值卡  17 记账卡,转换成十进制分别对应22,23
        card_type = str(int(self.command_recv_set.info_b4['CardType'], 16))
        # PSAM 卡编号 10字节
        try:
            psam_id = self.command_recv_set.info_ba['PsamSN']
        except:
            print(self.command_recv_set.info_ba)
        #  card_sn 物理卡号 8字节
        card_sn = psam_id[4:]
        # TODO 待确认
        logger.info('ETC 卡片类型(22:储值卡;23:记账卡): {}'.format(card_type))
        params = dict(
            algorithm_type="1",
            # TODO 金额位数待确定
            balance=CommonUtil.hex_to_etcfee(balance, unit='fen'),  # 交易后余额
            # TODO 待确认
            card_net_no=card_net_no,  # 网络编号
            card_rnd=CommonUtil.random_str(8),  # 卡内随机数
            card_serial_no=self.command_recv_set.
            info_b5['ETCTradNo'],  # 卡内交易序号
            card_sn=card_sn,
            # self.command_recv_set.info_b4['CardID'],  # "1030230218354952",ETC 支付时与卡物理号一致;非 ETC 时上传车牌号
            card_type=card_type,  # "23",  # ETC 卡片类型(22:储值卡;23:记账卡)
            charging_type="0",  # 扣费方式(0:天线 1:刷卡器)
            deduct_amount=CommonUtil.yuan_to_fen(deduct_amount),  # 扣款金额
            device_no=self.rsu_conf['device_no'],  # 设备号
            device_type=self.rsu_conf['device_type'],  # 设备类型(0:天线;1:刷卡器;9:其它)
            # TODO 折扣金额
            discount_amount=CommonUtil.yuan_to_fen(body.discount_amount),
            entrance_time=entrance_time,  # 入场时间 yyyyMMddHHmmss
            exit_time=exit_time,  # 交易时间(yyyyMMddHHmmss)
            issuer_identifier=self.command_recv_set.
            info_b4['IssuerIdentifier'].upper(),  # 发行商代码
            obu_id=self.command_recv_set.info_b4['ObuID'].upper(),  # OBU 序号编码
            park_code=self.rsu_conf['park_code'],  # 车场编号
            park_record_time=park_record_time,  # 停车时长,时间精确到秒, 6小时50分钟
            plate_color_code=body.
            plate_color,  # 车牌颜色编码 0:蓝色、1:黄色、2:黑色、3:白色、4:渐变绿色、5:黄绿双拼、6:绿色、7:蓝白渐变
            plate_no=body.plate_no,  # 车牌号码 "皖LX4652",
            # TODO 车辆类型编码 0:小车 1:大车 2:超大车
            plate_type_code=body.plate_type_code,
            psam_id=psam_id,  # PSAM 卡编号 "37010101000000295460"
            psam_serial_no=self.command_recv_set.
            info_b5['PSAMTransSerial'],  # PSAM 流水号 "00005BA2",
            # TODO 应收金额
            receivable_total_amount=CommonUtil.yuan_to_fen(
                body.receivable_total_amount),
            serial_number=self.command_recv_set.
            info_b4['ApplySerial'],  # 合同序列号"340119126C6AFEDE"
            tac=self.command_recv_set.info_b5['TAC'],  # 交易认证码
            terminal_id=self.command_recv_set.
            info_b5['PsamTerminalID'],  # 终端编号
            trans_before_balance=CommonUtil.hex_to_etcfee(
                trans_before_balance, unit='fen'),  # 交易前余额 1999918332 单位分
            # TODO 交易订单号 "6711683258167489287"
            trans_order_no=CommonUtil.random_str(16),  # body.trans_order_no,
            trans_time=trans_time,  # 交易时间
            # TODO 待确认
            trans_type='09',  # 交易类型(06:传统;09:复合)
            vehicle_type=str(
                int(self.command_recv_set.info_b4['VehicleClass'], 16))  # 收费车型
        )
        etc_deduct_info_dict = {"method": "etcPayUpload", "params": params}
        etc_deduct_info_json = json.dumps(etc_deduct_info_dict,
                                          ensure_ascii=False)
        logger.info(etc_deduct_info_json)
        # TODO 上传etc扣费数据
        upload_flag, upload_fail_count = ThirdEtcApi.etc_deduct_upload(
            etc_deduct_info_json)
        db_engine, db_session = create_db_session(
            sqlite_dir=CommonConf.SQLITE_DIR,
            sqlite_database='etc_deduct.sqlite')
        # etc_deduct_info_json入库
        DBClient.add(db_session=db_session,
                     orm=ETCFeeDeductInfoOrm(
                         id=CommonUtil.random_str(32).lower(),
                         etc_info=etc_deduct_info_json,
                         upload_flag=upload_flag,
                         upload_fail_count=upload_fail_count))
        db_session.close()
        db_engine.dispose()

        # 清除收集到的b2,b3, b4, b5
        self.command_recv_set.clear_info_b2345()
        result['flag'] = True
        result['data'] = params

        return result
Ejemplo n.º 19
0
    def handle_data(self, body: OBUModel):
        """
        处理self.command_recv_set,也就是收到的天线的信息
        :param body: 接收到的数据
        :return:
        """
        # 结果存储
        result = dict(flag=False, data=None, error_msg=None)
        # TODO 待待删打印信息
        # self.command_recv_set.print_obu_info()
        #  判断card_net和card_sn 物理卡号是否存在于黑名单中
        card_sn_in_blacklist_flag, error_msg = self.card_sn_in_blacklist()
        # 物理卡号存在于黑名单中直接返回
        if card_sn_in_blacklist_flag:
            result['error_msg'] = error_msg
            return result
        # 入场时间戳格式化 yyyyMMddHHmmss
        entrance_time = CommonUtil.timestamp_format(body.entrance_time,
                                                    format='%Y%m%d%H%M%S')
        # 交易时间格式化(yyyyMMddHHmmss)
        # exit_time = CommonUtil.timestamp_format(body.exit_time, format='%Y%m%d%H%M%S')
        exit_time = self.command_recv_set.info_b5['TransTime']
        exit_time_stamp = CommonUtil.str_to_timestamp(timestr=exit_time,
                                                      format='%Y%m%d%H%M%S')
        # 计算停车时长
        park_record_time = CommonUtil.time_difference(body.entrance_time,
                                                      exit_time_stamp)
        # 交易后余额
        balance = self.command_recv_set.info_b5['CardBalance']
        # 交易前余额 1999918332 单位分
        trans_before_balance = self.command_recv_set.info_b4['CardRestMoney']
        if CommonConf.ETC_CONF_DICT['debug'] == 'true':
            deduct_amount = 0.01
        else:
            deduct_amount = body.deduct_amount
        # 卡片发行信息
        issuer_info = self.command_recv_set.info_b4['IssuerInfo']
        # ETC 卡片类型(22:储值卡;23:记账卡), 位于issuer_info的16,17位, 16进制形式,需要转为10进制
        card_type = str(int(issuer_info[16:18], 16))
        # PSAM 卡编号
        psam_id = issuer_info[20:40]
        #  card_sn 物理卡号
        card_sn = psam_id[4:]
        # TODO 待确认
        logger.info('ETC 卡片类型(22:储值卡;23:记账卡): {}'.format(card_type))
        params = dict(
            algorithm_type="1",
            # TODO 金额位数待确定
            balance=CommonUtil.hex_to_etcfee(balance, unit='fen'),  # 交易后余额
            # TODO 待确认
            card_net_no=issuer_info[20:24],  # 网络编号
            card_rnd=CommonUtil.random_str(8),  # 卡内随机数
            card_serial_no=self.command_recv_set.
            info_b5['ICCPaySerial'],  # 卡内交易序号
            card_sn=card_sn,
            # self.command_recv_set.info_b4['CardID'],  # "1030230218354952",ETC 支付时与卡物理号一致;非 ETC 时上传车牌号
            card_type=card_type,  # "23",  # ETC 卡片类型(22:储值卡;23:记账卡)
            charging_type="0",  # 扣费方式(0:天线 1:刷卡器)
            deduct_amount=CommonUtil.yuan_to_fen(deduct_amount),  # 扣款金额
            device_no=self.rsu_conf['device_no'],  # 设备号
            device_type=self.rsu_conf['device_type'],  # 设备类型(0:天线;1:刷卡器;9:其它)
            discount_amount=CommonUtil.yuan_to_fen(
                body.discount_amount),  # 折扣金额
            entrance_time=entrance_time,  # 入场时间 yyyyMMddHHmmss
            exit_time=exit_time,  # 交易时间(yyyyMMddHHmmss)
            issuer_identifier=self.command_recv_set.
            info_b2['IssuerIdentifier'].upper(),  # 发行商代码
            obu_id=self.command_recv_set.info_b2['OBUID'].upper(),  # OBU 序号编码
            park_code=self.rsu_conf['park_code'],  # 车场编号
            park_record_time=park_record_time,  # 停车时长,时间精确到秒, 6小时50分钟
            plate_color_code=body.
            plate_color_code,  # 车牌颜色编码 0:蓝色、1:黄色、2:黑色、3:白色、4:渐变绿色、5:黄绿双拼、6:绿色、7:蓝白渐变
            plate_no=body.plate_no,  # 车牌号码 "皖LX4652",
            plate_type_code=body.plate_type_code,  # 车辆类型编码 0:小车 1:大车 2:超大车
            psam_id=psam_id,  # PSAM 卡编号 "37010101000000295460"
            psam_serial_no=self.command_recv_set.
            info_b5['PSAMTransSerial'],  # PSAM 流水号 "00005BA2",
            receivable_total_amount=CommonUtil.yuan_to_fen(
                body.receivable_total_amount),  # 应收金额
            serial_number=self.command_recv_set.
            info_b2['SerialNumber'],  # 合同序列号"340119126C6AFEDE"
            tac=self.command_recv_set.info_b5['TAC'],  # 交易认证码
            terminal_id=self.command_recv_set.info_b5['PSAMNo'],  # 终端编号
            trans_before_balance=CommonUtil.hex_to_etcfee(trans_before_balance,
                                                          unit='fen'),
            # 交易前余额 1999918332 单位分
            trans_order_no=body.trans_order_no,  # 交易订单号 "6711683258167489287"
            trans_type=self.command_recv_set.
            info_b5['TransType'],  # 交易类型(06:传统;09:复合)
            vehicle_type=str(int(
                self.command_recv_set.info_b3['VehicleClass']))  # 收费车型
        )
        etc_deduct_info_dict = {"method": "etcPayUpload", "params": params}
        # 业务编码报文json格式
        etc_deduct_info_json = json.dumps(etc_deduct_info_dict,
                                          ensure_ascii=False)
        # TODO 进行到此步骤,表示etc扣费成功,调用强哥接口
        payTime = CommonUtil.timeformat_convert(exit_time,
                                                format1='%Y%m%d%H%M%S',
                                                format2='%Y-%m-%d %H:%M:%S')
        res_etc_deduct_notify_flag = ThirdEtcApi.etc_deduct_notify(
            self.rsu_conf['park_code'], body.trans_order_no,
            body.discount_amount, body.deduct_amount, payTime)
        if res_etc_deduct_notify_flag:
            # 接收到强哥返回值后,上传etc扣费数据
            upload_flag, upload_fail_count = ThirdEtcApi.etc_deduct_upload(
                etc_deduct_info_json)
            db_engine, db_session = create_db_session(
                sqlite_dir=CommonConf.SQLITE_DIR,
                sqlite_database='etc_deduct.sqlite')
            # etc_deduct_info_json入库
            DBClient.add(db_session=db_session,
                         orm=ETCFeeDeductInfoOrm(
                             id=CommonUtil.random_str(32).lower(),
                             trans_order_no=body.trans_order_no,
                             etc_info=etc_deduct_info_json,
                             upload_flag=upload_flag,
                             upload_fail_count=upload_fail_count))
            db_session.close()
            db_engine.dispose()

        # 清除收集到的b2,b3, b4, b5
        self.command_recv_set.clear_info_b2345()
        result['flag'] = True
        result['data'] = params

        return result