diff --git a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/JT808.java b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/JT808.java index 334a892..2de2b6c 100644 --- a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/JT808.java +++ b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/JT808.java @@ -151,6 +151,8 @@ public final class JT808 { public static JT808Message parseMessage(ByteBuf buf) { JT808Message jt808Message = new JT808Message(); + byte[] h_b = ByteBufUtil.getBytes(buf); + try { // 1. 消息ID (2字节) jt808Message.setMessageId(buf.readUnsignedShort()); @@ -184,14 +186,22 @@ public final class JT808 { jt808Message.setMessageBody(array); // 7. 校验码 (1字节) - jt808Message.setCheckCode(buf.readByte()); + byte checkCode = buf.readByte(); + jt808Message.setCheckCode(checkCode); - // 验证校验码 - if (!verifyCheckCode(jt808Message, buf)) { - log.error("校验码错误: {}", jt808Message); - return null; + + if (jt808Message.getMessageId() == 0x704) { + log.info("报文:{}", h_b); } + int code = 0; + for (int i = 0; i < h_b.length - 1; i++) { + code = code ^ h_b[i]; + } + if (code != checkCode) { + log.error("校验码错误: {} {}", code, checkCode); + // return null; + } return jt808Message; } } catch (Exception e) { diff --git a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/message/JT808Message.java b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/message/JT808Message.java index 01def22..53eb977 100644 --- a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/message/JT808Message.java +++ b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/message/JT808Message.java @@ -7,6 +7,9 @@ import lombok.Setter; import lombok.experimental.Accessors; import lombok.extern.slf4j.Slf4j; +import java.util.ArrayList; +import java.util.List; + /** * JT808协议消息实体类 * 用于存储解析后的JT808协议消息内容 @@ -31,6 +34,7 @@ public class JT808Message { private byte[] messageBody; // 校验码 (1字节) private byte checkCode; + public JT808Message() { } @@ -39,6 +43,17 @@ public class JT808Message { return messageBodyProps & 0x3FF; } + public List getBodyBytes() { + if (messageBody == null || messageBody.length == 0) { + return null; + } + ArrayList integers = new ArrayList<>(messageBody.length); + for (byte b : messageBody) { + integers.add((int) b); + } + return integers; + } + // 从消息体属性中获取是否分包 public boolean isPackaged() { return (messageBodyProps & 0x4000) != 0; diff --git a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageCenter.java b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageCenter.java index b78df30..fc59c39 100644 --- a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageCenter.java +++ b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageCenter.java @@ -31,6 +31,10 @@ public class JT808MessageCenter { Map> m = listeners.computeIfPresent(localizerType, (k, v) -> { MessageType messageType = MessageType.getMessageType(messageId); + if (messageType == MessageType.TerminalLocationBatchReport) { + log.info("批量上报:{}", message); + } + if (messageType == null) { log.error("未找到消息类型,设备号:{},消息 Id:0x{}", terminalId, Integer.toHexString(messageId)); return v; diff --git a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageListener.java b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageListener.java index caa1dd1..1beb88b 100644 --- a/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageListener.java +++ b/njzscloud-common/njzscloud-common-localizer/src/main/java/com/njzscloud/common/localizer/jt808/support/JT808MessageListener.java @@ -134,6 +134,9 @@ public abstract class JT808MessageListener { int speedThreshold = localizer.getSpeedThreshold(); for (int i = 0; i < count; i++) { int length = byteBuf.readUnsignedShort(); + /* if (length > 28) { // 有扩展信息 + + } */ LocationReportMessage locationReportMsg = new LocationReportMessage(byteBuf.slice(byteBuf.readerIndex(), length)); byteBuf.skipBytes(length); double speed = locationReportMsg.getSpeed(); @@ -144,6 +147,8 @@ public abstract class JT808MessageListener { Mqtt.publish(terminalId + "/track_location", realtimeLocationResult); Mqtt.publish(terminalId + "/track_location_real", realtimeLocationResult); } + } catch (Exception e) { + log.error("批量上报处理失败:{} {}", terminalId, message.getFlowId()); } finally { byteBuf.release(); } diff --git a/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/Hsoa.java b/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/Hsoa.java index 12a4428..d50c930 100644 --- a/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/Hsoa.java +++ b/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/Hsoa.java @@ -41,6 +41,10 @@ public class Hsoa { param.setCityCode(defaultPlace.getCity()) .setCityName(defaultPlace.getCityName()) ; + if (StrUtil.isBlank(tnt) || StrUtil.isBlank(refTnt)) { + return new HsoaResult<>() + .setSuccess(false); + } return API.pushVehicleTrajectory(param, new TokenParam().setTnt(tnt).setRefTnt(refTnt)); } finally { rlock.unlock(); @@ -64,6 +68,7 @@ public class Hsoa { } else { refTnt = ""; tnt = ""; + log.error("政务平台登录失败"); } } else if (now - lastLoginTime > hsoaProperties.getExpire() - 60) { HsoaResult loginResult = API.refreshToken(new RefreshTokenParam().setRefTnt(refTnt)); @@ -75,6 +80,7 @@ public class Hsoa { } else { refTnt = ""; tnt = ""; + log.error("政务平台登录失败"); } } } catch (Exception e) { diff --git a/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/controller/HsoaController.java b/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/controller/HsoaController.java index dd76012..cc01310 100644 --- a/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/controller/HsoaController.java +++ b/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/controller/HsoaController.java @@ -4,17 +4,17 @@ import com.njzscloud.common.core.utils.R; import com.njzscloud.supervisory.hsoa.Hsoa; import com.njzscloud.supervisory.hsoa.pojo.param.PushVehicleTrajectoryParam; import com.njzscloud.supervisory.hsoa.pojo.result.HsoaResult; +import com.njzscloud.supervisory.hsoa.service.HsoaService; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @RequestMapping("/hsoa") public class HsoaController { + private final HsoaService hsoaService; + @PostMapping("/push") public R push(@RequestBody PushVehicleTrajectoryParam pushVehicleTrajectoryParam) { HsoaResult objectHsoaResult = Hsoa.pushVehicleTrajectory(pushVehicleTrajectoryParam); @@ -23,4 +23,9 @@ public class HsoaController { } return R.failed(); } + + @GetMapping("/push_order") + public R pushOrder(@RequestParam Long orderId, @RequestParam Integer count) { + return R.success(hsoaService.pushOrder(orderId, count)); + } } diff --git a/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/service/HsoaService.java b/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/service/HsoaService.java new file mode 100644 index 0000000..3ec6bdf --- /dev/null +++ b/njzscloud-svr/src/main/java/com/njzscloud/supervisory/hsoa/service/HsoaService.java @@ -0,0 +1,141 @@ +package com.njzscloud.supervisory.hsoa.service; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapBuilder; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.thread.ThreadUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.njzscloud.common.core.ex.Exceptions; +import com.njzscloud.supervisory.biz.pojo.entity.TruckLocationTrackEntity; +import com.njzscloud.supervisory.biz.service.TruckLocationTrackService; +import com.njzscloud.supervisory.hsoa.Hsoa; +import com.njzscloud.supervisory.hsoa.pojo.param.PushVehicleTrajectoryParam; +import com.njzscloud.supervisory.hsoa.pojo.result.HsoaResult; +import com.njzscloud.supervisory.order.pojo.result.OrderPagingResult; +import com.njzscloud.supervisory.order.service.OrderInfoService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +@Slf4j +@Service +@RequiredArgsConstructor +public class HsoaService { + private final OrderInfoService orderInfoService; + private final TruckLocationTrackService truckLocationTrackService; + private final AtomicBoolean run = new AtomicBoolean(false); + private final AtomicInteger succ = new AtomicInteger(0); + private final AtomicInteger fail = new AtomicInteger(0); + private final AtomicInteger total = new AtomicInteger(0); + private final AtomicLong order = new AtomicLong(0); + + public synchronized Map pushOrder(Long orderId, Integer count) { + MapBuilder builder = MapUtil.builder(); + + if (run.get()) { + int i1 = total.get(); + int i2 = succ.get(); + int i3 = fail.get(); + long v = order.get(); + return builder + .put("订单", v) + .put("任务数量", i1) + .put("成功数量", i2) + .put("失败数量", i3) + .put("剩余数量", i1 - i2 - i3) + .build(); + } + OrderPagingResult orderDetail = orderInfoService.detail(orderId); + Assert.notNull(orderDetail, () -> Exceptions.clierr("订单不存在")); + String licensePlate = orderDetail.getLicensePlate(); + String transCompanyName = orderDetail.getTransCompanyName(); + List list = truckLocationTrackService.list(Wrappers.lambdaQuery().eq(TruckLocationTrackEntity::getOrderId, orderId)); + + if (list.isEmpty()) { + return builder + .put("订单", orderId) + .put("任务数量", 0) + .build(); + } + if (count == null || count == 0) { + count = list.size(); + } else { + count = Math.min(count, list.size()); + } + run.set(true); + order.set(orderId); + total.set(count); + succ.set(0); + fail.set(0); + int c = count; + Thread thread = new Thread(() -> { + for (int i = 0; i < c; i++) { + ThreadUtil.sleep(1000); + TruckLocationTrackEntity locationTrack = list.get(i); + boolean b = run.get(); + if (!b) { + return; + } + try { + Double longitude = locationTrack.getLongitude(); + Double latitude = locationTrack.getLatitude(); + Double speed = locationTrack.getSpeed(); + Integer direction = locationTrack.getDirection(); + LocalDateTime locationTime = locationTrack.getLocationTime(); + String time = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(locationTime); + HsoaResult result = Hsoa.pushVehicleTrajectory(new PushVehicleTrajectoryParam() + .setCompanyName(transCompanyName) + .setTransportLicense(orderDetail.getCertificateSn()) + .setPlateNumber(licensePlate) + .setVehicleType(orderDetail.getTruckCategory()) + .setLongitude(longitude + "") + .setLatitude(latitude + "") + .setSpeed(speed) + .setDirection(direction + 0.0) + .setStateType("正常行驶") + .setAlarmType("无") + .setLoadStatus("2") + .setSealedStatus("1") + .setLiftStatus("0") + .setAccStatus(1) + .setGpsTime(time) + .setLocationMode("WGS84") + ); + if (result == null || !result.isSuccess()) { + fail.incrementAndGet(); + log.error("推送定位数据失败,数据Id:{}", locationTrack.getId()); + } else { + succ.incrementAndGet(); + } + + } catch (Exception e) { + fail.incrementAndGet(); + log.error("推送定位数据失败,数据Id:{}", locationTrack.getId(), e); + } + } + run.set(false); + }); + thread.setDaemon(true); + thread.start(); + + int i1 = total.get(); + int i2 = succ.get(); + int i3 = fail.get(); + return builder + .put("订单", orderId) + .put("任务数量", i1) + .put("成功数量", i2) + .put("失败数量", i3) + .put("剩余数量", i1 - i2 - i3) + .build(); + + } +} diff --git a/njzscloud-svr/src/main/resources/application-dev.yml b/njzscloud-svr/src/main/resources/application-dev.yml index 68cd0e9..95390bb 100644 --- a/njzscloud-svr/src/main/resources/application-dev.yml +++ b/njzscloud-svr/src/main/resources/application-dev.yml @@ -29,6 +29,7 @@ spring: - /biz_audit_config/copy - /order_info/gps_test - /wechatTemplateMessage/bind + - /hsoa/push_order app: default-place: province: 320000 @@ -93,4 +94,4 @@ mqtt: hsoa: base-url: http://60.173.195.121:9908 username: chuz_trajectory - password: e9t2YsgM5ug/kpIZpMdY9e9uXq60jyEQ30zQX+BzphI= + password: e9t2YsgM5ug%2FkpIZpMdY9e9uXq60jyEQ30zQX%2BBzphI%3D diff --git a/njzscloud-svr/src/main/resources/application-prod.yml b/njzscloud-svr/src/main/resources/application-prod.yml index ab1d8a8..1043904 100644 --- a/njzscloud-svr/src/main/resources/application-prod.yml +++ b/njzscloud-svr/src/main/resources/application-prod.yml @@ -27,6 +27,7 @@ spring: - /district/areaList - /biz_audit_config/copy - /wechatTemplateMessage/bind + - /hsoa/push_order app: in-out-gap: 180 @@ -83,4 +84,4 @@ localizer: hsoa: base-url: http://117.68.7.91:8088 username: chuz_trajectory - password: e9t2YsgM5ug/kpIZpMdY9e9uXq60jyEQ30zQX+BzphI= + password: e9t2YsgM5ug%2FkpIZpMdY9e9uXq60jyEQ30zQX%2BBzphI%3D