Compare commits
6 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a1d837b5a5 | |
|
|
28adc5863b | |
|
|
b27c54dd2e | |
|
|
ee1bcefc9f | |
|
|
dc4b0143e0 | |
|
|
53176657d1 |
|
|
@ -2,10 +2,11 @@ package com.njzscloud.common.localizer;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.njzscloud.common.localizer.contant.LocalizerType;
|
||||
import com.njzscloud.common.mqtt.util.Mqtt;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
|
@ -18,10 +19,10 @@ public class DeviceStore {
|
|||
private static final Lock localizersReadLock = localizersLock.readLock();
|
||||
|
||||
public static void init() {
|
||||
Mqtt.publish("localizer/loader");
|
||||
// Mqtt.publish("localizer/loader");
|
||||
}
|
||||
|
||||
public static void setLocalizers(LinkedList<Localizer> list) {
|
||||
public static void setLocalizers(List<Localizer> list) {
|
||||
localizersWriteLock.lock();
|
||||
try {
|
||||
log.info("重新加载设备:{}", list.size());
|
||||
|
|
@ -60,4 +61,8 @@ public class DeviceStore {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static Collection<Localizer> list() {
|
||||
return CollUtil.unmodifiable(localizers);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@ public class Localizer {
|
|||
@Getter
|
||||
@Setter
|
||||
protected String terminalId;
|
||||
|
||||
/**
|
||||
* 车牌
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private String licensePlate;
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class Htzj {
|
||||
private static HtzjListeners htzjListeners = new HtzjListeners();
|
||||
private static HtzjListeners htzjListeners;
|
||||
|
||||
public static void init() {
|
||||
htzjListeners = new HtzjListeners();
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import lombok.AccessLevel;
|
|||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
|
@ -150,6 +151,7 @@ public final class JT808 {
|
|||
|
||||
public static JT808Message parseMessage(ByteBuf buf) {
|
||||
JT808Message jt808Message = new JT808Message();
|
||||
byte[] bytes = ByteBufUtil.getBytes(buf);
|
||||
|
||||
try {
|
||||
// 1. 消息ID (2字节)
|
||||
|
|
@ -191,6 +193,12 @@ public final class JT808 {
|
|||
log.error("校验码错误: {}", jt808Message);
|
||||
return null;
|
||||
}
|
||||
int messageId = jt808Message.getMessageId();
|
||||
if (messageId == 0x0200
|
||||
|| messageId == 0x704
|
||||
|| messageId == 0x0201) {
|
||||
log.info("{},{},报文:{}", terminalPhone, MessageType.getMessageType(messageId), Arrays.toString(bytes));
|
||||
}
|
||||
|
||||
return jt808Message;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.njzscloud.common.localizer.jt808.support;
|
|||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.njzscloud.common.localizer.DeviceStore;
|
||||
import com.njzscloud.common.localizer.Localizer;
|
||||
import com.njzscloud.common.localizer.contant.LocalizerType;
|
||||
|
|
@ -10,11 +11,13 @@ import com.njzscloud.common.localizer.contant.MessageType;
|
|||
import com.njzscloud.common.localizer.jt808.JT808;
|
||||
import com.njzscloud.common.localizer.jt808.message.*;
|
||||
import com.njzscloud.common.localizer.mqtt.result.RealtimeLocationResult;
|
||||
import com.njzscloud.common.localizer.service.LocalizerService;
|
||||
import com.njzscloud.common.mqtt.util.Mqtt;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Slf4j
|
||||
|
|
@ -105,9 +108,12 @@ public abstract class JT808MessageListener {
|
|||
LocationReportMessage locationReportMsg = new LocationReportMessage(byteBuf);
|
||||
double speed = locationReportMsg.getSpeed();
|
||||
int speedThreshold = localizer.getSpeedThreshold();
|
||||
String licensePlate = localizer.getLicensePlate();
|
||||
RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
|
||||
.setLicensePlate(licensePlate)
|
||||
.setTerminalId(terminalId)
|
||||
.setOverspeed(speed > speedThreshold);
|
||||
saveData(realtimeLocationResult);
|
||||
Mqtt.publish(terminalId + "/track_location", realtimeLocationResult);
|
||||
Mqtt.publish(terminalId + "/track_location_real", realtimeLocationResult);
|
||||
} finally {
|
||||
|
|
@ -137,10 +143,13 @@ public abstract class JT808MessageListener {
|
|||
LocationReportMessage locationReportMsg = new LocationReportMessage(byteBuf.slice(byteBuf.readerIndex(), length));
|
||||
byteBuf.skipBytes(length);
|
||||
double speed = locationReportMsg.getSpeed();
|
||||
String licensePlate = localizer.getLicensePlate();
|
||||
RealtimeLocationResult realtimeLocationResult = BeanUtil.copyProperties(locationReportMsg, RealtimeLocationResult.class)
|
||||
.setLicensePlate(licensePlate)
|
||||
.setTerminalId(terminalId)
|
||||
.setOverspeed(speed > speedThreshold)
|
||||
.setType(type);
|
||||
saveData(realtimeLocationResult);
|
||||
Mqtt.publish(terminalId + "/track_location", realtimeLocationResult);
|
||||
Mqtt.publish(terminalId + "/track_location_real", realtimeLocationResult);
|
||||
}
|
||||
|
|
@ -149,6 +158,17 @@ public abstract class JT808MessageListener {
|
|||
}
|
||||
}
|
||||
|
||||
protected void saveData(RealtimeLocationResult realtimeLocationResult) {
|
||||
try {
|
||||
LocalizerService localizerService = SpringUtil.getBean(LocalizerService.class);
|
||||
if (localizerService != null) {
|
||||
localizerService.save(Collections.singletonList(realtimeLocationResult));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("数据保存失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询位置响应消息
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@ import lombok.experimental.Accessors;
|
|||
@Accessors(chain = true)
|
||||
public class RealtimeLocationResult {
|
||||
private String terminalId;
|
||||
|
||||
/**
|
||||
* 车牌
|
||||
*/
|
||||
private String licensePlate;
|
||||
private int type;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
package com.njzscloud.common.localizer.service;
|
||||
|
||||
|
||||
import com.njzscloud.common.localizer.mqtt.result.RealtimeLocationResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface LocalizerService {
|
||||
void save(List<RealtimeLocationResult> data);
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ public class TokenHandshakeInterceptor implements HandshakeInterceptor {
|
|||
try {
|
||||
HttpServletRequest req = ((ServletServerHttpRequest) request).getServletRequest();
|
||||
String authorization = req.getParameter(Authorization);
|
||||
if (StrUtil.isBlank(authorization)) return false;
|
||||
// if (StrUtil.isBlank(authorization)) return false;
|
||||
|
||||
Tuple2<Long, String> resolved = this.resolve(authorization);
|
||||
if (resolved == null) return false;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,19 @@
|
|||
<artifactId>njzscloud-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njzscloud</groupId>
|
||||
<artifactId>njzscloud-common-mvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.njzscloud</groupId>
|
||||
<artifactId>njzscloud-common-ws</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.njzscloud</groupId>
|
||||
<artifactId>njzscloud-common-mp</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.njzscloud</groupId>
|
||||
<artifactId>njzscloud-common-localizer</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,226 @@
|
|||
package com.njzscloud.localizer.config;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.njzscloud.common.core.ex.ExceptionMsg;
|
||||
import com.njzscloud.common.core.thread.ThreadPool;
|
||||
import com.njzscloud.common.core.tuple.Tuple2;
|
||||
import com.njzscloud.common.core.utils.CoordinateConverter;
|
||||
import com.njzscloud.common.core.utils.R;
|
||||
import com.njzscloud.common.ws.support.Websocket;
|
||||
import com.njzscloud.common.ws.support.WsMsg;
|
||||
import com.njzscloud.localizer.device.service.LocalizerDeviceService;
|
||||
import com.njzscloud.localizer.track.pojo.entity.TruckLocationTrackEntity;
|
||||
import com.njzscloud.localizer.track.pojo.param.LocationTrackSearchParam;
|
||||
import com.njzscloud.localizer.track.service.TruckLocationTrackService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class OnStarted {
|
||||
private final LocalizerDeviceService localizerDeviceService;
|
||||
private final TruckLocationTrackService truckLocationTrackService;
|
||||
ThreadPoolExecutor threadPoolExecutor = ThreadPool.createThreadPool(
|
||||
"GPS 数据",
|
||||
10,
|
||||
200,
|
||||
60,
|
||||
1,
|
||||
1,
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||
);
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void onApplicationReady() {
|
||||
localizerDeviceService.loadDevice();
|
||||
Websocket.subscribe("up/truck_location_track/history", msg -> {
|
||||
WsMsg.User from = msg.getFrom();
|
||||
String cid = from.getCid();
|
||||
LocationTrackSearchParam param = msg.extractData(LocationTrackSearchParam.class);
|
||||
// String terminalId = param.getTerminalId();
|
||||
String licensePlate = param.getLicensePlate();
|
||||
LocalDateTime startTime = param.getStartTime();
|
||||
LocalDateTime endTime = param.getEndTime();
|
||||
Integer speed = param.getSpeed();
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
int currentPage = 1;
|
||||
// 分页查询,每次500条
|
||||
while (true) {
|
||||
// 检查是否被取消
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
log.info("任务被取消");
|
||||
return;
|
||||
}
|
||||
|
||||
Page<TruckLocationTrackEntity> page = new Page<>(currentPage, 500);
|
||||
page.addOrder(OrderItem.asc("location_time"));
|
||||
|
||||
// 分页查询当前页数据
|
||||
IPage<TruckLocationTrackEntity> resultPage = truckLocationTrackService.page(page, Wrappers.lambdaQuery(TruckLocationTrackEntity.class)
|
||||
.eq(TruckLocationTrackEntity::getLicensePlate, licensePlate)
|
||||
.ge(startTime != null, TruckLocationTrackEntity::getLocationTime, startTime)
|
||||
.le(endTime != null, TruckLocationTrackEntity::getLocationTime, endTime));
|
||||
|
||||
List<TruckLocationTrackEntity> records = resultPage.getRecords();
|
||||
if (records.isEmpty()) {
|
||||
Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/history")
|
||||
.setData(R.failed(ExceptionMsg.SYS_ERR_MSG, "数据发送完成"))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理当前页数据,按时间间隔推送
|
||||
for (TruckLocationTrackEntity record : records) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
log.info("任务被取消");
|
||||
return;
|
||||
}
|
||||
if (speed > 100) {
|
||||
if (!ThreadUtil.sleep(speed)) {
|
||||
log.info("任务被取消");
|
||||
Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/history")
|
||||
.setData(R.failed(ExceptionMsg.SYS_ERR_MSG, "数据发送完成"))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Tuple2<Double, Double> doubles = CoordinateConverter.wgs84ToGcj02(record.getLatitude(), record.getLongitude());
|
||||
record.setLatitude(doubles.get_0())
|
||||
.setLongitude(doubles.get_1());
|
||||
boolean publish = Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/history")
|
||||
.setData(R.success(record))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
if (!publish) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为最后一页
|
||||
if (currentPage >= resultPage.getPages()) {
|
||||
Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/history")
|
||||
.setData(R.failed(ExceptionMsg.SYS_ERR_MSG, "数据发送完成"))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 继续查询下一页
|
||||
currentPage++;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// 其他异常
|
||||
log.error("查询历史轨迹异常", e);
|
||||
}
|
||||
}, threadPoolExecutor);
|
||||
});
|
||||
|
||||
Websocket.subscribe("up/truck_location_track/realtime", msg -> {
|
||||
WsMsg.User from = msg.getFrom();
|
||||
String cid = from.getCid();
|
||||
LocationTrackSearchParam param = msg.extractData(LocationTrackSearchParam.class);
|
||||
// String terminalId = param.getTerminalId();
|
||||
String licensePlate = param.getLicensePlate();
|
||||
Integer speed = param.getSpeed();
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
LocalDateTime startTime = LocalDateTime.now().minusSeconds(60 * 30);
|
||||
int errCount = 0;
|
||||
while (true) {
|
||||
// 检查是否被取消
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
log.info("任务被取消");
|
||||
return;
|
||||
}
|
||||
|
||||
Page<TruckLocationTrackEntity> page = new Page<>(1, 10);
|
||||
page.addOrder(OrderItem.asc("location_time"));
|
||||
|
||||
// 分页查询当前页数据
|
||||
IPage<TruckLocationTrackEntity> resultPage = truckLocationTrackService.page(page, Wrappers.lambdaQuery(TruckLocationTrackEntity.class)
|
||||
.eq(TruckLocationTrackEntity::getLicensePlate, licensePlate)
|
||||
.gt(TruckLocationTrackEntity::getLocationTime, startTime));
|
||||
|
||||
List<TruckLocationTrackEntity> records = resultPage.getRecords();
|
||||
if (records.isEmpty()) {
|
||||
if (errCount >= 3600) {
|
||||
log.error("暂无实时数据, 车牌号: {}, 时间: {}", licensePlate, startTime);
|
||||
Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/realtime")
|
||||
.setData(R.failed(ExceptionMsg.SYS_ERR_MSG, "暂无实时数据"))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
return;
|
||||
}
|
||||
errCount++;
|
||||
if (!ThreadUtil.sleep(1000)) {
|
||||
log.info("任务被取消");
|
||||
return;
|
||||
} else {
|
||||
// startTime = startTime.plusSeconds(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
errCount = 0;
|
||||
|
||||
// 处理当前页数据,按时间间隔推送
|
||||
for (TruckLocationTrackEntity record : records) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
log.info("任务被取消");
|
||||
return;
|
||||
}
|
||||
if (speed > 100) {
|
||||
if (!ThreadUtil.sleep(speed)) {
|
||||
log.info("任务被取消");
|
||||
Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/realtime")
|
||||
.setData(R.failed(ExceptionMsg.SYS_ERR_MSG, "数据发送完成"))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
startTime = record.getLocationTime();
|
||||
Tuple2<Double, Double> doubles = CoordinateConverter.wgs84ToGcj02(record.getLatitude(), record.getLongitude());
|
||||
record.setLatitude(doubles.get_0())
|
||||
.setLongitude(doubles.get_1());
|
||||
boolean publish = Websocket.publish(new WsMsg()
|
||||
.setEvent("down/truck_location_track/realtime")
|
||||
.setData(R.success(record))
|
||||
.setTo(Collections.singletonList(new WsMsg.User().setCid(cid)))
|
||||
);
|
||||
if (!publish) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 其他异常
|
||||
log.error("查询历史轨迹异常", e);
|
||||
}
|
||||
}, threadPoolExecutor);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.njzscloud.localizer.device.controller;
|
||||
|
||||
import com.njzscloud.common.core.utils.R;
|
||||
import com.njzscloud.common.localizer.DeviceStore;
|
||||
import com.njzscloud.common.localizer.tuqiang.Tuqiang;
|
||||
import com.njzscloud.localizer.device.service.LocalizerDeviceService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Slf4j
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/localizer_device")
|
||||
@RequiredArgsConstructor
|
||||
public class LocalizerDeviceController {
|
||||
private final LocalizerDeviceService localizerDeviceService;
|
||||
|
||||
@GetMapping("/load_device")
|
||||
public R<?> loadDevice() {
|
||||
localizerDeviceService.loadDevice();
|
||||
return R.success();
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public R<?> list() {
|
||||
return R.success(DeviceStore.list());
|
||||
}
|
||||
|
||||
@GetMapping("/current")
|
||||
public R<?> current(String terminalId) {
|
||||
Tuqiang.currentLocation(terminalId);
|
||||
return R.success();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.njzscloud.localizer.device.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.njzscloud.localizer.device.pojo.entity.LocalizerDeviceEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface LocalizerDeviceMapper extends BaseMapper<LocalizerDeviceEntity> {
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package com.njzscloud.localizer.device.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import com.njzscloud.common.localizer.contant.LocalizerType;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Accessors(chain = true)
|
||||
@TableName("localizer_device")
|
||||
public class LocalizerDeviceEntity {
|
||||
|
||||
/**
|
||||
* Id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
/**
|
||||
* 车牌
|
||||
*/
|
||||
private String licensePlate;
|
||||
/**
|
||||
* 设备 Id
|
||||
*/
|
||||
protected String terminalId;
|
||||
|
||||
/**
|
||||
* 设备类型
|
||||
*/
|
||||
protected LocalizerType localizerType;
|
||||
|
||||
/**
|
||||
* 速度阈值
|
||||
*/
|
||||
private Integer speedThreshold;
|
||||
/**
|
||||
* 是否可用; 0-->否、1-->是
|
||||
*/
|
||||
private Boolean canuse;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package com.njzscloud.localizer.device.service;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.njzscloud.common.localizer.DeviceStore;
|
||||
import com.njzscloud.common.localizer.Localizer;
|
||||
import com.njzscloud.localizer.device.mapper.LocalizerDeviceMapper;
|
||||
import com.njzscloud.localizer.device.pojo.entity.LocalizerDeviceEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class LocalizerDeviceService extends ServiceImpl<LocalizerDeviceMapper, LocalizerDeviceEntity> implements IService<LocalizerDeviceEntity> {
|
||||
|
||||
public void loadDevice() {
|
||||
List<LocalizerDeviceEntity> list = this.list();
|
||||
List<Localizer> localizers = list.stream().map(it -> BeanUtil.copyProperties(it, Localizer.class)).collect(Collectors.toList());
|
||||
if (CollUtil.isEmpty(localizers)) return;
|
||||
DeviceStore.setLocalizers(localizers);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package com.njzscloud.localizer.track.controller;
|
||||
|
||||
import com.njzscloud.common.core.utils.R;
|
||||
import com.njzscloud.common.localizer.tuqiang.Tuqiang;
|
||||
import com.njzscloud.localizer.track.service.TruckLocationTrackService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* 车辆定位数据
|
||||
*/
|
||||
@Slf4j
|
||||
@CrossOrigin
|
||||
@RestController
|
||||
@RequestMapping("/truck_location_track")
|
||||
@RequiredArgsConstructor
|
||||
public class TruckLocationTrackController {
|
||||
|
||||
private final TruckLocationTrackService truckLocationTrackService;
|
||||
|
||||
@GetMapping("/start")
|
||||
public R<?> startTrack(@RequestParam("licensePlate") String licensePlate) {
|
||||
truckLocationTrackService.startTrack(licensePlate);
|
||||
return R.success();
|
||||
}
|
||||
|
||||
@GetMapping("/stop")
|
||||
public R<?> stopTrack(@RequestParam("licensePlate") String licensePlate) {
|
||||
truckLocationTrackService.stopTrack(licensePlate);
|
||||
return R.success();
|
||||
}
|
||||
|
||||
@GetMapping("/send")
|
||||
public R<?> send(@RequestParam("terminalId") String terminalId,
|
||||
@RequestParam("directive") String directive) {
|
||||
Tuqiang.sendDirective(terminalId, directive);
|
||||
return R.success();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.njzscloud.localizer.track.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.njzscloud.localizer.track.pojo.entity.TruckLocationTrackEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 车辆定位数据
|
||||
*/
|
||||
@Mapper
|
||||
public interface TruckLocationTrackMapper extends BaseMapper<TruckLocationTrackEntity> {
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
package com.njzscloud.localizer.track.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 车辆定位数据
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Accessors(chain = true)
|
||||
@TableName("truck_location_track")
|
||||
public class TruckLocationTrackEntity {
|
||||
|
||||
/**
|
||||
* Id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 车牌
|
||||
*/
|
||||
private String licensePlate;
|
||||
/**
|
||||
* 设备号
|
||||
*/
|
||||
private String terminalId;
|
||||
|
||||
/**
|
||||
* 经度; 单位:度
|
||||
*/
|
||||
private Double longitude;
|
||||
|
||||
/**
|
||||
* 纬度; 单位:度
|
||||
*/
|
||||
private Double latitude;
|
||||
|
||||
/**
|
||||
* 海拔; 米
|
||||
*/
|
||||
private Integer altitude;
|
||||
|
||||
/**
|
||||
* 速度; 千米/小时
|
||||
*/
|
||||
private Double speed;
|
||||
|
||||
/**
|
||||
* 定位时间
|
||||
*/
|
||||
private LocalDateTime locationTime;
|
||||
|
||||
/**
|
||||
* 方向; 正北为 0 度
|
||||
*/
|
||||
private Integer direction;
|
||||
|
||||
/**
|
||||
* 是否超速; 0-->否、1-->是
|
||||
*/
|
||||
private Boolean overspeed;
|
||||
|
||||
/**
|
||||
* 是否为补偿数据; 0-->否、1-->是
|
||||
*/
|
||||
private Boolean compensate;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(fill = FieldFill.INSERT)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.njzscloud.localizer.track.pojo.param;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Accessors(chain = true)
|
||||
public class LocationTrackSearchParam {
|
||||
private String terminalId;
|
||||
/**
|
||||
* 车牌
|
||||
*/
|
||||
private String licensePlate;
|
||||
private LocalDateTime startTime;
|
||||
private LocalDateTime endTime;
|
||||
private Integer speed;
|
||||
|
||||
public Integer getSpeed() {
|
||||
return speed == null || speed <= 0 ? 1000 : speed;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package com.njzscloud.localizer.track.service;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.njzscloud.common.localizer.mqtt.result.RealtimeLocationResult;
|
||||
import com.njzscloud.common.localizer.service.LocalizerService;
|
||||
import com.njzscloud.localizer.track.mapper.TruckLocationTrackMapper;
|
||||
import com.njzscloud.localizer.track.pojo.entity.TruckLocationTrackEntity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 车辆定位数据
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TruckLocationTrackService extends ServiceImpl<TruckLocationTrackMapper, TruckLocationTrackEntity> implements LocalizerService, IService<TruckLocationTrackEntity> {
|
||||
|
||||
private static final ConcurrentHashMap<String, Boolean> TRACK_FLAG = new ConcurrentHashMap<>();
|
||||
@Value("${trackFlag}")
|
||||
boolean trackFlag = false;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void save(List<RealtimeLocationResult> dataList) {
|
||||
for (RealtimeLocationResult realtimeLocationResult : dataList) {
|
||||
if (realtimeLocationResult == null) {
|
||||
return;
|
||||
}
|
||||
String licensePlate = realtimeLocationResult.getLicensePlate();
|
||||
if (trackFlag && !TRACK_FLAG.getOrDefault(licensePlate, Boolean.FALSE)) {
|
||||
return;
|
||||
}
|
||||
String time = realtimeLocationResult.getTime();
|
||||
double latitude = realtimeLocationResult.getLatitude();
|
||||
double longitude = realtimeLocationResult.getLongitude();
|
||||
|
||||
if (latitude <= 0 && longitude <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
TruckLocationTrackEntity entity = new TruckLocationTrackEntity()
|
||||
.setLicensePlate(licensePlate)
|
||||
.setTerminalId(realtimeLocationResult.getTerminalId())
|
||||
.setLatitude(latitude)
|
||||
.setLongitude(longitude)
|
||||
.setAltitude(realtimeLocationResult.getAltitude())
|
||||
.setSpeed(realtimeLocationResult.getSpeed())
|
||||
.setLocationTime(DateUtil.parseLocalDateTime(time))
|
||||
.setDirection(realtimeLocationResult.getDirection())
|
||||
.setOverspeed(realtimeLocationResult.isOverspeed())
|
||||
.setCompensate(realtimeLocationResult.getType() == 1);
|
||||
this.save(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public void startTrack(String licensePlate) {
|
||||
TRACK_FLAG.put(licensePlate, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public void stopTrack(String licensePlate) {
|
||||
TRACK_FLAG.put(licensePlate, Boolean.FALSE);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,24 @@
|
|||
spring:
|
||||
servlet:
|
||||
multipart:
|
||||
location: D:\ProJects\gov_manage\njzscloud-supervisory-svr\logs\temp
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:33061/green_frog?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true&allowMultiQueries=true
|
||||
username: dbard01
|
||||
password: mik9uvNZ
|
||||
trackFlag: false
|
||||
mybatis-plus:
|
||||
tunnel:
|
||||
enable: false
|
||||
ssh:
|
||||
host: 121.43.155.83
|
||||
port: 22
|
||||
user: root
|
||||
credentials: D:/W/首炬/dzsj.pem
|
||||
localPort: 33061
|
||||
db:
|
||||
host: rm-bp1w3397b718u1882.mysql.rds.aliyuncs.com
|
||||
port: 3306
|
||||
mqtt:
|
||||
enabled: true
|
||||
broker: tcp://139.224.54.144:1883
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
spring:
|
||||
application:
|
||||
name: localizer
|
||||
servlet:
|
||||
multipart:
|
||||
location: D:\ProJects\gov_manage\njzscloud-supervisory-svr\logs\temp
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:33061/green_frog?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true&allowMultiQueries=true
|
||||
username: dbard01
|
||||
password: mik9uvNZ
|
||||
|
||||
trackFlag: false
|
||||
|
||||
mqtt:
|
||||
enabled: true
|
||||
|
|
|
|||
|
|
@ -369,6 +369,7 @@
|
|||
|
||||
// WebSocket实例
|
||||
let websocket = null;
|
||||
let ii = null;
|
||||
|
||||
// 连接WebSocket
|
||||
connectBtn.addEventListener('click', () => {
|
||||
|
|
@ -388,8 +389,8 @@
|
|||
const authorization = wsAuthorizationInput.value.trim();
|
||||
try {
|
||||
// 创建WebSocket连接
|
||||
url = `${url}?authorization=${authorization}`;
|
||||
websocket = new WebSocket(url);
|
||||
url = `${url}`;
|
||||
websocket = new WebSocket("wss://admin.dzzszy.com/api/fdx");
|
||||
|
||||
// 连接成功
|
||||
websocket.onopen = () => {
|
||||
|
|
@ -398,6 +399,9 @@
|
|||
|
||||
// 显示连接详情
|
||||
connectionDetails.textContent = `地址: ${url}`;
|
||||
ii = setInterval(() => {
|
||||
websocket.send("{\"action\":\"ping\",\"event\":\"ping\"}")
|
||||
}, 10000)
|
||||
};
|
||||
|
||||
// 接收消息
|
||||
|
|
@ -410,15 +414,27 @@
|
|||
updateConnectionStatus(false);
|
||||
addSystemMessage(`连接已关闭 (代码: ${event.code}, 原因: ${event.reason || '无'})`);
|
||||
connectionDetails.textContent = '未连接到服务器';
|
||||
if (ii != null) {
|
||||
clearInterval(ii)
|
||||
ii = null
|
||||
}
|
||||
};
|
||||
|
||||
// 连接错误
|
||||
websocket.onerror = (error) => {
|
||||
addSystemMessage(`发生错误: ${error.message || '未知错误'}`, true);
|
||||
if (ii != null) {
|
||||
clearInterval(ii)
|
||||
ii = null
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
alert(`连接失败: ${error.message}`);
|
||||
updateConnectionStatus(false);
|
||||
if (ii != null) {
|
||||
clearInterval(ii)
|
||||
ii = null
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue