| New file |
| | |
| | | package toTcp; |
| | | |
| | | import static java.lang.System.arraycopy; |
| | | |
| | | public class DLT645_2007Control { |
| | | |
| | | // 读数据 ,传入电表的表号后生成 读数据的命令,将命令发送到电表 |
| | | public byte[] ReadData(String address) { |
| | | |
| | | byte[] readcommand = new byte[20]; |
| | | readcommand[0] = (byte) 0xFE; // 网上资料说前面要加四个固定的 0xFE, |
| | | readcommand[1] = (byte) 0xFE; |
| | | readcommand[2] = (byte) 0xFE; |
| | | readcommand[3] = (byte) 0xFE; |
| | | readcommand[4] = (byte) 0x68;// 真正的数据帧起始位置 |
| | | byte[] addressbytes = setAddrByte(address); // 电表的地址 转成16进制,有一个倒序的操作 |
| | | arraycopy(addressbytes, 0, readcommand, 5, addressbytes.length); |
| | | readcommand[11] = (byte) 0x68;// 固定格式 |
| | | readcommand[12] = (byte) 0x11;// 表示 读数据 |
| | | readcommand[13] = (byte) 0x04;// 后面 数据项的长度 |
| | | // byte[] dataTypeBytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) |
| | | // 0x00, (byte) 0x00 };//读电表的有功总电能 |
| | | byte[] dataTypeBytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00 };// 数据项代码: |
| | | // 读电表的正向有功总电能 |
| | | |
| | | if (dataTypeBytes != null) { |
| | | for (int i = 0; i < dataTypeBytes.length; i++) { |
| | | dataTypeBytes[i] += 0x33; |
| | | } |
| | | } |
| | | arraycopy(dataTypeBytes, 0, readcommand, 14, dataTypeBytes.length); |
| | | readcommand[18] = getSigned(getCSCode(readcommand, 4, 17)); |
| | | readcommand[19] = (byte) 0x16; |
| | | return readcommand; |
| | | } |
| | | |
| | | // 解析从设备返回的数据 |
| | | public static void ReturnData(byte[] returndatas) { |
| | | float reslut =0; |
| | | if (returndatas.length > 8) { |
| | | |
| | | if (returndatas[8] == (byte) 0x91)// 对应读数据命令11 的正确应答 |
| | | { |
| | | String EachByteAddress = GetBCDAddress(returndatas); // 得到 |
| | | // 当前返回数据代表的 |
| | | // 电表表号 |
| | | boolean check = checkData(returndatas); |
| | | if (check) { |
| | | int[] read_ints = new int[returndatas.length]; |
| | | for (int i = 0; i < returndatas.length; i++) { |
| | | if ((int) returndatas[i] > 0) { |
| | | read_ints[i] = (int) returndatas[i]; |
| | | } else { |
| | | read_ints[i] = (int) returndatas[i] + 256; |
| | | } |
| | | } |
| | | |
| | | if (read_ints[8] == 0x91) { |
| | | int lengthOfData = read_ints[9];// 数据长度; |
| | | byte[] data = new byte[lengthOfData - 4]; |
| | | for (int d = 0; d < lengthOfData - 4; d++) { |
| | | data[d] = (byte) (read_ints[14 + d] - 0x33); |
| | | } |
| | | int value = 0; |
| | | for (int v = 0; v < lengthOfData - 4; v++) { |
| | | value = v + (data[v] * 10 / 16 + (data[v]) % 16) * 100 ^ v; |
| | | } |
| | | reslut = value * 0.01f;// value *0.01 是最终的 正向有功总电能 |
| | | |
| | | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // System.out.println(reslut); |
| | | } |
| | | |
| | | // 把表号地址转成16进制 |
| | | public byte[] setAddrByte(String addr) { |
| | | byte[] addressByte = new byte[6]; |
| | | for (int i = 11; i > 0; i -= 2) { |
| | | int a = addr.charAt(i); |
| | | int b = addr.charAt(i - 1); |
| | | // 由于地址是16进制,所以先进行判断 |
| | | // A - F |
| | | if (a >= 65 && a <= 70) { |
| | | a -= 15; |
| | | } else if (a >= 97 && a <= 102) { |
| | | a -= 87; |
| | | } else { |
| | | a -= 48; |
| | | } |
| | | |
| | | if (b >= 65 && b <= 70) { |
| | | b -= 15; |
| | | } else if (b >= 97 && b <= 102) { |
| | | b -= 87; |
| | | } else { |
| | | b -= 48; |
| | | } |
| | | |
| | | addressByte[(11 - i) / 2] = (byte) (b * 16 + a); |
| | | } |
| | | return addressByte; |
| | | } |
| | | |
| | | // 把16进制的表号数据 转成字符串形式的表号 |
| | | public static String GetBCDAddress(byte[] address) { |
| | | byte[] byteAddress = new byte[6]; |
| | | arraycopy(address, 1, byteAddress, 0, 6); |
| | | String addr = ""; |
| | | String EachByteAddress; |
| | | int bitdata; |
| | | for (byte addr_b : byteAddress) { |
| | | if (addr_b < 0) { |
| | | bitdata = addr_b + 256; |
| | | } else { |
| | | bitdata = addr_b; |
| | | } |
| | | EachByteAddress = bitdata / 16 + "" + bitdata % 16; |
| | | addr = EachByteAddress + addr; |
| | | } |
| | | return addr; |
| | | } |
| | | |
| | | // CS校验码 |
| | | private int getCSCode(byte[] byteFrame, int i, int j) { |
| | | int s = 0; |
| | | for (int k = i; k <= j; k++) { |
| | | s += (byteFrame[k] & 0xff) % 256; |
| | | } |
| | | return s; |
| | | } |
| | | |
| | | // 将无符号(形式上的)的数据转化成有符号的byte数据值 |
| | | private byte getSigned(int a) { |
| | | if (a > 0x7f) |
| | | return (byte) (a - 256); |
| | | else |
| | | return (byte) (a); |
| | | } |
| | | |
| | | // 校验 返回的数据包内容 |
| | | static boolean checkData(byte[] data) { |
| | | byte s = 0; |
| | | int j; |
| | | for (j = data.length - 1; j > 0; j--) { |
| | | if (data[j] == 22) { |
| | | break; |
| | | } |
| | | } |
| | | |
| | | for (int i = 0; i < j - 1; i++) { |
| | | s += (data[i] & 0xff) % 256; |
| | | } |
| | | // System.out.println(s); |
| | | if (s == data[j - 1]) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } |
| | | } |