Commit bf6e293e authored by hanbing's avatar hanbing

运行信息接口-信号运行状态数据-订阅信号运行状态

parent e8a16e03
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
<collections.version>3.2.2</collections.version> <collections.version>3.2.2</collections.version>
<beanutils.version>1.9.4</beanutils.version> <beanutils.version>1.9.4</beanutils.version>
<httpclient.version>4.5.13</httpclient.version> <httpclient.version>4.5.13</httpclient.version>
<jedis.version>3.3.0</jedis.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
...@@ -141,6 +142,12 @@ ...@@ -141,6 +142,12 @@
<artifactId>httpclient</artifactId> <artifactId>httpclient</artifactId>
<version>${httpclient.version}</version> <version>${httpclient.version}</version>
</dependency> </dependency>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
......
...@@ -129,6 +129,11 @@ ...@@ -129,6 +129,11 @@
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId> <artifactId>httpclient</artifactId>
</dependency> </dependency>
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -12,7 +12,7 @@ import lombok.Data; ...@@ -12,7 +12,7 @@ import lombok.Data;
@ApiModel(value = "BaseCrossInfo", description = "查询信号路口基础信息输出参数") @ApiModel(value = "BaseCrossInfo", description = "查询信号路口基础信息输出参数")
public class BaseCrossInfo { public class BaseCrossInfo {
@ApiModelProperty(value = "信号机ID") @ApiModelProperty(value = "信号机ID")
private String telesemeId; private String code;
@ApiModelProperty(value = "厂商缩写") @ApiModelProperty(value = "厂商缩写")
private String manufacturerAbbr; private String manufacturerAbbr;
......
package net.wanji.utc.common.constant; package net.wanji.utc.common.constant;
import net.wanji.utc.po.ApiInfoPO; import net.wanji.utc.po.ApiInfoPO;
import net.wanji.utc.vo.CrossLanesVO;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class Constants { public class Constants {
...@@ -10,6 +12,11 @@ public class Constants { ...@@ -10,6 +12,11 @@ public class Constants {
*/ */
private static ConcurrentHashMap<String, ApiInfoPO> manufacturerUrlMap = new ConcurrentHashMap<>(); private static ConcurrentHashMap<String, ApiInfoPO> manufacturerUrlMap = new ConcurrentHashMap<>();
/**
* 海康信号机车道关系
*/
private static ConcurrentHashMap<String, List<CrossLanesVO>> telesemeLaneRealMap = new ConcurrentHashMap<>();
/** /**
* 系统缩写 * 系统缩写
*/ */
...@@ -21,6 +28,23 @@ public class Constants { ...@@ -21,6 +28,23 @@ public class Constants {
**/ **/
public static final String SEPARATOR_UNDER_LINE = "_"; public static final String SEPARATOR_UNDER_LINE = "_";
/**
* 分隔符:逗号
**/
public static final String SEPARATOR_COMMA = ",";
/**
* 分隔符:减号
**/
public static final String SEPARATOR_MINUS = "-";
/**
* 分隔符:冒号
**/
public static final String SEPARATOR_COLON = ":";
/** /**
* 海康返回成功码 * 海康返回成功码
*/ */
...@@ -37,4 +61,8 @@ public class Constants { ...@@ -37,4 +61,8 @@ public class Constants {
public static void putManufacturerUrlMap(String key, ApiInfoPO value) { public static void putManufacturerUrlMap(String key, ApiInfoPO value) {
manufacturerUrlMap.put(key, value); manufacturerUrlMap.put(key, value);
} }
public static ConcurrentHashMap<String, List<CrossLanesVO>> getTelesemeLaneRealMap() {
return telesemeLaneRealMap;
}
} }
\ No newline at end of file
package net.wanji.utc.common.constant;
public interface RedisKeyConst {
/**
* Redis存储Key前缀
*/
String KEY_PREFIX = "utcsystem_";
//token常量名称
String TOKEN = "qs_token";
//redis时段方案版本号
String SECTIM_VERSION = "sectim_version_";
//redis相位方案版本号
String PHASE_VERSION = "phase_version_";
//token存储Redis有效时长
int TOKEN_EXPIRE_TIME = 7200;
// 信号机状态
String TELESEME_STATUS = "teleseme_status";
// 告警
String ALARM = "alarm";
// 灯态
String LIGHTS_STATUS = "lights_status";
//信号机灯组方向信息
String CROSS_LIGHTS = "cross_lights";
//信号灯线圈车道
String CROSS_COIL_LANE = "cross_coil_lane";
//信号机列表
String SIGNAL_LIST = "signal_list";
//优化配置管理
String SET_OPT_CONFIG = "set_opt_config";
//最小绿时长
String MIN_GREEN_TIME = "min_green_time";
//最大绿时长
String MAX_GREEN_TIME = "max_green_time";
//绿信比是否下发
String IS_SEND = "is_send";
//绿信比优化时段
String OPT_TIME = "opt_time";
}
\ No newline at end of file
package net.wanji.utc.common.typeenum;
public enum DateStyle {
YYYY_MM("yyyy-MM", false),
YYYY_MM_DD("yyyy-MM-dd", false),
YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm", false),
YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss", false),
YYYYMMDDHHMMSS("yyyyMMddHHmmss", false),
YYYYMMDDHHMMSSSSS("yyyyMMddHHmmssSSS", false),
YYYYMMDD("yyyyMMdd", false),
YYYY_MM_EN("yyyy/MM", false),
YYYY_MM_DD_EN("yyyy/MM/dd", false),
YYYY_MM_DD_HH_MM_EN("yyyy/MM/dd HH:mm", false),
YYYY_MM_DD_HH_MM_SS_EN("yyyy/MM/dd HH:mm:ss", false),
DD_MM_YYYY_EN("dd/MM/yyyy", false),
YYYY_MM_CN("yyyy年MM月", false),
YYYY_MM_DD_CN("yyyy年MM月dd日", false),
YYYY_MM_DD_HH_MM_CN("yyyy年MM月dd日 HH:mm", false),
YYYY_MM_DD_HH_MM_SS_CN("yyyy年MM月dd日 HH:mm:ss", false),
HH_MM("HH:mm", true),
HH_MM_SS("HH:mm:ss", true),
MM_DD("MM-dd", true),
MM_DD_HH_MM("MM-dd HH:mm", true),
MM_DD_HH_MM_SS("MM-dd HH:mm:ss", true),
MM_DD_EN("MM/dd", true),
MM_DD_HH_MM_EN("MM/dd HH:mm", true),
MM_DD_HH_MM_SS_EN("MM/dd HH:mm:ss", true),
MM_DD_CN("MM月dd日", true),
MM_DD_HH_MM_CN("MM月dd日 HH:mm", true),
MM_DD_HH_MM_SS_CN("MM月dd日 HH:mm:ss", true);
private String value;
private boolean isShowOnly;
DateStyle(String value, boolean isShowOnly) {
this.value = value;
this.isShowOnly = isShowOnly;
}
public String getValue() {
return value;
}
public boolean isShowOnly() {
return isShowOnly;
}
}
\ No newline at end of file
package net.wanji.utc.config;
import net.wanji.utc.util.FastJson2JsonRedisSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@EnableAutoConfiguration
public class RedisConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.timeout}")
private int timeout;
@Value("${spring.redis.jedis.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.jedis.pool.max-active}")
private int maxTotal;
@Value("${spring.redis.jedis.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.jedis.pool.max-wait}")
private long maxWaitMillis;
/**
* 获取Jedis连接工厂
* <p>用于创建Jedis对象</p>
* @return JedisPool
*/
@Bean
public JedisPool redisPoolFactory() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setTestOnBorrow(false);
jedisPoolConfig.setTestOnReturn(false);
return new JedisPool(jedisPoolConfig, host, port,timeout, password, database);
}
/**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
//不开启事务
template.setEnableTransactionSupport(false);
// 值采用json序列化value
template.setValueSerializer(fastJson2JsonRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* 选择redis作为默认缓存工具
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
/**
* @description: 自定义Redis序列化类
* @date 2019/4/29 20:23
*/
@Bean
public RedisSerializer fastJson2JsonRedisSerializer() {
return new FastJson2JsonRedisSerializer(Object.class);
}
@Bean
public Jedis jedis() {
Jedis jedis = new Jedis("10.100.1.74", 6379);
jedis.auth("Wanji300552");
return jedis;
}
}
\ No newline at end of file
package net.wanji.utc.controller; package net.wanji.utc.controller;
import net.wanji.utc.common.constant.Constants; import net.wanji.utc.common.constant.Constants;
import net.wanji.utc.service.StaticInfoService; import net.wanji.utc.service.staticinfo.StaticInfoService;
import net.wanji.utc.common.baseentity.BaseCrossInfo; import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.vo.CrossInfoInVO; import net.wanji.utc.vo.CrossInfoInVO;
import net.wanji.utc.common.genericentity.OutVO; import net.wanji.utc.common.genericentity.OutVO;
......
package net.wanji.utc.entity;
import lombok.Data;
import java.util.HashMap;
@Data
public class SignalLampStatus {
//信号机编号
private String signalId;
//运行模式
private Integer runmodel;
//方案号
private String planId;
//周期
private Integer cycleLen;
//当前步
private Integer stepNo;
//周期剩余时长
private Integer cycleCountDown;
//相位号
private String phaseId;
//当前步已走时间
private Integer stepGoneTime;
//方向灯组状态
private HashMap<String, HashMap<String, String>> dirLampGroupMap;
//存放当前方案每个相位的时长
HashMap<String, Integer> phaseMap;
//记录灯态变更时间
Long updateTime = Long.valueOf(0);
/**
* 信号机厂商编号
*/
private String signalType;
/**
* 当前步长
*/
private Integer stepLen;
/**
* 当前步剩余时长
*/
private Integer stepSurplusTime;
/**
* 相位内步号
*/
private Integer stepNum;
}
\ No newline at end of file
package net.wanji.utc.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "SignalRunring", description = "信号机运行环数实体")
public class SignalRunring {
//绿灯1
@ApiModelProperty(value = "绿灯1时长")
private Integer oneTime;
//绿灯2
@ApiModelProperty(value = "绿灯2时长")
private Integer twoTime;
//绿灯3
@ApiModelProperty(value = "绿灯3时长")
private Integer threeTime;
//黄灯4
@ApiModelProperty(value = "黄灯4时长")
private Integer fourTime;
//红灯5
@ApiModelProperty(value = "红灯5时长")
private Integer fiveTime;
//环号
@ApiModelProperty(value = "环号")
private String runringNo;
//当前相位编号
@ApiModelProperty(value = "当前相位编号")
private String phaseId;
//相位时长
@ApiModelProperty(value = "相位时长")
private Integer phaseLen;
//相位剩余时长
@ApiModelProperty(value = "相位剩余时长")
private Integer phaseLeft;
//当前步号
@ApiModelProperty(value = "当前步号")
private Integer stepNo;
//当前步类型
@ApiModelProperty(value = "当前步类型")
private Integer stepType;
//当前步长
@ApiModelProperty(value = "当前步长")
private Integer stepLen;
//当前步剩余时间
@ApiModelProperty(value = "当前步剩余时间")
private Integer stepLeft;
//下一相位id
@ApiModelProperty(value = "下一相位id")
private String nextPhaseId;
//相位顺序号
@ApiModelProperty(value = "相位顺序号")
private Integer phaseOrderId;
//当前灯色
@ApiModelProperty(value = "当前灯色")
private Integer lampStatus;
//当前说明
// 11 灭灯
// 21 红灯
// 22 黄灯
// 23 绿灯
// 31 红黄
@ApiModelProperty(value = "当前灯色")
private String lampStatusName;
}
\ No newline at end of file
...@@ -3,6 +3,7 @@ package net.wanji.utc.mapper; ...@@ -3,6 +3,7 @@ package net.wanji.utc.mapper;
import net.wanji.utc.po.CrossInfoPO; import net.wanji.utc.po.CrossInfoPO;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
...@@ -16,5 +17,9 @@ public interface CrossInfoMapper { ...@@ -16,5 +17,9 @@ public interface CrossInfoMapper {
List<String> selectCrossCodesByIds(@Param("entities") List<String> crossIdList); List<String> selectCrossCodesByIds(@Param("entities") List<String> crossIdList);
String selectIdByCode(@Param("crossCode")String crossCode); String selectIdByCode(@Param("crossCode") String crossCode);
List<CrossInfoPO> selectByManufacturerId(@Param("manufacturerId") Integer manufacturerId);
List<CrossInfoPO> selectAll();
} }
...@@ -3,12 +3,17 @@ package net.wanji.utc.mapper; ...@@ -3,12 +3,17 @@ package net.wanji.utc.mapper;
import net.wanji.utc.po.CrossLightsPO; import net.wanji.utc.po.CrossLightsPO;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.List;
/** /**
* @author Kent HAN * @author Kent HAN
* @date 2022/11/18 14:10 * @date 2022/11/18 14:10
*/ */
public interface CrossLightsMapper { public interface CrossLightsMapper {
void deleteOne(@Param("crossId") String crossId, @Param("lightsNo") String lightsNo); void deleteOne(@Param("crossId") String crossId,
@Param("elementId") String elementId);
void insertOne(CrossLightsPO crossLightsPO); void insertOne(CrossLightsPO crossLightsPO);
List<CrossLightsPO> selectByCrossId(@Param("crossId") String crossId);
} }
...@@ -3,6 +3,9 @@ package net.wanji.utc.mapper; ...@@ -3,6 +3,9 @@ package net.wanji.utc.mapper;
import net.wanji.utc.po.ManufacturerInfoPO; import net.wanji.utc.po.ManufacturerInfoPO;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.Arrays;
import java.util.List;
/** /**
* @author Kent HAN * @author Kent HAN
* @date 2022/11/15 16:48 * @date 2022/11/15 16:48
...@@ -12,4 +15,6 @@ public interface ManufacturerInfoMapper { ...@@ -12,4 +15,6 @@ public interface ManufacturerInfoMapper {
ManufacturerInfoPO selectByAbbr(@Param("abbr") String abbr); ManufacturerInfoPO selectByAbbr(@Param("abbr") String abbr);
ManufacturerInfoPO selectById(@Param("manufacturerId") Integer manufacturerId); ManufacturerInfoPO selectById(@Param("manufacturerId") Integer manufacturerId);
List<ManufacturerInfoPO> selectAll();
} }
package net.wanji.utc.mapper;
import net.wanji.utc.po.SignalStatusLogPO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author Kent HAN
* @date 2022/11/21 11:48
*/
public interface SignalStatusLogMapper {
void insertBatch(@Param("entities") List<SignalStatusLogPO> signalStatusLogPOList);
}
package net.wanji.utc.po;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* @author Kent HAN
* @date 2022/11/21 11:18
*/
@Data
public class SignalStatusLogPO {
/** 日志ID */
@ApiModelProperty(name = "日志ID",notes = "")
private Integer id ;
/** 信号机ID */
@ApiModelProperty(name = "信号机ID",notes = "")
private String signalId ;
/** 信号状态:0离线;1在线 */
@ApiModelProperty(name = "信号状态:0离线;1在线",notes = "")
private Integer status ;
/** 故障类型:0正常;1检测器故障;2时钟故障;3电源故障;4驱动模块故障;5信号灯故障;6箱门开启;7方案错误;8绿冲突;9红全熄;10行人红熄; */
@ApiModelProperty(name = "故障类型:0正常;1检测器故障;2时钟故障;3电源故障;4驱动模块故障;5信号灯故障;6箱门开启;7方案错误;8绿冲突;9红全熄;10行人红熄;",notes = "")
private Integer faultType ;
/** 控制类型:1时间表;2全红;3黄闪;4锁定;5中心优化;6MEC优化;7现场手动 */
@ApiModelProperty(name = "控制类型:1时间表;2全红;3黄闪;4锁定;5中心优化;6MEC优化;7现场手动",notes = "")
private Integer controlType ;
/** 创建时间 */
@ApiModelProperty(name = "创建时间",notes = "")
private Date gmtCreate ;
}
package net.wanji.utc.service.runninginfo;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.vo.LightsStatusVO;
import java.util.List;
/**
* @author Kent HAN
* @date 2022/11/21 14:07
*/
public interface HkLightsStatusService {
List<LightsStatusVO> getHkLightsStatus(List<BaseCrossInfo> baseCrossInfoList);
}
package net.wanji.utc.service.runninginfo;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.po.SignalStatusLogPO;
import java.util.List;
/**
* @author Kent HAN
* @date 2022/11/21 10:04
*/
public interface HkRunningStatusService {
List<SignalStatusLogPO> getHkRunningStatus(List<BaseCrossInfo> baseCrossInfoList);
}
package net.wanji.utc.service.runninginfo;
/**
* @author Kent HAN
* @date 2022/11/21 9:09
*/
public interface SignalStatusService {
void runningStatusAlarm();
void lightStatus();
}
package net.wanji.utc.service.runninginfo.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import lombok.extern.slf4j.Slf4j;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.common.commonentity.HttpRequest;
import net.wanji.utc.common.constant.Constants;
import net.wanji.utc.common.typeenum.BasicEnum;
import net.wanji.utc.mapper.CrossInfoMapper;
import net.wanji.utc.mapper.CrossLightsMapper;
import net.wanji.utc.po.CrossLightsPO;
import net.wanji.utc.service.runninginfo.HkLightsStatusService;
import net.wanji.utc.vo.LightsStatusVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Kent HAN
* @date 2022/11/21 14:07
*/
@Service
@Slf4j
public class HkLightsStatusServiceImpl implements HkLightsStatusService {
@Value("${signal.manufacturer.hk.artemisPath}")
private String artemisPath;
@Autowired
private ArtemisConfig artemisConfig;
@Autowired
private CrossLightsMapper crossLightsMapper;
@Autowired
CrossInfoMapper crossInfoMapper;
@Override
public List<LightsStatusVO> getHkLightsStatus(List<BaseCrossInfo> baseCrossInfoList) {
List<LightsStatusVO> result = new ArrayList<>();
LightsStatusVO infoVo;
try {
Map<String, String> path = getPathMapByApiCode("getRealtimeSchemeStateInfo");
for (BaseCrossInfo entity : baseCrossInfoList) {
JSONObject jsonBody = new JSONObject();
jsonBody.put("pageNo", 1);
jsonBody.put("pageSize", 9999);
JSONObject searchObj = new JSONObject();
JSONArray crossCodes = new JSONArray();
crossCodes.add(entity.getCode());
searchObj.put("crossCodes", crossCodes);
jsonBody.put("searchObj", searchObj);
String strResult = ArtemisHttpUtil.doPostStringArtemis(artemisConfig, path, jsonBody.toJSONString(),
null, null, "application/json", null);
JSONObject object = JSON.parseObject(strResult);
String crossId = crossInfoMapper.selectIdByCode(entity.getCode());
List<CrossLightsPO> crossLightsPOList = crossLightsMapper.selectByCrossId(crossId);
if(Constants.HK_SUCCESS_CODE.equals(object.getInteger(Constants.HK_CODE_KEY))) {
JSONObject data = object.getJSONObject("data");
JSONArray list = data.getJSONArray("list");
for (int i = 0; i < list.size(); i++) {
infoVo = new LightsStatusVO();
JSONObject jsonObject = list.getJSONObject(i);
String patternNo = jsonObject.getString("patternNo"); // 方案编号
JSONArray rings = jsonObject.getJSONArray("rings"); // 环列表
JSONArray channelState = jsonObject.getJSONArray("channelState"); // 灯组列表
infoVo.setRunMode(jsonObject.getString("controlType")); // 控制模式
infoVo.setPhasePlanId(patternNo); // 相位方案号
int cycleLen = jsonObject.getIntValue("cycle"); // 周期时长
int curRunTime = jsonObject.getIntValue("curRunTime"); // 当前运行时长
int cycleCountDown = cycleLen - curRunTime; // 周期剩余时长
infoVo.setCode(entity.getCode());
infoVo.setManufacturerAbbr(entity.getManufacturerAbbr());
infoVo.setCycleCountDown(cycleCountDown);
infoVo.setCycleLen(cycleLen);
// 循环相位列表
Map<String,Object> phaseMap = new HashMap<>();
for (int j = 0; j < rings.size(); j++) {
JSONObject jsonObj = rings.getJSONObject(j);
JSONArray phaseList = jsonObj.getJSONArray("phaseList");
for (int k = 0; k < phaseList.size(); k++) {
JSONObject phase = phaseList.getJSONObject(k);
String phaseNo = phase.getString("phaseNo");
Integer vehicleStatus = phase.getInteger("vehicleStatus");
Integer phaseLength = phase.getInteger("phaseLength");
Integer red = phase.getInteger("red");
Integer yellow = phase.getInteger("yellow");
Integer green = phaseLength - yellow - red;
phaseMap.put(phaseNo, green);
if(2 != vehicleStatus){ // 2红灯
infoVo.setPhaseId(phaseNo);
}
}
}
infoVo.setPhaseMap(phaseMap);
Map<String,Object> dirLampGroupMap = new HashMap<>();
// 循环构建灯组对象(从灯组表获取灯组信息)
for (int k = 0; k < channelState.size(); k++) {
JSONObject channelObj = channelState.getJSONObject(k);
int channelNo = channelObj.getIntValue("channelNo");
String color = transferHKLampGroup(channelObj.getIntValue("state"));
for (CrossLightsPO po : crossLightsPOList){
if(Integer.parseInt(po.getLightsNo()) == channelNo) {
String direction = po.getDir().toString();
String turn = po.getTurn().toString();
if(dirLampGroupMap.get(direction) != null){
Map<String,String> mstr = (Map<String,String>)dirLampGroupMap.get(direction);
mstr.put(turn,color);
dirLampGroupMap.put(direction,mstr);
} else {
Map<String,String> lamp = new HashMap<>();
lamp.put(turn,color);
dirLampGroupMap.put(direction,lamp);
}
}
}
}
infoVo.setDirLampGroupMap(dirLampGroupMap);
result.add(infoVo);
}
}
}
} catch(Exception e){
log.error("系统繁忙,服务器端内部错误!", e);
}
return result;
}
/**
* 灯组颜色转换
* @param state
* @return
*/
private String transferHKLampGroup(int state){
String color = "";
switch (state) {
case 1: color = "green"; break;
case 2: color = "red"; break;
case 3: color = "yellow"; break;
case 4: color = "greenFlash"; break;
case 5: color = "yellowFlash"; break;
case 6: color = "red"; break;
case 7: color = "lightsOut"; break;
case 8: color = "redFlash"; break;
case 9: color = "redYellow"; break;
default: color = ""; break;
}
return color;
}
private Map<String, String> getPathMapByApiCode(String apiCode) {
Map<String, String> res = new HashMap<>();
HttpRequest httpRequest = new HttpRequest(BasicEnum.ManufacturerEnum.HK.getAbbr(), apiCode);
res.put("http://", artemisPath + httpRequest.getUrl());
return res;
}
}
package net.wanji.utc.service.runninginfo.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hikvision.artemis.sdk.ArtemisHttpUtil;
import com.hikvision.artemis.sdk.config.ArtemisConfig;
import lombok.extern.slf4j.Slf4j;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.common.commonentity.HttpRequest;
import net.wanji.utc.common.constant.Constants;
import net.wanji.utc.common.typeenum.BasicEnum;
import net.wanji.utc.po.SignalStatusLogPO;
import net.wanji.utc.service.runninginfo.HkRunningStatusService;
import net.wanji.utc.vo.RunningStatusVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Kent HAN
* @date 2022/11/21 10:05
*/
@Slf4j
@Service
public class HkRunningStatusServiceImpl implements HkRunningStatusService {
@Value("${signal.manufacturer.hk.artemisPath}")
private String artemisPath;
@Autowired
private ArtemisConfig artemisConfig;
@Override
public List<SignalStatusLogPO> getHkRunningStatus(List<BaseCrossInfo> baseCrossInfoList) {
List<SignalStatusLogPO> result = new ArrayList<>();
SignalStatusLogPO po;
try {
Map<String, String> runningPath = getPathMapByApiCode("getWorkingStateBatch");
for (BaseCrossInfo baseCrossInfo : baseCrossInfoList) {
JSONArray jsonBody = new JSONArray();
jsonBody.add(baseCrossInfo.getCode());
String strResult = ArtemisHttpUtil.doPostStringArtemis(artemisConfig, runningPath, jsonBody.toJSONString(),
null, null, "application/json", null);
JSONObject object = JSON.parseObject(strResult);
if (Constants.HK_SUCCESS_CODE.equals(object.getInteger(Constants.HK_CODE_KEY))) {
JSONArray data = object.getJSONArray("data");
for (int i = 0; i < data.size(); i++) {
JSONObject obj = data.getJSONObject(i);
po = new SignalStatusLogPO();
po.setSignalId(baseCrossInfo.getCode());
po.setStatus(transferStatus(obj.getInteger("state")));
// 告警信息
Integer hasFault = obj.getInteger("hasFault");
if (hasFault == 0) {
po.setFaultType(hasFault);
}
// todo 从Redis中查询控制类型
result.add(po);
}
}
}
} catch(Exception e){
log.error("系统繁忙,服务器端内部错误!", e);
}
return result;
}
private Map<String, String> getPathMapByApiCode(String apiCode) {
Map<String, String> res = new HashMap<>();
HttpRequest httpRequest = new HttpRequest(BasicEnum.ManufacturerEnum.HK.getAbbr(), apiCode);
res.put("http://", artemisPath + httpRequest.getUrl());
return res;
}
/**
* 转换海康信号机运行状态,0 离线 1 在线
* @param state 海康信号机状态定义 0 在线 1 离线
* @return
*/
private int transferStatus(int state) {
return 0 == state ? 1 : 0;
}
}
package net.wanji.utc.service.runninginfo.impl;
import com.alibaba.fastjson.JSON;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.common.constant.Constants;
import net.wanji.utc.common.constant.RedisKeyConst;
import net.wanji.utc.common.typeenum.BasicEnum;
import net.wanji.utc.mapper.CrossInfoMapper;
import net.wanji.utc.mapper.ManufacturerInfoMapper;
import net.wanji.utc.mapper.SignalStatusLogMapper;
import net.wanji.utc.po.CrossInfoPO;
import net.wanji.utc.po.ManufacturerInfoPO;
import net.wanji.utc.po.SignalStatusLogPO;
import net.wanji.utc.service.runninginfo.HkLightsStatusService;
import net.wanji.utc.service.runninginfo.HkRunningStatusService;
import net.wanji.utc.service.runninginfo.SignalStatusService;
import net.wanji.utc.util.ListUtil;
import net.wanji.utc.util.RedisUtil;
import net.wanji.utc.vo.LightsStatusVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* @date 2022/11/21 9:11
*/
@Service
public class SignalStatusServiceImpl implements SignalStatusService {
@Autowired
ManufacturerInfoMapper manufacturerInfoMapper;
@Autowired
CrossInfoMapper crossInfoMapper;
@Autowired
HkRunningStatusService hkRunningStatusService;
@Autowired
HkLightsStatusService hkLightsStatusService;
@Autowired
RedisUtil redisUtil;
@Autowired
SignalStatusLogMapper signalStatusLogMapper;
@Override
public void runningStatusAlarm() {
BasicEnum.ManufacturerEnum[] manufacturerEnums = BasicEnum.ManufacturerEnum.values();
for (BasicEnum.ManufacturerEnum manufacturerEnum : manufacturerEnums) {
List<BaseCrossInfo> baseCrossInfoList = getBaseCrossInfoList(manufacturerEnum);
if (baseCrossInfoList == null) continue;
List<SignalStatusLogPO> signalStatusLogPOList = null;
if(manufacturerEnum.getAbbr().equals(BasicEnum.ManufacturerEnum.HK.getAbbr())) {
// 海康
// 3.2.5信号机运行状态和告警信息
signalStatusLogPOList = hkRunningStatusService.getHkRunningStatus(baseCrossInfoList);
} else {
// todo 其他厂商
// ParamEntity<List<BaseSignal>> param = new ParamEntity<>();
// param.setDatacontent(baseSignals);
// param.setSourcetype(vendorTypeEnum.getNick());
// param.setSystemtype(Const.SYSTEM_TYPE);
// param.setUpdatetime(new Date());
// statusVos = signalRunService.queryRunState(param).getDatacontent();
}
// 更新Redis
if (null != signalStatusLogPOList) {
for (SignalStatusLogPO signalStatusLogPO : signalStatusLogPOList) {
String field = manufacturerEnum.getAbbr() + Constants.SEPARATOR_UNDER_LINE +
signalStatusLogPO.getSignalId();
redisUtil.setHash(RedisKeyConst.KEY_PREFIX + RedisKeyConst.TELESEME_STATUS, field,
signalStatusLogPO.getStatus()+"");
}
// 更新日志数据库
if (ListUtil.isNotEmpty(signalStatusLogPOList)) {
signalStatusLogMapper.insertBatch(signalStatusLogPOList);
}
}
}
}
@Override
public void lightStatus() {
BasicEnum.ManufacturerEnum[] manufacturerEnums = BasicEnum.ManufacturerEnum.values();
for (BasicEnum.ManufacturerEnum manufacturerEnum : manufacturerEnums) {
List<BaseCrossInfo> baseCrossInfoList = getBaseCrossInfoList(manufacturerEnum);
if (baseCrossInfoList == null) continue;
List<LightsStatusVO> lightsStatusVOList = null;
if(manufacturerEnum.getAbbr().equals(BasicEnum.ManufacturerEnum.HK.getAbbr())) {
// 海康
// 3.2.4灯态
lightsStatusVOList = hkLightsStatusService.getHkLightsStatus(baseCrossInfoList);
} else {
// todo 其他厂商
}
// 更新Redis
if (lightsStatusVOList != null) {
for (LightsStatusVO lightsStatusVO : lightsStatusVOList) {
String field = manufacturerEnum.getAbbr() + Constants.SEPARATOR_UNDER_LINE +
lightsStatusVO.getCode();
redisUtil.setHash(RedisKeyConst.KEY_PREFIX + RedisKeyConst.LIGHTS_STATUS, field,
JSON.toJSONString(lightsStatusVO));
}
}
}
}
private List<BaseCrossInfo> getBaseCrossInfoList(BasicEnum.ManufacturerEnum manufacturerEnum) {
// 查询路口信息
ManufacturerInfoPO manufacturerInfoPO = manufacturerInfoMapper.selectByAbbr(manufacturerEnum.getAbbr());
Integer manufacturerId = manufacturerInfoPO.getId();
List<CrossInfoPO> crossInfoPOList = crossInfoMapper.selectByManufacturerId(manufacturerId);
if (ListUtil.isEmpty(crossInfoPOList)) {
return null;
}
// 信号机接口入参
List<BaseCrossInfo> baseCrossInfoList = new ArrayList<>();
for (CrossInfoPO infoPO : crossInfoPOList) {
BaseCrossInfo baseCrossInfo = new BaseCrossInfo();
baseCrossInfo.setCode(infoPO.getCode());
baseCrossInfo.setManufacturerAbbr(manufacturerEnum.getAbbr());
baseCrossInfoList.add(baseCrossInfo);
}
return baseCrossInfoList;
}
}
package net.wanji.utc.service; package net.wanji.utc.service.staticinfo;
import net.wanji.utc.po.CrossInfoPO; import net.wanji.utc.po.CrossInfoPO;
......
package net.wanji.utc.service; package net.wanji.utc.service.staticinfo;
import net.wanji.utc.common.genericentity.ManufacturerRes; import net.wanji.utc.common.genericentity.ManufacturerRes;
import net.wanji.utc.vo.DetailCrossInfoVO; import net.wanji.utc.vo.DetailCrossInfoVO;
......
package net.wanji.utc.service; package net.wanji.utc.service.staticinfo;
import net.wanji.utc.common.baseentity.BaseCrossInfo; import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.common.genericentity.ManufacturerRes; import net.wanji.utc.common.genericentity.ManufacturerRes;
......
package net.wanji.utc.service.impl; package net.wanji.utc.service.staticinfo.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
...@@ -14,7 +13,7 @@ import net.wanji.utc.mapper.CrossInfoMapper; ...@@ -14,7 +13,7 @@ import net.wanji.utc.mapper.CrossInfoMapper;
import net.wanji.utc.mapper.CrossPlanMapper; import net.wanji.utc.mapper.CrossPlanMapper;
import net.wanji.utc.mapper.CrossSchedulesMapper; import net.wanji.utc.mapper.CrossSchedulesMapper;
import net.wanji.utc.po.CrossSchedulesPO; import net.wanji.utc.po.CrossSchedulesPO;
import net.wanji.utc.service.HkCrossSchedulesService; import net.wanji.utc.service.staticinfo.HkCrossSchedulesService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package net.wanji.utc.service.impl; package net.wanji.utc.service.staticinfo.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
...@@ -15,7 +15,7 @@ import net.wanji.utc.mapper.CrossSectionMapper; ...@@ -15,7 +15,7 @@ import net.wanji.utc.mapper.CrossSectionMapper;
import net.wanji.utc.po.CrossPlanPO; import net.wanji.utc.po.CrossPlanPO;
import net.wanji.utc.po.CrossSchemePO; import net.wanji.utc.po.CrossSchemePO;
import net.wanji.utc.po.CrossSectionPO; import net.wanji.utc.po.CrossSectionPO;
import net.wanji.utc.service.HkPlanSectionService; import net.wanji.utc.service.staticinfo.HkPlanSectionService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package net.wanji.utc.service.impl; package net.wanji.utc.service.staticinfo.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
...@@ -11,7 +11,7 @@ import net.wanji.utc.common.typeenum.*; ...@@ -11,7 +11,7 @@ import net.wanji.utc.common.typeenum.*;
import net.wanji.utc.entity.cache.PhaseCache; import net.wanji.utc.entity.cache.PhaseCache;
import net.wanji.utc.mapper.*; import net.wanji.utc.mapper.*;
import net.wanji.utc.po.*; import net.wanji.utc.po.*;
import net.wanji.utc.service.HkSchemePhaseLightsService; import net.wanji.utc.service.staticinfo.HkSchemePhaseLightsService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -98,8 +98,10 @@ public class HkSchemePhaseLightsServiceImpl implements HkSchemePhaseLightsServic ...@@ -98,8 +98,10 @@ public class HkSchemePhaseLightsServiceImpl implements HkSchemePhaseLightsServic
for (int j = 0; j < laneEles.size(); j++) { for (int j = 0; j < laneEles.size(); j++) {
JSONObject laneObj = laneEles.getJSONObject(j); JSONObject laneObj = laneEles.getJSONObject(j);
CrossLightsPO crossLightsPO = new CrossLightsPO(); CrossLightsPO crossLightsPO = new CrossLightsPO();
String lightsNo = laneObj.getString("elementId"); String lightsNo = laneObj.getString("channelNo");
crossLightsPO.setLightsNo(lightsNo); crossLightsPO.setLightsNo(lightsNo);
String elementId = laneObj.getString("elementId");
crossLightsPO.setName(elementId);
Integer lampGroupType = laneObj.getInteger("lampGroupType"); Integer lampGroupType = laneObj.getInteger("lampGroupType");
Integer type = HkLightsTypeEnum.getCodeByHkCode(lampGroupType); Integer type = HkLightsTypeEnum.getCodeByHkCode(lampGroupType);
crossLightsPO.setType(type); crossLightsPO.setType(type);
...@@ -112,7 +114,7 @@ public class HkSchemePhaseLightsServiceImpl implements HkSchemePhaseLightsServic ...@@ -112,7 +114,7 @@ public class HkSchemePhaseLightsServiceImpl implements HkSchemePhaseLightsServic
crossLightsPO.setCrossId(crossId); crossLightsPO.setCrossId(crossId);
crossLightsPO.setInOutType(3); // 海康都是进出口 crossLightsPO.setInOutType(3); // 海康都是进出口
// 插入数据返回自增ID // 插入数据返回自增ID
crossLightsMapper.deleteOne(crossId, lightsNo); crossLightsMapper.deleteOne(crossId, elementId);
crossLightsMapper.insertOne(crossLightsPO); crossLightsMapper.insertOne(crossLightsPO);
Integer crossLightsPOId = crossLightsPO.getId(); Integer crossLightsPOId = crossLightsPO.getId();
// 匹配缓存信息,构造相位灯组关系对象列表 // 匹配缓存信息,构造相位灯组关系对象列表
......
package net.wanji.utc.service.impl; package net.wanji.utc.service.staticinfo.impl;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
...@@ -14,7 +14,7 @@ import net.wanji.utc.mapper.CrossInfoMapper; ...@@ -14,7 +14,7 @@ import net.wanji.utc.mapper.CrossInfoMapper;
import net.wanji.utc.mapper.ManufacturerInfoMapper; import net.wanji.utc.mapper.ManufacturerInfoMapper;
import net.wanji.utc.po.CrossInfoPO; import net.wanji.utc.po.CrossInfoPO;
import net.wanji.utc.po.ManufacturerInfoPO; import net.wanji.utc.po.ManufacturerInfoPO;
import net.wanji.utc.service.HkStaticInfoService; import net.wanji.utc.service.staticinfo.HkStaticInfoService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package net.wanji.utc.service.impl; package net.wanji.utc.service.staticinfo.impl;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.TypeReference;
import net.wanji.utc.common.commonentity.HttpRequest; import net.wanji.utc.common.commonentity.HttpRequest;
import net.wanji.utc.common.genericentity.ManufacturerRes; import net.wanji.utc.common.genericentity.ManufacturerRes;
import net.wanji.utc.service.OthersStaticInfoService; import net.wanji.utc.service.staticinfo.OthersStaticInfoService;
import net.wanji.utc.util.HttpRestUtil; import net.wanji.utc.util.HttpRestUtil;
import net.wanji.utc.util.StringUtils; import net.wanji.utc.util.StringUtils;
import net.wanji.utc.vo.DetailCrossInfoVO; import net.wanji.utc.vo.DetailCrossInfoVO;
......
package net.wanji.utc.service.impl; package net.wanji.utc.service.staticinfo.impl;
import net.wanji.utc.common.genericentity.ManufacturerRes; import net.wanji.utc.common.genericentity.ManufacturerRes;
import net.wanji.utc.common.typeenum.BasicEnum; import net.wanji.utc.common.typeenum.BasicEnum;
...@@ -6,9 +6,9 @@ import net.wanji.utc.mapper.CrossInfoMapper; ...@@ -6,9 +6,9 @@ import net.wanji.utc.mapper.CrossInfoMapper;
import net.wanji.utc.mapper.ManufacturerInfoMapper; import net.wanji.utc.mapper.ManufacturerInfoMapper;
import net.wanji.utc.po.CrossInfoPO; import net.wanji.utc.po.CrossInfoPO;
import net.wanji.utc.po.ManufacturerInfoPO; import net.wanji.utc.po.ManufacturerInfoPO;
import net.wanji.utc.service.*;
import net.wanji.utc.common.baseentity.BaseCrossInfo; import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.common.genericentity.OutVO; import net.wanji.utc.common.genericentity.OutVO;
import net.wanji.utc.service.staticinfo.*;
import net.wanji.utc.util.ListUtil; import net.wanji.utc.util.ListUtil;
import net.wanji.utc.vo.CrossSchedulesInVO; import net.wanji.utc.vo.CrossSchedulesInVO;
import net.wanji.utc.vo.DetailCrossInfoVO; import net.wanji.utc.vo.DetailCrossInfoVO;
...@@ -59,7 +59,7 @@ public class StaticInfoServiceImpl implements StaticInfoService { ...@@ -59,7 +59,7 @@ public class StaticInfoServiceImpl implements StaticInfoService {
return null; return null;
} }
for (DetailCrossInfoVO vo : dataContent) { for (DetailCrossInfoVO vo : dataContent) {
String id = vo.getTelesemeId(); String id = vo.getCode();
CrossInfoPO crossInfoPO = crossInfoMapper.selectByPrimaryKey(id); CrossInfoPO crossInfoPO = crossInfoMapper.selectByPrimaryKey(id);
if (null != crossInfoPO) { if (null != crossInfoPO) {
continue; continue;
......
package net.wanji.utc.task;
import net.wanji.utc.service.runninginfo.SignalStatusService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 订阅信号运行状态、告警、灯态
*
* @author Kent HAN
* @date 2022/11/21 9:01
*/
@Component
public class SignalStatusTask {
@Autowired
SignalStatusService signalStatusService;
// 运行状态、告警,5分钟一次
@Scheduled(fixedRate = 5 * 60 * 1000)
public void runningStatusAlarm() {
signalStatusService.runningStatusAlarm();
}
// 灯态,5秒一次
@Scheduled(fixedRate = 5 * 1000)
public void lightStatus() {
signalStatusService.lightStatus();
}
}
package net.wanji.utc.util;
import lombok.extern.slf4j.Slf4j;
import net.wanji.utc.common.constant.Constants;
import net.wanji.utc.common.typeenum.DateStyle;
import java.math.BigDecimal;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
public class DateUtils {
private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<>();
private static final Object object = new Object();
private DateUtils() {}
/**
* 获取SimpleDateFormat
* @param pattern 日期格式
* @return SimpleDateFormat对象
* @throws RuntimeException 异常:非法日期格式
*/
public static SimpleDateFormat getDateFormat(String pattern) {
SimpleDateFormat dateFormat = threadLocal.get();
if (dateFormat == null) {
synchronized (object) {
dateFormat = new SimpleDateFormat(pattern);
dateFormat.setLenient(false);
threadLocal.set(dateFormat);
}
}
dateFormat.applyPattern(pattern);
return dateFormat;
}
/**
* 获取日期中的某数值。如获取月份
* @param date 日期
* @param dateType 日期格式
* @return 数值
*/
private static int getInteger(Date date, int dateType) {
int num = 0;
Calendar calendar = Calendar.getInstance();
if (date != null) {
calendar.setTime(date);
num = calendar.get(dateType);
}
return num;
}
/**
* 增加日期中某类型的某数值。如增加日期
* @param date 日期字符串
* @param dateType 类型
* @param amount 数值
* @return 计算后日期字符串
*/
private static String addInteger(String date, int dateType, int amount) {
String dateString = null;
DateStyle dateStyle = getDateStyle(date);
if (dateStyle != null) {
Date myDate = stringToDate(date, dateStyle);
myDate = addInteger(myDate, dateType, amount);
dateString = dateToString(myDate, dateStyle);
}
return dateString;
}
/**
* 增加日期中某类型的某数值。如增加日期
* @param date 日期
* @param dateType 类型
* @param amount 数值
* @return 计算后日期
*/
private static Date addInteger(Date date, int dateType, int amount) {
Date myDate = null;
if (date != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(dateType, amount);
myDate = calendar.getTime();
}
return myDate;
}
/**
* 获取精确的日期
* @param timestamps 时间long集合
* @return 日期
*/
private static Date getAccurateDate(List<Long> timestamps) {
Date date = null;
long timestamp = 0;
Map<Long, long[]> map = new HashMap<>();
List<Long> absoluteValues = new ArrayList<>();
if (timestamps != null && !timestamps.isEmpty()) {
if (timestamps.size() > 1) {
for (int i = 0; i < timestamps.size(); i++) {
for (int j = i + 1; j < timestamps.size(); j++) {
long absoluteValue = Math.abs(timestamps.get(i)
- timestamps.get(j));
absoluteValues.add(absoluteValue);
long[] timestampTmp = { timestamps.get(i),
timestamps.get(j) };
map.put(absoluteValue, timestampTmp);
}
}
// 有可能有相等的情况。如2012-11和2012-11-01。时间戳是相等的。此时minAbsoluteValue为0
// 因此不能将minAbsoluteValue取默认值0
long minAbsoluteValue = -1;
if (!absoluteValues.isEmpty()) {
minAbsoluteValue = absoluteValues.get(0);
for (int i = 1; i < absoluteValues.size(); i++) {
if (minAbsoluteValue > absoluteValues.get(i)) {
minAbsoluteValue = absoluteValues.get(i);
}
}
}
if (minAbsoluteValue != -1) {
long[] timestampsLastTmp = map.get(minAbsoluteValue);
long dateOne = timestampsLastTmp[0];
long dateTwo = timestampsLastTmp[1];
if (absoluteValues.size() > 1) {
timestamp = Math.abs(dateOne) > Math.abs(dateTwo) ? dateOne
: dateTwo;
}
}
} else {
timestamp = timestamps.get(0);
}
}
if (timestamp != 0) {
date = new Date(timestamp);
}
return date;
}
/**
* 根据开始时间和结束时间获取间隔的时间(单位/小时)
* @param startTime
* @param endTime
* @return
*/
public static Double getIntervalHours(String startTime, String endTime){
Date staDate = DateUtils.stringToDate(startTime, DateStyle.HH_MM_SS);
Date endDate = DateUtils.stringToDate(endTime, DateStyle.HH_MM_SS);
if(staDate == null || endDate == null) return null;
BigDecimal startTimeStamp = BigDecimal.valueOf(staDate.getTime());
BigDecimal endTimeStamp = BigDecimal.valueOf(endDate.getTime());
BigDecimal hours = endTimeStamp.subtract(startTimeStamp).divide(new BigDecimal(1000*60*60), 2, BigDecimal.ROUND_DOWN);
return hours.doubleValue();
}
/**
* 判断字符串是否为日期字符串
* @param date 日期字符串
* @return true or false
*/
public static boolean isDate(String date) {
boolean isDate = false;
if (date != null && getDateStyle(date) != null) {
isDate = true;
}
return isDate;
}
/**
* 获取日期字符串的日期风格。失敗返回null。
* @param date 日期字符串
* @return 日期风格
*/
public static DateStyle getDateStyle(String date) {
DateStyle dateStyle = null;
Map<Long, DateStyle> map = new HashMap<>();
List<Long> timestamps = new ArrayList<>();
for (DateStyle style : DateStyle.values()) {
if (style.isShowOnly()) {
continue;
}
Date dateTmp = null;
if (date != null) {
try {
ParsePosition pos = new ParsePosition(0);
dateTmp = getDateFormat(style.getValue()).parse(date, pos);
if (pos.getIndex() != date.length()) {
dateTmp = null;
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
if (dateTmp != null) {
timestamps.add(dateTmp.getTime());
map.put(dateTmp.getTime(), style);
}
}
Date accurateDate = getAccurateDate(timestamps);
if (accurateDate != null) {
dateStyle = map.get(accurateDate.getTime());
}
return dateStyle;
}
/**
* 将日期字符串转化为日期。失败返回null。
* @param date 日期字符串
* @return 日期
*/
public static Date stringToDate(String date) {
DateStyle dateStyle = getDateStyle(date);
return stringToDate(date, dateStyle);
}
/**
* 将日期字符串转化为日期。失败返回null。
* @param date 日期字符串
* @param pattern 日期格式
* @return 日期
*/
public static Date stringToDate(String date, String pattern) {
Date myDate = null;
if (date != null) {
try {
myDate = getDateFormat(pattern).parse(date);
} catch (Exception e) {
log.error(e.getMessage());
}
}
return myDate;
}
/**
* 将日期字符串转化为日期。失败返回null。
* @param date 日期字符串
* @param dateStyle 日期风格
* @return 日期
*/
public static Date stringToDate(String date, DateStyle dateStyle) {
Date myDate = null;
if (dateStyle != null) {
myDate = stringToDate(date, dateStyle.getValue());
}
return myDate;
}
/**
* 将日期转化为日期字符串。失败返回null。
* @param date 日期
* @param pattern 日期格式
* @return 日期字符串
*/
public static String dateToString(Date date, String pattern) {
String dateString = null;
if (date != null) {
try {
dateString = getDateFormat(pattern).format(date);
} catch (Exception e) {
log.error(e.getMessage());
}
}
return dateString;
}
/**
* 将日期转化为日期字符串。失败返回null。
* @param date 日期
* @param dateStyle 日期风格
* @return 日期字符串
*/
public static String dateToString(Date date, DateStyle dateStyle) {
String dateString = null;
if (dateStyle != null) {
dateString = dateToString(date, dateStyle.getValue());
}
return dateString;
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
* @param date 旧日期字符串
* @param newPattern 新日期格式
* @return 新日期字符串
*/
public static String stringToString(String date, String newPattern) {
DateStyle oldDateStyle = getDateStyle(date);
return stringToString(date, oldDateStyle, newPattern);
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
* @param date 旧日期字符串
* @param newDateStyle 新日期风格
* @return 新日期字符串
*/
public static String stringToString(String date, DateStyle newDateStyle) {
DateStyle oldDateStyle = getDateStyle(date);
return stringToString(date, oldDateStyle, newDateStyle);
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
* @param date 旧日期字符串
* @param olddPattern 旧日期格式
* @param newPattern 新日期格式
* @return 新日期字符串
*/
public static String stringToString(String date, String olddPattern,
String newPattern) {
return dateToString(stringToDate(date, olddPattern), newPattern);
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
* @param date 旧日期字符串
* @param olddDteStyle 旧日期风格
* @param newParttern 新日期格式
* @return 新日期字符串
*/
public static String stringToString(String date, DateStyle olddDteStyle,
String newParttern) {
String dateString = null;
if (olddDteStyle != null) {
dateString = stringToString(date, olddDteStyle.getValue(),
newParttern);
}
return dateString;
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
* @param date 旧日期字符串
* @param olddPattern 旧日期格式
* @param newDateStyle 新日期风格
* @return 新日期字符串
*/
public static String stringToString(String date, String olddPattern,
DateStyle newDateStyle) {
String dateString = null;
if (newDateStyle != null) {
dateString = stringToString(date, olddPattern,
newDateStyle.getValue());
}
return dateString;
}
/**
* 将日期字符串转化为另一日期字符串。失败返回null。
* @param date 旧日期字符串
* @param olddDteStyle 旧日期风格
* @param newDateStyle 新日期风格
* @return 新日期字符串
*/
public static String stringToString(String date, DateStyle olddDteStyle,
DateStyle newDateStyle) {
String dateString = null;
if (olddDteStyle != null && newDateStyle != null) {
dateString = stringToString(date, olddDteStyle.getValue(),
newDateStyle.getValue());
}
return dateString;
}
/**
* 格式化时间
* @param date
* @param dateStyle
* @return 时间
*/
public static Date dateForMat(Date date, DateStyle dateStyle){
return stringToDate(dateToString(date, dateStyle),dateStyle);
}
/**
* 增加日期的年份。失败返回null。
* @param date 日期
* @param yearAmount 增加数量。可为负数
* @return 增加年份后的日期字符串
*/
public static String addYear(String date, int yearAmount) {
return addInteger(date, Calendar.YEAR, yearAmount);
}
/**
* 增加日期的值。失败返回null。
* @param date 日期
* @param type 添加的类型 年、月、日、时、分、秒
* @param amount 增加数量
* @return
*/
public static Date add (Date date,int type ,int amount) {
return addInteger(date, type , amount);
}
/**
* 增加日期的年份。失败返回null。
* @param date 日期
* @param yearAmount 增加数量。可为负数
* @return 增加年份后的日期
*/
public static Date addYear(Date date, int yearAmount) {
return addInteger(date, Calendar.YEAR, yearAmount);
}
/**
* 增加日期的月份。失败返回null。
* @param date 日期
* @param monthAmount 增加数量。可为负数
* @return 增加月份后的日期字符串
*/
public static String addMonth(String date, int monthAmount) {
return addInteger(date, Calendar.MONTH, monthAmount);
}
/**
* 增加日期的月份。失败返回null。
* @param date 日期
* @param monthAmount 增加数量。可为负数
* @return 增加月份后的日期
*/
public static Date addMonth(Date date, int monthAmount) {
return addInteger(date, Calendar.MONTH, monthAmount);
}
/**
* 增加日期的天数。失败返回null。
* @param date 日期字符串
* @param dayAmount 增加数量。可为负数
* @return 增加天数后的日期字符串
*/
public static String addDay(String date, int dayAmount) {
return addInteger(date, Calendar.DATE, dayAmount);
}
/**
* 增加日期的天数。失败返回null。
* @param date 日期
* @param dayAmount 增加数量。可为负数
* @return 增加天数后的日期
*/
public static Date addDay(Date date, int dayAmount) {
return addInteger(date, Calendar.DATE, dayAmount);
}
/**
* 增加日期的小时。失败返回null。
* @param date 日期字符串
* @param hourAmount 增加数量。可为负数
* @return 增加小时后的日期字符串
*/
public static String addHour(String date, int hourAmount) {
return addInteger(date, Calendar.HOUR_OF_DAY, hourAmount);
}
/**
* 增加日期的小时。失败返回null。
* @param date 日期
* @param hourAmount 增加数量。可为负数
* @return 增加小时后的日期
*/
public static Date addHour(Date date, int hourAmount) {
return addInteger(date, Calendar.HOUR_OF_DAY, hourAmount);
}
/**
* 增加日期的分钟。失败返回null。
* @param date 日期字符串
* @param minuteAmount 增加数量。可为负数
* @return 增加分钟后的日期字符串
*/
public static String addMinute(String date, int minuteAmount) {
return addInteger(date, Calendar.MINUTE, minuteAmount);
}
/**
* 增加日期的分钟。失败返回null。
* @param date 日期
* @param minuteAmount 增加数量。可为负数
* @return 增加分钟后的日期
*/
public static Date addMinute(Date date, int minuteAmount) {
return addInteger(date, Calendar.MINUTE, minuteAmount);
}
/**
* 增加日期的秒钟。失败返回null。
* @param date 日期字符串
* @param secondAmount 增加数量。可为负数
* @return 增加秒钟后的日期字符串
*/
public static String addSecond(String date, int secondAmount) {
return addInteger(date, Calendar.SECOND, secondAmount);
}
/**
* 增加日期的秒钟。失败返回null。
* @param date 日期
* @param secondAmount 增加数量。可为负数
* @return 增加秒钟后的日期
*/
public static Date addSecond(Date date, int secondAmount) {
return addInteger(date, Calendar.SECOND, secondAmount);
}
/**
* 获取日期的年份。失败返回0。
* @param date 日期字符串
* @return 年份
*/
public static int getYear(String date) {
return getYear(stringToDate(date));
}
/**
* 获取日期的年份。失败返回0。
* @param date 日期
* @return 年份
*/
public static int getYear(Date date) {
return getInteger(date, Calendar.YEAR);
}
/**
* 获取日期的月份。失败返回0。
* @param date 日期字符串
* @return 月份
*/
public static int getMonth(String date) {
return getMonth(stringToDate(date));
}
/**
* 获取日期的月份。失败返回0。
* @param date 日期
* @return 月份
*/
public static int getMonth(Date date) {
return getInteger(date, Calendar.MONTH) + 1;
}
/**
* 获取日期的星期。失败返回0
*
* @param date 日期
* @return 星期
*/
public static int getWeek(String date) {
return getWeek(stringToDate(date));
}
/**
* 获取日期的星期。失败返回0
*
* @param date 日期
* @return 星期
*/
public static int getWeek(Date date) {
return getInteger(date, Calendar.DAY_OF_WEEK) - 1;
}
/**
* 获取日期的天数。失败返回0。
* @param date 日期字符串
* @return 天
*/
public static int getDay(String date) {
return getDay(stringToDate(date));
}
/**
* 获取日期的天数。失败返回0。
* @param date 日期
* @return 天
*/
public static int getDay(Date date) {
return getInteger(date, Calendar.DATE);
}
/**
* 获取日期的小时。失败返回0。
* @param date 日期字符串
* @return 小时
*/
public static int getHour(String date) {
return getHour(stringToDate(date));
}
/**
* 获取日期的小时。失败返回0。
* @param date 日期
* @return 小时
*/
public static int getHour(Date date) {
return getInteger(date, Calendar.HOUR_OF_DAY);
}
/**
* 获取日期的分钟。失败返回0。
* @param date 日期字符串
* @return 分钟
*/
public static int getMinute(String date) {
return getMinute(stringToDate(date));
}
/**
* 获取日期的分钟。失败返回0。
* @param date 日期
* @return 分钟
*/
public static int getMinute(Date date) {
return getInteger(date, Calendar.MINUTE);
}
/**
* 获取日期的秒钟。失败返回0。
* @param date 日期字符串
* @return 秒钟
*/
public static int getSecond(String date) {
return getSecond(stringToDate(date));
}
/**
* 获取日期的秒钟。失败返回0。
* @param date 日期
* @return 秒钟
*/
public static int getSecond(Date date) {
return getInteger(date, Calendar.SECOND);
}
/**
* 获取日期 。默认yyyy-MM-dd格式。失败返回null。
* @param date 日期字符串
* @return 日期
*/
public static String getDate(String date) {
return stringToString(date, DateStyle.YYYY_MM_DD);
}
/**
* 获取日期。默认yyyy-MM-dd格式。失败返回null。
* @param date 日期
* @return 日期
*/
public static String getDate(Date date) {
return dateToString(date, DateStyle.YYYY_MM_DD);
}
/**
* 获取日期的时间。默认HH:mm:ss格式。失败返回null。
* @param date 日期字符串
* @return 时间
*/
public static String getTime(String date) {
return stringToString(date, DateStyle.HH_MM_SS);
}
/**
* 获取日期的时间。默认HH:mm:ss格式。失败返回null。
* @param date 日期
* @return 时间
*/
public static String getTime(Date date) {
return dateToString(date, DateStyle.HH_MM_SS);
}
/**
* 获取两个日期相差的天数
* @param date 日期字符串
* @param otherDate 另一个日期字符串
* @return 相差天数。如果失败则返回-1
*/
public static int getIntervalDays(String date, String otherDate) {
return getIntervalDays(stringToDate(date), stringToDate(otherDate));
}
/**
* @param date 日期
* @param otherDate 另一个日期
* @return 相差天数。如果失败则返回-1
*/
public static int getIntervalDays(Date date, Date otherDate) {
int num = -1;
Date dateTmp = DateUtils.stringToDate(DateUtils.getDate(date),
DateStyle.YYYY_MM_DD);
Date otherDateTmp = DateUtils.stringToDate(DateUtils.getDate(otherDate),
DateStyle.YYYY_MM_DD);
if (dateTmp != null && otherDateTmp != null) {
long time = Math.abs(dateTmp.getTime() - otherDateTmp.getTime());
num = (int) (time / (24 * 60 * 60 * 1000));
}
return num;
}
/**
* @param date 日期
* @param otherDate 另一个日期
* @return 相差分钟数。如果失败则返回-1
*/
public static int getIntervalMinute(Date date, Date otherDate) {
int num = -1;
if (date != null && otherDate != null) {
long time = Math.abs(date.getTime() - otherDate.getTime());
num = (int) (time / (1000*60));
}
return num;
}
/**
* Description :获取当前时间yyyyMMddHHmmss字符串
* @return String 当前时间yyyyMMddHHmmss字符串
*/
public static String getSecondString() {
return dateToString(new Date(), DateStyle.YYYYMMDDHHMMSS);
}
/**
* Description : 获取当前时间yyyyMMddHHmmssSSS字符串
* @return String 当前时间yyyyMMddHHmmssSSS字符串
*/
public static String getMillisecondString() {
return dateToString(new Date(), DateStyle.YYYYMMDDHHMMSSSSS);
}
/**
* Description:[返回开始时间到结束的时间段值 例:分段计算时间值,将24小时分为48个时间段,例如:1,2标识00:00到01:00]
* @param startTime 开始时间9:00
* @param endTime 结束时间10:30
* @return 返回开始时间到结束的时间段值
*/
public static String splitTime(Date startTime, Date endTime ) {
//开始时间
StringBuilder splitTime = new StringBuilder();
int startHour = DateUtils.getHour(startTime);
int startMinute = DateUtils.getMinute(startTime);
int startCount = startHour * 2;
if (startMinute > 0 ) {
startCount = startCount + 1;
}
//结束时间
int endHour = DateUtils.getHour(endTime);
int endMinute = DateUtils.getMinute(endTime);
int endCount = endHour * 2;
if (endMinute > 0) {
endCount = endCount +1;
}
//如果结束是00:00 最后时间
if(endHour == 0 && endMinute == 0) {
endCount = 48;
}
//之所以需要++ 原因在于开始时间为9:00结束时间为9:30,不加1的情况18表示是8:30到9:00的时间段这样是错误的,我需要的是9:00到9:30的所以是19。
startCount ++;
endCount ++;
//如果跨天会议 结束时间的小时小于开始时间的小时认定为跨天会议
if(endHour < startHour) {
for (int i = startCount;i < 49; i++) {
splitTime.append(i);
splitTime.append(Constants.SEPARATOR_COMMA);
}
if (endCount != 49) {
for (int j = 1; j < endCount; j++) {
splitTime.append(j);
if (j < endCount - 1) {
splitTime.append(Constants.SEPARATOR_COMMA);
}
}
}
return splitTime.toString();
}
//不是跨天会议
if (startCount == endCount) {
splitTime.append(startCount);
return splitTime.toString();
}
for (int i = startCount;i < endCount; i++) {
splitTime.append(i);
if (i < endCount - 1) {
splitTime.append(Constants.SEPARATOR_COMMA);
}
}
return splitTime.toString();
}
/**
* Description:[返回开始时间到结束的时间段值 例:分段计算时间值,将24小时分为48个时间段,例如:1,2标识00:00到01:00]
* @param startTime 开始时间9:00
* @param endTime 结束时间10:30
* @return 返回开始时间到结束的时间段值
* Created on 2019/4/17
* @author: hfx
*/
public static String splitTime(String startTime, String endTime ) {
Date startDate = DateUtils.stringToDate(startTime, DateStyle.HH_MM_SS);
Date endDate = DateUtils.stringToDate(endTime, DateStyle.HH_MM_SS);
return splitTime(startDate, endDate);
}
/**
* Description:[24小时分为48个时间段,根据时间段的数值获取真实的时间 -- 会议开始时间]
* @param number 24小时分为48个时间段的值
* @return 数值解析后的真实时间 -- 会议开始时间
*
* Created on 2019/4/17
* @author: hfx
*/
public static Date numberByStartTime(int number) {
int i = (number - 1) % 2;
int hour = (number - 1) / 2;
int minute = 0;
if (i > 0) {
minute = 30;
}
String endTime = hour + Constants.SEPARATOR_COLON + minute;
return DateUtils.stringToDate(endTime, DateStyle.HH_MM);
}
/**
* Description:[24小时分为48个时间段,根据时间段的数值获取真实的时间 -- 会议结束时间]
* @param number 24小时分为48个时间段的值
* @return 数值解析后的真实时间 -- 会议结束时间
*
* Created on 2019/4/17
* @author: hfx
*/
public static Date numberByEndTime(int number) {
return addMinute(numberByStartTime(number), 30);
}
/**
* Description:[判断两个日期是否相等]
* @param d1 日期1
* @param d2 日期2
* @return boolean 相等true
*
* Created on 2019/4/17
* @author: hfx
*/
public static boolean isSameDate(Date d1, Date d2) {
if(null == d1 || null == d2)
return false;
Calendar cal1 = Calendar.getInstance();
cal1.setTime(d1);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(d2);
return cal1.get(0) == cal2.get(0) && cal1.get(1) == cal2.get(1) && cal1.get(6) == cal2.get(6);
}
/**
* Description:[获取两个时间的时间差]
* @param date1 时间一
* @param date2 时间二
* @param type 获取的类型 天 时 分 秒
* @return 时间一 减 时间二 的值
*
* Created on 2019/4/17
* @author: hfx
*/
public static int dayDiff(Date date1, Date date2, int type) {
long diff = date1.getTime() - date2.getTime();
int nd = 1000 * 24 * 60 * 60;
int nh = 1000 * 60 * 60;
int nm = 1000 * 60;
int ns = 1000;
// 计算差多少天
long day = diff / nd;
// 计算差多少小时
long hour = diff / nh;
// 计算差多少分钟
long min = diff / nm;
// 计算差多少秒
long sec = diff / ns;
if (Calendar.DATE == type) {
return (int) day;
} else if (Calendar.HOUR_OF_DAY == type) {
return (int) hour;
} else if (Calendar.MINUTE == type) {
return (int) min;
} else if (Calendar.SECOND == type) {
return (int) sec;
} else {
return (int) diff;
}
}
/**
* Description:[根据参数时间获取前推的整点时间:列2017-11-22 17:13返回17:00;列2017-11-22 17:59返回17:30]
* @param date 时间
* @return 列2017-11-22 17:13返回17:00;列2017-11-22 17:59返回17:30
*
* Created on 2019/4/17
* @author: hfx
*/
public static Date wholeHour(Date date){
int hour = DateUtils.getHour(date);
int minute = DateUtils.getMinute(date);
if (minute >= 30) {
minute = 30;
}else {
minute = 00;
}
String endTime = hour + Constants.SEPARATOR_COLON + minute;
return DateUtils.stringToDate(endTime, DateStyle.HH_MM);
}
/**
* <p>Description:[计算两个日期相差的月数,不足15天按照半个月计算,超过15天按照一个月计算]</p>
*
* @param startDate 开始时间
* @param endDate 结束时间
* @return 相差的月数0.5的倍数
* Created on 2019/4/17
* @author: hfx
*/
public static double getMonths(Date startDate, Date endDate) {
int startYear = DateUtils.getYear(startDate);
int endYear = DateUtils.getYear(endDate);
int startMonth = DateUtils.getMonth(startDate);
int endMonth = DateUtils.getMonth(endDate);
int startDay = DateUtils.getDay(startDate);
int endDay = DateUtils.getDay(endDate);
int endLastDay = DateUtils.getLastDay(endDate);
int startLastDay = DateUtils.getLastDay(startDate);
int intervalYears = endYear - startYear;
double intervalMonths;
int intervalDays;
if (intervalYears >= 1) {
intervalDays = (startLastDay - startDay) + endDay + 1;
intervalMonths = (12.0 - startMonth) + endMonth + 1;
if (startDay == 1 && endDay == endLastDay) {
intervalDays = 0;
} else {
if (startDay != 1) {
intervalMonths -= 1.0;
} else {
intervalDays = endDay;
}
if (endDay != endLastDay) {
intervalMonths -= 1.0;
} else {
intervalDays = startLastDay - startDay + 1;
}
}
} else {
intervalMonths = endMonth - startMonth + 1.0;
if (intervalMonths > 1.0) {
intervalDays = (startLastDay - startDay) + endDay + 1;
if (startDay == 1 && endDay == endLastDay) {
intervalDays = 0;
} else {
if (startDay != 1) {
intervalMonths -= 1.0;
} else {
intervalDays = endDay;
}
if (endDay != endLastDay) {
intervalMonths -= 1.0;
} else {
intervalDays = startLastDay - startDay + 1;
}
}
intervalMonths = intervalMonths < 0.0 ? 0.0 : intervalMonths;
} else {
intervalMonths = 0.0;
intervalDays = endDay - startDay + 1;
}
}
if (intervalDays == 0) {
intervalMonths += 0.0;
} else if (intervalDays <= 15) {
intervalMonths += 0.5;
} else if (intervalDays >= 31) {
intervalMonths += 1.0;
if (intervalDays - 31 > 15) {
intervalMonths += 1.0;
} else if (intervalDays - 31 >= 1) {
intervalMonths += 0.5;
}
} else {
intervalMonths += 1.0;
}
for (int i = 1; i < intervalYears; i++) {
intervalMonths += 12.0;
}
return intervalMonths;
}
/**
* <p>Description:[计算当前时间所处的拆分时间段]</p>
*
* @return 拆分时间段Integer值
* Created on 2019/4/17
* @author: hfx
*/
public static Integer getSplitTimeByNow() {
return getSplitTime(new Date());
}
/**
* <p>Description:[计算时间所处的拆分时间段]</p>
*
* @return 拆分时间段Integer值
* Created on 2019/4/17
* @author: hfx
*/
public static Integer getSplitTime(Date date) {
int hour = DateUtils.getHour(date);
int minute = DateUtils.getMinute(date);
if (minute > 0 && minute < 30) {
minute = 30;
}
int splitTime = hour * 2 + 1;
if (minute >= 30) {
splitTime += 1;
}
return splitTime;
}
/**
* Description:[获取当前月的第一天的日期]
* @return 当前月第一天
*
* Created on 2019/4/17
* @author: hfx
*/
public static Date getfirstDate(){
Calendar c = Calendar.getInstance();
c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天
return stringToDate(getDateFormat(DateStyle.YYYY_MM_DD.getValue()).format(c.getTime()));
}
/**
* Description:[获取当前月的最后一天的日期]
* @return 当前月的最后一天
*
* Created on 2019/4/17
* @author: hfx
*/
public static Date getlastDate(){
Calendar c = Calendar.getInstance();
c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
return stringToDate(getDateFormat(DateStyle.YYYY_MM_DD.getValue()).format(c.getTime()));
}
/**
* Description:[获取指定月的最后一天的日期]
* @return 指定的最后一天
*
* Created on 2019/4/17
* @author: hfx
*/
public static int getLastDay(Date date){
Calendar c = Calendar.getInstance();
c.setTime(date);
int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
return lastDay;
}
/**
* Description:[获取指定月的第一天的日期]
* @return 指定的第一天
*
* Created on 2019/4/17
* @author: hfx
*/
public static int getFirstDay(Date date){
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.getActualMinimum(Calendar.DAY_OF_MONTH);
}
/**
* <p>Description:[获取当前日期字符串]</p>
* Created on 2019/4/17
* @author: hfx
*/
public static String getCurrentDateString() {
return dateToString(new Date(), DateStyle.YYYY_MM_DD);
}
/**
* <p>Description:[获取当前日期]</p>
* Created on 2019/4/17
* @author: hfx
*/
public static Date getCurrentDate() {
return stringToDate(getCurrentDateString(), DateStyle.YYYY_MM_DD);
}
/**
* <p>Description:[获取某月最大日期]</p>
* Created on 2019/4/17
* @author: hfx
*/
public static int getMonthMaxDay(Date date) {
Calendar calendar = Calendar.getInstance();
calendar.set(getYear(date), getMonth(date) - 1, 1);
return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
}
/**
* <p>Discription:[根据传入的两个时间计算相差几个小时,结果保留一位小数]</p>
* @param dateLast date类型的时间1
* @param dateNext date类型的时间2
* @return Double 返回保留一位小数的绝对值
* Created on 2019/4/17
* @author: hfx
*/
public static Double calculateHour(Date dateLast, Date dateNext) {
long millisLast = dateLast.getTime();
long millisNext = dateNext.getTime();
double differenceMillis = (double) millisNext - millisLast;
double hourDouble = differenceMillis/1000/60/60;
hourDouble = BigDecimal.valueOf(hourDouble).setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
return Math.abs(hourDouble);
}
/**
* 判断一个时间是否在一个时间段之间
* @param date 为目标时间
* @param startDate 为起始时间
* @param endDate 为结束时间
* @return true or false
* Created on 2019/4/17
* @author: hfx
*/
public static boolean getInDate(String date,String startDate,String endDate) {
boolean flag =false;
Date targetTime = DateUtils.stringToDate(date, DateStyle.YYYY_MM_DD);
Date startTime = DateUtils.stringToDate(startDate, DateStyle.YYYY_MM_DD);
Date endTime = DateUtils.stringToDate(endDate, DateStyle.YYYY_MM_DD);
//目标时间大于等于开始时间 且 目标时间小于等于结束时间 时返回true
if (targetTime != null && targetTime.compareTo(startTime) >= 0 && targetTime.compareTo(endTime) <= 0) {
flag = true;
}
return flag;
}
/**
* @description: 获取时段名称
* @param startTime 开始时间
* @param endTime 结束时间
* @return java.lang.String 时段名称
* @author hfx
* @date 2019/5/5 20:12
*/
public static String getSectimeName(String startTime, String endTime){
String secname = "平峰";
String st = startTime.split(":")[0];
String et = endTime.split(":")[0];
if (StringUtils.isEmpty(st) || StringUtils.isEmpty(et)) {
return secname;
}
int s = Integer.parseInt(st);
int e = Integer.parseInt(et);
if (s>=0 && e<=6){
secname = "低峰";
}else if (s>=6 && e<=7){
secname = "早平峰";
}else if (s>=7 && e<=9){
secname = "早高峰";
}else if (s>=9 && e<=12){
secname = "平峰";
}else if (s>=12 && e<=14){
secname = "次平峰";
}else if (s>=14 && e<=17){
secname = "平峰";
}else if (s>=17 && e<=19){
secname = "晚高峰";
}else if (s>=19 && e<=22){
secname = "次平峰";
}else if (s>=22 && e<=24){
secname = "低峰";
}
return secname;
}
}
\ No newline at end of file
package net.wanji.utc.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import java.nio.charset.Charset;
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
public FastJson2JsonRedisSerializer(Class<T> clazz) {
super(); this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return (T) JSON.parseObject(str, clazz);
}
}
\ No newline at end of file
package net.wanji.utc.util;
import net.wanji.utc.common.constant.Constants;
import net.wanji.utc.common.constant.RedisKeyConst;
import net.wanji.utc.common.typeenum.DateStyle;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtil {
/**
* 注入redisTemplate
*/
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* @description: 判断是否存在Key
* @param key redis的Key
* @return boolean true:有 false:无
*/
public boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
/**
* @description: 添加字符串
* @param key redis的Key
* @param value 添加redis的value
*/
public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* @description: 添加对象
* @param key redis的Key
* @param object 添加redis的value
*/
public void set(String key, Object object) {
redisTemplate.opsForValue().set(key, object);
}
/**
* @description: 添加带生命周期的对象
* @param key redis的Key
* @param object 添加redis的value
* @param seconds 失效时间
*/
public void setAndExpire(String key, Object object, int seconds) {
redisTemplate.opsForValue().set(key, object);
redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
}
/**
* @description: 添加带生命周期的对象
* @param key redis的Key
* @param value 添加redis的value
* @param seconds 失效时间
*/
public void setAndExpire(String key, String value, int seconds) {
redisTemplate.opsForValue().set(key, value);
redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
}
/**
* @description: 获取对象
* @param key redis的Key
* @return Object 返回对象
*/
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* @description: 存入redis的hash
* @param key redis的Key
* @param field 字段值
* @param value 存入的值
*/
public void setHash(String key, String field, String value) {
redisTemplate.opsForHash().put(key, field, value);
}
/**
* @description: 存入redis的hash
* @param key redis的Key
* @param field 字段值
* @param value 存入的值
*/
public void setHash(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
/**
* @description: 根据key和字段值获取内容值
* @param key redis的Key
* @param field 字段值
* @return String 返回字符串
*/
public String getHash(String key, String field) {
return (String)redisTemplate.opsForHash().get(key, field);
}
/**
* @description: 根据field删除值
* @param key redis的Key
* @param field 字段值
*/
public void delHashMap(String key, String field) {
redisTemplate.boundHashOps(key).delete(field);
}
/**
* @description: 存入hash集合
* @param key redis的Key
* @param hashmap 存入的Map集合
*/
public void setHashMap(String key, Map<String, Object> hashmap){
redisTemplate.opsForHash().putAll(key, hashmap);;
}
/**
* @description: 取出hash集合
* @param key redis的Key
* @return Map<Object, Object> 返回Map集合
*/
public Map<Object, Object> getHashMap(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* @description: 存入redis的Set
* @param key redis的Key
* @param object 对象
*/
public void setSet(String key,Object object){
redisTemplate.opsForSet().add(key, object);
}
/**
* @description: 获取redis的Set
* @param key redis的Key
* @return Set<Object> Set集合
*/
public Set<Object> getSet(String key){
return redisTemplate.opsForSet().members(key);
}
/**
* @discription: 查看值是否是set成员
* @param key set的key
* @param value set的成员
* @return 是否是set成员
*/
public Boolean isSetMember(String key, Object value) {
return redisTemplate.opsForSet().isMember(key, value);
}
/**
* @description:设置key的过期时间,endTime格式:yyyy-MM-dd hh:mm:ss
* @param key redis的Key
* @param endTime 结束时间
*/
public void setExpire(String key, Date endTime) {
long seconds = endTime.getTime() - System.currentTimeMillis();
redisTemplate.expire(key, (int) (seconds / 1000), TimeUnit.SECONDS);
}
/**
* @description: 设置key的过期时间
* @param key redis的Key
* @param time 过期时间(秒)
*/
public void setExpire(String key, int time) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
/**
* <p>Discription:获取key的过期时间
* @param key redis的Key
* @return 过期时间(秒)
*/
public Long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* @description: 在redis消息队列队尾插入数据
* @param key redis的Key
* @param object 添加的对象
*/
public void tailPush(String key, Object object){
redisTemplate.opsForList().rightPush(key, object);
}
/**
* @description: 在redis消息队列对头插入数据
* @param key redis的Key
* @param object 添加的对象
*/
public void headPush(String key,Object object){
redisTemplate.opsForList().leftPush(key, object);
}
/**
* @description: 在redis消息队列队尾删除数据
* @param key redis的Key
* @return Object 删除的对象
*/
public Object tailPop(String key){
return redisTemplate.opsForList().rightPop(key);
}
/**
* @description: 在redis消息队列队头删除数据
* @param key redis的Key
* @return Object 删除的对象
*/
public Object headPop(String key){
return redisTemplate.opsForList().leftPop(key);
}
/**
* @description: 删除redis的值
* @param key redis的Key
*/
public void del(String key) {
if (hasKey(key)) {
redisTemplate.delete(key);
}
}
/**
* @description: 清理redis缓存
*/
public void flushDB(){
redisTemplate.getConnectionFactory().getConnection().flushDb();
}
/**
* @description: 根据类型生成版本号
* @param type 类型key区分
* @return 版本号
* @author hfx
* @date 2019/5/5 19:26
*/
public String getVersion(String type) {
String formatDate = DateUtils.dateToString(new Date(), DateStyle.YYYYMMDD);
String key = RedisKeyConst.KEY_PREFIX + type + formatDate;
//当前时间到第二天还剩多少时间
Date newDate = DateUtils.dateForMat(DateUtils.addDay(new Date(), 1), DateStyle.YYYY_MM_DD);
int liveTime = DateUtils.dayDiff(newDate, new Date(), Calendar.MILLISECOND);
//获取自增号
Long incr = getIncr(key, liveTime);
if(incr == 0) {
incr = getIncr(key, liveTime);//从001开始
}
DecimalFormat df = new DecimalFormat("000");//三位序列号
return formatDate + Constants.SEPARATOR_MINUS + df.format(incr);
}
/**
* 自增ID
* @param key 建
* @param liveTime 过期时间
* @return 自增结果
*/
public Long getIncr(String key, long liveTime) {
RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
Long increment = entityIdCounter.getAndIncrement();
if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
entityIdCounter.expire(liveTime, TimeUnit.MILLISECONDS);//单位毫秒
}
return increment;
}
/**
* 获取全部Redis的key
* @return
*/
public Set<String> keys() {
return redisTemplate.keys("*");
}
}
\ No newline at end of file
package net.wanji.utc.vo;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class CrossLanesVO {
/** 通道号 */
private Integer channelNo;
/** 车道号 */
private Integer laneNo;
/** 方向 */
private Integer direction;
/** 转向 */
private Integer turn;
/** 灯组类型 */
private Integer lampGroupType;
}
\ No newline at end of file
package net.wanji.utc.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
import net.wanji.utc.entity.SignalRunring;
import java.util.List;
import java.util.Map;
/**
* @author Kent HAN
* @date 2022/11/21 14:04
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class LightsStatusVO extends BaseCrossInfo {
//运行模式
@ApiModelProperty(value = "运行模式 `2=手动锁定当前相位`,`3=手动全红`,`4=手动黄闪`,`5=手动关灯`," +
"`6=全红闪控制`,`7=全黄控制`,`8=正常按计划运行`,`9=手动步进控制`,`10=自动步进控制`,`11=恢复时间表`,`255=临时控制方案`")
private String runMode;
//控制模式
@ApiModelProperty(value = "控制模式")
private String controlMode;
//相位方案号
@ApiModelProperty(value = "相位方案号")
private String phasePlanId;
//相位配时方案
@ApiModelProperty(value = "相位配时方案")
private String timePlanId;
//方案开始时间
@ApiModelProperty(value = "方案开始时间")
private String planStartTime;
//方案运行时间
@ApiModelProperty(value = "方案运行时间")
private Integer runTime;
//相位周期剩余时长
@ApiModelProperty(value = "相位周期剩余时长")
private Integer cycleCountDown;
//相位周期时长
@ApiModelProperty(value = "相位周期时长")
private Integer cycleLen;
//运行环数组
private List<SignalRunring> runrings;
//相位编号
@ApiModelProperty(value = "当前相位号")
private String phaseId;
//方案编号
@ApiModelProperty(value = "当前方案号")
private String planId;
//灯组状态
@ApiModelProperty(value = "灯组状态")
private Map<String,Object> dirLampGroupMap;
//相位对象:key:相位编号,value:绿灯时长
@ApiModelProperty(value = "相位对象:key相位编号,value绿灯时长")
private Map<String,Object> phaseMap;
public void setCycleCountDown(Integer cycleCountDown) {
if (null == cycleCountDown) {
this.cycleCountDown = -1;
} else {
this.cycleCountDown = cycleCountDown;
}
}
public Integer getCycleCountDown() {
if (null == cycleCountDown) {
return -1;
}
return cycleCountDown;
}
}
package net.wanji.utc.vo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import net.wanji.utc.common.baseentity.BaseCrossInfo;
/**
* @author Kent HAN
* @date 2022/11/21 9:44
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class RunningStatusVO extends BaseCrossInfo {
// 信号状态:0离线;1在线
private Integer status;
// 故障类型:0正常;1检测器故障;2时钟故障;3电源故障;4驱动模块故障;5信号灯故障;6箱门开启;7方案错误;8绿冲突;9红全熄;10行人红熄
private Integer faultType;
// 控制模式:1时间表;2全红;3黄闪;4锁定;5中心优化;6MEC优化;7现场手动
private Integer controlType;
}
...@@ -30,7 +30,7 @@ spring: ...@@ -30,7 +30,7 @@ spring:
max-idle: 20 max-idle: 20
min-idle: 10 min-idle: 10
timeout: 5000 timeout: 5000
database: 3 database: 5
# 信号平台 # 信号平台
signal: signal:
......
...@@ -46,4 +46,15 @@ ...@@ -46,4 +46,15 @@
from t_cross_info from t_cross_info
where code = #{crossCode} where code = #{crossCode}
</select> </select>
<select id="selectByManufacturerId" resultMap="BaseResultMap">
select id,name,code,manufacturer_id,ip,port,location,version,model,install_time,gmt_create,gmt_modified
from t_cross_info
where manufacturer_id = #{manufacturerId}
</select>
<select id="selectAll" resultMap="BaseResultMap">
select id,name,code,manufacturer_id,ip,port,location,version,model,install_time,gmt_create,gmt_modified
from t_cross_info
</select>
</mapper> </mapper>
...@@ -21,8 +21,15 @@ ...@@ -21,8 +21,15 @@
<delete id="deleteOne"> <delete id="deleteOne">
delete from t_cross_lights delete from t_cross_lights
where cross_id = #{crossId} and lights_no = #{lightsNo} where cross_id = #{crossId} and name = #{elementId}
</delete> </delete>
<select id="selectByCrossId" resultMap="BaseResultMap">
select
id,lights_no,name,type,dir,turn,cross_id,in_out_type,gmt_create,gmt_modified
from t_cross_lights
where cross_id = #{crossId}
</select>
</mapper> </mapper>
...@@ -25,4 +25,9 @@ ...@@ -25,4 +25,9 @@
from t_manufacturer_info from t_manufacturer_info
where id = #{manufacturerId} where id = #{manufacturerId}
</select> </select>
<select id="selectAll" resultMap="BaseResultMap">
select
id,code,name,nick_name,address,maintenance_unit,gmt_create,gmt_modified
from t_manufacturer_info
</select>
</mapper> </mapper>
<?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="net.wanji.utc.mapper.SignalStatusLogMapper">
<resultMap type="net.wanji.utc.po.SignalStatusLogPO" id="BaseResultMap">
<result property="id" column="id" />
<result property="signalId" column="signal_id"/>
<result property="status" column="status"/>
<result property="faultType" column="fault_type"/>
<result property="controlType" column="control_type"/>
<result property="gmtCreate" column="gmt_create"/>
</resultMap>
<!-- 批量新增数据 -->
<insert id="insertBatch" keyProperty="id" useGeneratedKeys="true">
insert into t_signal_status_log(signal_id,status,fault_type,control_type)
values
<foreach collection="entities" item="entity" separator=",">
(#{entity.signalId},#{entity.status},#{entity.faultType},#{entity.controlType})
</foreach>
</insert>
</mapper>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment