满车位锁杆

This commit is contained in:
zc
2026-04-30 14:49:53 +08:00
parent 778ab69fbc
commit 7871c2ac70
13 changed files with 246 additions and 12 deletions

View File

@@ -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,25 @@ public class ServerController {
return service.set_time(body);
}
//手动触发抬杆
@PostMapping("/openFloodgate")
public boolean openFloodgate(@RequestBody JSONObject js) {
String sn = js.getString("sn");
return service.openFloodgate(sn);
}
//锁杆&解锁
@PostMapping("/set_io_lock_status")
public JSONObject lock(@RequestBody JSONObject js) {
String sn = js.getString("sn");
Integer status = js.getInteger("status");
boolean publish = service.locked(sn, status);
JSONObject jsonObject = new JSONObject();
if (publish) {
jsonObject.put("code", 200);
} else {
jsonObject.put("code", 500);
}
return jsonObject;
}
}

View File

@@ -1,5 +1,7 @@
package org.dromara.mica.mqtt.server.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@@ -16,6 +18,7 @@ public class CarInfo implements Serializable {
private static final long serialVersionUID = 1L;
/** customer_id */
@TableId(type = IdType.AUTO)
private Long customerId;
/** 白名单生效时间 */

View File

@@ -1,5 +1,7 @@
package org.dromara.mica.mqtt.server.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@@ -22,6 +24,7 @@ public class CarParkItem implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
@@ -44,4 +47,14 @@ public class CarParkItem implements Serializable {
*/
private String area;
/**
* 车位数量
*/
private Integer carsNum;
/**
* 满车位自动锁杆0不锁1
*/
private Integer autoLock;
}

View File

@@ -1,5 +1,7 @@
package org.dromara.mica.mqtt.server.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@@ -22,6 +24,7 @@ public class CarPassGather implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO )
private Long id;
/**

View File

@@ -1,10 +1,10 @@
package org.dromara.mica.mqtt.server.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serial;
import java.io.Serializable;
@@ -24,6 +24,7 @@ public class CarPassRecord implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Long id;
/**

View File

@@ -1,6 +1,8 @@
package org.dromara.mica.mqtt.server.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@@ -16,6 +18,7 @@ public class Equipment implements Serializable {
/** 设备Id */
@TableId(type = IdType.AUTO)
private Long id;
/** 所属产品Id */

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dromara.mica.mqtt.core.annotation.MqttServerFunction;
@@ -20,6 +21,7 @@ import org.dromara.mica.mqtt.server.service.ICarParkItemService;
import org.dromara.mica.mqtt.server.service.ICarParkRecordService;
import org.dromara.mica.mqtt.server.service.ICarPassGatherService;
import org.dromara.mica.mqtt.server.service.ICarPassRecordService;
import org.dromara.mica.mqtt.server.service.impl.ServerService;
import org.dromara.mica.mqtt.server.utils.AESUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -29,6 +31,7 @@ import org.tio.utils.hutool.StrUtil;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -56,6 +59,10 @@ public class CarMessageListener {
@Autowired
ICarPassGatherService carPassGatherService;
@Autowired
private ServerService service;
private static String key = "1234567898765432";
//xa、jl、td、xj
@@ -116,6 +123,17 @@ public class CarMessageListener {
public void ivs_result(String topic, Map<String, String> topicVars, byte[] message) throws Exception {
String sn = topicVars.get("sn");
log.info("接收到车辆识别消息 -> Topic: {}", topic);
//如果开启了锁杆,且车位满了
CarParkItem carParkItem = carParkItemService.selectBySn(sn);
long count = carPassGatherService.count(new QueryWrapper<CarPassGather>().eq("park_id", carParkItem.getParkId()));
if (StrUtil.equals(carParkItem.getWay(), "0") //入场
&& carParkItem.getAutoLock() == 1 //开启了锁杆
&& count >= carParkItem.getCarsNum()) { //车位满了
log.info("车位满了,不记录入场数据");
return;
}
String data = new String(message, StandardCharsets.UTF_8);
JSONObject jsonObject = JSONObject.parseObject(data);
JSONObject payload = jsonObject.getJSONObject("payload");
@@ -163,14 +181,15 @@ public class CarMessageListener {
}
record.setSn(sn);
record.setUniqueNo(id);
record.setParkId(carParkItem.getParkId());
record.setTriggerType(plateResult.getString("triggerType"));
record.setType(carBrand.getString("type"));
carPassRecordService.save(record);
//保存/删除在场数据
CarParkItem carParkItem = carParkItemService.selectBySn(sn);
boolean isExist = carPassGatherService.exists(new QueryWrapper<CarPassGather>().eq("license", license));
//入场新增数据
if (StrUtil.equals(carParkItem.getWay(), "0")) {
if (StrUtil.equals(carParkItem.getWay(), "0") && !isExist) {
CarPassGather carPassGather = new CarPassGather();
carPassGather.setLicense(license);
carPassGather.setParkId(carParkItem.getParkId());
@@ -178,8 +197,23 @@ public class CarMessageListener {
carPassGather.setJoinTime(record.getPassTime());
carPassGather.setSn(sn);
carPassGatherService.save(carPassGather);
} else {//出场删除数据
//最后一辆车进场
if (carParkItem.getAutoLock() == 1 && (count + 1) >= carParkItem.getCarsNum()) {
List<String> snList = carParkItemService.selectSnByParkId(carParkItem.getParkId());
for (String s : snList) {
service.locked(s, 2);
}
}
} else if (StrUtil.equals(carParkItem.getWay(), "1") && isExist) {//出场删除数据
carPassGatherService.deleteByLicense(license);
//出去一辆车,有空位
if (carParkItem.getAutoLock() == 1 && count == carParkItem.getCarsNum()) {
List<String> snList = carParkItemService.selectSnByParkId(carParkItem.getParkId());
for (String s : snList) {
service.locked(s, 0);
}
}
}
}
@@ -270,7 +304,9 @@ public class CarMessageListener {
public void set_io_lock_status(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);
JSONObject jsonObject = JSONObject.parseObject(data);
}
/**

View File

@@ -12,6 +12,9 @@ import java.util.List;
@Mapper
public interface CarParkItemMapper extends BaseMapper<CarParkItem> {
@Select("SELECT p.id,p.park_id parkId,p.way,p.equipment_id equipmentId,p.area FROM car_park_item p left join sys_equipment e on p.equipment_id = e.id where e.sequence = #{sn} and e.product_id = 4 limit 1")
@Select("SELECT p.id,p.park_id parkId,k.auto_lock autoLock,k.cars_num carsNum,p.way,p.equipment_id equipmentId,p.area FROM car_park_item p left join sys_equipment e on p.equipment_id = e.id LEFT JOIN car_park k on p.park_id = k.id where e.sequence = #{sn} and e.product_id = 4 limit 1")
CarParkItem selectBySn(@Param("sn") String sn);
@Select("SELECT e.sequence FROM car_park_item p left join sys_equipment e on p.equipment_id = e.id where p.park_id = #{parkId} and p.way = 0 and e.product_id = 4")
List<String> selectSnByParkId(@Param("parkId") String parkId);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -3,7 +3,11 @@ package org.dromara.mica.mqtt.server.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.dromara.mica.mqtt.server.entity.CarParkItem;
import java.util.List;
public interface ICarParkItemService extends IService<CarParkItem> {
CarParkItem selectBySn(String sn);
List<String> selectSnByParkId(String parkId);
}

View File

@@ -1,6 +1,5 @@
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.dromara.mica.mqtt.server.entity.CarParkItem;
import org.dromara.mica.mqtt.server.mapper.CarParkItemMapper;
@@ -8,6 +7,8 @@ import org.dromara.mica.mqtt.server.service.ICarParkItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CarParkItemServiceImpl extends ServiceImpl<CarParkItemMapper, CarParkItem> implements ICarParkItemService {
@@ -18,4 +19,9 @@ public class CarParkItemServiceImpl extends ServiceImpl<CarParkItemMapper, CarPa
public CarParkItem selectBySn(String sn) {
return carParkItemMapper.selectBySn(sn);
}
@Override
public List<String> selectSnByParkId(String parkId) {
return carParkItemMapper.selectSnByParkId(parkId);
}
}

View File

@@ -1,12 +1,18 @@
package org.dromara.mica.mqtt.server.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dromara.mica.mqtt.server.pojo.DeviceIOLockRequestPO;
import org.dromara.mica.mqtt.server.pojo.OpenFloodgatePO;
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
@@ -55,4 +61,58 @@ public class ServerService {
log.info("发布离线数据数量body:{},result:{}", body, result);
return result;
}
public boolean openFloodgate(String sn) {
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, JSON.toJSONString(openFloodgatePO).getBytes(StandardCharsets.UTF_8));
log.info("抬杠设备编码:{},result:{},请求体{}", sn,result,openFloodgatePO);
return result;
}
public boolean locked(String sn, Integer status) {
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(status));
boolean result = server.publish(sn,topic, JSON.toJSONString(deviceIOLockRequestPO).getBytes(StandardCharsets.UTF_8));
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(Integer status) {
JSONObject payload = new JSONObject();
payload.put("type", "set_io_lock_status");
JSONObject body = new JSONObject();
//io口摄像头接线口
body.put("ioout", 0);
//0解锁 1高电平锁定保持常抬 2低电平锁定保持常关
body.put("status", status);
payload.put("body", body);
return payload;
}
}