Commit 75b08ad3 authored by duanruiming's avatar duanruiming

[add] 绿波城项目绿波时序图

parent 38a27564
......@@ -17,6 +17,12 @@ public class Constants {
public static final String CROSS_FREE_FLOW_SPEED_KEY = "crossFreeFlowSpeed";
public static final String CROSS_FREE_FLOW_SPEED_TOPIC = "cross_free_flow_speed";
/**
* 绿波优化查询缓存key
*/
public static final String GREEN_ID_OPT_KEY = "green_opt_";
public static final String GREEN_ID_OPT_CHART_KEY = "green_opt_chart_";
private Constants() {
}
}
\ No newline at end of file
package net.wanji.datacenter.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.DecimalFormat;
/**
* @author duanruiming
* @date 2024/11/20 19:00
*/
public class DoubleToTwoDecimalPlacesSerializer extends JsonSerializer<Double> {
private static final DecimalFormat df = new DecimalFormat("#.00");
@Override
public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value != null) {
String formattedValue = df.format(value);
gen.writeString(formattedValue);
} else {
gen.writeNull();
}
}
}
\ No newline at end of file
package net.wanji.datacenter.kafka;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import net.wanji.common.utils.tool.JacksonUtils;
import net.wanji.common.utils.tool.StringUtils;
import net.wanji.datacenter.common.Constants;
import net.wanji.datacenter.pojo.vo.GreenBeltChartVO;
import net.wanji.datacenter.pojo.vo.GreenBeltOptInfoVO;
import net.wanji.datacenter.service.GreenBeltInfoService;
import net.wanji.datacenter.util.RedisUtils;
import org.apache.kafka.clients.consumer.Consumer;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.listener.KafkaListenerErrorHandler;
import org.springframework.kafka.listener.ListenerExecutionFailedException;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author duanruiming
* @date 2024/11/20 19:12
*/
@Component
@Slf4j
public class GreenBeltDataConsumerHandler implements KafkaListenerErrorHandler {
@Resource
private GreenBeltInfoService greenBeltInfoService;
@Resource
private RedisUtils redisUtils;
@KafkaListener(topics = {"green_belt_info_data"}, groupId = "group2", containerFactory = "kafkaListenerContainerFactory2")
public void receiveGreenBeltInfoData(String message) throws Exception {
if (StringUtils.isNotBlank(message)) {
GreenBeltOptInfoVO greenBeltOptInfoVO = greenBeltInfoService.convertData(message);
greenBeltInfoService.save(greenBeltOptInfoVO);
String key = Constants.GREEN_ID_OPT_KEY.concat(greenBeltOptInfoVO.getGreenId());
redisUtils.set(key, JacksonUtils.getInstance().writeValueAsString(greenBeltOptInfoVO));
GreenBeltChartVO greenBeltChartVO = greenBeltInfoService.convertChartData(greenBeltOptInfoVO);
String chartKey = Constants.GREEN_ID_OPT_CHART_KEY.concat(greenBeltOptInfoVO.getGreenId());
redisUtils.set(chartKey, JacksonUtils.getInstance().writeValueAsString(greenBeltChartVO));
}
}
@Override
@NonNull
public Object handleError(Message<?> message, ListenerExecutionFailedException e) {
return new Object();
}
@Override
@NonNull
public Object handleError(Message<?> message, ListenerExecutionFailedException exception, Consumer<?, ?> consumer) {
String errorMessage = String.format("监听主题:%s,消费者详情:%s,异常信息:%s,消息详情:%s",
consumer.listTopics(), consumer.groupMetadata(), exception, message);
log.error(errorMessage);
return KafkaListenerErrorHandler.super.handleError(message, exception, consumer);
}
}
......@@ -24,7 +24,7 @@ import java.util.concurrent.ConcurrentHashMap;
*/
@Component
@Slf4j
public class ConsumerHandler implements KafkaListenerErrorHandler {
public class PeriodDataConsumerHandler implements KafkaListenerErrorHandler {
@Resource
private DataProcessService dataProcessService;
......
package net.wanji.datacenter.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.wanji.datacenter.pojo.StrategyGreenOptHistEntity;
/**
* @author duanruiming
* @date 2024/11/19 18:02
* @description 神思推送绿波时序图信息
*/
public interface StrategyGreenOptHistMapper extends BaseMapper<StrategyGreenOptHistEntity> {
}
package net.wanji.datacenter.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @author duanruiming
* @date 2024/11/19 17:48
*/
@Data
@TableName("t_strategy_green_opt_hist")
public class StrategyGreenOptHistEntity {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField("green_id")
private String greenId;
@TableField("length")
private Double length;
@TableField("cycle")
private Integer cycle;
@TableField("control_time")
private String controlTime;
@TableField("control_duration")
private Integer controlDuration;
@TableField("control_method")
private Integer controlMethod;
@TableField("type")
private Integer type;
@TableField("dynamic")
private Integer dynamic;
@TableField("dir_type")
private Integer dirType;
@TableField("dir")
private String dir;
@TableField("max_speed")
private Double maxSpeed;
@TableField("min_speed")
private Double minSpeed;
@TableField("green_width_time")
private Double greenWidthTime;
@TableField("cross_green_detail")
private String crossGreenDetail;
@TableField("create_time")
private Date createTime;
@TableField("modify_time")
private Date modifyTime;
}
package net.wanji.datacenter.pojo.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.Map;
/**
* @author duanruiming
* @date 2024/11/19 10:20
* @description 神思绿波时序图推送数据消息
*/
@Data
@SuppressWarnings("all")
@JsonIgnoreProperties(ignoreUnknown = true)
public class GreenBeltKafkaDTO {
@JsonProperty("greenbelt_id")
private String greenbeltId; // 绿波带id
@JsonProperty("greenbelt_length")
private double greenbeltLength; // 绿波干线长度(m)
@JsonProperty("max_speed_forward")
private double maxSpeedForward; // 正向绿波推荐最大速度(km/h)
@JsonProperty("max_speed_backward")
private double maxSpeedBackward; // 反向绿波推荐最大速度(km/h)
@JsonProperty("min_speed_forward")
private double minSpeedForward; // 正向绿波推荐最小速度(km/h)
@JsonProperty("min_speed_backward")
private double minSpeedBackward; // 反向绿波推荐最小速度(km/h)
@JsonProperty("forward_direction")
private String forwardDirection; // 正向绿波方向(w2e/e2w/n2s/s2n)
@JsonProperty("backward_direction")
private String backwardDirection; // 反向绿波方向(w2e/e2w/n2s/s2n)
@JsonProperty("greenbelt_direction")
private int greenbeltDirection; // 此次策略下发绿波带方向(0=正向,1=反向,2=双向)
@JsonProperty("green_width_forward")
private double greenWidthForward; // 正向绿波带宽(s)
@JsonProperty("green_width_backward")
private double greenWidthBackward; // 反向绿波带宽(s)
@JsonProperty("phase_start_forward")
private Map<String, Double> phaseStartForward; // 每个路口正向绿波相位开始时间(s)
@JsonProperty("phase_start_backward")
private Map<String, Double> phaseStartBackward; // 每个路口反向绿波相位开始时间(s)
@JsonProperty("phase_end_forward")
private Map<String, Double> phaseEndForward; // 每个路口正向绿波相位结束时间(s)
@JsonProperty("phase_end_backward")
private Map<String, Double> phaseEndBackward; // 每个路口反向绿波相位结束时间(s)
@JsonProperty("belt_start_forward")
private Map<String, Double> beltStartForward; // 每个路口正向绿波带宽开始时间(s)
@JsonProperty("belt_start_backward")
private Map<String, Double> beltStartBackward; // 每个路口反向绿波带宽开始时间(s)
@JsonProperty("speed_forward")
private Map<String, Double> speedForward; // 每个路口正向绿波速度(km/h)
@JsonProperty("speed_backward")
private Map<String, Double> speedBackward; // 每个路口反向绿波速度(km/h)
@JsonProperty("offset")
private Map<String, Double> offset; // 每个路口相位差(s)
@JsonProperty("max_cycle")
private int maxCycle; // 最大周期(s)
@JsonProperty("control_time")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "GMT+8")
private String controlTime; // 策略下发时间
@JsonProperty("control_duration")
private int controlDuration; // 策略执行时长(s)
@JsonProperty("greenbelt_type")
private int greenbeltType; // 执行策略(1=单条, 2=垂直,3=平行)
private int dynamic; // 是否动态绿波(1=是,0=否)
@JsonProperty("control_method")
private int controlMethod; // -1=stop by error, 0=no control, 1=control
@JsonProperty("travel_time_forward")
private Map<String, Double> travelTimeForward;
@JsonProperty("travel_time_backward")
private Map<String, Double> travelTimeBackward;
@JsonProperty("distance_forward")
private Map<String, Double> distanceForward;
@JsonProperty("distance_backward")
private Map<String, Double> distanceBackward;
}
package net.wanji.datacenter.pojo.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* @author duanruiming
* @date 2024/11/21 11:04
*/
@Data
@ApiModel(value = "GreenBeltChartVO", description = "绿波时序图返回实体")
@JsonIgnoreProperties(ignoreUnknown = true)
public class GreenBeltChartVO {
@ApiModelProperty("绿波路口红灯范围")
Map<String, List<Double[]>> crossRedTimesMap;
@ApiModelProperty("绿波路口绿波开始时间")
Map<String, Double> greenStartMap;
@ApiModelProperty("绿波路口距离下一个路口距离")
Map<String, Double> distanceMap;
@ApiModelProperty("绿波带宽")
private Double greenWidthTime;
}
package net.wanji.datacenter.pojo.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import net.wanji.datacenter.config.DoubleToTwoDecimalPlacesSerializer;
import java.util.List;
/**
* @author duanruiming
* @date 2024/11/19 10:48
* @description 绿波带时序图
*/
@Data
@ApiModel(value = "GreenBeltInfoVO", description = "绿波时序图优化数据返回实体")
@JsonIgnoreProperties(ignoreUnknown = true)
public class GreenBeltOptInfoVO {
@ApiModelProperty("绿波id")
private String greenId;
@ApiModelProperty("绿波带长度")
private Double length;
@ApiModelProperty("绿波带周期")
private Integer cycle;
@ApiModelProperty("绿波带下发时间")
private String controlTime;
@ApiModelProperty("策略执行时长")
private Integer controlDuration;
@ApiModelProperty("执行策略(1=单条, 2=垂直,3=平行)")
private Integer type;
@ApiModelProperty("是否动态绿波(1=是,0=否)")
private Integer dynamic;
@ApiModelProperty("-1=stop by error, 0=no control, 1=control")
private Integer controlMethod;
private List<DirGreenDetail> dirGreenDetails;
@Data
public static class DirGreenDetail {
@ApiModelProperty("0-反向 1-正向 2-双向")
private Integer dirType;
@ApiModelProperty("绿波方向")
private String dir;
@ApiModelProperty("最大速度")
@JsonSerialize(using = DoubleToTwoDecimalPlacesSerializer.class)
private Double maxSpeed;
@ApiModelProperty("最小速度")
@JsonSerialize(using = DoubleToTwoDecimalPlacesSerializer.class)
private Double minSpeed;
@ApiModelProperty("绿波带宽")
private Double greenWidthTime;
@ApiModelProperty("绿波路口详情")
private List<CrossGreenDetail> crossGreenDetailList;
}
@Data
public static class CrossGreenDetail {
@ApiModelProperty("路口")
private String crossId;
@ApiModelProperty("相位开始时间")
private Double phaseStartTime;
@ApiModelProperty("相位结束时间")
private Double phaseEndTime;
@ApiModelProperty("绿波带开始时间")
private Double greenStartTime;
@ApiModelProperty("绿波速度")
@JsonSerialize(using = DoubleToTwoDecimalPlacesSerializer.class)
private Double speed;
@ApiModelProperty("相位差")
private Double offset;
@ApiModelProperty("行程时间")
private Double travelTime;
@ApiModelProperty("到下一个路口距离")
@JsonSerialize(using = DoubleToTwoDecimalPlacesSerializer.class)
private Double distance;
}
}
package net.wanji.datacenter.service;
import net.wanji.datacenter.pojo.vo.GreenBeltChartVO;
import net.wanji.datacenter.pojo.vo.GreenBeltOptInfoVO;
/**
* @author duanruiming
* @date 2024/11/19 18:07
*/
public interface GreenBeltInfoService {
/**
* 数据转换
* @param message
* @return
* @throws Exception
*/
GreenBeltOptInfoVO convertData(String message) throws Exception;
GreenBeltChartVO convertChartData(GreenBeltOptInfoVO vo) throws Exception;
/**
* 存储
* @param infoVO
* @throws Exception
*/
void save(GreenBeltOptInfoVO infoVO) throws Exception;
}
<?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.opt.dao.mapper.StrategyGreenOptHistMapper">
</mapper>
\ No newline at end of file
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