本项目使用modbus4j-3.0.3.jar实现于PLC通讯。
实现与PLC连接并完成读写基本数据类型通讯测试不再赘述,本人参考了云逸的博客https://www.cnblogs.com/ioufev/p/10831289.html
直接进入主题,读写字符串
写入字符串
/**
* 测试程序
*
* @param slaveId
* @param offset
* @param dataType
* @param value
* @return
* @throws ModbusTransportException
* @throws ErrorResponseException
* @throws ModbusInitException
*/
public static boolean writeStrToPlc(int slaveId, int startOffset, String value) throws ModbusTransportException, ErrorResponseException, ModbusInitException {
// 获取master
ModbusMaster tcpMaster = getMaster();
short[] sdata = SetString(value);
// 创建请求对象
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
// 发送请求并获取响应对象
ModbusResponse response = tcpMaster.send(request);
if (response.isException()) {
// log.error(response.getExceptionMessage());
return false;
} else {
return true;
}
}
工具类方法 setString()主要进行了一下数据类型转换
public static short[] SetString(String value) {
byte[] bytesTemp = value.getBytes(StandardCharsets.UTF_8);
byte[] bytes;
if (bytesTemp.length % 2 > 0) {
bytes = Arrays.copyOf(bytesTemp, bytesTemp.length + 1);
} else {
bytes = bytesTemp;
}
return bytesToShort(bytes);
}
/**
* Byte数组转short数组
*
* @param bytes
* @return
*/
public static short[] bytesToShort(byte[] bytes) {
if (bytes == null) {
return null;
}
short[] shorts = new short[bytes.length / 2];
ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);
return shorts;
}
读取字符串
/**
*
* @param slaveId
* @param offset
* @param dataType
* @return
* @throws ModbusTransportException
* @throws ErrorResponseException
* @throws ModbusInitException
*/
public static String readHoldingRegisters(int slaveId, int offset, int dataType, int num)
throws ModbusTransportException, ErrorResponseException, ModbusInitException {
// 03 Holding Register类型数据读取
short[] data = new short[num];
for (int i = 0; i < num; i++) {
data[i] = readHoldingRegister(slaveId, offset + i, dataType).shortValue();
}
try {
return GetString(data, 0, num);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(Modbus4jReadUtils.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
工具类方法getString() 类型转换
/**
*
* @param src
* @param start
* @param len
* @return
*/
public static String GetString(short[] src, int start, int len) throws UnsupportedEncodingException
{
short[] temp = new short[len];
for (int i = 0; i < len; i++)
{
temp[i] = src[i + start];
}
byte[] bytesTemp = shorts2Bytes(temp);
for (int i = 0; i < bytesTemp.length; i++) {
byte b = bytesTemp[i];
}
String str = new String(bytesTemp, "UTF-8");
return str;
}
/**
*
* @param data
* @return
*/
public static byte [] shorts2Bytes(short [] data){
byte[] byteValue = new byte[data.length * 2];
for (int i = 0; i < data.length; i++) {
byteValue[i * 2] = (byte) (data[i] & 0xff);
byteValue[i * 2 + 1] = (byte) ((data[i] & 0xff00) >> 8);
}
return byteValue;
}
PLC本身并不直接支持字符串类型数据。这里只能将字符串进行转换后进行存储,读的时候也是一样,通过读入一段连续的寄存器地址数据,再转成字符串