src/main/java/com/fzzy/api/data/GatewayDeviceProtocol.java
@@ -15,6 +15,8 @@ GRAIN_FZZY_IGDS_V40("GRAIN_FZZY_IGDS_V40", "ç²®æ -飿£è´è¿ç³»ç»V40"), GRAIN_FZZY_BHZN_WEB("GRAIN_FZZY_BHZN_WEB", "ç²®æ -FZZY-馿µ·æºè½ç½å£åè®®"), GRAIN_FZZY_ZLDZ_WEB("GRAIN_FZZY_ZLDZ_WEB", "ç²®æ -FZZY-æ£æ¥çµåç½å£åè®®"), GRAIN_YOUXIAN0_2023("GRAIN_YOUXIAN0_2023", "ç²®æ -游ä»ä¸»åºåè®®"), GRAIN_YOUXIAN1_2023("GRAIN_YOUXIAN1_2023", "ç²®æ -游ä»ååºåè®®"), DEVICE_WEIGHT_HTTP("DEVICE_WEIGHT_HTTP", "å°ç£ -HTTPåè®®"), DEVICE_WEIGHT_TCP_YH("DEVICE_WEIGHT_TCP_YH", "å°ç£ -èåTCPåè®®"), DEVICE_IDCARD_HTTP("DEVICE_IDCARD_HTTP", "身份è¯-HTTPåè®®"), @@ -32,6 +34,9 @@ list.add(new ApiTrigger(GRAIN_FZZY_IGDS_V40.getCode(), GRAIN_FZZY_IGDS_V40.getName())); list.add(new ApiTrigger(GRAIN_FZZY_BHZN_WEB.getCode(), GRAIN_FZZY_BHZN_WEB.getName())); list.add(new ApiTrigger(GRAIN_FZZY_ZLDZ_WEB.getCode(), GRAIN_FZZY_ZLDZ_WEB.getName())); list.add(new ApiTrigger(GRAIN_YOUXIAN0_2023.getCode(), GRAIN_YOUXIAN0_2023.getName())); list.add(new ApiTrigger(GRAIN_YOUXIAN1_2023.getCode(), GRAIN_YOUXIAN1_2023.getName())); list.add(new ApiTrigger(DEVICE_WEIGHT_HTTP.getCode(), DEVICE_WEIGHT_HTTP.getName())); list.add(new ApiTrigger(DEVICE_WEIGHT_TCP_YH.getCode(), DEVICE_WEIGHT_TCP_YH.getName())); list.add(new ApiTrigger(DEVICE_IDCARD_HTTP.getCode(), DEVICE_IDCARD_HTTP.getName())); src/main/java/com/fzzy/api/utils/BytesUtil.java
@@ -320,29 +320,6 @@ return String.format("%04x", num).toUpperCase(); } // 计ç®16è¿å¶å¯¹åºçæ°å¼ public static int GetHex(char ch) throws Exception { if (ch >= '0' && ch <= '9') return (int) (ch - '0'); if (ch >= 'a' && ch <= 'f') return (int) (ch - 'a' + 10); if (ch >= 'A' && ch <= 'F') return (int) (ch - 'A' + 10); throw new Exception("error param"); } // 计ç®å¹ public static int GetPower(int nValue, int nCount) throws Exception { if (nCount < 0) throw new Exception("nCount can't small than 1!"); if (nCount == 0) return 1; int nSum = 1; for (int i = 0; i < nCount; ++i) { nSum = nSum * nValue; } return nSum; } public static void main(String[] args) { @@ -353,6 +330,7 @@ System.out.println(d2); System.out.println(d1 + d2); } src/main/java/com/fzzy/gateway/GatewayRunner.java
@@ -3,7 +3,6 @@ import com.fzzy.gateway.hx2023.service.ApiInitService; import com.fzzy.mqtt.MqttPublishService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; src/main/java/com/fzzy/gateway/GatewayUtils.java
@@ -4,7 +4,6 @@ import com.fzzy.api.data.ApiCommonDevice; import com.fzzy.api.data.GatewayDeviceType; import com.fzzy.gateway.entity.GatewayDevice; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import java.util.*; src/main/java/com/fzzy/protocol/ProtocolUtils.java
@@ -3,6 +3,7 @@ import com.fzzy.gateway.data.BaseReqData; import com.fzzy.protocol.data.THDto; import io.netty.channel.Channel; import java.util.HashMap; import java.util.Map; @@ -11,6 +12,10 @@ * å议解æå ¨å±å¸¸é */ public class ProtocolUtils { /** * 请æ±ç¼å key = deviceId,value = requData @@ -52,4 +57,5 @@ public static THDto getCacheTh(String deviceId) { return contextThMap.get(deviceId); } } src/main/java/com/fzzy/protocol/youxian0/ServiceUtils.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,26 @@ package com.fzzy.protocol.youxian0; /** * å·¥å ·ç±» */ public class ServiceUtils { //è·¯ç±=6A public static String FUNCTION_6A = "6a"; //æç´¢=62 public static String FUNCTION_62 = "6a"; //æµæ¸©=66 public static String FUNCTION_66 = "66"; //ä»å¤æ¹¿åº¦=67 public static String FUNCTION_67 = "67"; //ä»å 湿度=68 public static String FUNCTION_68 = "68"; } src/main/java/com/fzzy/protocol/youxian0/analysis/AnalysisService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,96 @@ package com.fzzy.protocol.youxian0.analysis; import com.fzzy.api.Constant; import com.fzzy.api.utils.BytesUtil; import com.fzzy.gateway.GatewayUtils; import com.fzzy.gateway.entity.GatewayDevice; import com.fzzy.protocol.ProtocolUtils; import com.fzzy.protocol.youxian0.ServiceUtils; import org.springframework.stereotype.Component; import java.net.InetAddress; /** * 游ä»ä¸»åºï¼è¿åæ¥æè§£æ */ @Component(AnalysisService.BEAN_ID) public class AnalysisService { public static final String BEAN_ID = "youxian0.analysisService"; /** * å议解æ * <p> * 7E 00 02 02 00 77 00 00 A0 FF FF 66 FF 04 BE 01 64 6A 6B 6A 68 CE 02 A4 BB BA BA B4 CE 03 E4 32 3D 32 3D CE 04 44 BC B3 BC B3 20 47 7E * * @param address * @param port * @param strMsg */ public void analysis(InetAddress address, int port, String strMsg) { //åæºID int start = 2 * 2; String deviceSn = strMsg.substring(start, start + 2); deviceSn = BytesUtil.hexToInt(deviceSn) + ""; //å½ä»¤ID start = 5 * 2; String msgIdHex = strMsg.substring(start, start + 2); int msgId = BytesUtil.hexToInt(msgIdHex); //å½ä»¤ç±»å start = 11 * 2; String funId = strMsg.substring(start, start + 2); GatewayDevice device = GatewayUtils.getCacheByDeviceSn(deviceSn); //ç²®æ è¿å if (ServiceUtils.FUNCTION_66.equalsIgnoreCase(funId)) { this.analysisGrain(device, msgId, strMsg); } } /** * ç²®æ è§£æ * <p> * 7E 00 02 02 00 77 00 00 A0 FF FF 66 FF 04 BE 01 64 6A 6B 6A 68 CE * 02 A4 BB BA BA B4 CE 03 E4 32 3D 32 3D CE 04 44 BC B3 BC B3 20 47 7E * * @param device * @param msgId å½ä»¤ID */ private void analysisGrain(GatewayDevice device, int msgId, String strMsg) { //åªä¿çç²®æ ä¿¡æ¯ int start = 22 * 2; strMsg = strMsg.substring(start); //å¯é¥åç¹æ° String kyeNumHex = strMsg.substring(2, 4); String kyeNumBin = BytesUtil.toBinary8String(BytesUtil.hexToInt(kyeNumHex)); String key = kyeNumBin.substring(0, 3); int keyValue = BytesUtil.hexToInt(BytesUtil.bin2Hex(key)); key = kyeNumBin.substring(4); int numValue = BytesUtil.hexToInt(BytesUtil.bin2Hex(key)); //02 A4 BB BA BA B4 start = 2 * 2; String tempHex; for (int i = 0; i < numValue; i++) { start = start + i * 2; tempHex = strMsg.substring(start, start + 2); //å®é 温度ï¼å¯é¥*å¯é¥*37(溢åºä¸ºæ 符å·åè)å弿å å¯åçæ¸©åº¦/2ã } } } src/main/java/com/fzzy/protocol/youxian0/client/ClientEngine.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,147 @@ package com.fzzy.protocol.youxian0.client; import com.fzzy.api.utils.BytesUtil; import com.fzzy.protocol.ProtocolUtils; import com.ld.io.api.InvokeResult; import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import io.netty.channel.*; import io.netty.channel.oio.OioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.oio.OioSocketChannel; import io.netty.handler.codec.bytes.ByteArrayDecoder; import io.netty.handler.codec.bytes.ByteArrayEncoder; import lombok.extern.slf4j.Slf4j; import java.util.HashMap; import java.util.Map; /** * 游ä»ä¸»åºï¼é讯åè®® */ @Slf4j public class ClientEngine implements Runnable { /** * 客æ·ç«¯æ¨¡å¼å建çè¿æ¥éé */ public static Map<String, Channel> clientChannelMap = new HashMap<>(); private String host; private int port; public Channel defaultChannel; public ClientEngine(String host, int port) { this.host = host; this.port = port; } public void start() { Thread thread = new Thread(this); thread.start(); } @Override public void run() { try { startClient(); } catch (Exception e) { e.printStackTrace(); } } public void startClient() throws Exception { EventLoopGroup group = new OioEventLoopGroup(); Bootstrap b = new Bootstrap(); //é»è®¤é¿è¿æ¥ b.option(ChannelOption.SO_KEEPALIVE, true); b.group(group).channel(OioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); // å符串解ç å ç¼ç p.addLast("decoder", new ByteArrayDecoder()); p.addLast("encoder", new ByteArrayEncoder()); // èªå·±çé»è¾Handler p.addLast("handler", new ClientHandler()); } }); // åèµ·å¼æ¥è¿æ¥è¯·æ±ï¼ç»å®è¿æ¥ç«¯å£åhostä¿¡æ¯ ChannelFuture channelFuture = b.connect(host, port); this.defaultChannel = channelFuture.channel(); // channelFuture.channel().closeFuture().sync(); this.add2ChannelMap(host, defaultChannel); channelFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture arg0) throws Exception { if (channelFuture.isSuccess()) { log.info("-----IP={},è¿æ¥æå"); } else { log.info("-----IP={},è¿æ¥å¤±è´¥ï¼èªå¨å ³é线ç¨"); channelFuture.cause().printStackTrace(); group.shutdownGracefully(); // å ³é线ç¨ç» } } }); } public InvokeResult send(byte[] array) throws InterruptedException { if (null == defaultChannel) { return InvokeResult.SOCKET_NOT_CREATE; } if (!defaultChannel.isActive()) { return InvokeResult.CHANNEL_CLOSED; } defaultChannel.writeAndFlush(Unpooled.copiedBuffer(array)).sync(); return InvokeResult.SUCCESS; } public Channel getChannel() { return defaultChannel; } public static void add2ChannelMap(String key, Channel channel) { clientChannelMap.put(key, channel); } /** * 妿 * * @param key * @return */ public static Channel getChannel(String key) { Channel channel = clientChannelMap.get(key); if (null == channel) return null; if (channel.isActive()) { return channel; } else { channel.close(); } return null; } public static InvokeResult send2(String hex,Channel channel) throws InterruptedException { if (null == channel) { return InvokeResult.SOCKET_NOT_CREATE; } if (!channel.isActive()) { return InvokeResult.CHANNEL_CLOSED; } channel.writeAndFlush(Unpooled.copiedBuffer(BytesUtil.hexStrToBytes(hex))).sync(); return InvokeResult.SUCCESS; } } src/main/java/com/fzzy/protocol/youxian0/client/ClientHandler.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,59 @@ package com.fzzy.protocol.youxian0.client; import com.fzzy.api.utils.BytesUtil; import com.fzzy.api.utils.SpringUtil; import com.fzzy.protocol.youxian0.analysis.AnalysisService; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import lombok.extern.slf4j.Slf4j; import java.net.InetSocketAddress; @Slf4j public class ClientHandler extends SimpleChannelInboundHandler<Object> { private AnalysisService analysisService; @Override public void channelActive(ChannelHandlerContext ctx) { InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel() .remoteAddress(); log.info("è¿æ¥ç»æåï¼IP={},port={}", socketAddress.getAddress() .getHostAddress(), socketAddress.getPort()); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress(); log.info("è¿æ¥ç»ç«¯æçº¿ï¼IP={},port={}", socketAddress.getAddress(), socketAddress.getPort()); } @Override public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { byte[] bytes = (byte[]) msg; InetSocketAddress socketAddress = (InetSocketAddress) ctx.channel().remoteAddress(); String strMsg = BytesUtil.bytesToString(bytes); log.info("ç»ç«¯è¿åä¿¡æ¯ï¼IP={},port={}ï¼msg={}", socketAddress.getAddress(), socketAddress.getPort(), strMsg); if (null == analysisService) { analysisService = SpringUtil.getBean(AnalysisService.class); } analysisService.analysis(socketAddress.getAddress(), socketAddress.getPort(), strMsg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); } } src/main/java/com/fzzy/protocol/youxian0/data/GrainRoot.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,19 @@ package com.fzzy.protocol.youxian0.data; import lombok.Getter; import lombok.Setter; @Getter @Setter public class GrainRoot { private long time = System.currentTimeMillis(); private int num; //éå·éå¼çæ¸©åº¦å¼ private String points; private String key; } src/main/java/com/fzzy/protocol/youxian0/package-info.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,4 @@ /** * 游ä»ä¸»åºï¼é讯åè®® */ package com.fzzy.protocol.youxian0; src/main/java/com/fzzy/protocol/youxian0/service/Youxian0GatewayGrainService.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,228 @@ 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 * <p> * 7e 01 00 00 01 00 00 02 00 01 a0 ff ff 66 ff 05 3a 59 7e * <p> * æµè¯ï¼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(); } }