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 + ")";
|
}
|
}
|