jiazx0107@163.com
2023-12-24 8efb5a8cd2c8a6b40e58f4f3fb851d54cf415af9
游仙协议解析-1
已修改5个文件
已添加7个文件
616 ■■■■■ 文件已修改
src/main/java/com/fzzy/api/data/GatewayDeviceProtocol.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/api/utils/BytesUtil.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/gateway/GatewayRunner.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/gateway/GatewayUtils.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/ProtocolUtils.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/ServiceUtils.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/analysis/AnalysisService.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/client/ClientEngine.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/client/ClientHandler.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/data/GrainRoot.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/package-info.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/fzzy/protocol/youxian0/service/Youxian0GatewayGrainService.java 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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) {
        
@@ -354,6 +331,7 @@
        
        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();
    }
}