package com.fzzy.protocol.youxian0.service; import com.fzzy.api.data.GatewayDeviceProtocol; import com.fzzy.api.utils.BytesUtil; import com.fzzy.gateway.api.GatewaySyncGranService; import com.fzzy.gateway.data.BaseReqData; import com.fzzy.gateway.data.BaseResp; import com.fzzy.gateway.entity.GatewayDevice; import com.fzzy.protocol.ProtocolUtils; import com.fzzy.protocol.youxian0.ServiceUtils; import com.fzzy.protocol.youxian0.client.ClientEngine; import com.ld.io.api.InvokeResult; import io.netty.channel.Channel; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * 游仙主库协议-粮情采集入口 */ @Slf4j @Component public class Youxian0GatewayGrainService implements GatewaySyncGranService { @Override public String getGrainProtocol() { return GatewayDeviceProtocol.GRAIN_YOUXIAN0_2023.getCode(); } /** * 发送[测温]命令 9精度的 返回温度数据是单个字节 * 发送数据: 7e 01 00 00 01 0b 00 02 00 01 a0 ff ff 66 ff 05 4e 83 7e * 接收数据: 00 01 01 00 0B 00 00 A0 FF FF 66 FF 05 BE 01 64 78 7B 79 79 CC 02 A4 A8 A8 A9 A8 (去掉7e头7e尾 去掉最后两位crc校验) * 杆号:1 [ 26.5 27.0 26.0 26.0 ] * 杆号:2 [ 26.0 27.0 26.0 26.0 ] * * @param reqData * @return */ @Override public BaseResp syncGrain(BaseReqData reqData) { BaseResp resp = new BaseResp(); GatewayDevice device = reqData.getDevice(); if (null == device) { resp.setCode(500); resp.setMsg("系统未获取到下行连接设备信息,无法执行"); log.error("----------------系统未获取到下行连接设备信息,无法执行---------"); return resp; } try { //Step 请求信息放入内存 ProtocolUtils.addSyncReq2Map(device.getDepotIdSys(), reqData); // 判断数据有没有收取完整 String[] attCable = device.getCableRule().split("-"); int cableY = Integer.valueOf(attCable[1]); int cableX = Integer.valueOf(attCable[2]); int start = 0, length = cableY; // 生成粮情信息 String hexStr = ""; InvokeResult message; for (int i = 1; i <= cableX; i++) { if (1 == i) start = 255; start = i * cableY + 1; hexStr = this.buildGrainCmd(device, i, start, length); // 发送命令 Channel channel = ClientEngine.getChannel(device.getIp()); if (null == channel) { ClientEngine clientEngine = new ClientEngine(device.getIp(), device.getPort()); clientEngine.start(); Thread.sleep(500); channel = clientEngine.getChannel(); } message = ClientEngine.send2(hexStr, channel); log.error("平台------>>>>控制柜:发送粮情检测命令-{}", message); // 封装返回信息 if (!InvokeResult.SUCCESS.getCode().equals(message.getCode())) { log.error("平台------>>>>控制柜:发送粮情检测命令-失败{}", message.getMessage()); resp.setCode(500); resp.setMsg("平台------>>>>控制柜:发送粮情检测命令-失败:" + message.getMessage()); } } } catch (Exception e) { log.error("粮情检测异常:{}", e); resp.setCode(500); resp.setMsg("平台------>>>>控制柜:发送粮情检测命令:" + e.getMessage()); return resp; } return resp; } /** * 生成粮情采集命令 * * @param device * @return */ private String buildGrainCmd(GatewayDevice device, int cur, int startCur, int length) { String start = "7e"; //测温命令--7e 01 00 00 01 00 00 02 00 01 a0 ff ff 66 ff 05 3a 59 7e String content = "{id}0000{id}{msgId}000200{id}a0ffff{funId}{start}{length}"; //开始封装消息体-主机ID String deviceSn = device.getDeviceSn(); deviceSn = BytesUtil.intToHexStr1(Integer.valueOf(deviceSn)); content = content.replaceAll("\\{id}", deviceSn); //命令ID String msgIdHex = BytesUtil.intToHexStr1(cur); content = content.replace("\\{msgId}", msgIdHex); //命令类型 content = content.replace("\\{funId}", ServiceUtils.FUNCTION_66); //开始根号 String startCurHex = BytesUtil.intToHexStr1(startCur); content = content.replace("\\{start}", startCurHex); //截取长度 String lenHex = BytesUtil.intToHexStr1(length); content = content.replace("\\{length}", lenHex); //校验码 String crcCode = this.getCRC(content); String end = "7e"; return start + content + crcCode + end; } /** * 参考结果:http://www.ip33.com/crc.html *
* 7e 01 00 00 01 00 00 02 00 01 a0 ff ff 66 ff 05 3a 59 7e *
* 测试:010000010000020001a0ffff66ff05 * 返回:3a59 * * @param content * @return */ private String getCRC(String content) { byte[] bytes = HexStringToBytes(content);//16进制字符串转成16进制字符串数组 int i = CRC16_XMODEM(bytes);//进行CRC—XMODEM校验得到十进制校验数 String CRC = Integer.toHexString(i);//10进制转16进制 //调整高位在右,地位在左侧 CRC = tran_LH(CRC); return CRC; } public static String tran_LH(String info) { return info.substring(2) + info.substring(0, 2); } public static int CRC16_XMODEM(byte[] buffer) { int wCRCin = 0x0000; // initial value 65535 int wCPoly = 0x1021; // 0001 0000 0010 0001 (0, 5, 12) for (byte b : buffer) { for (int i = 0; i < 8; i++) { boolean bit = ((b >> (7 - i) & 1) == 1); boolean c15 = ((wCRCin >> 15 & 1) == 1); wCRCin <<= 1; if (c15 ^ bit) wCRCin ^= wCPoly; } } wCRCin &= 0xffff; return wCRCin ^= 0x0000; } public static byte[] HexStringToBytes(String src) { int len = src.length() / 2; byte[] ret = new byte[len]; byte[] tmp = src.getBytes(); for (int i = 0; i < len; i++) { ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]); } return ret; } public static byte uniteBytes(byte src0, byte src1) { byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})) .byteValue(); _b0 = (byte) (_b0 << 4); byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})) .byteValue(); byte ret = (byte) (_b0 ^ _b1); return ret; } @Override public BaseResp syncConf(BaseReqData reqData) { return new BaseResp(); } @Override public BaseResp writeConf(BaseReqData reqData) { return new BaseResp(); } @Override public BaseResp initCable(BaseReqData reqData) { return new BaseResp(); } @Override public BaseResp disconnect(BaseReqData reqData) { return new BaseResp(); } @Override public BaseResp transparent(BaseReqData reqData) { return new BaseResp(); } }