Browse Source

add;多topic配置,二维码

wulianwei 1 năm trước cách đây
mục cha
commit
b3cf19b9e6
31 tập tin đã thay đổi với 999 bổ sung191 xóa
  1. 128 121
      pom.xml
  2. 30 5
      src/main/java/com/tuoren/forward/config/amqp/AmqpClient1.java
  3. 30 10
      src/main/java/com/tuoren/forward/config/amqp/AmqpClient2.java
  4. 11 1
      src/main/java/com/tuoren/forward/config/mqtt/MqttCallbackCustom.java
  5. 1 0
      src/main/java/com/tuoren/forward/constant/CommonConstant.java
  6. 61 0
      src/main/java/com/tuoren/forward/controller/DevConfigController.java
  7. 20 0
      src/main/java/com/tuoren/forward/controller/DeviceController.java
  8. 10 0
      src/main/java/com/tuoren/forward/controller/UserController.java
  9. 26 0
      src/main/java/com/tuoren/forward/entity/DevConfig.java
  10. 18 0
      src/main/java/com/tuoren/forward/entity/MqTick.java
  11. 3 0
      src/main/java/com/tuoren/forward/entity/User.java
  12. 21 0
      src/main/java/com/tuoren/forward/entity/req/DeviceBindReq.java
  13. 18 0
      src/main/java/com/tuoren/forward/entity/req/ReLoginReq.java
  14. 15 0
      src/main/java/com/tuoren/forward/entity/resp/QRCodeResp.java
  15. 13 5
      src/main/java/com/tuoren/forward/init/AmqpInit.java
  16. 2 0
      src/main/java/com/tuoren/forward/init/MqttInit.java
  17. 19 0
      src/main/java/com/tuoren/forward/mapper/DevConfigMapper.java
  18. 21 0
      src/main/java/com/tuoren/forward/mapper/MqTickMapper.java
  19. 2 0
      src/main/java/com/tuoren/forward/mapper/UserMapper.java
  20. 69 0
      src/main/java/com/tuoren/forward/service/DevConfigService.java
  21. 52 0
      src/main/java/com/tuoren/forward/service/DeviceService.java
  22. 42 0
      src/main/java/com/tuoren/forward/service/MqTickService.java
  23. 54 0
      src/main/java/com/tuoren/forward/service/UserService.java
  24. 98 3
      src/main/resources/application.yml
  25. 22 0
      src/main/resources/db/migration/V1.0.1__dev_config.sql
  26. 0 13
      src/main/resources/db/migration/V1.0.1__satasitc_init.sql
  27. 0 30
      src/main/resources/db/migration/V1.0.2__modle_update.sql
  28. 1 1
      src/main/resources/generatorConfig.xml
  29. 115 0
      src/main/resources/mapper/DevConfigMapper.xml
  30. 84 0
      src/main/resources/mapper/MqTickMapper.xml
  31. 13 2
      src/main/resources/mapper/UserMapper.xml

+ 128 - 121
pom.xml

@@ -1,79 +1,80 @@
-<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>
+<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.tuoren</groupId>
-  <artifactId>forward</artifactId>
-  <version>0.0.1-SNAPSHOT</version>
-  <packaging>jar</packaging>
+	<groupId>com.tuoren</groupId>
+	<artifactId>forward</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<packaging>jar</packaging>
 
-  <name>forward</name>
-  <url>http://maven.apache.org</url>
+	<name>forward</name>
+	<url>http://maven.apache.org</url>
 
-  <properties>
+	<properties>
 		<encoding>UTF-8</encoding>
 		<java-version>1.8</java-version>
 	</properties>
 	<parent>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-starter-parent</artifactId>
-        <version>2.7.16</version>
-    </parent>
-    
-    <dependencies>
-    	<dependency>
-		    <groupId>org.springframework.boot</groupId>
-		    <artifactId>spring-boot-starter-web</artifactId>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>2.7.16</version>
+	</parent>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
 		</dependency>
-		
+
 		<dependency>
-		    <groupId>org.springframework.boot</groupId>
-		    <artifactId>spring-boot-starter-aop</artifactId>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-aop</artifactId>
 		</dependency>
 
-	    <dependency>
-		    <groupId>org.springframework.boot</groupId>
-		    <artifactId>spring-boot-starter-jdbc</artifactId>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-jdbc</artifactId>
 		</dependency>
 		<dependency>
-		    <groupId>org.mybatis.spring.boot</groupId>
-		    <artifactId>mybatis-spring-boot-starter</artifactId>
-		    <version>2.3.1</version>
+			<groupId>org.mybatis.spring.boot</groupId>
+			<artifactId>mybatis-spring-boot-starter</artifactId>
+			<version>2.3.1</version>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework.boot</groupId>
 			<artifactId>spring-boot-starter-data-redis</artifactId>
 		</dependency>
 		<dependency>
-		    <groupId>org.mybatis.generator</groupId>
-		    <artifactId>mybatis-generator-core</artifactId>
-		    <version>1.4.2</version>
+			<groupId>org.mybatis.generator</groupId>
+			<artifactId>mybatis-generator-core</artifactId>
+			<version>1.4.2</version>
 		</dependency>
 		<dependency>
 			<groupId>com.mysql</groupId>
-        	<artifactId>mysql-connector-j</artifactId>
+			<artifactId>mysql-connector-j</artifactId>
 			<scope>runtime</scope>
 		</dependency>
 		<!-- SpringBoot MongoDB -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-data-mongodb</artifactId>
-        </dependency>
 		<dependency>
-		    <groupId>com.github.pagehelper</groupId>
-		    <artifactId>pagehelper-spring-boot-starter</artifactId>
-		    <version>1.4.7</version>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-mongodb</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>com.github.pagehelper</groupId>
+			<artifactId>pagehelper-spring-boot-starter</artifactId>
+			<version>1.4.7</version>
 		</dependency>
-		
+
 		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>
 		</dependency>
-		
+
 		<dependency>
-		    <groupId>com.alibaba.fastjson2</groupId>
-		    <artifactId>fastjson2</artifactId>
-		    <version>2.0.51</version>
+			<groupId>com.alibaba.fastjson2</groupId>
+			<artifactId>fastjson2</artifactId>
+			<version>2.0.51</version>
 		</dependency>
 
 		<dependency>
@@ -82,93 +83,99 @@
 		</dependency>
 		<!-- 提供Redis连接池 -->
 		<dependency>
-		    <groupId>org.apache.commons</groupId>
-		    <artifactId>commons-pool2</artifactId>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-pool2</artifactId>
 		</dependency>
-		
+
 		<dependency>
-		    <groupId>com.github.xiaoymin</groupId>
-		    <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
-		    <version>4.1.0</version>
+			<groupId>com.github.xiaoymin</groupId>
+			<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
+			<version>4.1.0</version>
 		</dependency>
-		
+
 		<!-- Sa-Token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
 		<dependency>
-		    <groupId>cn.dev33</groupId>
-		    <artifactId>sa-token-spring-boot-starter</artifactId>
-		    <version>1.30.0</version>
+			<groupId>cn.dev33</groupId>
+			<artifactId>sa-token-spring-boot-starter</artifactId>
+			<version>1.30.0</version>
+		</dependency>
+		<dependency>
+			<groupId>cn.dev33</groupId>
+			<artifactId>sa-token-dao-redis-jackson</artifactId>
+			<version>1.30.0</version>
 		</dependency>
+
 		<dependency>
-		    <groupId>cn.dev33</groupId>
-		    <artifactId>sa-token-dao-redis-jackson</artifactId>
-		    <version>1.30.0</version>
+			<groupId>cn.hutool</groupId>
+			<artifactId>hutool-all</artifactId>
+			<version>5.7.22</version>
 		</dependency>
-		
+		<!-- 二维码 -->
 		<dependency>
-		    <groupId>cn.hutool</groupId>
-		    <artifactId>hutool-all</artifactId>
-		    <version>5.7.22</version>
+			<groupId>com.google.zxing</groupId>
+			<artifactId>core</artifactId>
+			<version>3.5.3</version>
 		</dependency>
 		<!-- amqp 1.0 qpid client -->
-		 <dependency>
-		   <groupId>org.apache.qpid</groupId>
-		   <artifactId>qpid-jms-client</artifactId>
-		   <version>0.57.0</version>
-		 </dependency>
-		 <!-- util for base64-->
-		 <dependency>
-		   <groupId>commons-codec</groupId>
-		  <artifactId>commons-codec</artifactId>
-		</dependency>
-		 <!--mqtt依赖-->
-        <dependency>
-            <groupId>org.eclipse.paho</groupId>
-            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
-            <version>1.2.2</version>
-        </dependency>
-        <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
-        <dependency>
-		    <groupId>com.squareup.okhttp3</groupId>
-		    <artifactId>okhttp</artifactId>
+		<dependency>
+			<groupId>org.apache.qpid</groupId>
+			<artifactId>qpid-jms-client</artifactId>
+			<version>0.57.0</version>
+		</dependency>
+		<!-- util for base64-->
+		<dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+		</dependency>
+		<!--mqtt依赖-->
+		<dependency>
+			<groupId>org.eclipse.paho</groupId>
+			<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
+			<version>1.2.2</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
+		<dependency>
+			<groupId>com.squareup.okhttp3</groupId>
+			<artifactId>okhttp</artifactId>
 		</dependency>
 		<!-- https://mvnrepository.com/artifact/org.flywaydb/flyway-core -->
 		<dependency>
-		    <groupId>org.flywaydb</groupId>
-		    <artifactId>flyway-core</artifactId>
+			<groupId>org.flywaydb</groupId>
+			<artifactId>flyway-core</artifactId>
 		</dependency>
 		<dependency>
-		    <groupId>org.flywaydb</groupId>
-		    <artifactId>flyway-mysql</artifactId>
+			<groupId>org.flywaydb</groupId>
+			<artifactId>flyway-mysql</artifactId>
 		</dependency>
 		<!--阿里云短信服务-->
 		<dependency>
-	      <groupId>com.aliyun</groupId>
-	      <artifactId>dysmsapi20170525</artifactId>
-	      <version>2.0.24</version>
-	    </dependency>
-	    <dependency>
-	      <groupId>com.aliyun</groupId>
-	      <artifactId>tea-openapi</artifactId>
-	      <version>0.3.2</version>
-	    </dependency>
-	    <dependency>
-	      <groupId>com.aliyun</groupId>
-	      <artifactId>tea-console</artifactId>
-	      <version>0.0.1</version>
-	    </dependency>
-	    <dependency>
-	      <groupId>com.aliyun</groupId>
-	      <artifactId>tea-util</artifactId>
-	      <version>0.2.21</version>
-	    </dependency>
-        <!--<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>dysmsapi20170525</artifactId>
+			<version>2.0.24</version>
+		</dependency>
+		<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>tea-openapi</artifactId>
+			<version>0.3.2</version>
+		</dependency>
+		<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>tea-console</artifactId>
+			<version>0.0.1</version>
+		</dependency>
+		<dependency>
+			<groupId>com.aliyun</groupId>
+			<artifactId>tea-util</artifactId>
+			<version>0.2.21</version>
+		</dependency>
+		<!--<dependency>
         	<groupId>com.demo</groupId>
         	<artifactId>forward</artifactId>
         	<version>0.0.1-SNAPSHOT</version>
         </dependency>-->
-    </dependencies>
-    
-    <build>
+	</dependencies>
+
+	<build>
 		<plugins>
 			<plugin>
 				<groupId>org.apache.maven.plugins</groupId>
@@ -191,22 +198,22 @@
 				</executions>
 			</plugin>
 			<plugin>
-                <groupId>org.mybatis.generator</groupId>
-                <artifactId>mybatis-generator-maven-plugin</artifactId>
-                <version>1.4.2</version>
-                <configuration>
-                   <!--  mybatis-generator 配置文件存放地址 -->
-                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
-                    <!-- <overwrite>true</overwrite>-->
-                </configuration>
-                <dependencies>
-                    <dependency>
+				<groupId>org.mybatis.generator</groupId>
+				<artifactId>mybatis-generator-maven-plugin</artifactId>
+				<version>1.4.2</version>
+				<configuration>
+					<!--  mybatis-generator 配置文件存放地址 -->
+					<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
+					<!-- <overwrite>true</overwrite>-->
+				</configuration>
+				<dependencies>
+					<dependency>
 						<groupId>com.mysql</groupId>
-        				<artifactId>mysql-connector-j</artifactId>
+						<artifactId>mysql-connector-j</artifactId>
 						<version>${mysql.version}</version>
 					</dependency>
-                </dependencies>
-            </plugin>
+				</dependencies>
+			</plugin>
 		</plugins>
 	</build>
 </project>

+ 30 - 5
src/main/java/com/tuoren/forward/config/amqp/AmqpClient1.java

@@ -29,22 +29,26 @@ import org.apache.qpid.jms.JmsConnection;
 import org.apache.qpid.jms.JmsConnectionListener;
 import org.apache.qpid.jms.message.JmsInboundMessageDispatch;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.stereotype.Component;
 
-import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONObject;
 import com.tuoren.forward.config.mqtt.MqttUtil;
 import com.tuoren.forward.constant.CommonConstant;
+import com.tuoren.forward.entity.DevConfig;
 import com.tuoren.forward.entity.Device;
 import com.tuoren.forward.entity.Model;
+import com.tuoren.forward.entity.MqTick;
 import com.tuoren.forward.entity.SatasticDay;
 import com.tuoren.forward.entity.StationLocation;
 import com.tuoren.forward.entity.User;
 import com.tuoren.forward.entity.dto.ModelDto;
+import com.tuoren.forward.mapper.DevConfigMapper;
 import com.tuoren.forward.mapper.DeviceMapper;
 import com.tuoren.forward.mapper.ModelMapper;
+import com.tuoren.forward.mapper.MqTickMapper;
 import com.tuoren.forward.mapper.SatasticDayMapper;
 import com.tuoren.forward.mapper.StationLocationMapper;
 import com.tuoren.forward.mapper.UserMapper;
@@ -58,6 +62,7 @@ import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
 @Component
+@ConditionalOnProperty(value = "aliyun1.enable")
 @ConfigurationProperties(prefix = "aliyun1")
 @Setter
 public class AmqpClient1 {
@@ -91,6 +96,9 @@ public class AmqpClient1 {
     @Autowired
     UserMapper userMapper;
     
+    @Autowired
+    DevConfigMapper devConfigMapper;
+    
     @Autowired
     SatasticDayMapper satasticDayMapper;
     
@@ -106,10 +114,13 @@ public class AmqpClient1 {
     @Autowired
     ModelMapper modelMapper;
     
+    @Autowired
+    MqTickMapper mqTickMapper;
+    
   //业务处理异步线程池,线程池参数可以根据您的业务特点调整,或者您也可以用其他异步方式处理接收到的消息。
     private final static ExecutorService executorService = new ThreadPoolExecutor(
-        Runtime.getRuntime().availableProcessors(),
-        Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS,
+        1,
+        1, 60, TimeUnit.SECONDS,
         new LinkedBlockingQueue<Runnable>(50000));
     
     public void connection() throws Exception{
@@ -207,8 +218,9 @@ public class AmqpClient1 {
      
             String hospitalCode = !items.containsKey("userId") ? "" : items.getString("userId");
             String tenentId = "";
+            User owner = null;
             if(!StringUtils.isEmpty(hospitalCode)) {
-            	User owner = userMapper.selectByCode(hospitalCode);
+                owner = userMapper.selectByCode(hospitalCode);
             	if(owner == null) {
         			log.info("不存在该医院:"+hospitalCode);
         			//return;
@@ -295,7 +307,20 @@ public class AmqpClient1 {
     			JSONObject mqttJson = JSONObject.from(record);
     			mqttJson.put("items", items);
     			log.info("mqtt publish1:"+  mqttJson.toString());
-    			mqttUtil.pub(CommonConstant.MQTT_PUBLISH_PREFIX+hospitalCode, mqttJson.toString());
+    			if(owner != null) {
+    				DevConfig config = devConfigMapper.selectByPrimaryKey(owner.getId());
+    				if(!StringUtils.isEmpty(config.getMqttTopic())) {
+    					String[] topics = config.getMqttTopic().split(",");
+    					for(String t : topics) {
+    						MqTick mt = mqTickMapper.selectOnlineByTopic(t);
+    						if(mt != null) {
+    							mqttUtil.pub(CommonConstant.MQTT_PUBLISH_PREFIX+hospitalCode+t, mqttJson.toString());
+    						}
+    					}
+    				}
+    			}else {
+    				mqttUtil.pub(CommonConstant.MQTT_PUBLISH_PREFIX+hospitalCode, mqttJson.toString());
+    			}
     		}
         } catch (Exception e) {
         	log.error("processMessage occurs error ", e);

+ 30 - 10
src/main/java/com/tuoren/forward/config/amqp/AmqpClient2.java

@@ -29,6 +29,7 @@ import org.apache.qpid.jms.JmsConnection;
 import org.apache.qpid.jms.JmsConnectionListener;
 import org.apache.qpid.jms.message.JmsInboundMessageDispatch;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.stereotype.Component;
@@ -36,14 +37,18 @@ import org.springframework.stereotype.Component;
 import com.alibaba.fastjson2.JSONObject;
 import com.tuoren.forward.config.mqtt.MqttUtil;
 import com.tuoren.forward.constant.CommonConstant;
+import com.tuoren.forward.entity.DevConfig;
 import com.tuoren.forward.entity.Device;
 import com.tuoren.forward.entity.Model;
+import com.tuoren.forward.entity.MqTick;
 import com.tuoren.forward.entity.SatasticDay;
 import com.tuoren.forward.entity.StationLocation;
 import com.tuoren.forward.entity.User;
 import com.tuoren.forward.entity.dto.ModelDto;
+import com.tuoren.forward.mapper.DevConfigMapper;
 import com.tuoren.forward.mapper.DeviceMapper;
 import com.tuoren.forward.mapper.ModelMapper;
+import com.tuoren.forward.mapper.MqTickMapper;
 import com.tuoren.forward.mapper.SatasticDayMapper;
 import com.tuoren.forward.mapper.StationLocationMapper;
 import com.tuoren.forward.mapper.UserMapper;
@@ -57,6 +62,7 @@ import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
 @Component
+@ConditionalOnProperty(value = "aliyun2.enable")
 @ConfigurationProperties(prefix = "aliyun2")
 @Setter
 public class AmqpClient2 {
@@ -90,6 +96,9 @@ public class AmqpClient2 {
     @Autowired
     UserMapper userMapper;
     
+    @Autowired
+    DevConfigMapper devConfigMapper;
+    
     @Autowired
     SatasticDayMapper satasticDayMapper;
     
@@ -105,10 +114,13 @@ public class AmqpClient2 {
     @Autowired
     ModelMapper modelMapper;
     
+    @Autowired
+    MqTickMapper mqTickMapper;
+    
   //业务处理异步线程池,线程池参数可以根据您的业务特点调整,或者您也可以用其他异步方式处理接收到的消息。
     private final static ExecutorService executorService = new ThreadPoolExecutor(
-        Runtime.getRuntime().availableProcessors(),
-        Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS,
+        1,
+        1, 60, TimeUnit.SECONDS,
         new LinkedBlockingQueue<Runnable>(50000));
     
     public void connection() throws Exception{
@@ -206,12 +218,6 @@ public class AmqpClient2 {
      
             String hospitalCode = !items.containsKey("userId") ? "" : items.getString("userId");
             if(StringUtils.isEmpty(hospitalCode)) {
-//            	String sql = "SELECT h.code FROM bus_hospital h  inner join bus_device d on d.tenant_id = h.tenant_id where device_id=? limit 1";
-//             	try {
-//             		hospitalCode = nbJdbcTemplate.queryForObject(sql, String.class, deviceName);
-//             	}catch (Exception e) {
-//     				// TODO: handle exception
-//     			}
             	hospitalCode = remoteUtil.getHospitalCode(deviceName);
             	if(StringUtils.isEmpty(hospitalCode)) {
   				  log.info("设备没有对应医院:"+deviceName);
@@ -219,8 +225,9 @@ public class AmqpClient2 {
   			    }
             }
             String tenentId = "";
+            User owner = null;
             if(!StringUtils.isEmpty(hospitalCode)) {
-            	User owner = userMapper.selectByCode(hospitalCode);
+            	owner = userMapper.selectByCode(hospitalCode);
             	if(owner == null) {
         			log.info("不存在该医院:"+hospitalCode);
         			//return;
@@ -308,7 +315,20 @@ public class AmqpClient2 {
     			JSONObject mqttJson = JSONObject.from(record);
     			mqttJson.put("items", items);
     			log.info("mqtt publish2:"+  mqttJson.toString());
-    			mqttUtil.pub(CommonConstant.MQTT_PUBLISH_PREFIX+hospitalCode, mqttJson.toString());
+    			if(owner != null) {
+    				DevConfig config = devConfigMapper.selectByPrimaryKey(owner.getId());
+    				if(!StringUtils.isEmpty(config.getMqttTopic())) {
+    					String[] topics = config.getMqttTopic().split(",");
+    					for(String t : topics) {
+    						MqTick mt = mqTickMapper.selectOnlineByTopic(t);
+    						if(mt != null) {
+    							mqttUtil.pub(CommonConstant.MQTT_PUBLISH_PREFIX+hospitalCode+t, mqttJson.toString());
+    						}
+    					}
+    				}
+    			}else {
+    				mqttUtil.pub(CommonConstant.MQTT_PUBLISH_PREFIX+hospitalCode, mqttJson.toString());
+    			}
     		}
         } catch (Exception e) {
         	log.error("processMessage occurs error ", e);

+ 11 - 1
src/main/java/com/tuoren/forward/config/mqtt/MqttCallbackCustom.java

@@ -1,11 +1,16 @@
 package com.tuoren.forward.config.mqtt;
 
+import org.apache.commons.lang3.StringUtils;
 import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
 import org.eclipse.paho.client.mqttv3.MqttCallback;
 import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.stereotype.Component;
 
+import com.tuoren.forward.constant.CommonConstant;
+import com.tuoren.forward.service.MqTickService;
+
 import lombok.extern.slf4j.Slf4j;
 
 @Slf4j
@@ -13,7 +18,8 @@ import lombok.extern.slf4j.Slf4j;
 @ConditionalOnBean(MqttConfig.class)
 public class MqttCallbackCustom implements MqttCallback{
 
-	
+	@Autowired
+	MqTickService mqTickService;
 	 /**
      * MQTT 断开连接会执行此方法
      */
@@ -33,6 +39,10 @@ public class MqttCallbackCustom implements MqttCallback{
 	@Override
 	public void messageArrived(String topic, MqttMessage message) throws Exception {
 		// TODO Auto-generated method stub
+		String tickTopic = new String(message.getPayload());
+		if(topic.equals(CommonConstant.MQTT_TICK_TOPIC) && StringUtils.isNotEmpty(tickTopic)) {
+			mqTickService.mqTick(tickTopic);
+		}
 		
 	}
 

+ 1 - 0
src/main/java/com/tuoren/forward/constant/CommonConstant.java

@@ -17,6 +17,7 @@ public final class CommonConstant {
 	public static final Integer MQTT_QOS1 = 1;
 	public static final Integer MQTT_QOS2 = 2;
 	public static final String MQTT_PUBLISH_PREFIX = "hospital/";
+	public static final String MQTT_TICK_TOPIC = "user/tick";
 
 	
 	public static final String TOKEN_NAME = "token";

+ 61 - 0
src/main/java/com/tuoren/forward/controller/DevConfigController.java

@@ -0,0 +1,61 @@
+package com.tuoren.forward.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+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.ResponseBody;
+
+import com.tuoren.forward.entity.DevConfig;
+import com.tuoren.forward.entity.req.IdReq;
+import com.tuoren.forward.service.DevConfigService;
+import com.tuoren.forward.util.Result;
+import com.tuoren.forward.util.ResultData;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.enums.ParameterIn;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Controller
+@RequestMapping("devConfig")
+@Tag(name="开发配置接口")
+public class DevConfigController {
+	
+	@Autowired
+	DevConfigService devConfigService;
+	
+	
+	@PostMapping("detailByUserId")
+    @ResponseBody
+    @Operation(summary = "根据用户获取配置详情")
+	@Parameter(name="token",description = "token",required = true,in = ParameterIn.HEADER)
+	public ResultData<DevConfig> detailByUserId(@RequestBody IdReq req){
+		log.info("detailByUserId>>:{}",req);
+		return devConfigService.detailByUserId(req.getId());
+	}
+	
+	@PostMapping("config")
+    @ResponseBody
+    @Operation(summary = "用户开发配置")
+	@Parameter(name="token",description = "token",required = true,in = ParameterIn.HEADER)
+	public Result config(@RequestBody DevConfig req) {
+		log.info("add>>:{}",req);
+		return devConfigService.config(req);
+	}
+	
+	
+	@PostMapping("delete")
+    @ResponseBody
+    @Operation(summary = "删除开发配置")
+	@Parameter(name="token",description = "token",required = true,in = ParameterIn.HEADER)
+	public Result delete(@RequestBody IdReq req) {
+		log.info("delete>>:{}",req);
+		return devConfigService.delete(req.getId());
+	}
+	
+	
+}

+ 20 - 0
src/main/java/com/tuoren/forward/controller/DeviceController.java

@@ -12,12 +12,14 @@ import com.github.pagehelper.util.StringUtil;
 import com.tuoren.forward.annotation.HandleLog;
 import com.tuoren.forward.constant.CommonConstant;
 import com.tuoren.forward.entity.req.DeviceAddReq;
+import com.tuoren.forward.entity.req.DeviceBindReq;
 import com.tuoren.forward.entity.req.DeviceRecordSearchReq;
 import com.tuoren.forward.entity.req.DeviceSearchReq;
 import com.tuoren.forward.entity.req.IdReq;
 import com.tuoren.forward.entity.resp.CountCategoryResp;
 import com.tuoren.forward.entity.resp.CountResp;
 import com.tuoren.forward.entity.resp.DeviceResp;
+import com.tuoren.forward.entity.resp.QRCodeResp;
 import com.tuoren.forward.service.DeviceService;
 import com.tuoren.forward.util.Result;
 import com.tuoren.forward.util.ResultData;
@@ -114,4 +116,22 @@ public class DeviceController {
 		return deviceService.countOnlineDevice();
 	}
 	
+	@PostMapping("qrCode")
+    @ResponseBody
+    @Operation(summary = "生成设备信息二维码")
+	@Parameter(name="token",description = "token",required = true,in = ParameterIn.HEADER)
+	public ResultData<QRCodeResp> qrCode(@RequestBody IdReq req){
+		log.info("qrCode>>:{}",req);
+		return deviceService.qrCode(req.getId());
+	}
+	
+	@PostMapping("bind")
+    @ResponseBody
+    @Operation(summary = "设备用户绑定")
+	@Parameter(name="token",description = "token",required = true,in = ParameterIn.HEADER)
+	public Result bind(@RequestBody DeviceBindReq req){
+		log.info("bind>>:{}",req);
+		return deviceService.bind(req);
+	}
+	
 }

+ 10 - 0
src/main/java/com/tuoren/forward/controller/UserController.java

@@ -12,6 +12,7 @@ import com.tuoren.forward.constant.HandleLogChoice;
 import com.tuoren.forward.entity.User;
 import com.tuoren.forward.entity.req.IdReq;
 import com.tuoren.forward.entity.req.LoginReq;
+import com.tuoren.forward.entity.req.ReLoginReq;
 import com.tuoren.forward.entity.req.UserAddReq;
 import com.tuoren.forward.entity.req.UserEditPwdReq;
 import com.tuoren.forward.entity.req.UserEditSelfReq;
@@ -47,6 +48,15 @@ public class UserController {
 		return userService.login(req);
 	}
 	
+	@HandleLog(value=HandleLogChoice.RECORD_SUC, type = HandleLogChoice.TYPE_LOGIN)
+	@PostMapping("relogin")
+	@ResponseBody
+	@Operation(summary = "重新登录")
+	public ResultData<LoginResp> relogin(@RequestBody ReLoginReq req){
+		log.info("relogin>>:{}",req);
+		return userService.relogin(req);
+	}
+	
 	@PostMapping("register")
     @ResponseBody
     @Operation(summary = "注册用户")

+ 26 - 0
src/main/java/com/tuoren/forward/entity/DevConfig.java

@@ -0,0 +1,26 @@
+package com.tuoren.forward.entity;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(description = "开发配置")
+public class DevConfig {
+    @Schema(description = "ID")
+    private String id;
+
+    @Schema(description = "开发编码")
+    private String devCode;
+
+    @Schema(description = "开发密钥")
+    private String devSecret;
+
+    @Schema(description = "mqtt账号")
+    private String mqttAccount;
+
+    @Schema(description = "mqtt密钥")
+    private String mqttSecret;
+
+    @Schema(description = "订阅主题")
+    private String mqttTopic;
+}

+ 18 - 0
src/main/java/com/tuoren/forward/entity/MqTick.java

@@ -0,0 +1,18 @@
+package com.tuoren.forward.entity;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import java.util.Date;
+import lombok.Data;
+
+@Data
+@Schema(description = "消息队列主题心跳")
+public class MqTick {
+    @Schema(description = "ID")
+    private String id;
+
+    @Schema(description = "消息队列主题")
+    private String topic;
+
+    @Schema(description = "心跳时间")
+    private Date tickTime;
+}

+ 3 - 0
src/main/java/com/tuoren/forward/entity/User.java

@@ -45,6 +45,9 @@ public class User {
     @Schema(description = "详细地址")
     private String address;
     
+    @Schema(description = "登录令牌")
+    private String token;
+    
     @Schema(description="角色ID, 'roleId1,roleId2'")
     private List<String> roleIds;
 }

+ 21 - 0
src/main/java/com/tuoren/forward/entity/req/DeviceBindReq.java

@@ -0,0 +1,21 @@
+package com.tuoren.forward.entity.req;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(description = "设备")
+public class DeviceBindReq {
+
+	@Schema(description = "设备编码")
+    private String deviceId;
+	
+	@Schema(description = "版本")
+    private String version;
+	
+	@Schema(description = "设备摘要")
+    private String sign;
+	
+	@Schema(description = "用户编码")
+    private String userCode;
+}

+ 18 - 0
src/main/java/com/tuoren/forward/entity/req/ReLoginReq.java

@@ -0,0 +1,18 @@
+package com.tuoren.forward.entity.req;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(description  = "用户重新登录请求")
+public class ReLoginReq {
+
+	@Schema(description = "用户名")
+    private String username;
+
+    @Schema(description = "密码")
+    private String password;
+    
+    @Schema(description = "旧token")
+    private String token;
+}

+ 15 - 0
src/main/java/com/tuoren/forward/entity/resp/QRCodeResp.java

@@ -0,0 +1,15 @@
+package com.tuoren.forward.entity.resp;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+@Schema(description = "二维码信息")
+public class QRCodeResp {
+
+	@Schema(description = "二维码内容")
+	private String content;
+	
+	@Schema(description = "二维码图片")
+	private String qrCode;
+}

+ 13 - 5
src/main/java/com/tuoren/forward/init/AmqpInit.java

@@ -15,18 +15,26 @@ import lombok.extern.slf4j.Slf4j;
 @Component
 public class AmqpInit implements ApplicationRunner,Ordered{
 
-	@Autowired
+	@Autowired(required = false)
 	AmqpClient1 amqpClient1; 
 	
-	@Autowired
+	@Autowired(required = false)
 	AmqpClient2 amqpClient2; 
 	
 	@Override
 	public void run(ApplicationArguments args) throws Exception {
 		// TODO Auto-generated method stub
-		log.info("Amqp初始化>>>");
-		amqpClient1.connection();
-		amqpClient2.connection();
+		
+		if(amqpClient1 != null) {
+			log.info("Amqp1初始化>>>");
+			amqpClient1.connection();
+		}
+		if(amqpClient2 != null) {
+			log.info("Amqp2初始化>>>");
+			amqpClient2.connection();
+		}
+//		amqpClient1.connection();
+//		amqpClient2.connection();
 	}
 
 	@Override

+ 2 - 0
src/main/java/com/tuoren/forward/init/MqttInit.java

@@ -10,6 +10,7 @@ import org.springframework.stereotype.Component;
 
 import com.tuoren.forward.config.mqtt.MqttCallbackCustom;
 import com.tuoren.forward.config.mqtt.MqttConfig;
+import com.tuoren.forward.constant.CommonConstant;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -35,6 +36,7 @@ public class MqttInit implements ApplicationRunner,Ordered{
 	public void run(ApplicationArguments args) throws Exception {
 		// TODO Auto-generated method stub
 		log.info("mqtt初始化>>>>");
+		mqttClient.subscribe(CommonConstant.MQTT_TICK_TOPIC);
 		mqttClient.setCallback(callback);
 	}
 

+ 19 - 0
src/main/java/com/tuoren/forward/mapper/DevConfigMapper.java

@@ -0,0 +1,19 @@
+package com.tuoren.forward.mapper;
+
+import com.tuoren.forward.entity.DevConfig;
+
+public interface DevConfigMapper {
+    int deleteByPrimaryKey(String id);
+
+    int insert(DevConfig row);
+
+    int insertSelective(DevConfig row);
+
+    DevConfig selectByPrimaryKey(String id);
+    
+    DevConfig selectByDevCode(String devCode);
+    
+    int updateByPrimaryKeySelective(DevConfig row);
+
+    int updateByPrimaryKey(DevConfig row);
+}

+ 21 - 0
src/main/java/com/tuoren/forward/mapper/MqTickMapper.java

@@ -0,0 +1,21 @@
+package com.tuoren.forward.mapper;
+
+import com.tuoren.forward.entity.MqTick;
+
+public interface MqTickMapper {
+    int deleteByPrimaryKey(String id);
+
+    int insert(MqTick row);
+
+    int insertSelective(MqTick row);
+
+    MqTick selectByPrimaryKey(String id);
+    
+    MqTick selectByTopic(String topic);
+    
+    MqTick selectOnlineByTopic(String topic); //在线topic
+
+    int updateByPrimaryKeySelective(MqTick row);
+
+    int updateByPrimaryKey(MqTick row);
+}

+ 2 - 0
src/main/java/com/tuoren/forward/mapper/UserMapper.java

@@ -24,6 +24,8 @@ public interface UserMapper {
     
     User selectByCode(String code);
     
+    User selectByToken(String token);
+    
     List<User> select(UserDto row);
 
     int updateByPrimaryKeySelective(User row);

+ 69 - 0
src/main/java/com/tuoren/forward/service/DevConfigService.java

@@ -0,0 +1,69 @@
+package com.tuoren.forward.service;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.tuoren.forward.constant.CommonConstant;
+import com.tuoren.forward.entity.DevConfig;
+import com.tuoren.forward.mapper.DevConfigMapper;
+import com.tuoren.forward.util.Result;
+import com.tuoren.forward.util.ResultData;
+import com.tuoren.forward.util.UUIDUtil;
+
+@Service
+public class DevConfigService {
+
+	@Autowired
+	DevConfigMapper devConfigMapper;
+	
+	/**
+	 * @title 获取用户配置
+	 * @param userId
+	 * @return
+	 */
+	public ResultData<DevConfig> detailByUserId(String id){
+		DevConfig config = devConfigMapper.selectByPrimaryKey(id);
+		return ResultData.success(config);
+	}
+	
+	
+	/**
+	 * @title 用户开发配置
+	 * @param req
+	 * @return
+	 */
+	public Result config(DevConfig req) {
+		if(StringUtils.isAnyEmpty(req.getId(),req.getDevCode())) {
+			return Result.fail(CommonConstant.LACK_PARAM);
+		}
+		DevConfig record = devConfigMapper.selectByPrimaryKey(req.getId());
+		if(record == null) {
+			DevConfig exist = devConfigMapper.selectByDevCode(req.getDevCode());
+			if(exist != null) {
+				return Result.fail("开发编码已存在");
+			}
+			devConfigMapper.insert(req);
+		}else {
+			DevConfig exist = devConfigMapper.selectByDevCode(req.getDevCode());
+			if(exist != null && !exist.getId().equals(req.getId())) {
+				return Result.fail("开发编码冲突");
+			}
+			devConfigMapper.updateByPrimaryKeySelective(req);
+		}
+		return Result.success();
+	}
+	
+	/**
+	 * @title 删除配置
+	 * @return
+	 */
+	public Result delete(String id) {
+		if(StringUtils.isEmpty(id)) {
+			return Result.fail(CommonConstant.LACK_PARAM);
+		}
+		devConfigMapper.deleteByPrimaryKey(id);
+		return Result.success();
+	}
+	
+}

+ 52 - 0
src/main/java/com/tuoren/forward/service/DeviceService.java

@@ -7,6 +7,7 @@ import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.mongodb.core.MongoTemplate;
 import org.springframework.data.mongodb.core.query.Criteria;
@@ -21,27 +22,41 @@ import com.tuoren.forward.entity.Device;
 import com.tuoren.forward.entity.User;
 import com.tuoren.forward.entity.dto.DeviceDto;
 import com.tuoren.forward.entity.req.DeviceAddReq;
+import com.tuoren.forward.entity.req.DeviceBindReq;
 import com.tuoren.forward.entity.req.DeviceRecordSearchReq;
 import com.tuoren.forward.entity.req.DeviceSearchReq;
 import com.tuoren.forward.entity.resp.CountCategoryResp;
 import com.tuoren.forward.entity.resp.CountResp;
 import com.tuoren.forward.entity.resp.DeviceResp;
+import com.tuoren.forward.entity.resp.QRCodeResp;
 import com.tuoren.forward.mapper.DeviceMapper;
+import com.tuoren.forward.mapper.UserMapper;
 import com.tuoren.forward.util.AccessTokenUtil;
+import com.tuoren.forward.util.MD5Util;
 import com.tuoren.forward.util.Result;
 import com.tuoren.forward.util.ResultData;
 import com.tuoren.forward.util.ResultPage;
 import com.tuoren.forward.util.UUIDUtil;
 
+import cn.hutool.core.codec.Base64;
+import cn.hutool.extra.qrcode.QrCodeUtil;
+import cn.hutool.extra.qrcode.QrConfig;
+
 @Service
 public class DeviceService {
 
 	@Autowired
 	DeviceMapper deviceMapper;
 	
+	@Autowired
+	UserMapper userMapper;
+	
 	@Autowired
     MongoTemplate mongoTemplate;
 	
+	@Value("${remote.h5Address}")
+	private String h5Address;
+	
 	/**
 	 * @title 查询设备
 	 * @param req
@@ -165,4 +180,41 @@ public class DeviceService {
 		CountResp resp = deviceMapper.countOnlineDevice();
 		return ResultData.success(resp);
 	}
+	
+	/**
+	 * @title 生成二维码
+	 * @return
+	 */
+	public ResultData<QRCodeResp> qrCode(String deviceId){
+		String version = "1.0";
+		String signText = deviceId+"&"+"1.0"+"&"+"user";
+		String md5Hex = MD5Util.encode32(signText);
+		QRCodeResp resp = new QRCodeResp();
+		String content = h5Address+"/device/ascend/"+deviceId+"?version="+version+"&sign="+md5Hex;
+		resp.setContent(content);		
+		QrConfig config = new QrConfig(300, 300);
+		byte[] pngData = QrCodeUtil.generatePng(content, config);
+		String base64String = "data:image/png;base64,"+Base64.encode(pngData);
+		resp.setQrCode(base64String);
+		return ResultData.success(resp);
+	}
+	
+	/**
+	 * @title 绑定医院
+	 * @return
+	 */
+	public Result bind(DeviceBindReq req){
+		if(StringUtils.isAnyBlank(req.getDeviceId(),req.getUserCode())){
+			return Result.fail(CommonConstant.LACK_PARAM);
+		}
+		Device dev = deviceMapper.selectByMac(req.getDeviceId());
+		if(dev != null) {
+			User user = userMapper.selectByCode(req.getUserCode());
+			if(user != null) {
+				dev.setTenantId(user.getId());
+			}
+			deviceMapper.updateByPrimaryKeySelective(dev);
+		}
+		return Result.success();
+	}
 }

+ 42 - 0
src/main/java/com/tuoren/forward/service/MqTickService.java

@@ -0,0 +1,42 @@
+package com.tuoren.forward.service;
+
+import java.util.Date;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.tuoren.forward.entity.MqTick;
+import com.tuoren.forward.mapper.MqTickMapper;
+import com.tuoren.forward.util.Result;
+import com.tuoren.forward.util.UUIDUtil;
+
+@Service
+public class MqTickService {
+	
+	@Autowired
+	MqTickMapper mqTickMapper;
+	
+	
+	/**
+	 * @title  消息队列心跳
+	 * @param topic
+	 * @return
+	 */
+	public Result mqTick(String topic) {
+		Date now = new Date();
+		MqTick mt= mqTickMapper.selectByTopic(topic);
+		if(mt == null) {
+			MqTick record = new MqTick();
+			record.setId(UUIDUtil.get32UUID());
+			record.setTopic(topic);
+			record.setTickTime(now);
+			mqTickMapper.insert(record);
+			return Result.success();
+		}
+		mt.setTopic(topic);
+		mt.setTickTime(now);
+		mqTickMapper.updateByPrimaryKeySelective(mt);
+		return Result.success();
+	}
+
+}

+ 54 - 0
src/main/java/com/tuoren/forward/service/UserService.java

@@ -18,6 +18,7 @@ import com.tuoren.forward.entity.User;
 import com.tuoren.forward.entity.UserRole;
 import com.tuoren.forward.entity.dto.UserDto;
 import com.tuoren.forward.entity.req.LoginReq;
+import com.tuoren.forward.entity.req.ReLoginReq;
 import com.tuoren.forward.entity.req.UserAddOpenReq;
 import com.tuoren.forward.entity.req.UserAddReq;
 import com.tuoren.forward.entity.req.UserEditPwdReq;
@@ -95,6 +96,59 @@ public class UserService {
 		User user = new User();
 		user.setId(loginUser.getId());
 		user.setLasttime(date);
+		user.setToken(token);
+		userMapper.updateByPrimaryKeySelective(user);
+		
+		if(logMapper.existLoginTodayByUseid(user.getId()) == null) {
+			String sataType = "login";
+			SatasticDay existSata = satasticDayMapper.selectSataTodayByType(sataType);
+    		if(existSata == null) {
+    			SatasticDay record = new SatasticDay();
+    			record.setId(UUIDUtil.get32UUID());
+    			record.setType(sataType);
+    			record.setNum(1);
+    			record.setCreatedate(date);
+    			satasticDayMapper.insert(record);
+    		}else {
+    			existSata.setNum(existSata.getNum()+1);
+    			satasticDayMapper.updateByPrimaryKey(existSata);
+    		}
+		}
+		
+		//返回登录结果
+		LoginResp resp = new LoginResp();
+		BeanUtils.copyProperties(loginUser, resp);
+		resp.setRoleIds(roleIds);
+		resp.setToken(token);		
+		return ResultData.success(resp,"登录成功");
+	}
+	
+	/**
+	 * @title 重新登录
+	 * @param req
+	 * @return ResultData<LoginResp>
+	 */
+	public ResultData<LoginResp> relogin(ReLoginReq req) {
+		// TODO Auto-generated method stub
+		User loginUser = userMapper.selectByUsername(req.getUsername());
+		if(loginUser == null || !MD5Util.encode32(req.getPassword()).equals(loginUser.getPassword())) {
+			return ResultData.failNull("用户名或密码错误");
+		}
+		if(!loginUser.getToken().equals(req.getToken())) {
+			return ResultData.failNull("token无效");
+		}
+		Date date= new Date();
+		List<String> roleIds = roleMapper.selectIdByUserId(loginUser.getId());
+		loginUser.setRoleIds(roleIds);
+		StpUtil.login(loginUser.getId());
+		StpUtil.getSession().set("user", loginUser);
+		String token = StpUtil.getTokenValue();
+		//redisTemplate.opsForValue().set(token, loginUser,CommonConstant.LOGIN_EXPIRE,TimeUnit.SECONDS);
+		//跟新登录时间
+		User user = new User();
+		user.setId(loginUser.getId());
+		user.setLasttime(date);
+		user.setToken(token);
 		userMapper.updateByPrimaryKeySelective(user);
 		
 		if(logMapper.existLoginTodayByUseid(user.getId()) == null) {

+ 98 - 3
src/main/resources/application.yml

@@ -2,7 +2,7 @@ server:
   port: 8585
 spring:
   profiles:
-      active: dev
+      active: test
   application:
     name: forward
   jackson:
@@ -58,7 +58,7 @@ spring:
     clean-disabled: true
     locations: classpath:db/migration
     #迁移时是否校验,默认为true.
-    validate-on-migrate: true
+    validate-on-migrate: false
     # 如果数据库不是空表,需要设置成 true,否则启动报错
     baseline-on-migrate: true
   redis:
@@ -94,6 +94,7 @@ mqtt:
   
 #阿里云配置
 aliyun1: 
+  enable: true
   accessKey: LTAI5tRaK95AqvWiQ9LspZ3q
   accessSecret: wZUpYGeztNcV4tGbBLfK2OvxnZzZF3
   consumerGroupId: 0na0olXpWEmWgMucxIH1000100
@@ -102,6 +103,7 @@ aliyun1:
   amqpHost: iot-06z00hi2guq5qi3.amqp.iothub.aliyuncs.com
   
 aliyun2: 
+  enable: true
   accessKey: LTAI4G7FA9ytMc76oNkJ45YJ
   accessSecret: R7hOvMfiHb0PYroDqUDXAYgB9htQss
   consumerGroupId: AQ2Lk4saOGHYWBzJa39c000100
@@ -120,6 +122,96 @@ handleLog:
 #pca获取医院编码地址
 remote:
   hospitalCodeAddress: https://pca.tuoren.com:9090/api/bus/device/info/hospitalCode
+  h5Address: https://iot.tuoren.com/wap
+
+#测试环境
+---
+spring:
+  profiles: test
+  datasource:
+    primary:
+      url: jdbc:mysql://192.168.100.249:3306/forward?useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
+      username: root
+      password: 123456
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      # 连接池配置
+      hikari:
+        connection-timeout: 30000
+        maximum-pool-size: 10
+        idle-timeout: 600000
+        pool-name: HikariCP
+  flyway:
+    #是否启用
+    enabled: false
+    # flyway 的 clean 命令会删除指定 schema 下的所有 table, 生产务必禁掉
+    clean-disabled: true
+    locations: classpath:db/migration
+    #迁移时是否校验,默认为true.
+    validate-on-migrate: false
+    # 如果数据库不是空表,需要设置成 true,否则启动报错
+    baseline-on-migrate: true
+  redis:
+    database: 1
+    host: 192.168.100.249
+    port: 6379
+    timeout: 5000
+    lettuce: 
+      pool:
+        # 连接池最大连接数
+        max-active: 200
+        # 连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+        # 连接池中的最大空闲连接
+        max-idle: 10
+         # 连接池中的最小空闲连接
+        min-idle: 0
+  data:
+    mongodb:
+      host: 192.168.100.249
+      port: 27017
+      database: forward
+      username: forward
+      password: 1qaz!QAZ
+
+mqtt:
+  hostUrl: tcp://192.168.100.249:1883		# 你自己服务器的地址和端口,这个需要改 
+  clientId: fe80aba1dfd66b3576ce							# 这个改不改随意,但不同的客户端肯定不能一样
+  username: server							
+  password: 1qaz!QAZ
+  timeout: 100							   
+  keepalive: 100
+  
+#阿里云配置
+aliyun1: 
+  enable: true
+  accessKey: LTAI4G7FA9ytMc76oNkJ45YJ
+  accessSecret: R7hOvMfiHb0PYroDqUDXAYgB9htQss
+  consumerGroupId: Zlpp6svZNbJN4slY0rwJ000100
+  iotInstanceId: iot-060a0bgd
+  clientId: fe80aba1dfd66b3576ce
+  amqpHost: iot-060a0bgd.amqp.iothub.aliyuncs.com
+  
+aliyun2: 
+  enable: false
+  accessKey: LTAI4G7FA9ytMc76oNkJ45YJ
+  accessSecret: R7hOvMfiHb0PYroDqUDXAYgB9htQss
+  consumerGroupId: AQ2Lk4saOGHYWBzJa39c000100
+  iotInstanceId: iot-060a0bgd
+  clientId: fe80aba1dfd66b3576ce
+  amqpHost: iot-060a0bgd.amqp.iothub.aliyuncs.com
+  
+#日志
+logging:
+  config: classpath:log/logback.xml
+  path: D://logs/forward
+  level: 
+    com.tuoren.forward.mapper: debug
+handleLog:
+  enable: true   #是否记录请求操作
+#pca获取医院编码地址
+remote:
+  hospitalCodeAddress: https://pca.tuoren.com:9090/api/bus/device/info/hospitalCode
+  h5Address: https://iot.tuoren.com/wap
 
   
 #生产环境
@@ -140,7 +232,7 @@ spring:
         pool-name: HikariCP-primary
   flyway:
     #是否启用
-    enabled: false
+    enabled: true
     url: jdbc:mysql://192.168.100.115:3306/forward?useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
     user: root
     password: forward.data#@
@@ -184,6 +276,7 @@ mqtt:
   
 #阿里云配置
 aliyun1: 
+  enable: true
   accessKey: LTAI4G7FA9ytMc76oNkJ45YJ
   accessSecret: R7hOvMfiHb0PYroDqUDXAYgB9htQss
   consumerGroupId: u3mShumaQA0Yyk3gfQM5000100
@@ -192,6 +285,7 @@ aliyun1:
   amqpHost: iot-060a0bgd.amqp.iothub.aliyuncs.com
   
 aliyun2: 
+  enable: true
   accessKey: LTAI4G7FA9ytMc76oNkJ45YJ
   accessSecret: R7hOvMfiHb0PYroDqUDXAYgB9htQss
   consumerGroupId: RJeEjZ6TroTZ5TDrdRYP000100
@@ -211,3 +305,4 @@ handleLog:
 #pca获取医院编码地址
 remote:
   hospitalCodeAddress: https://pca.tuoren.com:9090/api/bus/device/info/hospitalCode
+  h5Address: https://iot.tuoren.com/wap

+ 22 - 0
src/main/resources/db/migration/V1.0.1__dev_config.sql

@@ -0,0 +1,22 @@
+CREATE TABLE `dev_config` (
+  `id` VARCHAR(40) NOT NULL COMMENT '人员ID',
+  `dev_code` VARCHAR(45) NULL COMMENT '开发编码',
+  `dev_secret` VARCHAR(45) NULL COMMENT '开发密钥',
+  `mqtt_account` VARCHAR(45) NULL COMMENT 'mqtt账号',
+  `mqtt_secret` VARCHAR(45) NULL COMMENT 'mqtt密钥',
+  `mqtt_topic` VARCHAR(200) NULL COMMENT '订阅主题',
+  PRIMARY KEY (`id`))
+COMMENT = '开发配置';
+
+
+ALTER TABLE `forward`.`user` 
+ADD COLUMN `token` VARCHAR(45) NULL COMMENT '登录令牌' AFTER `code`;
+
+
+CREATE TABLE `mq_tick` (
+  `id` varchar(45) NOT NULL COMMENT 'ID',
+  `topic` varchar(200) DEFAULT NULL COMMENT '消息队列主题',
+  `tick_time` datetime DEFAULT NULL COMMENT '心跳时间',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `topic_UNIQUE` (`topic`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='消息队列主题心跳'

+ 0 - 13
src/main/resources/db/migration/V1.0.1__satasitc_init.sql

@@ -1,13 +0,0 @@
-CREATE TABLE `station_location` (
-  `id` varchar(45) NOT NULL,
-  `mnc` char(3) DEFAULT NULL COMMENT '移动网络代码,00:移动 01:联通 11:电信',
-  `lac` varchar(10) DEFAULT NULL COMMENT '位置区码',
-  `ci` varchar(10) DEFAULT NULL COMMENT '小区识别码',
-  `lng` varchar(45) DEFAULT NULL COMMENT '经度',
-  `lat` varchar(45) DEFAULT NULL COMMENT '维度',
-  `address` varchar(200) DEFAULT NULL COMMENT '地址',
-  `radius` varchar(10) DEFAULT NULL COMMENT '误差范围',
-  `createtime` datetime DEFAULT NULL COMMENT '创建时间',
-  `modifytime` datetime DEFAULT NULL COMMENT '修改时间',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='基站位置'

+ 0 - 30
src/main/resources/db/migration/V1.0.2__modle_update.sql

@@ -1,30 +0,0 @@
-update device set data = null;
-
-ALTER TABLE `forward`.`model` 
-ADD COLUMN `createtime` DATETIME NULL COMMENT '创建时间' AFTER `tenant_id`,
-ADD COLUMN `modifytime` DATETIME NULL COMMENT '修改时间' AFTER `createtime`;
-
-update model set createtime='2024-04-09 13:47:58';
-
-ALTER TABLE `forward`.`permission` 
-ADD COLUMN `name` VARCHAR(45) NULL COMMENT '别名' AFTER `icon`;
-
-UPDATE `forward`.`role` SET `id` = 'developer', `name` = '开发人员', `description` = '开发人员' WHERE (`id` = 'worker');
-
-LOCK TABLES `permission` WRITE;
-/*!40000 ALTER TABLE `permission` DISABLE KEYS */;
-INSERT INTO `permission` VALUES (4,0,'home','01',NULL,'管理员首页',0,NULL,'系统首页'),(5,0,'product','01','/product','产品管理',10,NULL,'产品管理'),(6,5,'product::add','03','/product/add','添加产品',20,NULL,'添加产品'),(15,0,'device','01','/device','设备管理相关功能',1,NULL,'设备管理');
-/*!40000 ALTER TABLE `permission` ENABLE KEYS */;
-UNLOCK TABLES;
-
---
--- Dumping data for table `role_permission`
---
-
-LOCK TABLES `role_permission` WRITE;
-/*!40000 ALTER TABLE `role_permission` DISABLE KEYS */;
-INSERT INTO `role_permission` VALUES ('developer',4),('developer',5),('developer',15),('manager',4),('manager',5),('manager',6),('manager',15),('user',4),('user',5),('user',15);
-/*!40000 ALTER TABLE `role_permission` ENABLE KEYS */;
-UNLOCK TABLES;
-
-

+ 1 - 1
src/main/resources/generatorConfig.xml

@@ -34,6 +34,6 @@
             <property name="enableSubPackages" value="true"/>
         </javaClientGenerator>
         <!--生成对应表及类名-->
-        <table tableName="station_location" domainObjectName="StationLocation" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
+        <table tableName="mq_tick" domainObjectName="MqTick" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
     </context>
 </generatorConfiguration>

+ 115 - 0
src/main/resources/mapper/DevConfigMapper.xml

@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.tuoren.forward.mapper.DevConfigMapper">
+  <resultMap id="BaseResultMap" type="com.tuoren.forward.entity.DevConfig">
+    <id column="id" jdbcType="VARCHAR" property="id" />
+    <result column="dev_code" jdbcType="VARCHAR" property="devCode" />
+    <result column="dev_secret" jdbcType="VARCHAR" property="devSecret" />
+    <result column="mqtt_account" jdbcType="VARCHAR" property="mqttAccount" />
+    <result column="mqtt_secret" jdbcType="VARCHAR" property="mqttSecret" />
+    <result column="mqtt_topic" jdbcType="VARCHAR" property="mqttTopic" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    id, dev_code, dev_secret, mqtt_account, mqtt_secret, mqtt_topic
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from dev_config
+    where id = #{id,jdbcType=VARCHAR}
+  </select>
+  <select id="selectByDevCode" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from dev_config
+    where dev_code = #{devCode,jdbcType=VARCHAR} limit 1
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from dev_config
+    where id = #{id,jdbcType=VARCHAR}
+  </delete>
+  <insert id="insert" parameterType="com.tuoren.forward.entity.DevConfig">
+    insert into dev_config (id, dev_code, 
+      dev_secret, mqtt_account, mqtt_secret, 
+      mqtt_topic)
+    values (#{id,jdbcType=VARCHAR}, #{devCode,jdbcType=VARCHAR}, 
+      #{devSecret,jdbcType=VARCHAR}, #{mqttAccount,jdbcType=VARCHAR}, #{mqttSecret,jdbcType=VARCHAR}, 
+      #{mqttTopic,jdbcType=VARCHAR})
+  </insert>
+  <insert id="insertSelective" parameterType="com.tuoren.forward.entity.DevConfig">
+    insert into dev_config
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="devCode != null">
+        dev_code,
+      </if>
+      <if test="devSecret != null">
+        dev_secret,
+      </if>
+      <if test="mqttAccount != null">
+        mqtt_account,
+      </if>
+      <if test="mqttSecret != null">
+        mqtt_secret,
+      </if>
+      <if test="mqttTopic != null">
+        mqtt_topic,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=VARCHAR},
+      </if>
+      <if test="userId != null">
+        #{userId,jdbcType=VARCHAR},
+      </if>
+      <if test="devCode != null">
+        #{devCode,jdbcType=VARCHAR},
+      </if>
+      <if test="devSecret != null">
+        #{devSecret,jdbcType=VARCHAR},
+      </if>
+      <if test="mqttAccount != null">
+        #{mqttAccount,jdbcType=VARCHAR},
+      </if>
+      <if test="mqttSecret != null">
+        #{mqttSecret,jdbcType=VARCHAR},
+      </if>
+      <if test="mqttTopic != null">
+        #{mqttTopic,jdbcType=VARCHAR},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.tuoren.forward.entity.DevConfig">
+    update dev_config
+    <set>
+      <if test="devCode != null">
+        dev_code = #{devCode,jdbcType=VARCHAR},
+      </if>
+      <if test="devSecret != null">
+        dev_secret = #{devSecret,jdbcType=VARCHAR},
+      </if>
+      <if test="mqttAccount != null">
+        mqtt_account = #{mqttAccount,jdbcType=VARCHAR},
+      </if>
+      <if test="mqttSecret != null">
+        mqtt_secret = #{mqttSecret,jdbcType=VARCHAR},
+      </if>
+      <if test="mqttTopic != null">
+        mqtt_topic = #{mqttTopic,jdbcType=VARCHAR},
+      </if>
+    </set>
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.tuoren.forward.entity.DevConfig">
+    update dev_config
+    set dev_code = #{devCode,jdbcType=VARCHAR},
+      dev_secret = #{devSecret,jdbcType=VARCHAR},
+      mqtt_account = #{mqttAccount,jdbcType=VARCHAR},
+      mqtt_secret = #{mqttSecret,jdbcType=VARCHAR},
+      mqtt_topic = #{mqttTopic,jdbcType=VARCHAR}
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+</mapper>

+ 84 - 0
src/main/resources/mapper/MqTickMapper.xml

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.tuoren.forward.mapper.MqTickMapper">
+  <resultMap id="BaseResultMap" type="com.tuoren.forward.entity.MqTick">
+    <id column="id" jdbcType="VARCHAR" property="id" />
+    <result column="topic" jdbcType="VARCHAR" property="topic" />
+    <result column="tick_time" jdbcType="TIMESTAMP" property="tickTime" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    id, topic, tick_time
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from mq_tick
+    where id = #{id,jdbcType=VARCHAR}
+  </select>
+  <select id="selectByTopic" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from mq_tick
+    where topic = #{topic,jdbcType=VARCHAR}
+  </select>
+  <select id="selectOnlineByTopic" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from mq_tick
+    where topic = #{topic,jdbcType=VARCHAR}
+    and TIMESTAMPDIFF(MINUTE, tick_time,now()) &gt; 20
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from mq_tick
+    where id = #{id,jdbcType=VARCHAR}
+  </delete>
+  <insert id="insert" parameterType="com.tuoren.forward.entity.MqTick">
+    insert into mq_tick (id, topic, tick_time
+      )
+    values (#{id,jdbcType=VARCHAR}, #{topic,jdbcType=VARCHAR}, #{tickTime,jdbcType=TIMESTAMP}
+      )
+  </insert>
+  <insert id="insertSelective" parameterType="com.tuoren.forward.entity.MqTick">
+    insert into mq_tick
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="topic != null">
+        topic,
+      </if>
+      <if test="tickTime != null">
+        tick_time,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=VARCHAR},
+      </if>
+      <if test="topic != null">
+        #{topic,jdbcType=VARCHAR},
+      </if>
+      <if test="tickTime != null">
+        #{tickTime,jdbcType=TIMESTAMP},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.tuoren.forward.entity.MqTick">
+    update mq_tick
+    <set>
+      <if test="topic != null">
+        topic = #{topic,jdbcType=VARCHAR},
+      </if>
+      <if test="tickTime != null">
+        tick_time = #{tickTime,jdbcType=TIMESTAMP},
+      </if>
+    </set>
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.tuoren.forward.entity.MqTick">
+    update mq_tick
+    set topic = #{topic,jdbcType=VARCHAR},
+      tick_time = #{tickTime,jdbcType=TIMESTAMP}
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+</mapper>

+ 13 - 2
src/main/resources/mapper/UserMapper.xml

@@ -16,7 +16,7 @@
     <result column="address" jdbcType="VARCHAR" property="address" />
   </resultMap>
   <sql id="Base_Column_List">
-    id, username, password, mobile, email, salt, enabled, createtime, lasttime,code,region_code,address
+    id, username, password, mobile, email, salt, enabled, createtime, lasttime,code,region_code,address,token
   </sql>
   <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
     select 
@@ -52,6 +52,13 @@
 		from user
 		where code = #{code,jdbcType=VARCHAR} limit 1
 	</select>
+	<select id="selectByToken"
+		parameterType="java.lang.String" resultMap="BaseResultMap">
+		select
+		<include refid="Base_Column_List" />
+		from user
+		where token = #{token,jdbcType=VARCHAR} limit 1
+	</select>
 	<select id="select"
 		parameterType="UserDto" resultMap="BaseResultMap">
 		select
@@ -200,6 +207,9 @@
       <if test="address != null">
         address = #{address,jdbcType=VARCHAR},
       </if>
+      <if test="token != null">
+        token = #{token,jdbcType=VARCHAR},
+      </if>
     </set>
     where id = #{id,jdbcType=VARCHAR}
   </update>
@@ -215,7 +225,8 @@
       lasttime = #{lasttime,jdbcType=TIMESTAMP},
       code = #{code,jdbcType=VARCHAR},
       region_code = #{regionCode,jdbcType=VARCHAR},
-      address = #{address,jdbcType=VARCHAR}
+      address = #{address,jdbcType=VARCHAR},
+      token = #{token,jdbcType=VARCHAR}
     where id = #{id,jdbcType=VARCHAR}
   </update>
 </mapper>