diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/controller/ServerController.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/controller/ServerController.java index 5832440..a895391 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/controller/ServerController.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/controller/ServerController.java @@ -3,10 +3,7 @@ package org.dromara.mica.mqtt.server.controller; import com.alibaba.fastjson2.JSONObject; import org.dromara.mica.mqtt.server.service.impl.ServerService; import org.springframework.beans.factory.annotation.Autowired; -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.*; @RequestMapping("/mqtt/server") @RestController @@ -52,4 +49,13 @@ public class ServerController { return service.set_time(body); } + @GetMapping("/openFloodgate/{sn}") + public boolean openFloodgate(@PathVariable String sn){ + return service.openFloodgate(sn); + } + + @GetMapping("/lock/{sn}") + public boolean lock(@PathVariable String sn){ + return service.locked(sn); + } } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarInfo.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarInfo.java index 46dbb2c..285f12d 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarInfo.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarInfo.java @@ -16,7 +16,7 @@ public class CarInfo implements Serializable { private static final long serialVersionUID = 1L; /** customer_id */ - private Long customerId; + private Long id; /** 白名单生效时间 */ diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarPark.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarPark.java new file mode 100644 index 0000000..ea81dd8 --- /dev/null +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarPark.java @@ -0,0 +1,70 @@ +package org.dromara.mica.mqtt.server.entity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +/** + * + * @author lz + * @date 2026-02-24 + */ +@Data +@TableName("car_park") +public class CarPark implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 主键ID + */ + @TableId(type = IdType.AUTO) // 自增主键 + private Long id; + + /** + * 车场名称 + */ + private String name; + + /** + * 所属空间 + */ + private Long spaceId; + + /** + * 车位总数 + */ + private Long carsNum; + + /** + * 余位数 + */ + private Long surplusNum; + + /** + * 备注 + */ + private String remark; + + /** + * 创建者 + */ + private Long createUser; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) // 插入时自动填充 + private Date createTime; + + /** + * 更新者 + */ + private Long updateUser; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) // 插入/更新时自动填充 + private Date updateTime; +} diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkItem.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkItem.java index 1237010..052a551 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkItem.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkItem.java @@ -27,7 +27,7 @@ public class CarParkItem implements Serializable { /** * 设备id */ - private String equipmentId; + private Long equipmentId; /** * 停车场id diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkRecord.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkRecord.java index efbdafe..080c6e8 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkRecord.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/CarParkRecord.java @@ -36,6 +36,11 @@ public class CarParkRecord implements Serializable { */ private Long customerId; + /* + * 车牌号 + * */ + private String plate; + /** * 是否下发(0未下发1已下发) */ @@ -46,4 +51,9 @@ public class CarParkRecord implements Serializable { */ private String clientId; + /* + * 设备序列号 + * */ + private String sequence; + } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/Equipment.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/Equipment.java index f3a5bdf..4b50890 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/Equipment.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/entity/Equipment.java @@ -45,4 +45,8 @@ public class Equipment implements Serializable { /** 设备状态(0在线 1离线) */ private String flag; + /* 车辆设备字段 杆是否被锁住 0:未上锁 1: 已上锁 */ + private String locked; + + } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/listener/CarMessageListener.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/listener/CarMessageListener.java index cacf4c7..0fe5963 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/listener/CarMessageListener.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/listener/CarMessageListener.java @@ -58,8 +58,8 @@ public class CarMessageListener { private static String key = "1234567898765432"; -// private String jinjiangUrl = "http://127.0.0.1:6609/"; - private String jinjiangUrl = "http://192.168.155.42:6609/"; + private String jinjiangUrl = "http://127.0.0.1:6609/"; +// private String jinjiangUrl = "http://192.168.155.42:6609/"; /** * 心跳 @@ -97,7 +97,7 @@ public class CarMessageListener { carParkRecord.setClientId(whiteListOperatorPO.getId()); //新增修改和删除车牌得回执信息一致,通过id区分 if (whiteListOperatorPO.getId().contains("del_")) { - carParkRecord.setSync("2"); + carParkRecord.setSync("3"); } else { carParkRecord.setSync("1"); } @@ -244,7 +244,6 @@ public class CarMessageListener { public void gpio_out(String topic, byte[] message) { log.info("IO输出事件监听消息 -> Topic: {}, message: {}", topic, new String(message)); String data = new String(message, StandardCharsets.UTF_8); - log.info("IO输出事件监听:{}", data); } @@ -273,4 +272,11 @@ public class CarMessageListener { String data = new String(message, StandardCharsets.UTF_8); } + @MqttServerFunction("device/${sn}/message/down/set_time/reply") + public void set_time(String topic, byte[] message) { + log.info("订阅离线数据数量 -> Topic: {}, message: {}", topic, new String(message)); + String data = new String(message, StandardCharsets.UTF_8); + } + + } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarInfoMapper.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarInfoMapper.java index 10ce42c..f13d187 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarInfoMapper.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarInfoMapper.java @@ -10,5 +10,4 @@ import java.util.List; public interface CarInfoMapper extends BaseMapper { List selectCarInfoList(CarInfo car); - } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkMapper.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkMapper.java new file mode 100644 index 0000000..bf609de --- /dev/null +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkMapper.java @@ -0,0 +1,9 @@ +package org.dromara.mica.mqtt.server.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.dromara.mica.mqtt.server.entity.CarPark; + +@Mapper +public interface CarParkMapper extends BaseMapper { +} diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkRecordMapper.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkRecordMapper.java index 35e7d99..05b76e6 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkRecordMapper.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarParkRecordMapper.java @@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.dromara.mica.mqtt.server.entity.CarParkRecord; +import java.util.List; + @Mapper public interface CarParkRecordMapper extends BaseMapper { - + List selectWithEquipmentSequence(); } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarPassGatherMapper.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarPassGatherMapper.java index 374eba2..ff61eb4 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarPassGatherMapper.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/mapper/CarPassGatherMapper.java @@ -2,8 +2,11 @@ package org.dromara.mica.mqtt.server.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import org.dromara.mica.mqtt.server.entity.CarPassGather; +import java.util.List; + @Mapper public interface CarPassGatherMapper extends BaseMapper { diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/pojo/DeviceIOLockRequestPO.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/pojo/DeviceIOLockRequestPO.java new file mode 100644 index 0000000..5705348 --- /dev/null +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/pojo/DeviceIOLockRequestPO.java @@ -0,0 +1,45 @@ +package org.dromara.mica.mqtt.server.pojo; + +import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class DeviceIOLockRequestPO { + /** + * 消息ID,用于关联具体消息 + */ + @JsonProperty("id") + private String id; + + /** + * 设备序列号 + */ + @JsonProperty("sn") + private String sn; + + /** + * 消息名称 + */ + @JsonProperty("name") + private String name; + + /** + * 消息版本,目前都填1.0 + */ + @JsonProperty("version") + private String version = "1.0"; + + /** + * 时间戳 + */ + @JsonProperty("timestamp") + private long timestamp = System.currentTimeMillis() / 1000; + + /** + * 消息负载 + */ + @JsonProperty("payload") + private JSONObject payload; + +} diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/pojo/OpenFloodgatePO.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/pojo/OpenFloodgatePO.java new file mode 100644 index 0000000..43a694e --- /dev/null +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/pojo/OpenFloodgatePO.java @@ -0,0 +1,39 @@ +package org.dromara.mica.mqtt.server.pojo; + + +import lombok.Data; +import com.alibaba.fastjson2.JSONObject; + +@Data +public class OpenFloodgatePO { + /** + * 消息ID,用于关联具体消息 + */ + private String id; + + /** + * 设备序列号 + */ + private String sn; + + /** + * 消息名称(固定为gpio_out) + */ + private String name; + + /** + * 消息版本(目前都填1.0) + */ + private String version = "1.0"; + + /** + * 时间戳 + */ + private Long timestamp = System.currentTimeMillis() / 1000; + + /** + * 消息负载 + */ + private JSONObject payload; + +} diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarParkRecordService.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarParkRecordService.java index 0d48072..25ad1c9 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarParkRecordService.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarParkRecordService.java @@ -3,9 +3,13 @@ package org.dromara.mica.mqtt.server.service; import com.baomidou.mybatisplus.extension.service.IService; import org.dromara.mica.mqtt.server.entity.CarParkRecord; +import java.util.List; + public interface ICarParkRecordService extends IService { int updateByClientId(CarParkRecord carParkRecord); void delByClientId(CarParkRecord carParkRecord); + + List listSn(); } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassGatherService.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassGatherService.java index ab1cba5..8486716 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassGatherService.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassGatherService.java @@ -2,8 +2,13 @@ package org.dromara.mica.mqtt.server.service; import com.baomidou.mybatisplus.extension.service.IService; import org.dromara.mica.mqtt.server.entity.CarPassGather; +import org.dromara.mica.mqtt.server.entity.CarPassRecord; + +import java.util.List; public interface ICarPassGatherService extends IService { void deleteByLicense(String license); + + void deleteBatchByLicences(List carPassRecords); } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassRecordService.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassRecordService.java index 562463a..79b144c 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassRecordService.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/ICarPassRecordService.java @@ -3,6 +3,13 @@ package org.dromara.mica.mqtt.server.service; import com.baomidou.mybatisplus.extension.service.IService; import org.dromara.mica.mqtt.server.entity.CarPassRecord; +import java.util.List; + public interface ICarPassRecordService extends IService { + /* + * 批量设置通行记录为历史数据 + * */ + public void batchUpdate(List carPassRecords); + } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/IEquipmentService.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/IEquipmentService.java index 04ee0b4..93d7c45 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/IEquipmentService.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/IEquipmentService.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import org.dromara.mica.mqtt.server.entity.Equipment; import java.util.List; +import java.util.Map; public interface IEquipmentService extends IService { @@ -12,4 +13,8 @@ public interface IEquipmentService extends IService { List selectAllSnFlag(); void updateFlag(String sn, String flag); + + List selectAllOnline(); + + Map selectIdSnMap(); } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarParkRecordServiceImpl.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarParkRecordServiceImpl.java index 394ce15..4abc052 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarParkRecordServiceImpl.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarParkRecordServiceImpl.java @@ -1,19 +1,28 @@ package org.dromara.mica.mqtt.server.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.dromara.mica.mqtt.server.entity.CarParkRecord; import org.dromara.mica.mqtt.server.mapper.CarParkRecordMapper; +import org.dromara.mica.mqtt.server.mapper.EquipmentMapper; import org.dromara.mica.mqtt.server.service.ICarParkRecordService; +import org.dromara.mica.mqtt.server.service.IEquipmentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.Map; + @Service public class CarParkRecordServiceImpl extends ServiceImpl implements ICarParkRecordService { @Autowired CarParkRecordMapper carParkRecordMapper; + @Autowired + IEquipmentService equipmentService; + @Override public int updateByClientId(CarParkRecord carParkRecord) { int id = carParkRecordMapper.update(carParkRecord, new QueryWrapper().eq("client_id", carParkRecord.getClientId())); @@ -24,4 +33,10 @@ public class CarParkRecordServiceImpl extends ServiceImpl().eq("client_id", carParkRecord.getClientId())); } + + @Override + public List listSn() { + List list = carParkRecordMapper.selectWithEquipmentSequence(); + return list; + } } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassGatherServiceImpl.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassGatherServiceImpl.java index c643cb6..3ac0bd1 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassGatherServiceImpl.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassGatherServiceImpl.java @@ -1,13 +1,19 @@ package org.dromara.mica.mqtt.server.service.impl; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.dromara.mica.mqtt.server.entity.CarPassGather; +import org.dromara.mica.mqtt.server.entity.CarPassRecord; import org.dromara.mica.mqtt.server.mapper.CarPassGatherMapper; import org.dromara.mica.mqtt.server.service.ICarPassGatherService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.stream.Collectors; + @Service public class CarPassGatherServiceImpl extends ServiceImpl implements ICarPassGatherService { @@ -18,4 +24,15 @@ public class CarPassGatherServiceImpl extends ServiceImpl().eq(CarPassGather::getLicense, license)); } + + @Override + public void deleteBatchByLicences(List carPassRecords) { + if(ObjectUtil.isEmpty(carPassRecords) && carPassRecords.size() == 0) { + return ; + } + List licenses = carPassRecords.stream().map(CarPassRecord::getLicense).collect(Collectors.toList()); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.in(CarPassGather::getLicense, licenses); + carPassGatherMapper.delete(wrapper); + } } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassRecordServiceImpl.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassRecordServiceImpl.java index f52e228..6e5d1b1 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassRecordServiceImpl.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/CarPassRecordServiceImpl.java @@ -2,6 +2,7 @@ package org.dromara.mica.mqtt.server.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.ibatis.executor.BatchResult; import org.dromara.mica.mqtt.server.entity.CarParkRecord; import org.dromara.mica.mqtt.server.entity.CarPassRecord; import org.dromara.mica.mqtt.server.mapper.CarParkRecordMapper; @@ -11,10 +12,20 @@ import org.dromara.mica.mqtt.server.service.ICarPassRecordService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.List; + @Service public class CarPassRecordServiceImpl extends ServiceImpl implements ICarPassRecordService { @Autowired CarPassRecordMapper carPassRecordMapper; + + @Override + public void batchUpdate(List carPassRecords) { + carPassRecords.stream().forEach(carPassRecord -> { + carPassRecord.setDataType("1"); + }); + carPassRecordMapper.updateById(carPassRecords); + } } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/EquipmentServiceImpl.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/EquipmentServiceImpl.java index 286d8c4..493ae50 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/EquipmentServiceImpl.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/EquipmentServiceImpl.java @@ -8,7 +8,10 @@ import org.dromara.mica.mqtt.server.service.IEquipmentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; @Service public class EquipmentServiceImpl extends ServiceImpl implements IEquipmentService { @@ -32,4 +35,16 @@ public class EquipmentServiceImpl extends ServiceImpl().eq("sequence", sn).eq("product_id", 4L)); } + + @Override + public List selectAllOnline() { + return equipmentMapper.selectList(new QueryWrapper().eq("product_id", 4L).eq("flag","0").eq("open_need","1")); + } + + @Override + public Map selectIdSnMap() { + List list = equipmentMapper.selectList(new QueryWrapper().eq("product_id", 4L)); + Map map = list.stream().collect(Collectors.toMap(Equipment::getId, Equipment::getSequence)); + return map; + } } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/ServerService.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/ServerService.java index 0e998b0..09f5c3d 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/ServerService.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/service/impl/ServerService.java @@ -1,12 +1,21 @@ package org.dromara.mica.mqtt.server.service.impl; +import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.extern.slf4j.Slf4j; +import org.dromara.mica.mqtt.server.entity.Equipment; +import org.dromara.mica.mqtt.server.pojo.DeviceIOLockRequestPO; +import org.dromara.mica.mqtt.server.pojo.OpenFloodgatePO; +import org.dromara.mica.mqtt.server.service.IEquipmentService; +import org.dromara.mica.mqtt.server.utils.UuidUtil; import org.dromara.mica.mqtt.spring.server.MqttServerTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.ZoneId; /** * @author wsq @@ -17,6 +26,9 @@ public class ServerService { @Autowired private MqttServerTemplate server; + @Autowired + private IEquipmentService equipmentService; + public boolean publish(JSONObject js) { String sn = js.getString("sn"); String topic = js.getString("topic"); @@ -51,8 +63,64 @@ public class ServerService { } public boolean set_time(String body) { - boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/up/offline_record", body.getBytes(StandardCharsets.UTF_8)); + boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/down/set_time", body.getBytes(StandardCharsets.UTF_8)); log.info("发布离线数据数量body:{},result:{}", body, result); return result; } + + public boolean openFloodgate(String sn) { +// Equipment equipment = equipmentService.getOne(new LambdaQueryWrapper().eq(Equipment::getName,name)); +// String sn = equipment.getSequence(); + String operUrl = "device/%s/message/down/gpio_out"; + String topic = String.format(operUrl, sn); + OpenFloodgatePO openFloodgatePO = new OpenFloodgatePO(); + String uuid = "open_" + UuidUtil.getUuid(); + openFloodgatePO.setId(uuid); + openFloodgatePO.setSn(sn); + openFloodgatePO.setName("gpio_out"); + LocalDateTime now = LocalDateTime.now(); + long timestamp = now.atZone(ZoneId.systemDefault()).toEpochSecond(); + openFloodgatePO.setTimestamp(timestamp); + openFloodgatePO.setPayload(this.buildPayloadOpen()); + boolean result = server.publish(sn,topic, openFloodgatePO.toString().getBytes(StandardCharsets.UTF_8)); + log.info("抬杠设备编码:{},result:{},请求体{}", sn,result,openFloodgatePO); + return result; + } + + public boolean locked(String sn) { +// Equipment equipment = equipmentService.getOne(new LambdaQueryWrapper().eq(Equipment::getName,name)); +// String sn = equipment.getSequence(); + String operUrl = "device/%s/message/down/set_io_lock_status"; + String topic = String.format(operUrl, sn); + DeviceIOLockRequestPO deviceIOLockRequestPO = new DeviceIOLockRequestPO(); + String uuid = "locked_" + UuidUtil.getUuid(); + deviceIOLockRequestPO.setId(uuid); + deviceIOLockRequestPO.setSn(sn); + deviceIOLockRequestPO.setName("set_io_lock_status"); + deviceIOLockRequestPO.setPayload(this.buildPayloadLocked()); + boolean result = server.publish(sn,topic, deviceIOLockRequestPO.toString().getBytes(StandardCharsets.UTF_8)); + log.info("抬杠解锁:{},result:{},请求体:{}", sn,result,deviceIOLockRequestPO); + return result; + } + + private JSONObject buildPayloadOpen() { + JSONObject body = new JSONObject(); + body.put("delay", 10000); + body.put("io", 0); + body.put("value",2); + JSONObject payload = new JSONObject(); + payload.put("type", "gpio_out"); + payload.put("body", body); + return payload; + } + + private JSONObject buildPayloadLocked() { + JSONObject payload = new JSONObject(); + payload.put("type","set_io_lock_status"); + JSONObject body = new JSONObject(); + body.put("ioout",1); + body.put("status",0); + payload.put("body", body); + return payload; + } } diff --git a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/task/PlatePublishTask.java b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/task/PlatePublishTask.java index 1fc4235..0f2c06f 100644 --- a/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/task/PlatePublishTask.java +++ b/example/mqtt-car/src/main/java/org/dromara/mica/mqtt/server/task/PlatePublishTask.java @@ -4,15 +4,17 @@ import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.dromara.mica.mqtt.core.server.MqttServer; import org.dromara.mica.mqtt.server.constant.CacheConstants; -import org.dromara.mica.mqtt.server.entity.CarInfo; -import org.dromara.mica.mqtt.server.entity.CarParkRecord; +import org.dromara.mica.mqtt.server.entity.*; +import org.dromara.mica.mqtt.server.mapper.CarParkMapper; +import org.dromara.mica.mqtt.server.mapper.CarPassRecordMapper; +import org.dromara.mica.mqtt.server.pojo.DeviceIOLockRequestPO; import org.dromara.mica.mqtt.server.pojo.WhiteListOperatorPO; import org.dromara.mica.mqtt.server.redis.RedisService; -import org.dromara.mica.mqtt.server.service.ICarInfoService; -import org.dromara.mica.mqtt.server.service.ICarParkRecordService; +import org.dromara.mica.mqtt.server.service.*; import org.dromara.mica.mqtt.server.utils.UuidUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; @@ -24,6 +26,8 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * 车牌下发设备定时任务 @@ -41,6 +45,24 @@ public class PlatePublishTask { @Autowired ICarParkRecordService carParkRecordService; + @Autowired + CarPassRecordMapper carPassRecordMapper; + + @Autowired + ICarPassRecordService carPassRecordService; + + @Autowired + ICarPassGatherService carPassGatherService; + + @Autowired + CarParkMapper carParkMapper; + + @Autowired + IEquipmentService equipmentService; + + @Autowired + ICarParkItemService carParkItemService; + @Autowired RedisService redisService; @@ -50,11 +72,52 @@ public class PlatePublishTask { */ @Scheduled(fixedDelay = 8 * 1000) public void run() { + log.info("===== 白名单定时任务开始执行 ====="); String whiteUrl = "device/%s/message/down/white_list_operator"; + + //删除车牌 + List carInfos = carParkRecordService.listSn(); + if (CollUtil.isNotEmpty(carInfos)) { + //需要下发的设备 + List snList = carInfos.stream().map(CarParkRecord::getSequence).toList(); + for (String sn : snList) { + if (!redisService.hasKey(CacheConstants.EQUIPMENT_HEARTBEAT + sn)) { + log.error("删除车牌,设备:{},无心跳", sn); + continue; + } + //车辆授权列表 + List carParkRecords = new ArrayList<>(); + String topic = String.format(whiteUrl, sn); + WhiteListOperatorPO po = new WhiteListOperatorPO(); + String uuid = "del_" + UuidUtil.getUuid(); + po.setId(uuid); + po.setSn(sn); + po.setName("white_list_operator"); + //构造内层数据 + List plates = new ArrayList<>(); + for (CarParkRecord carParkRecord : carInfos) { + plates.add(carParkRecord.getPlate()); + if (StrUtil.equals(carParkRecord.getSequence(), sn)) { + carParkRecord.setClientId(uuid); + carParkRecords.add(carParkRecord); + } + } + po.setPayload(buildPayloadDel(plates)); + //更新车辆授权信息 + if (CollUtil.isNotEmpty(carParkRecords)) { + carParkRecordService.saveOrUpdateBatch(carParkRecords); + } + //发布车牌到设备 + boolean publish = mqttServer.publish(sn, topic, JSON.toJSONString(po).getBytes(StandardCharsets.UTF_8)); + log.info("定时任务删除车牌topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(po), publish); + + } + } + //新增&编辑车牌 CarInfo carInfo = new CarInfo(); - carInfo.setDelFlag("0"); +// carInfo.setDelFlag("0"); carInfo.setSync("0"); List carInfoList = carInfoService.selectCarInfoList(carInfo); if (CollUtil.isNotEmpty(carInfoList)) { @@ -78,65 +141,169 @@ public class PlatePublishTask { //必须在发送前更新,不然会导致发送后,还没更新完数据库,回执已经收到,无法更新数据,导致持续下发车牌 CarParkRecord carParkRecord = new CarParkRecord(); carParkRecord.setId(car.getCarParkRecordId()); + carParkRecord.setSequence(car.getSn()); carParkRecord.setClientId(uuid); carParkRecordService.updateById(carParkRecord); - //发布车牌到设备(协议只能单条发布) boolean publish = mqttServer.publish(car.getSn(), topic, JSON.toJSONString(po).getBytes(StandardCharsets.UTF_8)); log.info("定时任务下发车牌topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(po), publish); } } - - //删除车牌 - CarInfo carDel = new CarInfo(); - carDel.setDelFlag("2"); - carDel.setSync("1"); - List carInfos = carInfoService.selectCarInfoList(carDel); - if (CollUtil.isNotEmpty(carInfos)) { - //需要下发的设备 - List snList = carInfos.stream().map(CarInfo::getSn).distinct().toList(); - for (String sn : snList) { - if (!redisService.hasKey(CacheConstants.EQUIPMENT_HEARTBEAT + sn)) { - log.error("删除车牌,设备:{},无心跳", sn); - continue; - } - - //车辆授权列表 - List carParkRecords = new ArrayList<>(); - - String topic = String.format(whiteUrl, sn); - WhiteListOperatorPO po = new WhiteListOperatorPO(); - String uuid = "del_" + UuidUtil.getUuid(); - po.setId(uuid); - po.setSn(sn); - po.setName("white_list_operator"); + log.info("白名单定时任务处理结束"); + } - //构造内层数据 - List plates = new ArrayList<>(); - for (CarInfo car : carInfos) { - plates.add(car.getPlate()); + /* + * 定时任务 处理通行记录对车位的影响 + * */ + @Scheduled(cron = "0/30 * * * * ?") + private void handlePassRecord(){ + log.info("==========开始对通行记录进行处理=========="); + String lockStatusUrl = "device/%s/message/down/set_io_lock_status"; + //存放需要上锁的车场id和设备 + List lockedParkList = new ArrayList<>(); + List lockedEquipmentList; + //存放需要解锁的车场id和设备 + List unlockParkList = new ArrayList<>(); + List unlockEquipmentList; - if (StrUtil.equals(car.getSn(), sn)) { - CarParkRecord carParkRecord = new CarParkRecord(); - carParkRecord.setClientId(uuid); - carParkRecord.setId(car.getCarParkRecordId()); - carParkRecords.add(carParkRecord); - } - } - po.setPayload(buildPayloadDel(plates)); + //获取全部车场对应的剩余车位信息 + List carParks = carParkMapper.selectList(Wrappers.lambdaQuery()); + //获取车场对应的当前剩余车位 + Map parkIdSpaceMap = carParks.stream().collect(Collectors.toMap(item -> item.getId(), item -> item.getSurplusNum(),(v1,v2)->v1)); + //处理非历史数据的离场通行记录 + //获取需要处理的出场记录 + List carOutPassRecord = carPassRecordMapper.selectList( + Wrappers.lambdaQuery(CarPassRecord.class) + .eq(CarPassRecord::getDirection, "1") + .eq(CarPassRecord::getDataType, "0") + ); - //更新车辆授权信息 - if (CollUtil.isNotEmpty(carParkRecords)) { - carParkRecordService.saveOrUpdateBatch(carParkRecords); - } - //发布车牌到设备 - boolean publish = mqttServer.publish(sn, topic, JSON.toJSONString(po).getBytes(StandardCharsets.UTF_8)); - log.info("定时任务删除车牌topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(po), publish); + Map> outRecordByParkId = carOutPassRecord.stream() + .filter(record -> record.getParkId() != null) + .collect(Collectors.groupingBy(CarPassRecord::getParkId)); + // 遍历每个车场的出场记录,更新剩余车位 + outRecordByParkId.forEach((parkId, outRecords) -> { + // 获取该车场当前剩余车位(默认0,避免空指针) + Long currentSurplus = parkIdSpaceMap.getOrDefault(Long.valueOf(parkId), 0L); + Long newSurplus = currentSurplus + outRecords.size(); + parkIdSpaceMap.put(Long.valueOf(parkId), newSurplus); + log.info("车场ID:{},处理出场记录{}条,剩余车位从{}更新为{}", parkId, outRecords.size(), currentSurplus, newSurplus); + }); + //将出场的车辆从在场记录中删除 + carPassGatherService.deleteBatchByLicences(carOutPassRecord); + //将处理过的通行记录标记为历史数据 + carPassRecordService.batchUpdate(carOutPassRecord); + carParks.stream().forEach(park -> { + Long currentSurplus = parkIdSpaceMap.get(park.getId()); + Long oldSurplus = park.getSurplusNum(); // 原来的剩余车位 + if (currentSurplus > 0 && oldSurplus <= 0) unlockParkList.add(park.getId()); + }); + //先获取全部需解锁的车场对应的绑定列表 只需要管理入场设备 + if (unlockParkList.size() > 0) { + List parkItemList = carParkItemService.list(Wrappers.lambdaQuery(CarParkItem.class).in(CarParkItem::getParkId, unlockParkList).eq(CarParkItem::getWay,"0")); + List ids = parkItemList.stream().map(CarParkItem::getEquipmentId).collect(Collectors.toList()); + unlockEquipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class).in(Equipment::getId, ids).eq(Equipment::getFlag, "0").eq(Equipment::getLocked, "1")); + + //存放成功上锁的设备 + List successList = new ArrayList<>(); + for (Equipment equipment : unlockEquipmentList) { + String topic = String.format(lockStatusUrl, equipment.getSequence()); + DeviceIOLockRequestPO deviceIOLockRequestPO = new DeviceIOLockRequestPO(); + String uuid = "unlock_" + UuidUtil.getUuid(); + deviceIOLockRequestPO.setId(uuid); + deviceIOLockRequestPO.setSn(equipment.getSequence()); + deviceIOLockRequestPO.setName("set_io_lock_status"); + JSONObject payload = this.buildPayLoadUnLock(); + deviceIOLockRequestPO.setPayload(payload); + boolean publish = mqttServer.publish(equipment.getSequence(), topic, JSON.toJSONString(deviceIOLockRequestPO).getBytes(StandardCharsets.UTF_8)); + if (publish) successList.add(equipment); + log.info("定时任务设备解锁topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(deviceIOLockRequestPO), publish); + } + if (successList.size() > 0) { + successList.stream().forEach(equipment -> { + equipment.setLocked("0"); + }); + equipmentService.updateBatchById(successList); } } + + //处理非历史数据的进场通行记录 + //存放新增的在场记录 + List insertList = new ArrayList<>(); + //存放已经处理的进场通行记录到待处理集合 + List handedList = new ArrayList<>(); + List carIntoPassRecord = carPassRecordMapper.selectList( + Wrappers.lambdaQuery(CarPassRecord.class) + .eq(CarPassRecord::getDirection, "0") + .eq(CarPassRecord::getDataType, "0") + ); + + Map> insertRecordByParkId = carIntoPassRecord.stream() + .filter(record -> record.getParkId() != null) + .collect(Collectors.groupingBy(CarPassRecord::getParkId)); + + insertRecordByParkId.forEach((parkId, insertRecords) -> { + for (CarPassRecord record : insertRecords) { + Long currentSurplus = parkIdSpaceMap.getOrDefault(Long.valueOf(parkId), 0L); + if (currentSurplus <= 0) continue; + //更新当前车位数 + Long currentSpace = currentSurplus-1; + parkIdSpaceMap.put(Long.valueOf(parkId), currentSpace); + //将处理过的进场通行记录加入待处理集合 + handedList.add(record); + //生成新地在场记录,并加入待处理集合 + CarPassGather carPassGather = new CarPassGather(); + carPassGather.setParkId(parkId); + carPassGather.setLicense(record.getLicense()); + carPassGather.setSn(record.getSn()); + carPassGather.setJoinTime(record.getPassTime()); + insertList.add(carPassGather); + } + }); + //将待处理的通行记录标记为历史数据 + carPassRecordService.batchUpdate(handedList); + //将新生成的在场记录添加到表中 + carPassGatherService.saveBatch(insertList); + //更新车场的车位信息 + carParks.stream().forEach(park -> { + Long currentSurplus = parkIdSpaceMap.get(park.getId()); + Long oldSurplus = park.getSurplusNum(); + park.setSurplusNum(currentSurplus); + // 从有车位变为无车位才需要上锁 + if (currentSurplus <= 0 && oldSurplus > 0) lockedParkList.add(park.getId()); + }); + carParkMapper.updateById(carParks); + if (lockedParkList.size() > 0) { + //先获取全部需上锁的车场对应的绑定列表 只需要管理进场设备 + List parkItemList1 = carParkItemService.list(Wrappers.lambdaQuery(CarParkItem.class).in(CarParkItem::getParkId, lockedParkList).eq(CarParkItem::getWay,"0")); + List ids1 = parkItemList1.stream().map(CarParkItem::getEquipmentId).collect(Collectors.toList()); + lockedEquipmentList = equipmentService.list(Wrappers.lambdaQuery(Equipment.class).in(Equipment::getId, ids1).eq(Equipment::getFlag, "0").eq(Equipment::getLocked, "0")); + //存放成功解锁的设备 + List successList = new ArrayList<>(); + for (Equipment equipment : lockedEquipmentList) { + String topic = String.format(lockStatusUrl, equipment.getSequence()); + DeviceIOLockRequestPO deviceIOLockRequestPO = new DeviceIOLockRequestPO(); + String uuid = "locked_" + UuidUtil.getUuid(); + deviceIOLockRequestPO.setId(uuid); + deviceIOLockRequestPO.setSn(equipment.getSequence()); + deviceIOLockRequestPO.setName("set_io_lock_status"); + JSONObject payload = this.buildPayloadLocked(); + deviceIOLockRequestPO.setPayload(payload); + boolean publish = mqttServer.publish(equipment.getSequence(), topic, JSON.toJSONString(deviceIOLockRequestPO).getBytes(StandardCharsets.UTF_8)); + if (publish) successList.add(equipment); + log.info("定时任务设备上锁topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(deviceIOLockRequestPO), publish); + } + if (successList.size() > 0) { + successList.stream().forEach(equipment -> { + equipment.setLocked("1"); + }); + equipmentService.updateBatchById(successList); + } + } + log.info("==========通行记录处理结束=========="); } @@ -181,4 +348,25 @@ public class PlatePublishTask { return payload; } + //上锁 + private JSONObject buildPayloadLocked() { + JSONObject payload = new JSONObject(); + payload.put("type","set_io_lock_status"); + JSONObject body = new JSONObject(); + body.put("ioout",1); + body.put("status",2); + payload.put("body", body); + return payload; + } + //解锁 + private JSONObject buildPayLoadUnLock(){ + JSONObject payload = new JSONObject(); + payload.put("type","set_io_lock_status"); + JSONObject body = new JSONObject(); + body.put("ioout",1); + body.put("status",0); + payload.put("body", body); + return payload; + } + } diff --git a/example/mqtt-car/src/main/resources/mapper/CarInfoMapper.xml b/example/mqtt-car/src/main/resources/mapper/CarInfoMapper.xml index 635265f..9b8465d 100644 --- a/example/mqtt-car/src/main/resources/mapper/CarInfoMapper.xml +++ b/example/mqtt-car/src/main/resources/mapper/CarInfoMapper.xml @@ -5,7 +5,7 @@ - + @@ -24,19 +24,19 @@ - select ci.customer_id, ci.enable_time, ci.overdue_time, ci.enable, ci.plate, ci.time_seg_enable, ci.seg_time, + select ci.id, ci.enable_time, ci.overdue_time, ci.enable, ci.plate, ci.time_seg_enable, ci.seg_time, ci.need_alarm, ci.vehicle_code, ci.vehicle_comment, ci.people_id, ci.del_flag, ci.sync, ci.remark, - ci.create_by, ci.create_time, ci.update_by, ci.update_time, ci.overclock_card + ci.create_user, ci.create_time, ci.update_user, ci.update_time, ci.overclock_card from car_info ci left join car_park cp on ci.park_id=cp.id left join sys_people p on ci.people_id=p.id - left join car_park_record cpr on cpr.customer_id=ci.customer_id + left join car_park_record cpr on cpr.customer_id=ci.id left join sys_equipment se on cpr.equipment_id=se.id + SELECT + cpr.id, + cpr.equipment_id, + cpr.park_id, + cpr.plate, + cpr.customer_id, + cpr.sync, + cpr.client_id, + eq.sequence AS sequence + FROM car_park_record cpr + LEFT JOIN sys_equipment eq ON cpr.equipment_id = eq.id + where + cpr.sync = '2' + ORDER BY cpr.id DESC + + diff --git a/example/mqtt-car/src/main/resources/mapper/CarPassGatherMapper.xml b/example/mqtt-car/src/main/resources/mapper/CarPassGatherMapper.xml new file mode 100644 index 0000000..01bb9ab --- /dev/null +++ b/example/mqtt-car/src/main/resources/mapper/CarPassGatherMapper.xml @@ -0,0 +1,7 @@ + + + + +