Files
jcgl/docs/07-外部集成与定时任务.md

9.1 KiB
Raw Permalink Blame History

07 外部集成与定时任务

1. Asterisk 电话/广播链路

1.1 角色

  • 叫乘执行者:AsteriskCallUtil。
  • 连接方式:Asterisk Manager Interface(AMI),使用定制版 asterisk-java 3.38.0-zfjia。
  • 会议桥:Conf-01。
  • 呼叫对象:
    • 值班台:Local/1701@from-internal(callcontrol.ami.console,默认 1009/1010)。
    • 房间:房间 sip_account(GY_ROOMS.sip_account)经 Local/1901@from-internal 呼入。
  • 串口:callcontrol.console.*(默认 COM1、9600),用于广播/话机控制。

1.2 配置项

callcontrol:
  ami:
    host: 127.0.0.1
    port: 7058
    user: ${AMI_USER}
    pwd: ${AMI_PASSWORD}
    console: 1010
    callduration: 180
  console:
    port: COM1
    baudrate: 9600
  recording:
    base-url: ...   # 录音回放地址

1.3 一次叫乘的时序

sequenceDiagram
    participant Q as Quartz WakeUpJob
    participant S as JcglService
    participant A as AsteriskCallUtil
    participant AMI as Asterisk AMI
    participant C as 值班台
    participant R as 房间话机

    Q->>S: 触发 JC/FJ/JCJS
    S->>A: makeWakeup(人员, 房间SIP)
    A->>A: 组装 TTS 文本
    A->>AMI: 呼叫 1701(值班台)
    A->>AMI: 呼叫 1901 + 房间 SIP
    AMI->>C: 接通
    AMI->>R: 接通并加入 Conf-01
    A->>AMI: 播放 TTS
    R-->>A: ConfbridgeJoin / Answered
    A->>S: ryzt=5(通话中)→ 挂断后 ryzt=3(待离寓)

1.4 TTS 文案

尊敬的{姓名},{公寓名称}提醒您,您值乘的{车次}次,接车方式是{接车方式},开车时间{开车时间},现在时间{当前时间},请您携带好随身物品,准备出乘。

车次、接车方式、时间会做口语化格式化(formatTrainCodeForSpeech / formatPickupModeForSpeech / formatTrainTimeForSpeech)。

1.5 超时与挂断

常量 值 说明
CALL_TIMEOUT_MS 30 秒 呼叫无应答超时
WAKEUP_ANSWERED_AUTO_HANGUP_SECONDS 40 秒 叫乘接通后自动挂断
SHOUT_CALL_ANSWERED_AUTO_HANGUP_SECONDS 30 秒 广播/喊话接通后自动挂断

事件监听:

  • ConfbridgeJoinEvent:入会,记录通道与接通。
  • ConfbridgeLeaveEvent:离会,清理跟踪。
  • NewCallerIdEvent:回填通道/主叫。
  • HangupEvent:挂断,若已接通且需跟踪则置 ryzt=3;未接通则进入未应答处理(转报警/复叫)。

录音:接通后记录录音文件名,追加到 GY_JCXX.recordfile;/jcgl/getRecordingConfig 返回回放地址。

1.6 停止/挂断

  • stopWakeupCall / stopWakeupCallAsync:挂断该人员所有跟踪通道、值班台/房间通道、Conf-01。
  • hangupTrackedCallsByRyid:只挂断跟踪到的通道。
  • isConferenceBusy:会议桥占用时任务延迟 60 秒。

2. 机务运安(BYXX)SOAP

2.1 接入方式

  • WSDL:classpath:/wsdl/PbResource.wsdl。
  • 生成客户端:byxx.resource.PbResource_Service / PbResource。
  • 服务实现:ByxxResourceService。

2.2 主要操作

操作 用途
getLocoHomeList 机务段列表
getDriverInfoBySectionCode 按段获取司机资料
getDriverInfoByWorkNo 按工号获取司机
getDriverPlanByTimeStr 按时间段获取乘务计划(叫乘快照来源)

2.3 计划字段映射

运安字段 快照字段
jobid + taskdicid id
driver1..driver4 ryid(一条计划拆成最多 4 条人员记录)
plantrainnum cc
model + loco jch
dispmancode h1
plandeptime kcsj
plancalltime jcsj(仅保留,最终叫乘时间按本地规则重算)
plandepstation jhcqdd
jobType(0 库出,其他站接) jcfs

2.4 调度

  • 每 5 分钟抓取一次(SynDataSchedule.getSynDataJob),窗口约 4 小时。
  • 每 5 天同步一次人员(SyncPersonData,仅 T 开头机务段)。
  • 抓取/匹配共用 CallDutyMatchLock,防止并发清表。
  • 匹配只处理 baseConfig.gyid 配置的公寓;一实例多公寓部署时,其他公寓不会自动匹配,需改造或拆实例。

2.5 已知限制

  • mergeSynJcXx 已停用(同 id 多司机导致 MERGE 重复)。
  • getRemoteSynJcXx 为桩实现,未恢复远程 HTTP 同步。
  • WSDL 地址与派班室/公寓编码硬编码(“通辽南公寓”“通辽南派班室”),多公寓部署需参数化。

3. 中心服务器 HTTP

场景 地址/配置 说明
人员资料拉取 http://10.32.112.153:52411/api/users?pagenum=N SynDataService.personData,分页拉取机务人员
人员变更推送 /synData/modifyPersonData 运安推送人员增量
公寓人员查询 /synData/getApartmentPersonData* 按公寓/工号/时间查询在寓人员
财务数据 /synData/synFinanceData 按 IP 解析公寓后返回余额数据
照片/静态资源 baseConfig.centerServerUrl / serverUrl 人员照片 URL 前缀

中心同步使用 HttpRequest(内部封装),未见超时/重试统一配置,排障时需关注网络与超时。

4. WebSocket

端点 用途
/websocket/{username} 通用推送(历史)
/jcwebsocket/{username} 叫乘主界面刷新/人员信息
/jlwebsocket/{username} 交路界面
/rlywebsocket/{username} 人员/入住相关
/MealsWebsocket/{username} 餐食订单

关键消息见 06-接口清单.md 第 9 节。服务端推送按 gyid 路由,"all" 广播。

5. Quartz 叫乘任务

项 说明
Job 类 quartz/WakeUpJob
调度管理 quartz/SchedulerManager
JobKey ryid + "JC" / "FJ" / "JCJS"
TriggerGroup gyid + fjh
触发方式 一次性 cron,精确到秒
优先级 JC=1、FJ=2、JCJS=3
并发控制 @DisallowConcurrentExecution
参数 JobParas(人员、房间、车次、时间、jcid 等)
执行前校验 jcid/fjh/叫乘时间 与库中一致才执行,否则跳过
合并执行 同房间/同车次合并为一个执行组,组长先叫
会议桥忙 延迟 60 秒
恢复 WakeupJobRecoveryRunner 在 ApplicationReadyEvent 后恢复未来任务

失败处理:

  • 任务内部异常写业务日志,不抛到 Quartz。
  • JCJS 挂断会议桥、置 ryzt=2、写报警记录。
  • 人工停止叫乘会取消该人员全部任务。

6. Spring @Scheduled 清单

类.方法 Cron 作用 状态
JcSchedule.notifyMissedCallWarnings 5 * * * * ?(每分钟第 5 秒) 超时未叫乘分级提醒(第 1/10/15 分钟) 启用
JcSchedule.triggerOverdueLeaveAlarms 15 * * * * ?(每分钟第 15 秒) 已应答但超时未离寓报警 启用
JcSchedule.syncJcXxData 0 0 0 * * ?(Asia/Shanghai) 归档已离寓满 7 天记录 启用
SynDataSchedule.getSynDataJob 0 */5 * * * ? 运安抓取 + 记录同步时间 + 触发匹配 启用
SynDataSchedule.synPersonDataJob 30 0 0 */5 * ? 每 5 天同步运安人员 启用
LeaveSnapshotCleanupSchedule.cleanupExpiredLeaveSnapshots ${leaveSnapshot.cleanupCron:0 30 2 * * ?} 清理过期离寓抓拍 启用
RechargeSchedule.* — 自动补助/充值 全部注释停用
JlSchedule.* — 交路定时同步 注释停用
LogSchedule.* — 日志清理 注释停用

7. 并发控制与幂等

机制 位置 说明
交路同步锁 CallDutyMatchLock + GY_CALL_DUTY_MATCH_LOCK 抓取/推送/匹配互斥,事务提交后释放
同步状态位 GY_SYN_JCXX_STATUS 只有 1 才能匹配
设备事件幂等 GYGL_LY_EVENT(device_code, device_event_id) 刷脸离寓重复请求直接返回已处理
报警去重 triggerLeaveAlarmIfPending 条件更新 同一次入住只触发一次离寓报警
提醒去重 route_notice_key / call_timeout_notice_key / missed_call_notice_key 同一节点只提醒一次
充值互斥 GY_YKT_CASH_REQUEST 条件更新 完成与取消只能成功一个
房间占用 refreshRoomOccupancy + 有效在寓明细 防止计数漂移
任务过期校验 WakeUpJob 执行前比对库中数据 防止旧任务误叫

8. 排障入口

  1. 叫乘没响:看 Quartz 任务是否存在(SchedulerManager 日志)→ AMI 连接 → 会议桥是否忙 → 房间 sip_account 是否为空 → 任务时间是否已过期被跳过。
  2. 叫乘响了但状态不变:看 AMI 事件(Join/Hangup)是否被正确匹配通道 → GY_JCXX.ryzt / recordfile。
  3. 运安计划没进来:看 5 分钟任务日志、GY_SYN_JCXX_STATUS、JWDATA_SYNC_LOG、WSDL 可达性。
  4. 匹配不上:核对 GY_YKT_RY.card_id 与 GY_SYN_JCXX.workno,以及人员是否在有效在寓状态、jllx 是否被人工锁定。
  5. 离寓报错:看抓拍配置 leaveSnapshot.*、事件幂等记录、GYGL_LY_EVENT。
  6. 设备指令不下发:看 GY_SB 是否有该设备、心跳是否带 deviceCode、指令是否已被置 deleted=1。