From 69d00365e9f099b26c4fc7a298cabeb131956d8a Mon Sep 17 00:00:00 2001
From: jinpengyong <jpy123456>
Date: Wed, 23 Jun 2021 14:35:05 +0800
Subject: [PATCH] 定时任务,kafka

---
 screen-job/src/main/java/com/moral/api/service/DeviceService.java                       |   20 
 screen-job/src/main/java/com/moral/api/entity/HistoryDaily.java                         |   36 +
 screen-job/src/main/java/com/moral/api/service/HistoryDailyService.java                 |   21 
 screen-job/src/main/java/com/moral/api/mapper/HistoryMinutelyMapper.java                |   11 
 screen-manage/src/main/java/com/moral/api/controller/DeviceController.java              |    2 
 screen-api/src/main/resources/application-dev.yml                                       |    9 
 screen-job/src/main/java/com/moral/api/mapper/CityAqiConfigMapper.java                  |   16 
 screen-job/src/main/java/com/moral/api/service/impl/HistoryDailyServiceImpl.java        |   33 
 screen-job/src/main/java/com/moral/api/mapper/HistoryDailyMapper.java                   |   21 
 screen-job/src/main/java/com/moral/api/entity/HistoryAqi.java                           |   45 +
 screen-api/src/main/resources/mapper/GroupMapper.xml                                    |    2 
 screen-common/src/main/java/com/moral/util/DateUtils.java                               |   42 
 screen-job/src/main/java/com/moral/api/service/HistoryMinutelyService.java              |   12 
 screen-manage/src/main/java/com/moral/api/service/DeviceService.java                    |    6 
 screen-job/src/main/resources/mapper/HistoryFiveMinutelyMapper.xml                      |   25 
 screen-manage/src/main/java/com/moral/api/service/impl/HistoryHourlyServiceImpl.java    |   63 +
 screen-job/src/main/java/com/moral/api/config/redis/RedisConfig.java                    |   67 +
 screen-manage/src/main/resources/application-dev.yml                                    |    3 
 screen-job/src/main/java/com/moral/api/service/HistoryFiveMinutelyService.java          |    9 
 screen-manage/src/main/resources/mapper/HistoryHourlyMapper.xml                         |   17 
 screen-manage/src/main/resources/mapper/DeviceMapper.xml                                |    8 
 screen-job/src/main/java/com/moral/api/mapper/DeviceMapper.java                         |   16 
 screen-job/src/main/java/com/moral/api/task/CreateTableTask.java                        |   52 +
 screen-job/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java     |   27 
 screen-job/src/main/java/com/moral/api/service/impl/HistoryFiveMinutelyServiceImpl.java |   64 +
 screen-manage/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java  |   34 
 screen-manage/src/main/java/com/moral/api/util/AdjustDataUtils.java                     |   97 ++
 screen-job/src/main/java/com/moral/api/entity/CityAqiConfig.java                        |   50 +
 screen-job/src/main/resources/logback-spring.xml                                        |   56 +
 screen-manage/src/main/java/com/moral/api/kafka/consumer/KafkaConsumer.java             |  127 +++
 screen-job/src/main/java/com/moral/api/service/impl/CityAqiConfigServiceImpl.java       |   31 
 screen-manage/src/main/java/com/moral/api/entity/HistoryHourly.java                     |   51 +
 screen-job/src/main/java/com/moral/api/config/xxljob/XxlJobConfig.java                  |   68 ++
 screen-job/src/main/java/com/moral/api/task/HistoryTableInsertTask.java                 |   74 ++
 screen-common/src/main/java/com/moral/constant/Constants.java                           |    5 
 screen-job/src/main/java/com/moral/api/task/JudgeOffLineDeviceTask.java                 |   28 
 screen-api/src/main/resources/mapper/GroupMenuMapper.xml                                |   22 
 screen-job/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java              |   69 ++
 screen-common/src/main/java/com/moral/constant/RedisConstants.java                      |   11 
 screen-api/src/main/resources/mapper/MenuMapper.xml                                     |   17 
 screen-job/src/main/java/com/moral/api/service/CityAqiConfigService.java                |   20 
 screen-job/src/main/resources/mapper/DeviceMapper.xml                                   |   29 
 screen-common/src/main/java/com/moral/constant/KafkaConstants.java                      |   16 
 screen-job/src/main/resources/mapper/CityAqiConfigMapper.xml                            |   13 
 screen-manage/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java           |  149 +++-
 screen-manage/src/main/java/com/moral/api/config/kafka/KafkaConsumerConfig.java         |    9 
 screen-job/src/main/java/com/moral/api/service/impl/HistoryAqiServiceImpl.java          |   77 ++
 screen-job/src/main/resources/mapper/HistoryDailyMapper.xml                             |   19 
 screen-job/src/main/java/com/moral/api/service/HistoryAqiService.java                   |   10 
 screen-job/src/main/resources/mapper/HistoryAqiMapper.xml                               |   12 
 screen-job/src/main/java/com/moral/api/mapper/HistoryAqiMapper.java                     |   17 
 /dev/null                                                                               |    4 
 screen-job/src/main/java/com/moral/api/mapper/HistoryFiveMinutelyMapper.java            |   15 
 screen-manage/src/main/java/com/moral/api/controller/TestController.java                |   25 
 screen-job/src/main/java/com/moral/api/task/HistoryAqiInsertTask.java                   |   27 
 screen-manage/src/main/java/com/moral/api/service/HistoryHourlyService.java             |   20 
 screen-job/src/main/resources/application-dev.yml                                       |    1 
 screen-manage/src/main/java/com/moral/api/service/HistoryMinutelyService.java           |    2 
 screen-manage/src/main/java/com/moral/api/mapper/HistoryHourlyMapper.java               |   20 
 screen-job/src/main/java/com/moral/api/entity/Device.java                               |  132 +++
 screen-job/src/main/resources/mapper/HistoryMinutelyMapper.xml                          |   50 +
 61 files changed, 1,890 insertions(+), 144 deletions(-)

diff --git a/screen-api/src/main/resources/application-dev.yml b/screen-api/src/main/resources/application-dev.yml
index 3ec8fff..03d4b28 100644
--- a/screen-api/src/main/resources/application-dev.yml
+++ b/screen-api/src/main/resources/application-dev.yml
@@ -13,6 +13,8 @@
 spring:
   profiles:
     active: dev
+    include:
+      moduleFormColumn
   application:
     name: screen-manage
   redis:
@@ -90,14 +92,11 @@
     enable:
       auto:
         commit: false
-    group:
-      id: test
     servers: 192.168.0.191:9092
     session:
       timeout: 6000
-    topic: test_topic
     zookeeper:
-      connect: 192.168.0.16:2181,192.168.0.17:2181,192.168.0.18:2181
+      connect: 172.16.44.65:2181,172.16.44.67:2181,172.16.44.66:2181
   producer:
     batch:
       size: 4096
@@ -105,7 +104,7 @@
       memory: 40960
     linger: 1
     retries: 0
-    servers: 192.168.0.16:9092,192.168.0.17:9092,192.168.0.18:9092
+    servers: 72.16.44.65:9092,172.16.44.67:9092,172.16.44.66:9092
 mvc:
   interceptor:
     exclude:
diff --git a/screen-api/src/main/resources/mapper/GroupMapper.xml b/screen-api/src/main/resources/mapper/GroupMapper.xml
index 1123a96..9fbdc8d 100644
--- a/screen-api/src/main/resources/mapper/GroupMapper.xml
+++ b/screen-api/src/main/resources/mapper/GroupMapper.xml
@@ -17,7 +17,7 @@
         <result column="group_name" property="groupName"/>
     </resultMap>
 
-    <select id="selectUserGroup" resultMap="GroupResultMap">
+    <select id="selectUserGroup" resultMap="BaseResultMap">
         SELECT g.id,g.group_name
         FROM `group` g,`user_group` ug
         WHERE ug.user_id = #{userId}
diff --git a/screen-api/src/main/resources/mapper/GroupMenuMapper.xml b/screen-api/src/main/resources/mapper/GroupMenuMapper.xml
index 5930463..f0a661b 100644
--- a/screen-api/src/main/resources/mapper/GroupMenuMapper.xml
+++ b/screen-api/src/main/resources/mapper/GroupMenuMapper.xml
@@ -2,16 +2,16 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.moral.api.mapper.GroupMenuMapper">
 
-        <!-- ������������������������ -->
-        <resultMap id="BaseResultMap" type="com.moral.api.entity.GroupMenu">
-                    <id column="id" property="id" />
-                    <result column="group_id" property="groupId" />
-                    <result column="menu_id" property="menuId" />
-                    <result column="channel_key" property="channelKey" />
-                    <result column="organization_id" property="organizationId" />
-                    <result column="create_time" property="createTime" />
-                    <result column="update_time" property="updateTime" />
-                    <result column="is_delete" property="isDelete" />
-        </resultMap>
+    <!-- ������������������������ -->
+    <resultMap id="BaseResultMap" type="com.moral.api.entity.GroupMenu">
+        <id column="id" property="id"/>
+        <result column="group_id" property="groupId"/>
+        <result column="menu_id" property="menuId"/>
+        <result column="channel_key" property="channelKey"/>
+        <result column="organization_id" property="organizationId"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="is_delete" property="isDelete"/>
+    </resultMap>
 
 </mapper>
\ No newline at end of file
diff --git a/screen-api/src/main/resources/mapper/MenuMapper.xml b/screen-api/src/main/resources/mapper/MenuMapper.xml
index bfe661a..2634fdb 100644
--- a/screen-api/src/main/resources/mapper/MenuMapper.xml
+++ b/screen-api/src/main/resources/mapper/MenuMapper.xml
@@ -20,7 +20,7 @@
     </sql>
 
     <select id="selectUserMenu" resultMap="BaseResultMap">
-        select
+        SELECT
         <include refid="Base_Column_List"/>
         FROM `user_group` ug,`group_menu` gm,`menu` m
         WHERE ug.user_id = #{userId}
@@ -33,14 +33,13 @@
     </select>
 
     <select id="selectOrganizationMenu" resultMap="BaseResultMap">
-        select
-        <include refid="Base_Column_List"/>
-        FROM `menu` m, `organization_menu` om
-        WHERE om.organization_id = #{orgId}
-        AND m.id = om.menu_id
-        AND om.channel_key = 0
-        AND om.menu_id = m.id
-        AND om.is_delete = 0
+        SELECT
+        DISTINCT m.id, m.name, m.url, m.icon, m.parent_id, m.order, m.create_time, m.update_time
+        FROM `menu` m, `group_menu` gm
+        WHERE gm.organization_id = #{orgId}
+        AND m.id = gm.menu_id
+        AND gm.channel_key = 0
+        AND gm.is_delete = 0
         AND m.is_delete = 0
     </select>
 </mapper>
\ No newline at end of file
diff --git a/screen-common/src/main/java/com/moral/constant/Constants.java b/screen-common/src/main/java/com/moral/constant/Constants.java
index a56abbd..535af51 100644
--- a/screen-common/src/main/java/com/moral/constant/Constants.java
+++ b/screen-common/src/main/java/com/moral/constant/Constants.java
@@ -120,5 +120,10 @@
      * */
     public static final String UN_ADJUST = "unadjust";
 
+    /*
+     * ���������������������
+     * */
+    public static final String DEVICE_STATE_OFFLINE = "4";
+
 
 }
diff --git a/screen-common/src/main/java/com/moral/constant/KafkaConstants.java b/screen-common/src/main/java/com/moral/constant/KafkaConstants.java
index 8f904d1..e1d6e80 100644
--- a/screen-common/src/main/java/com/moral/constant/KafkaConstants.java
+++ b/screen-common/src/main/java/com/moral/constant/KafkaConstants.java
@@ -5,15 +5,25 @@
     /**
      * ������������������
      */
-    public static final String TOPIC_MINUTE = "test_topic";
+    public static final String TOPIC_MINUTE = "minute";
 
     /**
      * ������������������
      */
     public static final String TOPIC_HOUR = "hour";
 
+    /*
+     * ���������������
+     * */
+    public static final String TOPIC_SECOND = "test";
+
     /**
-     * ���������
+     * ������������������������������������������
      */
-    public static final String GROUP_ID = "test";
+    public static final String GROUP_ID_INSERT = "insert";
+
+    /**
+     * ���������������������������������
+     */
+    public static final String GROUP_ID_STATE = "state";
 }
diff --git a/screen-common/src/main/java/com/moral/constant/RedisConstants.java b/screen-common/src/main/java/com/moral/constant/RedisConstants.java
index dd34339..bbc6324 100644
--- a/screen-common/src/main/java/com/moral/constant/RedisConstants.java
+++ b/screen-common/src/main/java/com/moral/constant/RedisConstants.java
@@ -47,4 +47,15 @@
     * ���������������Map<String,Device>
     * */
     public static final String DEVICE_INFO = "device_alarm_info";
+
+    /*
+     * ������������������������
+     * */
+    public static final String ADJUST = "adjust";
+
+    /*
+     * ������������������
+     * */
+    public static final String DEVICE_DATA = "data";
+
 }
diff --git a/screen-common/src/main/java/com/moral/util/DateUtils.java b/screen-common/src/main/java/com/moral/util/DateUtils.java
index cbc63a2..f5ecd8a 100644
--- a/screen-common/src/main/java/com/moral/util/DateUtils.java
+++ b/screen-common/src/main/java/com/moral/util/DateUtils.java
@@ -67,6 +67,14 @@
      * ������������(HH:mm:ss)
      */
     public static final String HH_mm_ss_EN = "HH:mm:ss";
+    /*
+     * ������������(yyyy-MM-dd HH:mm)
+     * */
+    public static final String yyyy_MM_dd_HH_mm_EN = "yyyy-MM-dd HH:mm";
+    /*
+     * ������������(yyyy-MM-dd HH)
+     * */
+    public static final String yyyy_MM_dd_HH_EN = "yyyy-MM-dd HH";
     /**
      * DateFormat������
      */
@@ -443,14 +451,14 @@
     }
 
     /**
-    * @Description: ������������������day���������������
-            * @Param: [date, day]
-            * @return: java.util.Date
-            * @Author: ���������
-            * @Date: 2021/3/30
-            */
+     * @Description: ������������������day���������������
+     * @Param: [date, day]
+     * @return: java.util.Date
+     * @Author: ���������
+     * @Date: 2021/3/30
+     */
     public static Date getDateOfDay(Date date, int day) {
-        if(date==null)
+        if (date == null)
             return null;
         Calendar now = Calendar.getInstance(TimeZone.getDefault());
         now.setTime(date);
@@ -1293,11 +1301,23 @@
         return date;
     }
 
+    //������������������������������������
+    public static Date convertDate(Date date) {
+        String dateString = dateToDateString(date, yyyy_MM_dd_HH_mm_EN);
+        return getDate(dateString, yyyy_MM_dd_HH_mm_EN);
+    }
+
+    //���������������������������������
+    public static Date dataToTimeStampTime(Date time, String dateFormat) {
+        String dateString = dateToDateString(time, dateFormat);
+        try {
+            return getDateFormat(dateFormat).parse(dateString);
+        } catch (ParseException e) {
+            throw new RuntimeException(e);
+        }
+    }
 
     public static void main(String[] args) throws InterruptedException {
-        Date date1 = new Date();
-        Thread.sleep(1000);
-        Date date2 = new Date();
-        System.out.println(DateUtils.compareDateStr(date1, date2));
+        System.out.println(new Date().getTime());
     }
 }
diff --git a/screen-job/src/main/java/com/moral/api/config/redis/RedisConfig.java b/screen-job/src/main/java/com/moral/api/config/redis/RedisConfig.java
new file mode 100644
index 0000000..1b34bb0
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/config/redis/RedisConfig.java
@@ -0,0 +1,67 @@
+package com.moral.api.config.redis;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+@Configuration
+public class RedisConfig {
+
+    @Bean(name = "redisTemplate")
+    @ConditionalOnMissingBean(StringRedisTemplate.class)  //������������������  ���������������������RedisTemplate ������������    ������������������
+    public RedisTemplate<String, Object> stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        // key������String������������������
+        redisTemplate.setKeySerializer(stringRedisSerializer);
+        // hash���key���������String������������������
+        redisTemplate.setHashKeySerializer(stringRedisSerializer);
+        // valuevalue������jackson���������������
+        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
+        // hash���value������jackson���������������
+        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
+        redisTemplate.afterPropertiesSet();
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+    public RedisTemplate createRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+
+        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+        ObjectMapper objectMapper = new ObjectMapper();
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
+
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        // key������String������������������
+        redisTemplate.setKeySerializer(stringRedisSerializer);
+        // hash���key���������String������������������
+        redisTemplate.setHashKeySerializer(stringRedisSerializer);
+        // valuevalue������jackson���������������
+        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
+        // hash���value������jackson���������������
+        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
+        redisTemplate.afterPropertiesSet();
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/config/xxl/XxlJobConfig.java b/screen-job/src/main/java/com/moral/api/config/xxl/XxlJobConfig.java
deleted file mode 100644
index fc087e1..0000000
--- a/screen-job/src/main/java/com/moral/api/config/xxl/XxlJobConfig.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.moral.api.config.xxl;
-
-
-import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-
-import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
-
-@Configuration
-@ComponentScan(basePackages = "com.moral.api.jobHandler")
-@Slf4j
-public class XxlJobConfig {
-
-    @Value("${xxl.job.admin.addresses}")
-    private String adminAddresses;
-
-    @Value("${xxl.job.executor.appname}")
-    private String appName;
-
-    @Value("${xxl.job.executor.ip}")
-    private String ip;
-
-    @Value("${xxl.job.executor.port}")
-    private Integer port;
-
-    @Value("${xxl.job.accessToken}")
-    private String accessToken;
-
-    @Value("${xxl.job.executor.logpath}")
-    private String logPath;
-
-    @Value("${xxl.job.executor.logretentiondays}")
-    private Integer logRetentionDays;
-
-    @Bean
-    public XxlJobSpringExecutor xxlJobSpringExecutor(){
-        log.info("xxl jon config init");
-        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
-        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
-        xxlJobSpringExecutor.setAppname(appName);
-        xxlJobSpringExecutor.setIp(ip);
-        xxlJobSpringExecutor.setPort(port);
-        xxlJobSpringExecutor.setAccessToken(accessToken);
-        xxlJobSpringExecutor.setLogPath(logPath);
-        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
-        return xxlJobSpringExecutor;
-    }
-
-    @Override
-    public String toString() {
-        return "XxlJobConfig{" +
-                "adminAddresses='" + adminAddresses + '\'' +
-                ", appName='" + appName + '\'' +
-                ", ip='" + ip + '\'' +
-                ", port=" + port +
-                ", accessToken='" + accessToken + '\'' +
-                ", logPath='" + logPath + '\'' +
-                ", logRetentionDays=" + logRetentionDays +
-                '}';
-    }
-
-    public XxlJobConfig() {
-    }
-
-    public XxlJobConfig(String adminAddresses, String appName, String ip, Integer port, String accessToken, String logPath, Integer logRetentionDays) {
-        this.adminAddresses = adminAddresses;
-        this.appName = appName;
-        this.ip = ip;
-        this.port = port;
-        this.accessToken = accessToken;
-        this.logPath = logPath;
-        this.logRetentionDays = logRetentionDays;
-    }
-
-    public String getAdminAddresses() {
-        return adminAddresses;
-    }
-
-    public void setAdminAddresses(String adminAddresses) {
-        this.adminAddresses = adminAddresses;
-    }
-
-    public String getAppName() {
-        return appName;
-    }
-
-    public void setAppName(String appName) {
-        this.appName = appName;
-    }
-
-    public String getIp() {
-        return ip;
-    }
-
-    public void setIp(String ip) {
-        this.ip = ip;
-    }
-
-    public Integer getPort() {
-        return port;
-    }
-
-    public void setPort(Integer port) {
-        this.port = port;
-    }
-
-    public String getAccessToken() {
-        return accessToken;
-    }
-
-    public void setAccessToken(String accessToken) {
-        this.accessToken = accessToken;
-    }
-
-    public String getLogPath() {
-        return logPath;
-    }
-
-    public void setLogPath(String logPath) {
-        this.logPath = logPath;
-    }
-
-    public Integer getLogRetentionDays() {
-        return logRetentionDays;
-    }
-
-    public void setLogRetentionDays(Integer logRetentionDays) {
-        this.logRetentionDays = logRetentionDays;
-    }
-}
diff --git a/screen-job/src/main/java/com/moral/api/config/xxljob/XxlJobConfig.java b/screen-job/src/main/java/com/moral/api/config/xxljob/XxlJobConfig.java
new file mode 100644
index 0000000..ccb076d
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/config/xxljob/XxlJobConfig.java
@@ -0,0 +1,68 @@
+package com.moral.api.config.xxljob;
+
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
+
+@Configuration
+@ComponentScan(basePackages = "com.moral.api.job")
+@Slf4j
+public class XxlJobConfig {
+
+    @Value("${xxl.job.admin.addresses}")
+    private String adminAddresses;
+
+    @Value("${xxl.job.executor.appname}")
+    private String appName;
+
+    @Value("${xxl.job.executor.ip}")
+    private String ip;
+
+    @Value("${xxl.job.executor.port}")
+    private Integer port;
+
+    @Value("${xxl.job.accessToken}")
+    private String accessToken;
+
+    @Value("${xxl.job.executor.logpath}")
+    private String logPath;
+
+    @Value("${xxl.job.executor.logretentiondays}")
+    private Integer logRetentionDays;
+
+    @Bean
+    public XxlJobSpringExecutor xxlJobSpringExecutor() {
+        log.info("xxl jon config init");
+        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
+        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
+        xxlJobSpringExecutor.setAppname(appName);
+        xxlJobSpringExecutor.setIp(ip);
+        xxlJobSpringExecutor.setPort(port);
+        xxlJobSpringExecutor.setAccessToken(accessToken);
+        xxlJobSpringExecutor.setLogPath(logPath);
+        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
+        return xxlJobSpringExecutor;
+    }
+
+    /**
+     * ������������������������������������������������������ "spring-cloud-commons" ��������� "InetUtils" ������������������������IP���
+     *
+     *      1������������������
+     *          <dependency>
+     *             <groupId>org.springframework.cloud</groupId>
+     *             <artifactId>spring-cloud-commons</artifactId>
+     *             <version>${version}</version>
+     *         </dependency>
+     *
+     *      2������������������������������������������
+     *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
+     *
+     *      3���������IP
+     *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
+     */
+}
diff --git a/screen-job/src/main/java/com/moral/api/entity/CityAqiConfig.java b/screen-job/src/main/java/com/moral/api/entity/CityAqiConfig.java
new file mode 100644
index 0000000..4c95fa0
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/entity/CityAqiConfig.java
@@ -0,0 +1,50 @@
+package com.moral.api.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * ������������aqi������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class CityAqiConfig extends Model<CityAqiConfig> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ������id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * ������code
+     */
+    private String cityCode;
+
+    /**
+     * ������������
+     */
+    private String cityName;
+
+    /**
+     * ���������������������������id
+     */
+    private Integer cityId;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/entity/Device.java b/screen-job/src/main/java/com/moral/api/entity/Device.java
new file mode 100644
index 0000000..842a27f
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/entity/Device.java
@@ -0,0 +1,132 @@
+package com.moral.api.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-22
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class Device extends Model<Device> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ������id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * ������������
+     */
+    private String name;
+
+    /**
+     * mac���
+     */
+    private String mac;
+
+    /**
+     * ������������
+     */
+    private String address;
+
+    /**
+     * ������
+     */
+    private Double longitude;
+
+    /**
+     * ������
+     */
+    private Double latitude;
+
+    /**
+     * ���������������������������������
+     */
+    private String state;
+
+    /**
+     * ���������id���������������������������������manage_account
+     */
+    private String operateIds;
+
+    /**
+     * ������id
+     */
+    private Integer monitorPointId;
+
+    /**
+     * ������id
+     */
+    private Integer organizationId;
+
+    /**
+     * ������������id
+     */
+    private Integer deviceVersionId;
+
+    /**
+     * ���������������������������
+     */
+    private String profession;
+
+    /**
+     * ���������������1������������2������������3������������������������������������
+     */
+    private String tech;
+
+    /**
+     * ������������������������������������
+     */
+    private String detector;
+
+    /**
+     * ������������������������������
+     */
+    private String purchaser;
+
+    /**
+     * ������(������)������
+     */
+    private LocalDateTime createTime;
+
+    /**
+     * ������������
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     * ������������
+     */
+    private LocalDateTime installTime;
+
+    /**
+     * ������������,0���������������1���������
+     */
+    private String isDelete;
+
+    /**
+     * ������������������������
+     */
+    private String extend;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/entity/HistoryAqi.java b/screen-job/src/main/java/com/moral/api/entity/HistoryAqi.java
new file mode 100644
index 0000000..95327da
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/entity/HistoryAqi.java
@@ -0,0 +1,45 @@
+package com.moral.api.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * ������aqi���������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class HistoryAqi extends Model<HistoryAqi> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ������code
+     */
+    private String cityCode;
+
+    /**
+     * ������
+     */
+    private Date time;
+
+    /**
+     * ������
+     */
+    private String value;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return null;
+    }
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/entity/HistoryDaily.java b/screen-job/src/main/java/com/moral/api/entity/HistoryDaily.java
new file mode 100644
index 0000000..b24913d
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/entity/HistoryDaily.java
@@ -0,0 +1,36 @@
+package com.moral.api.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-11
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class HistoryDaily extends Model<HistoryDaily> {
+
+    private static final long serialVersionUID = 1L;
+
+    private String mac;
+
+    private Date time;
+
+    private String value;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return null;
+    }
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/mapper/CityAqiConfigMapper.java b/screen-job/src/main/java/com/moral/api/mapper/CityAqiConfigMapper.java
new file mode 100644
index 0000000..825f5ac
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/mapper/CityAqiConfigMapper.java
@@ -0,0 +1,16 @@
+package com.moral.api.mapper;
+
+import com.moral.api.entity.CityAqiConfig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * ������������aqi������������ Mapper ������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+public interface CityAqiConfigMapper extends BaseMapper<CityAqiConfig> {
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/mapper/DeviceMapper.java b/screen-job/src/main/java/com/moral/api/mapper/DeviceMapper.java
new file mode 100644
index 0000000..4bb2d15
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/mapper/DeviceMapper.java
@@ -0,0 +1,16 @@
+package com.moral.api.mapper;
+
+import com.moral.api.entity.Device;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * ��������� Mapper ������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-22
+ */
+public interface DeviceMapper extends BaseMapper<Device> {
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/mapper/HistoryAqiMapper.java b/screen-job/src/main/java/com/moral/api/mapper/HistoryAqiMapper.java
new file mode 100644
index 0000000..87650be
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/mapper/HistoryAqiMapper.java
@@ -0,0 +1,17 @@
+package com.moral.api.mapper;
+
+import com.moral.api.entity.HistoryAqi;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * ������aqi��������� Mapper ������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+public interface HistoryAqiMapper extends BaseMapper<HistoryAqi> {
+
+}
+
diff --git a/screen-job/src/main/java/com/moral/api/mapper/HistoryDailyMapper.java b/screen-job/src/main/java/com/moral/api/mapper/HistoryDailyMapper.java
new file mode 100644
index 0000000..0159fde
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/mapper/HistoryDailyMapper.java
@@ -0,0 +1,21 @@
+package com.moral.api.mapper;
+
+import java.util.List;
+import java.util.Map;
+
+import com.moral.api.entity.HistoryDaily;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper ������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-11
+ */
+public interface HistoryDailyMapper extends BaseMapper<HistoryDaily> {
+
+    void insertHistoryDaily(List<HistoryDaily> list);
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/mapper/HistoryFiveMinutelyMapper.java b/screen-job/src/main/java/com/moral/api/mapper/HistoryFiveMinutelyMapper.java
new file mode 100644
index 0000000..40c1caa
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/mapper/HistoryFiveMinutelyMapper.java
@@ -0,0 +1,15 @@
+package com.moral.api.mapper;
+
+
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface HistoryFiveMinutelyMapper {
+
+    void createTable(String timeUnits);
+
+    void insertHistoryFiveMinutely(@Param("list") List<Map<String, Object>> list, @Param("timeUnits") String timeUnits);
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/mapper/HistoryMinutelyMapper.java b/screen-job/src/main/java/com/moral/api/mapper/HistoryMinutelyMapper.java
new file mode 100644
index 0000000..dd466df
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/mapper/HistoryMinutelyMapper.java
@@ -0,0 +1,11 @@
+package com.moral.api.mapper;
+
+import java.util.List;
+import java.util.Map;
+
+public interface HistoryMinutelyMapper {
+
+    void createTable(String timeUnits);
+
+    List<Map<String, Object>> getHistoryFiveMinutelyData(Map<String,Object> params);
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/CityAqiConfigService.java b/screen-job/src/main/java/com/moral/api/service/CityAqiConfigService.java
new file mode 100644
index 0000000..26e6691
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/CityAqiConfigService.java
@@ -0,0 +1,20 @@
+package com.moral.api.service;
+
+import java.util.List;
+
+import com.moral.api.entity.CityAqiConfig;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * ������������aqi������������ ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+public interface CityAqiConfigService extends IService<CityAqiConfig> {
+
+    List<CityAqiConfig> getCityAqiConfigs();
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/DeviceService.java b/screen-job/src/main/java/com/moral/api/service/DeviceService.java
new file mode 100644
index 0000000..f33824e
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/DeviceService.java
@@ -0,0 +1,20 @@
+package com.moral.api.service;
+
+import com.moral.api.entity.Device;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * ��������� ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-22
+ */
+public interface DeviceService extends IService<Device> {
+
+    void judgeOffLineDevice();
+
+    void updateDeviceState(Device device);
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/HistoryAqiService.java b/screen-job/src/main/java/com/moral/api/service/HistoryAqiService.java
new file mode 100644
index 0000000..078a270
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/HistoryAqiService.java
@@ -0,0 +1,10 @@
+package com.moral.api.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.moral.api.entity.HistoryAqi;
+
+public interface HistoryAqiService extends IService<HistoryAqi> {
+
+    void insertHistoryAqi();
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/HistoryDailyService.java b/screen-job/src/main/java/com/moral/api/service/HistoryDailyService.java
new file mode 100644
index 0000000..b08dd7b
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/HistoryDailyService.java
@@ -0,0 +1,21 @@
+package com.moral.api.service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.moral.api.entity.HistoryDaily;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-11
+ */
+public interface HistoryDailyService extends IService<HistoryDaily> {
+
+    void insertHistoryDaily(List<HistoryDaily> list);
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/HistoryFiveMinutelyService.java b/screen-job/src/main/java/com/moral/api/service/HistoryFiveMinutelyService.java
new file mode 100644
index 0000000..23ad4ef
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/HistoryFiveMinutelyService.java
@@ -0,0 +1,9 @@
+package com.moral.api.service;
+
+public interface HistoryFiveMinutelyService {
+
+    void createTable(String timeUnits);
+
+    void insertHistoryFiveMinutely();
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/HistoryMinutelyService.java b/screen-job/src/main/java/com/moral/api/service/HistoryMinutelyService.java
new file mode 100644
index 0000000..7b614af
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/HistoryMinutelyService.java
@@ -0,0 +1,12 @@
+package com.moral.api.service;
+
+import java.util.List;
+import java.util.Map;
+
+public interface HistoryMinutelyService {
+
+    void createTable(String timeUnits);
+
+    List<Map<String, Object>> getHistoryFiveMinutelyData(Map<String, Object> params);
+
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/Test.java b/screen-job/src/main/java/com/moral/api/service/Test.java
deleted file mode 100644
index 7b34503..0000000
--- a/screen-job/src/main/java/com/moral/api/service/Test.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.moral.api.service;
-
-public class Test {
-}
diff --git a/screen-job/src/main/java/com/moral/api/service/impl/CityAqiConfigServiceImpl.java b/screen-job/src/main/java/com/moral/api/service/impl/CityAqiConfigServiceImpl.java
new file mode 100644
index 0000000..5d7aca6
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/impl/CityAqiConfigServiceImpl.java
@@ -0,0 +1,31 @@
+package com.moral.api.service.impl;
+
+import com.moral.api.entity.CityAqiConfig;
+import com.moral.api.mapper.CityAqiConfigMapper;
+import com.moral.api.service.CityAqiConfigService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * ������������aqi������������ ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+@Service
+public class CityAqiConfigServiceImpl extends ServiceImpl<CityAqiConfigMapper, CityAqiConfig> implements CityAqiConfigService {
+
+    @Autowired
+    private CityAqiConfigMapper cityAqiConfigMapper;
+
+    @Override
+    public List<CityAqiConfig> getCityAqiConfigs() {
+        return cityAqiConfigMapper.selectList(null);
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java b/screen-job/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java
new file mode 100644
index 0000000..265c405
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java
@@ -0,0 +1,69 @@
+package com.moral.api.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.moral.api.entity.Device;
+import com.moral.api.mapper.DeviceMapper;
+import com.moral.api.service.DeviceService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.moral.constant.Constants;
+import com.moral.constant.RedisConstants;
+import com.moral.util.DateUtils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * ��������� ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-22
+ */
+@Service
+public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {
+
+    @Autowired
+    private DeviceMapper deviceMapper;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    @Override
+    public void judgeOffLineDevice() {
+        QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
+        queryWrapper.ne("state", Constants.DEVICE_STATE_OFFLINE);
+        //������������������������
+        List<Device> devices = deviceMapper.selectList(queryWrapper);
+        for (Device device : devices) {
+            Map<String, Object> data = getDataFromRedis(device.getMac());
+            device.setState(Constants.DEVICE_STATE_OFFLINE);
+            if (data != null && data.containsKey("DataTime")) {
+                long time = Long.parseLong(data.get("DataTime").toString());
+                //���������������������������������
+                if (DateUtils.getDateOfMin(new Date(time), 2).getTime() < new Date().getTime()) {
+                    updateDeviceState(device);
+                }
+            } else {
+                updateDeviceState(device);
+            }
+        }
+    }
+
+    @Override
+    public void updateDeviceState(Device device) {
+        UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("id", device.getId()).set("state", device.getState());
+        deviceMapper.update(null, updateWrapper);
+    }
+
+    private Map<String, Object> getDataFromRedis(String mac) {
+        return (Map<String, Object>) redisTemplate.opsForValue().get(RedisConstants.DEVICE_DATA + "_" + mac);
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/impl/HistoryAqiServiceImpl.java b/screen-job/src/main/java/com/moral/api/service/impl/HistoryAqiServiceImpl.java
new file mode 100644
index 0000000..0fadead
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/impl/HistoryAqiServiceImpl.java
@@ -0,0 +1,77 @@
+package com.moral.api.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.moral.api.entity.CityAqiConfig;
+import com.moral.api.entity.HistoryAqi;
+import com.moral.api.mapper.HistoryAqiMapper;
+import com.moral.api.service.CityAqiConfigService;
+import com.moral.api.service.HistoryAqiService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * ������aqi��������� ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-15
+ */
+@Service
+@Slf4j
+public class HistoryAqiServiceImpl extends ServiceImpl<HistoryAqiMapper, HistoryAqi> implements HistoryAqiService {
+
+    @Autowired
+    private HistoryAqiMapper historyAqiMapper;
+
+    @Autowired
+    private CityAqiConfigService cityAqiConfigService;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    @Override
+    public void insertHistoryAqi() {
+        RestTemplate restTemplate = new RestTemplate();
+        //������aqi������������
+        List<CityAqiConfig> cityAqiConfigs = cityAqiConfigService.getCityAqiConfigs();
+        for (CityAqiConfig cityAqiConfig : cityAqiConfigs) {
+            Map<String, Object> mjMap = restTemplate.getForObject("http://sapi.7drlb.com/api/mj?cityID={1}&apiKey=aqi", Map.class, cityAqiConfig.getCityId());
+            if (ObjectUtils.isEmpty(mjMap)) {
+                continue;
+            }
+            HistoryAqi historyAqi = new HistoryAqi();
+            //city_code
+            String cityCode = cityAqiConfig.getCityCode();
+            historyAqi.setCityCode(cityCode);
+            Map<String, Object> value = new HashMap<>();
+            Map<String, Object> data = (Map<String, Object>) ((Map) mjMap.get("data")).get("aqi");
+            //������������
+            historyAqi.setTime(new Date(Long.parseLong(data.get("pubtime").toString())));
+            value.put("PM25", data.get("pm25C"));
+            value.put("PM10", data.get("pm10C"));
+            value.put("SO2", data.get("so2C"));
+            value.put("NO2", data.get("no2C"));
+            value.put("CO", data.get("coC"));
+            value.put("O3", data.get("o3C"));
+            value.put("AQI", data.get("value"));
+            //������
+            historyAqi.setValue(JSON.toJSONString(value));
+            //���������������������
+            historyAqiMapper.insert(historyAqi);
+            //������redis
+            redisTemplate.opsForHash().putAll("aqi_" + cityCode, value);
+        }
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/impl/HistoryDailyServiceImpl.java b/screen-job/src/main/java/com/moral/api/service/impl/HistoryDailyServiceImpl.java
new file mode 100644
index 0000000..07b3958
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/impl/HistoryDailyServiceImpl.java
@@ -0,0 +1,33 @@
+package com.moral.api.service.impl;
+
+import com.moral.api.entity.HistoryDaily;
+import com.moral.api.mapper.HistoryDailyMapper;
+import com.moral.api.service.HistoryDailyService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-11
+ */
+@Service
+public class HistoryDailyServiceImpl extends ServiceImpl<HistoryDailyMapper, HistoryDaily> implements HistoryDailyService {
+
+    @Autowired
+    private HistoryDailyMapper historyDailyMapper;
+
+    @Override
+    public void insertHistoryDaily(List<HistoryDaily> list) {
+        System.out.println(list);
+        historyDailyMapper.insertHistoryDaily(list);
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/impl/HistoryFiveMinutelyServiceImpl.java b/screen-job/src/main/java/com/moral/api/service/impl/HistoryFiveMinutelyServiceImpl.java
new file mode 100644
index 0000000..fb85a9d
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/impl/HistoryFiveMinutelyServiceImpl.java
@@ -0,0 +1,64 @@
+package com.moral.api.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.fastjson.JSON;
+import com.moral.api.mapper.HistoryFiveMinutelyMapper;
+import com.moral.api.service.HistoryFiveMinutelyService;
+import com.moral.api.service.HistoryMinutelyService;
+import com.moral.util.DateUtils;
+
+@Service
+public class HistoryFiveMinutelyServiceImpl implements HistoryFiveMinutelyService {
+
+    @Autowired
+    private HistoryFiveMinutelyMapper historyFiveMinutelyMapper;
+
+    @Autowired
+    private HistoryMinutelyService historyMinutelyService;
+
+    @Override
+    public void createTable(String timeUnits) {
+        historyFiveMinutelyMapper.createTable(timeUnits);
+    }
+
+    @Override
+    public void insertHistoryFiveMinutely() {
+        Map<String, Object> params = new HashMap<>();
+        //������������������������
+        Date start = DateUtils.convertDate(DateUtils.getDateOfMin(-5));
+        //������������������������
+        Date end = DateUtils.convertDate(new Date());
+        params.put("start", start);
+        params.put("end", end);
+        //���������������
+        String timeUnits = DateUtils.dateToDateString(start, DateUtils.yyyyMM_EN);
+        params.put("timeUnits", timeUnits);
+
+        //������
+
+        params.put("sensorKeys", null);
+
+        historyMinutelyService.getHistoryFiveMinutelyData(params);
+        /*List<Map<String, Object>> list = new ArrayList<>();
+        Map<String, Object> map = new HashMap<>();
+        map.put("mac", "123456");
+        Date date = new Date();
+        map.put("time", date);
+        Map<String, Object> value = new HashMap<>();
+        value.put("e1", 10);
+        value.put("e2", 20);
+        map.put("value", JSON.toJSONString(value));
+        list.add(map);*/
+
+        historyFiveMinutelyMapper.insertHistoryFiveMinutely(null, null);
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java b/screen-job/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java
new file mode 100644
index 0000000..730ef35
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java
@@ -0,0 +1,27 @@
+package com.moral.api.service.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.moral.api.mapper.HistoryMinutelyMapper;
+import com.moral.api.service.HistoryMinutelyService;
+
+@Service
+public class HistoryMinutelyServiceImpl implements HistoryMinutelyService {
+
+    @Autowired
+    private HistoryMinutelyMapper historyMinutelyMapper;
+
+    @Override
+    public void createTable(String timeUnits) {
+        historyMinutelyMapper.createTable(timeUnits);
+    }
+
+    @Override
+    public List<Map<String, Object>> getHistoryFiveMinutelyData(Map<String, Object> params) {
+        return historyMinutelyMapper.getHistoryFiveMinutelyData(params);
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/task/CreateTableTask.java b/screen-job/src/main/java/com/moral/api/task/CreateTableTask.java
new file mode 100644
index 0000000..2fab184
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/task/CreateTableTask.java
@@ -0,0 +1,52 @@
+package com.moral.api.task;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.moral.api.service.HistoryFiveMinutelyService;
+import com.moral.api.service.HistoryMinutelyService;
+import com.moral.constant.Constants;
+import com.moral.util.DateUtils;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+
+@Component
+public class CreateTableTask {
+
+    @Autowired
+    private HistoryFiveMinutelyService historyFiveMinutelyService;
+
+    @Autowired
+    private HistoryMinutelyService historyMinutelyService;
+
+
+    //���������������������
+    @XxlJob("createHistoryMinutelyTable")
+    public ReturnT createHistoryMinutelyTable() {
+        String timeUnits = DateUtils.getDateStringOfMon(1, DateUtils.yyyyMM_EN);
+        try {
+            //������������������
+            historyMinutelyService.createTable(timeUnits);
+            //������������������
+            historyMinutelyService.createTable(timeUnits + "_" + Constants.UN_ADJUST);
+        } catch (Exception e) {
+            XxlJobHelper.log(e.getMessage());
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
+
+    //5���������������������
+    @XxlJob("createHistoryFiveMinutelyTable")
+    public ReturnT createHistoryFiveMinutelyTable() {
+        String timeUnits = DateUtils.getDateStringOfMon(1, DateUtils.yyyyMM_EN);
+        try {
+            historyFiveMinutelyService.createTable(timeUnits);
+        } catch (Exception e) {
+            XxlJobHelper.log(e.getMessage());
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/task/HistoryAqiInsertTask.java b/screen-job/src/main/java/com/moral/api/task/HistoryAqiInsertTask.java
new file mode 100644
index 0000000..603e2d2
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/task/HistoryAqiInsertTask.java
@@ -0,0 +1,27 @@
+package com.moral.api.task;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.moral.api.service.HistoryAqiService;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+
+@Component
+public class HistoryAqiInsertTask {
+
+    @Autowired
+    private HistoryAqiService historyAqiService;
+
+    @XxlJob("insertHistoryAqi")
+    public ReturnT insertHistoryAqi() {
+        try {
+            historyAqiService.insertHistoryAqi();
+        } catch (Exception e) {
+            XxlJobHelper.log(e.getMessage());
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/task/HistoryTableInsertTask.java b/screen-job/src/main/java/com/moral/api/task/HistoryTableInsertTask.java
new file mode 100644
index 0000000..eb9b6af
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/task/HistoryTableInsertTask.java
@@ -0,0 +1,74 @@
+package com.moral.api.task;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.fastjson.JSON;
+import com.moral.api.entity.HistoryDaily;
+import com.moral.api.service.HistoryDailyService;
+import com.moral.api.service.HistoryFiveMinutelyService;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+
+@Component
+public class HistoryTableInsertTask {
+
+    @Autowired
+    private HistoryDailyService historyDailyService;
+
+    @Autowired
+    private HistoryFiveMinutelyService historyFiveMinutelyService;
+
+    //5������������������
+    @XxlJob("insertHistoryFiveMinutely")
+    public ReturnT insertHistoryFiveMinutely() {
+        try {
+           /* List<Map<String, Object>> list = new ArrayList<>();
+            Map<String, Object> map = new HashMap<>();
+            map.put("mac", "123456");
+            Date date = new Date();
+            map.put("time", date);
+            Map<String, Object> value = new HashMap<>();
+            value.put("e1", 10);            value.put("e2", 20);
+            map.put("value", JSON.toJSONString(value));
+            list.add(map);
+            String timeUnits = DateUtils.dateToDateString(date, DateUtils.yyyyMM_EN);*/
+
+            historyFiveMinutelyService.insertHistoryFiveMinutely();
+        } catch (Exception e) {
+            XxlJobHelper.log(e.getMessage());
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
+
+    //���������������
+    @XxlJob("insertHistoryDaily")
+    public ReturnT insertHistoryDaily() {
+        try {
+            List<HistoryDaily> list = new ArrayList<>();
+            HistoryDaily historyDaily = new HistoryDaily();
+            historyDaily.setMac("123456");
+            historyDaily.setTime(new Date());
+            Map<String, Object> value = new HashMap<>();
+            value.put("e1", 1);
+            value.put("e2", 2);
+            historyDaily.setValue(JSON.toJSONString(value));
+            for (int i = 0; i < 20000; i++) {
+                list.add(historyDaily);
+            }
+            historyDailyService.insertHistoryDaily(list);
+        } catch (Exception e) {
+            XxlJobHelper.log(e.getMessage());
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
+}
diff --git a/screen-job/src/main/java/com/moral/api/task/JudgeOffLineDeviceTask.java b/screen-job/src/main/java/com/moral/api/task/JudgeOffLineDeviceTask.java
new file mode 100644
index 0000000..aa5d7a6
--- /dev/null
+++ b/screen-job/src/main/java/com/moral/api/task/JudgeOffLineDeviceTask.java
@@ -0,0 +1,28 @@
+package com.moral.api.task;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.moral.api.service.DeviceService;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+
+@Component
+public class JudgeOffLineDeviceTask {
+
+    @Autowired
+    private DeviceService deviceService;
+
+    //������������������������
+    @XxlJob("judgeOffLineDevice")
+    public ReturnT judgeOffLineDevice() {
+        try {
+            deviceService.judgeOffLineDevice();
+        } catch (Exception e) {
+            XxlJobHelper.log(e.getMessage());
+            return ReturnT.FAIL;
+        }
+        return ReturnT.SUCCESS;
+    }
+}
diff --git a/screen-job/src/main/resources/application-dev.yml b/screen-job/src/main/resources/application-dev.yml
index d996a3c..248edec 100644
--- a/screen-job/src/main/resources/application-dev.yml
+++ b/screen-job/src/main/resources/application-dev.yml
@@ -81,6 +81,7 @@
 
 logging:
   config: classpath:logback.xml
+
 xxl:
   job:
     admin:
diff --git a/screen-job/src/main/resources/logback-spring.xml b/screen-job/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..d830e7a
--- /dev/null
+++ b/screen-job/src/main/resources/logback-spring.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+	<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
+
+	<springProperty scope="context" name="springAppName" source="spring.application.name"/>
+	<!-- ��������������������������������� -->
+	<property name="LOG_FILE" value="/home/moral/soft/log/${springAppName}"/>
+	<!-- ������������������������������ -->
+	<property name="CONSOLE_LOG_PATTERN"
+			  value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%X{logseq}]{faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${springAppName}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
+
+	<property name="FILE_LOG_PATTERN"
+			  value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{logseq}] [%thread] %X{T} [%level] %logger.%method:%line %msg%n"/>
+
+	<!-- ���������Appender -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+			<level>INFO</level>
+		</filter>
+		<encoder>
+			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
+			<charset>utf8</charset>
+		</encoder>
+	</appender>
+	<!-- ������������Appender -->
+	<appender name="screenJobLog" class="ch.qos.logback.classic.sift.SiftingAppender">
+		<discriminator>
+			<key>taskId</key>
+			<defaultValue>default</defaultValue>
+		</discriminator>
+		<sift>
+			<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
+
+				<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+					<level>INFO</level>
+				</filter>
+				<file>${LOG_FILE}/%d{yyyy-MM-dd}/${springAppName}.log</file>
+				<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+					<maxFileSize>30MB</maxFileSize>
+					<fileNamePattern>${LOG_FILE}/%d{yyyy-MM-dd}/${springAppName}-%d{yyyy-MM-dd}.log%i.log</fileNamePattern>
+					<maxHistory>30</maxHistory>
+				</rollingPolicy>
+				<encoder>
+					<pattern>${FILE_LOG_PATTERN}</pattern>
+					<charset>utf8</charset>
+				</encoder>
+			</appender>
+		</sift>
+	</appender>
+
+
+	<root level="INFO">
+		<appender-ref ref="console"/>
+		<appender-ref ref="screenJobLog"/>
+	</root>
+</configuration>
diff --git a/screen-job/src/main/resources/mapper/CityAqiConfigMapper.xml b/screen-job/src/main/resources/mapper/CityAqiConfigMapper.xml
new file mode 100644
index 0000000..a465401
--- /dev/null
+++ b/screen-job/src/main/resources/mapper/CityAqiConfigMapper.xml
@@ -0,0 +1,13 @@
+<?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.moral.api.mapper.CityAqiConfigMapper">
+
+    <!-- ������������������������ -->
+    <resultMap id="BaseResultMap" type="com.moral.api.entity.CityAqiConfig">
+        <id column="id" property="id"/>
+        <result column="city_code" property="cityCode"/>
+        <result column="city_name" property="cityName"/>
+        <result column="city_id" property="cityId"/>
+    </resultMap>
+
+</mapper>
\ No newline at end of file
diff --git a/screen-job/src/main/resources/mapper/DeviceMapper.xml b/screen-job/src/main/resources/mapper/DeviceMapper.xml
new file mode 100644
index 0000000..493dc7b
--- /dev/null
+++ b/screen-job/src/main/resources/mapper/DeviceMapper.xml
@@ -0,0 +1,29 @@
+<?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.moral.api.mapper.DeviceMapper">
+
+        <!-- ������������������������ -->
+        <resultMap id="BaseResultMap" type="com.moral.api.entity.Device">
+                    <id column="id" property="id" />
+                    <result column="name" property="name" />
+                    <result column="mac" property="mac" />
+                    <result column="address" property="address" />
+                    <result column="longitude" property="longitude" />
+                    <result column="latitude" property="latitude" />
+                    <result column="state" property="state" />
+                    <result column="operate_ids" property="operateIds" />
+                    <result column="monitor_point_id" property="monitorPointId" />
+                    <result column="organization_id" property="organizationId" />
+                    <result column="device_version_id" property="deviceVersionId" />
+                    <result column="profession" property="profession" />
+                    <result column="tech" property="tech" />
+                    <result column="detector" property="detector" />
+                    <result column="purchaser" property="purchaser" />
+                    <result column="create_time" property="createTime" />
+                    <result column="update_time" property="updateTime" />
+                    <result column="install_time" property="installTime" />
+                    <result column="is_delete" property="isDelete" />
+                    <result column="extend" property="extend" />
+        </resultMap>
+
+</mapper>
\ No newline at end of file
diff --git a/screen-job/src/main/resources/mapper/HistoryAqiMapper.xml b/screen-job/src/main/resources/mapper/HistoryAqiMapper.xml
new file mode 100644
index 0000000..24658a1
--- /dev/null
+++ b/screen-job/src/main/resources/mapper/HistoryAqiMapper.xml
@@ -0,0 +1,12 @@
+<?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.moral.api.mapper.HistoryAqiMapper">
+
+        <!-- ������������������������ -->
+        <resultMap id="BaseResultMap" type="com.moral.api.entity.HistoryAqi">
+                    <result column="city_code" property="cityCode" />
+                    <result column="time" property="time" />
+                    <result column="value" property="value" />
+        </resultMap>
+
+</mapper>
\ No newline at end of file
diff --git a/screen-job/src/main/resources/mapper/HistoryDailyMapper.xml b/screen-job/src/main/resources/mapper/HistoryDailyMapper.xml
new file mode 100644
index 0000000..f1582cd
--- /dev/null
+++ b/screen-job/src/main/resources/mapper/HistoryDailyMapper.xml
@@ -0,0 +1,19 @@
+<?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.moral.api.mapper.HistoryDailyMapper">
+
+    <!-- ������������������������ -->
+    <resultMap id="BaseResultMap" type="com.moral.api.entity.HistoryDaily">
+        <result column="mac" property="mac"/>
+        <result column="time" property="time"/>
+        <result column="value" property="value"/>
+    </resultMap>
+
+    <insert id="insertHistoryDaily" parameterType="com.moral.api.entity.HistoryDaily">
+        INSERT INTO history_daily
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{item.mac},#{item.time},#{item.value})
+        </foreach>
+    </insert>
+</mapper>
\ No newline at end of file
diff --git a/screen-job/src/main/resources/mapper/HistoryFiveMinutelyMapper.xml b/screen-job/src/main/resources/mapper/HistoryFiveMinutelyMapper.xml
new file mode 100644
index 0000000..13de990
--- /dev/null
+++ b/screen-job/src/main/resources/mapper/HistoryFiveMinutelyMapper.xml
@@ -0,0 +1,25 @@
+<?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.moral.api.mapper.HistoryFiveMinutelyMapper">
+
+    <update id="createTable" parameterType="String">
+        CREATE TABLE  IF NOT EXISTS `history_five_minutely_${timeUnits}` (
+            `mac` VARCHAR (20) DEFAULT NULL COMMENT '������mac',
+            `time` datetime DEFAULT NULL COMMENT '������������',
+            `value` json DEFAULT NULL COMMENT '������',
+            KEY `idx_mac` (`mac`),
+            KEY `idx_time` (`time`),
+            KEY `idx_mac_time` (`mac`,`time`)
+            ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT '5���������������'
+    </update>
+
+    <insert id="insertHistoryFiveMinutely">
+        INSERT INTO
+        history_five_minutely_${timeUnits}
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{item.mac}, #{item.time}, #{item.value})
+        </foreach>
+    </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/screen-job/src/main/resources/mapper/HistoryMinutelyMapper.xml b/screen-job/src/main/resources/mapper/HistoryMinutelyMapper.xml
new file mode 100644
index 0000000..d705dd2
--- /dev/null
+++ b/screen-job/src/main/resources/mapper/HistoryMinutelyMapper.xml
@@ -0,0 +1,50 @@
+<?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.moral.api.mapper.HistoryMinutelyMapper">
+
+    <update id="createTable" parameterType="String">
+        CREATE TABLE  IF NOT EXISTS `history_minutely_${timeUnits}` (
+            `mac` VARCHAR (20) DEFAULT NULL COMMENT '������mac',
+            `time` datetime DEFAULT NULL COMMENT '������������',
+            `value` json DEFAULT NULL COMMENT '������',
+            `version` INT (11) DEFAULT NULL COMMENT '������',
+            KEY `idx_mac` (`mac`),
+            KEY `idx_time` (`time`),
+            KEY `idx_mac_time` (`mac`,`time`)
+            ) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT '���������������'
+    </update>
+
+    <select id="getHistoryFiveMinutelyData" resultType="java.util.LinkedHashMap">
+        SELECT
+        mac
+        <foreach collection="sensorKeys" open="," separator="," item="sensorKey">
+            <choose>
+                <when test="sensorKey=='e23[0]'">
+                    ROUND((CASE WHEN AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))<![CDATA[>]]>0 AND
+                    AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI()))<![CDATA[>]]>0
+                    THEN
+                    ATAN(AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))/AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI())))*180/PI()
+                    WHEN AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))>0 AND
+                    AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI()))<![CDATA[<]]>0
+                    THEN
+                    (ATAN(AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))/AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI())))*180/PI())+180
+                    WHEN AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))<![CDATA[<]]>0 AND
+                    AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI()))<![CDATA[<]]>0
+                    THEN
+                    (ATAN(AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))/AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI())))*180/PI())+180
+                    ELSE
+                    (ATAN(AVG(value->'$.e18[0]'*SIN((value->'$.e23[0]'/180)*PI()))/AVG(value->'$.e18[0]'*COS((value->'$.e23[0]'/180)*PI())))*180/PI())+360
+                    END),3) AS '${sensorKey}'
+                </when>
+                <otherwise>
+                    ROUND(AVG(value->'$.${sensorKey}[0]'),3) AS '${sensorKey}'
+                </otherwise>
+            </choose>
+        </foreach>
+        FROM
+        history_minutely_${timeUnits}
+        WHERE time <![CDATA[>=]]> #{start} AND time <![CDATA[<]]> #{end}
+        GROUP BY mac
+    </select>
+
+</mapper>
\ No newline at end of file
diff --git a/screen-manage/src/main/java/com/moral/api/config/kafka/KafkaConsumerConfig.java b/screen-manage/src/main/java/com/moral/api/config/kafka/KafkaConsumerConfig.java
index 9d983d0..4d6652a 100644
--- a/screen-manage/src/main/java/com/moral/api/config/kafka/KafkaConsumerConfig.java
+++ b/screen-manage/src/main/java/com/moral/api/config/kafka/KafkaConsumerConfig.java
@@ -2,7 +2,6 @@
 
 import org.apache.kafka.clients.consumer.ConsumerConfig;
 import org.apache.kafka.common.serialization.StringDeserializer;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -13,6 +12,7 @@
 import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
 import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
 import org.springframework.kafka.listener.ContainerProperties;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -27,8 +27,6 @@
     private String sessionTimeout;
     @Value("${kafka.consumer.auto.commit.interval}")
     private String autoCommitInterval;
-    @Value("${kafka.consumer.groupMenu.id}")
-    private String groupId;
     @Value("${kafka.consumer.auto.offset.reset}")
     private String autoOffsetReset;
     @Value("${kafka.consumer.concurrency}")
@@ -41,16 +39,12 @@
         factory.setConcurrency(concurrency);
         factory.getContainerProperties().setPollTimeout(1500);
         factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
-
-        /*factory.setBatchListener(true);//@KafkaListener ������������  ���������������������Kafka���������������������ConsumerConfig.MAX_POLL_RECORDS_CONFIG
-        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);//������������������������������*/
         return factory;
     }
 
     public ConsumerFactory<String, String> consumerFactory() {
         return new DefaultKafkaConsumerFactory<>(consumerConfigs());
     }
-
 
     public Map<String, Object> consumerConfigs() {
         Map<String, Object> propsMap = new HashMap<>();
@@ -60,7 +54,6 @@
         propsMap.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, sessionTimeout);
         propsMap.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
         propsMap.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
-        propsMap.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
         propsMap.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, autoOffsetReset);
         return propsMap;
     }
diff --git a/screen-manage/src/main/java/com/moral/api/controller/DeviceController.java b/screen-manage/src/main/java/com/moral/api/controller/DeviceController.java
index 8b0f88e..bb495c8 100644
--- a/screen-manage/src/main/java/com/moral/api/controller/DeviceController.java
+++ b/screen-manage/src/main/java/com/moral/api/controller/DeviceController.java
@@ -56,7 +56,7 @@
         //������mac���������������
         QueryWrapper<Device> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("mac", device.getMac());
-        if (deviceService.getOne(queryWrapper) != null) {
+        if (deviceService.count(queryWrapper) > 0) {
             return ResultMessage.fail(ResponseCodeEnum.MAC_IS_EXIST.getCode(), ResponseCodeEnum.MAC_IS_EXIST.getMsg());
         }
         deviceService.insert(device);
diff --git a/screen-manage/src/main/java/com/moral/api/controller/TestController.java b/screen-manage/src/main/java/com/moral/api/controller/TestController.java
index 3cb3911..81bb874 100644
--- a/screen-manage/src/main/java/com/moral/api/controller/TestController.java
+++ b/screen-manage/src/main/java/com/moral/api/controller/TestController.java
@@ -4,6 +4,7 @@
 import com.moral.api.entity.Test;
 import com.moral.api.service.TestService;
 import com.moral.api.util.CacheUtils;
+import com.moral.constant.KafkaConstants;
 import com.moral.constant.ResultMessage;
 import com.moral.redis.RedisUtil;
 import com.moral.util.PageResult;
@@ -101,15 +102,31 @@
     }
 
     /**
-     * kafka������
+     * ������������kafka������
      */
     @ApiOperation(value = "kafka������", notes = "kafka������")
     @ApiImplicitParams({
+            @ApiImplicitParam(name = "data", value = "data", required = true, paramType = "query", dataType = "String"),
             @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header", dataType = "String")
     })
-    @RequestMapping(value = "kafkaTest", method = RequestMethod.GET)
-    public void kafkaTest() {
-        kafkaTemplate.send("test_topic", "{'mac': 'p5dnd1234567','DataTime':1623058244104,'e1':10,'e2':20,'ver':2}");
+    @RequestMapping(value = "minuteKafkaTest", method = RequestMethod.GET)
+    public void minuteKafkaTest(String data) {
+        System.out.println(data);
+        kafkaTemplate.send(KafkaConstants.TOPIC_MINUTE, data);
+    }
+
+    /**
+     * ������������kafka������
+     */
+    @ApiOperation(value = "kafka������", notes = "kafka������")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "data", value = "data", required = true, paramType = "query", dataType = "String"),
+            @ApiImplicitParam(name = "token", value = "token", required = true, paramType = "header", dataType = "String")
+    })
+    @RequestMapping(value = "hourKafkaTest", method = RequestMethod.GET)
+    public void hourKafkaTest(String data) {
+        System.out.println(data);
+        kafkaTemplate.send(KafkaConstants.TOPIC_HOUR, data);
     }
 
     @GetMapping("testToken")
diff --git a/screen-manage/src/main/java/com/moral/api/entity/HistoryHourly.java b/screen-manage/src/main/java/com/moral/api/entity/HistoryHourly.java
new file mode 100644
index 0000000..08c64b6
--- /dev/null
+++ b/screen-manage/src/main/java/com/moral/api/entity/HistoryHourly.java
@@ -0,0 +1,51 @@
+package com.moral.api.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * ������������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class HistoryHourly extends Model<HistoryHourly> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ������mac
+     */
+    private String mac;
+
+    /**
+     * ������������
+     */
+    private Date time;
+
+    /**
+     * ������
+     */
+    private String value;
+
+    /**
+     * ������
+     */
+    private Integer version;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return null;
+    }
+
+}
diff --git a/screen-manage/src/main/java/com/moral/api/kafka/consumer/KafkaConsumer.java b/screen-manage/src/main/java/com/moral/api/kafka/consumer/KafkaConsumer.java
index af6c8cc..cc98e98 100644
--- a/screen-manage/src/main/java/com/moral/api/kafka/consumer/KafkaConsumer.java
+++ b/screen-manage/src/main/java/com/moral/api/kafka/consumer/KafkaConsumer.java
@@ -1,37 +1,128 @@
 package com.moral.api.kafka.consumer;
 
-import com.moral.api.constant.TopicConstants;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.kafka.annotation.KafkaListener;
 import org.springframework.kafka.support.Acknowledgment;
 import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
 
-import java.util.Random;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
 
-@Component
+import com.alibaba.fastjson.JSON;
+import com.moral.api.service.DeviceService;
+import com.moral.api.service.HistoryHourlyService;
+import com.moral.api.service.HistoryMinutelyService;
+import com.moral.api.util.AdjustDataUtils;
+import com.moral.constant.KafkaConstants;
+import com.moral.constant.RedisConstants;
+
+//@Component
 @Slf4j
 public class KafkaConsumer {
 
-/*    *//**
-     * ���������������������������������
-     * @param record
-     * @param ack
-     * @throws Exception
-     *//*
-    @KafkaListener(topics = TopicConstants.TEST_TOPIC_MESSAGE,groupId = "test")
-    public void listenTest(ConsumerRecord<String, String> record , Acknowledgment ack) throws Exception {
+    @Autowired
+    private HistoryMinutelyService historyMinutelyService;
+
+    @Autowired
+    private HistoryHourlyService historyHourlyService;
+
+    @Autowired
+    private DeviceService deviceService;
+
+    @Autowired
+    private AdjustDataUtils adjustDataUtils;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    //������������
+    @KafkaListener(topics = KafkaConstants.TOPIC_MINUTE, groupId = KafkaConstants.GROUP_ID_INSERT, containerFactory = "kafkaListenerContainerFactory")
+    public void listenMinute(ConsumerRecord<String, String> record, Acknowledgment ack) {
         String msg = record.value();
-        System.out.println(msg);
-        if (new Random().nextInt(100)<50){
-            log.info(String.format("kafka ������������������---------------- listen1 topic = %s, offset = %d, value = %s ", record.topic(), record.offset(), record.value()));
+        try {
+            Map<String, Object> data = JSON.parseObject(msg, HashMap.class);
+            Object mac = data.get("mac");
+            Object time = data.get("DataTime");
+            Object ver = data.get("ver");
+            if (StringUtils.isEmpty(ver) || StringUtils.isEmpty(time) || StringUtils.isEmpty(mac)) {
+                log.warn("some properties is null, param{}", msg);
+                ack.acknowledge();
+                return;
+            }
+
+            //������������
+            data = data.entrySet().stream()
+                    .filter(map -> {
+                        String key = map.getKey();
+                        return !(key.contains("Min") || key.contains("Max") || key.contains("Cou"));
+                    }).collect(Collectors.toMap(m -> m.getKey().replaceAll("-Avg", ""), Map.Entry::getValue));
+            data.remove("time");
+            //���������������
+            historyMinutelyService.insertHistoryMinutely(data);
             ack.acknowledge();
+        } catch (Exception e) {
+            //log.error("param{}" + msg);
         }
+    }
 
-    }*/
+    //������������
+    @KafkaListener(topics = KafkaConstants.TOPIC_HOUR, groupId = KafkaConstants.GROUP_ID_INSERT, containerFactory = "kafkaListenerContainerFactory")
+    public void listenHour(ConsumerRecord<String, String> record, Acknowledgment ack) {
+        String msg = record.value();
+        try {
+            Map<String, Object> data = JSON.parseObject(msg, HashMap.class);
+            Object mac = data.get("mac");
+            Object time = data.get("DataTime");
+            Object ver = data.get("ver");
+            if (StringUtils.isEmpty(ver) || StringUtils.isEmpty(time) || StringUtils.isEmpty(mac)) {
+                log.warn("some properties is null, param{}", msg);
+                ack.acknowledge();
+                return;
+            }
 
+            //������������
+            data = data.entrySet().stream()
+                    .filter(map -> {
+                        String key = map.getKey();
+                        return !(key.contains("Min") || key.contains("Max") || key.contains("Cou"));
+                    }).collect(Collectors.toMap(m -> m.getKey().replaceAll("-Avg", ""), Map.Entry::getValue));
+            data.remove("time");
+            //���������������
+            historyHourlyService.insertHistoryHourly(data);
+            ack.acknowledge();
+        } catch (Exception e) {
+            //log.error("param{}" + msg);
+        }
+    }
 
-
-
-
+    //������������������������������������������������������
+    @KafkaListener(topics = KafkaConstants.TOPIC_SECOND, groupId = KafkaConstants.GROUP_ID_STATE, containerFactory = "kafkaListenerContainerFactory")
+    public void listenSecond(ConsumerRecord<String, String> record, Acknowledgment ack) {
+        String msg = record.value();
+        try {
+            Map<String, Object> data = JSON.parseObject(msg, HashMap.class);
+            Object mac = data.get("mac");
+            Object time = data.get("DataTime");
+            Object ver = data.get("ver");
+            if (StringUtils.isEmpty(ver) || StringUtils.isEmpty(time) || StringUtils.isEmpty(mac)) {
+                log.warn("some properties is null, param{}", msg);
+                ack.acknowledge();
+                return;
+            }
+            //������������
+            data = adjustDataUtils.adjust(data);
+            //������redis
+            redisTemplate.opsForValue().set(RedisConstants.DEVICE_DATA + "_" + mac, data);
+            //���������������������������
+            deviceService.judgeDeviceState(data);
+            ack.acknowledge();
+        } catch (Exception e) {
+            //log.error("param{}" + msg);
+        }
+    }
 }
diff --git a/screen-manage/src/main/java/com/moral/api/mapper/HistoryHourlyMapper.java b/screen-manage/src/main/java/com/moral/api/mapper/HistoryHourlyMapper.java
new file mode 100644
index 0000000..46898e3
--- /dev/null
+++ b/screen-manage/src/main/java/com/moral/api/mapper/HistoryHourlyMapper.java
@@ -0,0 +1,20 @@
+package com.moral.api.mapper;
+
+import java.util.Map;
+
+import com.moral.api.entity.HistoryHourly;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * ��������� Mapper ������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-04
+ */
+public interface HistoryHourlyMapper extends BaseMapper<HistoryHourly> {
+
+    void insertHistoryHourlyUnAdjust(Map<String, Object> params);
+
+}
diff --git a/screen-manage/src/main/java/com/moral/api/service/DeviceService.java b/screen-manage/src/main/java/com/moral/api/service/DeviceService.java
index 5fac936..0d3fa02 100644
--- a/screen-manage/src/main/java/com/moral/api/service/DeviceService.java
+++ b/screen-manage/src/main/java/com/moral/api/service/DeviceService.java
@@ -56,9 +56,9 @@
     Map<String, Object> getDeviceByMac(String mac);
 
     //������������������
-    Map<String, Object> adjustDeviceData(Map<String, Object> deviceData, Map<String, Object> deviceInfo);
+    Map<String, Object> adjustDeviceData(Map<String, Object> deviceData);
 
-    //���������������������������
-    Map<String, Object> judgeDeviceState(Map<String, Object> data, Map<String, Object> deviceInfo);
+    //���������������������������
+    void judgeDeviceState(Map<String, Object> data);
 
 }
diff --git a/screen-manage/src/main/java/com/moral/api/service/HistoryHourlyService.java b/screen-manage/src/main/java/com/moral/api/service/HistoryHourlyService.java
new file mode 100644
index 0000000..1a5a63e
--- /dev/null
+++ b/screen-manage/src/main/java/com/moral/api/service/HistoryHourlyService.java
@@ -0,0 +1,20 @@
+package com.moral.api.service;
+
+import java.util.Map;
+
+import com.moral.api.entity.HistoryHourly;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * ��������� ���������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-04
+ */
+public interface HistoryHourlyService extends IService<HistoryHourly> {
+
+    void insertHistoryHourly(Map<String, Object> data);
+
+}
diff --git a/screen-manage/src/main/java/com/moral/api/service/HistoryMinutelyService.java b/screen-manage/src/main/java/com/moral/api/service/HistoryMinutelyService.java
index 4834d08..91c4fa6 100644
--- a/screen-manage/src/main/java/com/moral/api/service/HistoryMinutelyService.java
+++ b/screen-manage/src/main/java/com/moral/api/service/HistoryMinutelyService.java
@@ -13,6 +13,6 @@
  */
 public interface HistoryMinutelyService {
 
-    void insertHistoryMinutely(Map<String, Object> deviceData);
+    void insertHistoryMinutely(Map<String, Object> data);
 
 }
diff --git a/screen-manage/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java b/screen-manage/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java
index 9e06f36..c1b48df 100644
--- a/screen-manage/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java
+++ b/screen-manage/src/main/java/com/moral/api/service/impl/DeviceServiceImpl.java
@@ -1,26 +1,31 @@
 package com.moral.api.service.impl;
 
-import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.Expression;
 import com.moral.api.entity.*;
 import com.moral.api.mapper.*;
 import com.moral.api.pojo.vo.device.DeviceVO;
 import com.moral.api.service.DeviceService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 
+import com.moral.api.util.AdjustDataUtils;
 import com.moral.api.util.LogUtils;
 import com.moral.constant.Constants;
 import com.moral.constant.RedisConstants;
 import com.moral.util.ConvertUtils;
 import com.moral.util.DateUtils;
 
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
@@ -28,10 +33,12 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -44,6 +51,7 @@
  * @since 2021-05-11
  */
 @Service
+@Slf4j
 public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {
 
     @Autowired
@@ -76,13 +84,14 @@
     @Autowired
     private VersionSensorUnitMapper versionSensorUnitMapper;
 
-
+    @Autowired
+    private AdjustDataUtils adjustDataUtils;
 
     /*
      * ���redis������������������
      * */
     private Map<String, Object> getDeviceInfoFromRedis(String mac) {
-        Map<String, Object> deviceInfo = (Map<String, Object>) redisTemplate.opsForValue().get(RedisConstants.DEVICE + mac);
+        Map<String, Object> deviceInfo = (Map<String, Object>) redisTemplate.opsForValue().get(getDeviceKey(mac));
         return deviceInfo;
     }
 
@@ -107,6 +116,13 @@
         return keysConnect(RedisConstants.DEVICE, mac);
     }
 
+    /*
+     * ���redis������������������
+     * */
+    private Map<String, Object> getOrgAlarmConfigFromRedis(String orId) {
+        return null;
+    }
+
     //redis key������
     private String keysConnect(String... keys) {
         StringBuilder key = new StringBuilder(keys[0]);
@@ -125,7 +141,7 @@
         deviceMapper.insert(device);
         Map<String, Object> deviceInfo = selectDeviceInfoById(device.getId());
         //���������������������������
-        insertOrganizationUnitAlarm(orgId,device.getDeviceVersionId());
+        insertOrganizationUnitAlarm(orgId, device.getDeviceVersionId());
         //������������������������redis
         String mac = device.getMac();
         //���redis���������������������
@@ -142,17 +158,13 @@
     @Override
     @Transactional
     public void delete(Integer deviceId) {
+        Device device = deviceMapper.selectById(deviceId);
         UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
         updateWrapper.eq("id", deviceId).set("is_delete", Constants.DELETE);
         deviceMapper.update(null, updateWrapper);
-        Device device = deviceMapper.selectById(deviceId);
         String mac = device.getMac();
         //���redis���������������������
         delDeviceInfoFromRedis(mac);
-        //���������������������������
-        Integer versionId = device.getDeviceVersionId();
-        Integer orgId = device.getOrganizationId();
-        deleteOrganizationUnitAlarm(orgId,versionId);
         //������������������
         HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
         StringBuilder content = new StringBuilder();
@@ -166,7 +178,7 @@
         Integer deviceId = device.getId();
         Device oldDevice = deviceMapper.selectById(deviceId);
         //���������������������������������������������������������������������������������id������������
-        if(!ObjectUtils.isEmpty(device.getMonitorPointId())){
+        if (!ObjectUtils.isEmpty(device.getMonitorPointId())) {
             MonitorPoint monitorPoint = monitorPointMapper.selectById(device.getMonitorPointId());
             device.setOrganizationId(monitorPoint.getOrganizationId());
         }
@@ -174,14 +186,14 @@
         Device updateDevice = deviceMapper.selectById(deviceId);
         String mac = updateDevice.getMac();
         //���������������������������
-       Integer oldOrgId = oldDevice.getOrganizationId();
-       Integer newOrgId = updateDevice.getOrganizationId();
-       Integer oldVersionId = oldDevice.getDeviceVersionId();
-       Integer newVersionId = updateDevice.getDeviceVersionId();
-       if(!oldOrgId.equals(newOrgId)||!oldVersionId.equals(newVersionId)){
-           deleteOrganizationUnitAlarm(oldOrgId,oldVersionId);
-           insertOrganizationUnitAlarm(newOrgId,newVersionId);
-       }
+        Integer oldOrgId = oldDevice.getOrganizationId();
+        Integer newOrgId = updateDevice.getOrganizationId();
+        Integer oldVersionId = oldDevice.getDeviceVersionId();
+        Integer newVersionId = updateDevice.getDeviceVersionId();
+        if (!oldOrgId.equals(newOrgId) || !oldVersionId.equals(newVersionId)) {
+            deleteOrganizationUnitAlarm(oldOrgId, oldVersionId);
+            insertOrganizationUnitAlarm(newOrgId, newVersionId);
+        }
         //���redis���������������������
         delDeviceInfoFromRedis(mac);
         Map<String, Object> deviceInfo = selectDeviceInfoById(deviceId);
@@ -276,13 +288,15 @@
             queryWrapper.eq("monitor_point_id", mpId);
         }
 
+        //���������������������
         if (name != null) {
             queryWrapper.like("name", name);
         }
+
+        //mac������������
         if (mac != null) {
             queryWrapper.like("mac", mac);
         }
-
 
         //������������,������create_time������
         if (order != null && orderType != null) {
@@ -311,7 +325,6 @@
         result.put("item", items);
         return result;
     }
-
 
     @Override
     public Map<String, Object> selectDeviceInfoById(Integer deviceId) {
@@ -382,6 +395,9 @@
         MonitorPoint monitorPoint = device.getMonitorPoint();
         mpInfo.put("id", monitorPoint.getId());
         mpInfo.put("name", monitorPoint.getName());
+        mpInfo.put("areaCode", monitorPoint.getAreaCode());
+        mpInfo.put("cityCode", monitorPoint.getCityCode());
+        mpInfo.put("provinceCode", monitorPoint.getProvinceCode());
         deviceInfo.put("monitorPoint", mpInfo);
 
         setDeviceInfoToRedis(mac, deviceInfo);
@@ -418,27 +434,74 @@
     }
 
     @Override
-    public Map<String, Object> adjustDeviceData(Map<String, Object> deviceData, Map<String, Object> deviceInfo) {
-        return null;
+    public Map<String, Object> adjustDeviceData(Map<String, Object> deviceData) {
+        return adjustDataUtils.adjust(deviceData);
     }
 
     @Override
-    public Map<String, Object> judgeDeviceState(Map<String, Object> deviceData, Map<String, Object> deviceInfo) {
-        return null;
+    public void judgeDeviceState(Map<String, Object> deviceData) {
+        String mac = deviceData.remove("mac").toString();
+        Device device = (Device) redisTemplate.opsForHash().get(RedisConstants.DEVICE_INFO, mac);
+        Version version = device.getVersion();
+        List<Sensor> sensors = version.getSensors();
+        Expression expression;
+        int state = 1;
+        for (Sensor sensor : sensors) {
+            //������������������
+            String alarmLevel = sensor.getAlarmLevel();
+            if (StringUtils.isEmpty(alarmLevel)) {
+                continue;
+            }
+            List<Double> list = JSONObject.parseObject(alarmLevel, List.class);
+            String sensorCode = sensor.getCode();
+            //������������
+            String formula = sensor.getFormula();
+            //������������������������
+            String sensorValue = (String) deviceData.get(sensorCode);
+            double value = Double.parseDouble(String.format("%.3f", sensorValue));
+            //������������
+            if (formula != null) {
+                //������������������
+                sensorValue = formula.replace("{0}", sensorValue);
+                expression = AviatorEvaluator.compile(sensorValue);
+                value = Double.parseDouble(String.format("%.3f", expression.execute()));
+            }
+            int sensorState = judgeState(list, value);
+            if (sensorState > state) {
+                state = sensorState;
+            }
+        }
+        //������������������
+        UpdateWrapper<Device> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("id", device.getId()).set("state", state);
+        deviceMapper.update(null, updateWrapper);
     }
 
-    private void insertOrganizationUnitAlarm(Integer orgId,Integer versionId){
+    //���������������������������
+    private int judgeState(List<Double> levels, Double data) {
+        int state = 1;
+        for (int i = levels.size() - 1; i >= 0; i--) {
+            Double level = levels.get(i);
+            if (data >= level) {
+                state = i + 2;
+                break;
+            }
+        }
+        return state;
+    }
+
+    private void insertOrganizationUnitAlarm(Integer orgId, Integer versionId) {
         QueryWrapper<OrganizationUnitAlarm> queryOrganizationVersionWrapper = new QueryWrapper<>();
-        queryOrganizationVersionWrapper.eq("organization_id",orgId);
-        queryOrganizationVersionWrapper.eq("version_id",versionId);
-        queryOrganizationVersionWrapper.eq("is_delete",Constants.NOT_DELETE);
+        queryOrganizationVersionWrapper.eq("organization_id", orgId);
+        queryOrganizationVersionWrapper.eq("version_id", versionId);
+        queryOrganizationVersionWrapper.eq("is_delete", Constants.NOT_DELETE);
         List<OrganizationUnitAlarm> organizationUnitAlarms = organizationUnitAlarmMapper.selectList(queryOrganizationVersionWrapper);
-        if(ObjectUtils.isEmpty(organizationUnitAlarms)){
-            QueryWrapper<VersionSensorUnit> queryVersionSensorUnitWrapper =new QueryWrapper<>();
-            queryVersionSensorUnitWrapper.eq("version_id",versionId);
-            queryVersionSensorUnitWrapper.eq("is_delete",Constants.NOT_DELETE);
+        if (ObjectUtils.isEmpty(organizationUnitAlarms)) {
+            QueryWrapper<VersionSensorUnit> queryVersionSensorUnitWrapper = new QueryWrapper<>();
+            queryVersionSensorUnitWrapper.eq("version_id", versionId);
+            queryVersionSensorUnitWrapper.eq("is_delete", Constants.NOT_DELETE);
             List<VersionSensorUnit> versionSensorUnits = versionSensorUnitMapper.selectList(queryVersionSensorUnitWrapper);
-            if(!ObjectUtils.isEmpty(versionSensorUnits)){
+            if (!ObjectUtils.isEmpty(versionSensorUnits)) {
                 for (VersionSensorUnit versionSensorUnit : versionSensorUnits) {
                     OrganizationUnitAlarm organizationUnitAlarm = new OrganizationUnitAlarm();
                     organizationUnitAlarm.setOrganizationId(orgId);
@@ -452,19 +515,19 @@
         }
     }
 
-    private void deleteOrganizationUnitAlarm(Integer orgId,Integer versionId){
+    private void deleteOrganizationUnitAlarm(Integer orgId, Integer versionId) {
         QueryWrapper<Device> queryOrganizationVersionWrapper = new QueryWrapper<>();
-        queryOrganizationVersionWrapper.eq("organization_id",orgId);
-        queryOrganizationVersionWrapper.eq("device_version_id",versionId);
-        queryOrganizationVersionWrapper.eq("is_delete",Constants.NOT_DELETE);
+        queryOrganizationVersionWrapper.eq("organization_id", orgId);
+        queryOrganizationVersionWrapper.eq("device_version_id", versionId);
+        queryOrganizationVersionWrapper.eq("is_delete", Constants.NOT_DELETE);
         List<Device> devices = deviceMapper.selectList(queryOrganizationVersionWrapper);
-        if(ObjectUtils.isEmpty(devices)){//������������������������������������������������������
+        if (ObjectUtils.isEmpty(devices)) {//������������������������������������������������������
             UpdateWrapper deleteWrapper = new UpdateWrapper();
-            deleteWrapper.eq("organization_id",orgId);
-            deleteWrapper.eq("version_id",versionId);
-            deleteWrapper.eq("is_delete",Constants.NOT_DELETE);
-            deleteWrapper.set("is_delete",Constants.DELETE);
-            organizationUnitAlarmMapper.update(null,deleteWrapper);
+            deleteWrapper.eq("organization_id", orgId);
+            deleteWrapper.eq("version_id", versionId);
+            deleteWrapper.eq("is_delete", Constants.NOT_DELETE);
+            deleteWrapper.set("is_delete", Constants.DELETE);
+            organizationUnitAlarmMapper.update(null, deleteWrapper);
         }
     }
 }
diff --git a/screen-manage/src/main/java/com/moral/api/service/impl/HistoryHourlyServiceImpl.java b/screen-manage/src/main/java/com/moral/api/service/impl/HistoryHourlyServiceImpl.java
new file mode 100644
index 0000000..26598b6
--- /dev/null
+++ b/screen-manage/src/main/java/com/moral/api/service/impl/HistoryHourlyServiceImpl.java
@@ -0,0 +1,63 @@
+package com.moral.api.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.moral.api.entity.HistoryHourly;
+import com.moral.api.mapper.HistoryHourlyMapper;
+import com.moral.api.service.DeviceService;
+import com.moral.api.service.HistoryHourlyService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.moral.constant.Constants;
+import com.moral.util.DateUtils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * ��������� ���������������
+ * </p>
+ *
+ * @author moral
+ * @since 2021-06-04
+ */
+@Service
+public class HistoryHourlyServiceImpl extends ServiceImpl<HistoryHourlyMapper, HistoryHourly> implements HistoryHourlyService {
+
+    @Autowired
+    private HistoryHourlyMapper historyHourlyMapper;
+
+    @Autowired
+    private DeviceService deviceService;
+
+    @Override
+    public void insertHistoryHourly(Map<String, Object> data) {
+        Map<String, Object> dataAdjust = new HashMap<>(data);
+        String mac = data.remove("mac").toString();
+        Date time = DateUtils.dataToTimeStampTime(new Date(new Long((String) data.remove("DataTime"))), DateUtils.yyyy_MM_dd_HH_EN);
+        Integer version = (Integer) data.remove("ver");
+        Map<String, Object> result = new HashMap<>(data);
+        result.put("mac", mac);
+        result.put("time", time);
+        result.put("version", version);
+        result.put("timeUnits", Constants.UN_ADJUST);
+        result.put("value", JSONObject.toJSONString(data));
+        //���������������������������
+        historyHourlyMapper.insertHistoryHourlyUnAdjust(result);
+
+        //������������
+        dataAdjust = deviceService.adjustDeviceData(dataAdjust);
+        dataAdjust.remove("mac");
+        dataAdjust.remove("DataTime");
+        dataAdjust.remove("ver");
+        HistoryHourly historyHourly = new HistoryHourly();
+        historyHourly.setMac(mac);
+        historyHourly.setTime(time);
+        historyHourly.setVersion(version);
+        historyHourly.setValue(JSONObject.toJSONString(dataAdjust));
+        historyHourlyMapper.insert(historyHourly);
+    }
+}
diff --git a/screen-manage/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java b/screen-manage/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java
index 6df638c..9360a70 100644
--- a/screen-manage/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java
+++ b/screen-manage/src/main/java/com/moral/api/service/impl/HistoryMinutelyServiceImpl.java
@@ -7,7 +7,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.moral.api.mapper.HistoryMinutelyMapper;
 import com.moral.api.service.DeviceService;
 import com.moral.api.service.HistoryMinutelyService;
@@ -24,30 +24,31 @@
     private DeviceService deviceService;
 
     @Override
-    public void insertHistoryMinutely(Map<String, Object> deviceData) {
+    public void insertHistoryMinutely(Map<String, Object> data) {
         Map<String, Object> result = new HashMap<>();
-        Object mac = deviceData.remove("mac");
+        Map<String, Object> dataAdjust = new HashMap<>(data);
+        Object mac = data.remove("mac");
         result.put("mac", mac);
-        result.put("version", deviceData.remove("ver"));
-        Date time = new Date((Long) deviceData.remove("DataTime"));
-        result.put("time", DateUtils.dateToDateString(time));
-        result.put("value", JSON.toJSONString(deviceData));
+        result.put("version", data.remove("ver"));
+        Date time = new Date(new Long((String) data.remove("DataTime")));
+        result.put("time", DateUtils.dataToTimeStampTime(time,DateUtils.yyyy_MM_dd_HH_mm_EN));
+        result.put("value", JSONObject.toJSONString(data));
         String timeUnits = DateUtils.dateToDateString(time, DateUtils.yyyyMM_EN);
         result.put("timeUnits", tableSuffix(timeUnits, Constants.UN_ADJUST));
-        //���������
+
+        //���������������������������
         historyMinutelyMapper.insertHistoryMinutely(result);
 
-        //������������
-        Map<String, Object> deviceInfo = deviceService.getDeviceByMac(mac.toString());
-
-        //���������������������������������������
+        //������������
+        dataAdjust = deviceService.adjustDeviceData(dataAdjust);
+        dataAdjust.remove("mac");
+        dataAdjust.remove("DataTime");
+        dataAdjust.remove("ver");
         result.put("timeUnits", timeUnits);
-        deviceData = deviceService.adjustDeviceData(deviceData, deviceInfo);
-        result.put("value", JSON.toJSONString(deviceData));
+        result.put("value", JSONObject.toJSONString(dataAdjust));
         historyMinutelyMapper.insertHistoryMinutely(result);
 
-        //������������������
-        Map<String, Object> deviceState = deviceService.judgeDeviceState(deviceData, deviceInfo);
+
     }
 
     //���������
@@ -59,5 +60,4 @@
         }
         return key.toString();
     }
-
 }
diff --git a/screen-manage/src/main/java/com/moral/api/util/AdjustDataUtils.java b/screen-manage/src/main/java/com/moral/api/util/AdjustDataUtils.java
new file mode 100644
index 0000000..36fdf60
--- /dev/null
+++ b/screen-manage/src/main/java/com/moral/api/util/AdjustDataUtils.java
@@ -0,0 +1,97 @@
+package com.moral.api.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.fastjson.JSON;
+import com.googlecode.aviator.AviatorEvaluator;
+import com.googlecode.aviator.Expression;
+import com.moral.api.entity.DeviceAdjustValue;
+import com.moral.api.service.DeviceService;
+import com.moral.constant.RedisConstants;
+import com.moral.util.DateUtils;
+
+@Slf4j
+@Component
+public class AdjustDataUtils {
+
+    @Autowired
+    private DeviceService deviceService;
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    public Map<String, Object> adjust(Map<String, Object> deviceData) {
+        try {
+            Object dataTime = deviceData.get("DataTime");
+            String mac = deviceData.get("mac").toString();
+            //���������������������������
+            long time = Math.round(new Double((String) dataTime) / 1000) * 1000L;
+            long finalTime = DateUtils.dataToTimeStampTime(new Date(time), DateUtils.HH_mm_ss_EN).getTime();
+            //������������
+            Map<String, Object> deviceInfo = deviceService.getDeviceByMac(mac);
+            Map<String, Object> monitorPoint = (Map<String, Object>) deviceInfo.get("monitorPoint");
+            Object areaCode = monitorPoint.get("areaCode");
+            Object cityCode = monitorPoint.get("cityCode");
+            for (String key : deviceData.keySet()) {
+                if (!key.equals("mac") && !key.equals("time") && !key.equals("DataTime") && !key.equals("ver") && !key.contains("Flag")) {
+                    //���������
+                    Object measuredValue = deviceData.get(key);
+                    List<DeviceAdjustValue> adjustValues = (List<DeviceAdjustValue>) redisTemplate.opsForHash().get(RedisConstants.ADJUST + "_" + mac, key);
+                    if (ObjectUtils.isEmpty(adjustValues)) {
+                        deviceData.put(key, measuredValue);
+                        continue;
+                    }
+
+                    //���������������������������������
+                    DeviceAdjustValue deviceAdjustValue = adjustValues.stream()
+                            .filter(o -> o.getStartTime().getTime() <= finalTime && o.getEndTime().getTime() > finalTime)
+                            .findFirst().get();
+                    String adjustValue = deviceAdjustValue.getValue();
+                    if (ObjectUtils.isEmpty(adjustValue)) {
+                        deviceData.put(key, measuredValue);
+                        continue;
+                    }
+
+                    Expression expression = AviatorEvaluator.compile(adjustValue);
+                    Map<String, Object> env = new HashMap<>();
+                    if (adjustValue.contains("aqi")) {
+                        Object aqiValue = redisTemplate.opsForHash().get("aqi_" + areaCode, key);
+                        if (ObjectUtils.isEmpty(aqiValue)) {
+                            aqiValue = redisTemplate.opsForHash().get("aqi_" + cityCode, key);
+                        }
+                        env.put("aqi", ObjectUtils.isEmpty(aqiValue) ? 0F : Float.parseFloat((String) aqiValue));
+                    }
+                    if (adjustValue.contains("vocs")) {
+                        Object vocsValue = ObjectUtils.isEmpty(deviceData.get("a99054")) ? 0F : deviceData.get("a99054");
+                        env.put("vocs", vocsValue);
+                    }
+                    if (adjustValue.contains("cel")) {
+                        env.put("cel", Float.parseFloat((String) measuredValue));
+                    }
+                    //������
+                    measuredValue = expression.execute(env);
+                    //������������
+                    if (Float.parseFloat(measuredValue.toString()) < 0 && !"a01001".equals(measuredValue)) {
+                        measuredValue = 0F;
+                    }
+                    deviceData.put(key, Double.parseDouble(String.format("%.3f", measuredValue)));
+
+                }
+            }
+        } catch (Exception e) {
+            log.error("param[0] deviceData:" + JSON.toJSONString(deviceData));
+            log.error(e.getMessage());
+        }
+        return deviceData;
+    }
+
+}
diff --git a/screen-manage/src/main/resources/application-dev.yml b/screen-manage/src/main/resources/application-dev.yml
index 4a6899a..e81262e 100644
--- a/screen-manage/src/main/resources/application-dev.yml
+++ b/screen-manage/src/main/resources/application-dev.yml
@@ -92,12 +92,9 @@
     enable:
       auto:
         commit: false
-    group:
-      id: test
     servers: 192.168.0.16:9092,192.168.0.17:9092,192.168.0.18:9092
     session:
       timeout: 6000
-    topic: test_topic
     zookeeper:
       connect: 192.168.0.16:2181,192.168.0.17:2181,192.168.0.18:2181
   producer:
diff --git a/screen-manage/src/main/resources/mapper/DeviceMapper.xml b/screen-manage/src/main/resources/mapper/DeviceMapper.xml
index 6e7f549..d1c0809 100644
--- a/screen-manage/src/main/resources/mapper/DeviceMapper.xml
+++ b/screen-manage/src/main/resources/mapper/DeviceMapper.xml
@@ -49,7 +49,9 @@
         <association property="monitorPoint" javaType="com.moral.api.entity.MonitorPoint">
             <result column="mp_id" property="id"/>
             <result column="mp_name" property="name"/>
-            <result column="mp_address" property="address"/>
+            <result column="mp_area_code" property="areaCode"/>
+            <result column="mp_city_code" property="cityCode"/>
+            <result column="mp_province_code" property="provinceCode"/>
         </association>
 
         <!--������-->
@@ -116,7 +118,9 @@
             o.`name` org_name,
             mp.id mp_id,
             mp.`name` mp_name,
-            mp.address mp_address,
+            mp.area_code mp_area_code,
+            mp.city_code mp_city_code,
+            mp.province_code mp_province_code,
             ma.id operate_id,
             v.id version_id,
             v.`name` version_name,
diff --git a/screen-manage/src/main/resources/mapper/HistoryHourlyMapper.xml b/screen-manage/src/main/resources/mapper/HistoryHourlyMapper.xml
new file mode 100644
index 0000000..a2dde7f
--- /dev/null
+++ b/screen-manage/src/main/resources/mapper/HistoryHourlyMapper.xml
@@ -0,0 +1,17 @@
+<?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.moral.api.mapper.HistoryHourlyMapper">
+
+    <!-- ������������������������ -->
+    <resultMap id="BaseResultMap" type="com.moral.api.entity.HistoryHourly">
+        <result column="mac" property="mac"/>
+        <result column="time" property="time"/>
+        <result column="value" property="value"/>
+        <result column="version" property="version"/>
+    </resultMap>
+
+    <insert id="insertHistoryHourlyUnAdjust">
+        INSERT INTO history_hourly_${timeUnits} VALUES (#{mac}, #{time}, #{value}, #{version})
+    </insert>
+
+</mapper>
\ No newline at end of file

--
Gitblit v1.8.0