home %!s(int64=2) %!d(string=hai) anos
achega
156272f003
Modificáronse 100 ficheiros con 6822 adicións e 0 borrados
  1. 6 0
      .gitignore
  2. 190 0
      pom.xml
  3. 31 0
      src/main/java/com/fjhx/Application.java
  4. 40 0
      src/main/java/com/fjhx/business/controller/RfidController.java
  5. 40 0
      src/main/java/com/fjhx/business/mapper/ProductionLineRouteMapper.java
  6. 30 0
      src/main/java/com/fjhx/business/mapper/QrCodeMapper.java
  7. 30 0
      src/main/java/com/fjhx/business/mapper/RfidHasauMapper.java
  8. 30 0
      src/main/java/com/fjhx/business/mapper/RfidNoauMapper.java
  9. 29 0
      src/main/java/com/fjhx/business/mapper/TaskMapper.java
  10. 31 0
      src/main/java/com/fjhx/business/mapper/TaskStepMapper.java
  11. 31 0
      src/main/java/com/fjhx/business/mapper/WorkFollowMapper.java
  12. 39 0
      src/main/java/com/fjhx/business/mapper/WorkMapper.java
  13. 33 0
      src/main/java/com/fjhx/business/service/IProductionLineRouteService.java
  14. 30 0
      src/main/java/com/fjhx/business/service/IQrCodeService.java
  15. 30 0
      src/main/java/com/fjhx/business/service/IRfidHasauService.java
  16. 30 0
      src/main/java/com/fjhx/business/service/IRfidNoauService.java
  17. 29 0
      src/main/java/com/fjhx/business/service/ITaskService.java
  18. 31 0
      src/main/java/com/fjhx/business/service/ITaskStepService.java
  19. 35 0
      src/main/java/com/fjhx/business/service/IWorkFollowService.java
  20. 37 0
      src/main/java/com/fjhx/business/service/IWorkService.java
  21. 46 0
      src/main/java/com/fjhx/business/service/impl/ProductionLineRouteServiceImpl.java
  22. 34 0
      src/main/java/com/fjhx/business/service/impl/QrCodeServiceImpl.java
  23. 33 0
      src/main/java/com/fjhx/business/service/impl/RfidHasauServiceImpl.java
  24. 34 0
      src/main/java/com/fjhx/business/service/impl/RfidNoauServiceImpl.java
  25. 33 0
      src/main/java/com/fjhx/business/service/impl/TaskServiceImpl.java
  26. 54 0
      src/main/java/com/fjhx/business/service/impl/TaskStepServiceImpl.java
  27. 55 0
      src/main/java/com/fjhx/business/service/impl/WorkFollowServiceImpl.java
  28. 43 0
      src/main/java/com/fjhx/business/service/impl/WorkServiceImpl.java
  29. 113 0
      src/main/java/com/fjhx/config/RFIDConfig.java
  30. 19 0
      src/main/java/com/fjhx/constant/ApiConstant.java
  31. 88 0
      src/main/java/com/fjhx/constant/HttpStatus.java
  32. 105 0
      src/main/java/com/fjhx/constant/RFIDConstant.java
  33. 31 0
      src/main/java/com/fjhx/constant/RedisKeyConstant.java
  34. 81 0
      src/main/java/com/fjhx/entity/enums/AntnoStatusEnum.java
  35. 18 0
      src/main/java/com/fjhx/entity/rfid/Hyy.java
  36. 13 0
      src/main/java/com/fjhx/entity/rfid/Log.java
  37. 65 0
      src/main/java/com/fjhx/entity/rfid/QrCode.java
  38. 51 0
      src/main/java/com/fjhx/entity/rfid/RFIDClient.java
  39. 18 0
      src/main/java/com/fjhx/entity/rfid/Sd.java
  40. 18 0
      src/main/java/com/fjhx/entity/rfid/Service.java
  41. 20 0
      src/main/java/com/fjhx/entity/rfid/Tcp.java
  42. 20 0
      src/main/java/com/fjhx/entity/rfid/Udp.java
  43. 107 0
      src/main/java/com/fjhx/entity/rfid/base/BasicsEntity.java
  44. 65 0
      src/main/java/com/fjhx/entity/rfid/business/ProductionLineRoute.java
  45. 91 0
      src/main/java/com/fjhx/entity/rfid/business/RfidHasau.java
  46. 68 0
      src/main/java/com/fjhx/entity/rfid/business/RfidNoau.java
  47. 98 0
      src/main/java/com/fjhx/entity/rfid/business/Task.java
  48. 57 0
      src/main/java/com/fjhx/entity/rfid/business/TaskStep.java
  49. 100 0
      src/main/java/com/fjhx/entity/rfid/business/Work.java
  50. 62 0
      src/main/java/com/fjhx/entity/rfid/business/WorkFollow.java
  51. 55 0
      src/main/java/com/fjhx/rabbitmq/JsRabbitMQListener.java
  52. 249 0
      src/main/java/com/fjhx/rabbitmq/RabbitMQListener.java
  53. 87 0
      src/main/java/com/fjhx/rabbitmq/RabbitMQProducer.java
  54. 87 0
      src/main/java/com/fjhx/rabbitmq/SdRabbitMQProducer.java
  55. 48 0
      src/main/java/com/fjhx/rabbitmq/busi/BusiRabbitMQListener.java
  56. 59 0
      src/main/java/com/fjhx/rabbitmq/config/RabbitMQConfig.java
  57. 59 0
      src/main/java/com/fjhx/rabbitmq/config/SDRabbitMQConfig.java
  58. 64 0
      src/main/java/com/fjhx/rabbitmq/enums/MsgSourceEnum.java
  59. 30 0
      src/main/java/com/fjhx/rabbitmq/service/RabbitmqService.java
  60. 45 0
      src/main/java/com/fjhx/rabbitmq/service/impl/RabbitmqServiceImpl.java
  61. 297 0
      src/main/java/com/fjhx/redis/RedisCache.java
  62. 214 0
      src/main/java/com/fjhx/redis/RedissonLockClient.java
  63. 28 0
      src/main/java/com/fjhx/redis/redisson/RedissonConfiguration.java
  64. 98 0
      src/main/java/com/fjhx/redis/redisson/RedissonManager.java
  65. 13 0
      src/main/java/com/fjhx/redis/redisson/enums/GlobalConstant.java
  66. 29 0
      src/main/java/com/fjhx/redis/redisson/enums/LockModel.java
  67. 49 0
      src/main/java/com/fjhx/redis/redisson/enums/RedisConnectionType.java
  68. 74 0
      src/main/java/com/fjhx/redis/redisson/properties/RedissonProperties.java
  69. 22 0
      src/main/java/com/fjhx/redis/redisson/strategy/RedissonConfigStrategy.java
  70. 42 0
      src/main/java/com/fjhx/redis/redisson/strategy/impl/ClusterRedissonConfigStrategyImpl.java
  71. 52 0
      src/main/java/com/fjhx/redis/redisson/strategy/impl/MasterslaveRedissonConfigStrategyImpl.java
  72. 47 0
      src/main/java/com/fjhx/redis/redisson/strategy/impl/SentinelRedissonConfigStrategyImpl.java
  73. 39 0
      src/main/java/com/fjhx/redis/redisson/strategy/impl/StandaloneRedissonConfigStrategyImpl.java
  74. 22 0
      src/main/java/com/fjhx/rfid/r2000/common/service/IRFIDService.java
  75. 88 0
      src/main/java/com/fjhx/rfid/r2000/common/service/impl/RFIDServiceImpl.java
  76. 14 0
      src/main/java/com/fjhx/rfid/r2000/controller/RFIDController.java
  77. 46 0
      src/main/java/com/fjhx/rfid/r2000/controller/SdRFIDController.java
  78. 54 0
      src/main/java/com/fjhx/rfid/r2000/controller/TcpController.java
  79. 59 0
      src/main/java/com/fjhx/rfid/r2000/controller/UdpController.java
  80. 29 0
      src/main/java/com/fjhx/rfid/r2000/sd/service/ISdService.java
  81. 104 0
      src/main/java/com/fjhx/rfid/r2000/sd/service/impl/SdServiceImpl.java
  82. 94 0
      src/main/java/com/fjhx/rfid/r2000/tcp/callback/SdTcpCallBack.java
  83. 24 0
      src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBack.java
  84. 124 0
      src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBackAllData.java
  85. 120 0
      src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBackGoHeavyData.java
  86. 130 0
      src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBackSaveLog.java
  87. 34 0
      src/main/java/com/fjhx/rfid/r2000/tcp/service/ISdTcpService.java
  88. 38 0
      src/main/java/com/fjhx/rfid/r2000/tcp/service/TcpService.java
  89. 44 0
      src/main/java/com/fjhx/rfid/r2000/tcp/service/TcpServiceV2.java
  90. 151 0
      src/main/java/com/fjhx/rfid/r2000/tcp/service/impl/ISdTcpServiceImpl.java
  91. 251 0
      src/main/java/com/fjhx/rfid/r2000/tcp/service/impl/TcpServiceImpl.java
  92. 276 0
      src/main/java/com/fjhx/rfid/r2000/tcp/service/impl/TcpServiceImplV2.java
  93. 88 0
      src/main/java/com/fjhx/rfid/r2000/udp/callback/SdUdpCallBack.java
  94. 13 0
      src/main/java/com/fjhx/rfid/r2000/udp/callback/UdpCallBack.java
  95. 127 0
      src/main/java/com/fjhx/rfid/r2000/udp/callback/UdpCallBackSaveLog.java
  96. 34 0
      src/main/java/com/fjhx/rfid/r2000/udp/service/ISdUdpService.java
  97. 39 0
      src/main/java/com/fjhx/rfid/r2000/udp/service/UdpService.java
  98. 143 0
      src/main/java/com/fjhx/rfid/r2000/udp/service/impl/SdUdpServiceImpl.java
  99. 244 0
      src/main/java/com/fjhx/rfid/r2000/udp/service/impl/UdpServiceImpl.java
  100. 223 0
      src/main/java/com/fjhx/rfid/r2000/udp/utils/Utility.java

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+**.iml
+.idea
+target
+**/target
+# 自动生成不提交
+hx-common/code-generator/src/main/java/com/fjhx/modular/**

+ 190 - 0
pom.xml

@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.fjhx</groupId>
+    <packaging>jar</packaging>
+    <artifactId>rfid-r2000</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.5.1</version>
+    </parent>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <!-- 依赖声明 -->
+    <dependencies>
+        <!--mybatisplus依赖-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>21.0</version>
+        </dependency>
+        <!--mybatis-plus依赖-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>3.5.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.7</version>
+        </dependency>
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus</artifactId>
+            <version>3.5.0</version>
+        </dependency>
+        <!-- SpringBoot Web容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>2.5.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.76</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.12.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+            <version>4.4</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- redis 缓存操作 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+        <!-- redisson 分布式锁 -->
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+            <version>3.16.1</version>
+        </dependency>
+
+        <!-- RFID相关jar包加载项 begin (以下都属本地jar包,需要手动添加到本地maven资源库) -->
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>common</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>common-network</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>common-sdk</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>common-serialport</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>common-udp</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>jna</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx.rfid-r2000</groupId>
+            <artifactId>RXTXcomm</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <!-- RFID相关jar包加载项 end -->
+
+        <!--amqp-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.aspectj</groupId>
+            <artifactId>aspectjweaver</artifactId>
+            <version>1.9.6</version>
+        </dependency>
+
+        <!-- hutool -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.5.8</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.5.1</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                    <includeSystemScope>true</includeSystemScope>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.3.1</version>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+</project>

+ 31 - 0
src/main/java/com/fjhx/Application.java

@@ -0,0 +1,31 @@
+package com.fjhx;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+/**
+ * 启动程序
+ *
+ * @author linqt
+ */
+@EnableAsync
+@SpringBootApplication
+@MapperScan("com.fjhx.business.mapper")
+public class Application {
+    public static void main(String[] args) {
+        SpringApplication.run(Application.class, args);
+        System.err.println("(♥◠‿◠)ノ゙  启动成功   ლ(´ڡ`ლ)゙  \n" +
+                " .-------.       ____     ___       \n" +
+                " |  _ _   \\      \\   \\   /  /    \n" +
+                " | ( ' )  |       \\  _. /  '       \n" +
+                " |(_ o _) /        _( )_ .'         \n" +
+                " | (_,_).' __  ___(_ o _)'          \n" +
+                " |  |\\ \\  |  ||   |(_,_)'         \n" +
+                " |  | \\ `'   /|   `-'  /           \n" +
+                " |  |  \\    /  \\      /           \n" +
+                " ''-'   `'-'    `-..-'              ");
+    }
+}

+ 40 - 0
src/main/java/com/fjhx/business/controller/RfidController.java

@@ -0,0 +1,40 @@
+
+package com.fjhx.business.controller;
+
+import com.fjhx.business.service.IRfidHasauService;
+import com.fjhx.entity.rfid.business.RfidHasau;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Date;
+
+
+/**
+ * rfid控制器
+ *
+ * @author BladeX
+ * @since 2022-07-20
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/rfid")
+public class RfidController {
+
+	private final IRfidHasauService rfidHasauService;
+
+	/**
+	 * 保存
+	 * @return
+	 */
+	@PostMapping("/save")
+	public void getListCount() {
+		RfidHasau hasau = new RfidHasau();
+		hasau.setCreateTime(new Date());
+		rfidHasauService.save(hasau);
+	}
+
+
+
+}

+ 40 - 0
src/main/java/com/fjhx/business/mapper/ProductionLineRouteMapper.java

@@ -0,0 +1,40 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.ProductionLineRoute;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 工艺产线路线表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-08-17
+ */
+public interface ProductionLineRouteMapper extends BaseMapper<ProductionLineRoute> {
+
+    /**
+     * 获取工序ID
+     * @param ip
+     * @param antno
+     * @return
+     */
+    List<ProductionLineRoute> getWorkmanshipId(@Param("ip")String ip, @Param("antno")String antno);
+}

+ 30 - 0
src/main/java/com/fjhx/business/mapper/QrCodeMapper.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+
+import com.fjhx.entity.rfid.QrCode;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * 二维码工单表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+public interface QrCodeMapper extends BaseMapper<QrCode> {
+
+}

+ 30 - 0
src/main/java/com/fjhx/business/mapper/RfidHasauMapper.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.RfidHasau;
+
+/**
+ * rfid已鉴权表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+public interface RfidHasauMapper extends BaseMapper<RfidHasau> {
+
+}

+ 30 - 0
src/main/java/com/fjhx/business/mapper/RfidNoauMapper.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.RfidNoau;
+
+/**
+ * rfid未鉴权表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+public interface RfidNoauMapper extends BaseMapper<RfidNoau> {
+
+}

+ 29 - 0
src/main/java/com/fjhx/business/mapper/TaskMapper.java

@@ -0,0 +1,29 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.Task;
+
+/**
+ * 生产任务表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface TaskMapper extends BaseMapper<Task> {
+
+}

+ 31 - 0
src/main/java/com/fjhx/business/mapper/TaskStepMapper.java

@@ -0,0 +1,31 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.TaskStep;
+
+/**
+ * 任务工序进度表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface TaskStepMapper extends BaseMapper<TaskStep> {
+
+
+}

+ 31 - 0
src/main/java/com/fjhx/business/mapper/WorkFollowMapper.java

@@ -0,0 +1,31 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.WorkFollow;
+
+/**
+ * 生产任务工单跟进表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface WorkFollowMapper extends BaseMapper<WorkFollow> {
+
+
+}

+ 39 - 0
src/main/java/com/fjhx/business/mapper/WorkMapper.java

@@ -0,0 +1,39 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.mapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.entity.rfid.business.Work;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+
+/**
+ * 生产任务工单表 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface WorkMapper extends BaseMapper<Work> {
+
+    /**
+     * 获取工单
+     * @param rfid
+     * @return
+     */
+    List<Work> getWorkList(@Param("rfid")String rfid);
+}

+ 33 - 0
src/main/java/com/fjhx/business/service/IProductionLineRouteService.java

@@ -0,0 +1,33 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.ProductionLineRoute;
+
+import java.util.List;
+
+/**
+ * 工艺产线路线表 服务类
+ *
+ * @author BladeX
+ * @since 2022-08-17
+ */
+public interface IProductionLineRouteService extends IService<ProductionLineRoute> {
+
+    List<ProductionLineRoute> getWorkmanshipId(String ip, String antno);
+}

+ 30 - 0
src/main/java/com/fjhx/business/service/IQrCodeService.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.fjhx.entity.rfid.QrCode;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * 二维码工单表 服务类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+public interface IQrCodeService extends IService<QrCode> {
+
+}

+ 30 - 0
src/main/java/com/fjhx/business/service/IRfidHasauService.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.RfidHasau;
+
+/**
+ * rfid已鉴权表 服务类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+public interface IRfidHasauService extends IService<RfidHasau> {
+
+}

+ 30 - 0
src/main/java/com/fjhx/business/service/IRfidNoauService.java

@@ -0,0 +1,30 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.RfidNoau;
+
+/**
+ * rfid未鉴权表 服务类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+public interface IRfidNoauService extends IService<RfidNoau> {
+
+}

+ 29 - 0
src/main/java/com/fjhx/business/service/ITaskService.java

@@ -0,0 +1,29 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.Task;
+
+/**
+ * 生产任务表 服务类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface ITaskService extends IService<Task> {
+}

+ 31 - 0
src/main/java/com/fjhx/business/service/ITaskStepService.java

@@ -0,0 +1,31 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.TaskStep;
+
+/**
+ * 任务工序进度表 服务类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface ITaskStepService extends IService<TaskStep> {
+
+    void saveTaskStep(String taskId,String workShipId);
+}

+ 35 - 0
src/main/java/com/fjhx/business/service/IWorkFollowService.java

@@ -0,0 +1,35 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.WorkFollow;
+
+/**
+ * 生产任务工单跟进表 服务类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface IWorkFollowService extends IService<WorkFollow> {
+
+    /**
+     * 保存工序流程
+     * @param follow
+     */
+    void saveFollow(String workId,String workShipId);
+}

+ 37 - 0
src/main/java/com/fjhx/business/service/IWorkService.java

@@ -0,0 +1,37 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fjhx.entity.rfid.business.Work;
+
+import java.util.List;
+
+/**
+ * 生产任务工单表 服务类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+public interface IWorkService extends IService<Work> {
+
+    /**
+     * 获取工单
+     * @param rfid
+     * @return
+     */
+    List<Work> getWorkList(String rfid);
+}

+ 46 - 0
src/main/java/com/fjhx/business/service/impl/ProductionLineRouteServiceImpl.java

@@ -0,0 +1,46 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.ProductionLineRouteMapper;
+import com.fjhx.business.service.IProductionLineRouteService;
+import com.fjhx.entity.rfid.business.ProductionLineRoute;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 工艺产线路线表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-08-17
+ */
+@Service
+public class ProductionLineRouteServiceImpl extends ServiceImpl<ProductionLineRouteMapper, ProductionLineRoute> implements IProductionLineRouteService {
+
+    /**
+     * 获取工序ID
+     * @param ip
+     * @param antno
+     * @return
+     */
+    @Override
+    public List<ProductionLineRoute> getWorkmanshipId(String ip, String antno) {
+        return baseMapper.getWorkmanshipId(ip,antno);
+    }
+}

+ 34 - 0
src/main/java/com/fjhx/business/service/impl/QrCodeServiceImpl.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import com.fjhx.business.mapper.QrCodeMapper;
+import com.fjhx.business.service.IQrCodeService;
+import com.fjhx.entity.rfid.QrCode;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * 二维码工单表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+@Service
+public class QrCodeServiceImpl extends ServiceImpl<QrCodeMapper, QrCode> implements IQrCodeService {
+
+}

+ 33 - 0
src/main/java/com/fjhx/business/service/impl/RfidHasauServiceImpl.java

@@ -0,0 +1,33 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.RfidHasauMapper;
+import com.fjhx.business.service.IRfidHasauService;
+import com.fjhx.entity.rfid.business.RfidHasau;
+import org.springframework.stereotype.Service;
+
+/**
+ * rfid已鉴权表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+@Service
+public class RfidHasauServiceImpl extends ServiceImpl<RfidHasauMapper, RfidHasau> implements IRfidHasauService {
+}

+ 34 - 0
src/main/java/com/fjhx/business/service/impl/RfidNoauServiceImpl.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.RfidNoauMapper;
+import com.fjhx.business.service.IRfidNoauService;
+import com.fjhx.entity.rfid.business.RfidNoau;
+import org.springframework.stereotype.Service;
+
+/**
+ * rfid未鉴权表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+@Service
+public class RfidNoauServiceImpl extends ServiceImpl<RfidNoauMapper, RfidNoau> implements IRfidNoauService {
+
+}

+ 33 - 0
src/main/java/com/fjhx/business/service/impl/TaskServiceImpl.java

@@ -0,0 +1,33 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.TaskMapper;
+import com.fjhx.business.service.ITaskService;
+import com.fjhx.entity.rfid.business.Task;
+import org.springframework.stereotype.Service;
+
+/**
+ * 生产任务表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Service
+public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements ITaskService {
+}

+ 54 - 0
src/main/java/com/fjhx/business/service/impl/TaskStepServiceImpl.java

@@ -0,0 +1,54 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.TaskStepMapper;
+import com.fjhx.business.service.ITaskStepService;
+import com.fjhx.entity.rfid.business.TaskStep;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/**
+ * 任务工序进度表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Service
+public class TaskStepServiceImpl extends ServiceImpl<TaskStepMapper, TaskStep> implements ITaskStepService {
+
+    @Override
+    public void saveTaskStep(String taskId,String workShipId) {
+        TaskStep step = getOne(Wrappers.<TaskStep>query().lambda().eq(TaskStep::getTaskId,taskId).eq(TaskStep::getWorkmanshipId,workShipId));
+        if(ObjectUtil.isNotEmpty(step)){//数量加1
+            step.setCompletNum(step.getCompletNum()+1);
+            step.setUpdateTime(new Date());
+            updateById(step);
+        }else{//添加一条新的数据
+            TaskStep addStep = new TaskStep();
+            addStep.setCreateTime(new Date());
+            addStep.setCompletNum(1);
+            addStep.setWorkmanshipId(workShipId);
+            addStep.setTaskId(taskId);
+            save(addStep);
+        }
+    }
+}

+ 55 - 0
src/main/java/com/fjhx/business/service/impl/WorkFollowServiceImpl.java

@@ -0,0 +1,55 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.WorkFollowMapper;
+import com.fjhx.business.service.IWorkFollowService;
+import com.fjhx.entity.rfid.business.Work;
+import com.fjhx.entity.rfid.business.WorkFollow;
+import com.fjhx.utils.DateUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/**
+ * 生产任务工单跟进表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Service
+public class WorkFollowServiceImpl extends ServiceImpl<WorkFollowMapper, WorkFollow> implements IWorkFollowService {
+
+    /**
+     * 保存工序流程
+     * @param follow
+     */
+    @Override
+    public void saveFollow(String workId,String workShipId) {
+        WorkFollow follow = new WorkFollow();
+        follow.setPutTime(DateUtils.getTime());
+        follow.setCreateTime(new Date());
+        follow.setStatus(0);
+        follow.setElapsedTime(0);
+        follow.setWorkId(workId);
+        follow.setWorkmanshipId(workShipId);
+        follow.setCompletTime(DateUtils.getTime());
+        save(follow);
+    }
+}

+ 43 - 0
src/main/java/com/fjhx/business/service/impl/WorkServiceImpl.java

@@ -0,0 +1,43 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.business.service.impl;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.business.mapper.WorkMapper;
+import com.fjhx.business.service.IWorkService;
+import com.fjhx.entity.rfid.business.Work;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 生产任务工单表 服务实现类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Service
+public class WorkServiceImpl extends ServiceImpl<WorkMapper, Work> implements IWorkService {
+    /**
+     * 获取工单
+     * @param rfid
+     * @return
+     */
+    @Override
+    public List<Work> getWorkList(String rfid) {
+        return baseMapper.getWorkList(rfid);
+    }
+}

+ 113 - 0
src/main/java/com/fjhx/config/RFIDConfig.java

@@ -0,0 +1,113 @@
+package com.fjhx.config;
+
+import com.fjhx.entity.rfid.Hyy;
+import com.fjhx.entity.rfid.Log;
+import com.fjhx.entity.rfid.Sd;
+import com.fjhx.entity.rfid.Service;
+import com.fjhx.entity.rfid.Tcp;
+import com.fjhx.entity.rfid.Udp;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Description:
+ * @ClassName: RFIDClientConfig
+ * @Author: linqt
+ * @Date: 2022/3/17 10:55
+ * @Version: 1.0
+ */
+@Component
+@ConfigurationProperties(prefix = "rfid")
+public class RFIDConfig {
+
+    /**
+     * tcp对象
+     */
+    private static Tcp tcp;
+
+    /**
+     * udp对象
+     */
+    private static Udp udp;
+
+    /**
+     * hyy对象
+     */
+    private static Hyy hyy;
+
+    /**
+     * 业务服务对象
+     */
+    private static Service service;
+
+    /**
+     * 胜德集团对象
+     */
+    private static Sd sd;
+
+    /**
+     * log对象
+     */
+    private static Log log;
+
+    /**
+     * 读取RFID间隔时间(单位:ms),超过该时间则认为是新的RFID
+     */
+    private static Integer defaultTime;
+
+    public static Tcp getTcp() {
+        return tcp;
+    }
+
+    public void setTcp(Tcp tcp) {
+        RFIDConfig.tcp = tcp;
+    }
+
+    public static Udp getUdp() {
+        return udp;
+    }
+
+    public void setUdp(Udp udp) {
+        RFIDConfig.udp = udp;
+    }
+
+    public static Hyy getHyy() {
+        return hyy;
+    }
+
+    public void setHyy(Hyy hyy) {
+        RFIDConfig.hyy = hyy;
+    }
+
+    public static Service getService() {
+        return service;
+    }
+
+    public void setService(Service service) {
+        RFIDConfig.service = service;
+    }
+
+    public static Sd getSd() {
+        return sd;
+    }
+
+    public void setSd(Sd sd) {
+        RFIDConfig.sd = sd;
+    }
+
+    public static Log getLog() {
+        return log;
+    }
+
+    public void setLog(Log log) {
+        RFIDConfig.log = log;
+    }
+
+    public static Integer getDefaultTime() {
+        return defaultTime;
+    }
+
+    public void setDefaultTime(Integer defaultTime) {
+        RFIDConfig.defaultTime = defaultTime;
+    }
+}

+ 19 - 0
src/main/java/com/fjhx/constant/ApiConstant.java

@@ -0,0 +1,19 @@
+package com.fjhx.constant;
+
+/**
+ * @Author:caozj
+ * @DATE:2022/9/8 14:38
+ */
+public class ApiConstant {
+
+    public static final String URL = "http://192.168.2.15:8126";
+    /**
+     * 推送通道
+     */
+    public static final String PUSH_ANTNO = URL+"/saas/production/userantno/pushAntno";
+
+    /**
+     * 绑定工单
+     */
+    public static final String BIND_WORK = URL+"/saas/production/work/bindWork";
+}

+ 88 - 0
src/main/java/com/fjhx/constant/HttpStatus.java

@@ -0,0 +1,88 @@
+package com.fjhx.constant;
+
+/**
+ * 返回状态码
+ *
+ * @author linqt
+ */
+public class HttpStatus {
+    /**
+     * 操作成功
+     */
+    public static final int SUCCESS = 200;
+
+    /**
+     * 对象创建成功
+     */
+    public static final int CREATED = 201;
+
+    /**
+     * 请求已经被接受
+     */
+    public static final int ACCEPTED = 202;
+
+    /**
+     * 操作已经执行成功,但是没有返回数据
+     */
+    public static final int NO_CONTENT = 204;
+
+    /**
+     * 资源已被移除
+     */
+    public static final int MOVED_PERM = 301;
+
+    /**
+     * 重定向
+     */
+    public static final int SEE_OTHER = 303;
+
+    /**
+     * 资源没有被修改
+     */
+    public static final int NOT_MODIFIED = 304;
+
+    /**
+     * 参数列表错误(缺少,格式不匹配)
+     */
+    public static final int BAD_REQUEST = 400;
+
+    /**
+     * 未授权
+     */
+    public static final int UNAUTHORIZED = 401;
+
+    /**
+     * 访问受限,授权过期
+     */
+    public static final int FORBIDDEN = 403;
+
+    /**
+     * 资源,服务未找到
+     */
+    public static final int NOT_FOUND = 404;
+
+    /**
+     * 不允许的http方法
+     */
+    public static final int BAD_METHOD = 405;
+
+    /**
+     * 资源冲突,或者资源被锁
+     */
+    public static final int CONFLICT = 409;
+
+    /**
+     * 不支持的数据,媒体类型
+     */
+    public static final int UNSUPPORTED_TYPE = 415;
+
+    /**
+     * 系统内部错误
+     */
+    public static final int ERROR = 500;
+
+    /**
+     * 接口未实现
+     */
+    public static final int NOT_IMPLEMENTED = 501;
+}

+ 105 - 0
src/main/java/com/fjhx/constant/RFIDConstant.java

@@ -0,0 +1,105 @@
+package com.fjhx.constant;
+
+/**
+ * @Description:
+ * @ClassName: RFIDConstant
+ * @Author: linqt
+ * @Date: 2022/3/18 11:29
+ * @Version: 1.0
+ */
+public class RFIDConstant {
+
+    /**
+     * 读写器启动成功
+     */
+    public static final String SERVER_START_SUCCESS = "IP为【{0}】的读写器启动成功,开始读取数据!";
+
+    /**
+     * 读写器启动失败
+     */
+    public static final String SERVER_START_ERR = "IP为【{0}】的读写器启动失败!";
+
+    /**
+     * 读写器关闭成功
+     */
+    public static final String SERVER_CLOSE_SUCCESS = "IP为【{0}】的读写器关闭成功,停止读取数据!";
+
+    /**
+     * 读写器关闭失败
+     */
+    public static final String SERVER_CLOSE_ERR = "IP为【{0}】的读写器关闭失败!";
+
+    /**
+     * 读取数据成功
+     */
+    public static final String READ_DATA_SUCCESS = "读取数据成功!";
+    /**
+     * 读取数据失败
+     */
+    public static final String READ_DATA_ERR = "读取数据失败!";
+
+    /**
+     * rfid udp默认绑定端口
+     */
+    public static final Integer RFID_UDP_DEFAULT_BINDING_PORT = 0;
+
+    /**
+     * rfid udp开始读取数据指令
+     */
+    public static final String RFID_UDP_START_READ_INSTRUCTION = "A50401005501";
+
+    /**
+     * rfid udp停止读取数据指令
+     */
+    public static final String RFID_UDP_STOP_READ_INSTRUCTION = "A504010060F6";
+
+    /**
+     * UDP返回数据截取天线号开始下标(从14开始)
+     */
+    public static final Integer UDP_RESULT_DATA_SUBSTRING_ANT_NO_BEGIN_INDEX = 14;
+
+    /**
+     * UDP返回数据截取天线号结束下标(到16结束)
+     */
+    public static final Integer UDP_RESULT_DATA_SUBSTRING_ANT_NO_END_INDEX = 16;
+
+    /**
+     * UDP返回数据截取RFID开始下标(从21开始)
+     */
+    public static final Integer UDP_RESULT_DATA_SUBSTRING_RFID_BEGIN_INDEX = 20;
+
+    /**
+     * UDP返回数据截取RFID结束下标(从最后往前推10位)
+     */
+    public static final Integer UDP_RESULT_DATA_SUBSTRING_RFID_END_INDEX = 10;
+
+    /**
+     * 指令类型常量类
+     */
+    public static final class InstructType {
+        /**
+         * 开始并返回所有数据
+         */
+        public static final Integer INSTRUCT_TYPE_1 = 1;
+
+        /**
+         * 开始并返回去重数据
+         */
+        public static final Integer INSTRUCT_TYPE_2 = 2;
+
+        /**
+         * 关闭
+         */
+        public static final Integer INSTRUCT_TYPE_3 = 3;
+    }
+
+    /**
+     * 读取RFID间隔时间(单位:ms),超过该时间则认为是新的RFID
+     */
+    public static final Integer DEFAULT_TIME = 5000;
+
+    /**
+     * RFID缓存存活时间
+     */
+    public static final Integer RFID_CACHE_TIME = 60;
+}

+ 31 - 0
src/main/java/com/fjhx/constant/RedisKeyConstant.java

@@ -0,0 +1,31 @@
+package com.fjhx.constant;
+
+/**
+ * @Description:
+ * @ClassName: RedisKeyConstant
+ * @Author: linqt
+ * @Date: 2022/3/18 9:25
+ * @Version: 1.0
+ */
+public class RedisKeyConstant {
+
+    /**
+     * rabbitmq缓存key
+     */
+    public static final String RABBITMQ_REDIS_CACHE_KEY = "rabbitmq:messageId:";
+
+    /**
+     * rfid tcp数据缓存key前缀
+     */
+    public static final String RFID_TCP_DATA_REDIS_CACHE_PREFIX = "rfid:tcp:{0}:data";
+
+    /**
+     * rfid udp数据缓存key前缀
+     */
+    public static final String RFID_UDP_DATA_REDIS_CACHE_PREFIX = "rfid:udp:{0}:data";
+
+    /**
+     * rfid 缓存key前缀
+     */
+    public static final String RFID_REDIS_CACHE_PREFIX = "sd:rfid:{0}:data";
+}

+ 81 - 0
src/main/java/com/fjhx/entity/enums/AntnoStatusEnum.java

@@ -0,0 +1,81 @@
+package com.fjhx.entity.enums;
+
+import org.apache.commons.collections4.MapUtils;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 数据类型枚举
+ */
+public enum AntnoStatusEnum {
+
+    STATUS_2("2", "纠偏"),
+    STATUS_4("4", "检测瑕疵"),
+    STATUS_3("3", "激光"),
+    STATUS_1("1", "质检"),
+    ;
+
+    private String key;
+
+    private String value;
+
+    private static Map<String, String> map = new LinkedHashMap<>();
+
+    AntnoStatusEnum(String key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+     * 是否存在
+     *
+     * @param key
+     * @return
+     */
+    public static boolean contain(Integer key) {
+        if (key == null) {
+            return false;
+        }
+        Map<String, String> map = getMap();
+        return map.containsKey(key);
+    }
+
+    /**
+     * 获取枚举map
+     *
+     * @return
+     */
+    public static Map<String, String> getMap() {
+        if (MapUtils.isNotEmpty(map)) {
+            return map;
+        }
+        for (AntnoStatusEnum ms : values()) {
+            map.put(ms.key, ms.value);
+        }
+        return map;
+    }
+
+    /**
+     * 通过key获取名称
+     *
+     * @param key
+     * @return
+     */
+    public static String getNameByKey(Integer key) {
+        if (key == null || key < 0) {
+            return "";
+        }
+        Map<String, String> map = getMap();
+        return map.getOrDefault(key, "");
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}

+ 18 - 0
src/main/java/com/fjhx/entity/rfid/Hyy.java

@@ -0,0 +1,18 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+@Data
+public class Hyy {
+
+    /**
+     * 服务器ID
+     */
+    private String ip;
+
+    /**
+     * 服务器端口
+     */
+    private Integer port;
+
+}

+ 13 - 0
src/main/java/com/fjhx/entity/rfid/Log.java

@@ -0,0 +1,13 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+@Data
+public class Log {
+
+    /**
+     * 日志保存路径
+     */
+    private String savePath;
+
+}

+ 65 - 0
src/main/java/com/fjhx/entity/rfid/QrCode.java

@@ -0,0 +1,65 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import lombok.Data;
+/**
+ * 二维码工单表实体类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+@Data
+@TableName("t_pro_qr_code")
+public class QrCode implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	* 订单id
+	*/
+	private String id;
+	/**
+	* 二维码
+	*/
+	private String qrcode;
+	/**
+	* 视觉设备标识
+	*/
+	private String veId;
+	/**
+	* 创建者ID
+	*/
+	private String createUser;
+	/**
+	* 创建时间
+	*/
+	private LocalDateTime createTime;
+	/**
+	* 更新者iID
+	*/
+	private String updateUser;
+	/**
+	* 更新时间
+	*/
+	private LocalDateTime updateTime;
+
+
+}

+ 51 - 0
src/main/java/com/fjhx/entity/rfid/RFIDClient.java

@@ -0,0 +1,51 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description: RFID读写器
+ * @ClassName: RFIDClient
+ * @Author: linqt
+ * @Date: 2022/3/16 11:38
+ * @Version: 1.0
+ */
+@Data
+public class RFIDClient {
+
+    /**
+     * 读写器IP
+     */
+    private String ip;
+
+    /**
+     * 读写器端口
+     */
+    private int port;
+
+    /**
+     * 多个读写器IP
+     */
+    private List<String> ipList;
+
+    /**
+     * 读取时间
+     */
+    private Long readTime;
+
+    /**
+     * 编号
+     */
+    private Integer num;
+
+    /**
+     * 用户账号
+     */
+    private String userName;
+
+    /**
+     * 是否推送到华为云IOT平台
+     */
+    private Boolean isSendIot;
+}

+ 18 - 0
src/main/java/com/fjhx/entity/rfid/Sd.java

@@ -0,0 +1,18 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+@Data
+public class Sd {
+
+    /**
+     * tcp信息
+     */
+    private Tcp tcp;
+
+    /**
+     * udp信息
+     */
+    private Udp udp;
+
+}

+ 18 - 0
src/main/java/com/fjhx/entity/rfid/Service.java

@@ -0,0 +1,18 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+@Data
+public class Service {
+
+    /**
+     * 服务器ID
+     */
+    private String ip;
+
+    /**
+     * 服务器端口
+     */
+    private Integer port;
+
+}

+ 20 - 0
src/main/java/com/fjhx/entity/rfid/Tcp.java

@@ -0,0 +1,20 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Tcp {
+
+    /**
+     * 读写器IP集合
+     */
+    private List<String> ips;
+
+    /**
+     * 读写器端口
+     */
+    private Integer port;
+
+}

+ 20 - 0
src/main/java/com/fjhx/entity/rfid/Udp.java

@@ -0,0 +1,20 @@
+package com.fjhx.entity.rfid;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class Udp {
+
+    /**
+     * 读写器IP集合
+     */
+    private List<String> ips;
+
+    /**
+     * 读写器端口
+     */
+    private Integer port;
+
+}

+ 107 - 0
src/main/java/com/fjhx/entity/rfid/base/BasicsEntity.java

@@ -0,0 +1,107 @@
+package com.fjhx.entity.rfid.base;
+import com.baomidou.mybatisplus.annotation.TableField;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 基础实体类
+ */
+public abstract class BasicsEntity implements Serializable {
+
+    private static final long serialVersionUID = 3568046178869491465L;
+
+    /**
+     * 主键id
+     */
+    private String id;
+
+    /**
+     * 创建人id
+     */
+    private String createUser;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新人id
+     */
+    private String updateUser;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 当前页
+     */
+    @TableField(exist = false)
+
+    private Integer pageNum =1;
+
+    /**
+     * 每页显示条数
+     */
+    @TableField(exist = false)
+    private Integer pageSize =10;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCreateUser() {
+        return createUser;
+    }
+
+    public void setCreateUser(String createUser) {
+        this.createUser = createUser;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getUpdateUser() {
+        return updateUser;
+    }
+
+    public void setUpdateUser(String updateUser) {
+        this.updateUser = updateUser;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Integer getPageNum() {
+        return pageNum;
+    }
+
+    public void setPageNum(Integer pageNum) {
+        this.pageNum = pageNum;
+    }
+
+    public Integer getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize) {
+        this.pageSize = pageSize;
+    }
+}

+ 65 - 0
src/main/java/com/fjhx/entity/rfid/business/ProductionLineRoute.java

@@ -0,0 +1,65 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 工艺产线路线表实体类
+ *
+ * @author BladeX
+ * @since 2022-08-17
+ */
+@Data
+@TableName("t_sd_production_line_route")
+public class ProductionLineRoute{
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 主键id
+	 */
+	private String id;
+	/**
+	 * 工艺产线ID
+	 */
+	private String productionLineId;
+	/**
+	 * 工艺表ID
+	 */
+	private String workmanshipId;
+	/**
+	 * 设备表ID
+	 */
+	private String deviceManagementId;
+
+	/**
+	 * rfidIp
+	 */
+	private String rfidIp;
+
+	/**
+	 * rfid通道
+	 */
+	private String rfidPassageway;
+
+	/**
+	 * 排序
+	 */
+	private Integer sort;
+
+}

+ 91 - 0
src/main/java/com/fjhx/entity/rfid/business/RfidHasau.java

@@ -0,0 +1,91 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+/**
+ * rfid已鉴权表实体类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+@Data
+@TableName("t_pro_rfid_hasau")
+public class RfidHasau implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	* id
+	*/
+	private String id;
+	/**
+	* rfid
+	*/
+	private String rfid;
+	/**
+	* ip值
+	*/
+	private String ip;
+	/**
+	* 工单ID
+	*/
+	private String workId;
+	/**
+	* bom主材ID
+	*/
+	private String bomColorId;
+	/**
+	* 产品规格ID
+	*/
+	private String productColorId;
+	/**
+	 * 工艺产线ID
+	 */
+	private String productLineId;
+	/**
+	* 订单ID
+	*/
+	private String contractId;
+	/**
+	* 订单产品ID
+	*/
+	private String contractProductId;
+	/**
+	* 工序ID
+	*/
+	private String workmanshipId;
+	/**
+	* 通道(工序)
+	*/
+	private String antno;
+	/**
+	* 是否删除  0:否  1:是
+	*/
+	private Integer delFlag;
+	/**
+	* 创建时间
+	*/
+	private Date createTime;
+
+
+}

+ 68 - 0
src/main/java/com/fjhx/entity/rfid/business/RfidNoau.java

@@ -0,0 +1,68 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * rfid未鉴权表实体类
+ *
+ * @author BladeX
+ * @since 2022-09-01
+ */
+@Data
+@TableName("t_pro_rfid_noau")
+public class RfidNoau implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	* id
+	*/
+	private String id;
+	/**
+	* rfid
+	*/
+	private String rfid;
+	/**
+	* ip值
+	*/
+	private String ip;
+	/**
+	* 通道(工序)
+	*/
+	private String antno;
+	/**
+	* 工序ID
+	*/
+	private String workmanshipId;
+	/**
+	* 是否删除  0:否  1:是
+	*/
+	private Integer delFlag;
+	/**
+	* 创建时间
+	*/
+	private Date createTime;
+
+
+}

+ 98 - 0
src/main/java/com/fjhx/entity/rfid/business/Task.java

@@ -0,0 +1,98 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fjhx.entity.rfid.base.BasicsEntity;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 生产任务表实体类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Data
+@TableName("t_pro_task")
+public class Task extends BasicsEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	* 订单ID
+	*/
+	private String contractId;
+
+	/**
+	 * 产品ID
+	 */
+	private String productId;
+
+	/**
+	 * 产品规格ID
+	 */
+	private String productColorId;
+
+	/**
+	* 工艺线路ID
+	*/
+	private String processLineId;
+	/**
+	* 生产状态 0:待投产  10:生产中 20:待发货 30:已发货  40:订单结束
+	*/
+	private Integer status;
+	/**
+	* 真实投产时间
+	*/
+	private Date putTime;
+	/**
+	* 计划投产时间
+	*/
+	private Date planTime;
+	/**
+	 * 计划投产结束时间
+	 */
+	private Date planEndTime;
+	/**
+	* 完成时间
+	*/
+	private String completTime;
+	/**
+	* 生产用时(秒)
+	*/
+	private Integer elapsedTime;
+	/**
+	* 完成数量
+	*/
+	private Integer completNum;
+
+	/**
+	 * 完成数量
+	 */
+	private BigDecimal quantity;
+
+	/**
+	* 描述
+	*/
+	private String remark;
+	/**
+	* 是否结束
+	*/
+	private Integer isEnd;
+}

+ 57 - 0
src/main/java/com/fjhx/entity/rfid/business/TaskStep.java

@@ -0,0 +1,57 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fjhx.entity.rfid.base.BasicsEntity;
+import lombok.Data;
+
+/**
+ * 任务工序进度表实体类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Data
+@TableName("t_pro_task_step")
+public class TaskStep extends BasicsEntity {
+
+	private static final long serialVersionUID = 1L;
+
+
+	/**
+	* 任务ID
+	*/
+	private String taskId;
+	/**
+	* 工序ID
+	*/
+	private String workmanshipId;
+	/**
+	* 状态 0:正常  1删除
+	*/
+	private Integer status;
+	/**
+	* 完成数量
+	*/
+	private Integer completNum;
+	/**
+	* 描述
+	*/
+	private String remark;
+
+}

+ 100 - 0
src/main/java/com/fjhx/entity/rfid/business/Work.java

@@ -0,0 +1,100 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+/**
+ * 生产任务工单表实体类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Data
+@TableName("t_pro_work")
+public class Work {
+
+    private static final long serialVersionUID = 1L;
+
+
+    private String id;
+    /**
+     * 任务ID
+     */
+    private String taskId;
+
+    /**
+     * 工艺线路ID
+     */
+    private String processLineId;
+
+    /**
+     * 合同ID
+     */
+    private String contractId;
+
+    /**
+     * 工单号
+     */
+    private String code;
+
+    /**
+     * 产品规格ID
+     */
+    private String productColorId;
+    /**
+     * 真实投产时间
+     */
+    private String putTime;
+    /**
+     * 完成时间
+     */
+    private String completTime;
+    /**
+     * 生产用时(秒)
+     */
+    private Integer elapsedTime;
+    /**
+     * rfid
+     */
+    private String rfid;
+    /**
+     * 描述
+     */
+    private String remark;
+    /**
+     * 生产状态 0:待生产  10:生产中 30:已完成
+     */
+    private Integer status;
+
+    /**
+     * 唯一标识
+     */
+    private String uuid;
+
+    /**
+     * 通道
+     */
+    private String antnos;
+    /**
+     * bom规格ID
+     */
+    @TableField(exist = false)
+    private String bomColorId;
+}

+ 62 - 0
src/main/java/com/fjhx/entity/rfid/business/WorkFollow.java

@@ -0,0 +1,62 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.entity.rfid.business;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fjhx.entity.rfid.base.BasicsEntity;
+import lombok.Data;
+
+/**
+ * 生产任务工单跟进表实体类
+ *
+ * @author BladeX
+ * @since 2022-08-19
+ */
+@Data
+@TableName("t_pro_work_follow")
+public class WorkFollow extends BasicsEntity {
+
+	private static final long serialVersionUID = 1L;
+	/**
+	* 工单ID
+	*/
+	private String workId;
+	/**
+	* 工序ID
+	*/
+	private String workmanshipId;
+	/**
+	* 状态 0:成功  1:失败  2:生产中
+	*/
+	private Integer status;
+	/**
+	* 投产时间
+	*/
+	private String putTime;
+	/**
+	* 完成时间
+	*/
+	private String completTime;
+	/**
+	* 生产用时(秒)
+	*/
+	private Integer elapsedTime;
+	/**
+	* 描述
+	*/
+	private String remark;
+
+}

+ 55 - 0
src/main/java/com/fjhx/rabbitmq/JsRabbitMQListener.java

@@ -0,0 +1,55 @@
+package com.fjhx.rabbitmq;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.rfid.r2000.common.service.IRFIDService;
+import com.rabbitmq.client.Channel;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Component;
+
+import java.nio.charset.StandardCharsets;
+
+/**
+ * rabbitmq队列监听工具
+ */
+@EnableRetry
+@Component
+public class JsRabbitMQListener implements ChannelAwareMessageListener {
+
+    @Autowired
+    private IRFIDService rfidService;
+
+    @RabbitHandler
+    @RabbitListener(
+            queues = {
+                    "rfid1_to_rfid2_queue"
+            },
+            concurrency = "8"
+    )
+    @Retryable(value = {Exception.class}, backoff = @Backoff(delay = 3000, multiplier = 1))
+    @Override
+    public void onMessage(Message message, Channel channel) throws Exception {
+        try {
+            String msg = new String(message.getBody(), StandardCharsets.UTF_8);
+            JSONObject jsonObject = JSONObject.parseObject(msg);
+
+            rfidService.receiveInstructions(jsonObject);
+
+            // 手动签收消息,通知mq服务器端删除该消息
+            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        } catch (Exception e) {
+            e.printStackTrace();
+            // 丢弃该消息
+            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
+            throw e;
+        }
+    }
+
+}
+

+ 249 - 0
src/main/java/com/fjhx/rabbitmq/RabbitMQListener.java

@@ -0,0 +1,249 @@
+package com.fjhx.rabbitmq;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fjhx.business.service.*;
+import com.fjhx.constant.ApiConstant;
+import com.fjhx.entity.rfid.QrCode;
+import com.fjhx.entity.rfid.business.*;
+import com.fjhx.rfid.r2000.common.service.IRFIDService;
+import com.fjhx.utils.DateUtils;
+import com.fjhx.utils.HttpUtils;
+import com.fjhx.utils.MapUtil;
+import com.google.common.collect.Interner;
+import com.google.common.collect.Interners;
+import com.rabbitmq.client.Channel;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * rabbitmq队列监听工具
+ */
+@EnableRetry
+@Component
+public class RabbitMQListener implements ChannelAwareMessageListener {
+
+    @Autowired
+    private IRFIDService irfidService;
+
+    @Autowired
+    private IRfidHasauService iRfidHasauService;
+
+    @Autowired
+    private IRfidNoauService iRfidNoauService;
+
+    @Autowired
+    private IProductionLineRouteService iProductionLineRouteService;
+
+    @Autowired
+    private IWorkService iWorkService;
+
+    @Autowired
+    private IQrCodeService qrCodeService;
+
+    @Autowired
+    private IWorkFollowService iWorkFollowService;
+
+    @Autowired
+    private ITaskStepService taskStepService;
+
+    //弱引用
+    private static Interner<String> lock = Interners.newWeakInterner();
+
+    @RabbitHandler
+    @RabbitListener(
+            queues = {
+                    "rfid_to_sd_queue"
+            },
+            concurrency = "8"
+    )
+    @Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 3000, multiplier = 1))
+    @Override
+    public void onMessage(Message message, Channel channel) throws Exception {
+        try {
+            String msg = new String(message.getBody(), "UTF-8");
+            JSONObject jsonObject = JSONObject.parseObject(msg);
+            rfid(jsonObject);
+            System.err.println(jsonObject.toJSONString());
+            // 手动签收消息,通知mq服务器端删除该消息
+            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        } catch (Exception e) {
+            e.printStackTrace();
+            // 丢弃该消息
+            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
+            throw e;
+        }
+    }
+
+
+    @Transactional(rollbackFor = Exception.class)
+    public void rfid(JSONObject jsonObject){
+        System.out.println(System.currentTimeMillis());
+        List<String> list = new ArrayList<>();
+        list.add("1");
+        list.add("2");
+        list.add("3");
+        //如果返回数据存在
+        if(jsonObject.containsKey("rfidMsg")) {
+            String antno = jsonObject.getJSONObject("rfidMsg").get("ANTNO").toString();
+            String ip = jsonObject.getJSONObject("rfidMsg").get("IP").toString();
+            String rfid = jsonObject.getJSONObject("rfidMsg").get("RFID").toString();
+            synchronized (lock.intern(rfid)) {
+                if(StringUtils.equals("16",antno)){
+                    Map<String,Object> map = new HashMap<>();
+                    map.put("rfid",rfid);
+                    map.put("antno",antno);
+                    HttpUtils.sendPost(ApiConstant.PUSH_ANTNO, JSON.toJSONString(map));
+                    List<ProductionLineRoute> productionLineRoutes = iProductionLineRouteService.getWorkmanshipId(ip, antno);
+                    //工序肯定只有一条
+                    if (productionLineRoutes.size() == 1) {
+                        //取出工序数据
+                        ProductionLineRoute route = productionLineRoutes.get(0);
+                        //判断当前rfid是否已经绑定过工单
+                        long workCount = iWorkService.count(Wrappers.<Work>query().
+                                lambda()
+                                .eq(Work::getRfid, rfid)
+                                .ne(Work::getStatus, 30));
+                        if (workCount ==1) {
+                            //取出这条工单
+                            Work work = iWorkService.getOne(Wrappers.<Work>query().
+                                    lambda()
+                                    .eq(Work::getRfid, rfid)
+                                    .ne(Work::getStatus, 30)
+                                    .last("limit 1"));
+                            if (ObjectUtil.isNotEmpty(work)){
+                                //判断当前这条工单工序是否存在
+                                long count = iWorkFollowService.count(Wrappers.<WorkFollow>query().lambda().
+                                        eq(WorkFollow::getWorkId,work.getId()).
+                                        eq(WorkFollow::getWorkmanshipId,route.getWorkmanshipId()));
+                                //不存在
+                                if(count==0){
+                                    //添加工序流程
+                                    iWorkFollowService.saveFollow(work.getId(), route.getWorkmanshipId());
+                                    //添加任务流程
+                                    taskStepService.saveTaskStep(work.getTaskId(), route.getWorkmanshipId());
+                                }
+                            }
+                        }
+                    }
+                }else{
+                    //取出工序ID
+                    List<ProductionLineRoute> productionLineRoutes = iProductionLineRouteService.getWorkmanshipId(ip, antno);
+                    //工序肯定只有一条
+                    if (productionLineRoutes.size() == 1) {
+                        //取出工序数据
+                        ProductionLineRoute route = productionLineRoutes.get(0);
+                        List<String> geways = Arrays.asList(route.getRfidPassageway().split(","));
+                        //判断当前通道是不是第一道工序
+                        if (list.contains(antno)) {
+                            //判断当前rfid是否已经绑定过工单
+                            long workCount = iWorkService.count(Wrappers.<Work>query().
+                                    lambda()
+                                    .eq(Work::getRfid, rfid)
+                                    .ne(Work::getStatus, 30));
+                            if (workCount == 0) {
+                                //取出最新的那一条二维码工单
+                                QrCode qrCode = qrCodeService.getOne(Wrappers.<QrCode>query().
+                                        lambda().eq(QrCode::getVeId, 1).
+                                        orderByDesc(QrCode::getCreateTime).
+                                        last("limit 1"));
+//                                String[] code = qrCode.getQrcode().split("-");
+                                if (ObjectUtil.isNotEmpty(qrCode)) {
+                                    //绑定工单
+                                    Map<String,Object> map = new HashMap<>();
+                                    map.put("rfid",rfid);
+                                    map.put("qrCode",qrCode.getQrcode());
+                                    map.put("workShipId",route.getWorkmanshipId());
+                                    HttpUtils.sendPost(ApiConstant.BIND_WORK, JSON.toJSONString(map));
+//                                    //取出这条工单
+//                                    Work work = iWorkService.getOne(Wrappers.<Work>query().
+//                                            lambda()
+//                                            .eq(Work::getTaskId, code[0])
+//                                            .eq(Work::getRfid, "0")
+//                                            .eq(Work::getUuid,"0")
+//                                            .orderByAsc(Work::getCode)
+//                                            .ne(Work::getStatus, 30)
+//                                            .last("limit 1"));
+//                                    if (ObjectUtil.isNotEmpty(work) && StringUtils.equals(work.getRfid(),"0")&& StringUtils.equals(work.getUuid(),"0")) {
+//                                        //绑定rfid
+//                                        work.setRfid(rfid);
+//                                        work.setUuid(code[1]);
+//                                        work.setPutTime(DateUtils.getTime());
+//                                        work.setStatus(10);//把状态改成生产中
+//                                        iWorkService.updateById(work);
+//                                        //添加工序流程
+//                                        iWorkFollowService.saveFollow(work.getId(), route.getWorkmanshipId());
+//                                        //添加任务流程
+//                                        taskStepService.saveTaskStep(work.getTaskId(), route.getWorkmanshipId());
+//                                    }
+                                    //清理当前这条数据之前得qrcode
+                                    qrCodeService.remove(Wrappers.<QrCode>query().lambda().
+                                            eq(QrCode::getVeId, 1).le(QrCode::getCreateTime, qrCode.getCreateTime()));
+                                }
+                            }
+                        } else {//其他通道的数据
+                            //判断当前rfid是否绑定了工单
+                            List<Work> workList = iWorkService.getWorkList(rfid);
+                            if (workList.size() == 1) {//有绑定工单
+                                Work work = workList.get(0);
+                                //判断数据库是否存在这条通道得数据,不是:添加数据   是:直接略过
+                                long count = iRfidHasauService.count(Wrappers.<RfidHasau>query().lambda().
+                                        in(RfidHasau::getAntno, geways).eq(RfidHasau::getIp, ip).
+                                        eq(RfidHasau::getDelFlag, 0)
+                                        .eq(RfidHasau::getRfid, rfid));
+                                if (count == 0) {
+                                    List<String> workAntno = Arrays.asList(work.getAntnos().split(","));
+                                    if(!workAntno.containsAll(geways)){
+                                        //                                    //判断当前这条工单工序是否存在
+//                                    long workFollowCount = iWorkFollowService.count(Wrappers.<WorkFollow>query().lambda().
+//                                            eq(WorkFollow::getWorkId,work.getId()).
+//                                            eq(WorkFollow::getWorkmanshipId,route.getWorkmanshipId()));
+//                                    //不存在
+//                                    if(workFollowCount==0){
+                                        RfidHasau hasau = new RfidHasau();
+                                        hasau.setCreateTime(new Date());
+                                        hasau.setIp(ip);
+                                        hasau.setRfid(rfid);
+                                        hasau.setAntno(antno);
+                                        hasau.setWorkmanshipId(route.getWorkmanshipId());
+                                        hasau.setContractId(work.getContractId());
+                                        hasau.setContractProductId(work.getTaskId());
+                                        hasau.setBomColorId(work.getBomColorId());
+                                        hasau.setProductLineId(work.getProcessLineId());
+                                        hasau.setProductColorId(work.getProductColorId());
+                                        hasau.setWorkId(work.getId());
+                                        iRfidHasauService.save(hasau);
+                                        //处理work
+                                        if(workAntno.size()!=1){
+                                            geways.addAll(workAntno);
+                                        }
+                                        work.setAntnos(String.join(",", geways));
+                                        iWorkService.updateById(work);
+//                                    }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
+

+ 87 - 0
src/main/java/com/fjhx/rabbitmq/RabbitMQProducer.java

@@ -0,0 +1,87 @@
+package com.fjhx.rabbitmq;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.redis.RedisCache;
+import org.springframework.amqp.AmqpException;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageBuilder;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 消息发送接口实现类
+ */
+@Component
+public class RabbitMQProducer implements ConfirmCallback {
+
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Value("${spring.rabbitmq.send.socket.exchange}")
+    public String exchange;
+
+    @Value("${spring.rabbitmq.send.socket.routingKey}")
+    public String routingKey;
+
+    @Value("${spring.rabbitmq.cache.time-out}")
+    public Integer timeOut;
+
+    /**
+     * rabbitmq缓存key
+     */
+    private final String rabbitmqKey = RedisKeyConstant.RABBITMQ_REDIS_CACHE_KEY;
+
+    /**
+     * 消息发送机制
+     *
+     * @param data 内容
+     */
+    public void send(JSONObject data) {
+        try {
+            // 消息唯一id
+            String messageId = data.getString("messageId");
+            String msg = data.toJSONString();
+
+            // 存入缓存
+            redisCache.setCacheObject(rabbitmqKey + messageId, data, timeOut, TimeUnit.SECONDS);
+
+            // 封装消息
+            Message message = MessageBuilder.withBody(msg.getBytes())
+                    .setContentType(MessageProperties.CONTENT_TYPE_JSON).setContentEncoding("UTF-8")
+                    .setMessageId(messageId).build();
+            // 构建回调返回的数据
+            CorrelationData correlationData = new CorrelationData(messageId);
+            // 发送消息
+            this.rabbitTemplate.setMandatory(true);
+            this.rabbitTemplate.setConfirmCallback(this);
+            rabbitTemplate.convertAndSend(exchange, routingKey, message, correlationData);
+        } catch (AmqpException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
+        // id 都是相同的哦 全局ID
+        String messageId = correlationData.getId();
+        // 消息发送失败,则继续发送
+        if (!ack) {
+            // 查询消息是否存在,当消息不存在得时候记录消息
+            JSONObject jsonObject = redisCache.getCacheObject(rabbitmqKey + messageId);
+            // 重试机制
+            send(jsonObject);
+        }
+    }
+
+}

+ 87 - 0
src/main/java/com/fjhx/rabbitmq/SdRabbitMQProducer.java

@@ -0,0 +1,87 @@
+package com.fjhx.rabbitmq;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.redis.RedisCache;
+import org.springframework.amqp.AmqpException;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.core.MessageBuilder;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.rabbit.connection.CorrelationData;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 消息发送接口实现类
+ */
+@Component
+public class SdRabbitMQProducer implements ConfirmCallback {
+
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Value("${spring.rabbitmq.send.sd.exchange}")
+    public String exchange;
+
+    @Value("${spring.rabbitmq.send.sd.routingKey}")
+    public String routingKey;
+
+    @Value("${spring.rabbitmq.cache.time-out}")
+    public Integer timeOut;
+
+    /**
+     * rabbitmq缓存key
+     */
+    private final String rabbitmqKey = RedisKeyConstant.RABBITMQ_REDIS_CACHE_KEY;
+
+    /**
+     * 消息发送机制
+     *
+     * @param data 内容
+     */
+    public void send(JSONObject data) {
+        try {
+            // 消息唯一id
+            String messageId = data.getString("messageId");
+            String msg = data.toJSONString();
+
+            // 存入缓存
+            redisCache.setCacheObject(rabbitmqKey + messageId, data, timeOut, TimeUnit.SECONDS);
+
+            // 封装消息
+            Message message = MessageBuilder.withBody(msg.getBytes())
+                    .setContentType(MessageProperties.CONTENT_TYPE_JSON).setContentEncoding("UTF-8")
+                    .setMessageId(messageId).build();
+            // 构建回调返回的数据
+            CorrelationData correlationData = new CorrelationData(messageId);
+            // 发送消息
+            this.rabbitTemplate.setMandatory(true);
+            this.rabbitTemplate.setConfirmCallback(this);
+            rabbitTemplate.convertAndSend(exchange, routingKey, message, correlationData);
+        } catch (AmqpException e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
+        // id 都是相同的哦 全局ID
+        String messageId = correlationData.getId();
+        // 消息发送失败,则继续发送
+        if (!ack) {
+            // 查询消息是否存在,当消息不存在得时候记录消息
+            JSONObject jsonObject = redisCache.getCacheObject(rabbitmqKey + messageId);
+            // 重试机制
+            send(jsonObject);
+        }
+    }
+
+}

+ 48 - 0
src/main/java/com/fjhx/rabbitmq/busi/BusiRabbitMQListener.java

@@ -0,0 +1,48 @@
+package com.fjhx.rabbitmq.busi;
+
+import com.alibaba.fastjson.JSONObject;
+import com.rabbitmq.client.Channel;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.stereotype.Component;
+
+/**
+ * rabbitmq队列监听工具
+ */
+@EnableRetry
+@Component
+public class BusiRabbitMQListener implements ChannelAwareMessageListener {
+
+    @RabbitHandler
+    @RabbitListener(
+            queues = {
+                    "rfid1_to_rfid2_queue"
+            },
+            concurrency = "8"
+    )
+    @Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(delay = 3000, multiplier = 1))
+    @Override
+    public void onMessage(Message message, Channel channel) throws Exception {
+        try {
+            String msg = new String(message.getBody(), "UTF-8");
+            JSONObject jsonObject = JSONObject.parseObject(msg);
+
+            System.err.println(jsonObject.toJSONString());
+
+            // 手动签收消息,通知mq服务器端删除该消息
+            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        } catch (Exception e) {
+            e.printStackTrace();
+            // 丢弃该消息
+            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
+            throw e;
+        }
+    }
+
+}
+

+ 59 - 0
src/main/java/com/fjhx/rabbitmq/config/RabbitMQConfig.java

@@ -0,0 +1,59 @@
+package com.fjhx.rabbitmq.config;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description: rabbitmq配置
+ * @ClassName: RabbitMQConfig
+ * @Author: linqt
+ * @Date: 2021/11/9 14:39
+ * @Version: 1.0
+ */
+@Configuration
+public class RabbitMQConfig {
+
+    @Value("${spring.rabbitmq.send.socket.queue}")
+    public String queue;
+
+    @Value("${spring.rabbitmq.send.socket.exchange}")
+    public String exchange;
+
+    @Value("${spring.rabbitmq.send.socket.routingKey}")
+    public String routingKey;
+
+    /**
+     * rabbitMq里初始化队列queue.
+     *
+     * @return
+     */
+    @Bean
+    public Queue queue() {
+        return new Queue(queue);
+    }
+
+    /**
+     * rabbitMq里初始化exchange.
+     *
+     * @return
+     */
+    @Bean
+    public TopicExchange exchange() {
+        return new TopicExchange(exchange);
+    }
+
+    /**
+     * 绑定exchange & queue & routekey.
+     *
+     * @return
+     */
+    @Bean
+    public Binding bindingExchange() {
+        return BindingBuilder.bind(queue()).to(exchange()).with(routingKey);
+    }
+}

+ 59 - 0
src/main/java/com/fjhx/rabbitmq/config/SDRabbitMQConfig.java

@@ -0,0 +1,59 @@
+package com.fjhx.rabbitmq.config;
+
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.TopicExchange;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description: rabbitmq配置
+ * @ClassName: RabbitMQConfig
+ * @Author: linqt
+ * @Date: 2021/11/9 14:39
+ * @Version: 1.0
+ */
+@Configuration
+public class SDRabbitMQConfig {
+
+    @Value("${spring.rabbitmq.send.sd.queue}")
+    public String queue;
+
+    @Value("${spring.rabbitmq.send.sd.exchange}")
+    public String exchange;
+
+    @Value("${spring.rabbitmq.send.sd.routingKey}")
+    public String routingKey;
+
+    /**
+     * rabbitMq里初始化队列queue.
+     *
+     * @return
+     */
+    @Bean
+    public Queue sdQueue() {
+        return new Queue(queue);
+    }
+
+    /**
+     * rabbitMq里初始化exchange.
+     *
+     * @return
+     */
+    @Bean
+    public TopicExchange sdExchange() {
+        return new TopicExchange(exchange);
+    }
+
+    /**
+     * 绑定exchange & queue & routekey.
+     *
+     * @return
+     */
+    @Bean
+    public Binding sdBindingExchange() {
+        return BindingBuilder.bind(sdQueue()).to(sdExchange()).with(routingKey);
+    }
+}

+ 64 - 0
src/main/java/com/fjhx/rabbitmq/enums/MsgSourceEnum.java

@@ -0,0 +1,64 @@
+package com.fjhx.rabbitmq.enums;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 消息来源枚举
+ */
+public enum MsgSourceEnum {
+
+    MSG_SOURCE_1(1, "消息通知"),
+    MSG_SOURCE_2(2, "RFID信息"),
+
+    ;
+
+    private int key;
+
+    private String value;
+
+    MsgSourceEnum(int key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+     * 获取枚举map
+     *
+     * @return
+     */
+    public static Map<Integer, String> getMap() {
+        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
+        for (MsgSourceEnum ms : values()) {
+            map.put(ms.key, ms.value);
+        }
+        return map;
+    }
+
+    /**
+     * 通过key获取名称
+     *
+     * @param key
+     * @return
+     */
+    public static String getNameByKey(Integer key) {
+        if (key == null || key < 0) {
+            return "";
+        }
+        for (MsgSourceEnum ms : values()) {
+            if (ms.key == key) {
+                return ms.value;
+            }
+        }
+        return "";
+    }
+
+    public int getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}

+ 30 - 0
src/main/java/com/fjhx/rabbitmq/service/RabbitmqService.java

@@ -0,0 +1,30 @@
+package com.fjhx.rabbitmq.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.scheduling.annotation.Async;
+
+/**
+ * @Description:
+ * @ClassName: RabbitmqService
+ * @Author: linqt
+ * @Date: 2022/3/28 15:16
+ * @Version: 1.0
+ */
+public interface RabbitmqService {
+
+    /**
+     * 发送消息
+     *
+     * @param jsonObject
+     */
+    @Async
+    void send(JSONObject jsonObject);
+
+    /**
+     * 发送消息
+     *
+     * @param jsonObject
+     */
+    @Async
+    void sdSend(JSONObject jsonObject);
+}

+ 45 - 0
src/main/java/com/fjhx/rabbitmq/service/impl/RabbitmqServiceImpl.java

@@ -0,0 +1,45 @@
+package com.fjhx.rabbitmq.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.rabbitmq.RabbitMQProducer;
+import com.fjhx.rabbitmq.SdRabbitMQProducer;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Description:
+ * @ClassName: RabbitmqServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/28 15:16
+ * @Version: 1.0
+ */
+@Service
+public class RabbitmqServiceImpl implements RabbitmqService {
+
+    @Autowired
+    private RabbitMQProducer rabbitMQProducer;
+
+    @Autowired
+    private SdRabbitMQProducer sdRabbitMQProducer;
+
+    /**
+     * 发送消息
+     *
+     * @param jsonObject
+     */
+    @Override
+    public void send(JSONObject jsonObject) {
+        rabbitMQProducer.send(jsonObject);
+    }
+
+    /**
+     * 发送消息
+     *
+     * @param jsonObject
+     */
+    @Override
+    public void sdSend(JSONObject jsonObject) {
+        sdRabbitMQProducer.send(jsonObject);
+    }
+}

+ 297 - 0
src/main/java/com/fjhx/redis/RedisCache.java

@@ -0,0 +1,297 @@
+package com.fjhx.redis;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * spring redis 工具类
+ */
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+@Component
+public class RedisCache {
+
+    @Autowired
+    public RedisTemplate redisTemplate;
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key   缓存的键值
+     * @param value 缓存的值
+     */
+    public <T> void setCacheObject(final String key, final T value) {
+        redisTemplate.opsForValue().set(key, value);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key      缓存的键值
+     * @param value    缓存的值
+     * @param timeout  时间
+     * @param timeUnit 时间颗粒度
+     */
+    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
+        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout) {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @param unit    时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
+        return redisTemplate.expire(key, timeout, unit);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheObject(final String key) {
+        ValueOperations<String, T> operation = redisTemplate.opsForValue();
+        return operation.get(key);
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public boolean deleteObject(final String key) {
+        return redisTemplate.delete(key);
+    }
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return
+     */
+    public long deleteObject(final Collection collection) {
+        return redisTemplate.delete(collection);
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key      缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public <T> long setCacheList(final String key, final List<T> dataList) {
+        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> List<T> getCacheList(final String key) {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key     缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public <T> long setCacheSet(final String key, final Set<T> dataSet) {
+        Long count = redisTemplate.opsForSet().add(key, dataSet);
+        return count == null ? 0 : count;
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public <T> Set<T> getCacheSet(final String key) {
+        return redisTemplate.opsForSet().members(key);
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
+        if (dataMap != null) {
+            redisTemplate.opsForHash().putAll(key, dataMap);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public <T> Map<String, T> getCacheMap(final String key) {
+        return redisTemplate.opsForHash().entries(key);
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key   Redis键
+     * @param hKey  Hash键
+     * @param value 值
+     */
+    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
+        redisTemplate.opsForHash().put(key, hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key  Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public <T> T getCacheMapValue(final String key, final String hKey) {
+        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+        return opsForHash.get(key, hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key   Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
+        return redisTemplate.opsForHash().multiGet(key, hKeys);
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public Collection<String> keys(final String pattern) {
+        return redisTemplate.keys(pattern);
+    }
+
+    /**
+     * 添加缓存,该方法会将对象转成字节在存入缓存
+     *
+     * @param key   缓存key
+     * @param value 数据
+     */
+    public void setCacheByteValue(final String key, final Object value) {
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(value);
+
+            redisTemplate.opsForValue().set(key, baos.toByteArray());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 添加缓存,该方法会将对象转成字节在存入缓存
+     *
+     * @param key      缓存key
+     * @param value    数据
+     * @param timeout  超时时间
+     * @param timeUnit 时间单位
+     */
+    public void setCacheByteValue(final String key, final Object value, final int timeout, final TimeUnit timeUnit) {
+        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+             ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(value);
+
+            redisTemplate.opsForValue().set(key, baos.toByteArray(), timeout, timeUnit);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获得缓存的基本对象,该方法将缓存字节转换成对象
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public <T> T getCacheByteValueToObject(final String key) {
+        ByteArrayInputStream byteArrayInputStream = null;
+        ObjectInputStream objectInputStream = null;
+        try {
+            ValueOperations<String, T> operation = redisTemplate.opsForValue();
+            T t1 = operation.get(key);
+            if (t1 == null) {
+                return null;
+            }
+            byte[] b = (byte[]) t1;
+
+            byteArrayInputStream = new ByteArrayInputStream(b);
+            objectInputStream = new ObjectInputStream(byteArrayInputStream);
+            T t = (T) objectInputStream.readObject();
+            return t;
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (byteArrayInputStream != null) {
+                    byteArrayInputStream.close();
+                }
+                if (objectInputStream != null) {
+                    objectInputStream.close();
+                }
+            } catch (Exception e) {
+
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 根据key获取节点下的所有子节点:模糊查询
+     *
+     * @param key 缓存key
+     * @return
+     */
+    public Set<String> getCacheChildKeysByKeyLike(final String key) {
+        return redisTemplate.keys(key + "*");
+    }
+}

+ 214 - 0
src/main/java/com/fjhx/redis/RedissonLockClient.java

@@ -0,0 +1,214 @@
+package com.fjhx.redis;
+
+import com.fjhx.utils.StringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 分布式锁实现基于Redisson
+ */
+@Slf4j
+@Component
+public class RedissonLockClient {
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 获取锁
+     *
+     * @param lockKey 锁名称
+     * @return
+     */
+    public RLock getLock(String lockKey) {
+        return redissonClient.getLock(lockKey);
+    }
+
+    /**
+     * 尝试加锁
+     *
+     * @param lockKey   锁名称
+     * @param leaseTime 如果锁获取成功,这把锁的过期时间,单位分钟
+     * @return
+     */
+    public boolean tryLock(String lockKey, long leaseTime) {
+        return tryLock(lockKey, 0, leaseTime);
+    }
+
+    /**
+     * 尝试加锁
+     *
+     * @param lockKey   锁名称
+     * @param waitTime  获取锁的最长等待时间
+     * @param leaseTime 如果锁获取成功,这把锁的过期时间,单位分钟
+     * @return
+     */
+    public boolean tryLock(String lockKey, long waitTime, long leaseTime) {
+        RLock rLock = getLock(lockKey);
+        boolean getLock = false;
+        try {
+            getLock = rLock.tryLock(waitTime, leaseTime, TimeUnit.MINUTES);
+            if (getLock) {
+                log.debug("获取锁成功,lockKey={}", lockKey);
+            } else {
+                log.debug("获取锁失败,lockKey={}", lockKey);
+            }
+        } catch (Exception e) {
+            log.error("获取式锁异常,lockKey=" + lockKey, e);
+            getLock = false;
+        }
+        return getLock;
+    }
+
+    /**
+     * 尝试加锁
+     *
+     * @param lockKey
+     * @return
+     */
+    public boolean tryLock(String lockKey) {
+        RLock rLock = getLock(lockKey);
+        boolean getLock = false;
+        try {
+            getLock = rLock.tryLock();
+            if (getLock) {
+                log.debug("获取锁成功,lockKey={}", lockKey);
+            } else {
+                log.debug("获取锁失败,lockKey={}", lockKey);
+            }
+        } catch (Exception e) {
+            log.error("获取式锁异常,lockKey=" + lockKey, e);
+            getLock = false;
+        }
+        return getLock;
+    }
+
+    /**
+     * 尝试获取锁(实现公平锁定,从而保证线程的获取顺序)<br/>
+     * 使用公平锁,如果获取了锁,则为true,否则为false
+     *
+     * @param lockKey 锁名称
+     * @return
+     */
+    public boolean getFairTryLock(String lockKey) {
+        RLock fairLock = redissonClient.getFairLock(lockKey);
+        try {
+            boolean tryLock = fairLock.tryLock();
+            if (!tryLock) {
+                log.debug("锁已经存在了,lockKey={}", lockKey);
+            }
+            return tryLock;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /**
+     * 公平锁(实现公平锁定,从而保证线程的获取顺序)
+     *
+     * @param lockKey   锁名称
+     * @param leaseTime 锁的过期时间
+     * @param unit      时间单位
+     * @return
+     */
+    public boolean getFairLock(String lockKey, int leaseTime, TimeUnit unit) {
+        RLock fairLock = redissonClient.getFairLock(lockKey);
+        try {
+            boolean existKey = existKey(lockKey);
+            // 已经存在了,就直接返回
+            if (existKey) {
+                log.debug("锁已经存在了,lockKey={}", lockKey);
+                return false;
+            }
+            return fairLock.tryLock(3, leaseTime, unit);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    /**
+     * 公平锁(实现公平锁定,从而保证线程的获取顺序)
+     *
+     * @param lockKey 锁名称
+     * @return
+     */
+    public RLock getFairLock(String lockKey) {
+        RLock fairLock = redissonClient.getFairLock(lockKey);
+        return fairLock;
+    }
+
+    /**
+     * 缓存key是否存在
+     *
+     * @param key key名称
+     * @return
+     */
+    public boolean existKey(String key) {
+        return redisTemplate.hasKey(key);
+    }
+
+    /**
+     * 加锁
+     *
+     * @param lockKey 锁名称
+     * @return
+     */
+    public RLock lock(String lockKey) {
+        RLock lock = getLock(lockKey);
+        lock.lock();
+        return lock;
+    }
+
+    /**
+     * 加锁
+     *
+     * @param lockKey   锁名称
+     * @param leaseTime 锁的过期时间
+     * @return
+     */
+    public RLock lock(String lockKey, long leaseTime) {
+        RLock lock = getLock(lockKey);
+        lock.lock(leaseTime, TimeUnit.SECONDS);
+        return lock;
+    }
+
+    /**
+     * 解锁
+     *
+     * @param lockKey 锁名称
+     */
+    public void unlock(String lockKey) {
+        try {
+            if (StringUtils.isBlank(lockKey)) {
+                return;
+            }
+            redissonClient.getLock(lockKey).unlock();
+        } catch (Exception e) {
+
+        }
+    }
+
+    /**
+     * 公平锁,解锁
+     *
+     * @param lockKey
+     */
+    public void fairUnlock(String lockKey) {
+        if (StringUtils.isBlank(lockKey)) {
+            return;
+        }
+        redissonClient.getFairLock(lockKey).unlock();
+    }
+
+}

+ 28 - 0
src/main/java/com/fjhx/redis/redisson/RedissonConfiguration.java

@@ -0,0 +1,28 @@
+package com.fjhx.redis.redisson;
+
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Redisson自动化配置
+ */
+@Slf4j
+@Configuration
+public class RedissonConfiguration {
+
+    @Autowired
+    private RedissonProperties redissonProperties;
+
+    @Bean
+    @ConditionalOnMissingBean(RedissonClient.class)
+    public RedissonClient redissonClient() {
+        RedissonManager redissonManager = new RedissonManager(redissonProperties);
+        return redissonManager.getRedisson();
+    }
+
+}

+ 98 - 0
src/main/java/com/fjhx/redis/redisson/RedissonManager.java

@@ -0,0 +1,98 @@
+package com.fjhx.redis.redisson;
+
+import com.fjhx.redis.redisson.enums.RedisConnectionType;
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import com.fjhx.redis.redisson.strategy.RedissonConfigStrategy;
+import com.fjhx.redis.redisson.strategy.impl.ClusterRedissonConfigStrategyImpl;
+import com.fjhx.redis.redisson.strategy.impl.MasterslaveRedissonConfigStrategyImpl;
+import com.fjhx.redis.redisson.strategy.impl.SentinelRedissonConfigStrategyImpl;
+import com.fjhx.redis.redisson.strategy.impl.StandaloneRedissonConfigStrategyImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.Redisson;
+import org.redisson.config.Config;
+
+/**
+ * Redisson配置管理器,用于初始化的redisson实例
+ */
+@Slf4j
+public class RedissonManager {
+
+    private Config config = new Config();
+
+    private Redisson redisson = null;
+
+    public RedissonManager() {
+
+    }
+
+    public RedissonManager(RedissonProperties redissonProperties) {
+        //装配开关
+        Boolean enabled = redissonProperties.getEnabled();
+        if (enabled) {
+            try {
+                log.debug("RedissonManager初始化完成,当前连接方式:" + redissonProperties.getType() + ",连接地址:" + redissonProperties.getAddress());
+
+                config = RedissonConfigFactory.getInstance().createConfig(redissonProperties);
+                redisson = (Redisson) Redisson.create(config);
+            } catch (Exception e) {
+                log.error("Redisson初始化错误", e);
+            }
+        }
+    }
+
+    public Redisson getRedisson() {
+        return redisson;
+    }
+
+    /**
+     * Redisson连接方式配置工厂
+     * 双重检查锁
+     */
+    static class RedissonConfigFactory {
+
+        private RedissonConfigFactory() {
+
+        }
+
+        private static volatile RedissonConfigFactory factory = null;
+
+        public static RedissonConfigFactory getInstance() {
+            if (factory == null) {
+                synchronized (Object.class) {
+                    if (factory == null) {
+                        factory = new RedissonConfigFactory();
+                    }
+                }
+            }
+            return factory;
+        }
+
+        /**
+         * 根据连接类型創建连接方式的配置
+         *
+         * @param redissonProperties
+         * @return Config
+         */
+        Config createConfig(RedissonProperties redissonProperties) {
+            RedisConnectionType connectionType = redissonProperties.getType();
+            // 声明连接方式
+            RedissonConfigStrategy redissonConfigStrategy;
+            if (connectionType.equals(RedisConnectionType.SENTINEL)) {
+                //哨兵部署方式
+                redissonConfigStrategy = new SentinelRedissonConfigStrategyImpl();
+            } else if (connectionType.equals(RedisConnectionType.CLUSTER)) {
+                //集群部署方式
+                redissonConfigStrategy = new ClusterRedissonConfigStrategyImpl();
+            } else if (connectionType.equals(RedisConnectionType.MASTERSLAVE)) {
+                //主从部署方式
+                redissonConfigStrategy = new MasterslaveRedissonConfigStrategyImpl();
+            } else {
+                //单机部署
+                redissonConfigStrategy = new StandaloneRedissonConfigStrategyImpl();
+            }
+            Config config = redissonConfigStrategy.createRedissonConfig(redissonProperties);
+            return config;
+        }
+    }
+
+}

+ 13 - 0
src/main/java/com/fjhx/redis/redisson/enums/GlobalConstant.java

@@ -0,0 +1,13 @@
+package com.fjhx.redis.redisson.enums;
+
+/**
+ * 全局常量枚举
+ */
+public interface GlobalConstant {
+
+    /**
+     * Redis地址连接前缀
+     */
+    String REDIS_CONNECTION_PREFIX = "redis://";
+
+}

+ 29 - 0
src/main/java/com/fjhx/redis/redisson/enums/LockModel.java

@@ -0,0 +1,29 @@
+package com.fjhx.redis.redisson.enums;
+
+/**
+ * 锁的模式
+ */
+public enum LockModel {
+
+    //可重入锁
+    REENTRANT,
+
+    //公平锁
+    FAIR,
+
+    //联锁(可以把一组锁当作一个锁来加锁和释放)
+    MULTIPLE,
+
+    //红锁
+    REDLOCK,
+
+    //读锁
+    READ,
+
+    //写锁
+    WRITE,
+
+    //自动模式,当参数只有一个.使用 REENTRANT 参数多个 REDLOCK
+    AUTO
+
+}

+ 49 - 0
src/main/java/com/fjhx/redis/redisson/enums/RedisConnectionType.java

@@ -0,0 +1,49 @@
+package com.fjhx.redis.redisson.enums;
+
+/**
+ * Redis连接方式
+ */
+public enum RedisConnectionType {
+	/**
+	 * 单机部署方式(默认)
+	 */
+	STANDALONE("standalone", "单机部署方式"),
+
+	/**
+	 * 哨兵部署方式
+	 */
+	SENTINEL("sentinel", "哨兵部署方式"),
+
+	/**
+	 * 集群部署方式
+	 */
+	CLUSTER("cluster", "集群方式"),
+
+	/**
+	 * 主从部署方式
+	 */
+	MASTERSLAVE("masterslave", "主从部署方式");
+
+	/**
+	 * 编码
+	 */
+	private final String code;
+	/**
+	 * 名称
+	 */
+	private final String name;
+
+	RedisConnectionType(String code, String name) {
+		this.code = code;
+		this.name = name;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+}

+ 74 - 0
src/main/java/com/fjhx/redis/redisson/properties/RedissonProperties.java

@@ -0,0 +1,74 @@
+package com.fjhx.redis.redisson.properties;
+
+import com.fjhx.redis.redisson.enums.RedisConnectionType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Redisson配置映射类
+ */
+@Configuration
+public class RedissonProperties {
+
+    //连接地址
+    @Value("${redisson.address}")
+    private String address;
+
+    //连接类型
+    @Value("${redisson.type}")
+    private RedisConnectionType type;
+
+    /**
+     * 密码
+     */
+    @Value("${redisson.password}")
+    private String password;
+
+    //数据库(默认0)
+    @Value("${redisson.database}")
+    private Integer database;
+
+    //是否装配redisson配置
+    private Boolean enabled = true;
+
+    public String getAddress() {
+        return address;
+    }
+
+    public void setAddress(String address) {
+        this.address = address;
+    }
+
+    public RedisConnectionType getType() {
+        return type;
+    }
+
+    public void setType(RedisConnectionType type) {
+        this.type = type;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public Integer getDatabase() {
+        return database;
+    }
+
+    public void setDatabase(Integer database) {
+        this.database = database;
+    }
+
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+}

+ 22 - 0
src/main/java/com/fjhx/redis/redisson/strategy/RedissonConfigStrategy.java

@@ -0,0 +1,22 @@
+package com.fjhx.redis.redisson.strategy;
+
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import org.redisson.config.Config;
+
+/**
+ * Redisson配置构建接口
+ *
+ * @author zyf
+ * @date 2020-11-11
+ */
+public interface RedissonConfigStrategy {
+
+    /**
+     * 根据不同的Redis配置策略创建对应的Config
+     *
+     * @param redissonProperties
+     * @return Config
+     */
+    Config createRedissonConfig(RedissonProperties redissonProperties);
+
+}

+ 42 - 0
src/main/java/com/fjhx/redis/redisson/strategy/impl/ClusterRedissonConfigStrategyImpl.java

@@ -0,0 +1,42 @@
+package com.fjhx.redis.redisson.strategy.impl;
+
+import com.fjhx.redis.redisson.enums.GlobalConstant;
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import com.fjhx.redis.redisson.strategy.RedissonConfigStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.config.Config;
+
+/**
+ * 集群方式Redisson配置
+ * cluster方式至少6个节点(3主3从)
+ * 配置方式:127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,127.0.0.1:6383,127.0.0.1:6384
+ */
+@Slf4j
+public class ClusterRedissonConfigStrategyImpl implements RedissonConfigStrategy {
+
+    @Override
+    public Config createRedissonConfig(RedissonProperties redissonProperties) {
+        Config config = new Config();
+        try {
+            String address = redissonProperties.getAddress();
+            String password = redissonProperties.getPassword();
+            String[] addrTokens = address.split(",");
+            // 设置集群(cluster)节点的服务IP和端口
+            for (int i = 0; i < addrTokens.length; i++) {
+                config.useClusterServers().addNodeAddress(GlobalConstant.REDIS_CONNECTION_PREFIX + addrTokens[i]);
+                if (StringUtils.isNotBlank(password)) {
+                    config.useClusterServers().setPassword(password);
+                }
+            }
+            //连接间隔 心跳 1000
+            config.useClusterServers().setPingConnectionInterval(1000);
+            log.info("初始化集群方式Config,连接地址:" + address);
+        } catch (Exception e) {
+            log.error("集群Redisson初始化错误", e);
+            e.printStackTrace();
+        }
+        return config;
+    }
+
+}

+ 52 - 0
src/main/java/com/fjhx/redis/redisson/strategy/impl/MasterslaveRedissonConfigStrategyImpl.java

@@ -0,0 +1,52 @@
+package com.fjhx.redis.redisson.strategy.impl;
+
+import com.fjhx.redis.redisson.enums.GlobalConstant;
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import com.fjhx.redis.redisson.strategy.RedissonConfigStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.config.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 主从方式Redisson配置
+ * <p>配置方式: 127.0.0.1:6379(主),127.0.0.1:6380(子),127.0.0.1:6381(子)</p>
+ */
+@Slf4j
+public class MasterslaveRedissonConfigStrategyImpl implements RedissonConfigStrategy {
+
+    @Override
+    public Config createRedissonConfig(RedissonProperties redissonProperties) {
+        Config config = new Config();
+        try {
+            String address = redissonProperties.getAddress();
+            String password = redissonProperties.getPassword();
+            int database = redissonProperties.getDatabase();
+            String[] addrTokens = address.split(",");
+            String masterNodeAddr = addrTokens[0];
+            // 设置主节点ip
+            config.useMasterSlaveServers().setMasterAddress(masterNodeAddr);
+            if (StringUtils.isNotBlank(password)) {
+                config.useMasterSlaveServers().setPassword(password);
+            }
+            config.useMasterSlaveServers().setDatabase(database);
+            // 设置从节点,移除第一个节点,默认第一个为主节点
+            List<String> slaveList = new ArrayList<>();
+            for (String addrToken : addrTokens) {
+                slaveList.add(GlobalConstant.REDIS_CONNECTION_PREFIX + addrToken);
+            }
+            slaveList.remove(0);
+            //连接间隔 心跳 1000
+            config.useMasterSlaveServers().setPingConnectionInterval(1000);
+            config.useMasterSlaveServers().addSlaveAddress((String[]) slaveList.toArray());
+            log.info("初始化主从方式Config,redisAddress:" + address);
+        } catch (Exception e) {
+            log.error("主从Redisson初始化错误", e);
+            e.printStackTrace();
+        }
+        return config;
+    }
+
+}

+ 47 - 0
src/main/java/com/fjhx/redis/redisson/strategy/impl/SentinelRedissonConfigStrategyImpl.java

@@ -0,0 +1,47 @@
+package com.fjhx.redis.redisson.strategy.impl;
+
+import com.fjhx.redis.redisson.enums.GlobalConstant;
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import com.fjhx.redis.redisson.strategy.RedissonConfigStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.config.Config;
+
+/**
+ * 哨兵方式Redis连接配置
+ * 比如sentinel.conf里配置为sentinel monitor my-sentinel-name 127.0.0.1 6379 2,那么这里就配置my-sentinel-name
+ * 配置方式:my-sentinel-name,127.0.0.1:26379,127.0.0.1:26389,127.0.0.1:26399
+ */
+@Slf4j
+public class SentinelRedissonConfigStrategyImpl implements RedissonConfigStrategy {
+
+    @Override
+    public Config createRedissonConfig(RedissonProperties redissonProperties) {
+        Config config = new Config();
+        try {
+            String address = redissonProperties.getAddress();
+            String password = redissonProperties.getPassword();
+            int database = redissonProperties.getDatabase();
+            String[] addrTokens = address.split(",");
+            String sentinelAliasName = addrTokens[0];
+            // 设置redis配置文件sentinel.conf配置的sentinel别名
+            config.useSentinelServers().setMasterName(sentinelAliasName);
+            config.useSentinelServers().setDatabase(database);
+            if (StringUtils.isNotBlank(password)) {
+                config.useSentinelServers().setPassword(password);
+            }
+            // 设置哨兵节点的服务IP和端口
+            for (int i = 1; i < addrTokens.length; i++) {
+                config.useSentinelServers().addSentinelAddress(GlobalConstant.REDIS_CONNECTION_PREFIX + addrTokens[i]);
+            }
+            //连接间隔 心跳 1000
+            config.useSentinelServers().setPingConnectionInterval(1000);
+            log.info("初始化哨兵方式Config,redisAddress:" + address);
+        } catch (Exception e) {
+            log.error("哨兵Redisson初始化错误", e);
+            e.printStackTrace();
+        }
+        return config;
+    }
+
+}

+ 39 - 0
src/main/java/com/fjhx/redis/redisson/strategy/impl/StandaloneRedissonConfigStrategyImpl.java

@@ -0,0 +1,39 @@
+package com.fjhx.redis.redisson.strategy.impl;
+
+import com.fjhx.redis.redisson.enums.GlobalConstant;
+import com.fjhx.redis.redisson.properties.RedissonProperties;
+import com.fjhx.redis.redisson.strategy.RedissonConfigStrategy;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.config.Config;
+
+/**
+ * 单机方式Redisson配置
+ */
+@Slf4j
+public class StandaloneRedissonConfigStrategyImpl implements RedissonConfigStrategy {
+
+    @Override
+    public Config createRedissonConfig(RedissonProperties redissonProperties) {
+        Config config = new Config();
+        try {
+            String address = redissonProperties.getAddress();
+            String password = redissonProperties.getPassword();
+            int database = redissonProperties.getDatabase();
+            String redisAddr = GlobalConstant.REDIS_CONNECTION_PREFIX + address;
+            config.useSingleServer().setAddress(redisAddr);
+            config.useSingleServer().setDatabase(database);
+            if (StringUtils.isNotBlank(password)) {
+                config.useSingleServer().setPassword(password);
+            }
+            //连接间隔 心跳 1000
+            config.useSingleServer().setPingConnectionInterval(1000);
+            log.info("初始化Redisson单机配置,连接地址:" + address);
+        } catch (Exception e) {
+            log.error("单机Redisson初始化错误", e);
+            e.printStackTrace();
+        }
+        return config;
+    }
+
+}

+ 22 - 0
src/main/java/com/fjhx/rfid/r2000/common/service/IRFIDService.java

@@ -0,0 +1,22 @@
+package com.fjhx.rfid.r2000.common.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.scheduling.annotation.Async;
+
+/**
+ * @Description:
+ * @ClassName: TcpService
+ * @Author: linqt
+ * @Date: 2022/3/17 10:31
+ * @Version: 1.0
+ */
+public interface IRFIDService {
+
+    /**
+     * 接收指令
+     *
+     * @param jsonObject 参数
+     */
+    @Async
+    void receiveInstructions(JSONObject jsonObject);
+}

+ 88 - 0
src/main/java/com/fjhx/rfid/r2000/common/service/impl/RFIDServiceImpl.java

@@ -0,0 +1,88 @@
+package com.fjhx.rfid.r2000.common.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.rabbitmq.RabbitMQProducer;
+import com.fjhx.rfid.r2000.common.service.IRFIDService;
+import com.fjhx.rfid.r2000.tcp.service.TcpServiceV2;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @ClassName: TcpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/17 10:32
+ * @Version: 1.0
+ */
+@Service
+public class RFIDServiceImpl implements IRFIDService {
+
+    @Autowired
+    private RabbitMQProducer mqProducer;
+
+    @Autowired
+    private TcpServiceV2 tcpServiceV2;
+
+    /**
+     * 接收指令
+     *
+     * @param jsonObject 参数
+     */
+    @Override
+    public void receiveInstructions(JSONObject jsonObject) {
+        System.err.println(jsonObject.toJSONString());
+
+        //处理读写器ip地址
+        List<String> tcpIps = RFIDConfig.getTcp().getIps();
+        List<String> updIps = RFIDConfig.getUdp().getIps();
+        List<String> ips = new ArrayList<>();
+        Object o = jsonObject.get("ips");
+        if (ObjectUtils.isNotEmpty(o)) {
+            ips = JSONObject.parseArray(jsonObject.getString("ips"), String.class);
+        }
+        System.err.println("ips--:" + ips.toString());
+
+        if (CollectionUtils.isNotEmpty(ips)) {
+            List<String> finalTcpIps = tcpIps;
+            tcpIps = ips.stream()
+                    .filter(item -> finalTcpIps.stream().collect(Collectors.toList())
+                            .contains(item)).collect(Collectors.toList());
+
+            List<String> finalUpdIps = updIps;
+            updIps = ips.stream()
+                    .filter(item -> finalUpdIps.stream().collect(Collectors.toList())
+                            .contains(item)).collect(Collectors.toList());
+        }
+
+        System.err.println("tcpIps--:" + tcpIps.toString());
+        System.err.println("updIps--:" + updIps.toString());
+
+        //业务唯一标识
+        String busUuid = jsonObject.getString("busUuid");
+
+        //业务服务端用户userId
+        String userId = jsonObject.getString("userId");
+
+        //指令类型
+        Integer instructType = jsonObject.getInteger("instructType");
+        if (instructType == RFIDConstant.InstructType.INSTRUCT_TYPE_1) {
+            //启动读写器并返回所有数据
+            tcpServiceV2.openAndReturnAllData(tcpIps, busUuid, userId);
+        } else if (instructType == RFIDConstant.InstructType.INSTRUCT_TYPE_2) {
+            //启动读写器并返回去重数据
+            tcpServiceV2.openAndReturnGoHeavyData(tcpIps, busUuid, userId);
+        } else if (instructType == RFIDConstant.InstructType.INSTRUCT_TYPE_3) {
+            //关闭读写器
+        }
+    }
+
+}

+ 14 - 0
src/main/java/com/fjhx/rfid/r2000/controller/RFIDController.java

@@ -0,0 +1,14 @@
+package com.fjhx.rfid.r2000.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * rfid读写器服务 控制器
+ */
+@RestController
+@RequestMapping("/rfid/server")
+public class RFIDController {
+
+
+}

+ 46 - 0
src/main/java/com/fjhx/rfid/r2000/controller/SdRFIDController.java

@@ -0,0 +1,46 @@
+package com.fjhx.rfid.r2000.controller;
+
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.rfid.r2000.sd.service.ISdService;
+import com.fjhx.utils.AjaxResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * rfid读写器服务 控制器
+ */
+@RestController
+@RequestMapping("/rfid/server/sd")
+public class SdRFIDController {
+
+    @Autowired
+    private ISdService iSdService;
+
+    /**
+     * 启动
+     *
+     * @return
+     */
+    @PostConstruct
+    @PostMapping("/open")
+    public AjaxResult open() {
+        iSdService.open(new RFIDClient());
+        return AjaxResult.success();
+    }
+
+    /**
+     * 关闭
+     *
+     * @param client 参数
+     * @return
+     */
+    @PostMapping("/close")
+    public AjaxResult close(RFIDClient client) {
+        iSdService.close(client);
+        return AjaxResult.success();
+    }
+}

+ 54 - 0
src/main/java/com/fjhx/rfid/r2000/controller/TcpController.java

@@ -0,0 +1,54 @@
+package com.fjhx.rfid.r2000.controller;
+
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.rfid.r2000.tcp.service.TcpService;
+import com.fjhx.utils.AjaxResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * rfid读写器tcp协议 控制器
+ */
+@RestController
+@RequestMapping("/rfid/tcp/client")
+public class TcpController {
+
+    @Autowired
+    private TcpService tcpService;
+
+    /**
+     * 启动单台
+     *
+     * @param client
+     * @return
+     */
+    @PostMapping("/start/one")
+    public AjaxResult startOne(@RequestBody RFIDClient client) {
+        return tcpService.startOne(client);
+    }
+
+    /**
+     * 关闭单台
+     *
+     * @param client
+     * @return
+     */
+    @PostMapping("/close/one")
+    public AjaxResult closeOne(@RequestBody RFIDClient client) {
+        return tcpService.closeOne(client);
+    }
+
+    /**
+     * 启动多台
+     *
+     * @param client
+     * @return
+     */
+    @PostMapping("/open/more")
+    public AjaxResult openMore(@RequestBody RFIDClient client) {
+        return tcpService.openMore(client);
+    }
+}

+ 59 - 0
src/main/java/com/fjhx/rfid/r2000/controller/UdpController.java

@@ -0,0 +1,59 @@
+package com.fjhx.rfid.r2000.controller;
+
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.rfid.r2000.udp.service.UdpService;
+import com.fjhx.utils.AjaxResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Description:
+ * @ClassName: UdpController
+ * @Author: linqt
+ * @Date: 2022/3/8 16:48
+ * @Version: 1.0
+ */
+@RestController
+@RequestMapping("/rfid/udp/client")
+public class UdpController {
+
+    @Autowired
+    private UdpService udpService;
+
+    /**
+     * 启动单台
+     *
+     * @param client
+     * @return
+     */
+    @PostMapping("/start/one")
+    public AjaxResult startOne(@RequestBody RFIDClient client) {
+        return udpService.startOne(client);
+    }
+
+    /**
+     * 关闭单台
+     *
+     * @param client
+     * @return
+     */
+    @PostMapping("/close/one")
+    public AjaxResult closeOne(@RequestBody RFIDClient client) {
+        return udpService.closeOne(client);
+    }
+
+
+    /**
+     * 启动多台
+     *
+     * @param client
+     * @return
+     */
+    @PostMapping("/open/more")
+    public AjaxResult openMore(@RequestBody RFIDClient client) {
+        return udpService.openMore(client);
+    }
+}

+ 29 - 0
src/main/java/com/fjhx/rfid/r2000/sd/service/ISdService.java

@@ -0,0 +1,29 @@
+package com.fjhx.rfid.r2000.sd.service;
+
+import com.fjhx.entity.rfid.RFIDClient;
+
+/**
+ * @Description:
+ * @ClassName: TcpService
+ * @Author: linqt
+ * @Date: 2022/3/17 10:31
+ * @Version: 1.0
+ */
+public interface ISdService {
+
+    /**
+     * 启动
+     *
+     * @param client 参数
+     * @return
+     */
+    void open(RFIDClient client);
+
+    /**
+     * 关闭
+     *
+     * @param client 参数
+     * @return
+     */
+    void close(RFIDClient client);
+}

+ 104 - 0
src/main/java/com/fjhx/rfid/r2000/sd/service/impl/SdServiceImpl.java

@@ -0,0 +1,104 @@
+package com.fjhx.rfid.r2000.sd.service.impl;
+
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.rfid.r2000.sd.service.ISdService;
+import com.fjhx.rfid.r2000.tcp.service.ISdTcpService;
+import com.fjhx.rfid.r2000.udp.service.ISdUdpService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @ClassName: TcpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/17 10:32
+ * @Version: 1.0
+ */
+@Service
+public class SdServiceImpl implements ISdService {
+
+    @Autowired
+    private ISdTcpService iSdTcpService;
+
+    @Autowired
+    private ISdUdpService iSdUdpService;
+
+    /**
+     * 启动
+     *
+     * @param client 参数
+     * @return
+     */
+    @Override
+    public void open(RFIDClient client) {
+        //传进来的ip集合
+        List<String> ips = client.getIpList();
+        //默认tcp协议ip集合
+        List<String> tcpIps = RFIDConfig.getSd().getTcp().getIps();
+        //默认udp协议ip集合
+        List<String> updIps = RFIDConfig.getSd().getUdp().getIps();
+        if (CollectionUtils.isNotEmpty(ips)) {
+            List<String> finalTcpIps = tcpIps;
+            tcpIps = ips.stream()
+                    .filter(item -> finalTcpIps.stream().collect(Collectors.toList())
+                            .contains(item)).collect(Collectors.toList());
+
+            List<String> finalUpdIps = updIps;
+            updIps = ips.stream()
+                    .filter(item -> finalUpdIps.stream().collect(Collectors.toList())
+                            .contains(item)).collect(Collectors.toList());
+        }
+
+        if (CollectionUtils.isNotEmpty(tcpIps)) {
+            //启动tcp读写器
+            iSdTcpService.open(tcpIps);
+        }
+
+        if (CollectionUtils.isNotEmpty(updIps)) {
+            //启动upd读写器
+            iSdUdpService.open(updIps);
+        }
+    }
+
+    /**
+     * 关闭
+     *
+     * @param client 参数
+     * @return
+     */
+    @Override
+    public void close(RFIDClient client) {
+        //传进来的ip集合
+        List<String> ips = client.getIpList();
+        //默认tcp协议ip集合
+        List<String> tcpIps = RFIDConfig.getSd().getTcp().getIps();
+        //默认udp协议ip集合
+        List<String> updIps = RFIDConfig.getSd().getUdp().getIps();
+        if (CollectionUtils.isNotEmpty(ips)) {
+            List<String> finalTcpIps = tcpIps;
+            tcpIps = ips.stream()
+                    .filter(item -> finalTcpIps.stream().collect(Collectors.toList())
+                            .contains(item)).collect(Collectors.toList());
+
+            List<String> finalUpdIps = updIps;
+            updIps = ips.stream()
+                    .filter(item -> finalUpdIps.stream().collect(Collectors.toList())
+                            .contains(item)).collect(Collectors.toList());
+        }
+
+        if (CollectionUtils.isNotEmpty(tcpIps)) {
+            //关闭tcp读写器
+            iSdTcpService.close(tcpIps);
+        }
+
+        if (CollectionUtils.isNotEmpty(updIps)) {
+            //关闭udp读写器
+            iSdUdpService.close(updIps);
+        }
+    }
+}

+ 94 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/callback/SdTcpCallBack.java

@@ -0,0 +1,94 @@
+package com.fjhx.rfid.r2000.tcp.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.utils.id.IdUtils;
+import com.fjhx.utils.spring.SpringUtils;
+import com.rfid.callBack.CallBack.R2000;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+@Data
+public class SdTcpCallBack implements R2000 {
+
+    /**
+     * redis实例
+     */
+    private RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+
+    /**
+     * rabbitmq实例
+     */
+    private RabbitmqService rabbitmqService = SpringUtils.getBean(RabbitmqService.class);
+
+    private String ip;
+
+    public SdTcpCallBack(String ip) {
+        this.ip = ip;
+    }
+
+    public void readData(String data, String rssi, String antennaNo, String deviceNo, String direction, String communicationMode) {
+        try {
+            if (StringUtils.isBlank(data)) {
+                return;
+            }
+
+            //是否发送
+            Boolean isSend = false;
+
+            //获取rfid缓存信息
+            Long time = redisCache.getCacheObject(MessageFormat.format(RedisKeyConstant.RFID_REDIS_CACHE_PREFIX, ip + "-" + antennaNo + "-" + data));
+            //缓存记录为空,或者上次的记录时间离现在超过5s,则发送信息
+            if (time == null || System.currentTimeMillis() - time > RFIDConstant.DEFAULT_TIME) {
+                isSend = true;
+            }
+
+            // 存入缓存
+            redisCache.setCacheObject(MessageFormat.format(RedisKeyConstant.RFID_REDIS_CACHE_PREFIX, ip + "-" + antennaNo + "-" + data), new Date().getTime(), RFIDConfig.getDefaultTime(), TimeUnit.MILLISECONDS);
+
+            // 封装实际数据
+            JSONObject object = new JSONObject();
+            object.put("RFID", data);
+            object.put("ANTNO", antennaNo);
+            object.put("IP", ip);
+
+            if (isSend) {
+                // -------------------- 使用rabbitmq派转消息 --------------------
+                JSONObject jsonObject = new JSONObject();
+                jsonObject.put("messageId", IdUtils.fastSimpleUUID());
+                jsonObject.put("rfidMsg", object);
+                rabbitmqService.sdSend(jsonObject);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public void onceReadTagEnd(Boolean result) {
+
+    }
+
+    public void serialPortException(String name, boolean result) {
+
+    }
+
+    public void heartBeat(String value, String deviceNo, String communicationMode) {
+        System.out.println("value " + value + " deviceNo " + deviceNo + " communicationMode " + communicationMode);
+    }
+
+    public void infraredTrigger(boolean direction, String value, String deviceNo, String communicationMode) {
+        System.out.println("方向 " + direction + " 红外值 " + value + " 设备号 " + deviceNo + " IP或串口号 " + communicationMode);
+    }
+
+    public void onceReadTagEnd(boolean arg0) {
+
+    }
+}

+ 24 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBack.java

@@ -0,0 +1,24 @@
+package com.fjhx.rfid.r2000.tcp.callback;
+
+import com.rfid.callBack.CallBack.R2000;
+
+public class TcpCallBack implements R2000 {
+
+    public void onceReadTagEnd(Boolean result) {
+    }
+
+    public void readData(String data, String rssi, String antennaNo, String deviceNo, String direction, String communicationMode) {
+    }
+
+    public void serialPortException(String name, boolean result) {
+    }
+
+    public void heartBeat(String value, String deviceNo, String communicationMode) {
+    }
+
+    public void infraredTrigger(boolean direction, String value, String deviceNo, String communicationMode) {
+    }
+
+    public void onceReadTagEnd(boolean arg0) {
+    }
+}

+ 124 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBackAllData.java

@@ -0,0 +1,124 @@
+package com.fjhx.rfid.r2000.tcp.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.rabbitmq.enums.MsgSourceEnum;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.utils.id.IdUtils;
+import com.fjhx.utils.spring.SpringUtils;
+import com.rfid.callBack.CallBack.R2000;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Data
+public class TcpCallBackAllData implements R2000 {
+
+    /**
+     * redis实例
+     */
+    private RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+
+    /**
+     * rabbitmq实例
+     */
+    private RabbitmqService rabbitmqService = SpringUtils.getBean(RabbitmqService.class);
+
+    /**
+     * rdis缓存key
+     */
+    private String redisKey;
+
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 读写器IP
+     */
+    private String ip;
+
+    /**
+     * 数据集合
+     */
+    private List<JSONObject> list;
+
+    private String readTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+
+    public TcpCallBackAllData(String redisKey, String userId, String ip, List<JSONObject> list) {
+        this.redisKey = redisKey;
+        this.userId = userId;
+        this.ip = ip;
+        this.list = list;
+    }
+
+    public void readData(String data, String rssi, String antennaNo, String deviceNo, String direction, String communicationMode) {
+        String content = "RFID:" + data + ", ANTNO: " + antennaNo + ", TIME: " + readTime + "\r\n";
+//        System.err.println("tcp--:" + content);
+        FileWriter fwriter = null;
+        try {
+            if (StringUtils.isBlank(data)) {
+                return;
+            }
+
+            // 封装实际数据
+            JSONObject object = new JSONObject();
+            object.put("RFID", data);
+            object.put("ANTNO", antennaNo);
+
+            // 不存在文件夹则创建
+            String filePath = RFIDConfig.getLog().getSavePath() + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "\\";
+            File file = new File(filePath);
+            if (!file.exists() && !file.isDirectory()) {
+                file.mkdir();
+            }
+            filePath += new SimpleDateFormat("yyyyMMdd HH").format(new Date()) + ".txt";
+            // true表示不覆盖原来的内容,而是加到文件的后面。若要覆盖原来的内容,直接省略这个参数就好
+            fwriter = new FileWriter(filePath, true);
+            fwriter.write(content);
+
+            // 收集数据
+            list.add(object);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        } finally {
+            try {
+                if (fwriter != null) {
+                    fwriter.flush();
+                    fwriter.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    public void onceReadTagEnd(Boolean result) {
+
+    }
+
+    public void serialPortException(String name, boolean result) {
+
+    }
+
+    public void heartBeat(String value, String deviceNo, String communicationMode) {
+        System.out.println("value " + value + " deviceNo " + deviceNo + " communicationMode " + communicationMode);
+    }
+
+    public void infraredTrigger(boolean direction, String value, String deviceNo, String communicationMode) {
+        System.out.println("方向 " + direction + " 红外值 " + value + " 设备号 " + deviceNo + " IP或串口号 " + communicationMode);
+    }
+
+    public void onceReadTagEnd(boolean arg0) {
+
+    }
+}

+ 120 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBackGoHeavyData.java

@@ -0,0 +1,120 @@
+package com.fjhx.rfid.r2000.tcp.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.utils.spring.SpringUtils;
+import com.rfid.callBack.CallBack.R2000;
+import lombok.Data;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Data
+public class TcpCallBackGoHeavyData implements R2000 {
+
+    /**
+     * redis实例
+     */
+    private RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+
+    /**
+     * rabbitmq实例
+     */
+    private RabbitmqService rabbitmqService = SpringUtils.getBean(RabbitmqService.class);
+
+    /**
+     * rdis缓存key
+     */
+    private String redisKey;
+
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 读写器IP
+     */
+    private String ip;
+
+    /**
+     * 数据map
+     */
+    private ConcurrentHashMap<String, JSONObject> map;
+
+    private String readTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+
+    public TcpCallBackGoHeavyData(String redisKey, String userId, String ip, ConcurrentHashMap<String, JSONObject> map) {
+        this.redisKey = redisKey;
+        this.userId = userId;
+        this.ip = ip;
+        this.map = map;
+    }
+
+    public void readData(String data, String rssi, String antennaNo, String deviceNo, String direction, String communicationMode) {
+        String content = "RFID:" + data + ", ANTNO: " + antennaNo + ", TIME: " + readTime + "\r\n";
+//        System.err.println("tcp--:" + content);
+        FileWriter fwriter = null;
+        try {
+            if (StringUtils.isBlank(data)) {
+                return;
+            }
+
+            // 封装实际数据
+            JSONObject object = new JSONObject();
+            object.put("RFID", data);
+            object.put("ANTNO", antennaNo);
+
+            // 不存在文件夹则创建
+            String filePath = RFIDConfig.getLog().getSavePath() + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "\\";
+            File file = new File(filePath);
+            if (!file.exists() && !file.isDirectory()) {
+                file.mkdir();
+            }
+            filePath += new SimpleDateFormat("yyyyMMdd HH").format(new Date()) + ".txt";
+            // true表示不覆盖原来的内容,而是加到文件的后面。若要覆盖原来的内容,直接省略这个参数就好
+            fwriter = new FileWriter(filePath, true);
+            fwriter.write(content);
+
+            // 收集数据
+            map.put(data, object);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        } finally {
+            try {
+                if (fwriter != null) {
+                    fwriter.flush();
+                    fwriter.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    public void onceReadTagEnd(Boolean result) {
+
+    }
+
+    public void serialPortException(String name, boolean result) {
+
+    }
+
+    public void heartBeat(String value, String deviceNo, String communicationMode) {
+        System.out.println("value " + value + " deviceNo " + deviceNo + " communicationMode " + communicationMode);
+    }
+
+    public void infraredTrigger(boolean direction, String value, String deviceNo, String communicationMode) {
+        System.out.println("方向 " + direction + " 红外值 " + value + " 设备号 " + deviceNo + " IP或串口号 " + communicationMode);
+    }
+
+    public void onceReadTagEnd(boolean arg0) {
+
+    }
+}

+ 130 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/callback/TcpCallBackSaveLog.java

@@ -0,0 +1,130 @@
+package com.fjhx.rfid.r2000.tcp.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.rabbitmq.enums.MsgSourceEnum;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.utils.spring.SpringUtils;
+import com.rfid.callBack.CallBack.R2000;
+import lombok.Data;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Data
+public class TcpCallBackSaveLog implements R2000 {
+
+    /**
+     * redis实例
+     */
+    private RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+
+    /**
+     * rabbitmq实例
+     */
+    private RabbitmqService rabbitmqService = SpringUtils.getBean(RabbitmqService.class);
+
+    /**
+     * rdis缓存key
+     */
+    private String redisKey;
+
+    /**
+     * 用户账号
+     */
+    private String userName;
+
+    private ConcurrentHashMap<String, JSONObject> map = new ConcurrentHashMap<>();
+
+    private String readTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+
+    public TcpCallBackSaveLog(String redisKey, String userName) {
+        this.redisKey = redisKey;
+        this.userName = userName;
+    }
+
+    public void readData(String data, String rssi, String antennaNo, String deviceNo, String direction, String communicationMode) {
+        String content = "RFID:" + data + ", ANTNO: " + antennaNo + ", TIME: " + readTime + "\r\n";
+//        System.err.println("tcp--:" + content);
+        FileWriter fwriter = null;
+        try {
+            if (StringUtils.isBlank(data)) {
+                return;
+            }
+
+            // 封装实际数据
+            JSONObject object = new JSONObject();
+            object.put("RFID", data);
+            object.put("ANTNO", antennaNo);
+
+            // 不存在文件夹则创建
+            String filePath = RFIDConfig.getLog().getSavePath() + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "\\";
+            File file = new File(filePath);
+            if (!file.exists() && !file.isDirectory()) {
+                file.mkdir();
+            }
+            filePath += new SimpleDateFormat("yyyyMMdd HH").format(new Date()) + ".txt";
+            // true表示不覆盖原来的内容,而是加到文件的后面。若要覆盖原来的内容,直接省略这个参数就好
+            fwriter = new FileWriter(filePath, true);
+
+            // 过滤重复写入
+            if (MapUtils.isEmpty(map) || map.get(data) == null) {
+                fwriter.write(content);
+
+                if (StringUtils.isNotBlank(userName)) {
+                    // -------------------- 往websocket推送消息 --------------------
+                    JSONObject jsonObject = new JSONObject();
+                    jsonObject.put("messageId", data);
+                    jsonObject.put("msgSource", MsgSourceEnum.MSG_SOURCE_2.getKey());
+                    jsonObject.put("userName", userName);
+                    jsonObject.put("notices", object);
+                    // 使用rabbitmq派转消息
+                    rabbitmqService.send(jsonObject);
+                }
+            }
+
+            // 收集数据
+            map.put(data, object);
+
+            // 存入缓存
+            redisCache.setCacheObject(redisKey, map);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        } finally {
+            try {
+                if (fwriter != null) {
+                    fwriter.flush();
+                    fwriter.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+
+    public void onceReadTagEnd(Boolean result) {
+
+    }
+
+    public void serialPortException(String name, boolean result) {
+
+    }
+
+    public void heartBeat(String value, String deviceNo, String communicationMode) {
+        System.out.println("value " + value + " deviceNo " + deviceNo + " communicationMode " + communicationMode);
+    }
+
+    public void infraredTrigger(boolean direction, String value, String deviceNo, String communicationMode) {
+        System.out.println("方向 " + direction + " 红外值 " + value + " 设备号 " + deviceNo + " IP或串口号 " + communicationMode);
+    }
+
+    public void onceReadTagEnd(boolean arg0) {
+
+    }
+}

+ 34 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/service/ISdTcpService.java

@@ -0,0 +1,34 @@
+package com.fjhx.rfid.r2000.tcp.service;
+
+import com.fjhx.utils.AjaxResult;
+import org.springframework.scheduling.annotation.Async;
+
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: TcpService
+ * @Author: linqt
+ * @Date: 2022/3/17 10:31
+ * @Version: 1.0
+ */
+public interface ISdTcpService {
+
+    /**
+     * 启动读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Async
+    AjaxResult open(List<String> ips);
+
+    /**
+     * 关闭读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Async
+    AjaxResult close(List<String> ips);
+}

+ 38 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/service/TcpService.java

@@ -0,0 +1,38 @@
+package com.fjhx.rfid.r2000.tcp.service;
+
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.utils.AjaxResult;
+
+/**
+ * @Description:
+ * @ClassName: TcpService
+ * @Author: linqt
+ * @Date: 2022/3/17 10:31
+ * @Version: 1.0
+ */
+public interface TcpService {
+
+    /**
+     * 启动单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult startOne(RFIDClient client);
+
+    /**
+     * 关闭单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult closeOne(RFIDClient client);
+
+    /**
+     * 启动多台
+     *
+     * @param client
+     * @return
+     */
+    AjaxResult openMore(RFIDClient client);
+}

+ 44 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/service/TcpServiceV2.java

@@ -0,0 +1,44 @@
+package com.fjhx.rfid.r2000.tcp.service;
+
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.utils.AjaxResult;
+
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: TcpService
+ * @Author: linqt
+ * @Date: 2022/3/17 10:31
+ * @Version: 1.0
+ */
+public interface TcpServiceV2 {
+
+    /**
+     * 启动并返回所有数据
+     *
+     * @param ips     读写器ip集合
+     * @param busUuid 业务唯一标识
+     * @param userId  业务服务端用户userId
+     * @return
+     */
+    AjaxResult openAndReturnAllData(List<String> ips, String busUuid, String userId);
+
+    /**
+     * 启动并返回去重数据
+     *
+     * @param ips     读写器ip集合
+     * @param busUuid 业务唯一标识
+     * @param userId  业务服务端用户userId
+     * @return
+     */
+    AjaxResult openAndReturnGoHeavyData(List<String> ips, String busUuid, String userId);
+
+    /**
+     * 关闭多台
+     *
+     * @param client
+     * @return
+     */
+    AjaxResult closeMore(RFIDClient client);
+}

+ 151 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/service/impl/ISdTcpServiceImpl.java

@@ -0,0 +1,151 @@
+package com.fjhx.rfid.r2000.tcp.service.impl;
+
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.rfid.r2000.tcp.callback.SdTcpCallBack;
+import com.fjhx.rfid.r2000.tcp.service.ISdTcpService;
+import com.fjhx.thread.ThreadPoolManager;
+import com.fjhx.utils.AjaxResult;
+import com.fjhx.utils.StringUtils;
+import com.fjhx.web.exception.BaseException;
+import com.rfid.uhf.controller.impl.ReaderR2000;
+import com.rfid.uhf.service.ReaderR2000Service;
+import com.rfid.uhf.service.impl.ReaderR2000ServiceImpl;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.stereotype.Service;
+
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * @Description:
+ * @ClassName: TcpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/17 10:32
+ * @Version: 1.0
+ */
+@Service
+public class ISdTcpServiceImpl implements ISdTcpService {
+
+    /**
+     * 初始化实例集合
+     */
+    private static ConcurrentHashMap<String, ConcurrentHashMap<String, Object>> sdTcpServerMap = new ConcurrentHashMap<>();
+
+    /**
+     * 启动读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Override
+    public AjaxResult open(List<String> ips) {
+        if (CollectionUtils.isEmpty(ips)) {
+            throw new BaseException("读写器IP地址不能为空!");
+        }
+        try {
+            CountDownLatch countDownLatch = new CountDownLatch(ips.size());
+            // 启动扫描线程
+            for (String ip : ips) {
+                //如果读写器已开启,则跳过
+                if (ObjectUtils.isNotEmpty(sdTcpServerMap.get(ip))) {
+                    System.err.println("IP为【" + ip + "】的读写器已开启。");
+                    continue;
+                }
+
+                CountDownLatch errCountDownLatch = countDownLatch;
+                ThreadPoolManager.execute(() -> {
+                    try {
+                        ReaderR2000Service service = new ReaderR2000ServiceImpl();
+                        ReaderR2000 reader = service.connect(ip, RFIDConfig.getSd().getTcp().getPort(), new SdTcpCallBack(ip));
+
+                        // 实例存储
+                        ConcurrentHashMap<String, Object> sMap = new ConcurrentHashMap<>();
+                        sMap.put("service", service);
+                        sMap.put("reader", reader);
+                        sdTcpServerMap.put(ip, sMap);
+                        System.err.println("连接成功----------");
+                        // 开始扫描
+                        service.beginInvV2(reader);
+                        while (true){
+                            String v = service.version(reader);
+                            if(ObjectUtils.isEmpty(v)){
+                                sdTcpServerMap.clear();
+                                this.open(ips);
+                            }else{
+                                System.err.println("当前连接正常----设备版本为:"+v);
+                                Thread.sleep(3000);
+                            }
+                        }
+                    } catch (Exception e) {
+//                        e.printStackTrace();
+//                        if (errCountDownLatch != null) {
+//                            errCountDownLatch.countDown();
+//                        }
+//                        throw new BaseException(MessageFormat.format(RFIDConstant.SERVER_START_ERR, ip));
+                        try {
+                            System.err.println("重新连接中----------");
+                            Thread.sleep(3000);
+                            this.open(ips);
+                        } catch (InterruptedException ex) {
+                            ex.printStackTrace();
+                        }
+                    }
+                });
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success();
+    }
+
+    /**
+     * 关闭读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Override
+    public AjaxResult close(List<String> ips) {
+        if (CollectionUtils.isEmpty(ips)) {
+            throw new BaseException("参数缺失!");
+        }
+        // 关闭线程
+        for (String ip : ips) {
+            try {
+                //如果读写器已开启,则跳过
+                if (ObjectUtils.isEmpty(sdTcpServerMap.get(ip))) {
+                    System.err.println("IP为【" + ip + "】的读写器已关闭。");
+                    continue;
+                }
+
+                // 获取实例
+                ConcurrentHashMap<String, Object> map = sdTcpServerMap.get(ip);
+                ReaderR2000Service service = (ReaderR2000Service) map.get("service");
+                ReaderR2000 reader = (ReaderR2000) map.get("reader");
+
+                // 结束扫描
+                service.stopInvV2(reader);
+
+                // 关闭连接
+                service.disconnect(reader);
+
+                // 移除服务
+                sdTcpServerMap.remove(ip);
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new BaseException(MessageFormat.format(RFIDConstant.SERVER_CLOSE_ERR, ip));
+            }
+        }
+
+        return AjaxResult.success();
+    }
+}

+ 251 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/service/impl/TcpServiceImpl.java

@@ -0,0 +1,251 @@
+package com.fjhx.rfid.r2000.tcp.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.rfid.r2000.tcp.callback.TcpCallBackSaveLog;
+import com.fjhx.rfid.r2000.tcp.service.TcpService;
+import com.fjhx.thread.ThreadPoolManager;
+import com.fjhx.utils.AjaxResult;
+import com.fjhx.web.exception.BaseException;
+import com.rfid.uhf.controller.impl.ReaderR2000;
+import com.rfid.uhf.service.ReaderR2000Service;
+import com.rfid.uhf.service.impl.ReaderR2000ServiceImpl;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @ClassName: TcpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/17 10:32
+ * @Version: 1.0
+ */
+@Service
+public class TcpServiceImpl implements TcpService {
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 初始化实例集合
+     */
+    private static Map<String, Map<String, Object>> serverMap = new HashMap<>();
+
+    /**
+     * 启动单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult startOne(RFIDClient client) {
+        if (client == null || StringUtils.isBlank(client.getIp())) {
+            throw new BaseException("读写器IP地址不能为空!");
+        }
+
+        ReaderR2000Service service = null;
+        ReaderR2000 reader = null;
+        try {
+            // redis tcp数据缓存key
+            String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, client.getIp());
+
+            service = new ReaderR2000ServiceImpl();
+            reader = service.connect(client.getIp(), client.getPort(), new TcpCallBackSaveLog(dataRedisKey, client.getUserName()));
+
+            // 实例静态化
+            Map<String, Object> map = new HashMap<>();
+            map.put("service", service);
+            map.put("reader", reader);
+            TcpServiceImpl.serverMap.put(client.getIp(), map);
+
+            // 开始扫描
+            boolean result = service.beginInvV2(reader);
+            if (!result) {
+                // 关闭连接
+                service.disconnect(reader);
+                throw new BaseException(RFIDConstant.SERVER_START_ERR);
+            }
+        } catch (Exception e) {
+            if (reader != null) {
+                // 关闭连接
+                service.disconnect(reader);
+            }
+            e.printStackTrace();
+            throw new BaseException(RFIDConstant.SERVER_START_ERR);
+        }
+        return AjaxResult.success(RFIDConstant.SERVER_START_SUCCESS);
+    }
+
+    /**
+     * 关闭单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult closeOne(RFIDClient client) {
+        if (client == null || StringUtils.isBlank(client.getIp())) {
+            throw new BaseException("读写器IP地址不能为空!");
+        }
+
+        Map<String, JSONObject> data = new HashMap<>();
+        List<JSONObject> list = new ArrayList<>();
+        ReaderR2000Service service;
+        ReaderR2000 reader;
+
+        // redis tcp数据缓存key
+        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, client.getIp());
+        try {
+            // 从静态获取实例
+            Map<String, Object> map = TcpServiceImpl.serverMap.get(client.getIp());
+            service = (ReaderR2000Service) map.get("service");
+            reader = (ReaderR2000) map.get("reader");
+
+            // 结束扫描
+            service.stopInvV2(reader);
+
+            // 关闭连接
+            service.disconnect(reader);
+
+            // 移除服务
+            serverMap.remove(client.getIp());
+
+            // 获取数据缓存
+            data = redisCache.getCacheObject(dataRedisKey);
+//            System.err.println("当前缓存中取出的数据量:" + data.size());
+
+            // 删除数据缓存
+            redisCache.deleteObject(dataRedisKey);
+
+            if (MapUtils.isNotEmpty(data)) {
+                list = data.values().stream().collect(Collectors.toList());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BaseException(RFIDConstant.SERVER_CLOSE_ERR);
+        }
+        return AjaxResult.success(RFIDConstant.SERVER_CLOSE_SUCCESS, list);
+    }
+
+    /**
+     * 启动多台
+     *
+     * @param client
+     * @return
+     */
+    @Override
+    public AjaxResult openMore(RFIDClient client) {
+        ConcurrentHashMap<String, ConcurrentHashMap<String, Object>> sMap = new ConcurrentHashMap<>();
+        ConcurrentHashMap<String, JSONObject> dataMap = new ConcurrentHashMap<>();
+        List<JSONObject> list = new ArrayList<>();
+
+        Integer count = 0;
+        try {
+            if (client == null || CollectionUtils.isEmpty(client.getIpList())) {
+                throw new BaseException("读写器IP地址不能为空!");
+            }
+            CountDownLatch countDownLatch = new CountDownLatch(client.getIpList().size());
+            // 启动扫描线程
+            for (String ip : client.getIpList()) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch errCountDownLatch = countDownLatch;
+                ThreadPoolManager.execute(() -> {
+                    try {
+                        // redis tcp数据缓存key
+                        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+                        ReaderR2000Service service = new ReaderR2000ServiceImpl();
+                        ReaderR2000 reader = service.connect(ip, client.getPort(), new TcpCallBackSaveLog(dataRedisKey, null));
+
+                        // 实例存储
+                        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
+                        map.put("service", service);
+                        map.put("reader", reader);
+                        sMap.put(ip + "-" + finalCount, map);
+                        // 开始扫描
+                        service.beginInvV2(reader);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        if (errCountDownLatch != null) {
+                            errCountDownLatch.countDown();
+                        }
+                        throw new BaseException(RFIDConstant.READ_DATA_ERR);
+                    }
+                });
+            }
+
+            // 读取时间
+            Thread.sleep(client.getReadTime());
+
+            count = 0;
+            // 关闭线程
+            for (String ip : client.getIpList()) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch finalCountDownLatch = countDownLatch;
+                try {
+                    // redis tcp数据缓存key
+                    String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+
+                    // 获取实例
+                    ConcurrentHashMap<String, Object> map = sMap.get(ip + "-" + finalCount);
+                    ReaderR2000Service service = (ReaderR2000Service) map.get("service");
+                    ReaderR2000 reader = (ReaderR2000) map.get("reader");
+
+                    // 结束扫描
+                    service.stopInvV2(reader);
+
+                    // 关闭连接
+                    service.disconnect(reader);
+
+                    // 移除服务
+                    serverMap.remove(ip + "-" + finalCount);
+
+                    // 获取数据缓存
+                    ConcurrentHashMap<String, JSONObject> data = redisCache.getCacheObject(dataRedisKey);
+                    if (MapUtils.isEmpty(data)) {
+//                        System.err.println(ip + "-" + finalCount + "当前缓存中取出的数据为空!");
+                        continue;
+                    }
+//                    System.err.println(ip + "-" + finalCount + "当前缓存中取出的数据量:" + data.size());
+                    dataMap.putAll(data);
+
+                    // 删除数据缓存
+                    redisCache.deleteObject(dataRedisKey);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                } finally {
+                    if (finalCountDownLatch != null) {
+                        finalCountDownLatch.countDown();
+                    }
+                }
+            }
+//            System.err.println("最终总结果数量--:" + dataMap.size());
+
+            if (MapUtils.isNotEmpty(dataMap)) {
+                list = dataMap.values().stream().collect(Collectors.toList());
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success(RFIDConstant.READ_DATA_SUCCESS, list);
+    }
+}

+ 276 - 0
src/main/java/com/fjhx/rfid/r2000/tcp/service/impl/TcpServiceImplV2.java

@@ -0,0 +1,276 @@
+package com.fjhx.rfid.r2000.tcp.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.rabbitmq.enums.MsgSourceEnum;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.rfid.r2000.tcp.callback.TcpCallBackAllData;
+import com.fjhx.rfid.r2000.tcp.callback.TcpCallBackGoHeavyData;
+import com.fjhx.rfid.r2000.tcp.service.TcpServiceV2;
+import com.fjhx.thread.ThreadPoolManager;
+import com.fjhx.utils.AjaxResult;
+import com.fjhx.utils.id.IdUtils;
+import com.fjhx.web.exception.BaseException;
+import com.rfid.uhf.controller.impl.ReaderR2000;
+import com.rfid.uhf.service.ReaderR2000Service;
+import com.rfid.uhf.service.impl.ReaderR2000ServiceImpl;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @ClassName: TcpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/17 10:32
+ * @Version: 1.0
+ */
+@Service
+public class TcpServiceImplV2 implements TcpServiceV2 {
+
+    @Autowired
+    private RedisCache redisCache;
+
+    @Autowired
+    private RabbitmqService rabbitmqService;
+
+    /**
+     * 初始化实例集合
+     */
+    private static ConcurrentHashMap<String, ConcurrentHashMap<String, Object>> serverMap = new ConcurrentHashMap<>();
+
+    /**
+     * 启动并返回所有数据
+     *
+     * @param ips     读写器ip集合
+     * @param busUuid 业务唯一标识
+     * @param userId  业务服务端用户userId
+     * @return
+     */
+    @Override
+    public AjaxResult openAndReturnAllData(List<String> ips, String busUuid, String userId) {
+        Integer count = 0;
+        try {
+            CountDownLatch countDownLatch = new CountDownLatch(ips.size());
+            System.err.println(serverMap);
+            // 启动扫描线程
+            for (String ip : ips) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch errCountDownLatch = countDownLatch;
+                List<JSONObject> list = new ArrayList<>();
+                ThreadPoolManager.execute(() -> {
+                    try {
+                        // redis tcp数据缓存key
+                        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+                        ReaderR2000Service service = new ReaderR2000ServiceImpl();
+                        ReaderR2000 reader = service.connect(ip, RFIDConfig.getTcp().getPort(), new TcpCallBackAllData(dataRedisKey, userId, ip, list));
+
+                        // 实例存储
+                        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
+                        map.put("service", service);
+                        map.put("reader", reader);
+                        serverMap.put(ip + "-" + busUuid + "-" + finalCount, map);
+                        // 开始扫描
+                        service.beginInvV2(reader);
+
+                        while (true) {
+                            //休眠1s进行数据收集
+                            Thread.sleep(1000);
+
+                            if (CollectionUtils.isNotEmpty(list)) {
+                                // -------------------- 使用rabbitmq派转消息 --------------------
+                                JSONObject jsonObject = new JSONObject();
+                                jsonObject.put("messageId", IdUtils.fastSimpleUUID());
+                                jsonObject.put("msgSource", MsgSourceEnum.MSG_SOURCE_2.getKey());
+                                jsonObject.put("userId", userId);
+                                jsonObject.put("notices", list);
+                                rabbitmqService.send(jsonObject);
+                                System.err.println("jsonObject--:" + jsonObject.toJSONString());
+                            }
+
+                            list.clear();
+                        }
+
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        if (errCountDownLatch != null) {
+                            errCountDownLatch.countDown();
+                        }
+                        throw new BaseException(MessageFormat.format(RFIDConstant.SERVER_START_ERR, ip));
+                    }
+                });
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success();
+    }
+
+    /**
+     * 启动并返回去重数据
+     *
+     * @param ips     读写器ip集合
+     * @param busUuid 业务唯一标识
+     * @param userId  业务服务端用户userId
+     * @return
+     */
+    @Override
+    public AjaxResult openAndReturnGoHeavyData(List<String> ips, String busUuid, String userId) {
+        Integer count = 0;
+        try {
+            CountDownLatch countDownLatch = new CountDownLatch(ips.size());
+            System.err.println(serverMap);
+            // 启动扫描线程
+            for (String ip : ips) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch errCountDownLatch = countDownLatch;
+                ConcurrentHashMap<String, JSONObject> map = new ConcurrentHashMap<>();
+                ThreadPoolManager.execute(() -> {
+                    try {
+                        // redis tcp数据缓存key
+                        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+                        ReaderR2000Service service = new ReaderR2000ServiceImpl();
+                        ReaderR2000 reader = service.connect(ip, RFIDConfig.getTcp().getPort(), new TcpCallBackGoHeavyData(dataRedisKey, userId, ip, map));
+
+                        // 实例存储
+                        ConcurrentHashMap<String, Object> sMap = new ConcurrentHashMap<>();
+                        sMap.put("service", service);
+                        sMap.put("reader", reader);
+                        serverMap.put(ip + "-" + busUuid + "-" + finalCount, sMap);
+                        // 开始扫描
+                        service.beginInvV2(reader);
+
+                        while (true) {
+                            //休眠1s进行数据收集
+                            Thread.sleep(1000);
+
+                            // -------------------- 使用rabbitmq派转消息 --------------------
+                            JSONObject jsonObject = new JSONObject();
+                            jsonObject.put("messageId", IdUtils.fastSimpleUUID());
+                            jsonObject.put("msgSource", MsgSourceEnum.MSG_SOURCE_2.getKey());
+                            jsonObject.put("userId", userId);
+                            jsonObject.put("notices", map.values().stream().collect(Collectors.toList()));
+                            rabbitmqService.send(jsonObject);
+                            System.err.println("jsonObject--:" + jsonObject.toJSONString());
+
+                            map.clear();
+                        }
+
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        if (errCountDownLatch != null) {
+                            errCountDownLatch.countDown();
+                        }
+                        throw new BaseException(MessageFormat.format(RFIDConstant.SERVER_START_ERR, ip));
+                    }
+                });
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success();
+    }
+
+    /**
+     * 关闭多台
+     *
+     * @param client
+     * @return
+     */
+    @Override
+    public AjaxResult closeMore(RFIDClient client) {
+        ConcurrentHashMap<String, JSONObject> dataMap = new ConcurrentHashMap<>();
+        List<JSONObject> list = new ArrayList<>();
+
+        Integer count = 0;
+        List<String> ips = RFIDConfig.getTcp().getIps();
+        try {
+            if (client == null) {
+                throw new BaseException("参数缺失!");
+            }
+            if (CollectionUtils.isNotEmpty(client.getIpList())) {
+                ips = client.getIpList();
+            }
+            CountDownLatch countDownLatch = new CountDownLatch(ips.size());
+            // 关闭线程
+            for (String ip : ips) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch finalCountDownLatch = countDownLatch;
+                try {
+                    // redis tcp数据缓存key
+                    String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_TCP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+
+                    // 获取实例
+                    ConcurrentHashMap<String, Object> map = serverMap.get(ip + "-" + finalCount);
+                    ReaderR2000Service service = (ReaderR2000Service) map.get("service");
+                    ReaderR2000 reader = (ReaderR2000) map.get("reader");
+
+                    // 结束扫描
+                    service.stopInvV2(reader);
+
+                    // 关闭连接
+                    service.disconnect(reader);
+
+                    // 移除服务
+                    serverMap.remove(ip + "-" + finalCount);
+
+                    // 获取数据缓存
+                    ConcurrentHashMap<String, JSONObject> data = redisCache.getCacheObject(dataRedisKey);
+                    if (MapUtils.isEmpty(data)) {
+//                        System.err.println(ip + "-" + finalCount + "当前缓存中取出的数据为空!");
+                        continue;
+                    }
+//                    System.err.println(ip + "-" + finalCount + "当前缓存中取出的数据量:" + data.size());
+                    dataMap.putAll(data);
+
+                    // 删除数据缓存
+                    redisCache.deleteObject(dataRedisKey);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                } finally {
+                    if (finalCountDownLatch != null) {
+                        finalCountDownLatch.countDown();
+                    }
+                }
+            }
+//            System.err.println("最终总结果数量--:" + dataMap.size());
+
+            if (MapUtils.isNotEmpty(dataMap)) {
+                list = dataMap.values().stream().collect(Collectors.toList());
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success(RFIDConstant.READ_DATA_SUCCESS, list);
+    }
+}

+ 88 - 0
src/main/java/com/fjhx/rfid/r2000/udp/callback/SdUdpCallBack.java

@@ -0,0 +1,88 @@
+package com.fjhx.rfid.r2000.udp.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.rfid.r2000.udp.utils.Utility;
+import com.fjhx.utils.StringUtils;
+import com.fjhx.utils.id.IdUtils;
+import com.fjhx.utils.spring.SpringUtils;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.socket.DatagramPacket;
+import lombok.Data;
+
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+@Data
+public class SdUdpCallBack extends SimpleChannelInboundHandler<DatagramPacket> {
+
+    /**
+     * redis实例
+     */
+    private RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+
+    /**
+     * rabbitmq实例
+     */
+    private RabbitmqService rabbitmqService = SpringUtils.getBean(RabbitmqService.class);
+
+    private String ip;
+
+    public SdUdpCallBack(String ip) {
+        this.ip = ip;
+    }
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
+        try {
+            ByteBuf byteBuf = msg.content();
+            byte[] bytes = new byte[byteBuf.readableBytes()];
+            byteBuf.readBytes(bytes);
+            String str = Utility.bytes2HexString(bytes);
+
+            // 如果返回的结果长度小于20,则跳过
+            if (StringUtils.isNotBlank(str) && str.length() > 20) {
+                // 截取天线号
+                String antNo = str.substring(RFIDConstant.UDP_RESULT_DATA_SUBSTRING_ANT_NO_BEGIN_INDEX, RFIDConstant.UDP_RESULT_DATA_SUBSTRING_ANT_NO_END_INDEX);
+                // 截取rfid
+                String rfid = str.substring(RFIDConstant.UDP_RESULT_DATA_SUBSTRING_RFID_BEGIN_INDEX, str.length() - RFIDConstant.UDP_RESULT_DATA_SUBSTRING_RFID_END_INDEX);
+
+                //是否发送
+                Boolean isSend = false;
+
+                //获取rfid缓存信息
+                Long time = redisCache.getCacheObject(MessageFormat.format(RedisKeyConstant.RFID_REDIS_CACHE_PREFIX, ip + "-" + antNo + "-" + rfid));
+                //缓存记录为空,或者上次的记录时间离现在超过5s,则发送信息
+                if (time == null || System.currentTimeMillis() - time > RFIDConstant.DEFAULT_TIME) {
+                    isSend = true;
+                }
+
+                // 存入缓存
+                redisCache.setCacheObject(MessageFormat.format(RedisKeyConstant.RFID_REDIS_CACHE_PREFIX, ip + "-" + antNo + "-" + rfid), new Date().getTime(), RFIDConfig.getDefaultTime(), TimeUnit.MILLISECONDS);
+
+                // 封装实际数据
+                JSONObject object = new JSONObject();
+                object.put("RFID", rfid);
+                object.put("ANTNO", antNo);
+                object.put("IP", ip);
+
+                if (isSend) {
+                    // -------------------- 使用rabbitmq派转消息 --------------------
+                    JSONObject jsonObject = new JSONObject();
+                    jsonObject.put("messageId", IdUtils.fastSimpleUUID());
+                    jsonObject.put("rfidMsg", object);
+                    rabbitmqService.sdSend(jsonObject);
+                }
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+}

+ 13 - 0
src/main/java/com/fjhx/rfid/r2000/udp/callback/UdpCallBack.java

@@ -0,0 +1,13 @@
+package com.fjhx.rfid.r2000.udp.callback;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.socket.DatagramPacket;
+
+public class UdpCallBack extends SimpleChannelInboundHandler<DatagramPacket> {
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket datagramPacket) throws Exception {
+
+    }
+}

+ 127 - 0
src/main/java/com/fjhx/rfid/r2000/udp/callback/UdpCallBackSaveLog.java

@@ -0,0 +1,127 @@
+package com.fjhx.rfid.r2000.udp.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.rabbitmq.enums.MsgSourceEnum;
+import com.fjhx.rabbitmq.service.RabbitmqService;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.rfid.r2000.udp.utils.Utility;
+import com.fjhx.utils.StringUtils;
+import com.fjhx.utils.spring.SpringUtils;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.socket.DatagramPacket;
+import lombok.Data;
+import org.apache.commons.collections4.MapUtils;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Data
+public class UdpCallBackSaveLog extends SimpleChannelInboundHandler<DatagramPacket> {
+
+    /**
+     * redis实例
+     */
+    private RedisCache redisCache = SpringUtils.getBean(RedisCache.class);
+
+    /**
+     * rabbitmq实例
+     */
+    private RabbitmqService rabbitmqService = SpringUtils.getBean(RabbitmqService.class);
+
+    /**
+     * rdis缓存key
+     */
+    private String redisKey;
+
+    /**
+     * 用户账号
+     */
+    private String userName;
+
+    private ConcurrentHashMap<String, JSONObject> map = new ConcurrentHashMap<>();
+
+    private String readTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
+
+    public UdpCallBackSaveLog(String redisKey, String userName) {
+        this.redisKey = redisKey;
+        this.userName = userName;
+    }
+
+    @Override
+    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
+        FileWriter fwriter = null;
+        try {
+            ByteBuf byteBuf = msg.content();
+            byte[] bytes = new byte[byteBuf.readableBytes()];
+            byteBuf.readBytes(bytes);
+            String str = Utility.bytes2HexString(bytes);
+
+            // 如果返回的结果长度小于20,则跳过
+            if (StringUtils.isNotBlank(str) && str.length() > 20) {
+                // 截取天线号
+                String antNo = str.substring(RFIDConstant.UDP_RESULT_DATA_SUBSTRING_ANT_NO_BEGIN_INDEX, RFIDConstant.UDP_RESULT_DATA_SUBSTRING_ANT_NO_END_INDEX);
+                // 截取rfid
+                String rfid = str.substring(RFIDConstant.UDP_RESULT_DATA_SUBSTRING_RFID_BEGIN_INDEX, str.length() - RFIDConstant.UDP_RESULT_DATA_SUBSTRING_RFID_END_INDEX);
+
+                String content = "RFID:" + rfid + ", ANTNO: " + antNo + ", TIME: " + readTime + "\r\n";
+//                System.err.println("UDP--:" + content);
+
+
+                // 封装实际数据
+                JSONObject object = new JSONObject();
+                object.put("RFID", rfid);
+                object.put("ANTNO", antNo);
+
+                // 存在文件夹则创建
+                String filePath = RFIDConfig.getLog().getSavePath() + new SimpleDateFormat("yyyyMMdd").format(new Date()) + "\\";
+                File file = new File(filePath);
+                if (!file.exists() && !file.isDirectory()) {
+                    file.mkdir();
+                }
+                filePath += new SimpleDateFormat("yyyyMMdd HH").format(new Date()) + ".txt";
+                // true表示不覆盖原来的内容,而是加到文件的后面。若要覆盖原来的内容,直接省略这个参数就好
+                fwriter = new FileWriter(filePath, true);
+
+                // 过滤重复写入
+                if (MapUtils.isEmpty(map) || map.get(rfid) == null) {
+                    fwriter.write(content);
+
+                    if (org.apache.commons.lang3.StringUtils.isNotBlank(userName)) {
+                        // -------------------- 往websocket推送消息 --------------------
+                        JSONObject jsonObject = new JSONObject();
+                        jsonObject.put("messageId", rfid);
+                        jsonObject.put("msgSource", MsgSourceEnum.MSG_SOURCE_2.getKey());
+                        jsonObject.put("userName", userName);
+                        jsonObject.put("notices", object);
+                        // 使用rabbitmq派转消息
+                        rabbitmqService.send(jsonObject);
+                    }
+                }
+
+                // 收集数据
+                map.put(rfid, object);
+
+                // 存入缓存
+                redisCache.setCacheObject(redisKey, map);
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        } finally {
+            try {
+                if (fwriter != null) {
+                    fwriter.flush();
+                    fwriter.close();
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+        }
+    }
+}

+ 34 - 0
src/main/java/com/fjhx/rfid/r2000/udp/service/ISdUdpService.java

@@ -0,0 +1,34 @@
+package com.fjhx.rfid.r2000.udp.service;
+
+import com.fjhx.utils.AjaxResult;
+import org.springframework.scheduling.annotation.Async;
+
+import java.util.List;
+
+/**
+ * @Description:
+ * @ClassName: UdpService
+ * @Author: linqt
+ * @Date: 2022/3/18 11:22
+ * @Version: 1.0
+ */
+public interface ISdUdpService {
+
+    /**
+     * 启动读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Async
+    AjaxResult open(List<String> ips);
+
+    /**
+     * 关闭读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Async
+    AjaxResult close(List<String> ips);
+}

+ 39 - 0
src/main/java/com/fjhx/rfid/r2000/udp/service/UdpService.java

@@ -0,0 +1,39 @@
+package com.fjhx.rfid.r2000.udp.service;
+
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.utils.AjaxResult;
+
+/**
+ * @Description:
+ * @ClassName: UdpService
+ * @Author: linqt
+ * @Date: 2022/3/18 11:22
+ * @Version: 1.0
+ */
+public interface UdpService {
+
+    /**
+     * 启动单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult startOne(RFIDClient client);
+
+    /**
+     * 关闭单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult closeOne(RFIDClient client);
+
+
+    /**
+     * 启动多台
+     *
+     * @param client
+     * @return
+     */
+    AjaxResult openMore(RFIDClient client);
+}

+ 143 - 0
src/main/java/com/fjhx/rfid/r2000/udp/service/impl/SdUdpServiceImpl.java

@@ -0,0 +1,143 @@
+package com.fjhx.rfid.r2000.udp.service.impl;
+
+import com.fjhx.config.RFIDConfig;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.rfid.r2000.udp.callback.SdUdpCallBack;
+import com.fjhx.rfid.r2000.udp.service.ISdUdpService;
+import com.fjhx.rfid.r2000.udp.utils.Utility;
+import com.fjhx.thread.ThreadPoolManager;
+import com.fjhx.utils.AjaxResult;
+import com.fjhx.web.exception.BaseException;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.stereotype.Service;
+
+import java.net.InetSocketAddress;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * @Description:
+ * @ClassName: UdpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/18 11:22
+ * @Version: 1.0
+ */
+@Service
+public class SdUdpServiceImpl implements ISdUdpService {
+
+    /**
+     * 初始化实例集合
+     */
+    private static ConcurrentHashMap<String, Object> sdUdpServerMap = new ConcurrentHashMap<>();
+
+    /**
+     * 启动读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Override
+    public AjaxResult open(List<String> ips) {
+        if (CollectionUtils.isEmpty(ips)) {
+            throw new BaseException("读写器IP地址不能为空!");
+        }
+        try {
+            CountDownLatch countDownLatch = new CountDownLatch(ips.size());
+            // 启动扫描线程
+            for (String ip : ips) {
+                //如果读写器已开启,则跳过
+                if (ObjectUtils.isNotEmpty(sdUdpServerMap.get(ip))) {
+                    System.err.println("IP为【" + ip + "】的读写器已开启。");
+                    continue;
+                }
+
+                CountDownLatch errCountDownLatch = countDownLatch;
+                ThreadPoolManager.execute(() -> {
+                    try {
+                        EventLoopGroup group = new NioEventLoopGroup();
+                        Bootstrap b = new Bootstrap();
+                        b.group(group)
+                                .channel(NioDatagramChannel.class)
+                                .option(ChannelOption.SO_BROADCAST, true)
+                                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
+                                .handler(new SdUdpCallBack(ip));
+                        Channel ch = b.bind(RFIDConstant.RFID_UDP_DEFAULT_BINDING_PORT).sync().channel();
+                        // 读取
+                        byte[] sendData = Utility.convert2HexArray(RFIDConstant.RFID_UDP_START_READ_INSTRUCTION);
+                        ByteBuf byteBuf = Unpooled.copiedBuffer(sendData);
+                        ch.writeAndFlush(new DatagramPacket(byteBuf, new InetSocketAddress(ip, RFIDConfig.getSd().getUdp().getPort()))).sync();
+
+                        // 实例静态化
+                        sdUdpServerMap.put(ip, ch);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        if (errCountDownLatch != null) {
+                            errCountDownLatch.countDown();
+                        }
+                        throw new BaseException(MessageFormat.format(RFIDConstant.SERVER_START_ERR, ip));
+                    }
+                });
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success();
+    }
+
+    /**
+     * 关闭读写器
+     *
+     * @param ips 读写器ip集合
+     * @return
+     */
+    @Override
+    public AjaxResult close(List<String> ips) {
+        if (CollectionUtils.isEmpty(ips)) {
+            throw new BaseException("参数缺失!");
+        }
+        // 关闭线程
+        for (String ip : ips) {
+            try {
+                //如果读写器已开启,则跳过
+                if (ObjectUtils.isEmpty(sdUdpServerMap.get(ip))) {
+                    System.err.println("IP为【" + ip + "】的读写器已关闭。");
+                    continue;
+                }
+
+                // 获取实例
+                Channel ch = (Channel) sdUdpServerMap.get(ip);
+                // 停止读取
+                byte[] sendData = Utility.convert2HexArray(RFIDConstant.RFID_UDP_STOP_READ_INSTRUCTION);
+                ByteBuf byteBuf = Unpooled.copiedBuffer(sendData);
+                ch.writeAndFlush(new DatagramPacket(byteBuf, new InetSocketAddress(ip, RFIDConfig.getSd().getUdp().getPort()))).sync();
+                ch.close();
+
+                // 移除服务
+                sdUdpServerMap.remove(ip);
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new BaseException(MessageFormat.format(RFIDConstant.SERVER_CLOSE_ERR, ip));
+            }
+        }
+
+        return AjaxResult.success();
+    }
+}

+ 244 - 0
src/main/java/com/fjhx/rfid/r2000/udp/service/impl/UdpServiceImpl.java

@@ -0,0 +1,244 @@
+package com.fjhx.rfid.r2000.udp.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.constant.RFIDConstant;
+import com.fjhx.constant.RedisKeyConstant;
+import com.fjhx.entity.rfid.RFIDClient;
+import com.fjhx.redis.RedisCache;
+import com.fjhx.rfid.r2000.udp.callback.UdpCallBackSaveLog;
+import com.fjhx.rfid.r2000.udp.service.UdpService;
+import com.fjhx.rfid.r2000.udp.utils.Utility;
+import com.fjhx.thread.ThreadPoolManager;
+import com.fjhx.utils.AjaxResult;
+import com.fjhx.web.exception.BaseException;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.net.InetSocketAddress;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+/**
+ * @Description:
+ * @ClassName: UdpServiceImpl
+ * @Author: linqt
+ * @Date: 2022/3/18 11:22
+ * @Version: 1.0
+ */
+@Service
+public class UdpServiceImpl implements UdpService {
+
+    @Autowired
+    private RedisCache redisCache;
+
+    /**
+     * 初始化实例集合
+     */
+    private static Map<String, Object> serverMap = new HashMap<>();
+
+    /**
+     * 启动单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult startOne(RFIDClient client) {
+        // redis udp数据缓存key
+        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_UDP_DATA_REDIS_CACHE_PREFIX, client.getIp());
+
+        try {
+            EventLoopGroup group = new NioEventLoopGroup();
+            Bootstrap b = new Bootstrap();
+            b.group(group)
+                    .channel(NioDatagramChannel.class)
+                    .option(ChannelOption.SO_BROADCAST, true)
+                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
+                    .handler(new UdpCallBackSaveLog(dataRedisKey, client.getUserName()));
+            Channel ch = b.bind(RFIDConstant.RFID_UDP_DEFAULT_BINDING_PORT).sync().channel();
+            // 读取
+            byte[] sendData = Utility.convert2HexArray(RFIDConstant.RFID_UDP_START_READ_INSTRUCTION);
+            ByteBuf byteBuf = Unpooled.copiedBuffer(sendData);
+            ch.writeAndFlush(new DatagramPacket(byteBuf, new InetSocketAddress(client.getIp(), client.getPort()))).sync();
+
+            // 实例静态化
+            serverMap.put(client.getIp(), ch);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BaseException(RFIDConstant.SERVER_START_ERR);
+        }
+        return AjaxResult.success(RFIDConstant.SERVER_START_SUCCESS);
+    }
+
+    /**
+     * 关闭单台
+     *
+     * @param client
+     * @return
+     */
+    public AjaxResult closeOne(RFIDClient client) {
+        Map<String, JSONObject> data = new HashMap<>();
+        List<JSONObject> list = new ArrayList<>();
+
+        // redis udp数据缓存key
+        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_UDP_DATA_REDIS_CACHE_PREFIX, client.getIp());
+
+        try {
+            // 从静态获取实例
+            Channel ch = (Channel) serverMap.get(client.getIp());
+            // 停止读取
+            byte[] sendData = Utility.convert2HexArray(RFIDConstant.RFID_UDP_STOP_READ_INSTRUCTION);
+            ByteBuf byteBuf = Unpooled.copiedBuffer(sendData);
+            ch.writeAndFlush(new DatagramPacket(byteBuf, new InetSocketAddress(client.getIp(), client.getPort()))).sync();
+            ch.close();
+
+            // 移除服务
+            serverMap.remove(client.getIp());
+
+            // 获取数据缓存
+            data = redisCache.getCacheObject(dataRedisKey);
+//            System.err.println("当前缓存中取出的数据量:" + data.size());
+
+            // 删除数据缓存
+            redisCache.deleteObject(dataRedisKey);
+
+            if (MapUtils.isNotEmpty(data)) {
+                list = data.values().stream().collect(Collectors.toList());
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new BaseException(RFIDConstant.SERVER_CLOSE_ERR);
+        }
+        return AjaxResult.success(RFIDConstant.SERVER_CLOSE_SUCCESS, list);
+    }
+
+    /**
+     * 启动多台
+     *
+     * @param client
+     * @return
+     */
+    @Override
+    public AjaxResult openMore(RFIDClient client) {
+        ConcurrentHashMap<String, Object> sMap = new ConcurrentHashMap<>();
+        ConcurrentHashMap<String, JSONObject> dataMap = new ConcurrentHashMap<>();
+        List<JSONObject> list = new ArrayList<>();
+
+        Integer count = 0;
+        try {
+            if (client == null || CollectionUtils.isEmpty(client.getIpList())) {
+                throw new BaseException("读写器IP地址不能为空!");
+            }
+            CountDownLatch countDownLatch = new CountDownLatch(client.getIpList().size());
+            // 启动扫描线程
+            for (String ip : client.getIpList()) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch errCountDownLatch = countDownLatch;
+                ThreadPoolManager.execute(() -> {
+                    try {
+                        // redis udp数据缓存key
+                        String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_UDP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+                        EventLoopGroup group = new NioEventLoopGroup();
+                        Bootstrap b = new Bootstrap();
+                        b.group(group)
+                                .channel(NioDatagramChannel.class)
+                                .option(ChannelOption.SO_BROADCAST, true)
+                                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
+                                .handler(new UdpCallBackSaveLog(dataRedisKey, null));
+                        Channel ch = b.bind(RFIDConstant.RFID_UDP_DEFAULT_BINDING_PORT).sync().channel();
+                        // 读取
+                        byte[] sendData = Utility.convert2HexArray(RFIDConstant.RFID_UDP_START_READ_INSTRUCTION);
+                        ByteBuf byteBuf = Unpooled.copiedBuffer(sendData);
+                        ch.writeAndFlush(new DatagramPacket(byteBuf, new InetSocketAddress(ip, client.getPort()))).sync();
+
+                        // 实例静态化
+                        sMap.put(ip + "-" + finalCount, ch);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        if (errCountDownLatch != null) {
+                            errCountDownLatch.countDown();
+                        }
+                        throw new BaseException(RFIDConstant.READ_DATA_ERR);
+                    }
+                });
+            }
+
+            // 读取时间
+            Thread.sleep(client.getReadTime());
+
+            count = 0;
+            // 关闭线程
+            for (String ip : client.getIpList()) {
+                count++;
+                Integer finalCount = count;
+                CountDownLatch finalCountDownLatch = countDownLatch;
+                try {
+                    // redis udp数据缓存key
+                    String dataRedisKey = MessageFormat.format(RedisKeyConstant.RFID_UDP_DATA_REDIS_CACHE_PREFIX, ip + "-" + finalCount);
+
+                    // 获取实例
+                    Channel ch = (Channel) sMap.get(ip + "-" + finalCount);
+                    // 停止读取
+                    byte[] sendData = Utility.convert2HexArray(RFIDConstant.RFID_UDP_STOP_READ_INSTRUCTION);
+                    ByteBuf byteBuf = Unpooled.copiedBuffer(sendData);
+                    ch.writeAndFlush(new DatagramPacket(byteBuf, new InetSocketAddress(ip, client.getPort()))).sync();
+                    ch.close();
+
+                    // 移除服务
+                    sMap.remove(ip + "-" + finalCount);
+
+                    // 获取数据缓存
+                    ConcurrentHashMap<String, JSONObject> data = redisCache.getCacheObject(dataRedisKey);
+                    if (MapUtils.isEmpty(data)) {
+//                        System.err.println(ip + "-" + finalCount + "当前缓存中取出的数据为空!");
+                        continue;
+                    }
+//                    System.err.println(ip + "-" + finalCount + "当前缓存中取出的数据量:" + data.size());
+                    dataMap.putAll(data);
+
+                    // 删除数据缓存
+                    redisCache.deleteObject(dataRedisKey);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                } finally {
+                    if (finalCountDownLatch != null) {
+                        finalCountDownLatch.countDown();
+                    }
+                }
+            }
+//            System.err.println("最终总结果数量--:" + dataMap.size());
+
+            if (MapUtils.isNotEmpty(dataMap)) {
+                list = dataMap.values().stream().collect(Collectors.toList());
+            }
+
+            if (countDownLatch != null) {
+                countDownLatch.await();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return AjaxResult.success(RFIDConstant.READ_DATA_SUCCESS, list);
+    }
+}

+ 223 - 0
src/main/java/com/fjhx/rfid/r2000/udp/utils/Utility.java

@@ -0,0 +1,223 @@
+package com.fjhx.rfid.r2000.udp.utils;
+
+//import java.text.ParseException;
+
+import io.netty.buffer.ByteBuf;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * 字符串,字节数据之间转换的帮助类
+ */
+public class Utility {
+    private static final Logger LOG = Logger.getLogger(Utility.class.getName());
+
+    public static String timeFormatString = "yyyy/MM/dd HH:mm:ss";
+    public static SimpleDateFormat timeFormat = new SimpleDateFormat(timeFormatString);
+
+    public static String hex(byte[] bytes) {
+        StringBuilder result = new StringBuilder();
+        for (byte aByte : bytes) {
+            int decimal = (int) aByte & 0xff;               // bytes widen to int, need mask, prevent sign extension
+            // get last 8 bits
+            String hex = Integer.toHexString(decimal);
+            if (hex.length() % 2 == 1) {                    // if half hex, pad with zero, e.g \t
+                hex = "0" + hex;
+            }
+            result.append(hex);
+        }
+        return result.toString();
+    }
+
+    /**
+     * 字符串转化成为16进制字符串
+     *
+     * @param s
+     * @return
+     */
+    public static String strTo16(String s) {
+        String str = "";
+        for (int i = 0; i < s.length(); i++) {
+            int ch = (int) s.charAt(i);
+            String s4 = Integer.toHexString(ch);
+            str = str + s4;
+        }
+        return str;
+    }
+
+    /**
+     * 字符串转换成为16进制(无需Unicode编码)
+     *
+     * @param str
+     * @return
+     */
+    public static String str2HexStr(String str) {
+        char[] chars = "0123456789ABCDEF".toCharArray();
+        StringBuilder sb = new StringBuilder("");
+        byte[] bs = str.getBytes();
+        int bit;
+        for (int i = 0; i < bs.length; i++) {
+            bit = (bs[i] & 0x0f0) >> 4;
+            sb.append(chars[bit]);
+            bit = bs[i] & 0x0f;
+            sb.append(chars[bit]);
+            // sb.append(' ');
+        }
+        return sb.toString().trim();
+    }
+
+    /**
+     * @param hexString
+     * @return
+     */
+    public static byte[] convert2HexArray(String hexString) {
+        int m = 0, n = 0;
+        int byteLen = hexString.length() / 2; // 每两个字符描述一个字节
+        byte[] ret = new byte[byteLen];
+        for (int i = 0; i < byteLen; i++) {
+            m = i * 2 + 1;
+            n = m + 1;
+            int intVal = Integer.decode("0x" + hexString.substring(i * 2, m) + hexString.substring(m, n));
+            ret[i] = Byte.valueOf((byte) intVal);
+        }
+        return ret;
+    }
+
+    /**
+     * @param b
+     * @param count convert number
+     * @return
+     */
+    public static String bytes2HexString(byte[] b, int count) {
+        String ret = "";
+        for (int i = 0; i < count; i++) {
+            String hex = Integer.toHexString(b[i] & 0xFF);
+            if (hex.length() == 1) {
+                hex = '0' + hex;
+            }
+            ret += hex.toUpperCase();
+        }
+        return ret;
+    }
+
+    public static String bytes2HexString(byte[] b) {
+        String ret = "";
+        for (int i = 0; i < b.length; i++) {
+            String hex = Integer.toHexString(b[i] & 0xFF);
+            if (hex.length() == 1) {
+                hex = '0' + hex;
+            }
+            ret += hex.toUpperCase();
+        }
+        return ret;
+    }
+
+    public static byte BYTE(int i) {
+        return (byte) i;
+    }
+
+    /**
+     * check whether the str is a hex str
+     *
+     * @param str  str
+     * @param bits bits
+     * @return true or false
+     */
+    public static boolean isHexString(String str, int bits) {
+        String patten = "[abcdefABCDEF0123456789]{" + bits + "}";
+        if (str.matches(patten)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static boolean isHexString(String str) {
+        String patten = "[abcdefABCDEF0123456789]{1,}";
+        if (str.matches(patten)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static boolean isNumber(String str) {
+        String patten = "[-]{0,1}[0123456789]{0,}";
+        return str.matches(patten);
+    }
+
+    public static boolean isValiadTimeString(String dateString) {
+        timeFormat.setLenient(false);
+        try {
+            timeFormat.parse(dateString);
+        } catch (Exception ex) {
+            Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
+            LOG.info(dateString + " bad format");
+            return false;
+        }
+        LOG.info(dateString);
+        return true;
+    }
+
+    public static void main(String[] args) {
+        //SimpleDateFormat format = new SimpleDateFormat(dateFormatString);
+        timeFormat.setLenient(false);
+        try {
+            Date date = timeFormat.parse("2012/11/0a 12:34:07");
+            //format = new SimpleDateFormat(dateFormatString, Locale.getDefault())
+            System.err.println(date.toLocaleString());
+        } catch (Exception ex) {
+            Logger.getLogger(Utility.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+        System.err.println(isValiadTimeString("1984/10/13 19:45:40"));
+    }
+
+    /**
+     * ByteBuf 转换 String
+     *
+     * @param buf
+     * @return
+     */
+    public static String convertByteBufToString(ByteBuf buf) {
+        String str;
+        if (buf.hasArray()) { // 处理堆缓冲区
+            str = new String(buf.array(), buf.arrayOffset() + buf.readerIndex(), buf.readableBytes());
+        } else { // 处理直接缓冲区以及复合缓冲区
+            byte[] bytes = new byte[buf.readableBytes()];
+            buf.getBytes(buf.readerIndex(), bytes);
+            str = new String(bytes, 0, buf.readableBytes());
+        }
+        return str;
+    }
+
+    /**
+     * ByteBuffer 转换 String
+     *
+     * @param buffer
+     * @return
+     */
+    public static String convertByteBufferToString(ByteBuffer buffer) {
+        Charset charset = null;
+        CharsetDecoder decoder = null;
+        CharBuffer charBuffer = null;
+        try {
+            charset = Charset.forName("UTF-8");
+            decoder = charset.newDecoder();
+            // charBuffer = decoder.decode(buffer);//用这个的话,只能输出来一次结果,第二次显示为空
+            charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
+            return charBuffer.toString();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            return "";
+        }
+    }
+
+}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio