car-Net/train-networking/src/main/java/com/mobai/vehicle/VehicleInstance.java

309 lines
9.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.mobai.vehicle;
import com.alibaba.fastjson2.JSONObject;
import com.mobai.common.SystemConstant;
import com.mobai.common.pool.ScheduledThreadPool;
import com.mobai.domain.Vehicle;
import com.mobai.domain.model.PositionModel;
import com.mobai.utils.CalculateCheckDigit;
import com.mobai.utils.ConversionUtil;
import com.mobai.utils.VehicleUtils;
import com.mobai.vehicle.model.VehicleData;
import com.mobai.vehicle.model.properties.MqttProperties;
import com.mobai.vehicle.thread.VehicleThread;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledFuture;
import static com.mobai.common.SystemConstant.*;
/**
* @author Saisai.Liu
* @version 1.0
* @description 车辆实例
* @date 2023/11/16
*/
@Data
@Log4j2
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VehicleInstance {
/**
* 路线轨迹编码
*/
private String positionCode;
/**
* 路径队列
*/
private LinkedBlockingQueue<PositionModel> positionQueue = new LinkedBlockingQueue<>();
/**
* 车辆
*/
private Vehicle vehicle;
/**
* 实例数据
*/
private VehicleData vehicleData;
/**
* 上一个定位点
*/
private PositionModel lastPosition;
/**
* 车辆工作线程
*/
private VehicleThread vehicleThread;
/**
* 消息状态
*/
private String msgCode;
/**
* 线程提交回调
*/
private ScheduledFuture<?> scheduledFuture;
/**
* 链接上报
*/
private MqttClient client = null;
/**
* Mqtt配置
*/
private MqttProperties mqttProperties;
/***
* 获取当前车辆VIN
* @return VIN
*/
public String getVin() {
return this.vehicle.getVin();
}
/**
* 发送消息
* @param msg 消息
*/
public void sendMsg(String msg) {
//得到16进制报文
String sHex = ConversionUtil.strToSixteen(msg);
//计算校验和
String makeCheck = CalculateCheckDigit.makeCheck(sHex);
msg = MSG_START + sHex + makeCheck + " " + MSG_END;
// 创建消息并设置 QoS
MqttMessage message = new MqttMessage(msg.getBytes());
message.setQos(this.mqttProperties.getQos());
// 发布消息
try {
client.publish(this.mqttProperties.getTopic(), message);
} catch (MqttException e) {
throw new RuntimeException(e);
}
}
/**
* 初始化客户端
*/
public void initClient () {
try {
client = new MqttClient(mqttProperties.getBroker(), mqttProperties.getClientId(), new MemoryPersistence());
// 连接参数
MqttConnectOptions options = new MqttConnectOptions();
// 设置用户名和密码
if (Objects.nonNull(mqttProperties.getUsername()) && Objects.nonNull(mqttProperties.getPassword())) {
options.setUserName(mqttProperties.getUsername());
options.setPassword(mqttProperties.getPassword().toCharArray());
}
options.setConnectionTimeout(1);
options.setKeepAliveInterval(20);
// 连接
client.connect(options);
log.debug("车辆:[{}] 客户端初始化成功连接配置:{}", getVin(),
JSONObject.toJSONString(this.mqttProperties));
} catch (MqttException e) {
log.error("车辆:[{}] 客户端初始化异常", getVin(), e);
}
}
/**
* 是否连接在线
* @return 在线返回true不在线为false
*/
public boolean isOnline () {
if (this.client == null){
return false;
}
return this.client.isConnected();
}
/**
* 是否建立车辆模拟线程
* @return 建立返回true不建立返回false
*/
public boolean isSend(){
return this.vehicleThread != null;
}
/**
* 关闭连接
*/
public void closeClient(){
if (this.client != null){
try {
// 断开连接
this.client.disconnect();
// 关闭连接
this.client.close();
log.debug("车辆:[{}] 客户端下线成功", getVin());
} catch (MqttException e) {
log.error("车辆:[{}] 客户端关闭异常:[{}]",getVin(), e.getMessage(), e);
}
}
}
/**
* 初始化车辆路线
* @param positionModelList 路线集合
*/
public void settingPosition(List<PositionModel> positionModelList){
positionQueue.clear();
positionModelList.forEach(positionQueue::offer);
log.info("车辆:{} 设置路径成功", this.getVin());
}
/**
* 初始化线程
*/
public void initVehicleThread() {
if (this.positionCode == null){
throw new RuntimeException("车辆["+getVin()+"]为选中路径");
}
VehicleThread vehicleThread = new VehicleThread();
vehicleThread.setVehicleInstance(this);
this.setVehicleThread(vehicleThread);
ScheduledFuture<?> scheduledFuture = ScheduledThreadPool.submit(vehicleThread);
this.setScheduledFuture(scheduledFuture);
log.info("初始化车辆上报模拟线程开始:[{}]", this.getVin());
}
/**
* 开始上报线程
*/
public void startSend() {
this.msgCode = "上报";
if (this.vehicleThread != null){
this.vehicleThread.resume();
}
log.info("车辆[{}],开始上报", this.getVin());
}
/**
* 暂停上报线程
*/
public void pauseSend() {
this.msgCode = "暂停";
if (this.vehicleThread != null) {
this.vehicleThread.pause();
}
log.info("车辆[{}],暂停上报", this.getVin());
}
/**
* 结束发送
*/
public void stopSend() {
this.msgCode = "停止";
if (this.vehicleThread != null){
this.vehicleThread.stop();
}
log.info("车辆[{}],停止上报", this.getVin());
}
/**
* 取消执行
*/
public void cancelExecution() {
scheduledFuture.cancel(true);
this.vehicleThread = null;
this.scheduledFuture = null;
}
/**
* 模拟车辆数据
*/
public String imitateData() {
String gear = this.vehicleData.getGear();
if (!"D".equals(gear)){
log.info("车辆不是动车档位,不进行模拟数据");
return null;
}
// 获取上一次定位点
PositionModel lastPositionModel = this.lastPosition == null ? positionQueue.poll() : this.lastPosition;
// 获取当前定位点
PositionModel currentPositionModel = positionQueue.poll();
if (currentPositionModel == null) {
return "表示当前定位点已经跑完,需要其他操作";
}
// 两点之间的距离
BigDecimal distance = VehicleUtils.distance(lastPositionModel, currentPositionModel);
// 车辆总里程 相加
vehicleData.setMileage(vehicleData.getMileage().add(distance));
// 定位点填写
vehicleData.setLongitude(currentPositionModel.getLongitude());
vehicleData.setLatitude(currentPositionModel.getLatitude());
// 当前电量减少
// 电池浮动
BigDecimal batteryFloat = VehicleUtils.batteryFloat();
// 百公里占比
BigDecimal hundredKMScale = distance.divide(SystemConstant.hundredKilometers).setScale(3, RoundingMode.HALF_UP);
// 使用电量
BigDecimal powerUsage = powerConsumption.multiply(hundredKMScale)
.multiply(batteryFloat)
.setScale(2, RoundingMode.HALF_UP);
// 剩余电量
vehicleData.setRemainingBattery(vehicleData.getRemainingBattery().subtract(powerUsage));
// 百公里消耗量
vehicleData.setFuelConsumptionRate(
powerConsumption.multiply(batteryFloat).divide(new BigDecimal(1000)).setScale(2, RoundingMode.HALF_UP).toString()
);
// 计算总速度
vehicleData.setSpeed(
distance.divide(new BigDecimal(2))
.multiply(new BigDecimal("3600"))
.setScale(2, RoundingMode.HALF_UP).toString()
);
vehicleData.imitateBase();
vehicleData.imitateMotor();
vehicleData.imitateBatteryPack();
return null;
}
/**
* 更改车辆档位
* @param gear
*/
public void setGear (String gear) {
this.vehicleData.setGear(gear);
}
}