package com.back.sync; import java.text.SimpleDateFormat; import java.util.List; import com.back.action.Log; import com.back.common.Common; import com.back.entity.Control; import com.back.entity.Mcontrol; import com.back.entity.Sensor; import com.back.protocol.GW3761; public class DataSyncUtil { /** * 获取设置命令 datas 具体设置的报文 terminal 集中器通信地址 */ private static class Cmdinfor { String afn; // AFN String Comid; // 通信地址 String datas; // 数据区内容 Boolean FCV; // 帧计数有效位FCV String FCB; // FCB String host; // 主站地址 String PWD; // 密码 int PFC; // PFC Boolean bTime; // 是否有时间标签 int outTime;// 允许发送传输延时时间 Boolean TP;// 是否有时间标签 Boolean CON;// CON位置“true”,表示需要对该帧报文进行确认;置“false”,表示不需要对该帧报文进行确认。 public void Create(String afn, String comid, String datas, int PFC, Boolean btime) { datas = datas.replace(" ", ""); datas = datas.trim(); this.afn = afn; while (comid.length() < 8) comid = "0" + comid; this.Comid = comid; this.datas = datas; this.FCV = false; this.PFC = PFC; this.FCB = "01"; this.host = "02"; this.PWD = "00000000000000000000000000000000";// 固定密码 16个零 this.bTime = btime; this.outTime = 5; this.TP = btime; this.CON = true; } } private static Cmdinfor cmdinfor = new Cmdinfor(); /** * 配置灯具下发数据 202101 * * @param * * @param flag * true为新增,false为删除 * @return */ public static String configLampData(List controlList, boolean flag) { String data = "", temp = ""; try { for (int i = 0; i < controlList.size(); i++) { Control control = controlList.get(i); // 灯装置序号(2个字节) temp = dec2Hex(control.getNum(), 4); data = data + " " + temp.substring(2, 4); data = data + " " + temp.substring(0, 2); // 测量点号(2个字节) // if (flag) { // data = data + " " + temp.substring(2, 4); // data = data + " " + temp.substring(0, 2); // } else { // data += " 00 00"; // } // 灯通信地址(6个字节) temp = control.getComid(); temp = "000000000000" + temp; temp = temp.substring(temp.length() - 12); for (int j = temp.length(); j > 0; j -= 2) { data += " " + temp.substring(j - 2, j); } // 通讯信道(1个字节),即通信端口 // 1-载波通信 2-RS485_1口通信 3-RS485_2口通信 4-LORA无线通信(5-255:备用) String tunnel = control.getTunnel(); data += " " + tunnel.substring(2, 4); // 通信协议(1个字节) // 1-DL645_97版 2-DL645_07版 3-ModBus协议 (4-255:备用) String protocol = control.getProtocol(); data += " " + protocol.substring(2, 4); // 所属组号(1个字节) data = data + " " + dec2Hex(control.getGroupid(), 2); // 工作方式(1个字节) String worktypeString = control.getWorktype(); // 00 时间表;01经纬度;02 场景模式 data += " " + worktypeString.substring(2, 4); // 灯杆类型(1个字节) // 1—单灯调光 2-双色温调光 3-双灯头调光(3-255:备用) String type = control.getType(); data += " " + type.substring(2, 4); } } catch (Exception e) { Log.writelog1("构造灯杆安装命令出错, error:" + e.getMessage()); e.printStackTrace(); } return data; } public static String SendCmd(int type, int count, String message) { int[] cmd = new int[3]; cmd[0] = 0x81; cmd[1] = 0x01; cmd[2] = type; StringBuilder builder = new StringBuilder(); for (int i = 1; i < cmd.length; i++) { builder.append(" " + dec2Hex(cmd[i], 1)); } return builder.toString(); } public static String preSendCmd(String terminal) { String cmdCode = "0000" + GW3761.GetDAOrDT(4, 1) + "81" + "01" + "00"; String binarypfc = "00000000" + Common.inttobinary(PFC); PFC++; if (PFC == 255) PFC = 0; binarypfc = Common.right(binarypfc, 4); String seqdomain = Common.binarytohex("0111" + binarypfc); char[] chars = terminal.toCharArray(); String adomain = String.valueOf(chars[2]) + String.valueOf(chars[3]) + String.valueOf(chars[0]) + String.valueOf(chars[1]) + String.valueOf(chars[6]) + String.valueOf(chars[7]) + String.valueOf(chars[4]) + String.valueOf(chars[5]) + "04"; return gw3761.create3761("64", adomain, "FD", seqdomain, cmdCode); } public static String genetateLampData(String terminal, List controlList) { String data = configLampData(controlList, Boolean.TRUE); // String temp = dec2Hex(controlList.size(), 4); // String msgString = temp.substring(2, 4) + " " + temp.substring(0, 2) + " " + data; // msgString = GetDAOrDT(21, 1) + msgString.trim(); // cmdinfor.Create("A4", terminal, msgString, GetPFC(), false); String cmdCode = "0000" + GW3761.GetDAOrDT(4, 1) + "81" + "02" + "01" + dec2Hex(controlList.size(), 2) + data; cmdCode = cmdCode.replace(" ", ""); String binarypfc = "00000000" + Common.inttobinary(PFC); PFC++; if (PFC == 255) PFC = 0; binarypfc = Common.right(binarypfc, 4); String seqdomain = Common.binarytohex("0111" + binarypfc); char[] chars = terminal.toCharArray(); String adomain = String.valueOf(chars[2]) + String.valueOf(chars[3]) + String.valueOf(chars[0]) + String.valueOf(chars[1]) + String.valueOf(chars[6]) + String.valueOf(chars[7]) + String.valueOf(chars[4]) + String.valueOf(chars[5]) + "04"; return gw3761.create3761("64", adomain, "FD", seqdomain, cmdCode); } private static GW3761 gw3761 = new GW3761(); // 新集中器解码类 private static int PFC = 0; // 启动帧帧序号计数器(0~255) public static String generateMcontrolData(String terminal, List mcontrolList) { String message = configMcontrolData(mcontrolList, Boolean.TRUE); // message = GetDAOrDT(36, 1) + message; // cmdinfor.Create("A4", terminal, message, GetPFC(), false); String cmdCode = "0000" + GW3761.GetDAOrDT(4, 1) + "81" + "02" + "02" + dec2Hex(mcontrolList.size(), 2) + message; cmdCode = cmdCode.replace(" ", ""); String binarypfc = "00000000" + Common.inttobinary(PFC); PFC++; if (PFC == 255) PFC = 0; binarypfc = Common.right(binarypfc, 4); String seqdomain = Common.binarytohex("0111" + binarypfc); char[] chars = terminal.toCharArray(); String adomain = String.valueOf(chars[2]) + String.valueOf(chars[3]) + String.valueOf(chars[0]) + String.valueOf(chars[1]) + String.valueOf(chars[6]) + String.valueOf(chars[7]) + String.valueOf(chars[4]) + String.valueOf(chars[5]) + "04"; return gw3761.create3761("64", adomain, "FD", seqdomain, cmdCode); } public static String generateSensorData(String terminal, List sensorList, int fn, String sensorType) { String message = configSensorData(sensorList, Boolean.TRUE); // String temp = dec2Hex(1, 2); // message = temp.substring(0, 2) + " " + message; // message = GetDAOrDT(fn, 1) + message.trim(); // cmdinfor.Create("A4", terminal, message, GetPFC(), false); // return GetSendCmd(cmdinfor); String cmdCode = "0000" + GW3761.GetDAOrDT(4, 1) + "81" + "02" + sensorType + dec2Hex(sensorList.size(), 2) + message; cmdCode = cmdCode.replace(" ", ""); String binarypfc = "00000000" + Common.inttobinary(PFC); PFC++; if (PFC == 255) PFC = 0; binarypfc = Common.right(binarypfc, 4); String seqdomain = Common.binarytohex("0111" + binarypfc); char[] chars = terminal.toCharArray(); String adomain = String.valueOf(chars[2]) + String.valueOf(chars[3]) + String.valueOf(chars[0]) + String.valueOf(chars[1]) + String.valueOf(chars[6]) + String.valueOf(chars[7]) + String.valueOf(chars[4]) + String.valueOf(chars[5]) + "04"; return gw3761.create3761("64", adomain, "FD", seqdomain, cmdCode); } public static String configMcontrolData(List mcontrolList, boolean flag) { String data = "", temp = ""; try { for (int i = 0; i < mcontrolList.size(); i++) { Mcontrol mcontrol = mcontrolList.get(i); // 主控装置序号(2个字节) temp = dec2Hex(mcontrol.getNum(), 4); data = data + temp.substring(2, 4) + " " + temp.substring(0, 2); // 测量点号(2个字节) // if (flag) { // data += " " + temp.substring(2, 4) + " " + temp.substring(0, // 2); // } else { // data += " 00 00"; // } // 通信地址(6个字节) temp = mcontrol.getComid(); while (temp.length() < 12) temp = "0" + temp; for (int j = temp.length(); j > 0; j -= 2) { data += " " + temp.substring(j - 2, j); } // 通讯信道(1个字节):1为载波口 2为第一个485口 3为第二个485口 temp = mcontrol.getTunnel(); data += " " + temp.substring(2, 4); // 通讯协议(1个字节):1-DL645_97版 2-DL645_07版 3-ModBus协议 (4-255:备用) temp = mcontrol.getProtocol(); data += " " + temp.substring(2, 4); // 该线路所属组号(1个字节) if (mcontrol.getGroups() == null) { temp = ""; } else { temp = mcontrol.getGroups().trim(); } if (temp.equals("")) { data += " 00"; } else { temp = dec2Hex(Integer.parseInt(temp), 2); data += " " + temp; } // 工作方式(1个字节) String worktypeString = mcontrol.getWorktype(); if (worktypeString.equals("0001")) { // 走经纬度 data += " 01"; } else if (worktypeString.equals("0000")) { // 走时间表 data += " 00"; } else if (worktypeString.equals("0002")) { // 场景模式 data += " 02"; } // 回路类型(1个字节) temp = dec2Hex(mcontrol.getType(), 2); data += " " + temp; // 回路电流互感器变比值(1个字节) temp = dec2Hex(mcontrol.getRatio(), 2); data += " " + temp; } } catch (Exception e) { Log.writelog1("构造回路安装命令出错, error:" + e.getMessage()); e.printStackTrace(); } return data; } public static String configSensorData(List sensorList, boolean flag) { String data = "", temp = ""; try { for (int i = 0; i < sensorList.size(); i++) { Sensor sensor = sensorList.get(i); // 灯装置序号(2个字节) temp = dec2Hex(sensor.getNum(), 4); data = data + " " + temp.substring(2, 4); data = data + " " + temp.substring(0, 2); // 测量点号(2个字节) // if (flag) { // data = data + " " + temp.substring(2, 4); // data = data + " " + temp.substring(0, 2); // } else { // data += " 00 00"; // } // 灯通信地址(6个字节) temp = sensor.getComid(); temp = "000000000000" + temp; temp = temp.substring(temp.length() - 12); for (int j = temp.length(); j > 0; j -= 2) { data += " " + temp.substring(j - 2, j); } // 通讯信道(1个字节),即通信端口 1-载波通信 2-RS485_1口通信 3-RS485_2口通信 // 4-LORA无线通信(5-255:备用) String tunnel = sensor.getTunnel(); data += " " + tunnel.substring(2, 4); // 通信协议(1个字节) 1-DL645_97版 2-DL645_07版 3-ModBus协议 (4-255:备用) String protocol = sensor.getProtocol(); data += " " + protocol.substring(2, 4); int fn = 0; if (sensor.getType().equals("0001")) {// 照度传感器 fn = 37; } else if (sensor.getType().equals("0002")) {// 亮度传感器 fn = 38; // 转换系数(1个字节) temp = dec2Hex(sensor.getRatio(), 2); data += " " + temp; } else if (sensor.getType().equals("0003")) {// 车流量传感器 fn = 39; // 车流量统计周期(1个字节) temp = dec2Hex(sensor.getCycle(), 2); data += " " + temp; // 车道数量(1个字节) temp = dec2Hex(sensor.getLane(), 2); data += " " + temp; } } } catch (Exception e) { Log.writelog1("构造传感器安装命令出错, error:" + e.getMessage()); e.printStackTrace(); } return data; } /** * 10进制转16进制 * * @param dec * 要转换的数值 * @param len * 16进制的长度 * @return */ private static String dec2Hex(int dec, int len) { String tempString = Integer.toHexString(dec); while (tempString.length() < len) { tempString = "0" + tempString; } return tempString.trim(); } /** * 10进制字符串转16进制字符串 * * @param dec * @return */ public static String dec2Hex(String dec, int len) { if (dec == null || dec.equals("")) dec = "0"; String tempString = Long.toHexString(Long.parseLong(dec)); while (tempString.length() < len) { tempString = "0" + tempString; } return tempString.trim(); } /** * 为0时计算信息点标识DA(Pn),为1计算信息类标识DT(Fn) * * @param value * @param flag * 0/1 * @return F30,返回值格式:00 00 20 03 */ public static String GetDAOrDT(int value, int flag) { int d = 0; String D1, D2 = "0"; if (value == 0) { D1 = "0"; D2 = "0"; } else { d = value % 8; if (d == 0) { D1 = "1" + repeat(7, '0'); d = value / 8 - 1; if (flag == 0) { d = d + 1; } } else { D1 = "1" + repeat(d - 1, '0'); d = value / 8; if (flag == 0) { d = d + 1; } } } D1 = Common.right("00" + Common.binarytohex(D1), 2); D2 = Common.right("00" + Common.inttohex(d), 2); return "00 00 " + D1 + " " + D2; } /** 返回指定字符的重复 */ public static String repeat(int len, char c) { StringBuffer sbf = new StringBuffer(); int i = 0; while (i < len) { i += 1; sbf.append(c); } return sbf.toString(); } private static int GetPFC() { return 1; } private static int msg[] = new int[2024]; private static String GetSendCmd(Cmdinfor cmdinfor) { int count = cmdinfor.datas.length(); int i; String temp; for (i = 0; i < msg.length; i++) msg[i] = 0; // 报文头 msg[0] = 0x68;// 68H msg[5] = 0x68;// 68H // 控制码 msg[6] = GetDownCortrolByte(cmdinfor.afn, cmdinfor.FCB, cmdinfor.FCV);// C // 控制位 // 通信地址 16进制字 temp = cmdinfor.Comid.substring(0, 4); msg[8] = Integer.parseInt(temp.substring(0, 2), 16) & 0xFF; // A 地址域 --> // 行政区划码 A1 // 2字节 BCD码 msg[7] = Integer.parseInt(temp.substring(2), 16) & 0xFF; // A 地址域 --> // 行政区划码 A1 // 2字节 BCD码 temp = cmdinfor.Comid.substring(4); msg[10] = Integer.parseInt(temp.substring(0, 2), 16) & 0xFF; // A 地址域 // --> // 行政区划码 // A2 // 2字节 // BCD码 msg[9] = Integer.parseInt(temp.substring(2), 16) & 0xFF; // A 地址域 --> // 行政区划码 A2 // 2字节 BCD码 // 主站地址 msg[11] = (Integer.parseInt(cmdinfor.host, 16) << 1) & 0xFF;// A 地址域 --> // 主站地址 A3 // 1字节 Bin码 msg[12] = Integer.parseInt(cmdinfor.afn, 16) & 0xFF; // AFN if (cmdinfor.bTime) temp = "111"; else temp = "011"; // 20190216 增加 请求确认标志位 if (cmdinfor.CON) temp = temp + "1"; else temp = temp + "0"; msg[13] = (binaryString2Int(temp) << 4) + (cmdinfor.PFC % 16); // SEQ // 帧序列域 int len = cmdinfor.datas.length() / 2; for (int j = 0; j < (len); j++) { temp = cmdinfor.datas.substring(j * 2, (j * 2 + 2)); msg[14 + j] = Integer.parseInt(temp, 16) & 0xFF; } len = len + 13; if (CheckDwnPw(cmdinfor.afn)) { len++; for (int j = 0; j < 16; j++) { // 密码 temp = cmdinfor.PWD.substring(j * 2, (j * 2 + 2)); msg[len + j] = Integer.parseInt(temp, 16) & 0xFF; } len = len + 15; } if (cmdinfor.TP) { SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String datetime = tempDate.format(new java.util.Date()); len++; msg[len] = cmdinfor.PFC;// 启动帧帧序号计数器PFC len++; msg[len] = Integer.parseInt(datetime.substring(17, 19), 16);// 启动帧发送时标 // 秒 len++; msg[len] = Integer.parseInt(datetime.substring(14, 16), 16);// 启动帧发送时标 // 分 len++; msg[len] = Integer.parseInt(datetime.substring(11, 13), 16);// 启动帧发送时标 // 时 len++; msg[len] = Integer.parseInt(datetime.substring(8, 10), 16);// 启动帧发送时标 // 日 len++; msg[len] = 1;// 允许发送传输延时时间 } len++; msg[len] = GetCS(len); len++; msg[len] = 0x16; count = len - 7; count = (count << 2) + 2; msg[1] = count % 0x100; msg[2] = count / 0x100; msg[3] = count % 0x100; msg[4] = count / 0x100; // 转成字符串 StringBuffer sendBuffer = new StringBuffer(); for (int j = 0; j <= len; j++) sendBuffer.append(" " + dec2Hex(msg[j], 2)); System.out.println(sendBuffer.toString().trim()); return sendBuffer.toString().trim(); } /** * 获取相应的功能码 * * @param sType * @param sFCB * @param bFCV * @return */ private static Integer GetDownCortrolByte(String sType, String sFCB, Boolean bFCV) { String temp = ""; sType = sType.toUpperCase(); sType = sType.trim(); if (sType.equals("00")) temp = "0001"; if (sType.equals("02")) temp = "1001"; if (sType.equals("03")) temp = "1011"; if (sType.equals("04")) temp = "1010"; if (sType.equals("05")) temp = "1010"; if (sType.equals("06")) temp = "1011"; if (sType.equals("08")) temp = "1011"; if (sType.equals("09")) temp = "1011"; if (sType.equals("0A")) temp = "1011"; if (sType.equals("0B")) temp = "1011"; if (sType.equals("0C")) temp = "1011"; if (sType.equals("0D")) temp = "1011"; if (sType.equals("0E")) temp = "1011"; if (sType.equals("0F")) temp = "1011"; if (sType.equals("10")) temp = "1011"; if (sType.equals("8C")) temp = "1011"; if (sType.equals("A4")) temp = "1010"; if (sType.equals("A5")) temp = "1010"; if (sType.equals("AA")) temp = "1011"; if (sType.equals("AC")) temp = "1011"; if (sType.equals("AD")) temp = "1011"; if (bFCV) temp = "01" + sFCB.substring(1, 2) + "1" + temp; else temp = "01" + sFCB.substring(1, 2) + "0" + temp; return binaryString2Int(temp); } private static Boolean CheckDwnPw(String sType) { Boolean sign = false; if (sType.equals("01")) sign = true; if (sType.equals("03")) sign = true; if (sType.equals("04")) sign = true; if (sType.equals("05")) sign = true; if (sType.equals("06")) sign = true; if (sType.equals("0F")) sign = true; if (sType.equals("10")) sign = true; if (sType.equals("01")) sign = true; if (sType.equals("01")) sign = true; if (sType.equals("01")) sign = true; if (sType.equals("A4")) sign = true; if (sType.equals("A5")) sign = true; return sign; } /** * 二进制字符串转整型 * * @param bString * @return */ public static int binaryString2Int(String bString) { int temp = 0; for (int i = 0; i < bString.length(); i++) { temp <<= 1; temp += Integer.parseInt(bString.substring(i, i + 1)); } return temp; } private static int GetCS(int len) { int ics = 0; for (int i = 6; i < len; i++) { ics = ics + msg[i]; } return ics & 0xFF; } }