diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java b/jsowell-admin/src/main/java/com/jsowell/service/CameraService.java similarity index 67% rename from jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java rename to jsowell-admin/src/main/java/com/jsowell/service/CameraService.java index 1888dbd3d..5cc66478f 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/camera/service/CameraService.java +++ b/jsowell-admin/src/main/java/com/jsowell/service/CameraService.java @@ -1,4 +1,4 @@ -package com.jsowell.thirdparty.camera.service; +package com.jsowell.service; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; @@ -8,21 +8,28 @@ import com.aliyun.oss.model.ObjectMetadata; import com.jsowell.common.config.AliyunOssConfig; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.core.redis.RedisCache; +import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.file.AliyunOssUploadUtils; import com.jsowell.common.util.file.ImageUtils; +import com.jsowell.common.util.sign.MD5Util; +import com.jsowell.netty.server.mqtt.BootNettyMqttChannelInboundHandler; import com.jsowell.pile.domain.PileCameraInfo; import com.jsowell.pile.dto.GenerateOccupyOrderDTO; import com.jsowell.pile.dto.camera.CameraHeartBeatDTO; import com.jsowell.pile.dto.camera.CameraIdentifyResultsDTO; +import com.jsowell.pile.service.IMemberBasicInfoService; +import com.jsowell.pile.service.IMemberPlateNumberRelationService; import com.jsowell.pile.service.IPileCameraInfoService; import com.jsowell.pile.service.OrderPileOccupyService; +import com.jsowell.pile.vo.uniapp.MemberVO; import io.netty.channel.Channel; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -36,6 +43,7 @@ import java.util.Base64; import javax.imageio.ImageIO; import java.util.List; +import java.util.Locale; /** * 相机管理系统 Service @@ -56,6 +64,12 @@ public class CameraService { @Autowired private OrderPileOccupyService orderPileOccupyService; + @Autowired + private BootNettyMqttChannelInboundHandler handler; + + @Autowired + private IMemberBasicInfoService memberBasicInfoService; + public void receiveIdentifyResults(JSONObject jsonObject) { // 区分入场和出场 @@ -85,6 +99,7 @@ public class CameraService { /** * 车辆入场 + * * @param jsonObject */ private void vehicleEntry(JSONObject jsonObject, String parkingState) { @@ -92,7 +107,34 @@ public class CameraService { // boolean result = saveCarPicture2Redis(jsonObject, parkingState); // 将信息存数据库 - saveInfo2DataBase(jsonObject); + boolean result = saveInfo2DataBase(jsonObject); + if (!result) { + logger.error("车辆入场,将信息存入数据库 error, 源数据:{}", jsonObject); + return; + } + // 根据车牌号找出绑定小程序的用户 + CameraIdentifyResultsDTO.ProductH.Plate plate = JSONObject.parseObject(jsonObject.getJSONObject("product_h").getJSONObject("plate").toJSONString(), + CameraIdentifyResultsDTO.ProductH.Plate.class); + if (plate == null) { + return; + } + // Base64 解密 + String plateNumber = cn.hutool.core.codec.Base64.decodeStr(plate.getPlate()); + List memberList = memberBasicInfoService.getMemberInfoByPlateNumber(plateNumber); + if (CollectionUtils.isNotEmpty(memberList)) { + // 如果是有小程序的用户,则先降地锁,然后生成一笔占桩订单 + // 发送降锁指令 + + // 生成占桩订单 + } else { + // 如果没有小程序账号,再根据此车牌是否有挂起的占桩订单 + + // 如果没有,则先降锁,再生成一笔占桩订单 + + // 如果有已挂起的占桩订单,则不予降锁,将“已存在有未支付的占桩订单”信息返回 + + } + // TODO 生成占桩订单 // GenerateOccupyOrderDTO dto = new GenerateOccupyOrderDTO(); @@ -163,7 +205,7 @@ public class CameraService { /** * 保存图像 * @param base64Image 图像的Base64编码 - * @param fileName 文件名 + * @param fileName 文件名 * @return */ private String saveImage(String base64Image, String fileName) { @@ -195,6 +237,63 @@ public class CameraService { return null; } + + + + /** + * 发送具体指令到某主题 + * @param sn 设备 sn + * @param msgType 消息类型 + * @param msgPrefix 消息前缀 + * @param topic 主题 + * @param msgData 消息内容 + * @throws InterruptedException + */ + public void sendMsg2Topic(String sn, String msgType, String msgPrefix, String topic, JSONObject msgData) throws InterruptedException { + JSONObject jsonObject = spliceStr(sn, msgType, msgPrefix); + // 通过sn查找出对应的channelId + String mqttConnectRedisKey = CacheConstants.MQTT_CONNECT_SN + sn; + Object cacheObject = redisCache.getCacheObject(mqttConnectRedisKey); + if (cacheObject == null) { + return; + } + String channelId = (String) cacheObject; + if (msgData != null) { + jsonObject.put("msg_data", msgData); + } + + logger.info("给相机发送远程命令,sn:{}, 消息类型:{}, 主题:{}, 最终发送数据:{}", sn, msgType, topic, jsonObject.toJSONString()); + // 发送消息 + handler.sendMsg(channelId, topic, jsonObject.toJSONString()); + } + + /** + * 根据规则拼装字符串 + * @param sn 设备 sn + * @param msgType 消息类型 + * @param msgPrefix 消息前缀 + * @return 拼装好的json对象 + */ + private JSONObject spliceStr(String sn, String msgType, String msgPrefix) { + StringBuilder sb = new StringBuilder(); + String msgId = msgPrefix + DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSS) + "01"; + String timeStamp = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS); + sb.append("sn=").append(sn) + .append("×tamp=").append(timeStamp) + .append("&msg_id=").append(msgId) + .append("&msg_type=").append(msgType); + // 进行 32 位 MD5 计算 + String sign = MD5Util.MD5Encode(sb.toString()).toUpperCase(Locale.ROOT); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("sign", sign); + jsonObject.put("sn", sn); + jsonObject.put("timestamp", timeStamp); + jsonObject.put("msg_id", msgId); + jsonObject.put("msg_type", msgType); + + return jsonObject; + } + /** * 将车辆图片信息存入缓存 diff --git a/jsowell-admin/src/main/java/com/jsowell/web/controller/thirdparty/camera/CameraController.java b/jsowell-admin/src/main/java/com/jsowell/web/controller/thirdparty/camera/CameraController.java index 27194aa10..8450cee0d 100644 --- a/jsowell-admin/src/main/java/com/jsowell/web/controller/thirdparty/camera/CameraController.java +++ b/jsowell-admin/src/main/java/com/jsowell/web/controller/thirdparty/camera/CameraController.java @@ -4,13 +4,11 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.jsowell.common.annotation.Anonymous; import com.jsowell.common.core.controller.BaseController; -import com.jsowell.netty.server.mqtt.BootNettyMqttChannelInboundHandler; import com.jsowell.netty.service.camera.CameraBusinessService; import com.jsowell.pile.dto.camera.CameraHeartBeatDTO; import com.jsowell.pile.dto.camera.SendMsg2TopicDTO; import com.jsowell.thirdparty.camera.common.CameraCommonResult; -import com.jsowell.thirdparty.camera.service.CameraService; -import io.netty.channel.ChannelFuture; +import com.jsowell.service.CameraService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -66,7 +64,7 @@ public class CameraController extends BaseController { @PostMapping("/sendMsg2Topic") public void sendMsg2Topic(@RequestBody SendMsg2TopicDTO dto) { try { - cameraBusinessService.sendGroundLockCommand(dto.getSn(), dto.getMsgType(), dto.getMsgPrefix(), dto.getTopic(), dto.getMsgData()); + cameraService.sendMsg2Topic(dto.getSn(), dto.getMsgType(), dto.getMsgPrefix(), dto.getTopic(), dto.getMsgData()); } catch (Exception e) { logger.error("发送消息 error, ", e); } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java index 6f5cc2bce..ba4dd8f3d 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/TransactionRecordsRequestHandler.java @@ -670,12 +670,12 @@ public class TransactionRecordsRequestHandler extends AbstractHandler { // 给车辆绑定优惠券 try { - BigDecimal totalElectricity = new BigDecimal(data.getTotalElectricity()); - if (totalElectricity.compareTo(BigDecimal.TEN) > 0) { - // 充电度数大于10度 - String bindResult = bindCoupon(orderBasicInfo); - log.info("绑定优惠券 订单信息:{}, result:{}", orderBasicInfo, bindResult); - } + // BigDecimal totalElectricity = new BigDecimal(data.getTotalElectricity()); + // if (totalElectricity.compareTo(BigDecimal.TEN) > 0) { + // // 充电度数大于10度 + // } + String bindResult = bindCoupon(orderBasicInfo); + log.info("绑定优惠券 订单信息:{}, result:{}", orderBasicInfo, bindResult); } catch (BusinessException e) { log.error("绑定优惠券 error, code:{}, msg:{}", e.getCode(), e.getMessage()); } catch (Exception e) { diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/server/mqtt/BootNettyMqttChannelInboundHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/server/mqtt/BootNettyMqttChannelInboundHandler.java index 606e397a5..87fd75bdd 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/server/mqtt/BootNettyMqttChannelInboundHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/server/mqtt/BootNettyMqttChannelInboundHandler.java @@ -6,7 +6,6 @@ import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.bean.BeanUtils; import com.jsowell.netty.domain.MqttRequest; import com.jsowell.netty.service.camera.CameraBusinessService; -import com.jsowell.netty.service.camera.impl.CameraBusinessServiceImpl; import com.jsowell.thirdparty.camera.service.CameraService; import io.netty.buffer.Unpooled; import io.netty.channel.*; @@ -17,9 +16,6 @@ import java.net.InetSocketAddress; import java.util.concurrent.ConcurrentHashMap; import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/CameraBusinessService.java b/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/CameraBusinessService.java index f3f17c72a..9e0752714 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/CameraBusinessService.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/CameraBusinessService.java @@ -13,16 +13,6 @@ import java.net.UnknownHostException; * @Date 2023/12/20 15:15:26 */ public interface CameraBusinessService { - /** - * 发送具体指令到某主题 - * @param sn 设备 sn - * @param msgType 消息类型 - * @param msgPrefix 消息前缀 - * @param topic 主题 - * @param msgData 消息内容 - * @throws InterruptedException - */ - public void sendGroundLockCommand(String sn, String msgType, String msgPrefix, String topic, JSONObject msgData) throws InterruptedException; /** * 解析channel中的ip地址, 并将 sn 和 channelId 进行绑定,存入缓存 diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/impl/CameraBusinessServiceImpl.java b/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/impl/CameraBusinessServiceImpl.java index 8724c40ad..6391f4c37 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/impl/CameraBusinessServiceImpl.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/service/camera/impl/CameraBusinessServiceImpl.java @@ -33,33 +33,6 @@ public class CameraBusinessServiceImpl implements CameraBusinessService { @Autowired private BootNettyMqttChannelInboundHandler handler; - /** - * 发送具体指令到某主题 - * @param sn 设备 sn - * @param msgType 消息类型 - * @param msgPrefix 消息前缀 - * @param topic 主题 - * @param msgData 消息内容 - * @throws InterruptedException - */ - public void sendGroundLockCommand(String sn, String msgType, String msgPrefix, String topic, JSONObject msgData) throws InterruptedException { - JSONObject jsonObject = spliceStr(sn, msgType, msgPrefix); - // 通过sn查找出对应的channelId - String mqttConnectRedisKey = CacheConstants.MQTT_CONNECT_SN + sn; - Object cacheObject = redisCache.getCacheObject(mqttConnectRedisKey); - if (cacheObject == null) { - return; - } - String channelId = (String) cacheObject; - if (msgData != null) { - jsonObject.put("msg_data", msgData); - } - - log.info("给相机发送远程命令,sn:{}, 消息类型:{}, 主题:{}, 最终发送数据:{}", sn, msgType, topic, jsonObject.toJSONString()); - // 发送消息 - handler.sendMsg(channelId, topic, jsonObject.toJSONString()); - } - /** * 解析channel中的ip地址, 并将 sn 和 channelId 进行绑定,存入缓存 * @param channel @@ -90,32 +63,6 @@ public class CameraBusinessServiceImpl implements CameraBusinessService { } } - /** - * 根据规则拼装字符串 - * @param sn 设备 sn - * @param msgType 消息类型 - * @param msgPrefix 消息前缀 - * @return 拼装好的json对象 - */ - private JSONObject spliceStr(String sn, String msgType, String msgPrefix) { - StringBuilder sb = new StringBuilder(); - String msgId = msgPrefix + DateUtils.dateTimeNow(DateUtils.YYYYMMDDHHMMSS) + "01"; - String timeStamp = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS); - sb.append("sn=").append(sn) - .append("×tamp=").append(timeStamp) - .append("&msg_id=").append(msgId) - .append("&msg_type=").append(msgType); - // 进行 32 位 MD5 计算 - String sign = MD5Util.MD5Encode(sb.toString()).toUpperCase(Locale.ROOT); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("sign", sign); - jsonObject.put("sn", sn); - jsonObject.put("timestamp", timeStamp); - jsonObject.put("msg_id", msgId); - jsonObject.put("msg_type", msgType); - - return jsonObject; - } public static void main(String[] args) { System.out.println(System.currentTimeMillis()); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/mapper/MemberBasicInfoMapper.java b/jsowell-pile/src/main/java/com/jsowell/pile/mapper/MemberBasicInfoMapper.java index 9b1a5aa42..fe51f7522 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/mapper/MemberBasicInfoMapper.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/mapper/MemberBasicInfoMapper.java @@ -120,4 +120,11 @@ public interface MemberBasicInfoMapper { List getMerchantListByAuth(@Param("deptIds") List deptIds); List queryMerchantVipList(@Param("merchantIdList") List merchantIdList, @Param("dto") QueryMemberInfoDTO dto); + + /** + * 通过车牌号查询用户基本信息 + * @param plateNumber + * @return + */ + List getMemberInfoByPlateNumber(@Param("plateNumber") String plateNumber); } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/IMemberBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/IMemberBasicInfoService.java index c3b60e371..c27c9fad0 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/IMemberBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/IMemberBasicInfoService.java @@ -152,4 +152,11 @@ public interface IMemberBasicInfoService { List queryMerchantVipList(QueryMemberInfoDTO dto); void createMerchantVip(CreateMerchantVipDTO dto); + + /** + * 通过车牌号查询用户基本信息 + * @param plateNumber + * @return + */ + List getMemberInfoByPlateNumber(String plateNumber); } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java index fddbaf5cc..a5baf8d13 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/MemberBasicInfoServiceImpl.java @@ -595,4 +595,14 @@ public class MemberBasicInfoServiceImpl implements IMemberBasicInfoService { updateMemberBalance(updateMemberBalanceDTO); } + /** + * 通过车牌号查询用户基本信息 + * @param plateNumber + * @return + */ + @Override + public List getMemberInfoByPlateNumber(String plateNumber) { + return memberBasicInfoMapper.getMemberInfoByPlateNumber(plateNumber); + } + } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/MemberVO.java b/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/MemberVO.java index 21e86e289..7aa401cb4 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/MemberVO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/vo/uniapp/MemberVO.java @@ -89,4 +89,9 @@ public class MemberVO { * 头像地址 */ private String avatarUrl; + + /** + * 车牌号 + */ + private String plateNumber; } diff --git a/jsowell-pile/src/main/resources/mapper/pile/MemberBasicInfoMapper.xml b/jsowell-pile/src/main/resources/mapper/pile/MemberBasicInfoMapper.xml index 5e48b11cb..87d9c5997 100644 --- a/jsowell-pile/src/main/resources/mapper/pile/MemberBasicInfoMapper.xml +++ b/jsowell-pile/src/main/resources/mapper/pile/MemberBasicInfoMapper.xml @@ -281,4 +281,20 @@ and t2.member_id like '%${dto.memberId}%' + + \ No newline at end of file