package com.xxl.job.executor.sample.frameless;
import java.io.IOException;
import java.math.BigInteger;
public class FinalTest {
public static void main(String[] args) {
//模擬向2號寄存器寫入100
ModbusDataFormationBean modbusDataFormationBean=new ModbusDataFormationBean();
modbusDataFormationBean.setAddr(1);//地址1
modbusDataFormationBean.setFuncode(3);//功能碼5代表寫入寄存器
modbusDataFormationBean.setPortNumber(2);//2代表寄存器起始位為2
modbusDataFormationBean.setValue(100);//向2號寄存器寫入100
modbusDataFormationBean.setDataType(1);//1代表寫入的值是16位的
byte[] modbusData=ModbusTools.data(modbusDataFormationBean);//對象轉modbus數據
//模擬讀取返回的3個寄存器數據
//01030443686edf0393
byte[] data={(byte)0x01,(byte)0x03,(byte)0x06,(byte)0x01,(byte)0x67,(byte) 0xff,
(byte) 0xb5,(byte)0x00,(byte)0x64,(byte)0xd7,(byte)0x5e};
byte[] data2={(byte)0x01,(byte)0x03,(byte)0x04,(byte)0x43,(byte)0x68,(byte) 0x6e,
(byte) 0xdf,(byte)0x03,(byte)0x93};
//1. modbud存儲小數 byte數組 將兩個寄存器的值 轉成兩個十進制的整數 float
ModbusDataAnalyzeBean modbusDataAnalyzeBean =ModbusTools.dataAnalyze(data,1);
System.out.println("modbus數據解析為對象:"+modbusDataAnalyzeBean.toString());//modbus數據轉對象
ModbusDataAnalyzeBean modbusDataAnalyzeBean2 =ModbusTools.dataAnalyze(data2,1);
System.out.println("modbus數據解析為對象:"+modbusDataAnalyzeBean2.toString());//modbus數據轉對象
float v = ParseUtil.toFloat(modbusDataAnalyzeBean2.getValues().get(0).intValue(), modbusDataAnalyzeBean2.getValues().get(1).intValue());
System.out.println(v);
String str="43686edf";
int value = Integer.parseInt(str, 16);
value = ((value & 0x8000) > 0) ? (value - 0x10000) : (value );
float value1 = Float.intBitsToFloat(value);
System.out.println(value1);
//2. 十六進制 四個byte 4*8=32位 string轉float
float value2 = Float.intBitsToFloat(new BigInteger(str, 16).intValue());
System.out.println(value2);
//3. CRC校驗
//0103044368dddeb763
byte[] data3={(byte)0x01,(byte)0x03,(byte)0x04,(byte)0x43,(byte)0x68,(byte) 0xdd,
(byte) 0xde};
Integer crc162Int = ModbusTools.getCRC162Int(data3, true);
String result = Integer.toHexString(crc162Int);
System.out.println(result);
//4. 將十六進制的 字符串轉成byte數組
String str2="0103044368ddde";
int length = str2.length()/2;
byte[] bytes = ModbusTools.hexString2ByteArray(str2, length);
System.out.println(bytes);
//5. byte數組轉成float
try {
byte[] vs = new byte[]{0x41, (byte)0xd2, (byte)0x66, (byte)0x66};
System.out.println(ParseUtil.toFloat(vs));
byte[] vs2 = new byte[]{(byte)0xC1, (byte)0xd2, (byte)0x66, (byte)0x66};
System.out.println(ParseUtil.toFloat(vs2));
float v1 = ParseUtil.toFloat(vs2);
System.out.println(v1);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.xxl.job.executor.sample.frameless
public class ModbusTools {
/**
* modbus數據轉對象
* @param data 串口數據
* @param dataType 1代表16位讀取2個byte數據,2代表32位讀取4個byte數據
*/
public static ModbusDataAnalyzeBean dataAnalyze(byte []data, int dataType)
{
int readByteNum=0;//一次要讀取多少個byte
if (dataType==1)
{
readByteNum=2;
}
else if (dataType>1)
{
readByteNum=dataType*dataType;
}
ModbusDataAnalyzeBean modbusDataAnalyzeBean =new ModbusDataAnalyzeBean();
modbusDataAnalyzeBean.setAddr(Integer.parseInt(getOctFromHexBytes(data,0)));//獲取地址
modbusDataAnalyzeBean.setFuncode(Integer.parseInt(getOctFromHexBytes(data,1)));//獲取功能碼
modbusDataAnalyzeBean.setDataType(dataType);//數據類型
int byteNum=Integer.parseInt(getOctFromHexBytes(data,2));//統計有效byte數據個數
ArrayList<Double> arrayListVlaue=new ArrayList();
for (int n=1;n<(byteNum/readByteNum)+1;n++)
{
arrayListVlaue.add(Double.parseDouble(getOctFromHexBytes(data,3+readByteNum*(n-1),3+readByteNum*n-1)));//獲取值
}
modbusDataAnalyzeBean.setValues(arrayListVlaue);//將取到的值存進返回對象
return modbusDataAnalyzeBean;
}
/**
* 對象轉modbus數據
* @param modbusDataFormationBean
* @return
*/
public static byte[] data(ModbusDataFormationBean modbusDataFormationBean)
{
int readByteNum=0;//一次要讀取多少個byte
if (modbusDataFormationBean.getDataType()==1)
{
readByteNum=2;
}
else if (modbusDataFormationBean.getDataType()>1)
{
readByteNum=modbusDataFormationBean.getDataType()*modbusDataFormationBean.getDataType();
}
byte[] command=new byte[]{};
command = append(command,octInt2ByteArray( modbusDataFormationBean.getAddr(), 1));//設置地址
command = append(command,octInt2ByteArray( modbusDataFormationBean.getFuncode(), 1)); //設置功能碼
command = append(command,octInt2ByteArray( modbusDataFormationBean.getPortNumber(), 2));//設置寄存器起始地址
command = append(command,octInt2ByteArray( modbusDataFormationBean.getValue(), readByteNum));//設置數據值
command = append(command, octInt2ByteArray( getCRC162Int(command,true), 2) );// 設置CRC16校驗
return command;
}
/**
* 取得十制數組的from~to位,並按照十六進制轉化值
*
* @param data
* @param from
* @param to
* @return
*/
private static String getOctFromHexBytes(byte[] data, Object from, Object... to) {
if (data != null && data.length > 0 && from != null) {
try {
byte[] value;
int fromIndex = Integer.parseInt(from.toString());
if (to != null && to.length > 0) {
int toIndex = Integer.parseInt(to[0].toString());
if (fromIndex >= toIndex || toIndex <= 0) {
value = Arrays.copyOfRange(data, fromIndex, fromIndex + 1);
} else {
value = Arrays.copyOfRange(data, fromIndex, toIndex + 1);
}
} else {
value = Arrays.copyOfRange(data, fromIndex, fromIndex + 1);
}
if (value != null && value.length > 0) {
long octValue = 0L;
int j = -1;
for (int i = value.length - 1; i >= 0; i--, j++) {
int d = value[i];
if (d < 0) {
d += 256;
}
octValue += Math.round(d * Math.pow(16, 2 * j + 2));
}
return new Long(octValue).toString();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 十進制的字符串表示轉成字節數組
*
* @param octString
* 十進制格式的字符串
* @param capacity
* 需要填充的容量(可選)
* @return 轉換后的字節數組
**/
private static byte[] octInt2ByteArray(Integer oct, int... capacity) {
return hexString2ByteArray(Integer.toHexString(oct), capacity);
}
/**
* 16進制的字符串表示轉成字節數組
*
* @param hexString
* 16進制格式的字符串
* @param capacity
* 需要填充的容量(可選)
* @return 轉換后的字節數組
**/
public static byte[] hexString2ByteArray(String hexString, int... capacity) {
hexString = hexString.toLowerCase();
if (hexString.length() % 2 != 0) {
hexString = "0" + hexString;
}
int length = hexString.length() / 2;
if (length < 1) {
length = 1;
}
int size = length;
if (capacity != null && capacity.length > 0 && capacity[0] >= length) {
size = capacity[0];
}
final byte[] byteArray = new byte[size];
int k = 0;
for (int i = 0; i < size; i++) {
if (i < size - length) {
byteArray[i] = 0;
} else {
byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
if (k + 1 < hexString.length()) {
byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
byteArray[i] = (byte) (high << 4 | low);
} else {
byteArray[i] = (byte) (high);
}
k += 2;
}
}
return byteArray;
}
/**
* 連接字節流
*
* @return
*/
private static byte[] append(byte[] datas, byte[] data) {
if (datas == null) {
return data;
}
if (data == null) {
return datas;
} else {
return concat(datas, data);
}
}
/**
* 字節流拼接
*
* @param data
* 字節流
* @return 拼接后的字節數組
**/
private static byte[] concat(byte[]... data) {
if (data != null && data.length > 0) {
int size = 0;
for (int i = 0; i < data.length; i++) {
size += data[i].length;
}
byte[] byteArray = new byte[size];
int pos = 0;
for (int i = 0; i < data.length; i++) {
byte[] b = data[i];
for (int j = 0; j < b.length; j++) {
byteArray[pos++] = b[j];
}
}
return byteArray;
}
return null;
}
public static Integer getCRC162Int(byte[] bytes,Boolean flag) {
int CRC = 0x0000ffff;
int POLYNOMIAL = 0x0000a001;
int i, j;
for (i = 0; i < bytes.length; i++) {
// CRC ^= (int) bytes[i];
if(bytes[i] <0 ){
CRC ^= (int) (bytes[i]+256) ;
}else{
CRC ^= (int) bytes[i] ;
}
for (j = 0; j < 8; j++) {
if ((CRC & 0x00000001) == 1) {
CRC >>= 1;
CRC ^= POLYNOMIAL;
} else {
CRC >>= 1;
}
}
}
//高低位轉換,看情況使用(譬如本人這次對led彩屏的通訊開發就規定校驗碼高位在前低位在后,也就不需要轉換高低位)
if(flag){
CRC = ( (CRC & 0x0000FF00) >> 8) | ( (CRC & 0x000000FF ) << 8);
}
return CRC;
}
}