2 files deleted
	
		
		41 files added
	
		
		19 files modified
	
	
 
	
	
	
	
	
	
	
	
 |  |  | 
 |  |  | spring: | 
 |  |  |   profiles: | 
 |  |  |     active: dev | 
 |  |  |     include: | 
 |  |  |       moduleFormColumn | 
 |  |  |   application: | 
 |  |  |     name: screen-manage | 
 |  |  |   redis: | 
 |  |  | 
 |  |  |     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 | 
 |  |  | 
 |  |  |       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: | 
 
 |  |  | 
 |  |  |         <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} | 
 
 |  |  | 
 |  |  | <!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> | 
 
 |  |  | 
 |  |  |     </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} | 
 |  |  | 
 |  |  |     </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> | 
 
 |  |  | 
 |  |  |      * */ | 
 |  |  |     public static final String UN_ADJUST = "unadjust"; | 
 |  |  |  | 
 |  |  |     /* | 
 |  |  |      * 离线设备状态码 | 
 |  |  |      * */ | 
 |  |  |     public static final String DEVICE_STATE_OFFLINE = "4"; | 
 |  |  |  | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  |     /** | 
 |  |  |      * 分钟数据主题 | 
 |  |  |      */ | 
 |  |  |     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"; | 
 |  |  | } | 
 
 |  |  | 
 |  |  |     * 接收类型: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"; | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  |      * 日期格式(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缓存 | 
 |  |  |      */ | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |     * @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); | 
 |  |  | 
 |  |  |         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()); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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(); | 
 |  |  |      */ | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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> { | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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> { | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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> { | 
 |  |  |  | 
 |  |  | } | 
 |  |  |  | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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(); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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(); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | package com.moral.api.service; | 
 |  |  |  | 
 |  |  | public interface HistoryFiveMinutelyService { | 
 |  |  |  | 
 |  |  |     void createTable(String timeUnits); | 
 |  |  |  | 
 |  |  |     void insertHistoryFiveMinutely(); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  | } | 
 
 |  |  | 
 |  |  |  | 
 |  |  | logging: | 
 |  |  |   config: classpath:logback.xml | 
 |  |  |  | 
 |  |  | xxl: | 
 |  |  |   job: | 
 |  |  |     admin: | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
| New file | 
 |  |  | 
 |  |  | <?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> | 
 
 |  |  | 
 |  |  |  | 
 |  |  | 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; | 
 |  |  | 
 |  |  | 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; | 
 |  |  |  | 
 |  |  | 
 |  |  |     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}") | 
 |  |  | 
 |  |  |         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<>(); | 
 |  |  | 
 |  |  |         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; | 
 |  |  |     } | 
 
 |  |  | 
 |  |  |         //判断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); | 
 
 |  |  | 
 |  |  | 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; | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 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") | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  | 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); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  |     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); | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  |  */ | 
 |  |  | public interface HistoryMinutelyService { | 
 |  |  |  | 
 |  |  |     void insertHistoryMinutely(Map<String, Object> deviceData); | 
 |  |  |     void insertHistoryMinutely(Map<String, Object> data); | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  | 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; | 
 |  |  |  | 
 |  |  | 
 |  |  | 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; | 
 |  |  |  | 
 |  |  | 
 |  |  |  * @since 2021-05-11 | 
 |  |  |  */ | 
 |  |  | @Service | 
 |  |  | @Slf4j | 
 |  |  | public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService { | 
 |  |  |  | 
 |  |  |     @Autowired | 
 |  |  | 
 |  |  |     @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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | 
 |  |  |         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]); | 
 |  |  | 
 |  |  |         deviceMapper.insert(device); | 
 |  |  |         Map<String, Object> deviceInfo = selectDeviceInfoById(device.getId()); | 
 |  |  |         //维护组织型号关系表 | 
 |  |  |         insertOrganizationUnitAlarm(orgId,device.getDeviceVersionId()); | 
 |  |  |         insertOrganizationUnitAlarm(orgId, device.getDeviceVersionId()); | 
 |  |  |         //新增设备信息存入redis | 
 |  |  |         String mac = device.getMac(); | 
 |  |  |         //从redis中删除设备信息 | 
 |  |  | 
 |  |  |     @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(); | 
 |  |  | 
 |  |  |         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()); | 
 |  |  |         } | 
 |  |  | 
 |  |  |         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); | 
 |  |  | 
 |  |  |             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) { | 
 |  |  | 
 |  |  |         result.put("item", items); | 
 |  |  |         return result; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     @Override | 
 |  |  |     public Map<String, Object> selectDeviceInfoById(Integer deviceId) { | 
 |  |  | 
 |  |  |         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); | 
 |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     @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); | 
 |  |  | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     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); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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); | 
 |  |  |     } | 
 |  |  | } | 
 
 |  |  | 
 |  |  | 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; | 
 |  |  | 
 |  |  |     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); | 
 |  |  |  | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     //表后缀 | 
 |  |  | 
 |  |  |         } | 
 |  |  |         return key.toString(); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
| New file | 
 |  |  | 
 |  |  | 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; | 
 |  |  |     } | 
 |  |  |  | 
 |  |  | } | 
 
 |  |  | 
 |  |  |     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: | 
 
 |  |  | 
 |  |  |         <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> | 
 |  |  |  | 
 |  |  |         <!--型号--> | 
 |  |  | 
 |  |  |             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, | 
 
| New file | 
 |  |  | 
 |  |  | <?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> |