huang
2025-05-20 e5b578d2c586ca9f664e31d3759952752255fdd3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
package com.mes.service;
 
import com.mes.tools.HexConversion;
import com.mes.utils.HexUtil;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
 
import static com.mes.tools.HexConversion.*;
 
@Component
@Slf4j
public class ModbusTcp {
 
    //同IP下会有多个协议地址  key=地址区   PlcAgreement为协议内容  plcAgreements为协议组
    private Map<String,PlcAgreement> plcAgreement=new LinkedHashMap<String,PlcAgreement>();
    private String Ip;
    private int Port;
 
    public Socket socket =null;//通讯
    public String fileName ="";
    public ModbusTcp(){}
    public ModbusTcp(String Ip,int Port,String fileName){
        this.Ip=Ip;
        this.Port=Port;
        this.fileName=fileName;
        try {
            plcAgreement.put(this.fileName,new PlcAgreement(this.fileName));
        } catch (Exception e) {
            log.info("file error:"+this.fileName+",{}",e.getMessage());
        }
    }
    //连接
    public void connect(){
        try {
            this.socket=new Socket(Ip,Port);
            this.socket.setSoTimeout(1000);
        }catch (Exception e) {
            log.info("The IP address of the host cannot be determined:{}",e.getMessage());
        }
    }
    //关闭连接
    public void close(){
        try {
            this.socket.close();
        }catch (Exception e) {
            //log.info("连接关闭异常:{}",e.getMessage());
        }
    }
    //返回连接状态
    public boolean isConnect(){
        try {
            this.socket.isConnected();
        }catch (Exception e) {
            log.info("Connection status exception:{}",this.socket);
        }
        return false;
    }
 
    //读取数据
    public boolean read(PlcAgreement plcAgreement){
        try {
            if (!this.socket.isConnected()){
               // log.info("通讯连接失败:{}",this.socket.isConnected());
                return false;
            }
            int bufSizes = 0;
            byte[] msgs = new byte[2048];
            byte[] content = new byte[2048];
            //写入读取地址
            DataOutputStream outToServer = new DataOutputStream(this.socket.getOutputStream());
            outToServer.write(HexConversion.stringToInt(plcAgreement.requestHead));
            outToServer.flush();
            //读取内容
            DataInputStream in = new DataInputStream(this.socket.getInputStream());
            bufSizes = in.read(msgs);
            if(bufSizes<plcAgreement.plcAddressLength+9){
                log.info("Read byte length <1:{},content:{}",bufSizes,msgs);
                return false;
            }
            content=Arrays.copyOfRange(msgs,9,2048);
            //获取参数值
            Map<String, PlcParameter> plcParameters=plcAgreement.getPlcParameters();
            for (String key:plcParameters.keySet()){
                PlcParameter plcParameter=plcParameters.get(key);
                if("bit".equals(plcParameter.getType())){
                    byte font=content[plcParameter.getAddressStart()];
                    String[] fontBitString=String.format("%8s", Integer.toBinaryString((int)font)).replace(" ", "0").split("");
                    byte[] bit=new byte[1];
                    bit[0]=Byte.parseByte(fontBitString[plcParameter.getAddressLength()]);
                    plcParameter.setReadByte(bit);
                }else{
                    plcParameter.setReadByte(Arrays.copyOfRange(content,plcParameter.getAddressStart(),(plcParameter.getAddressStart()+plcParameter.getAddressLength())));
                }
            }
            return true;
        }catch (Exception e) {
            //log.info("读取异常:{}",plcAgreement);
        }
        return false;
    }
    //写入数据
    public void write(PlcParameter plcParameter){
        try {
            if (plcParameter.getWriteValue() != null && !"".equals(plcParameter.getWriteValue())) {
                //写入发送数据 0000 0000 0009 0110 0024 0001 02 0006
                byte []sendByte=new byte[13+plcParameter.getAddressLength()];
                byte []sendLength=intToBytesDesc(7+plcParameter.getAddressLength(),2);
                byte []sendAddress=intToBytesDesc(plcParameter.getAddressStart()/2,2);
                byte []sendFontLength=intToBytesDesc(plcParameter.getAddressLength()/2,2);
                byte []sendContent=plcParameter.getWriteByte();
                //byte []sendContent=intToBytesDesc(Integer.parseInt(plcParameter.getWriteValue().toString()),plcParameter.getAddressLength());
                sendByte[4]=sendLength[0];
                sendByte[5]=sendLength[1];
                sendByte[6]=(byte)1;
                sendByte[7]=(byte)16;
                sendByte[8]=sendAddress[0];
                sendByte[9]=sendAddress[1];
                sendByte[10]=sendFontLength[0];
                sendByte[11]=sendFontLength[1];
                sendByte[12]=(byte)plcParameter.getAddressLength();
                for(int i=0;i<sendContent.length;i++){
                    sendByte[i+13]=sendContent[i];
                }
                log.info("sendByte:{}",sendByte);
                DataOutputStream out = new DataOutputStream(this.socket.getOutputStream());
                out.write(sendByte);
                out.flush();
                //log.info("sendByte:{}",sendByte);
 
            }
        } catch (IOException e) {
            log.info("写入数据异常:{}",plcParameter);
            throw new RuntimeException(e);
        }
    }
    //数据处理
    public void handleData(PlcParameter plcParameter){
        //写入发送数据 0000 0000 0009 0110 0024 0001 02 0006
        try {
            int sendLength=plcParameter.getAddressLength()+7;//发送长度
            byte [] addressLength=intToBytesDesc(plcParameter.getAddressLength(),1);//字节长度
            byte [] addressLengthFont=intToBytesDesc((plcParameter.getAddressLength()/2),2);//字长度
            byte start[]=intToBytesDesc(plcParameter.getAddressStart()/2,2);//起始地址
            byte content[]=intToBytesDesc(Integer.valueOf(plcParameter.getWriteValue().toString()) ,2);//起始地址
            if (sendLength>14&&
                    addressLength.length>0&&
                    addressLengthFont.length>1&&
                    start.length>1&&
                    content.length>1){
                byte head[]=new byte[]{0,0,0,(byte)sendLength,1,16,start[0],start[1],addressLengthFont[0],addressLengthFont[1],addressLength[0],content[0],content[1]};
                this.write(head);
            }else{
                log.info("发送内容不符合: 字节长度 {},字长度:{},起始地址,{},内容:{}",addressLength,addressLengthFont,start,content);
            }
        } catch (Exception e) {
            log.info("数据处理异常: 内容 {}",plcParameter);
        }
    }
    //写入数据
    public void write(byte []sendByte){
        try {
            if (sendByte != null) {
                //写入发送数据
                DataOutputStream out = new DataOutputStream(this.socket.getOutputStream());
                out.write(sendByte);
                out.flush();
                log.info("写入成功: 内容 {}",sendByte);
            }
        } catch (Exception e) {
            log.info("写入失败: 内容 {}",sendByte);
        }
    }
    //写入数据String
    public void writeString(String sendString,String startAddress){
        try {
            String result=message(sendString,startAddress);
            if (result != null && !"".equals(result)) {
                //写入数据
                DataOutputStream out = new DataOutputStream(socket.getOutputStream());
                out.write(HexUtil.stringToInt(result));
                out.flush();
                log.info("写入成功:地址 {},内容 {},字节:{}",startAddress,sendString,HexUtil.stringToInt(result));
                //this.close();
            }
        } catch (Exception e) {
            log.info("写入异常:地址 {},内容 {}",startAddress,sendString);
        }
    }
    //写
    public String message(String senddate, String address) {
        String Herd = "0110" + address;
        int length = senddate.length() / 4;
        String dates = Herd + HexUtil.intTo2ByteHex(length) + HexUtil.intTo1ByteHex(length * 2) + senddate;
        int lengths = dates.length() / 2;
        String date = "00000000" + HexUtil.intTo2ByteHex(lengths) + dates;
        return date;
    }
    public PlcAgreement getPlcAgreement(String key){
        return plcAgreement.get(key);
    }
 
    public void consoleLogInfo(PlcAgreement thisPlcAgreement){
        String logInfo=this.fileName+"  ";
        Map<String,PlcParameter> plcParameterMap=thisPlcAgreement.getPlcParameters();
        for (String key:plcParameterMap.keySet()) {
            logInfo+=key+":"+plcParameterMap.get(key).getValueString()+",";
        }
        log.info(logInfo);
    }
}