| New file |
| | |
| | | package com.ruoyi.integration.iotda.utils.tools; |
| | | |
| | | import com.ruoyi.integration.iotda.constant.SendTagConstant; |
| | | import com.ruoyi.integration.iotda.enums.ServiceIdMenu; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 充电桩指令收发日志 |
| | | * <p> |
| | | * 1、使用独立 logger(pile-command)输出到独立日志文件,与业务日志分离(见 logback.xml); |
| | | * 2、日志记录统一打印指令含义,格式:指令=中文含义(service_id); |
| | | * 3、心跳指令(上行 ping、下行 pong)不记录,避免日志量过大。 |
| | | */ |
| | | public class IotCommandLog { |
| | | |
| | | /** 独立日志 logger,输出到独立日志文件(logback.xml 中 pile-command 配置) */ |
| | | private static final Logger COMMAND_LOG = LoggerFactory.getLogger("pile-command"); |
| | | |
| | | /** 上行指令 service_id -> 中文含义 */ |
| | | private static final Map<String, String> UPLINK_MEANING = new HashMap<>(); |
| | | |
| | | static { |
| | | UPLINK_MEANING.put(SendTagConstant.ONLINE, "充电桩登录认证"); |
| | | UPLINK_MEANING.put(SendTagConstant.PING, "充电桩心跳包"); |
| | | UPLINK_MEANING.put(SendTagConstant.END_CHARGE, "充电结束"); |
| | | UPLINK_MEANING.put(SendTagConstant.ERROR_MESSAGE, "错误报文"); |
| | | UPLINK_MEANING.put(SendTagConstant.BILLING_MODE_VERIFY, "计费模型验证请求"); |
| | | UPLINK_MEANING.put(SendTagConstant.ACQUISITION_BILLING_MODE, "充电桩计费模型请求"); |
| | | UPLINK_MEANING.put(SendTagConstant.UPLOAD_REAL_TIME_MONITORING_DATA, "上传实时监测数据"); |
| | | UPLINK_MEANING.put(SendTagConstant.CHARGING_HANDSHAKE, "充电握手"); |
| | | UPLINK_MEANING.put(SendTagConstant.PARAMETER_SETTING, "参数配置"); |
| | | UPLINK_MEANING.put(SendTagConstant.BMS_ABORT, "充电阶段BMS中止"); |
| | | UPLINK_MEANING.put(SendTagConstant.MOTOR_ABORT, "充电阶段充电机中止"); |
| | | UPLINK_MEANING.put(SendTagConstant.BMS_DEMAND_AND_CHARGER_EXPORTATION, "充电过程BMS需求、充电机输出"); |
| | | UPLINK_MEANING.put(SendTagConstant.BMS_INFORMATION, "充电过程BMS信息"); |
| | | UPLINK_MEANING.put(SendTagConstant.CHARGING_PILE_STARTS_CHARGING, "充电桩主动申请启动充电"); |
| | | UPLINK_MEANING.put(SendTagConstant.PLATFORM_START_CHARGING_REPLY, "远程启机命令回复"); |
| | | UPLINK_MEANING.put(SendTagConstant.PLATFORM_STOP_CHARGING_REPLY, "远程停机命令回复"); |
| | | UPLINK_MEANING.put(SendTagConstant.TRANSACTION_RECORD, "交易记录"); |
| | | UPLINK_MEANING.put(SendTagConstant.UPDATE_BALANCE_REPLY, "余额更新应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.SYNCHRONIZE_OFFLINE_CARD_REPLY, "卡数据同步应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.CLEAR_OFFLINE_CARD_REPLY, "离线卡数据清除应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.QUERY_OFFLINE_CARD_REPLY, "离线卡数据查询应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.WORKING_PARAMETER_SETTING_REPLY, "充电桩工作参数设置应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.TIMING_SETTING, "对时设置"); |
| | | UPLINK_MEANING.put(SendTagConstant.SETUP_BILLING_MODEL_REPLY, "计费模型应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.GROUND_LOCK_REAL_TIME_DATA, "地锁数据上送"); |
| | | UPLINK_MEANING.put(SendTagConstant.CHARGING_PILE_RETURNS_GROUND_LOCK_DATA, "充电桩返回地锁数据"); |
| | | UPLINK_MEANING.put(SendTagConstant.PLATFORM_RESTART_REPLY, "远程重启应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.PLATFORM_REMOTE_UPDATE_REPLY, "远程更新应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.QR_CODE_DELIVERY_REPLY, "二维码下发应答"); |
| | | UPLINK_MEANING.put(SendTagConstant.SECURITY_DETECTION, "安全监测"); |
| | | UPLINK_MEANING.put(SendTagConstant.GUN_STATUS, "推送充电设备接口状态信息"); |
| | | UPLINK_MEANING.put(SendTagConstant.ORDER_STATUS, "推送充电状态信息"); |
| | | UPLINK_MEANING.put(SendTagConstant.ORDER_INFO, "推送充电订单信息"); |
| | | } |
| | | |
| | | private IotCommandLog() { |
| | | } |
| | | |
| | | /** |
| | | * 记录上行指令(设备 -> 平台) |
| | | * 心跳(ping)不记录 |
| | | * |
| | | * @param deviceNo 设备编号 |
| | | * @param serviceId 指令 service_id |
| | | * @param payload 报文内容 |
| | | */ |
| | | public static void uplink(String deviceNo, String serviceId, Object payload) { |
| | | if (SendTagConstant.PING.equals(serviceId)) { |
| | | // 心跳不记录日志 |
| | | return; |
| | | } |
| | | COMMAND_LOG.info("[上行] 设备={} 指令={} 报文={}", deviceNo, describeUplink(serviceId), payload); |
| | | } |
| | | |
| | | /** |
| | | * 记录下行指令(平台 -> 设备) |
| | | * 心跳应答(pong)不记录 |
| | | * |
| | | * @param deviceNo 设备编号 |
| | | * @param name 下发名称 |
| | | * @param serviceId 指令 service_id |
| | | * @param payload 报文内容 |
| | | */ |
| | | public static void downlink(String deviceNo, String name, String serviceId, Object payload) { |
| | | if (isPong(serviceId)) { |
| | | // 心跳应答不记录日志 |
| | | return; |
| | | } |
| | | COMMAND_LOG.info("[下行] 设备={} 指令={} 报文={}", deviceNo, describeDownlink(serviceId, name), payload); |
| | | } |
| | | |
| | | /** |
| | | * 记录下行指令下发失败 |
| | | * 心跳应答(pong)不记录 |
| | | * |
| | | * @param deviceNo 设备编号 |
| | | * @param name 下发名称 |
| | | * @param serviceId 指令 service_id |
| | | * @param payload 报文内容 |
| | | * @param error 失败原因 |
| | | */ |
| | | public static void downlinkFail(String deviceNo, String name, String serviceId, Object payload, String error) { |
| | | if (isPong(serviceId)) { |
| | | // 心跳应答不记录日志 |
| | | return; |
| | | } |
| | | COMMAND_LOG.error("[下行失败] 设备={} 指令={} 报文={} 错误={}", deviceNo, describeDownlink(serviceId, name), payload, error); |
| | | } |
| | | |
| | | /** |
| | | * 记录无法解析的上行原始报文(兜底) |
| | | * 报文解析失败时无法识别 service_id,不能判断是否为心跳,仍记录原始内容便于排查 |
| | | * |
| | | * @param deviceNo 设备编号 |
| | | * @param rawPayload 原始报文内容 |
| | | */ |
| | | public static void uplinkUnparsed(String deviceNo, Object rawPayload) { |
| | | COMMAND_LOG.info("[上行-原始报文] 设备={} 报文={}", deviceNo, rawPayload); |
| | | } |
| | | |
| | | /** 是否心跳应答(pong) */ |
| | | private static boolean isPong(String serviceId) { |
| | | return ServiceIdMenu.PONG.getValue().equals(serviceId); |
| | | } |
| | | |
| | | /** 上行指令含义:中文含义(service_id) */ |
| | | private static String describeUplink(String serviceId) { |
| | | String meaning = UPLINK_MEANING.get(serviceId); |
| | | if (meaning == null || meaning.isEmpty()) { |
| | | meaning = "未识别指令"; |
| | | } |
| | | return meaning + "(" + serviceId + ")"; |
| | | } |
| | | |
| | | /** 下行指令含义:中文含义(service_id) */ |
| | | private static String describeDownlink(String serviceId, String name) { |
| | | String meaning = null; |
| | | if (serviceId != null) { |
| | | for (ServiceIdMenu menu : ServiceIdMenu.values()) { |
| | | if (menu.getValue().equals(serviceId)) { |
| | | meaning = menu.getKey(); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | if (meaning == null || meaning.isEmpty()) { |
| | | meaning = (name == null || name.isEmpty()) ? "未识别指令" : name; |
| | | } |
| | | return meaning + "(" + serviceId + ")"; |
| | | } |
| | | } |