mqtt模块初始化

This commit is contained in:
2026-04-07 07:59:11 +08:00
parent 3ee2ca5eb7
commit 6d40227435
48 changed files with 4228 additions and 298 deletions

View File

@@ -3,6 +3,7 @@ package com.shzg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 启动程序
@@ -10,11 +11,11 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
* @author wisdom
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableScheduling
public class WornApplication
{
public static void main(String[] args)
{
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(WornApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ Wisdom 系统启动成功 ლ(´ڡ`ლ)゙ \n" +

View File

@@ -114,6 +114,7 @@ public class SecurityConfig
requests.antMatchers("/login",
"/register",
"/unique/code/**",
"/device/cmd/**",
"/captchaImage").permitAll()
// 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()

View File

@@ -0,0 +1,36 @@
package com.shzg.project.worn.controller;
import com.shzg.framework.web.controller.BaseController;
import com.shzg.framework.web.domain.AjaxResult;
import com.shzg.project.worn.service.IDeviceCommandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/device/cmd")
public class DeviceCommandController extends BaseController {
@Autowired
private IDeviceCommandService deviceCommandService;
/**
* 烟雾传感器 - 持续消警
*/
@PostMapping("/smoke/stop")
public AjaxResult smokeStop(@RequestParam Long deviceId) {
deviceCommandService.smokeStop(deviceId);
return AjaxResult.success("消警指令已发送");
}
/**
* 烟雾传感器 - 单次消警80秒
*/
@PostMapping("/smoke/stopOnce")
public AjaxResult smokeStopOnce(@RequestParam Long deviceId) {
deviceCommandService.smokeStopOnce(deviceId);
return AjaxResult.success("单次消警指令已发送");
}
}

View File

@@ -0,0 +1,104 @@
package com.shzg.project.worn.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.shzg.framework.aspectj.lang.annotation.Log;
import com.shzg.framework.aspectj.lang.enums.BusinessType;
import com.shzg.project.worn.domain.MqttSensorCommand;
import com.shzg.project.worn.service.IMqttSensorCommandService;
import com.shzg.framework.web.controller.BaseController;
import com.shzg.framework.web.domain.AjaxResult;
import com.shzg.common.utils.poi.ExcelUtil;
import com.shzg.framework.web.page.TableDataInfo;
/**
* 指令管理Controller
*
* @author shzg
* @date 2026-04-01
*/
@RestController
@RequestMapping("/worn/mqttCommand")
public class MqttSensorCommandController extends BaseController
{
@Autowired
private IMqttSensorCommandService mqttSensorCommandService;
/**
* 查询指令管理列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttCommand:list')")
@GetMapping("/list")
public TableDataInfo list(MqttSensorCommand mqttSensorCommand)
{
startPage();
List<MqttSensorCommand> list = mqttSensorCommandService.selectMqttSensorCommandList(mqttSensorCommand);
return getDataTable(list);
}
/**
* 导出指令管理列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttCommand:export')")
@Log(title = "指令管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MqttSensorCommand mqttSensorCommand)
{
List<MqttSensorCommand> list = mqttSensorCommandService.selectMqttSensorCommandList(mqttSensorCommand);
ExcelUtil<MqttSensorCommand> util = new ExcelUtil<MqttSensorCommand>(MqttSensorCommand.class);
util.exportExcel(response, list, "指令管理数据");
}
/**
* 获取指令管理详细信息
*/
@PreAuthorize("@ss.hasPermi('worn:mqttCommand:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(mqttSensorCommandService.selectMqttSensorCommandById(id));
}
/**
* 新增指令管理
*/
@PreAuthorize("@ss.hasPermi('worn:mqttCommand:add')")
@Log(title = "指令管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MqttSensorCommand mqttSensorCommand)
{
return toAjax(mqttSensorCommandService.insertMqttSensorCommand(mqttSensorCommand));
}
/**
* 修改指令管理
*/
@PreAuthorize("@ss.hasPermi('worn:mqttCommand:edit')")
@Log(title = "指令管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MqttSensorCommand mqttSensorCommand)
{
return toAjax(mqttSensorCommandService.updateMqttSensorCommand(mqttSensorCommand));
}
/**
* 删除指令管理
*/
@PreAuthorize("@ss.hasPermi('worn:mqttCommand:remove')")
@Log(title = "指令管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(mqttSensorCommandService.deleteMqttSensorCommandByIds(ids));
}
}

View File

@@ -0,0 +1,104 @@
package com.shzg.project.worn.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.shzg.framework.aspectj.lang.annotation.Log;
import com.shzg.framework.aspectj.lang.enums.BusinessType;
import com.shzg.project.worn.domain.MqttSensorData;
import com.shzg.project.worn.service.IMqttSensorDataService;
import com.shzg.framework.web.controller.BaseController;
import com.shzg.framework.web.domain.AjaxResult;
import com.shzg.common.utils.poi.ExcelUtil;
import com.shzg.framework.web.page.TableDataInfo;
/**
* 设备数据Controller
*
* @author shzg
* @date 2026-04-01
*/
@RestController
@RequestMapping("/worn/mqttData")
public class MqttSensorDataController extends BaseController
{
@Autowired
private IMqttSensorDataService mqttSensorDataService;
/**
* 查询设备数据列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttData:list')")
@GetMapping("/list")
public TableDataInfo list(MqttSensorData mqttSensorData)
{
startPage();
List<MqttSensorData> list = mqttSensorDataService.selectMqttSensorDataList(mqttSensorData);
return getDataTable(list);
}
/**
* 导出设备数据列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttData:export')")
@Log(title = "设备数据", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MqttSensorData mqttSensorData)
{
List<MqttSensorData> list = mqttSensorDataService.selectMqttSensorDataList(mqttSensorData);
ExcelUtil<MqttSensorData> util = new ExcelUtil<MqttSensorData>(MqttSensorData.class);
util.exportExcel(response, list, "设备数据数据");
}
/**
* 获取设备数据详细信息
*/
@PreAuthorize("@ss.hasPermi('worn:mqttData:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(mqttSensorDataService.selectMqttSensorDataById(id));
}
/**
* 新增设备数据
*/
@PreAuthorize("@ss.hasPermi('worn:mqttData:add')")
@Log(title = "设备数据", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MqttSensorData mqttSensorData)
{
return toAjax(mqttSensorDataService.insertMqttSensorData(mqttSensorData));
}
/**
* 修改设备数据
*/
@PreAuthorize("@ss.hasPermi('worn:mqttData:edit')")
@Log(title = "设备数据", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MqttSensorData mqttSensorData)
{
return toAjax(mqttSensorDataService.updateMqttSensorData(mqttSensorData));
}
/**
* 删除设备数据
*/
@PreAuthorize("@ss.hasPermi('worn:mqttData:remove')")
@Log(title = "设备数据", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(mqttSensorDataService.deleteMqttSensorDataByIds(ids));
}
}

View File

@@ -0,0 +1,104 @@
package com.shzg.project.worn.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.shzg.framework.aspectj.lang.annotation.Log;
import com.shzg.framework.aspectj.lang.enums.BusinessType;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.service.IMqttSensorDeviceService;
import com.shzg.framework.web.controller.BaseController;
import com.shzg.framework.web.domain.AjaxResult;
import com.shzg.common.utils.poi.ExcelUtil;
import com.shzg.framework.web.page.TableDataInfo;
/**
* MQTT设备Controller
*
* @author shzg
* @date 2026-04-01
*/
@RestController
@RequestMapping("/worn/mqttDevice")
public class MqttSensorDeviceController extends BaseController
{
@Autowired
private IMqttSensorDeviceService mqttSensorDeviceService;
/**
* 查询MQTT设备列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttDevice:list')")
@GetMapping("/list")
public TableDataInfo list(MqttSensorDevice mqttSensorDevice)
{
startPage();
List<MqttSensorDevice> list = mqttSensorDeviceService.selectMqttSensorDeviceList(mqttSensorDevice);
return getDataTable(list);
}
/**
* 导出MQTT设备列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttDevice:export')")
@Log(title = "MQTT设备", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MqttSensorDevice mqttSensorDevice)
{
List<MqttSensorDevice> list = mqttSensorDeviceService.selectMqttSensorDeviceList(mqttSensorDevice);
ExcelUtil<MqttSensorDevice> util = new ExcelUtil<MqttSensorDevice>(MqttSensorDevice.class);
util.exportExcel(response, list, "MQTT设备数据");
}
/**
* 获取MQTT设备详细信息
*/
@PreAuthorize("@ss.hasPermi('worn:mqttDevice:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(mqttSensorDeviceService.selectMqttSensorDeviceById(id));
}
/**
* 新增MQTT设备
*/
@PreAuthorize("@ss.hasPermi('worn:mqttDevice:add')")
@Log(title = "MQTT设备", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MqttSensorDevice mqttSensorDevice)
{
return toAjax(mqttSensorDeviceService.insertMqttSensorDevice(mqttSensorDevice));
}
/**
* 修改MQTT设备
*/
@PreAuthorize("@ss.hasPermi('worn:mqttDevice:edit')")
@Log(title = "MQTT设备", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MqttSensorDevice mqttSensorDevice)
{
return toAjax(mqttSensorDeviceService.updateMqttSensorDevice(mqttSensorDevice));
}
/**
* 删除MQTT设备
*/
@PreAuthorize("@ss.hasPermi('worn:mqttDevice:remove')")
@Log(title = "MQTT设备", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(mqttSensorDeviceService.deleteMqttSensorDeviceByIds(ids));
}
}

View File

@@ -0,0 +1,104 @@
package com.shzg.project.worn.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.shzg.framework.aspectj.lang.annotation.Log;
import com.shzg.framework.aspectj.lang.enums.BusinessType;
import com.shzg.project.worn.domain.MqttSensorEvent;
import com.shzg.project.worn.service.IMqttSensorEventService;
import com.shzg.framework.web.controller.BaseController;
import com.shzg.framework.web.domain.AjaxResult;
import com.shzg.common.utils.poi.ExcelUtil;
import com.shzg.framework.web.page.TableDataInfo;
/**
* 设备事件Controller
*
* @author shzg
* @date 2026-04-01
*/
@RestController
@RequestMapping("/worn/mqttEvent")
public class MqttSensorEventController extends BaseController
{
@Autowired
private IMqttSensorEventService mqttSensorEventService;
/**
* 查询设备事件列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttEvent:list')")
@GetMapping("/list")
public TableDataInfo list(MqttSensorEvent mqttSensorEvent)
{
startPage();
List<MqttSensorEvent> list = mqttSensorEventService.selectMqttSensorEventList(mqttSensorEvent);
return getDataTable(list);
}
/**
* 导出设备事件列表
*/
@PreAuthorize("@ss.hasPermi('worn:mqttEvent:export')")
@Log(title = "设备事件", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MqttSensorEvent mqttSensorEvent)
{
List<MqttSensorEvent> list = mqttSensorEventService.selectMqttSensorEventList(mqttSensorEvent);
ExcelUtil<MqttSensorEvent> util = new ExcelUtil<MqttSensorEvent>(MqttSensorEvent.class);
util.exportExcel(response, list, "设备事件数据");
}
/**
* 获取设备事件详细信息
*/
@PreAuthorize("@ss.hasPermi('worn:mqttEvent:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(mqttSensorEventService.selectMqttSensorEventById(id));
}
/**
* 新增设备事件
*/
@PreAuthorize("@ss.hasPermi('worn:mqttEvent:add')")
@Log(title = "设备事件", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MqttSensorEvent mqttSensorEvent)
{
return toAjax(mqttSensorEventService.insertMqttSensorEvent(mqttSensorEvent));
}
/**
* 修改设备事件
*/
@PreAuthorize("@ss.hasPermi('worn:mqttEvent:edit')")
@Log(title = "设备事件", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MqttSensorEvent mqttSensorEvent)
{
return toAjax(mqttSensorEventService.updateMqttSensorEvent(mqttSensorEvent));
}
/**
* 删除设备事件
*/
@PreAuthorize("@ss.hasPermi('worn:mqttEvent:remove')")
@Log(title = "设备事件", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(mqttSensorEventService.deleteMqttSensorEventByIds(ids));
}
}

View File

@@ -0,0 +1,104 @@
package com.shzg.project.worn.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.shzg.framework.aspectj.lang.annotation.Log;
import com.shzg.framework.aspectj.lang.enums.BusinessType;
import com.shzg.project.worn.domain.MqttSensorThreshold;
import com.shzg.project.worn.service.IMqttSensorThresholdService;
import com.shzg.framework.web.controller.BaseController;
import com.shzg.framework.web.domain.AjaxResult;
import com.shzg.common.utils.poi.ExcelUtil;
import com.shzg.framework.web.page.TableDataInfo;
/**
* 传感器阈值配置Controller
*
* @author shzg
* @date 2026-04-01
*/
@RestController
@RequestMapping("/worn/threshold")
public class MqttSensorThresholdController extends BaseController
{
@Autowired
private IMqttSensorThresholdService mqttSensorThresholdService;
/**
* 查询传感器阈值配置列表
*/
@PreAuthorize("@ss.hasPermi('worn:threshold:list')")
@GetMapping("/list")
public TableDataInfo list(MqttSensorThreshold mqttSensorThreshold)
{
startPage();
List<MqttSensorThreshold> list = mqttSensorThresholdService.selectMqttSensorThresholdList(mqttSensorThreshold);
return getDataTable(list);
}
/**
* 导出传感器阈值配置列表
*/
@PreAuthorize("@ss.hasPermi('worn:threshold:export')")
@Log(title = "传感器阈值配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, MqttSensorThreshold mqttSensorThreshold)
{
List<MqttSensorThreshold> list = mqttSensorThresholdService.selectMqttSensorThresholdList(mqttSensorThreshold);
ExcelUtil<MqttSensorThreshold> util = new ExcelUtil<MqttSensorThreshold>(MqttSensorThreshold.class);
util.exportExcel(response, list, "传感器阈值配置数据");
}
/**
* 获取传感器阈值配置详细信息
*/
@PreAuthorize("@ss.hasPermi('worn:threshold:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(mqttSensorThresholdService.selectMqttSensorThresholdById(id));
}
/**
* 新增传感器阈值配置
*/
@PreAuthorize("@ss.hasPermi('worn:threshold:add')")
@Log(title = "传感器阈值配置", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody MqttSensorThreshold mqttSensorThreshold)
{
return toAjax(mqttSensorThresholdService.insertMqttSensorThreshold(mqttSensorThreshold));
}
/**
* 修改传感器阈值配置
*/
@PreAuthorize("@ss.hasPermi('worn:threshold:edit')")
@Log(title = "传感器阈值配置", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody MqttSensorThreshold mqttSensorThreshold)
{
return toAjax(mqttSensorThresholdService.updateMqttSensorThreshold(mqttSensorThreshold));
}
/**
* 删除传感器阈值配置
*/
@PreAuthorize("@ss.hasPermi('worn:threshold:remove')")
@Log(title = "传感器阈值配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(mqttSensorThresholdService.deleteMqttSensorThresholdByIds(ids));
}
}

View File

@@ -0,0 +1,150 @@
package com.shzg.project.worn.domain;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.shzg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.shzg.framework.aspectj.lang.annotation.Excel;
/**
* 指令管理对象 mqtt_sensor_command
*
* @author shzg
* @date 2026-04-01
*/
public class MqttSensorCommand extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 设备ID */
@Excel(name = "设备ID")
private Long deviceId;
/** 下发Topic */
@Excel(name = "下发Topic")
private String topic;
/** 指令类型 */
@Excel(name = "指令类型")
private String command;
/** 指令JSON */
@Excel(name = "指令JSON")
private String payload;
/** 状态0待发送 1成功 2失败 */
@Excel(name = "状态", readConverterExp = "0=待发送,1=成功,2=失败")
private String status;
/** 发送时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "发送时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date sendTime;
/** 删除标识 */
@Excel(name = "删除标识")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public Long getDeviceId()
{
return deviceId;
}
public void setTopic(String topic)
{
this.topic = topic;
}
public String getTopic()
{
return topic;
}
public void setCommand(String command)
{
this.command = command;
}
public String getCommand()
{
return command;
}
public void setPayload(String payload)
{
this.payload = payload;
}
public String getPayload()
{
return payload;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setSendTime(Date sendTime)
{
this.sendTime = sendTime;
}
public Date getSendTime()
{
return sendTime;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceId", getDeviceId())
.append("topic", getTopic())
.append("command", getCommand())
.append("payload", getPayload())
.append("status", getStatus())
.append("sendTime", getSendTime())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,254 @@
package com.shzg.project.worn.domain;
import java.math.BigDecimal;
import com.shzg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.shzg.framework.aspectj.lang.annotation.Excel;
/**
* 设备数据对象 mqtt_sensor_data
*
* @author shzg
* @date 2026-04-01
*/
public class MqttSensorData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 设备ID */
@Excel(name = "设备ID")
private Long deviceId;
/** MQTT Topic */
@Excel(name = "MQTT Topic")
private String topic;
/** 项目(如 tangshan */
@Excel(name = "项目", readConverterExp = "如=,t=angshan")
private String project;
/** 仓库(如 dianchi */
@Excel(name = "仓库", readConverterExp = "如=,d=ianchi")
private String warehouse;
/** 原始消息 */
@Excel(name = "原始消息")
private String payload;
/** 解析JSON */
@Excel(name = "解析JSON")
private String dataJson;
/** 电量 */
@Excel(name = "电量")
private Long battery;
/** 温度 */
@Excel(name = "温度")
private BigDecimal temperature;
/** 湿度 */
@Excel(name = "湿度")
private BigDecimal humidity;
/** 氨气 */
@Excel(name = "氨气")
private BigDecimal nh3;
/** 硫化氢 */
@Excel(name = "硫化氢")
private BigDecimal h2s;
/** 烟雾浓度 */
@Excel(name = "烟雾浓度")
private Long concentration;
/** ✅ 水浸状态0=正常1=报警) */
@Excel(name = "水浸状态")
private Integer waterStatus;
/** 删除标识 */
@Excel(name = "删除标识")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public Long getDeviceId()
{
return deviceId;
}
public void setTopic(String topic)
{
this.topic = topic;
}
public String getTopic()
{
return topic;
}
public void setProject(String project)
{
this.project = project;
}
public String getProject()
{
return project;
}
public void setWarehouse(String warehouse)
{
this.warehouse = warehouse;
}
public String getWarehouse()
{
return warehouse;
}
public void setPayload(String payload)
{
this.payload = payload;
}
public String getPayload()
{
return payload;
}
public void setDataJson(String dataJson)
{
this.dataJson = dataJson;
}
public String getDataJson()
{
return dataJson;
}
public void setBattery(Long battery)
{
this.battery = battery;
}
public Long getBattery()
{
return battery;
}
public void setTemperature(BigDecimal temperature)
{
this.temperature = temperature;
}
public BigDecimal getTemperature()
{
return temperature;
}
public void setHumidity(BigDecimal humidity)
{
this.humidity = humidity;
}
public BigDecimal getHumidity()
{
return humidity;
}
public void setNh3(BigDecimal nh3)
{
this.nh3 = nh3;
}
public BigDecimal getNh3()
{
return nh3;
}
public void setH2s(BigDecimal h2s)
{
this.h2s = h2s;
}
public BigDecimal getH2s()
{
return h2s;
}
public void setConcentration(Long concentration)
{
this.concentration = concentration;
}
public Long getConcentration()
{
return concentration;
}
public void setWaterStatus(Integer waterStatus)
{
this.waterStatus = waterStatus;
}
public Integer getWaterStatus()
{
return waterStatus;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceId", getDeviceId())
.append("topic", getTopic())
.append("project", getProject())
.append("warehouse", getWarehouse())
.append("payload", getPayload())
.append("dataJson", getDataJson())
.append("battery", getBattery())
.append("temperature", getTemperature())
.append("humidity", getHumidity())
.append("nh3", getNh3())
.append("h2s", getH2s())
.append("concentration", getConcentration())
.append("waterStatus", getWaterStatus())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,132 @@
package com.shzg.project.worn.domain;
import com.shzg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.shzg.framework.aspectj.lang.annotation.Excel;
/**
* MQTT设备对象 mqtt_sensor_device
*
* @author shzg
* @date 2026-04-01
*/
public class MqttSensorDevice extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 设备唯一标识DevEUI */
@Excel(name = "设备唯一标识", readConverterExp = "D=evEUI")
private String devEui;
/** 设备名称 */
@Excel(name = "设备名称")
private String deviceName;
/** 设备类型smoke / env */
@Excel(name = "设备类型", readConverterExp = "s=moke,/=,e=nv")
private String deviceType;
/** 所属部门ID */
@Excel(name = "所属部门ID")
private Long deptId;
/** 状态0正常 1停用 */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
/** 删除标识0正常 1删除 */
@Excel(name = "删除标识", readConverterExp = "0=正常,1=删除")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDevEui(String devEui)
{
this.devEui = devEui;
}
public String getDevEui()
{
return devEui;
}
public void setDeviceName(String deviceName)
{
this.deviceName = deviceName;
}
public String getDeviceName()
{
return deviceName;
}
public void setDeviceType(String deviceType)
{
this.deviceType = deviceType;
}
public String getDeviceType()
{
return deviceType;
}
public void setDeptId(Long deptId)
{
this.deptId = deptId;
}
public Long getDeptId()
{
return deptId;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("devEui", getDevEui())
.append("deviceName", getDeviceName())
.append("deviceType", getDeviceType())
.append("deptId", getDeptId())
.append("status", getStatus())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,132 @@
package com.shzg.project.worn.domain;
import com.shzg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.shzg.framework.aspectj.lang.annotation.Excel;
/**
* 设备事件对象 mqtt_sensor_event
*
* @author shzg
* @date 2026-04-01
*/
public class MqttSensorEvent extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 设备ID */
@Excel(name = "设备ID")
private Long deviceId;
/** 事件类型alarm / threshold / normal */
@Excel(name = "事件类型", readConverterExp = "a=larm,/=,t=hreshold,/=,n=ormal")
private String eventType;
/** 事件描述 */
@Excel(name = "事件描述")
private String eventDesc;
/** 等级LOW/MEDIUM/HIGH */
@Excel(name = "等级", readConverterExp = "L=OW/MEDIUM/HIGH")
private String level;
/** 处理状态0未处理 1已处理 */
@Excel(name = "处理状态", readConverterExp = "0=未处理,1=已处理")
private String status;
/** 删除标识 */
@Excel(name = "删除标识")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public Long getDeviceId()
{
return deviceId;
}
public void setEventType(String eventType)
{
this.eventType = eventType;
}
public String getEventType()
{
return eventType;
}
public void setEventDesc(String eventDesc)
{
this.eventDesc = eventDesc;
}
public String getEventDesc()
{
return eventDesc;
}
public void setLevel(String level)
{
this.level = level;
}
public String getLevel()
{
return level;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceId", getDeviceId())
.append("eventType", getEventType())
.append("eventDesc", getEventDesc())
.append("level", getLevel())
.append("status", getStatus())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,179 @@
package com.shzg.project.worn.domain;
import java.math.BigDecimal;
import com.shzg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.shzg.framework.aspectj.lang.annotation.Excel;
/**
* 传感器阈值配置对象 mqtt_sensor_threshold
*
* @author shzg
* @date 2026-04-01
*/
public class MqttSensorThreshold extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 设备ID关联 mqtt_sensor_device.id */
@Excel(name = "设备ID", readConverterExp = "关=联,m=qtt_sensor_device.id")
private Long deviceId;
/** 指标类型temperature/humidity/nh3/h2s/battery */
@Excel(name = "指标类型", readConverterExp = "t=emperature/humidity/nh3/h2s/battery")
private String metricType;
/** 预警最小值 */
@Excel(name = "预警最小值")
private BigDecimal warnMin;
/** 预警最大值 */
@Excel(name = "预警最大值")
private BigDecimal warnMax;
/** 报警最小值 */
@Excel(name = "报警最小值")
private BigDecimal alarmMin;
/** 报警最大值 */
@Excel(name = "报警最大值")
private BigDecimal alarmMax;
/** 单位(℃/%/ppm */
@Excel(name = "单位", readConverterExp = "℃=/%/ppm")
private String unit;
/** 状态1启用 0停用 */
@Excel(name = "状态", readConverterExp = "1=启用,0=停用")
private String status;
/** 是否删除0正常 1删除 */
@Excel(name = "是否删除", readConverterExp = "0=正常,1=删除")
private String isDelete;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setDeviceId(Long deviceId)
{
this.deviceId = deviceId;
}
public Long getDeviceId()
{
return deviceId;
}
public void setMetricType(String metricType)
{
this.metricType = metricType;
}
public String getMetricType()
{
return metricType;
}
public void setWarnMin(BigDecimal warnMin)
{
this.warnMin = warnMin;
}
public BigDecimal getWarnMin()
{
return warnMin;
}
public void setWarnMax(BigDecimal warnMax)
{
this.warnMax = warnMax;
}
public BigDecimal getWarnMax()
{
return warnMax;
}
public void setAlarmMin(BigDecimal alarmMin)
{
this.alarmMin = alarmMin;
}
public BigDecimal getAlarmMin()
{
return alarmMin;
}
public void setAlarmMax(BigDecimal alarmMax)
{
this.alarmMax = alarmMax;
}
public BigDecimal getAlarmMax()
{
return alarmMax;
}
public void setUnit(String unit)
{
this.unit = unit;
}
public String getUnit()
{
return unit;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
}
public String getIsDelete()
{
return isDelete;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("deviceId", getDeviceId())
.append("metricType", getMetricType())
.append("warnMin", getWarnMin())
.append("warnMax", getWarnMax())
.append("alarmMin", getAlarmMin())
.append("alarmMax", getAlarmMax())
.append("unit", getUnit())
.append("status", getStatus())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("isDelete", getIsDelete())
.toString();
}
}

View File

@@ -0,0 +1,19 @@
package com.shzg.project.worn.domain.device;
public enum DeviceTypeEnum {
SMOKE("smoke", "烟雾传感器"),
ENV("env", "环境传感器");
private final String code;
private final String name;
DeviceTypeEnum(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
}

View File

@@ -0,0 +1,61 @@
package com.shzg.project.worn.mapper;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorCommand;
/**
* 指令管理Mapper接口
*
* @author shzg
* @date 2026-04-01
*/
public interface MqttSensorCommandMapper
{
/**
* 查询指令管理
*
* @param id 指令管理主键
* @return 指令管理
*/
public MqttSensorCommand selectMqttSensorCommandById(Long id);
/**
* 查询指令管理列表
*
* @param mqttSensorCommand 指令管理
* @return 指令管理集合
*/
public List<MqttSensorCommand> selectMqttSensorCommandList(MqttSensorCommand mqttSensorCommand);
/**
* 新增指令管理
*
* @param mqttSensorCommand 指令管理
* @return 结果
*/
public int insertMqttSensorCommand(MqttSensorCommand mqttSensorCommand);
/**
* 修改指令管理
*
* @param mqttSensorCommand 指令管理
* @return 结果
*/
public int updateMqttSensorCommand(MqttSensorCommand mqttSensorCommand);
/**
* 删除指令管理
*
* @param id 指令管理主键
* @return 结果
*/
public int deleteMqttSensorCommandById(Long id);
/**
* 批量删除指令管理
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMqttSensorCommandByIds(Long[] ids);
}

View File

@@ -0,0 +1,61 @@
package com.shzg.project.worn.mapper;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorData;
/**
* 设备数据Mapper接口
*
* @author shzg
* @date 2026-04-01
*/
public interface MqttSensorDataMapper
{
/**
* 查询设备数据
*
* @param id 设备数据主键
* @return 设备数据
*/
public MqttSensorData selectMqttSensorDataById(Long id);
/**
* 查询设备数据列表
*
* @param mqttSensorData 设备数据
* @return 设备数据集合
*/
public List<MqttSensorData> selectMqttSensorDataList(MqttSensorData mqttSensorData);
/**
* 新增设备数据
*
* @param mqttSensorData 设备数据
* @return 结果
*/
public int insertMqttSensorData(MqttSensorData mqttSensorData);
/**
* 修改设备数据
*
* @param mqttSensorData 设备数据
* @return 结果
*/
public int updateMqttSensorData(MqttSensorData mqttSensorData);
/**
* 删除设备数据
*
* @param id 设备数据主键
* @return 结果
*/
public int deleteMqttSensorDataById(Long id);
/**
* 批量删除设备数据
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMqttSensorDataByIds(Long[] ids);
}

View File

@@ -0,0 +1,70 @@
package com.shzg.project.worn.mapper;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorDevice;
import io.lettuce.core.dynamic.annotation.Param;
/**
* MQTT设备Mapper接口
*
* @author shzg
* @date 2026-04-01
*/
public interface MqttSensorDeviceMapper
{
/**
* 查询MQTT设备
*
* @param id MQTT设备主键
* @return MQTT设备
*/
public MqttSensorDevice selectMqttSensorDeviceById(Long id);
/**
* 查询MQTT设备列表
*
* @param mqttSensorDevice MQTT设备
* @return MQTT设备集合
*/
public List<MqttSensorDevice> selectMqttSensorDeviceList(MqttSensorDevice mqttSensorDevice);
/**
* 新增MQTT设备
*
* @param mqttSensorDevice MQTT设备
* @return 结果
*/
public int insertMqttSensorDevice(MqttSensorDevice mqttSensorDevice);
/**
* 修改MQTT设备
*
* @param mqttSensorDevice MQTT设备
* @return 结果
*/
public int updateMqttSensorDevice(MqttSensorDevice mqttSensorDevice);
/**
* 删除MQTT设备
*
* @param id MQTT设备主键
* @return 结果
*/
public int deleteMqttSensorDeviceById(Long id);
/**
* 批量删除MQTT设备
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMqttSensorDeviceByIds(Long[] ids);
/**
* 根据devEui查询设备
* @param
* @return
*/
MqttSensorDevice selectByDevEui(@Param("devEui") String devEui);
}

View File

@@ -0,0 +1,61 @@
package com.shzg.project.worn.mapper;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorEvent;
/**
* 设备事件Mapper接口
*
* @author shzg
* @date 2026-04-01
*/
public interface MqttSensorEventMapper
{
/**
* 查询设备事件
*
* @param id 设备事件主键
* @return 设备事件
*/
public MqttSensorEvent selectMqttSensorEventById(Long id);
/**
* 查询设备事件列表
*
* @param mqttSensorEvent 设备事件
* @return 设备事件集合
*/
public List<MqttSensorEvent> selectMqttSensorEventList(MqttSensorEvent mqttSensorEvent);
/**
* 新增设备事件
*
* @param mqttSensorEvent 设备事件
* @return 结果
*/
public int insertMqttSensorEvent(MqttSensorEvent mqttSensorEvent);
/**
* 修改设备事件
*
* @param mqttSensorEvent 设备事件
* @return 结果
*/
public int updateMqttSensorEvent(MqttSensorEvent mqttSensorEvent);
/**
* 删除设备事件
*
* @param id 设备事件主键
* @return 结果
*/
public int deleteMqttSensorEventById(Long id);
/**
* 批量删除设备事件
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMqttSensorEventByIds(Long[] ids);
}

View File

@@ -0,0 +1,69 @@
package com.shzg.project.worn.mapper;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorThreshold;
/**
* 传感器阈值配置Mapper接口
*
* @author shzg
* @date 2026-04-01
*/
public interface MqttSensorThresholdMapper
{
/**
* 查询传感器阈值配置
*
* @param id 传感器阈值配置主键
* @return 传感器阈值配置
*/
public MqttSensorThreshold selectMqttSensorThresholdById(Long id);
/**
* 查询传感器阈值配置列表
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 传感器阈值配置集合
*/
public List<MqttSensorThreshold> selectMqttSensorThresholdList(MqttSensorThreshold mqttSensorThreshold);
/**
* 新增传感器阈值配置
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 结果
*/
public int insertMqttSensorThreshold(MqttSensorThreshold mqttSensorThreshold);
/**
* 修改传感器阈值配置
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 结果
*/
public int updateMqttSensorThreshold(MqttSensorThreshold mqttSensorThreshold);
/**
* 删除传感器阈值配置
*
* @param id 传感器阈值配置主键
* @return 结果
*/
public int deleteMqttSensorThresholdById(Long id);
/**
* 批量删除传感器阈值配置
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMqttSensorThresholdByIds(Long[] ids);
/**
* 根据设备id和指标类型查询阈值配置
* @param deviceId
* @param metricType
* @return
*/
MqttSensorThreshold selectByDeviceAndMetric(Long deviceId, String metricType);
}

View File

@@ -1,4 +1,4 @@
package com.shzg.project.worn.sensor.config;//package com.zg.project.wisdom.config;
package com.shzg.project.worn.sensor.config;
import com.shzg.project.worn.sensor.mqtt.dispatcher.MqttMessageDispatcher;
import lombok.extern.slf4j.Slf4j;
@@ -10,73 +10,44 @@ import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
/**
* MQTT 客户端初始化配置类
*
* 作用说明:
* 1. Spring Boot 启动时自动创建 MQTT 客户端
* 2. 连接 EMQX Broker
* 3. 订阅 application.yml 中配置的 Topic支持通配符
* 4. 接收传感器上报的数据
*
* 说明:
* - 同一个 MQTT Client 同时支持「订阅(接收)」和「发布(下发指令)」
* - 后端一般只需要一个 Client
*/
@Slf4j
@Configuration
public class MqttClientConfig {
/**
* MQTT 客户端实例
* 由本配置类统一维护
*/
private MqttClient mqttClient;
@Resource
private MqttMessageDispatcher mqttMessageDispatcher;
/**
* 创建 MQTT Client Bean
*
* @param props MQTT 配置(来自 application.yml
*/
@Bean
public MqttClient mqttClient(MqttProperties props) throws MqttException {
// 如果未开启 MQTT 功能,直接不初始化
// 注意:此时 mqttClient Bean 为 null
if (!props.isEnabled()) {
log.warn("[MQTT] mqtt.enabled=falseMQTT 功能未启用");
return null;
}
// 1. 创建 MQTT 客户端
// ✅ clientId 动态生成
String clientId = "worn-backend-" + UUID.randomUUID();
mqttClient = new MqttClient(
props.getBroker(),
props.getClientId(),
clientId,
new MemoryPersistence()
);
// 2. MQTT 连接参数
// 连接参数
MqttConnectOptions options = new MqttConnectOptions();
// 是否清除会话:
// true - 断开后清除订阅(推荐后端使用)
// false - 保留会话(多用于设备端)
options.setCleanSession(props.isCleanSession());
// 心跳时间(秒)
options.setKeepAliveInterval(props.getKeepAlive());
// 连接超时时间(秒)
options.setConnectionTimeout(props.getTimeout());
// 自动重连(非常重要,防止网络抖动)
options.setAutomaticReconnect(true);
// 设置用户名密码(如果配置了)
if (props.getUsername() != null && !props.getUsername().trim().isEmpty()) {
options.setUserName(props.getUsername().trim());
}
@@ -84,89 +55,63 @@ public class MqttClientConfig {
options.setPassword(props.getPassword().toCharArray());
}
// 3. 设置 MQTT 回调
// 回调
mqttClient.setCallback(new MqttCallbackExtended() {
/**
* 连接成功(或重连成功)回调
*/
@Override
public void connectComplete(boolean reconnect, String serverURI) {
log.info("[MQTT] 连接成功 reconnect={}, serverURI={}", reconnect, serverURI);
// 连接成功后订阅 Topic
subscribe(props);
}
/**
* 连接丢失回调
*/
@Override
public void connectionLost(Throwable cause) {
log.warn("[MQTT] 连接断开", cause);
}
/**
* 接收到消息回调
*
* @param topic 消息主题(用于区分设备、类型)
* @param message 消息内容
*/
@Override
public void messageArrived(String topic, MqttMessage message) {
String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
log.info("🔥 收到MQTT消息 topic={} payload={}", topic, payload);
mqttMessageDispatcher.dispatch(topic, payload);
}
/**
* 消息发送完成回调(发布消息后触发)
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// 后端下发指令时可用于确认发送完成
}
});
// 4. 连接 Broker
// 连接
log.info("[MQTT] 正在连接 Broker{}", props.getBroker());
mqttClient.connect(options);
log.info("[MQTT] MQTT 已连接");
// 5. 启动时先订阅一次(防止 connectComplete 未触发)
// 启动订阅
subscribe(props);
return mqttClient;
}
/**
* 订阅 Topic支持通配符
*/
private void subscribe(MqttProperties props) {
if (mqttClient == null || !mqttClient.isConnected()) {
log.warn("[MQTT] 订阅失败:客户端未连接");
return;
}
if (props.getTopics() == null || props.getTopics().isEmpty()) {
log.warn("[MQTT] 未配置订阅 Topic");
return;
}
try {
for (String topic : props.getTopics()) {
if (topic == null || topic.trim().isEmpty()) {
continue;
}
mqttClient.subscribe(topic.trim(), props.getQos());
log.info("[MQTT] 已订阅 Topic{}QoS={}", topic.trim(), props.getQos());
}
mqttClient.subscribe("worn/tangshan/dianchi/up", props.getQos());
log.info("[MQTT] 已订阅 Topicworn/tangshan/dianchi/upQoS={}", props.getQos());
} catch (Exception e) {
log.error("[MQTT] 订阅 Topic 失败", e);
}
}
/**
* Spring 容器关闭时,优雅断开 MQTT 连接
*/
@PreDestroy
public void destroy() {
try {
@@ -179,4 +124,4 @@ public class MqttClientConfig {
} catch (Exception ignored) {
}
}
}
}

View File

@@ -4,10 +4,13 @@ import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* MQTT 配置属性(对应 application.yml 中 mqtt.*
*
* 当前说明:
* 1. 这里只保留 MQTT 连接相关配置
* 2. clientId 由代码中动态生成,不再从 yml 配置
* 3. topic 不再写死,统一从数据库 mqtt_sensor_device 获取
*/
@Data
@Component
@@ -17,16 +20,13 @@ public class MqttProperties {
/** 是否启用 MQTT */
private boolean enabled;
/** Broker 地址tcp://192.168.1.29:1883 */
/** Broker 地址,例如tcp://47.100.212.83:1883 */
private String broker;
/** 客户端ID在 EMQX 中唯一) */
private String clientId;
/** 账号 */
/** MQTT 账号 */
private String username;
/** 密码 */
/** MQTT 密码 */
private String password;
/** 是否清除会话 */
@@ -40,7 +40,4 @@ public class MqttProperties {
/** 默认 QoS */
private int qos = 1;
/** 订阅 Topic 列表(支持通配符) */
private List<String> topics;
}
}

View File

@@ -10,51 +10,27 @@ import java.nio.charset.StandardCharsets;
/**
* MQTT 消息发布客户端
*
* 作用说明
* - 专门用于向指定设备下发控制指令
* - 例如:开启 / 关闭 / 重启 传感器
*
* 说明:
* - 依赖同一个 MqttClient
* - 发布消息时使用“精确 Topic”不能使用通配符
* 支持
* 1. JSON消息发送
* 2. HEX指令发送设备控制
*/
@Slf4j
@Component
public class MqttPublishClient {
/**
* MQTT 客户端(由 Spring 注入)
*/
private final MqttClient mqttClient;
public MqttPublishClient(MqttClient mqttClient) {
this.mqttClient = mqttClient;
}
/**
* 发布 MQTT 消息(默认 QoS=1不保留消息
*
* @param topic 目标 Topic必须是具体设备的 Topic
* @param payload 消息内容JSON 字符串)
*/
// ================== JSON发送 ==================
public void publish(String topic, String payload) {
publish(topic, payload, 1, false);
}
/**
* 发布 MQTT 消息(自定义参数)
*/
public void publish(String topic, String payload, int qos, boolean retained) {
// 如果 MQTT 未启用或未初始化
if (mqttClient == null) {
throw new IllegalStateException("MQTT 客户端未初始化mqtt.enabled=false");
}
// 如果 MQTT 尚未连接
if (!mqttClient.isConnected()) {
throw new IllegalStateException("MQTT 客户端未连接到 Broker");
}
checkClient();
try {
MqttMessage msg = new MqttMessage(payload.getBytes(StandardCharsets.UTF_8));
@@ -63,12 +39,85 @@ public class MqttPublishClient {
mqttClient.publish(topic, msg);
log.info("[MQTT] 指令已发送 topic={}, qos={}, retained={}, payload={}",
topic, qos, retained, payload);
log.info("[MQTT] JSON发送成功 topic={}, payload={}, qos={}, retained={}",
topic, payload, qos, retained);
} catch (Exception e) {
log.error("[MQTT] 指令发送失败 topic=" + topic, e);
throw new RuntimeException(e);
log.error("[MQTT] JSON发送失败 topic=" + topic + ", payload=" + payload, e);
throw new RuntimeException("MQTT JSON发送失败", e);
}
}
}
// ================== ⭐ HEX发送 ==================
public void publishHex(String topic, String hexPayload) {
publishHex(topic, hexPayload, 1, false);
}
public void publishHex(String topic, String hexPayload, int qos, boolean retained) {
checkClient();
try {
byte[] bytes = hexStringToByteArray(hexPayload);
MqttMessage msg = new MqttMessage(bytes);
msg.setQos(qos);
msg.setRetained(retained);
mqttClient.publish(topic, msg);
log.info("[MQTT] HEX发送成功 topic={}, hex={}, length={}, qos={}, retained={}",
topic, hexPayload, bytes.length, qos, retained);
} catch (Exception e) {
log.error("[MQTT] HEX发送失败 topic=" + topic + ", hex=" + hexPayload, e);
throw new RuntimeException("MQTT HEX发送失败", e);
}
}
// ================== 客户端校验 ==================
private void checkClient() {
if (mqttClient == null) {
throw new IllegalStateException("MQTT客户端未初始化mqtt.enabled=false");
}
if (!mqttClient.isConnected()) {
throw new IllegalStateException("MQTT客户端未连接到Broker");
}
}
// ================== HEX工具 ==================
/**
* HEX字符串 → byte[]
* 支持:
* - 大小写
* - 自动去空格
*
* 示例:
* 2218000000C6 → [0x22,0x18,0x00,0x00,0x00,0xC6]
*/
private byte[] hexStringToByteArray(String hex) {
if (hex == null || hex.trim().isEmpty()) {
throw new IllegalArgumentException("HEX字符串不能为空");
}
// 去空格 + 转大写
hex = hex.replace(" ", "").toUpperCase();
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException("HEX字符串长度必须为偶数" + hex);
}
int len = hex.length();
byte[] data = new byte[len / 2];
try {
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
}
} catch (Exception e) {
throw new IllegalArgumentException("HEX字符串解析失败" + hex, e);
}
return data;
}
}

View File

@@ -1,55 +1,126 @@
package com.shzg.project.worn.sensor.mqtt.dispatcher;
import com.shzg.project.worn.sensor.mqtt.handler.HumiSensorHandler;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.sensor.mqtt.handler.EnvSensorHandler;
import com.shzg.project.worn.sensor.mqtt.handler.SmokeSensorHandler;
import com.shzg.project.worn.sensor.mqtt.handler.TempSensorHandler;
import com.shzg.project.worn.sensor.mqtt.handler.WaterSensorHandler;
import com.shzg.project.worn.unit.MqttDeviceCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.util.concurrent.Executor;
/**
* MQTT消息分发器
* 负责根据MQTT主题(topic)将消息分发给相应的传感器处理器
* MQTT消息分发器(支持烟雾 / 环境 / 水浸)
*/
@Slf4j
@Component
public class MqttMessageDispatcher {
@Autowired
private TempSensorHandler tempSensorHandler;
@Autowired
private HumiSensorHandler humiSensorHandler;
private MqttDeviceCache deviceCache;
@Autowired
private SmokeSensorHandler smokeSensorHandler;
@Autowired
private EnvSensorHandler envSensorHandler;
// ✅ 新增:水浸处理器
@Autowired
private WaterSensorHandler waterSensorHandler;
@Autowired
@Qualifier("mqttExecutor")
private Executor executor;
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
/**
* 分发MQTT消息到对应的处理器
* 根据topic的前缀判断消息类型并调用相应的处理器进行处理
*
* @param topic MQTT主题用于判断消息类型
* @param payload 消息负载,包含具体的传感器数据
* MQTT入口(异步)
*/
public void dispatch(String topic, String payload) {
// 处理温度传感器消息
if (topic.startsWith("zg/wms/test/temp/")) {
tempSensorHandler.handle(topic, payload);
return;
}
// 处理湿度传感器消息
if (topic.startsWith("zg/wms/test/humi/")) {
humiSensorHandler.handle(topic, payload);
return;
}
// 处理烟雾传感器消息
if (topic.startsWith("zg/wms/test/smoke/")) {
smokeSensorHandler.handle(topic, payload);
return;
}
log.warn("未知 MQTT Topic: {}", topic);
executor.execute(() -> doDispatch(topic, payload));
}
}
/**
* 核心分发逻辑
*/
private void doDispatch(String topic, String payload) {
log.info("[MQTT] 收到消息 topic={}, payload={}", topic, payload);
try {
// =========================
// 1⃣ JSON解析
// =========================
JsonNode root = OBJECT_MAPPER.readTree(payload);
if (!root.has("devEUI")) {
log.warn("[MQTT] payload中未找到devEUI");
return;
}
String devEui = root.get("devEUI").asText();
if (devEui == null || devEui.isEmpty()) {
log.warn("[MQTT] devEUI为空");
return;
}
// 👉 统一小写(关键)
devEui = devEui.toLowerCase();
// =========================
// 2⃣ 获取设备
// =========================
MqttSensorDevice device = deviceCache.get(devEui);
if (device == null) {
log.warn("[MQTT] 未匹配设备 devEUI={}", devEui);
return;
}
String deviceType = device.getDeviceType();
if (deviceType == null || deviceType.isEmpty()) {
log.warn("[MQTT] device_type为空 devEUI={}", devEui);
return;
}
deviceType = deviceType.toLowerCase();
// =========================
// 3⃣ 分发(核心)
// =========================
// 🔥 烟雾
if (deviceType.contains("smoke")) {
smokeSensorHandler.handle(device, topic, payload);
return;
}
// 🌡 环境
if (deviceType.contains("env")) {
envSensorHandler.handle(device, topic, payload);
return;
}
// 💧 水浸(新增)
if (deviceType.contains("water")) {
waterSensorHandler.handle(device, topic, payload);
return;
}
// ❌ 未识别
log.warn("[MQTT] 未识别设备类型 deviceType={}", deviceType);
} catch (Exception e) {
log.error("[MQTT] 分发异常 topic=" + topic + ", payload=" + payload, e);
}
}
}

View File

@@ -0,0 +1,251 @@
package com.shzg.project.worn.sensor.mqtt.handler;
import com.alibaba.fastjson2.JSONObject;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.domain.MqttSensorData;
import com.shzg.project.worn.domain.MqttSensorEvent;
import com.shzg.project.worn.domain.MqttSensorThreshold;
import com.shzg.project.worn.service.IMqttSensorDataService;
import com.shzg.project.worn.service.IMqttSensorEventService;
import com.shzg.project.worn.service.IMqttSensorThresholdService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 综合环境传感器 Handler最终生产版防重复报警 + 状态机)
*/
@Slf4j
@Component
public class EnvSensorHandler {
@Autowired
private IMqttSensorDataService sensorDataService;
@Autowired
private IMqttSensorEventService eventService;
@Autowired
private IMqttSensorThresholdService thresholdService;
/**
* 状态缓存(核心:防重复)
* key = deviceId_metric
* value = normal / warning / alarm
*/
private static final Map<String, String> STATUS_CACHE = new ConcurrentHashMap<>();
/**
* 主入口
*/
public void handle(MqttSensorDevice device, String topic, String payload) {
log.info("[ENV] deviceId={}, topic={}, payload={}", device.getId(), topic, payload);
JSONObject json = parseJson(payload);
if (json == null) return;
SensorValue val = buildValue(json);
if (val.isEmpty()) return;
TopicInfo topicInfo = parseTopic(topic);
// 1⃣ 数据入库
saveData(device, topic, payload, topicInfo, val);
// 2⃣ 状态检测(核心)
handleEvent(device, val);
}
// ================== 事件处理 ==================
private void handleEvent(MqttSensorDevice device, SensorValue v) {
check(device, "temperature", v.temperature, "温度");
check(device, "humidity", v.humidity, "湿度");
check(device, "nh3", v.nh3, "氨气");
check(device, "h2s", v.h2s, "硫化氢");
// 电量(单独处理)
if (v.battery != null) {
MqttSensorThreshold t = thresholdService.getThreshold(device.getId(), "battery");
if (t != null) {
BigDecimal val = new BigDecimal(v.battery);
String status = calcStatus(val, t);
changeStatus(device, "battery", status, "电量:" + v.battery + "%");
}
}
}
// ================== 通用检测 ==================
private void check(MqttSensorDevice device,
String metric,
BigDecimal value,
String name) {
if (value == null) return;
MqttSensorThreshold t = thresholdService.getThreshold(device.getId(), metric);
if (t == null) return;
String status = calcStatus(value, t);
changeStatus(device, metric, status, name + ":" + value);
}
// ================== 状态计算 ==================
private String calcStatus(BigDecimal value, MqttSensorThreshold t) {
if (t.getAlarmMax() != null && value.compareTo(t.getAlarmMax()) > 0) {
return "alarm";
}
if (t.getAlarmMin() != null && value.compareTo(t.getAlarmMin()) < 0) {
return "alarm";
}
if (t.getWarnMax() != null && value.compareTo(t.getWarnMax()) > 0) {
return "warning";
}
if (t.getWarnMin() != null && value.compareTo(t.getWarnMin()) < 0) {
return "warning";
}
return "normal";
}
// ================== 状态变更 ==================
private void changeStatus(MqttSensorDevice device,
String metric,
String newStatus,
String desc) {
String key = device.getId() + "_" + metric;
String oldStatus = STATUS_CACHE.get(key);
// ❗ 防重复:状态没变,不处理
if (newStatus.equals(oldStatus)) {
return;
}
// 更新缓存
STATUS_CACHE.put(key, newStatus);
// 状态变化 → 记录事件
if ("alarm".equals(newStatus)) {
triggerEvent(device, "alarm", "HIGH", desc);
} else if ("warning".equals(newStatus)) {
triggerEvent(device, "warning", "MEDIUM", desc);
} else if ("normal".equals(newStatus)) {
triggerEvent(device, "recovery", "LOW", desc + " 正常");
}
}
// ================== 事件记录 ==================
private void triggerEvent(MqttSensorDevice device,
String type,
String level,
String desc) {
log.warn("[ENV事件] deviceId={}, type={}, level={}, desc={}",
device.getId(), type, level, desc);
MqttSensorEvent event = new MqttSensorEvent();
event.setDeviceId(device.getId());
event.setEventType(type);
event.setLevel(level);
event.setEventDesc(desc);
event.setStatus("0");
event.setIsDelete("0");
event.setCreateTime(new Date());
eventService.insertMqttSensorEvent(event);
// TODO: D2D联动风机/排风)
// TODO: 短信通知
// TODO: APP推送
}
// ================== 数据入库 ==================
private void saveData(MqttSensorDevice device,
String topic,
String payload,
TopicInfo topicInfo,
SensorValue v) {
MqttSensorData data = new MqttSensorData();
data.setDeviceId(device.getId());
data.setTopic(topic);
data.setProject(topicInfo.project);
data.setWarehouse(topicInfo.warehouse);
data.setPayload(payload);
data.setDataJson(payload);
data.setTemperature(v.temperature);
data.setHumidity(v.humidity);
data.setNh3(v.nh3);
data.setH2s(v.h2s);
data.setBattery(v.battery == null ? null : Long.valueOf(v.battery));
data.setCreateTime(new Date());
data.setIsDelete("0");
sensorDataService.insertMqttSensorData(data);
}
// ================== JSON解析 ==================
private JSONObject parseJson(String payload) {
try {
return JSONObject.parseObject(payload);
} catch (Exception e) {
log.error("[ENV] JSON解析失败 payload={}", payload, e);
return null;
}
}
// ================== 构建数据 ==================
private SensorValue buildValue(JSONObject json) {
SensorValue v = new SensorValue();
v.temperature = json.getBigDecimal("temperature");
v.humidity = json.getBigDecimal("humidity");
v.nh3 = json.getBigDecimal("nh3");
v.h2s = json.getBigDecimal("h2s");
v.battery = json.getInteger("battery");
return v;
}
// ================== topic解析 ==================
private TopicInfo parseTopic(String topic) {
TopicInfo info = new TopicInfo();
try {
String[] arr = topic.split("/");
info.project = arr.length > 1 ? arr[1] : "";
info.warehouse = arr.length > 2 ? arr[2] : "";
} catch (Exception e) {
log.warn("[ENV] topic解析失败 topic={}", topic);
}
return info;
}
// ================== 内部结构 ==================
private static class SensorValue {
BigDecimal temperature;
BigDecimal humidity;
BigDecimal nh3;
BigDecimal h2s;
Integer battery;
boolean isEmpty() {
return temperature == null && humidity == null && nh3 == null && h2s == null;
}
}
private static class TopicInfo {
String project;
String warehouse;
}
}

View File

@@ -1,43 +0,0 @@
package com.shzg.project.worn.sensor.mqtt.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 湿度传感器 Handler
* Topic 示例zg/wms/test/humi/{deviceId}
*/
@Slf4j
@Component
public class HumiSensorHandler {
public static final String TOPIC_PREFIX = "zg/wms/test/humi/";
/**
* 处理湿度传感器消息
* @param topic MQTT主题
* @param payload 消息负载
*/
public void handle(String topic, String payload) {
String deviceId = resolveDeviceId(topic, TOPIC_PREFIX);
log.info("[HUMI] deviceId={}, topic={}, payload={}", deviceId, topic, payload);
// TODO: 这里后续写湿度业务逻辑
}
/**
* 从MQTT主题中解析设备ID
* @param topic MQTT主题
* @param prefix 主题前缀
* @return 设备ID
*/
private String resolveDeviceId(String topic, String prefix) {
if (topic == null || !topic.startsWith(prefix)) {
return "";
}
// 提取设备ID部分
return topic.substring(prefix.length());
}
}

View File

@@ -1,47 +1,124 @@
package com.shzg.project.worn.sensor.mqtt.handler;
import com.alibaba.fastjson2.JSONObject;
import com.shzg.project.worn.domain.MqttSensorData;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.domain.MqttSensorEvent;
import com.shzg.project.worn.service.IMqttSensorDataService;
import com.shzg.project.worn.service.IMqttSensorEventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 烟雾传感器 Handler
* Topic 示例zg/wms/test/smoke/{deviceId}
*/
import java.math.BigDecimal;
@Slf4j
@Component
public class SmokeSensorHandler {
/**
* MQTT主题前缀用于烟雾传感器消息
*/
public static final String TOPIC_PREFIX = "zg/wms/test/smoke/";
@Autowired
private IMqttSensorDataService dataService;
@Autowired
private IMqttSensorEventService eventService;
/**
* 处理烟雾传感器消息
*
* @param topic MQTT主题
* @param payload 消息负载内容
*/
public void handle(String topic, String payload) {
String deviceId = resolveDeviceId(topic, TOPIC_PREFIX);
public void handle(MqttSensorDevice device, String topic, String payload) {
log.info("[SMOKE] deviceId={}, topic={}, payload={}", deviceId, topic, payload);
log.info("[SMOKE] deviceId={}, deviceName={}, topic={}, payload={}",
device.getId(), device.getDeviceName(), topic, payload);
// TODO: 这里后续写烟雾业务逻辑
}
JSONObject json;
/**
* 从MQTT主题中解析设备ID
*
* @param topic 完整的MQTT主题
* @param prefix 主题前缀
* @return 设备ID如果主题格式不正确则返回空字符串
*/
private String resolveDeviceId(String topic, String prefix) {
if (topic == null || !topic.startsWith(prefix)) {
return "";
try {
json = JSONObject.parseObject(payload);
} catch (Exception e) {
log.error("[SMOKE] JSON解析失败 payload={}", payload, e);
return;
}
// 提取前缀后的设备ID部分
return topic.substring(prefix.length());
// ================== topic解析 ==================
String project = null;
String warehouse = null;
try {
String[] arr = topic.split("/");
if (arr.length >= 3) {
project = arr[1]; // tangshan
warehouse = arr[2]; // dianchi
}
} catch (Exception e) {
log.warn("[SMOKE] topic解析失败 topic={}", topic);
}
// ================== 字段 ==================
String event = json.getString("event");
Integer battery = json.getInteger("battery");
Integer concentration = json.getInteger("concentration");
Integer temperature = json.getInteger("temperature");
// ================== 入库 ==================
MqttSensorData data = new MqttSensorData();
data.setDeviceId(device.getId());
data.setTopic(topic);
data.setProject(project);
data.setWarehouse(warehouse);
data.setPayload(payload);
data.setDataJson(json.toJSONString());
data.setBattery(battery != null ? battery.longValue() : null);
data.setConcentration(concentration != null ? concentration.longValue() : null);
data.setTemperature(temperature != null ? new BigDecimal(temperature) : null);
data.setIsDelete("0");
dataService.insertMqttSensorData(data);
// ================== 事件 ==================
if ("silent".equals(event)) {
insertEvent(device, "silent", "人为静音报警", "LOW");
return;
}
if ("alarm".equals(event) || (concentration != null && concentration > 0)) {
insertEvent(device, "alarm", "烟雾报警", "HIGH");
return;
}
if ("removed".equals(event)) {
insertEvent(device, "removed", "设备被拆/离位", "MEDIUM");
return;
}
if ("low_battery".equals(event)) {
insertEvent(device, "low_battery", "低电量告警", "LOW");
return;
}
if (battery != null && battery < 20) {
log.info("[SMOKE] 电量偏低 deviceId={}, battery={}",
device.getId(), battery);
}
log.info("[SMOKE] 正常数据 deviceId={}, battery={}, temp={}",
device.getId(), battery, temperature);
}
}
private void insertEvent(MqttSensorDevice device, String type, String desc, String level) {
MqttSensorEvent event = new MqttSensorEvent();
event.setDeviceId(device.getId());
event.setEventType(type);
event.setEventDesc(desc);
event.setLevel(level);
event.setStatus("0");
eventService.insertMqttSensorEvent(event);
}
}

View File

@@ -1,46 +0,0 @@
package com.shzg.project.worn.sensor.mqtt.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 温度传感器 Handler
* Topic 示例zg/wms/test/temp/{deviceId}
*/
@Slf4j
@Component
public class TempSensorHandler {
/**
* MQTT主题前缀用于温度传感器数据
*/
public static final String TOPIC_PREFIX = "zg/wms/test/temp/";
/**
* 处理温度传感器数据
*
* @param topic MQTT主题格式为 zg/wms/test/temp/{deviceId}
* @param payload 传感器数据载荷
*/
public void handle(String topic, String payload) {
String deviceId = resolveDeviceId(topic, TOPIC_PREFIX);
log.info("[TEMP] deviceId={}, topic={}, payload={}", deviceId, topic, payload);
// TODO: 这里后续写温度业务逻辑解析JSON、落库、告警等
}
/**
* 从MQTT主题中解析设备ID
*
* @param topic MQTT主题
* @param prefix 主题前缀
* @return 设备ID如果主题格式不正确则返回空字符串
*/
private String resolveDeviceId(String topic, String prefix) {
if (topic == null || !topic.startsWith(prefix)) {
return "";
}
return topic.substring(prefix.length());
}
}

View File

@@ -0,0 +1,214 @@
package com.shzg.project.worn.sensor.mqtt.handler;
import com.alibaba.fastjson2.JSONObject;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.domain.MqttSensorData;
import com.shzg.project.worn.domain.MqttSensorEvent;
import com.shzg.project.worn.service.IMqttSensorDataService;
import com.shzg.project.worn.service.IMqttSensorEventService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 水浸传感器 Handler对齐 Env 结构:状态机 + 防重复)
*/
@Slf4j
@Component
public class WaterSensorHandler {
@Autowired
private IMqttSensorDataService sensorDataService;
@Autowired
private IMqttSensorEventService eventService;
/**
* 状态缓存(防重复报警)
* key = deviceId_water
*/
private static final Map<String, String> STATUS_CACHE = new ConcurrentHashMap<>();
/**
* 主入口
*/
public void handle(MqttSensorDevice device, String topic, String payload) {
log.info("[WATER] deviceId={}, topic={}, payload={}", device.getId(), topic, payload);
JSONObject json = parseJson(payload);
if (json == null) return;
// 👉 从 data 字段解析Base64
Integer water = parseWater(json);
if (water == null) {
log.warn("[WATER] 无法解析水浸状态");
return;
}
TopicInfo topicInfo = parseTopic(topic);
// 1⃣ 数据入库
saveData(device, topic, payload, topicInfo, water);
// 2⃣ 状态处理
handleEvent(device, water);
}
// ================== 事件处理 ==================
private void handleEvent(MqttSensorDevice device, Integer water) {
String status;
// 👉 水浸1=有水报警0=正常
if (water == 1) {
status = "alarm";
} else {
status = "normal";
}
changeStatus(device, status, water);
}
// ================== 状态变更 ==================
private void changeStatus(MqttSensorDevice device,
String newStatus,
Integer water) {
String key = device.getId() + "_water";
String oldStatus = STATUS_CACHE.get(key);
// ❗ 防重复
if (newStatus.equals(oldStatus)) {
return;
}
STATUS_CACHE.put(key, newStatus);
if ("alarm".equals(newStatus)) {
triggerEvent(device, "alarm", "HIGH", "浸水预警!");
} else if ("normal".equals(newStatus)) {
triggerEvent(device, "recovery", "LOW", "水浸正常");
}
}
// ================== 事件记录 ==================
private void triggerEvent(MqttSensorDevice device,
String type,
String level,
String desc) {
log.warn("[WATER事件] deviceId={}, type={}, level={}, desc={}",
device.getId(), type, level, desc);
MqttSensorEvent event = new MqttSensorEvent();
event.setDeviceId(device.getId());
event.setEventType(type);
event.setLevel(level);
event.setEventDesc(desc);
event.setStatus("0");
event.setIsDelete("0");
event.setCreateTime(new Date());
eventService.insertMqttSensorEvent(event);
// TODO: 联动排水 / 告警推送
}
// ================== 数据入库 ==================
private void saveData(MqttSensorDevice device,
String topic,
String payload,
TopicInfo topicInfo,
Integer water) {
MqttSensorData data = new MqttSensorData();
data.setDeviceId(device.getId());
data.setTopic(topic);
data.setProject(topicInfo.project);
data.setWarehouse(topicInfo.warehouse);
data.setPayload(payload);
data.setDataJson(payload);
data.setWaterStatus(water);
data.setCreateTime(new Date());
data.setIsDelete("0");
sensorDataService.insertMqttSensorData(data);
}
// ================== JSON解析 ==================
private JSONObject parseJson(String payload) {
try {
return JSONObject.parseObject(payload);
} catch (Exception e) {
log.error("[WATER] JSON解析失败 payload={}", payload, e);
return null;
}
}
// ================== 解析水浸 ==================
private Integer parseWater(JSONObject json) {
try {
// 👉 LoRaWAN 原始数据Base64
String data = json.getString("data");
if (data == null) return null;
byte[] bytes = java.util.Base64.getDecoder().decode(data);
/**
* Milesight水浸协议关键
* 一般结构:
* [channel_id][channel_type][value]
*
* 水浸:
* channel_id = 0x05
* channel_type = 0x00
* value = 0/1
*/
for (int i = 0; i < bytes.length - 2; i++) {
int channelId = bytes[i] & 0xFF;
int channelType = bytes[i + 1] & 0xFF;
// 👉 水浸
if (channelId == 0x05 && channelType == 0x00) {
return bytes[i + 2] & 0xFF;
}
}
} catch (Exception e) {
log.error("[WATER] 解析payload失败", e);
}
return null;
}
// ================== topic解析 ==================
private TopicInfo parseTopic(String topic) {
TopicInfo info = new TopicInfo();
try {
String[] arr = topic.split("/");
info.project = arr.length > 1 ? arr[1] : "";
info.warehouse = arr.length > 2 ? arr[2] : "";
} catch (Exception e) {
log.warn("[WATER] topic解析失败 topic={}", topic);
}
return info;
}
// ================== 内部结构 ==================
private static class TopicInfo {
String project;
String warehouse;
}
}

View File

@@ -0,0 +1,8 @@
package com.shzg.project.worn.service;
public interface IDeviceCommandService {
void smokeStop(Long deviceId);
void smokeStopOnce(Long deviceId);
}

View File

@@ -0,0 +1,61 @@
package com.shzg.project.worn.service;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorCommand;
/**
* 指令管理Service接口
*
* @author shzg
* @date 2026-04-01
*/
public interface IMqttSensorCommandService
{
/**
* 查询指令管理
*
* @param id 指令管理主键
* @return 指令管理
*/
public MqttSensorCommand selectMqttSensorCommandById(Long id);
/**
* 查询指令管理列表
*
* @param mqttSensorCommand 指令管理
* @return 指令管理集合
*/
public List<MqttSensorCommand> selectMqttSensorCommandList(MqttSensorCommand mqttSensorCommand);
/**
* 新增指令管理
*
* @param mqttSensorCommand 指令管理
* @return 结果
*/
public int insertMqttSensorCommand(MqttSensorCommand mqttSensorCommand);
/**
* 修改指令管理
*
* @param mqttSensorCommand 指令管理
* @return 结果
*/
public int updateMqttSensorCommand(MqttSensorCommand mqttSensorCommand);
/**
* 批量删除指令管理
*
* @param ids 需要删除的指令管理主键集合
* @return 结果
*/
public int deleteMqttSensorCommandByIds(Long[] ids);
/**
* 删除指令管理信息
*
* @param id 指令管理主键
* @return 结果
*/
public int deleteMqttSensorCommandById(Long id);
}

View File

@@ -0,0 +1,61 @@
package com.shzg.project.worn.service;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorData;
/**
* 设备数据Service接口
*
* @author shzg
* @date 2026-04-01
*/
public interface IMqttSensorDataService
{
/**
* 查询设备数据
*
* @param id 设备数据主键
* @return 设备数据
*/
public MqttSensorData selectMqttSensorDataById(Long id);
/**
* 查询设备数据列表
*
* @param mqttSensorData 设备数据
* @return 设备数据集合
*/
public List<MqttSensorData> selectMqttSensorDataList(MqttSensorData mqttSensorData);
/**
* 新增设备数据
*
* @param mqttSensorData 设备数据
* @return 结果
*/
public int insertMqttSensorData(MqttSensorData mqttSensorData);
/**
* 修改设备数据
*
* @param mqttSensorData 设备数据
* @return 结果
*/
public int updateMqttSensorData(MqttSensorData mqttSensorData);
/**
* 批量删除设备数据
*
* @param ids 需要删除的设备数据主键集合
* @return 结果
*/
public int deleteMqttSensorDataByIds(Long[] ids);
/**
* 删除设备数据信息
*
* @param id 设备数据主键
* @return 结果
*/
public int deleteMqttSensorDataById(Long id);
}

View File

@@ -0,0 +1,68 @@
package com.shzg.project.worn.service;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorDevice;
/**
* MQTT设备Service接口
*
* @author shzg
* @date 2026-04-01
*/
public interface IMqttSensorDeviceService
{
/**
* 查询MQTT设备
*
* @param id MQTT设备主键
* @return MQTT设备
*/
public MqttSensorDevice selectMqttSensorDeviceById(Long id);
/**
* 查询MQTT设备列表
*
* @param mqttSensorDevice MQTT设备
* @return MQTT设备集合
*/
public List<MqttSensorDevice> selectMqttSensorDeviceList(MqttSensorDevice mqttSensorDevice);
/**
* 新增MQTT设备
*
* @param mqttSensorDevice MQTT设备
* @return 结果
*/
public int insertMqttSensorDevice(MqttSensorDevice mqttSensorDevice);
/**
* 修改MQTT设备
*
* @param mqttSensorDevice MQTT设备
* @return 结果
*/
public int updateMqttSensorDevice(MqttSensorDevice mqttSensorDevice);
/**
* 批量删除MQTT设备
*
* @param ids 需要删除的MQTT设备主键集合
* @return 结果
*/
public int deleteMqttSensorDeviceByIds(Long[] ids);
/**
* 删除MQTT设备信息
*
* @param id MQTT设备主键
* @return 结果
*/
public int deleteMqttSensorDeviceById(Long id);
/**
* 根据devEui查询设备
* @param devEui
* @return
*/
MqttSensorDevice selectByDevEui(String devEui);
}

View File

@@ -0,0 +1,61 @@
package com.shzg.project.worn.service;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorEvent;
/**
* 设备事件Service接口
*
* @author shzg
* @date 2026-04-01
*/
public interface IMqttSensorEventService
{
/**
* 查询设备事件
*
* @param id 设备事件主键
* @return 设备事件
*/
public MqttSensorEvent selectMqttSensorEventById(Long id);
/**
* 查询设备事件列表
*
* @param mqttSensorEvent 设备事件
* @return 设备事件集合
*/
public List<MqttSensorEvent> selectMqttSensorEventList(MqttSensorEvent mqttSensorEvent);
/**
* 新增设备事件
*
* @param mqttSensorEvent 设备事件
* @return 结果
*/
public int insertMqttSensorEvent(MqttSensorEvent mqttSensorEvent);
/**
* 修改设备事件
*
* @param mqttSensorEvent 设备事件
* @return 结果
*/
public int updateMqttSensorEvent(MqttSensorEvent mqttSensorEvent);
/**
* 批量删除设备事件
*
* @param ids 需要删除的设备事件主键集合
* @return 结果
*/
public int deleteMqttSensorEventByIds(Long[] ids);
/**
* 删除设备事件信息
*
* @param id 设备事件主键
* @return 结果
*/
public int deleteMqttSensorEventById(Long id);
}

View File

@@ -0,0 +1,69 @@
package com.shzg.project.worn.service;
import java.util.List;
import com.shzg.project.worn.domain.MqttSensorThreshold;
/**
* 传感器阈值配置Service接口
*
* @author shzg
* @date 2026-04-01
*/
public interface IMqttSensorThresholdService
{
/**
* 查询传感器阈值配置
*
* @param id 传感器阈值配置主键
* @return 传感器阈值配置
*/
public MqttSensorThreshold selectMqttSensorThresholdById(Long id);
/**
* 查询传感器阈值配置列表
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 传感器阈值配置集合
*/
public List<MqttSensorThreshold> selectMqttSensorThresholdList(MqttSensorThreshold mqttSensorThreshold);
/**
* 新增传感器阈值配置
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 结果
*/
public int insertMqttSensorThreshold(MqttSensorThreshold mqttSensorThreshold);
/**
* 修改传感器阈值配置
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 结果
*/
public int updateMqttSensorThreshold(MqttSensorThreshold mqttSensorThreshold);
/**
* 批量删除传感器阈值配置
*
* @param ids 需要删除的传感器阈值配置主键集合
* @return 结果
*/
public int deleteMqttSensorThresholdByIds(Long[] ids);
/**
* 删除传感器阈值配置信息
*
* @param id 传感器阈值配置主键
* @return 结果
*/
public int deleteMqttSensorThresholdById(Long id);
/**
* 根据设备ID和指标类型获取阈值
* @param deviceId
* @param metricType
* @return
*/
MqttSensorThreshold getThreshold(Long deviceId, String metricType);
}

View File

@@ -0,0 +1,147 @@
package com.shzg.project.worn.service.impl;
import com.alibaba.fastjson2.JSONObject;
import com.shzg.project.worn.domain.MqttSensorCommand;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.mapper.MqttSensorDeviceMapper;
import com.shzg.project.worn.sensor.config.MqttPublishClient;
import com.shzg.project.worn.service.IDeviceCommandService;
import com.shzg.project.worn.service.IMqttSensorCommandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Base64;
import java.util.Date;
@Service
public class DeviceCommandServiceImpl implements IDeviceCommandService {
@Autowired
private MqttPublishClient mqttPublishClient;
@Autowired
private MqttSensorDeviceMapper deviceMapper;
@Autowired
private IMqttSensorCommandService commandService;
// ================== Topic ==================
private String buildDownTopic(String devEui) {
return "worn/tangshan/dianchi/downlink/" + devEui;
}
// ================== 指令 ==================
@Override
public void smokeStop(Long deviceId) {
MqttSensorDevice device = getDevice(deviceId);
String topic = buildDownTopic(device.getDevEui());
String base64 = hexToBase64("2219000000C5");
String payload = buildPayload(base64);
executeCommand(deviceId, topic, "smokeStop", payload);
}
@Override
public void smokeStopOnce(Long deviceId) {
MqttSensorDevice device = getDevice(deviceId);
String topic = buildDownTopic(device.getDevEui());
String base64 = hexToBase64("2218000000C6");
String payload = buildPayload(base64);
executeCommand(deviceId, topic, "smokeStopOnce", payload);
}
// ================== 指令执行 ==================
private void executeCommand(Long deviceId, String topic, String command, String payload) {
MqttSensorCommand cmd = new MqttSensorCommand();
cmd.setDeviceId(deviceId);
cmd.setTopic(topic);
cmd.setCommand(command);
cmd.setPayload(payload);
cmd.setStatus("0");
cmd.setSendTime(new Date());
commandService.insertMqttSensorCommand(cmd);
try {
mqttPublishClient.publish(topic, payload);
cmd.setStatus("1");
commandService.updateMqttSensorCommand(cmd);
} catch (Exception e) {
cmd.setStatus("2");
commandService.updateMqttSensorCommand(cmd);
throw new RuntimeException("指令发送失败", e);
}
}
// ================== 公共方法 ==================
private MqttSensorDevice getDevice(Long deviceId) {
if (deviceId == null) {
throw new RuntimeException("设备ID不能为空");
}
MqttSensorDevice device = deviceMapper.selectMqttSensorDeviceById(deviceId);
if (device == null) {
throw new RuntimeException("设备不存在");
}
if (device.getDevEui() == null || device.getDevEui().isEmpty()) {
throw new RuntimeException("设备未配置devEUI");
}
if (!"0".equals(device.getStatus())) {
throw new RuntimeException("设备已禁用");
}
return device;
}
// ================== 工具方法 ==================
private String hexToBase64(String hex) {
byte[] bytes = hexStringToByteArray(hex);
return Base64.getEncoder().encodeToString(bytes);
}
private String buildPayload(String base64) {
JSONObject json = new JSONObject();
json.put("confirmed", true);
json.put("fport", 85);
json.put("data", base64);
return json.toJSONString();
}
private byte[] hexStringToByteArray(String hex) {
hex = hex.replace(" ", "").toUpperCase();
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
}
return data;
}
}

View File

@@ -0,0 +1,96 @@
package com.shzg.project.worn.service.impl;
import java.util.List;
import com.shzg.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shzg.project.worn.mapper.MqttSensorCommandMapper;
import com.shzg.project.worn.domain.MqttSensorCommand;
import com.shzg.project.worn.service.IMqttSensorCommandService;
/**
* 指令管理Service业务层处理
*
* @author shzg
* @date 2026-04-01
*/
@Service
public class MqttSensorCommandServiceImpl implements IMqttSensorCommandService
{
@Autowired
private MqttSensorCommandMapper mqttSensorCommandMapper;
/**
* 查询指令管理
*
* @param id 指令管理主键
* @return 指令管理
*/
@Override
public MqttSensorCommand selectMqttSensorCommandById(Long id)
{
return mqttSensorCommandMapper.selectMqttSensorCommandById(id);
}
/**
* 查询指令管理列表
*
* @param mqttSensorCommand 指令管理
* @return 指令管理
*/
@Override
public List<MqttSensorCommand> selectMqttSensorCommandList(MqttSensorCommand mqttSensorCommand)
{
return mqttSensorCommandMapper.selectMqttSensorCommandList(mqttSensorCommand);
}
/**
* 新增指令管理
*
* @param mqttSensorCommand 指令管理
* @return 结果
*/
@Override
public int insertMqttSensorCommand(MqttSensorCommand mqttSensorCommand)
{
mqttSensorCommand.setCreateTime(DateUtils.getNowDate());
return mqttSensorCommandMapper.insertMqttSensorCommand(mqttSensorCommand);
}
/**
* 修改指令管理
*
* @param mqttSensorCommand 指令管理
* @return 结果
*/
@Override
public int updateMqttSensorCommand(MqttSensorCommand mqttSensorCommand)
{
mqttSensorCommand.setUpdateTime(DateUtils.getNowDate());
return mqttSensorCommandMapper.updateMqttSensorCommand(mqttSensorCommand);
}
/**
* 批量删除指令管理
*
* @param ids 需要删除的指令管理主键
* @return 结果
*/
@Override
public int deleteMqttSensorCommandByIds(Long[] ids)
{
return mqttSensorCommandMapper.deleteMqttSensorCommandByIds(ids);
}
/**
* 删除指令管理信息
*
* @param id 指令管理主键
* @return 结果
*/
@Override
public int deleteMqttSensorCommandById(Long id)
{
return mqttSensorCommandMapper.deleteMqttSensorCommandById(id);
}
}

View File

@@ -0,0 +1,96 @@
package com.shzg.project.worn.service.impl;
import java.util.List;
import com.shzg.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shzg.project.worn.mapper.MqttSensorDataMapper;
import com.shzg.project.worn.domain.MqttSensorData;
import com.shzg.project.worn.service.IMqttSensorDataService;
/**
* 设备数据Service业务层处理
*
* @author shzg
* @date 2026-04-01
*/
@Service
public class MqttSensorDataServiceImpl implements IMqttSensorDataService
{
@Autowired
private MqttSensorDataMapper mqttSensorDataMapper;
/**
* 查询设备数据
*
* @param id 设备数据主键
* @return 设备数据
*/
@Override
public MqttSensorData selectMqttSensorDataById(Long id)
{
return mqttSensorDataMapper.selectMqttSensorDataById(id);
}
/**
* 查询设备数据列表
*
* @param mqttSensorData 设备数据
* @return 设备数据
*/
@Override
public List<MqttSensorData> selectMqttSensorDataList(MqttSensorData mqttSensorData)
{
return mqttSensorDataMapper.selectMqttSensorDataList(mqttSensorData);
}
/**
* 新增设备数据
*
* @param mqttSensorData 设备数据
* @return 结果
*/
@Override
public int insertMqttSensorData(MqttSensorData mqttSensorData)
{
mqttSensorData.setCreateTime(DateUtils.getNowDate());
return mqttSensorDataMapper.insertMqttSensorData(mqttSensorData);
}
/**
* 修改设备数据
*
* @param mqttSensorData 设备数据
* @return 结果
*/
@Override
public int updateMqttSensorData(MqttSensorData mqttSensorData)
{
mqttSensorData.setUpdateTime(DateUtils.getNowDate());
return mqttSensorDataMapper.updateMqttSensorData(mqttSensorData);
}
/**
* 批量删除设备数据
*
* @param ids 需要删除的设备数据主键
* @return 结果
*/
@Override
public int deleteMqttSensorDataByIds(Long[] ids)
{
return mqttSensorDataMapper.deleteMqttSensorDataByIds(ids);
}
/**
* 删除设备数据信息
*
* @param id 设备数据主键
* @return 结果
*/
@Override
public int deleteMqttSensorDataById(Long id)
{
return mqttSensorDataMapper.deleteMqttSensorDataById(id);
}
}

View File

@@ -0,0 +1,130 @@
package com.shzg.project.worn.service.impl;
import java.util.List;
import com.shzg.common.utils.DateUtils;
import com.shzg.project.worn.unit.MqttDeviceCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shzg.project.worn.mapper.MqttSensorDeviceMapper;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.service.IMqttSensorDeviceService;
/**
* MQTT设备Service业务层处理
*
* @author shzg
* @date 2026-04-01
*/
@Service
public class MqttSensorDeviceServiceImpl implements IMqttSensorDeviceService
{
@Autowired
private MqttSensorDeviceMapper mqttSensorDeviceMapper;
@Autowired
private MqttDeviceCache deviceCache;
/**
* 查询MQTT设备
*
* @param id MQTT设备主键
* @return MQTT设备
*/
@Override
public MqttSensorDevice selectMqttSensorDeviceById(Long id)
{
return mqttSensorDeviceMapper.selectMqttSensorDeviceById(id);
}
/**
* 查询MQTT设备列表
*
* @param mqttSensorDevice MQTT设备
* @return MQTT设备
*/
@Override
public List<MqttSensorDevice> selectMqttSensorDeviceList(MqttSensorDevice mqttSensorDevice)
{
return mqttSensorDeviceMapper.selectMqttSensorDeviceList(mqttSensorDevice);
}
/**
* 新增MQTT设备
*
* @param mqttSensorDevice MQTT设备
* @return 结果
*/
@Override
public int insertMqttSensorDevice(MqttSensorDevice mqttSensorDevice)
{
mqttSensorDevice.setCreateTime(DateUtils.getNowDate());
int rows = mqttSensorDeviceMapper.insertMqttSensorDevice(mqttSensorDevice);
// 👉 刷新缓存
deviceCache.refresh();
return rows;
}
/**
* 修改MQTT设备
*
* @param mqttSensorDevice MQTT设备
* @return 结果
*/
@Override
public int updateMqttSensorDevice(MqttSensorDevice mqttSensorDevice)
{
mqttSensorDevice.setUpdateTime(DateUtils.getNowDate());
int rows = mqttSensorDeviceMapper.updateMqttSensorDevice(mqttSensorDevice);
// 👉 刷新缓存
deviceCache.refresh();
return rows;
}
/**
* 批量删除MQTT设备
*
* @param ids 需要删除的MQTT设备主键
* @return 结果
*/
@Override
public int deleteMqttSensorDeviceByIds(Long[] ids)
{
int rows = mqttSensorDeviceMapper.deleteMqttSensorDeviceByIds(ids);
// 👉 刷新缓存
deviceCache.refresh();
return rows;
}
/**
* 删除MQTT设备信息
*
* @param id MQTT设备主键
* @return 结果
*/
@Override
public int deleteMqttSensorDeviceById(Long id)
{
return mqttSensorDeviceMapper.deleteMqttSensorDeviceById(id);
}
/**
* 根据DevEui查询设备
* @param devEui
* @return
*/
@Override
public MqttSensorDevice selectByDevEui(String devEui) {
if (devEui == null || devEui.isEmpty()) {
return null;
}
return mqttSensorDeviceMapper.selectByDevEui(devEui.toLowerCase());
}
}

View File

@@ -0,0 +1,96 @@
package com.shzg.project.worn.service.impl;
import java.util.List;
import com.shzg.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shzg.project.worn.mapper.MqttSensorEventMapper;
import com.shzg.project.worn.domain.MqttSensorEvent;
import com.shzg.project.worn.service.IMqttSensorEventService;
/**
* 设备事件Service业务层处理
*
* @author shzg
* @date 2026-04-01
*/
@Service
public class MqttSensorEventServiceImpl implements IMqttSensorEventService
{
@Autowired
private MqttSensorEventMapper mqttSensorEventMapper;
/**
* 查询设备事件
*
* @param id 设备事件主键
* @return 设备事件
*/
@Override
public MqttSensorEvent selectMqttSensorEventById(Long id)
{
return mqttSensorEventMapper.selectMqttSensorEventById(id);
}
/**
* 查询设备事件列表
*
* @param mqttSensorEvent 设备事件
* @return 设备事件
*/
@Override
public List<MqttSensorEvent> selectMqttSensorEventList(MqttSensorEvent mqttSensorEvent)
{
return mqttSensorEventMapper.selectMqttSensorEventList(mqttSensorEvent);
}
/**
* 新增设备事件
*
* @param mqttSensorEvent 设备事件
* @return 结果
*/
@Override
public int insertMqttSensorEvent(MqttSensorEvent mqttSensorEvent)
{
mqttSensorEvent.setCreateTime(DateUtils.getNowDate());
return mqttSensorEventMapper.insertMqttSensorEvent(mqttSensorEvent);
}
/**
* 修改设备事件
*
* @param mqttSensorEvent 设备事件
* @return 结果
*/
@Override
public int updateMqttSensorEvent(MqttSensorEvent mqttSensorEvent)
{
mqttSensorEvent.setUpdateTime(DateUtils.getNowDate());
return mqttSensorEventMapper.updateMqttSensorEvent(mqttSensorEvent);
}
/**
* 批量删除设备事件
*
* @param ids 需要删除的设备事件主键
* @return 结果
*/
@Override
public int deleteMqttSensorEventByIds(Long[] ids)
{
return mqttSensorEventMapper.deleteMqttSensorEventByIds(ids);
}
/**
* 删除设备事件信息
*
* @param id 设备事件主键
* @return 结果
*/
@Override
public int deleteMqttSensorEventById(Long id)
{
return mqttSensorEventMapper.deleteMqttSensorEventById(id);
}
}

View File

@@ -0,0 +1,108 @@
package com.shzg.project.worn.service.impl;
import java.util.List;
import com.shzg.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.shzg.project.worn.mapper.MqttSensorThresholdMapper;
import com.shzg.project.worn.domain.MqttSensorThreshold;
import com.shzg.project.worn.service.IMqttSensorThresholdService;
/**
* 传感器阈值配置Service业务层处理
*
* @author shzg
* @date 2026-04-01
*/
@Service
public class MqttSensorThresholdServiceImpl implements IMqttSensorThresholdService
{
@Autowired
private MqttSensorThresholdMapper mqttSensorThresholdMapper;
/**
* 查询传感器阈值配置
*
* @param id 传感器阈值配置主键
* @return 传感器阈值配置
*/
@Override
public MqttSensorThreshold selectMqttSensorThresholdById(Long id)
{
return mqttSensorThresholdMapper.selectMqttSensorThresholdById(id);
}
/**
* 查询传感器阈值配置列表
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 传感器阈值配置
*/
@Override
public List<MqttSensorThreshold> selectMqttSensorThresholdList(MqttSensorThreshold mqttSensorThreshold)
{
return mqttSensorThresholdMapper.selectMqttSensorThresholdList(mqttSensorThreshold);
}
/**
* 新增传感器阈值配置
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 结果
*/
@Override
public int insertMqttSensorThreshold(MqttSensorThreshold mqttSensorThreshold)
{
mqttSensorThreshold.setCreateTime(DateUtils.getNowDate());
return mqttSensorThresholdMapper.insertMqttSensorThreshold(mqttSensorThreshold);
}
/**
* 修改传感器阈值配置
*
* @param mqttSensorThreshold 传感器阈值配置
* @return 结果
*/
@Override
public int updateMqttSensorThreshold(MqttSensorThreshold mqttSensorThreshold)
{
mqttSensorThreshold.setUpdateTime(DateUtils.getNowDate());
return mqttSensorThresholdMapper.updateMqttSensorThreshold(mqttSensorThreshold);
}
/**
* 批量删除传感器阈值配置
*
* @param ids 需要删除的传感器阈值配置主键
* @return 结果
*/
@Override
public int deleteMqttSensorThresholdByIds(Long[] ids)
{
return mqttSensorThresholdMapper.deleteMqttSensorThresholdByIds(ids);
}
/**
* 删除传感器阈值配置信息
*
* @param id 传感器阈值配置主键
* @return 结果
*/
@Override
public int deleteMqttSensorThresholdById(Long id)
{
return mqttSensorThresholdMapper.deleteMqttSensorThresholdById(id);
}
/**
* 根据设备id和指标类型获取阈值配置
* @param deviceId
* @param metricType
* @return
*/
@Override
public MqttSensorThreshold getThreshold(Long deviceId, String metricType)
{
return mqttSensorThresholdMapper.selectByDeviceAndMetric(deviceId, metricType);
}
}

View File

@@ -0,0 +1,68 @@
package com.shzg.project.worn.unit;
import com.shzg.project.worn.domain.MqttSensorDevice;
import com.shzg.project.worn.service.IMqttSensorDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
public class MqttDeviceCache {
@Autowired
private IMqttSensorDeviceService deviceService;
// 本地缓存
private final Map<String, MqttSensorDevice> cache = new ConcurrentHashMap<>();
/**
* 启动加载
*/
@PostConstruct
public void init() {
refresh();
}
/**
* 定时刷新10分钟
*/
@Scheduled(fixedDelay = 10 * 60 * 1000)
public void refresh() {
try {
List<MqttSensorDevice> list = deviceService.selectMqttSensorDeviceList(new MqttSensorDevice());
Map<String, MqttSensorDevice> newCache = new ConcurrentHashMap<>();
for (MqttSensorDevice device : list) {
if (device.getDevEui() != null) {
newCache.put(device.getDevEui().toLowerCase(), device);
}
}
cache.clear();
cache.putAll(newCache);
log.info("[MQTT] 设备缓存刷新完成,数量={}", cache.size());
} catch (Exception e) {
log.error("[MQTT] 设备缓存刷新失败", e);
}
}
/**
* 获取设备
*/
public MqttSensorDevice get(String devEui) {
if (devEui == null) {
return null;
}
return cache.get(devEui.toLowerCase());
}
}

View File

@@ -0,0 +1,22 @@
package com.shzg.project.worn.unit;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.*;
@Configuration
public class MqttThreadPoolConfig {
@Bean("mqttExecutor")
public Executor mqttExecutor() {
return new ThreadPoolExecutor(
10, // 核心线程
50, // 最大线程
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1000),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}

View File

@@ -69,13 +69,15 @@ spring:
# redis 配置
redis:
# 地址
# host: localhost
host: 192.168.1.251
host: localhost
# host: 192.168.1.251
# host: 47.100.212.83
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
# password: shzg
password:
# 连接超时时间
timeout: 10s
@@ -155,45 +157,25 @@ gen:
# =========================
mqtt:
# 是否启用 MQTT 功能
# true系统启动时自动连接 EMQX 并订阅 Topic
# false不初始化 MQTT 客户端
enabled: true
# MQTT Broker 地址
# tcp://IP:1883 —— MQTT TCP
# ws://IP:8083 —— MQTT WebSocket
# ssl://IP:8883 —— MQTT SSL
broker: tcp://47.100.212.83:1883
# MQTT 客户端 ID在 EMQX 中唯一)
# 建议:系统名 + 模块名,避免重复
clientId: zg-wms-wsj
# MQTT 账号EMQX Dashboard 中配置)
# MQTT 账号
username: test
# MQTT 密码
password: 123456
# 是否清除会话
# true :断开后清除订阅和未接收消息(推荐后端使用)
# false :保留会话(适合设备端)
cleanSession: true
# 心跳时间(秒)
# 客户端与 Broker 保持连接的心跳间隔
keepAlive: 30
# 连接超时时间(秒)
timeout: 10
# 默认消息 QoS
# 0最多一次不保证到达性能最好
# 1至少一次推荐业务数据常用
# 2仅一次最严格性能最差
qos: 1
# 订阅的 Topic 列表(支持通配符)
# 建议先使用测试 Topic确认链路正常后再接入真实业务 Topic
topics:
- zg/wms/test/#
# 默认 QoS
qos: 1

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shzg.project.worn.mapper.MqttSensorCommandMapper">
<resultMap type="MqttSensorCommand" id="MqttSensorCommandResult">
<result property="id" column="id" />
<result property="deviceId" column="device_id" />
<result property="topic" column="topic" />
<result property="command" column="command" />
<result property="payload" column="payload" />
<result property="status" column="status" />
<result property="sendTime" column="send_time" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
</resultMap>
<sql id="selectMqttSensorCommandVo">
select id, device_id, topic, command, payload, status, send_time, remark, create_by, create_time, update_by, update_time, is_delete from mqtt_sensor_command
</sql>
<select id="selectMqttSensorCommandList" parameterType="MqttSensorCommand" resultMap="MqttSensorCommandResult">
<include refid="selectMqttSensorCommandVo"/>
<where>
<if test="deviceId != null "> and device_id = #{deviceId}</if>
<if test="topic != null and topic != ''"> and topic = #{topic}</if>
<if test="command != null and command != ''"> and command = #{command}</if>
<if test="payload != null and payload != ''"> and payload = #{payload}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="sendTime != null "> and send_time = #{sendTime}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectMqttSensorCommandById" parameterType="Long" resultMap="MqttSensorCommandResult">
<include refid="selectMqttSensorCommandVo"/>
where id = #{id}
</select>
<insert id="insertMqttSensorCommand" parameterType="MqttSensorCommand" useGeneratedKeys="true" keyProperty="id">
insert into mqtt_sensor_command
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null">device_id,</if>
<if test="topic != null">topic,</if>
<if test="command != null">command,</if>
<if test="payload != null">payload,</if>
<if test="status != null">status,</if>
<if test="sendTime != null">send_time,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null">#{deviceId},</if>
<if test="topic != null">#{topic},</if>
<if test="command != null">#{command},</if>
<if test="payload != null">#{payload},</if>
<if test="status != null">#{status},</if>
<if test="sendTime != null">#{sendTime},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateMqttSensorCommand" parameterType="MqttSensorCommand">
update mqtt_sensor_command
<trim prefix="SET" suffixOverrides=",">
<if test="deviceId != null">device_id = #{deviceId},</if>
<if test="topic != null">topic = #{topic},</if>
<if test="command != null">command = #{command},</if>
<if test="payload != null">payload = #{payload},</if>
<if test="status != null">status = #{status},</if>
<if test="sendTime != null">send_time = #{sendTime},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteMqttSensorCommandById" parameterType="Long">
delete from mqtt_sensor_command where id = #{id}
</delete>
<delete id="deleteMqttSensorCommandByIds" parameterType="String">
delete from mqtt_sensor_command where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shzg.project.worn.mapper.MqttSensorDataMapper">
<resultMap type="MqttSensorData" id="MqttSensorDataResult">
<result property="id" column="id"/>
<result property="deviceId" column="device_id"/>
<result property="topic" column="topic"/>
<result property="project" column="project"/>
<result property="warehouse" column="warehouse"/>
<result property="payload" column="payload"/>
<result property="dataJson" column="data_json"/>
<result property="battery" column="battery"/>
<result property="temperature" column="temperature"/>
<result property="humidity" column="humidity"/>
<result property="nh3" column="nh3"/>
<result property="h2s" column="h2s"/>
<result property="concentration" column="concentration"/>
<result property="waterStatus" column="water_status"/>
<result property="remark" column="remark"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="isDelete" column="is_delete"/>
</resultMap>
<sql id="selectMqttSensorDataVo">
select
id, device_id, topic, project, warehouse, payload, data_json,
battery, temperature, humidity, nh3, h2s, concentration,
water_status,
remark, create_by, create_time, update_by, update_time, is_delete
from mqtt_sensor_data
</sql>
<select id="selectMqttSensorDataList" parameterType="MqttSensorData" resultMap="MqttSensorDataResult">
<include refid="selectMqttSensorDataVo"/>
<where>
<if test="deviceId != null "> and device_id = #{deviceId}</if>
<if test="topic != null and topic != ''"> and topic = #{topic}</if>
<if test="project != null and project != ''"> and project = #{project}</if>
<if test="warehouse != null and warehouse != ''"> and warehouse = #{warehouse}</if>
<if test="payload != null and payload != ''"> and payload = #{payload}</if>
<if test="dataJson != null and dataJson != ''"> and data_json = #{dataJson}</if>
<if test="battery != null "> and battery = #{battery}</if>
<if test="temperature != null "> and temperature = #{temperature}</if>
<if test="humidity != null "> and humidity = #{humidity}</if>
<if test="nh3 != null "> and nh3 = #{nh3}</if>
<if test="h2s != null "> and h2s = #{h2s}</if>
<if test="concentration != null "> and concentration = #{concentration}</if>
<if test="waterStatus != null "> and water_status = #{waterStatus}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectMqttSensorDataById" parameterType="Long" resultMap="MqttSensorDataResult">
<include refid="selectMqttSensorDataVo"/>
where id = #{id}
</select>
<insert id="insertMqttSensorData" parameterType="MqttSensorData" useGeneratedKeys="true" keyProperty="id">
insert into mqtt_sensor_data
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null">device_id,</if>
<if test="topic != null">topic,</if>
<if test="project != null">project,</if>
<if test="warehouse != null">warehouse,</if>
<if test="payload != null">payload,</if>
<if test="dataJson != null">data_json,</if>
<if test="battery != null">battery,</if>
<if test="temperature != null">temperature,</if>
<if test="humidity != null">humidity,</if>
<if test="nh3 != null">nh3,</if>
<if test="h2s != null">h2s,</if>
<if test="concentration != null">concentration,</if>
<if test="waterStatus != null">water_status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null">#{deviceId},</if>
<if test="topic != null">#{topic},</if>
<if test="project != null">#{project},</if>
<if test="warehouse != null">#{warehouse},</if>
<if test="payload != null">#{payload},</if>
<if test="dataJson != null">#{dataJson},</if>
<if test="battery != null">#{battery},</if>
<if test="temperature != null">#{temperature},</if>
<if test="humidity != null">#{humidity},</if>
<if test="nh3 != null">#{nh3},</if>
<if test="h2s != null">#{h2s},</if>
<if test="concentration != null">#{concentration},</if>
<if test="waterStatus != null">#{waterStatus},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateMqttSensorData" parameterType="MqttSensorData">
update mqtt_sensor_data
<trim prefix="SET" suffixOverrides=",">
<if test="deviceId != null">device_id = #{deviceId},</if>
<if test="topic != null">topic = #{topic},</if>
<if test="project != null">project = #{project},</if>
<if test="warehouse != null">warehouse = #{warehouse},</if>
<if test="payload != null">payload = #{payload},</if>
<if test="dataJson != null">data_json = #{dataJson},</if>
<if test="battery != null">battery = #{battery},</if>
<if test="temperature != null">temperature = #{temperature},</if>
<if test="humidity != null">humidity = #{humidity},</if>
<if test="nh3 != null">nh3 = #{nh3},</if>
<if test="h2s != null">h2s = #{h2s},</if>
<if test="concentration != null">concentration = #{concentration},</if>
<!-- ✅ 新增 -->
<if test="waterStatus != null">water_status = #{waterStatus},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteMqttSensorDataById" parameterType="Long">
delete from mqtt_sensor_data where id = #{id}
</delete>
<delete id="deleteMqttSensorDataByIds" parameterType="String">
delete from mqtt_sensor_data where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shzg.project.worn.mapper.MqttSensorDeviceMapper">
<resultMap type="MqttSensorDevice" id="MqttSensorDeviceResult">
<result property="id" column="id" />
<result property="devEui" column="dev_eui" />
<result property="deviceName" column="device_name" />
<result property="deviceType" column="device_type" />
<result property="deptId" column="dept_id" />
<result property="status" column="status" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
</resultMap>
<sql id="selectMqttSensorDeviceVo">
select id, dev_eui, device_name, device_type, dept_id, status, remark, create_by, create_time, update_by, update_time, is_delete from mqtt_sensor_device
</sql>
<select id="selectMqttSensorDeviceList" parameterType="MqttSensorDevice" resultMap="MqttSensorDeviceResult">
<include refid="selectMqttSensorDeviceVo"/>
<where>
<if test="devEui != null and devEui != ''"> and dev_eui = #{devEui}</if>
<if test="deviceName != null and deviceName != ''"> and device_name like concat('%', #{deviceName}, '%')</if>
<if test="deviceType != null and deviceType != ''"> and device_type = #{deviceType}</if>
<if test="deptId != null "> and dept_id = #{deptId}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectMqttSensorDeviceById" parameterType="Long" resultMap="MqttSensorDeviceResult">
<include refid="selectMqttSensorDeviceVo"/>
where id = #{id}
</select>
<insert id="insertMqttSensorDevice" parameterType="MqttSensorDevice" useGeneratedKeys="true" keyProperty="id">
insert into mqtt_sensor_device
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="devEui != null and devEui != ''">dev_eui,</if>
<if test="deviceName != null">device_name,</if>
<if test="deviceType != null">device_type,</if>
<if test="deptId != null">dept_id,</if>
<if test="status != null">status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="devEui != null and devEui != ''">#{devEui},</if>
<if test="deviceName != null">#{deviceName},</if>
<if test="deviceType != null">#{deviceType},</if>
<if test="deptId != null">#{deptId},</if>
<if test="status != null">#{status},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateMqttSensorDevice" parameterType="MqttSensorDevice">
update mqtt_sensor_device
<trim prefix="SET" suffixOverrides=",">
<if test="devEui != null and devEui != ''">dev_eui = #{devEui},</if>
<if test="deviceName != null">device_name = #{deviceName},</if>
<if test="deviceType != null">device_type = #{deviceType},</if>
<if test="deptId != null">dept_id = #{deptId},</if>
<if test="status != null">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteMqttSensorDeviceById" parameterType="Long">
delete from mqtt_sensor_device where id = #{id}
</delete>
<delete id="deleteMqttSensorDeviceByIds" parameterType="String">
delete from mqtt_sensor_device where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="selectByDevEui" parameterType="String" resultMap="MqttSensorDeviceResult">
<include refid="selectMqttSensorDeviceVo"/>
WHERE dev_eui = #{devEui}
AND is_delete = '0'
LIMIT 1
</select>
</mapper>

View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shzg.project.worn.mapper.MqttSensorEventMapper">
<resultMap type="MqttSensorEvent" id="MqttSensorEventResult">
<result property="id" column="id" />
<result property="deviceId" column="device_id" />
<result property="eventType" column="event_type" />
<result property="eventDesc" column="event_desc" />
<result property="level" column="level" />
<result property="status" column="status" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
</resultMap>
<sql id="selectMqttSensorEventVo">
select id, device_id, event_type, event_desc, level, status, remark, create_by, create_time, update_by, update_time, is_delete from mqtt_sensor_event
</sql>
<select id="selectMqttSensorEventList" parameterType="MqttSensorEvent" resultMap="MqttSensorEventResult">
<include refid="selectMqttSensorEventVo"/>
<where>
<if test="deviceId != null "> and device_id = #{deviceId}</if>
<if test="eventType != null and eventType != ''"> and event_type = #{eventType}</if>
<if test="eventDesc != null and eventDesc != ''"> and event_desc = #{eventDesc}</if>
<if test="level != null and level != ''"> and level = #{level}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectMqttSensorEventById" parameterType="Long" resultMap="MqttSensorEventResult">
<include refid="selectMqttSensorEventVo"/>
where id = #{id}
</select>
<insert id="insertMqttSensorEvent" parameterType="MqttSensorEvent" useGeneratedKeys="true" keyProperty="id">
insert into mqtt_sensor_event
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null">device_id,</if>
<if test="eventType != null and eventType != ''">event_type,</if>
<if test="eventDesc != null">event_desc,</if>
<if test="level != null">level,</if>
<if test="status != null">status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null">#{deviceId},</if>
<if test="eventType != null and eventType != ''">#{eventType},</if>
<if test="eventDesc != null">#{eventDesc},</if>
<if test="level != null">#{level},</if>
<if test="status != null">#{status},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateMqttSensorEvent" parameterType="MqttSensorEvent">
update mqtt_sensor_event
<trim prefix="SET" suffixOverrides=",">
<if test="deviceId != null">device_id = #{deviceId},</if>
<if test="eventType != null and eventType != ''">event_type = #{eventType},</if>
<if test="eventDesc != null">event_desc = #{eventDesc},</if>
<if test="level != null">level = #{level},</if>
<if test="status != null">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteMqttSensorEventById" parameterType="Long">
delete from mqtt_sensor_event where id = #{id}
</delete>
<delete id="deleteMqttSensorEventByIds" parameterType="String">
delete from mqtt_sensor_event where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shzg.project.worn.mapper.MqttSensorThresholdMapper">
<resultMap type="MqttSensorThreshold" id="MqttSensorThresholdResult">
<result property="id" column="id" />
<result property="deviceId" column="device_id" />
<result property="metricType" column="metric_type" />
<result property="warnMin" column="warn_min" />
<result property="warnMax" column="warn_max" />
<result property="alarmMin" column="alarm_min" />
<result property="alarmMax" column="alarm_max" />
<result property="unit" column="unit" />
<result property="status" column="status" />
<result property="remark" column="remark" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="isDelete" column="is_delete" />
</resultMap>
<sql id="selectMqttSensorThresholdVo">
select id, device_id, metric_type, warn_min, warn_max, alarm_min, alarm_max, unit, status, remark, create_by, create_time, update_by, update_time, is_delete from mqtt_sensor_threshold
</sql>
<select id="selectMqttSensorThresholdList" parameterType="MqttSensorThreshold" resultMap="MqttSensorThresholdResult">
<include refid="selectMqttSensorThresholdVo"/>
<where>
<if test="deviceId != null "> and device_id = #{deviceId}</if>
<if test="metricType != null and metricType != ''"> and metric_type = #{metricType}</if>
<if test="warnMin != null "> and warn_min = #{warnMin}</if>
<if test="warnMax != null "> and warn_max = #{warnMax}</if>
<if test="alarmMin != null "> and alarm_min = #{alarmMin}</if>
<if test="alarmMax != null "> and alarm_max = #{alarmMax}</if>
<if test="unit != null and unit != ''"> and unit = #{unit}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
</where>
</select>
<select id="selectMqttSensorThresholdById" parameterType="Long" resultMap="MqttSensorThresholdResult">
<include refid="selectMqttSensorThresholdVo"/>
where id = #{id}
</select>
<insert id="insertMqttSensorThreshold" parameterType="MqttSensorThreshold" useGeneratedKeys="true" keyProperty="id">
insert into mqtt_sensor_threshold
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="deviceId != null">device_id,</if>
<if test="metricType != null and metricType != ''">metric_type,</if>
<if test="warnMin != null">warn_min,</if>
<if test="warnMax != null">warn_max,</if>
<if test="alarmMin != null">alarm_min,</if>
<if test="alarmMax != null">alarm_max,</if>
<if test="unit != null">unit,</if>
<if test="status != null">status,</if>
<if test="remark != null">remark,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="isDelete != null">is_delete,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="deviceId != null">#{deviceId},</if>
<if test="metricType != null and metricType != ''">#{metricType},</if>
<if test="warnMin != null">#{warnMin},</if>
<if test="warnMax != null">#{warnMax},</if>
<if test="alarmMin != null">#{alarmMin},</if>
<if test="alarmMax != null">#{alarmMax},</if>
<if test="unit != null">#{unit},</if>
<if test="status != null">#{status},</if>
<if test="remark != null">#{remark},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="isDelete != null">#{isDelete},</if>
</trim>
</insert>
<update id="updateMqttSensorThreshold" parameterType="MqttSensorThreshold">
update mqtt_sensor_threshold
<trim prefix="SET" suffixOverrides=",">
<if test="deviceId != null">device_id = #{deviceId},</if>
<if test="metricType != null and metricType != ''">metric_type = #{metricType},</if>
<if test="warnMin != null">warn_min = #{warnMin},</if>
<if test="warnMax != null">warn_max = #{warnMax},</if>
<if test="alarmMin != null">alarm_min = #{alarmMin},</if>
<if test="alarmMax != null">alarm_max = #{alarmMax},</if>
<if test="unit != null">unit = #{unit},</if>
<if test="status != null">status = #{status},</if>
<if test="remark != null">remark = #{remark},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="isDelete != null">is_delete = #{isDelete},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteMqttSensorThresholdById" parameterType="Long">
delete from mqtt_sensor_threshold where id = #{id}
</delete>
<delete id="deleteMqttSensorThresholdByIds" parameterType="String">
delete from mqtt_sensor_threshold where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="selectByDeviceAndMetric" resultMap="MqttSensorThresholdResult">
select *
from mqtt_sensor_threshold
where device_id = #{deviceId}
and metric_type = #{metricType}
and status = '1'
and is_delete = '0'
limit 1
</select>
</mapper>