廖井涛
2025-11-19 e69c125713fc59cd6bb31f5cb5e045f6284a4eca
nglib/src/toTcp/DLT645_2007Control.java
New file
@@ -0,0 +1,163 @@
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;
        }
    }
}