From d2d73cc7ef867e7ad980a40e44e1606488409bdf Mon Sep 17 00:00:00 2001 From: siontion Date: Fri, 26 Apr 2024 12:59:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=80=BB=E9=83=A8=E6=84=9F=E5=BA=94=E9=97=A8?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 总部感应门项目 --- pom.xml | 89 +++++++++ src/main/java/cc/cjyx/sc/Application.java | 14 ++ .../java/cc/cjyx/sc/common/SerialNumber.java | 22 +++ .../java/cc/cjyx/sc/common/TcpRunner.java | 170 ++++++++++++++++++ src/main/java/cc/cjyx/sc/test/TCPSocket.java | 155 ++++++++++++++++ src/main/java/cc/cjyx/sc/test/TcpServer.java | 40 +++++ .../java/cc/cjyx/sc/utils/DataParserUtil.java | 104 +++++++++++ src/main/resources/application.yml | 10 ++ src/main/resources/static/index.html | 6 + .../sc/demo/ModbusDemoApplicationTests.java | 51 ++++++ 10 files changed, 661 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/cc/cjyx/sc/Application.java create mode 100644 src/main/java/cc/cjyx/sc/common/SerialNumber.java create mode 100644 src/main/java/cc/cjyx/sc/common/TcpRunner.java create mode 100644 src/main/java/cc/cjyx/sc/test/TCPSocket.java create mode 100644 src/main/java/cc/cjyx/sc/test/TcpServer.java create mode 100644 src/main/java/cc/cjyx/sc/utils/DataParserUtil.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/static/index.html create mode 100644 src/test/java/cc/cjyx/sc/demo/ModbusDemoApplicationTests.java diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..dbaec0f --- /dev/null +++ b/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + cc.cjyx.sc + zbgym + 0.0.1-SNAPSHOT + zbgym + 总部感应门项目 + + 1.8 + UTF-8 + UTF-8 + 2.6.13 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + com.alibaba + fastjson + 1.2.72 + + + + org.projectlombok + lombok + true + + + + org.apache.commons + commons-lang3 + + + + cn.snowheart + spring-boot-dingtalk-robot-starter + 1.0.2.RELEASE + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + + diff --git a/src/main/java/cc/cjyx/sc/Application.java b/src/main/java/cc/cjyx/sc/Application.java new file mode 100644 index 0000000..473d839 --- /dev/null +++ b/src/main/java/cc/cjyx/sc/Application.java @@ -0,0 +1,14 @@ +package cc.cjyx.sc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/src/main/java/cc/cjyx/sc/common/SerialNumber.java b/src/main/java/cc/cjyx/sc/common/SerialNumber.java new file mode 100644 index 0000000..466b3df --- /dev/null +++ b/src/main/java/cc/cjyx/sc/common/SerialNumber.java @@ -0,0 +1,22 @@ +package cc.cjyx.sc.common; + +import java.text.SimpleDateFormat; + +public class SerialNumber { + private static final SimpleDateFormat YEAR_MONTH_FORMAT = new SimpleDateFormat("yyyyMM"); + private static int currentSerial = 0; + private static String currentYearMonth; + + public static synchronized String generateSerialNumber() { + String currentYearMonth = YEAR_MONTH_FORMAT.format(new java.util.Date()); + if (!currentYearMonth.equals(SerialNumber.currentYearMonth)) { + // 当年月变化时,重置流水号 + SerialNumber.currentYearMonth = currentYearMonth; + currentSerial = 1; + } else { + // 年月未变,递增流水号 + currentSerial++; + } + return currentYearMonth + String.format("%04d", currentSerial); + } +} diff --git a/src/main/java/cc/cjyx/sc/common/TcpRunner.java b/src/main/java/cc/cjyx/sc/common/TcpRunner.java new file mode 100644 index 0000000..46e97d0 --- /dev/null +++ b/src/main/java/cc/cjyx/sc/common/TcpRunner.java @@ -0,0 +1,170 @@ +package cc.cjyx.sc.common; + + +import cc.cjyx.sc.utils.DataParserUtil; +import cn.snowheart.dingtalk.robot.starter.client.DingTalkRobotClient; +import cn.snowheart.dingtalk.robot.starter.entity.DingTalkResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.PreDestroy; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + + +@Component +@Slf4j +@EnableScheduling +public class TcpRunner implements ApplicationRunner { + + private Socket socket; + + private OutputStream outputStream; + + private InputStream inputStream; + + @Value("${mobiles:15067827668,13375872885}") + private String mobiles; + + @Autowired + @Qualifier("dingTalkRobotClient") + private DingTalkRobotClient dingTalkClient; + + @Override + public void run(ApplicationArguments args) { + System.out.println("Tcp连接初始化中..."); +// System.out.println(Arrays.toString(mobiles.split(","))); + // 在应用程序启动后执行的代码 + this.connect(); + } + + // 连接数据 + private boolean connect() { + // 在应用程序启动后执行的代码 + try { +// this.socket = new Socket("cjdq.chko.cn", 9999); + this.socket = new Socket("192.168.100.2", 81); + log.info("socket connect status: {}", this.socket.isConnected()); + return true; + } catch (IOException e) { + log.error("Tcp Client连接失败,请检查网络!", e); + return false; + } + } + + + @Scheduled(fixedDelay = 2000) + public void send() { + log.info("2s定时发送指令..."); + try { + if (socket == null) { + log.info("Tcp Client未成功连接!"); + return; + } + this.handle(); + } catch (IOException e) { + log.error("Tcp Client 连接异常!", e); + // 尝试重新连接 + try { + if(this.connect()) { + this.handle(); + } + } catch (Exception exception) { + log.error("Tcp Client 重连异常!", e); + throw new RuntimeException(e); + } + } catch (Exception e) { + log.error("Tcp Client 数据请求异常!", e); + throw new RuntimeException(e); + } + } + + + private void handle() throws IOException { + // 获取写入流,用于发送数据 + outputStream = socket.getOutputStream(); + // 获取输入流,用于接收服务器的响应 + inputStream = socket.getInputStream(); + + // 发送指令(16进制格式) + String hexCommand = "01 02 00 00 00 01 B9 CA"; + byte[] command = DataParserUtil.hexString2byteArray(hexCommand); + outputStream.write(command); + outputStream.flush(); + + byte[] buffer = new byte[1024]; + int length = inputStream.read(buffer); + + // 解析服务器的响应(16进制格式) + if (length > 0) { + byte[] bytes = Arrays.copyOfRange(buffer, 0, length); +// System.out.println(Arrays.toString(response)); + String res = DataParserUtil.byteArray2HexString(bytes); + log.info("GET Tcp Server Response: {} ", res); +// System.out.println("服务器响应:" + hexResponse); + if (bytes.length == 6) { + this.alarmToDingTalk(bytes[3]); + } + } + } + + // 发送报警业务 + private void alarmToDingTalk(Byte b) { +// String s = DataParserUtil.formatBinary(b); // 此处在多个信号端点时,启用 +// System.out.println("bit string:" + s); + String[] atMobiles = mobiles.split(","); + if(b.intValue() == 1) { + String message = "("+SerialNumber.generateSerialNumber()+")"+"铜排车间安检门报警通知:当前时间(%s),感应到携带违禁物品出入,请尽快查验!"; + LocalDateTime currentDateTime = LocalDateTime.now(); + String time = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + message = String.format(message, time); + DingTalkResponse response = dingTalkClient.sendTextMessage(message, atMobiles); + log.info(response.toString()); + } + } + + + @PreDestroy + public void stop() { + System.out.println("Tcp Client 断开连接..."); + try { + if (socket != null) { + socket.close(); + } + if (inputStream != null) { + inputStream.close(); + } + if (outputStream != null) { + outputStream.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + public static void main(String[] args) { + LocalDateTime currentDateTime = LocalDateTime.now(); +// System.out.println(currentDateTime); +// System.out.println(new Date()); + String time = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + String message = "报警通知:当前时间(%s),感应到携带违禁物品进入,请尽快查验!"; + message = String.format(message, time); + System.out.println(message); + } +} diff --git a/src/main/java/cc/cjyx/sc/test/TCPSocket.java b/src/main/java/cc/cjyx/sc/test/TCPSocket.java new file mode 100644 index 0000000..e6a32a7 --- /dev/null +++ b/src/main/java/cc/cjyx/sc/test/TCPSocket.java @@ -0,0 +1,155 @@ +package cc.cjyx.sc.test; + +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.Socket; +import java.util.Arrays; +import java.util.Timer; +import java.util.TimerTask; + +public class TCPSocket { + public static void main(String args[]){ + send(); + } + + + public static void send() { + try { + // 创建Socket对象,指定服务器的IP地址和端口号 + Socket socket = new Socket("cjdq.chko.cn", 9999); + + // 获取输出流,用于向服务器发送指令 + OutputStream outputStream = socket.getOutputStream(); + + // 创建定时器,每秒发送一次指令 + Timer timer = new Timer(); + timer.schedule(new TimerTask() { + @Override + public void run() { + try { + // 发送指令(16进制格式) + String hexCommand = "0123456789ABCDEF"; + byte[] command = hexStrToBinaryStr(hexCommand); + outputStream.write(command); + outputStream.flush(); + + // 获取输入流,用于接收服务器的响应 + InputStream inputStream = socket.getInputStream(); + byte[] buffer = new byte[1024]; + int length = inputStream.read(buffer); + + // 解析服务器的响应(16进制格式) + if (length > 0) { + byte[] response = Arrays.copyOfRange(buffer, 0, length); + String hexResponse = BinaryToHexString(response); + System.out.println("服务器响应:" + hexResponse); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + }, 0, 1000); // 每秒发送一次 + + // 等待定时器结束 + Thread.sleep(10000); + + // 关闭连接和定时器 + timer.cancel(); + outputStream.close(); + socket.close(); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } + + + public static void send2(){ + try { + //要连接的服务端IP地址 + String host = "cjdq.chko.cn"; + //要连接的服务端对应的监听端口 + int port = 9999; + //1.建立客户端socket连接,指定服务器位置及端口 + Socket clientSocket =new Socket(host,port); + //2.得到socket读写流 + OutputStream os = clientSocket.getOutputStream(); + // 获取输入流,用于接收服务器的响应 + InputStream inputStream = clientSocket.getInputStream(); + + Thread thread = new Thread(() -> { + try { + + while (true) { + // 发送指令(16进制格式) + String hexCommand = "01 02 00 00 00 01 B9 CA"; + byte[] command = hexStrToBinaryStr(hexCommand); + os.write(command); + os.flush(); + + byte[] buffer = new byte[1024]; + int length = inputStream.read(buffer); + + // 解析服务器的响应(16进制格式) + if (length > 0) { + byte[] response = Arrays.copyOfRange(buffer, 0, length); + String hexResponse = BinaryToHexString(response); + System.out.println("服务器响应:" + hexResponse); + } + + Thread.sleep(1000); + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + System.out.println("发生了请求异常"); + } + }); + thread.start(); + }catch (Exception e){ +// if(clientSocket != null) { +// clientSocket.close(); +// } + e.printStackTrace(); + } + } + /** + * 将十六进制的字符串转换成字节数组 + * + * @param hexString + * @return + */ + public static byte[] hexStrToBinaryStr(String hexString) { + if (StringUtils.isEmpty(hexString)) { + return null; + } + hexString = hexString.replaceAll(" ", ""); + int len = hexString.length(); + int index = 0; + byte[] bytes = new byte[len / 2]; + while (index < len) { + String sub = hexString.substring(index, index + 2); + bytes[index/2] = (byte)Integer.parseInt(sub,16); + index += 2; + } + return bytes; + } + /** + * 将字节数组转换成十六进制的字符串 + * + * @return + */ + public static String BinaryToHexString(byte[] bytes) { + String hexStr = "0123456789ABCDEF"; + String result = ""; + String hex = ""; + for (byte b : bytes) { + hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4)); + hex += String.valueOf(hexStr.charAt(b & 0x0F)); + result += hex + " "; + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/cc/cjyx/sc/test/TcpServer.java b/src/main/java/cc/cjyx/sc/test/TcpServer.java new file mode 100644 index 0000000..1ea641a --- /dev/null +++ b/src/main/java/cc/cjyx/sc/test/TcpServer.java @@ -0,0 +1,40 @@ +package cc.cjyx.sc.test; + +import java.io.*; +import java.net.ServerSocket; +import java.net.Socket; + +public class TcpServer { + public static void main(String[] args) { + try { + // 创建ServerSocket对象,指定监听的端口号 + ServerSocket serverSocket = new ServerSocket(9991); + + System.out.println("服务器启动,等待客户端连接..."); + + // 监听客户端连接 + Socket socket = serverSocket.accept(); + System.out.println("客户端连接成功!"); + + // 获取输入流,用于接收客户端发送的数据 + InputStream inputStream = socket.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + String request = bufferedReader.readLine(); + System.out.println("客户端发送的数据:" + request); + + // 获取输出流,用于向客户端发送数据 + OutputStream outputStream = socket.getOutputStream(); + PrintWriter printWriter = new PrintWriter(outputStream); + printWriter.write("Hello Client!"); + printWriter.flush(); + + // 关闭连接 + printWriter.close(); + bufferedReader.close(); + socket.close(); + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/cc/cjyx/sc/utils/DataParserUtil.java b/src/main/java/cc/cjyx/sc/utils/DataParserUtil.java new file mode 100644 index 0000000..45a2960 --- /dev/null +++ b/src/main/java/cc/cjyx/sc/utils/DataParserUtil.java @@ -0,0 +1,104 @@ +package cc.cjyx.sc.utils; + +import lombok.extern.slf4j.Slf4j; + +// 数据解析 +@Slf4j +public class DataParserUtil { + + + /* + * byte 转 bit位 + * @description: 字节转比特 + * 1Byte=8bits + */ + public static String formatBinary(byte b) { + StringBuilder sb = new StringBuilder(); + for(int i = 7; i >=0; i--) { + sb.append((byte) ((b >> i) & 0x1)); + } + // 小端模式(低字节在前、高字节在后) + return sb.reverse().toString(); + } + + + + /** + * 字节数组转16进制字符串 + * + * @param b 字节数组 + * @return 16进制字符串 + */ + public static String byteArray2HexString(byte[] b) + { + StringBuilder sbf = new StringBuilder(); + for (byte value : b) + { + String hex = Integer.toHexString(value & 0xFF); + if (hex.length() == 1) + { + hex = '0' + hex; + } + sbf.append(hex.toUpperCase()).append(" "); + } + return sbf.toString().trim(); + } + + /** + * 16进制字符串转字节数组 + * + * @param hex 16进制字符串 + * @return 字节数组 + */ + public static byte[] hexString2byteArray(String hex) + { + hex = hex.replace(" ", ""); + if (!isHexString(hex)) + { + return null; + } + char[] arr = hex.toCharArray(); + byte[] b = new byte[hex.length() / 2]; + for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) + { + String swap = "" + arr[i++] + arr[i]; + int byteint = Integer.parseInt(swap, 16) & 0xFF; + b[j] = new Integer(byteint).byteValue(); + } + return b; + } + + /** + * 校验是否是16进制字符串 + * + * @param hex + * @return boolean + */ + public static boolean isHexString(String hex) + { + if (hex == null || hex.length() % 2 != 0) + { + return false; + } + for (int i = 0; i < hex.length(); i++) + { + char c = hex.charAt(i); + if (!isHexChar(c)) + { + return false; + } + } + return true; + } + + /** + * 校验是否是16进制字符 + * + * @param c + * @return boolean + */ + private static boolean isHexChar(char c) + { + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..8fd706c --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,10 @@ +server: + port: 8881 + +mobiles: + '15067827668,13375872885,13587753850' + +# 钉钉通知 +dingtalk: + robot: + webhook: https://oapi.dingtalk.com/robot/send?access_token=3e5c999e5a1163d7d9251c4f5781ccd1d10430c8987be3f3d377e6fea16a4293 diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..89bb8ba --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,6 @@ + + +

hello word!!!

+

this is a html page

+ + \ No newline at end of file diff --git a/src/test/java/cc/cjyx/sc/demo/ModbusDemoApplicationTests.java b/src/test/java/cc/cjyx/sc/demo/ModbusDemoApplicationTests.java new file mode 100644 index 0000000..c567164 --- /dev/null +++ b/src/test/java/cc/cjyx/sc/demo/ModbusDemoApplicationTests.java @@ -0,0 +1,51 @@ +package cc.cjyx.sc.demo; + +import cn.snowheart.dingtalk.robot.starter.client.DingTalkRobotClient; +import cn.snowheart.dingtalk.robot.starter.entity.DingTalkResponse; +import cn.snowheart.dingtalk.robot.starter.entity.TextMessage; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Slf4j +class ModbusDemoApplicationTests { + + @Autowired + @Qualifier("dingTalkRobotClient") + private DingTalkRobotClient client; + + + @Test + void contextLoads() { + } + + @Test + public void testSendTextMessage() throws InterruptedException { +// DingTalkResponse response = null; + +// response = client.sendTextMessage(new TextMessage("报警通知:构建 TextMessage对象发布!")); +// Assertions.assertEquals(response.getErrcode().longValue(), 0L); +// log.info(response.toString()); +// Thread.sleep(3000); + +// response = client.sendTextMessage("报警通知:构建普通字符串发布!"); +// Assertions.assertEquals(response.getErrcode().longValue(), 0L); +// log.info(response.toString()); +// Thread.sleep(3000); + + DingTalkResponse response = client.sendTextMessage("报警通知:通知指定人!", new String[]{"15137603460"}); + Assertions.assertEquals(response.getErrcode().longValue(), 0L); + log.info(response.toString()); + Thread.sleep(3000); + +// response = client.sendTextMessage("报警通知:通知群内所有人!", true); +// Assertions.assertEquals(response.getErrcode().longValue(), 0L); +// log.info(response.toString()); +// Thread.sleep(3000); + } + +}