更新mqtt支持

This commit is contained in:
zy 2025-12-19 19:20:30 +08:00
parent c7e837c0e7
commit 3ec596d8ef
75 changed files with 4703 additions and 19 deletions

View File

@ -68,6 +68,15 @@
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId> <artifactId>spring-security-crypto</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.52.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,143 @@
package org.jeecg.modules.appmana.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.entity.FIotVirtualDeviceGroup;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceGroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 虚拟设备模块分组
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
@Api(tags="99. 虚拟设备模块分组 id")
@RestController
@RequestMapping("/api/iot/fIotVirtualDeviceGroup")
@Slf4j
public class FIotVirtualDeviceGroupController extends JeecgController<FIotVirtualDeviceGroup, IFIotVirtualDeviceGroupService> {
@Autowired
private IFIotVirtualDeviceGroupService fIotVirtualDeviceGroupService;
//@AutoLog(value = "虚拟设备模块分组-分页列表查询")
@ApiOperation(value="01. 分页查询", notes="")
@ApiOperationSupport(order = 1)
@GetMapping(value = "/list")
public Result<IPage<FIotVirtualDeviceGroup>> queryPageList(FIotVirtualDeviceGroup fIotVirtualDeviceGroup,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<FIotVirtualDeviceGroup> queryWrapper = QueryGenerator.initQueryWrapper(fIotVirtualDeviceGroup, req.getParameterMap());
Page<FIotVirtualDeviceGroup> page = new Page<FIotVirtualDeviceGroup>(pageNo, pageSize);
IPage<FIotVirtualDeviceGroup> pageList = fIotVirtualDeviceGroupService.page(page, queryWrapper);
return Result.OK(pageList);
}
@AutoLog(value = "虚拟设备模块分组-添加")
@ApiOperationSupport(order = 2)
@ApiOperation(value="02. 添加", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_group:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody FIotVirtualDeviceGroup fIotVirtualDeviceGroup, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDeviceGroup.setCreateBy(username);
fIotVirtualDeviceGroup.setCreateTime(new Date());
fIotVirtualDeviceGroupService.save(fIotVirtualDeviceGroup);
return Result.OK("添加成功!");
}
@AutoLog(value = "虚拟设备模块分组-编辑")
@ApiOperationSupport(order = 3)
@ApiOperation(value="03. 编辑", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_group:edit")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody FIotVirtualDeviceGroup fIotVirtualDeviceGroup, HttpServletRequest request) {
//创建更新时间不能编辑
fIotVirtualDeviceGroup.setCreateTime(null);
fIotVirtualDeviceGroup.setUpdateTime(null);
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDeviceGroup.setUpdateBy(username);
fIotVirtualDeviceGroupService.updateById(fIotVirtualDeviceGroup);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "虚拟设备模块分组-通过id删除")
@ApiOperation(value="04.通过id删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_group:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
fIotVirtualDeviceGroupService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "虚拟设备模块分组-批量删除")
@ApiOperationSupport(order = 4)
@ApiOperation(value="04. 批量删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_group:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.fIotVirtualDeviceGroupService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
//@AutoLog(value = "虚拟设备模块分组-通过id查询")
@ApiOperationSupport(order = 5)
@ApiOperation(value="05. 通过id查询", notes="")
@GetMapping(value = "/queryById")
public Result<FIotVirtualDeviceGroup> queryById(@RequestParam(name="id",required=true) String id) {
FIotVirtualDeviceGroup fIotVirtualDeviceGroup = fIotVirtualDeviceGroupService.getById(id);
if(fIotVirtualDeviceGroup==null) {
return Result.error("未找到对应数据");
}
return Result.OK(fIotVirtualDeviceGroup);
}
@ApiOperationSupport(order = 6)
@ApiOperation(value="06. 导出excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_group:exportXls")
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, FIotVirtualDeviceGroup fIotVirtualDeviceGroup) {
return super.exportXls(request, fIotVirtualDeviceGroup, FIotVirtualDeviceGroup.class, "虚拟设备模块分组");
}
@ApiOperationSupport(order = 7)
@ApiOperation(value="07. 导入excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_group:importExcel")
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, FIotVirtualDeviceGroup.class);
}
}

View File

@ -0,0 +1,143 @@
package org.jeecg.modules.appmana.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.entity.FIotVirtualDeviceModule;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceModuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 虚拟设备模组表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
@Api(tags="99. 虚拟设备模组表 id")
@RestController
@RequestMapping("/api/iot/fIotVirtualDeviceModule")
@Slf4j
public class FIotVirtualDeviceModuleController extends JeecgController<FIotVirtualDeviceModule, IFIotVirtualDeviceModuleService> {
@Autowired
private IFIotVirtualDeviceModuleService fIotVirtualDeviceModuleService;
//@AutoLog(value = "虚拟设备模组表-分页列表查询")
@ApiOperation(value="01. 分页查询", notes="")
@ApiOperationSupport(order = 1)
@GetMapping(value = "/list")
public Result<IPage<FIotVirtualDeviceModule>> queryPageList(FIotVirtualDeviceModule fIotVirtualDeviceModule,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<FIotVirtualDeviceModule> queryWrapper = QueryGenerator.initQueryWrapper(fIotVirtualDeviceModule, req.getParameterMap());
Page<FIotVirtualDeviceModule> page = new Page<FIotVirtualDeviceModule>(pageNo, pageSize);
IPage<FIotVirtualDeviceModule> pageList = fIotVirtualDeviceModuleService.page(page, queryWrapper);
return Result.OK(pageList);
}
@AutoLog(value = "虚拟设备模组表-添加")
@ApiOperationSupport(order = 2)
@ApiOperation(value="02. 添加", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_module:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody FIotVirtualDeviceModule fIotVirtualDeviceModule, HttpServletRequest request) {
String username =JwtUtil.getUserNameByToken(request);
fIotVirtualDeviceModule.setCreateBy(username);
fIotVirtualDeviceModule.setCreateTime(new Date());
fIotVirtualDeviceModuleService.save(fIotVirtualDeviceModule);
return Result.OK("添加成功!");
}
@AutoLog(value = "虚拟设备模组表-编辑")
@ApiOperationSupport(order = 3)
@ApiOperation(value="03. 编辑", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_module:edit")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody FIotVirtualDeviceModule fIotVirtualDeviceModule, HttpServletRequest request) {
//创建更新时间不能编辑
fIotVirtualDeviceModule.setCreateTime(null);
fIotVirtualDeviceModule.setUpdateTime(null);
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDeviceModule.setUpdateBy(username);
fIotVirtualDeviceModuleService.updateById(fIotVirtualDeviceModule);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "虚拟设备模组表-通过id删除")
@ApiOperation(value="04.通过id删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_module:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
fIotVirtualDeviceModuleService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "虚拟设备模组表-批量删除")
@ApiOperationSupport(order = 4)
@ApiOperation(value="04. 批量删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_module:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.fIotVirtualDeviceModuleService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
//@AutoLog(value = "虚拟设备模组表-通过id查询")
@ApiOperationSupport(order = 5)
@ApiOperation(value="05. 通过id查询", notes="")
@GetMapping(value = "/queryById")
public Result<FIotVirtualDeviceModule> queryById(@RequestParam(name="id",required=true) String id) {
FIotVirtualDeviceModule fIotVirtualDeviceModule = fIotVirtualDeviceModuleService.getById(id);
if(fIotVirtualDeviceModule==null) {
return Result.error("未找到对应数据");
}
return Result.OK(fIotVirtualDeviceModule);
}
@ApiOperationSupport(order = 6)
@ApiOperation(value="06. 导出excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_module:exportXls")
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, FIotVirtualDeviceModule fIotVirtualDeviceModule) {
return super.exportXls(request, fIotVirtualDeviceModule, FIotVirtualDeviceModule.class, "虚拟设备模组表");
}
@ApiOperationSupport(order = 7)
@ApiOperation(value="07. 导入excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_module:importExcel")
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, FIotVirtualDeviceModule.class);
}
}

View File

@ -0,0 +1,143 @@
package org.jeecg.modules.appmana.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.entity.FIotVirtualDeviceNet;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceNetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 虚拟设备网络模块
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
@Api(tags="99. 虚拟设备网络模块 id")
@RestController
@RequestMapping("/api/iot/fIotVirtualDeviceNet")
@Slf4j
public class FIotVirtualDeviceNetController extends JeecgController<FIotVirtualDeviceNet, IFIotVirtualDeviceNetService> {
@Autowired
private IFIotVirtualDeviceNetService fIotVirtualDeviceNetService;
//@AutoLog(value = "虚拟设备网络模块-分页列表查询")
@ApiOperation(value="01. 分页查询", notes="")
@ApiOperationSupport(order = 1)
@GetMapping(value = "/list")
public Result<IPage<FIotVirtualDeviceNet>> queryPageList(FIotVirtualDeviceNet fIotVirtualDeviceNet,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<FIotVirtualDeviceNet> queryWrapper = QueryGenerator.initQueryWrapper(fIotVirtualDeviceNet, req.getParameterMap());
Page<FIotVirtualDeviceNet> page = new Page<FIotVirtualDeviceNet>(pageNo, pageSize);
IPage<FIotVirtualDeviceNet> pageList = fIotVirtualDeviceNetService.page(page, queryWrapper);
return Result.OK(pageList);
}
@AutoLog(value = "虚拟设备网络模块-添加")
@ApiOperationSupport(order = 2)
@ApiOperation(value="02. 添加", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_net:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody FIotVirtualDeviceNet fIotVirtualDeviceNet, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDeviceNet.setCreateBy(username);
fIotVirtualDeviceNet.setCreateTime(new Date());
fIotVirtualDeviceNetService.save(fIotVirtualDeviceNet);
return Result.OK("添加成功!");
}
@AutoLog(value = "虚拟设备网络模块-编辑")
@ApiOperationSupport(order = 3)
@ApiOperation(value="03. 编辑", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_net:edit")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody FIotVirtualDeviceNet fIotVirtualDeviceNet, HttpServletRequest request) {
//创建更新时间不能编辑
fIotVirtualDeviceNet.setCreateTime(null);
fIotVirtualDeviceNet.setUpdateTime(null);
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDeviceNet.setUpdateBy(username);
fIotVirtualDeviceNetService.updateById(fIotVirtualDeviceNet);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "虚拟设备网络模块-通过id删除")
@ApiOperation(value="04.通过id删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_net:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
fIotVirtualDeviceNetService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "虚拟设备网络模块-批量删除")
@ApiOperationSupport(order = 4)
@ApiOperation(value="04. 批量删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_net:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.fIotVirtualDeviceNetService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
//@AutoLog(value = "虚拟设备网络模块-通过id查询")
@ApiOperationSupport(order = 5)
@ApiOperation(value="05. 通过id查询", notes="")
@GetMapping(value = "/queryById")
public Result<FIotVirtualDeviceNet> queryById(@RequestParam(name="id",required=true) String id) {
FIotVirtualDeviceNet fIotVirtualDeviceNet = fIotVirtualDeviceNetService.getById(id);
if(fIotVirtualDeviceNet==null) {
return Result.error("未找到对应数据");
}
return Result.OK(fIotVirtualDeviceNet);
}
@ApiOperationSupport(order = 6)
@ApiOperation(value="06. 导出excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_net:exportXls")
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, FIotVirtualDeviceNet fIotVirtualDeviceNet) {
return super.exportXls(request, fIotVirtualDeviceNet, FIotVirtualDeviceNet.class, "虚拟设备网络模块");
}
@ApiOperationSupport(order = 7)
@ApiOperation(value="07. 导入excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device_net:importExcel")
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, FIotVirtualDeviceNet.class);
}
}

View File

@ -268,6 +268,8 @@ public class SurvDeviceDeployController extends JeecgController<SurvDeviceDeploy
cmds = relay.getRegisterCmdStop(); cmds = relay.getRegisterCmdStop();
} }
deviceDeploy.setSendInfo(cmds); deviceDeploy.setSendInfo(cmds);
//todo 调整为直接发送控制指令至mqtt
deviceDeployService.updateById(deviceDeploy); deviceDeployService.updateById(deviceDeploy);
try { try {

View File

@ -0,0 +1,144 @@
package org.jeecg.modules.appmana.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.entity.FDeviceOpration;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.modules.appmana.service.IFDeviceOprationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 设备操作记录
* @Author: jeecg-boot
* @Date: 2023-11-04
* @Version: V1.0
*/
@Api(tags = "99. 设备操作记录 id")
@RestController
@RequestMapping("/api/farm/fDeviceOpration")
@Slf4j
public class SurvDeviceOprationController extends JeecgController<FDeviceOpration, IFDeviceOprationService> {
@Autowired
private IFDeviceOprationService fDeviceOprationService;
//@AutoLog(value = "设备操作记录-分页列表查询")
@ApiOperation(value = "01. 分页查询", notes = "")
@ApiOperationSupport(order = 1)
@GetMapping(value = "/list")
public Result<IPage<FDeviceOpration>> queryPageList(FDeviceOpration fDeviceOpration,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<FDeviceOpration> queryWrapper = QueryGenerator.initQueryWrapper(fDeviceOpration, req.getParameterMap());
DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
if (StringUtils.isNotBlank(fDeviceOpration.getAlertTimes())) {
String[] tims = fDeviceOpration.getAlertTimes().split(",");
LocalDateTime bTime = LocalDateTime.of(LocalDate.parse(tims[0], sdf), LocalTime.MIN);
LocalDateTime eTime = LocalDateTime.of(LocalDate.parse(tims[1], sdf), LocalTime.MAX).withNano(999999000);
queryWrapper.gt("OPERATOR_TIME", bTime);
queryWrapper.lt("OPERATOR_TIME", eTime);
}
// if(fDeviceOpration.getEndTime()!=null){
// LocalDateTime eTime =LocalDateTime.of(fDeviceOpration.getEndTime(),LocalTime.MAX).withNano(999999000);
// queryWrapper.lt("OPERATOR_TIME", eTime);
// }
Page<FDeviceOpration> page = new Page<FDeviceOpration>(pageNo, pageSize);
IPage<FDeviceOpration> pageList = fDeviceOprationService.page(page, queryWrapper);
return Result.OK(pageList);
}
@AutoLog(value = "设备操作记录-添加")
@ApiOperationSupport(order = 2)
@ApiOperation(value = "02. 添加", notes = "")
@RequiresPermissions("farm:f_device_opration:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody FDeviceOpration fDeviceOpration, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
fDeviceOpration.setCreateBy(username);
fDeviceOpration.setCreateTime(new Date());
fDeviceOprationService.save(fDeviceOpration);
return Result.OK("添加成功!");
}
@AutoLog(value = "设备操作记录-编辑")
@ApiOperationSupport(order = 3)
@ApiOperation(value = "03. 编辑", notes = "")
@RequiresPermissions("farm:f_device_opration:edit")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody FDeviceOpration fDeviceOpration, HttpServletRequest request) {
//创建更新时间不能编辑
fDeviceOpration.setCreateTime(null);
fDeviceOpration.setUpdateTime(null);
String username = JwtUtil.getUserNameByToken(request);
fDeviceOpration.setUpdateBy(username);
fDeviceOprationService.updateById(fDeviceOpration);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "设备操作记录-通过id删除")
@ApiOperation(value = "04.通过id删除", notes = "")
@RequiresPermissions("farm:f_device_opration:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
fDeviceOprationService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "设备操作记录-批量删除")
@ApiOperationSupport(order = 4)
@ApiOperation(value = "04. 批量删除", notes = "")
@RequiresPermissions("farm:f_device_opration:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.fDeviceOprationService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
//@AutoLog(value = "设备操作记录-通过id查询")
@ApiOperationSupport(order = 5)
@ApiOperation(value = "05. 通过id查询", notes = "")
@GetMapping(value = "/queryById")
public Result<FDeviceOpration> queryById(@RequestParam(name = "id", required = true) String id) {
FDeviceOpration fDeviceOpration = fDeviceOprationService.getById(id);
if (fDeviceOpration == null) {
return Result.error("未找到对应数据");
}
return Result.OK(fDeviceOpration);
}
}

View File

@ -0,0 +1,143 @@
package org.jeecg.modules.appmana.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.entity.FIotProtocol;
import org.jeecg.modules.appmana.service.IFIotProtocolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 物联网设备协议表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
@Api(tags="99. 物联网设备协议表 id")
@RestController
@RequestMapping("/api/iot/fIotProtocol")
@Slf4j
public class SurvIotProtocolController extends JeecgController<FIotProtocol, IFIotProtocolService> {
@Autowired
private IFIotProtocolService fIotProtocolService;
//@AutoLog(value = "物联网设备协议表-分页列表查询")
@ApiOperation(value="01. 分页查询", notes="")
@ApiOperationSupport(order = 1)
@GetMapping(value = "/list")
public Result<IPage<FIotProtocol>> queryPageList(FIotProtocol fIotProtocol,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<FIotProtocol> queryWrapper = QueryGenerator.initQueryWrapper(fIotProtocol, req.getParameterMap());
Page<FIotProtocol> page = new Page<FIotProtocol>(pageNo, pageSize);
IPage<FIotProtocol> pageList = fIotProtocolService.page(page, queryWrapper);
return Result.OK(pageList);
}
@AutoLog(value = "物联网设备协议表-添加")
@ApiOperationSupport(order = 2)
@ApiOperation(value="02. 添加", notes="")
@RequiresPermissions("iot:f_iot_protocol:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody FIotProtocol fIotProtocol, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
fIotProtocol.setCreateBy(username);
fIotProtocol.setCreateTime(new Date());
fIotProtocolService.save(fIotProtocol);
return Result.OK("添加成功!");
}
@AutoLog(value = "物联网设备协议表-编辑")
@ApiOperationSupport(order = 3)
@ApiOperation(value="03. 编辑", notes="")
@RequiresPermissions("iot:f_iot_protocol:edit")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody FIotProtocol fIotProtocol, HttpServletRequest request) {
//创建更新时间不能编辑
fIotProtocol.setCreateTime(null);
fIotProtocol.setUpdateTime(null);
String username = JwtUtil.getUserNameByToken(request);
fIotProtocol.setUpdateBy(username);
fIotProtocolService.updateById(fIotProtocol);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "物联网设备协议表-通过id删除")
@ApiOperation(value="04.通过id删除", notes="")
@RequiresPermissions("iot:f_iot_protocol:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
fIotProtocolService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "物联网设备协议表-批量删除")
@ApiOperationSupport(order = 4)
@ApiOperation(value="04. 批量删除", notes="")
@RequiresPermissions("iot:f_iot_protocol:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.fIotProtocolService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
//@AutoLog(value = "物联网设备协议表-通过id查询")
@ApiOperationSupport(order = 5)
@ApiOperation(value="05. 通过id查询", notes="")
@GetMapping(value = "/queryById")
public Result<FIotProtocol> queryById(@RequestParam(name="id",required=true) String id) {
FIotProtocol fIotProtocol = fIotProtocolService.getById(id);
if(fIotProtocol==null) {
return Result.error("未找到对应数据");
}
return Result.OK(fIotProtocol);
}
@ApiOperationSupport(order = 6)
@ApiOperation(value="06. 导出excel", notes="")
@RequiresPermissions("iot:f_iot_protocol:exportXls")
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, FIotProtocol fIotProtocol) {
return super.exportXls(request, fIotProtocol, FIotProtocol.class, "物联网设备协议表");
}
@ApiOperationSupport(order = 7)
@ApiOperation(value="07. 导入excel", notes="")
@RequiresPermissions("iot:f_iot_protocol:importExcel")
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, FIotProtocol.class);
}
}

View File

@ -0,0 +1,143 @@
package org.jeecg.modules.appmana.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.entity.FIotVirtualDevice;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 虚拟设备表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
@Api(tags="99. 虚拟设备表 id")
@RestController
@RequestMapping("/api/iot/fIotVirtualDevice")
@Slf4j
public class SurvIotVirtualDeviceController extends JeecgController<FIotVirtualDevice, IFIotVirtualDeviceService> {
@Autowired
private IFIotVirtualDeviceService fIotVirtualDeviceService;
//@AutoLog(value = "虚拟设备表-分页列表查询")
@ApiOperation(value="01. 分页查询", notes="")
@ApiOperationSupport(order = 1)
@GetMapping(value = "/list")
public Result<IPage<FIotVirtualDevice>> queryPageList(FIotVirtualDevice fIotVirtualDevice,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<FIotVirtualDevice> queryWrapper = QueryGenerator.initQueryWrapper(fIotVirtualDevice, req.getParameterMap());
Page<FIotVirtualDevice> page = new Page<FIotVirtualDevice>(pageNo, pageSize);
IPage<FIotVirtualDevice> pageList = fIotVirtualDeviceService.page(page, queryWrapper);
return Result.OK(pageList);
}
@AutoLog(value = "虚拟设备表-添加")
@ApiOperationSupport(order = 2)
@ApiOperation(value="02. 添加", notes="")
@RequiresPermissions("iot:f_iot_virtual_device:add")
@PostMapping(value = "/add")
public Result<String> add(@RequestBody FIotVirtualDevice fIotVirtualDevice, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDevice.setCreateBy(username);
fIotVirtualDevice.setCreateTime(new Date());
fIotVirtualDeviceService.save(fIotVirtualDevice);
return Result.OK("添加成功!");
}
@AutoLog(value = "虚拟设备表-编辑")
@ApiOperationSupport(order = 3)
@ApiOperation(value="03. 编辑", notes="")
@RequiresPermissions("iot:f_iot_virtual_device:edit")
@PostMapping(value = "/edit")
public Result<String> edit(@RequestBody FIotVirtualDevice fIotVirtualDevice, HttpServletRequest request) {
//创建更新时间不能编辑
fIotVirtualDevice.setCreateTime(null);
fIotVirtualDevice.setUpdateTime(null);
String username = JwtUtil.getUserNameByToken(request);
fIotVirtualDevice.setUpdateBy(username);
fIotVirtualDeviceService.updateById(fIotVirtualDevice);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@AutoLog(value = "虚拟设备表-通过id删除")
@ApiOperation(value="04.通过id删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device:delete")
@DeleteMapping(value = "/delete")
public Result<String> delete(@RequestParam(name="id",required=true) String id) {
fIotVirtualDeviceService.removeById(id);
return Result.OK("删除成功!");
}
@AutoLog(value = "虚拟设备表-批量删除")
@ApiOperationSupport(order = 4)
@ApiOperation(value="04. 批量删除", notes="")
@RequiresPermissions("iot:f_iot_virtual_device:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<String> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.fIotVirtualDeviceService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
//@AutoLog(value = "虚拟设备表-通过id查询")
@ApiOperationSupport(order = 5)
@ApiOperation(value="05. 通过id查询", notes="")
@GetMapping(value = "/queryById")
public Result<FIotVirtualDevice> queryById(@RequestParam(name="id",required=true) String id) {
FIotVirtualDevice fIotVirtualDevice = fIotVirtualDeviceService.getById(id);
if(fIotVirtualDevice==null) {
return Result.error("未找到对应数据");
}
return Result.OK(fIotVirtualDevice);
}
@ApiOperationSupport(order = 6)
@ApiOperation(value="06. 导出excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device:exportXls")
@GetMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, FIotVirtualDevice fIotVirtualDevice) {
return super.exportXls(request, fIotVirtualDevice, FIotVirtualDevice.class, "虚拟设备表");
}
@ApiOperationSupport(order = 7)
@ApiOperation(value="07. 导入excel", notes="")
@RequiresPermissions("iot:f_iot_virtual_device:importExcel")
@PostMapping(value = "/importExcel")
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, FIotVirtualDevice.class);
}
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.common.entity.FDeviceOpration;
/**
* @Description: 设备操作记录
* @Author: jeecg-boot
* @Date: 2023-11-04
* @Version: V1.0
*/
public interface FDeviceOprationMapper extends BaseMapper<FDeviceOpration> {
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.common.entity.FIotProtocol;
/**
* @Description: 物联网设备协议表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
public interface FIotProtocolMapper extends BaseMapper<FIotProtocol> {
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.common.entity.FIotVirtualDeviceGroup;
/**
* @Description: 虚拟设备模块分组
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
public interface FIotVirtualDeviceGroupMapper extends BaseMapper<FIotVirtualDeviceGroup> {
}

View File

@ -0,0 +1,16 @@
package org.jeecg.modules.appmana.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.common.entity.FIotVirtualDevice;
/**
* @Description: 虚拟设备表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
public interface FIotVirtualDeviceMapper extends BaseMapper<FIotVirtualDevice> {
FIotVirtualDevice getDeviceByCode(@Param("deployCode")String deployCode);
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.common.entity.FIotVirtualDeviceModule;
/**
* @Description: 虚拟设备模组表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
public interface FIotVirtualDeviceModuleMapper extends BaseMapper<FIotVirtualDeviceModule> {
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.common.entity.FIotVirtualDeviceNet;
/**
* @Description: 虚拟设备网络模块
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
public interface FIotVirtualDeviceNetMapper extends BaseMapper<FIotVirtualDeviceNet> {
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.appmana.mapper; package org.jeecg.modules.appmana.mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.jeecg.common.iot.common.LoginUser2;
import org.jeecg.common.vo.VOHisFormResult; import org.jeecg.common.vo.VOHisFormResult;
import org.jeecg.common.vo.statistic.DTOIotCusSummray; import org.jeecg.common.vo.statistic.DTOIotCusSummray;
import org.jeecg.common.vo.statistic.DTOIotSummray; import org.jeecg.common.vo.statistic.DTOIotSummray;
@ -31,4 +32,6 @@ public interface IOTStatisticMapper {
List<VOHisDateFormResult> summaryMaxByDays(@Param("query") DTOIotSummray dtoIotSummray); List<VOHisDateFormResult> summaryMaxByDays(@Param("query") DTOIotSummray dtoIotSummray);
List<VOHisFormResult> summaryMaxYearMonth(@Param("deployCode") String deployCode, @Param("tables") String tables, @Param("survItem") String survItem, @Param("years") String years); List<VOHisFormResult> summaryMaxYearMonth(@Param("deployCode") String deployCode, @Param("tables") String tables, @Param("survItem") String survItem, @Param("years") String years);
LoginUser2 getUserByUserName(@Param("username") String username);
} }

View File

@ -0,0 +1,5 @@
<?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="org.jeecg.modules.appmana.mapper.FDeviceOprationMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?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="org.jeecg.modules.appmana.mapper.FIotProtocolMapper">
</mapper>

View File

@ -0,0 +1,6 @@
<?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="org.jeecg.modules.appmana.mapper.FIotVirtualDeviceGroupMapper">
</mapper>

View File

@ -0,0 +1,51 @@
<?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="org.jeecg.modules.appmana.mapper.FIotVirtualDeviceMapper">
<resultMap type="org.jeecg.common.entity.FIotVirtualDevice" id="FIotVirtualDeviceMap">
<result property="id" column="ID" jdbcType="VARCHAR"/>
<result property="companyId" column="COMPANY_ID" jdbcType="VARCHAR"/>
<result property="farmId" column="FARM_ID" jdbcType="VARCHAR"/>
<result property="groupId" column="GROUP_ID" jdbcType="VARCHAR"/>
<result property="busId" column="BUS_ID" jdbcType="VARCHAR"/>
<result property="iotId" column="IOT_ID" jdbcType="VARCHAR"/>
<result property="iotCode" column="IOT_CODE" jdbcType="VARCHAR"/>
<result property="iotParams" column="IOT_PARAMS" jdbcType="VARCHAR"/>
<result property="deviceName" column="DEVICE_NAME" jdbcType="VARCHAR"/>
<result property="deviceType" column="DEVICE_TYPE" jdbcType="VARCHAR"/>
<result property="deviceSecType" column="DEVICE_SEC_TYPE" jdbcType="VARCHAR"/>
<result property="protocolId" column="PROTOCOL_ID" jdbcType="VARCHAR"/>
<result property="cmdStr" column="CMD_STR" jdbcType="VARCHAR"/>
<result property="deviceLat" column="DEVICE_LAT" jdbcType="VARCHAR"/>
<result property="deviceLong" column="DEVICE_LONG" jdbcType="VARCHAR"/>
<result property="deviceLonglat" column="DEVICE_LONGLAT" jdbcType="VARCHAR"/>
<result property="deviceNotes" column="DEVICE_NOTES" jdbcType="VARCHAR"/>
<result property="statusSupport" column="STATUS_SUPPORT" jdbcType="INTEGER"/>
<result property="controlSupport" column="CONTROL_SUPPORT" jdbcType="INTEGER"/>
<result property="recordSupport" column="RECORD_SUPPORT" jdbcType="INTEGER"/>
<result property="lowerUrl" column="LOWER_URL" jdbcType="VARCHAR"/>
<result property="upperUrl" column="UPPER_URL" jdbcType="VARCHAR"/>
<result property="sortNo" column="SORT_NO" jdbcType="INTEGER"/>
<result property="isEnable" column="IS_ENABLE" javaType="INTEGER"/>
<result property="tenantId" column="TENANT_ID" jdbcType="VARCHAR"/>
<result property="reVision" column="RE_VISION" jdbcType="INTEGER"/>
<result property="createBy" column="CREATE_BY" jdbcType="VARCHAR"/>
<result property="createTime" column="CREATE_TIME" jdbcType="TIMESTAMP"/>
<result property="updateBy" column="UPDATE_BY" jdbcType="VARCHAR"/>
<result property="isDel" column="IS_DEL" jdbcType="INTEGER"/>
<result property="updateTime" column="UPDATE_TIME" jdbcType="TIMESTAMP"/>
</resultMap>
<resultMap id="ext" type="org.jeecg.common.entity.FIotVirtualDevice" extends="FIotVirtualDeviceMap">
<collection property="modules" column="{deviceId = id}" select="org.jeecg.modules.iot.mapper.FIotVirtualDeviceModuleMapper.getDeviceModule"/>
</resultMap>
<sql id="baseSql">
ID,COMPANY_ID,FARM_ID,GROUP_ID,BUS_ID,IOT_ID,IOT_PARAMS,DEVICE_NAME,DEVICE_TYPE,DEVICE_SEC_TYPE,PROTOCOL_ID,CMD_STR,DEVICE_LAT,DEVICE_LONG,DEVICE_LONGLAT,DEVICE_NOTES,STATUS_SUPPORT,CONTROL_SUPPORT,RECORD_SUPPORT,LOWER_URL,UPPER_URL,SORT_NO,IS_ENABLE,TENANT_ID,RE_VISION,CREATE_BY,CREATE_TIME,UPDATE_BY,IS_DEL,UPDATE_TIME
</sql>
<select id="getDeviceByCode" resultMap="ext">
select <include refid="baseSql"/>
from surv_iot_virtual_device where IOT_CODE = #{deployCode}
</select>
</mapper>

View File

@ -0,0 +1,59 @@
<?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="org.jeecg.modules.appmana.mapper.FIotVirtualDeviceModuleMapper">
<resultMap type="org.jeecg.common.entity.FIotVirtualDeviceModule" id="FIotVirtualDeviceModuleMap">
<result property="id" column="ID" jdbcType="VARCHAR"/>
<result property="companyId" column="COMPANY_ID" jdbcType="VARCHAR"/>
<result property="farmId" column="FARM_ID" jdbcType="VARCHAR"/>
<result property="deviceId" column="DEVICE_ID" jdbcType="VARCHAR"/>
<result property="moduleCode" column="MODULE_CODE" jdbcType="VARCHAR"/>
<result property="moduleNum" column="MODULE_NUM" jdbcType="VARCHAR"/>
<result property="moduleBusId" column="MODULE_BUS_ID" jdbcType="VARCHAR"/>
<result property="moduleGroupId" column="MODULE_GROUP_ID" jdbcType="VARCHAR"/>
<result property="moduleNetId" column="MODULE_NET_ID" jdbcType="VARCHAR"/>
<result property="moduleType" column="MODULE_TYPE" jdbcType="VARCHAR"/>
<result property="moduleSecType" column="MODULE_SEC_TYPE" jdbcType="VARCHAR"/>
<result property="moduleName" column="MODULE_NAME" jdbcType="VARCHAR"/>
<result property="moduleNotes" column="MODULE_NOTES" jdbcType="VARCHAR"/>
<result property="moduleMode" column="MODULE_MODE" jdbcType="VARCHAR"/>
<result property="moduleVirtualStatus" column="MODULE_VIRTUAL_STATUS" jdbcType="VARCHAR"/>
<result property="modulePath" column="MODULE_PATH" jdbcType="VARCHAR" typeHandler="org.jeecg.common.mybatis.typehandler.JsonTypeHandler"/>
<result property="registerType" column="REGISTER_TYPE" jdbcType="INTEGER"/>
<result property="registerNum" column="REGISTER_NUM" jdbcType="INTEGER"/>
<result property="registerCmdOn" column="REGISTER_CMD_ON" jdbcType="VARCHAR"/>
<result property="registerCmdOff" column="REGISTER_CMD_OFF" jdbcType="VARCHAR"/>
<result property="registerCmdStop" column="REGISTER_CMD_STOP" jdbcType="VARCHAR"/>
<result property="registerOn" column="REGISTER_ON" jdbcType="VARCHAR"/>
<result property="registerOff" column="REGISTER_OFF" jdbcType="VARCHAR"/>
<result property="registerStop" column="REGISTER_STOP" jdbcType="VARCHAR"/>
<result property="sortNo" column="SORT_NO" jdbcType="INTEGER"/>
<result property="isEnable" column="IS_ENABLE" javaType="INTEGER"/>
<result property="tenantId" column="TENANT_ID" jdbcType="VARCHAR"/>
<result property="reVision" column="RE_VISION" jdbcType="INTEGER"/>
<result property="createBy" column="CREATE_BY" jdbcType="VARCHAR"/>
<result property="createTime" column="CREATE_TIME" jdbcType="TIMESTAMP"/>
<result property="updateBy" column="UPDATE_BY" jdbcType="VARCHAR"/>
<result property="isDel" column="IS_DEL" jdbcType="INTEGER"/>
<result property="updateTime" column="UPDATE_TIME" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="baseSql">
ID,COMPANY_ID,FARM_ID,DEVICE_ID,MODULE_CODE,MODULE_NUM,MODULE_BUS_ID,MODULE_GROUP_ID,MODULE_NET_ID,MODULE_TYPE,MODULE_SEC_TYPE,MODULE_NAME,MODULE_NOTES,MODULE_MODE,MODULE_VIRTUAL_STATUS,MODULE_PATH,REGISTER_TYPE,REGISTER_NUM,REGISTER_CMD_ON,REGISTER_CMD_OFF,REGISTER_CMD_STOP,REGISTER_ON,REGISTER_OFF,REGISTER_STOP,SORT_NO,IS_ENABLE,TENANT_ID,RE_VISION,CREATE_BY,CREATE_TIME,UPDATE_BY,IS_DEL,UPDATE_TIME
</sql>
<select id="getAllmodule" resultMap="FIotVirtualDeviceModuleMap">
select
<include refid="baseSql"/>
from surv_iot_virtual_device_module where MODULE_GROUP_ID = #{groupId} order by SORT_NO,CREATE_TIME desc;
</select>
<select id="getDeviceModule" resultMap="FIotVirtualDeviceModuleMap">
select
<include refid="baseSql"/>
from surv_iot_virtual_device_module where DEVICE_ID = #{deviceId} order by SORT_NO,CREATE_TIME desc;
</select>
</mapper>

View File

@ -0,0 +1,5 @@
<?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="org.jeecg.modules.appmana.mapper.FIotVirtualDeviceNetMapper">
</mapper>

View File

@ -145,4 +145,7 @@
ON t1.index = t2.months ON t1.index = t2.months
ORDER BY t1.index asc ORDER BY t1.index asc
</select> </select>
<select id="getUserByUserName" resultType="org.jeecg.common.iot.common.LoginUser2">
select * from sys_user where username = #{username}
</select>
</mapper> </mapper>

View File

@ -0,0 +1,128 @@
package org.jeecg.modules.appmana.o.vo.common;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecg.common.desensitization.annotation.SensitiveField;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* <p>
* 在线用户信息
* </p>
*
* @Author scott
* @since 2018-12-20
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class LoginUser {
/**
* 登录人id
*/
@SensitiveField
private String id;
/**
* 登录人账号
*/
@SensitiveField
private String username;
/**
* 登录人名字
*/
@SensitiveField
private String realname;
/**
* 登录人密码
*/
@SensitiveField
private String password;
/**
* 当前登录部门code
*/
private String orgCode;
/**
* 头像
*/
@SensitiveField
private String avatar;
/**
* 生日
*/
@SensitiveField
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
/**
* 性别1 2
*/
private Integer sex;
/**
* 电子邮件
*/
@SensitiveField
private String email;
/**
* 电话
*/
@SensitiveField
private String phone;
/**
* 状态(1正常 2冻结
*/
private Integer status;
private Integer delFlag;
/**
* 同步工作流引擎1同步0不同步
*/
private Integer activitiSync;
/**
* 创建时间
*/
private Date createTime;
/**
* 身份1 普通员工 2 上级
*/
private Integer userIdentity;
/**
* 管理部门ids
*/
private String departIds;
/**
* 职务关联职务表
*/
@SensitiveField
private String post;
/**
* 座机号
*/
@SensitiveField
private String telephone;
/** 多租户ids临时用不持久化数据库(数据库字段不存在) */
private String relTenantIds;
/**设备id uniapp推送用*/
private String clientId;
}

View File

@ -0,0 +1,17 @@
package org.jeecg.modules.appmana.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.entity.FDeviceOpration;
import org.jeecg.common.iot.common.DeviceLogVo;
/**
* @Description: 设备操作记录
* @Author: jeecg-boot
* @Date: 2023-11-04
* @Version: V1.0
*/
public interface IFDeviceOprationService extends IService<FDeviceOpration> {
boolean saveDeviceOpration(DeviceLogVo deviceLogVo);
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.entity.FIotProtocol;
/**
* @Description: 物联网设备协议表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
public interface IFIotProtocolService extends IService<FIotProtocol> {
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.entity.FIotVirtualDeviceGroup;
/**
* @Description: 虚拟设备模块分组
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
public interface IFIotVirtualDeviceGroupService extends IService<FIotVirtualDeviceGroup> {
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.entity.FIotVirtualDeviceModule;
/**
* @Description: 虚拟设备模组表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
public interface IFIotVirtualDeviceModuleService extends IService<FIotVirtualDeviceModule> {
}

View File

@ -0,0 +1,14 @@
package org.jeecg.modules.appmana.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.entity.FIotVirtualDeviceNet;
/**
* @Description: 虚拟设备网络模块
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
public interface IFIotVirtualDeviceNetService extends IService<FIotVirtualDeviceNet> {
}

View File

@ -0,0 +1,71 @@
package org.jeecg.modules.appmana.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.entity.FIotVirtualDevice;
import org.jeecg.common.entity.FIotVirtualDeviceModule;
import org.jeecg.common.entity.SurvDeviceDeploy;
import org.jeecg.common.iot.Fertilizer.VOFertilizerStats;
import org.jeecg.common.iot.up.DeviceActionVo;
import org.jeecg.common.iot.up.ModuleStatusResultVo;
import org.jeecg.common.iot.vo.DeviceControlResultVo;
import org.jeecg.common.iot.vo.VODeviceCmd;
import java.util.List;
/**
* @Description: 虚拟设备表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
public interface IFIotVirtualDeviceService extends IService<FIotVirtualDevice> {
FIotVirtualDevice getDeviceByCode(String deployCode);
VOFertilizerStats getDeviceStats(SurvDeviceDeploy deploy);
/**
* 单控寄存器
* @param deploy
* @param voDeviceCmd
* @return
*/
DeviceControlResultVo sendControl(SurvDeviceDeploy deploy, VODeviceCmd voDeviceCmd);
/**
* 单查寄存器
*/
boolean sendSingleQuery(SurvDeviceDeploy deploy, FIotVirtualDeviceModule module);
/**
* 多查寄存器
*/
boolean sendMutiQuery(SurvDeviceDeploy deploy, List<FIotVirtualDeviceModule> modules);
FIotVirtualDevice getDeviceByIotCode(String deployCode);
/**
* 处理内部mqtt服务中设备行为
* @param deviceQueryActionVo
*/
void processIotAction(DeviceActionVo deviceQueryActionVo);
ModuleStatusResultVo getDeviceCache(String deployCode);
void pubDeviceTopic(ModuleStatusResultVo moduleStatusResultVo,List<FIotVirtualDevice> devices);
/**
* 厂家对接mqtt处理
* @param topic
*/
void processInterface(String topic, byte[] payload);
/**
* 获取所有需要订阅的mqtt主题
* @return
*/
List<String> getAllMqttTopic();
void processCache(DeviceActionVo deviceQueryActionVo);
}

View File

@ -0,0 +1,73 @@
package org.jeecg.modules.appmana.service.impl;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.entity.FDeviceOpration;
import org.jeecg.common.entity.SurvDeviceDeploy;
import org.jeecg.common.iot.common.DeviceLogVo;
import org.jeecg.common.iot.common.LoginUser2;
import org.jeecg.common.iot.vo.VOCmdPack;
import org.jeecg.common.util.IpUtils;
import org.jeecg.modules.appmana.mapper.FDeviceOprationMapper;
import org.jeecg.modules.appmana.service.IFDeviceOprationService;
import org.jeecg.modules.appmana.utils.HttpServletRequestUtil;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
/**
* @Description: 设备操作记录
* @Author: jeecg-boot
* @Date: 2023-11-04
* @Version: V1.0
*/
@Service
public class FDeviceOprationServiceImpl extends ServiceImpl<FDeviceOprationMapper, FDeviceOpration> implements IFDeviceOprationService {
@Override
public boolean saveDeviceOpration(DeviceLogVo deviceLogVo) {
if (deviceLogVo != null) {
LocalDateTime now = LocalDateTime.now();
SurvDeviceDeploy deploy = deviceLogVo.getDeploy();
LoginUser2 loginUser = deviceLogVo.getLoginUser();
if (deploy != null && loginUser != null) {
FDeviceOpration fDeviceOpration = new FDeviceOpration();
fDeviceOpration.setTenantId(deploy.getTenantId());
fDeviceOpration.setOperatorUserId(loginUser.getId());
fDeviceOpration.setOperatorUserName(loginUser.getRealname());
fDeviceOpration.setOperatorUserAvatar(loginUser.getAvatar());
fDeviceOpration.setCreateBy(loginUser.getId());
VOCmdPack voCmdPack = new VOCmdPack();
voCmdPack.setVariableName(deviceLogVo.getVariableName());
voCmdPack.setVariableValue(deviceLogVo.getVariableValue());
fDeviceOpration.setDeployId(deploy.getId());
fDeviceOpration.setOperatorTime(now);
fDeviceOpration.setOperatorContent(JSONUtil.parseObj(voCmdPack));
if(deviceLogVo.isProcessRequest()) {
HttpServletRequest request = HttpServletRequestUtil.getRequest();
String ipAddr = IpUtils.getIpAddr(request);
String header = request.getHeader("user-agent");
fDeviceOpration.setIp(ipAddr);
fDeviceOpration.setAgent(header);
}
fDeviceOpration.setOperatorDes(deviceLogVo.getOperationDetail());
fDeviceOpration.setVariableId(deviceLogVo.getVariableName());
fDeviceOpration.setVariableDes(deviceLogVo.getVariableDes());
fDeviceOpration.setOprationName(deviceLogVo.getActions());
fDeviceOpration.setVariableValue(deviceLogVo.getVariableValue());
fDeviceOpration.setOperationResult(deviceLogVo.isOperationResult() ? 1 : 0);
fDeviceOpration.setCalStatus(deviceLogVo.getCalStatus());
save(fDeviceOpration);
}
}
return false;
}
}

View File

@ -0,0 +1,18 @@
package org.jeecg.modules.appmana.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.entity.FIotProtocol;
import org.jeecg.modules.appmana.mapper.FIotProtocolMapper;
import org.jeecg.modules.appmana.service.IFIotProtocolService;
import org.springframework.stereotype.Service;
/**
* @Description: 物联网设备协议表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
@Service
public class FIotProtocolServiceImpl extends ServiceImpl<FIotProtocolMapper, FIotProtocol> implements IFIotProtocolService {
}

View File

@ -0,0 +1,18 @@
package org.jeecg.modules.appmana.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.entity.FIotVirtualDeviceGroup;
import org.jeecg.modules.appmana.mapper.FIotVirtualDeviceGroupMapper;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceGroupService;
import org.springframework.stereotype.Service;
/**
* @Description: 虚拟设备模块分组
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
@Service
public class FIotVirtualDeviceGroupServiceImpl extends ServiceImpl<FIotVirtualDeviceGroupMapper, FIotVirtualDeviceGroup> implements IFIotVirtualDeviceGroupService {
}

View File

@ -0,0 +1,61 @@
package org.jeecg.modules.appmana.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.entity.FIotVirtualDevice;
import org.jeecg.common.entity.FIotVirtualDeviceModule;
import org.jeecg.modules.appmana.mapper.FIotVirtualDeviceModuleMapper;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceModuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 虚拟设备模组表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
@Service
@Slf4j
public class FIotVirtualDeviceModuleServiceImpl extends ServiceImpl<FIotVirtualDeviceModuleMapper, FIotVirtualDeviceModule> implements IFIotVirtualDeviceModuleService {
@Autowired
@Lazy
private FIotVirtualDeviceServiceImpl deviceService;
public List<FIotVirtualDeviceModule> getModulesByCode(String deployCode) {
FIotVirtualDevice device = deviceService.lambdaQuery()
.eq(FIotVirtualDevice::getIotCode,deployCode)
.eq(FIotVirtualDevice::getIsEnable,1)
.orderByDesc(FIotVirtualDevice::getCreateTime)
.last("limit 1")
.one();
if(device==null){
log.error("=======无效虚拟设备:{}======",deployCode);
return new ArrayList<>();
}
List<FIotVirtualDeviceModule> modules = lambdaQuery()
.eq(FIotVirtualDeviceModule::getDeviceId,device.getId())
.eq(FIotVirtualDeviceModule::getIsEnable,1)
.orderByAsc(FIotVirtualDeviceModule::getSortNo)
.orderByDesc(FIotVirtualDeviceModule::getCreateTime)
.list()
;
return modules;
}
public List<FIotVirtualDeviceModule> getModulesByNet(String id) {
List<FIotVirtualDeviceModule> modules = lambdaQuery()
.eq(FIotVirtualDeviceModule::getModuleNetId,id)
.eq(FIotVirtualDeviceModule::getIsEnable,1)
.orderByAsc(FIotVirtualDeviceModule::getSortNo)
.orderByDesc(FIotVirtualDeviceModule::getCreateTime)
.list()
;
return modules;
}
}

View File

@ -0,0 +1,28 @@
package org.jeecg.modules.appmana.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.entity.FIotVirtualDeviceNet;
import org.jeecg.modules.appmana.mapper.FIotVirtualDeviceNetMapper;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceNetService;
import org.springframework.stereotype.Service;
/**
* @Description: 虚拟设备网络模块
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.0
*/
@Service
public class FIotVirtualDeviceNetServiceImpl extends ServiceImpl<FIotVirtualDeviceNetMapper, FIotVirtualDeviceNet> implements IFIotVirtualDeviceNetService {
public FIotVirtualDeviceNet matchNetSet(String ident) {
FIotVirtualDeviceNet net = lambdaQuery()
.eq(FIotVirtualDeviceNet::getNetIdentCode, ident)
.eq(FIotVirtualDeviceNet::getIsEnable,1)
.orderByDesc(FIotVirtualDeviceNet::getCreateTime)
.last("limit 1")
.one()
;
return net;
}
}

View File

@ -0,0 +1,764 @@
package org.jeecg.modules.appmana.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.iot.Fertilizer.VOFertilizerStats;
import org.jeecg.common.iot.Fertilizer.VOFertilizerStatsArr;
import org.jeecg.common.iot.common.LoginUser2;
import org.jeecg.common.iot.enums.*;
import org.jeecg.common.iot.vo.VODeviceCmd;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.common.constant.IotConstants;
import org.jeecg.common.entity.SurvDeviceDeploy;
import org.jeecg.common.iot.common.DeviceLogVo;
import org.jeecg.modules.appmana.mapper.IOTStatisticMapper;
import org.jeecg.modules.appmana.service.IFIotVirtualDeviceService;
import org.jeecg.modules.appmana.utils.CommonUtils;
import org.jeecg.common.entity.FIotVirtualDevice;
import org.jeecg.common.entity.FIotVirtualDeviceModule;
import org.jeecg.common.entity.FIotVirtualDeviceNet;
import org.jeecg.modules.appmana.mapper.FIotVirtualDeviceMapper;
import org.jeecg.common.iot.up.DeviceActionVo;
import org.jeecg.common.iot.up.ModuleStatusDetailVo;
import org.jeecg.common.iot.up.ModuleStatusResultVo;
import org.jeecg.common.iot.vo.DeviceControlResultVo;
import org.jeecg.common.util.ModbusCommandUtil;
import org.jeecg.common.util.ModbusResponseParser;
import org.jeecg.modules.mqtt.MqttService;
import org.jeecg.common.constant.TopicConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Description: 虚拟设备表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.0
*/
@Service
@Slf4j
public class FIotVirtualDeviceServiceImpl extends ServiceImpl<FIotVirtualDeviceMapper, FIotVirtualDevice> implements IFIotVirtualDeviceService {
@Autowired
private FIotVirtualDeviceModuleServiceImpl moduleService;
@Autowired
private FIotVirtualDeviceNetServiceImpl netService;
@Autowired(required = false)
private MqttService mqttCustomerClient;
@Autowired
@Lazy
private SurvDeviceDeployServiceImpl deviceDeployService;
@Autowired
@Lazy
private FDeviceOprationServiceImpl deviceOprationService;
@Resource
private IOTStatisticMapper iotStatisticMapper;
@Autowired
@Lazy
private RedisUtil redisUtil;
/**
* 设备缓存时间
*/
private long cacheTime = 3600;//缓存3600秒
@Override
public FIotVirtualDevice getDeviceByCode(String deployCode) {
FIotVirtualDevice fIotVirtualDevice = baseMapper.getDeviceByCode(deployCode);
return fIotVirtualDevice;
}
@Override
public VOFertilizerStats getDeviceStats(SurvDeviceDeploy deploy) {
VOFertilizerStats voFertilizerStats = new VOFertilizerStats();
//获取设备信息 todo
FIotVirtualDevice fIotVirtualDevice = baseMapper.getDeviceByCode(deploy.getDeployCode());
Assert.notNull(fIotVirtualDevice,"无效设备。");
List<VOFertilizerStatsArr> arrList = new ArrayList();
if(fIotVirtualDevice.getModules()!= null && !fIotVirtualDevice.getModules().isEmpty()){
for (FIotVirtualDeviceModule module : fIotVirtualDevice.getModules()) {
VOFertilizerStatsArr voFertilizerStatsArr = new VOFertilizerStatsArr();
voFertilizerStatsArr.setDeployId(deploy.getId());
voFertilizerStatsArr.setEleType(IotConstants.FERTILIZER_DATA);
voFertilizerStatsArr.setEleName(module.getModuleName());
voFertilizerStatsArr.setEleItem("");
voFertilizerStatsArr.setEleIcon("");
voFertilizerStatsArr.setEleColor("");
voFertilizerStatsArr.setEleIconFolder("");
// voFertilizerStatsArr.setEleValue(xphDeviceNewestDataEleVo.getEValue());
// voFertilizerStatsArr.setEleUnit(sele.getEleUnit());
voFertilizerStatsArr.setLastUpdate(null);
voFertilizerStatsArr.setDataDateTime(null);
arrList.add(voFertilizerStatsArr);
}
}
voFertilizerStats.setStatsList(arrList);
voFertilizerStats.setStatusSupport(fIotVirtualDevice.getStatusSupport());
voFertilizerStats.setRecordSupport(fIotVirtualDevice.getRecordSupport());
voFertilizerStats.setControlSupport(fIotVirtualDevice.getControlSupport());
voFertilizerStats.setUpperUrl(fIotVirtualDevice.getUpperUrl());
voFertilizerStats.setLowerUrl(fIotVirtualDevice.getLowerUrl());
return voFertilizerStats;
}
public DeviceControlResultVo sendControl(SurvDeviceDeploy deploy, VODeviceCmd voDeviceCmd) {
DeviceControlResultVo deviceControlResultVo = new DeviceControlResultVo();
deviceControlResultVo.setDeviceStatus(voDeviceCmd.getVariableValue());
boolean result = false;
if(deploy!=null){
//获取寄存器位置
FIotVirtualDeviceModule module = moduleService.getById(voDeviceCmd.getVariableName());
Assert.notNull(module,"模组未正确配置");
FIotVirtualDeviceNet net = netService.getById(module.getModuleNetId());
Assert.notNull(net,"模组物联网模块未正确配置");
deviceControlResultVo.setDeviceName(module.getModuleName());
deviceControlResultVo.setDeviceKey(module.getRegisterNum()+"");
String cmdStr = ModbusCommandUtil.buildCommand(1, RegisterType.valueOfCode(module.getRegisterType()), RWType.WRITE, module.getRegisterNum(), HexTransToInteger(voDeviceCmd.getVariableValue(),module), null);
log.warn("设备:{}成功构造M控制指令{},主题:{},即将发送",deploy.getDeployDes(),cmdStr,net.getNetDownTopic());
result = sendIt(net.getNetDownTopic(),cmdStr);
}
deviceControlResultVo.setActionResult(result);
return deviceControlResultVo;
}
@Override
public boolean sendSingleQuery(SurvDeviceDeploy deploy, FIotVirtualDeviceModule module) {
boolean result = false;
Assert.notNull(deploy,"设备未传入");
Assert.notNull(module,"模组未传入");
FIotVirtualDeviceNet net = netService.getById(module.getModuleNetId());
Assert.notNull(net,"模组物联网模块未正确配置");
String cmdStr = ModbusCommandUtil.buildCommand(1, RegisterType.valueOfCode(module.getRegisterType()), RWType.READ, module.getRegisterNum(), null, 1);
log.warn("设备:{}成功构造M单查询指令{},即将发送至:{}",deploy.getDeployDes(),cmdStr,net.getNetDownTopic());
result = sendIt(net.getNetDownTopic(),cmdStr);
return false;
}
@Override
public boolean sendMutiQuery(SurvDeviceDeploy deploy, List<FIotVirtualDeviceModule> modules) {
boolean result = false;
Assert.notNull(deploy,"设备未传入");
Assert.isTrue((modules!=null && !modules.isEmpty()),"模组列表未传入");
Map<String,List<FIotVirtualDeviceModule>> moduleMap = modules.stream().collect(Collectors.groupingBy(FIotVirtualDeviceModule::getModuleNetId));
Comparator<FIotVirtualDeviceModule> nameComparator = Comparator.comparing(FIotVirtualDeviceModule::getRegisterNum);
for (String netId : moduleMap.keySet()) {
List<FIotVirtualDeviceModule> list = moduleMap.get(netId);
FIotVirtualDeviceNet net = netService.getById(netId);
if(net==null){
log.error("无效的物联网id{},设备:{}",netId,deploy.getDeployDes());
continue;
}
//按寄存器类型分组
Map<Integer,List<FIotVirtualDeviceModule>> regTypeList = list.stream().collect(Collectors.groupingBy(FIotVirtualDeviceModule::getRegisterType));
for (Integer keys : regTypeList.keySet()) {
List<FIotVirtualDeviceModule> regs = regTypeList.get(keys);
regs.sort(nameComparator.reversed());//倒叙获取最大的寄存器
Integer maxRegister = regs.get(0).getRegisterNum() +1;//起始寄存器位置
// Integer minRegister = regs.get(regs.size()-1).getRegisterNum();//查询寄存器数量
Integer minRegister = 0;//只能从0号开始否则不清楚返回时是几号开始
Integer regType = regs.get(0).getRegisterType();
RegisterType typeEnum = RegisterType.valueOfCode(regType);
//构造查询参数
String cmdStr = ModbusCommandUtil.buildCommand(1, typeEnum, RWType.READ, minRegister, null, maxRegister);
log.warn("设备:{}成功构造M多查询指令{},即将发送至:{}",deploy.getDeployDes(),cmdStr,net.getNetDownTopic());
result = sendIt(net.getNetDownTopic(),cmdStr);
}
}
return result;
}
@Override
public FIotVirtualDevice getDeviceByIotCode(String deployCode){
List<FIotVirtualDevice> devices = lambdaQuery()
.eq(FIotVirtualDevice::getIotCode, deployCode)
.eq(FIotVirtualDevice::getIsEnable,1)
.list();
if(!devices.isEmpty()){
return devices.get(0);
}
return null;
}
@Override
public void processIotAction(DeviceActionVo deviceActionVo) {
//token校验
boolean isOk = checkToken(deviceActionVo);
if(isOk){
DeviceActionType actionType = DeviceActionType.valueOfCode(deviceActionVo.getActionType());
SurvDeviceDeploy deploy = deviceDeployService.getById(deviceActionVo.getDeployId());
if(deploy!=null){
switch (actionType){
case DEVICE_QUERY_ALL:
//检查缓存
ModuleStatusResultVo deviceAllChache = getDeviceCache(deploy.getDeployCode());
log.warn("============={}===检查缓存======{}======",deploy.getDeployCode(),deviceAllChache);
if(deviceAllChache!=null){//缓存直接传入设备mqtt
FIotVirtualDevice device = getDeviceByIotCode(deploy.getDeployCode());
List<FIotVirtualDevice> devices = new ArrayList<>();
if(device!=null){
devices.add(device);
}
log.warn("============={}====缓存推入蓝海主题:{}=============",deviceAllChache,devices.size());
pubDeviceTopic(deviceAllChache, devices);
}else{//无缓存查询
List<FIotVirtualDeviceModule> modules = moduleService.getModulesByCode(deploy.getDeployCode());
if(!modules.isEmpty()){
sendMutiQuery(deploy,modules);
}
}
break;
case DEVICE_QUERY_S:
//检查缓存
ModuleStatusResultVo deviceSCache = getDeviceCache(deploy.getDeployCode());
if(deviceSCache!=null){//缓存直接传入设备mqtt
FIotVirtualDevice device = getDeviceByIotCode(deploy.getDeployCode());
List<FIotVirtualDevice> devices = new ArrayList<>();
if(device!=null){
devices.add(device);
}
pubDeviceTopic(deviceSCache, devices);
}else {//无缓存查询
FIotVirtualDeviceModule module = moduleService.getById(deviceActionVo.getModuleId());
if (module != null) {
sendSingleQuery(deploy, module);
}
}
break;
case DEVICE_CONTROL:
VODeviceCmd voDeviceCmd = new VODeviceCmd();
voDeviceCmd.setDeployId(deploy.getId());
voDeviceCmd.setVariableName(deviceActionVo.getModuleId());
voDeviceCmd.setVariableValue(deviceActionVo.getCmdType());
DeviceControlResultVo resultVo = sendControl(deploy,voDeviceCmd);
//记录日志
String username = JwtUtil.getUsername(deviceActionVo.getToken());
LoginUser2 loginUser = iotStatisticMapper.getUserByUserName(username);
if(loginUser!=null){
DeviceLogVo deviceLogVo = new DeviceLogVo();
String formatStr = "用户%s于 %s 操作设备:%s操作内容%s操作结果%s";
deviceLogVo.setDeploy(deploy);
deviceLogVo.setLoginUser(loginUser);
deviceLogVo.setVariableDes(resultVo.getDeviceName());
deviceLogVo.setVariableName(resultVo.getDeviceKey());
deviceLogVo.setVariableValue(voDeviceCmd.getVariableValue());
deviceLogVo.setActions(CommonUtils.processRelayOprateName(resultVo.getDeviceName(), voDeviceCmd.getVariableValue()));
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
deviceLogVo.setOperationDetail(String.format(formatStr, loginUser.getRealname(), now.format(sdf), deploy.getDeployDes(), resultVo.getDeviceName() + "->" + deviceLogVo.getActions(), resultVo.isActionResult() ? "成功" : "失败"));
deviceLogVo.setOperationResult(resultVo.isActionResult());
deviceLogVo.setCalStatus(0);
deviceLogVo.setProcessRequest(false);//不处理request
deviceOprationService.saveDeviceOpration(deviceLogVo);
}else{
log.error("=========记录日志失败,无效用户:{}============",username);
}
break;
}
}
}else{
log.error("非法的mqtt操作设备{},模组:{},类型:{},行为:{}",deviceActionVo.getDeployId(),deviceActionVo.getModuleId(),deviceActionVo.getActionType(),deviceActionVo.getCmdType());
}
}
public ModuleStatusResultVo getDeviceCache(String deployCode){
//检查缓存如有直接返回
Object deviceCache = redisUtil.get(IotConstants.mqtt_device_status+deployCode);
if (deviceCache != null) {
log.warn("查询到 {} mqtt设备缓存缓存直接返回", deployCode);
return JSONUtil.toBean(deviceCache.toString(), ModuleStatusResultVo.class);
}else{
log.error("xxxxxxxxxxxxxxxxxxxx未查询到mqtt缓存:{}xxxxxxxxxxxxxxxxx",deployCode);
}
return null;
}
public boolean checkToken(DeviceActionVo deviceActionVo){
boolean result = false;
if(deviceActionVo != null){
if(StringUtils.isNotBlank(deviceActionVo.getToken())){
// 验证Token有效性
// result = TokenUtils.verifyToken(deviceActionVo.getToken(), sysBaseApi, redisUtil);//暂时无法验证需要写一个内部调用校验
}
}
return result;
}
@Override
public void processInterface(String topic, byte[] payload) {
try {
String ident = topic.replace(IotInerfaceTopicType.DTU_TOPIC.getCode(), "");
ModbusResponseParser.ModbusResult res = org.jeecg.common.util.ModbusResponseParser.parse(payload);
String orgStr = ModbusResponseParser.bytesToHex(payload);
log.warn("主题:{},收到mqtt回执{}=========,原文:{}", topic, res.toString(), orgStr);
if (res != null && res.isSuccess()) {
//查询网络模块
List<FIotVirtualDeviceModule> modules = getModulesByIdent(ident);
if (!modules.isEmpty()) {
ModuleStatusResultVo moduleStatusResultVo = processHexToJson(res, modules);
//转发至设备的上下行主题
//模组关联的设备
List<String> deviceId = modules.stream().map(FIotVirtualDeviceModule::getDeviceId).collect(Collectors.toList());
log.warn("转换modbus=========" + JSONUtil.toJsonStr(moduleStatusResultVo));
List<FIotVirtualDevice> devices = lambdaQuery().in(FIotVirtualDevice::getId, deviceId).list();
//推送蓝海设备主题
pubDeviceTopic(moduleStatusResultVo, devices);
//保存缓存
saveDeviceCache(moduleStatusResultVo,devices);
}
} else {
log.error("==================未能识别功能码,错误信息:{}:主题:{}===================", res != null ? res.getErrorMsg() : "", ident);
}
//如果是心跳更新设备的时间
String infoStr = new String(payload);
log.error("========{}==========更新心跳:{}===================", infoStr, ident);
if ("www.usr.cn".equals(infoStr)) {
//查询网络模块
List<FIotVirtualDeviceModule> modules = getModulesByIdent(ident);
if (!modules.isEmpty()) {
List<String> deviceId = modules.stream().map(FIotVirtualDeviceModule::getDeviceId).collect(Collectors.toList());
List<FIotVirtualDevice> devices = lambdaQuery().in(FIotVirtualDevice::getId, deviceId).list();
List<String> deploys = devices.stream().map(FIotVirtualDevice::getIotId).collect(Collectors.toList());
deviceDeployService.refreshLastSyncTimeByDeployCode(deploys);
}
}
}catch (Exception e){
e.printStackTrace();
log.error("处理厂家mqtt报文失败"+e.getMessage());
}
}
/**
* 收到回执时保存设备缓存
* @param devices
*/
private void saveDeviceCache(ModuleStatusResultVo inComeStaus, List<FIotVirtualDevice> devices) {
if(!devices.isEmpty()){
for (FIotVirtualDevice device : devices) {
String redisKey = IotConstants.mqtt_device_status+device.getIotCode();
//首先检查缓存
ModuleStatusResultVo deviceCache = getDeviceCache(device.getIotCode());
if (deviceCache != null) {
List<ModuleStatusDetailVo> status = deviceCache.getStatus();
List<ModuleStatusDetailVo> finalList = new ArrayList<>();
Map<String,ModuleStatusDetailVo> cacheMap = new HashMap<>();
for (ModuleStatusDetailVo cache : status) {
cacheMap.put(cache.getModuleId(),cache);
}
for (ModuleStatusDetailVo inComeStausStatus : inComeStaus.getStatus()) {
ModuleStatusDetailVo cacheKey = cacheMap.get(inComeStausStatus.getModuleId());
if(cacheKey != null){//缓存存在更新状态
status.remove(cacheKey);
cacheKey.setModuleStatus(inComeStausStatus.getModuleStatus());
finalList.add(cacheKey);
}else{//没有缓存做补充
ModuleStatusDetailVo newStaus = new ModuleStatusDetailVo();
newStaus.setModuleId(inComeStausStatus.getModuleId());
newStaus.setModuleStatus(inComeStausStatus.getModuleStatus());
finalList.add(newStaus);
}
}
finalList.addAll(status);
deviceCache.setStatus(finalList);
redisUtil.set(redisKey, JSONUtil.parseObj(deviceCache), cacheTime);
log.warn("设备:{} 缓存更新成功", device.getDeviceName() + "-" + device.getIotCode());
} else {//否则直接覆盖或新增
cn.hutool.json.JSONObject newDeviceCache = JSONUtil.parseObj(inComeStaus);
redisUtil.set(redisKey, newDeviceCache, cacheTime);
log.warn("设备:{} 缓存创建成功", device.getDeviceName() + "-" + device.getIotCode());
}
}
}
}
/**
* 根据主题获取设备模组
*/
private List<FIotVirtualDeviceModule> getModulesByIdent(String identCode){
//查询网络模块
FIotVirtualDeviceNet net = netService.matchNetSet(identCode);
if (net != null) {
List<FIotVirtualDeviceModule> modules = moduleService.getModulesByNet(net.getId());
if (!modules.isEmpty()) {
//模组关联的设备
return modules;
}else{
log.error("==================网络模块为空:{}:{}===================", identCode,net.getId());
}
} else {
log.error("==================网络模块未识别:{}===================", identCode);
}
return new ArrayList<>();
}
/**
* 推送消息至设备的主题
* @param moduleStatusResultVo
*/
public void pubDeviceTopic(ModuleStatusResultVo moduleStatusResultVo,List<FIotVirtualDevice> devices) {
if(moduleStatusResultVo.getStatus()!=null && !moduleStatusResultVo.getStatus().isEmpty()){
if(!devices.isEmpty()){
for (FIotVirtualDevice device : devices) {
//推送至设别的上行主题
sendModbus(device.getUpperUrl(),null,JSONObject.toJSONString(moduleStatusResultVo));
}
}else{
log.error("xxxxxxxx设备为空跳过发送xxxxxxxxxx");
}
}else{
log.error("<==================trans数据为空跳过发送=================>");
}
}
@Override
public List<String> getAllMqttTopic() {
List<String> topics = new ArrayList<>();
//已部署设备中配置的主题
List<SurvDeviceDeploy> deploys = deviceDeployService.lambdaQuery()
.eq(SurvDeviceDeploy::getIsDel,0)
.eq(SurvDeviceDeploy::getRunStatus,0)
.eq(SurvDeviceDeploy::getProtocolType, IotProtocolType.MQTT.getCode())
.list();
if(!deploys.isEmpty()){
for (SurvDeviceDeploy deploy : deploys) {
if(StringUtils.isNotBlank(deploy.getDeviceUrl())){
topics.add(deploy.getDeviceUrl());
}
if(StringUtils.isNotBlank(deploy.getDeviceIotUrl())){
topics.add(deploy.getDeviceIotUrl());
}
}
}
//虚拟设备中需要订阅的主题
List<FIotVirtualDevice> devices = lambdaQuery().nested(wrapper->
wrapper.isNotNull(FIotVirtualDevice::getUpperUrl)
.or()
.isNotNull(FIotVirtualDevice::getLowerUrl)
).list();
if(!devices.isEmpty()){
for (FIotVirtualDevice device : devices) {
if(StringUtils.isNotBlank(device.getUpperUrl())){
topics.add(device.getUpperUrl());
}
if(StringUtils.isNotBlank(device.getLowerUrl())){
topics.add(device.getLowerUrl());
}
}
}
//物联网模块中的主题
List<FIotVirtualDeviceNet> nets = netService.lambdaQuery()
.nested(wrapper->
wrapper.isNotNull(FIotVirtualDeviceNet::getNetUpTopic)
.or()
.isNotNull(FIotVirtualDeviceNet::getNetDownTopic)
).list();
;
if(!nets.isEmpty()){
for (FIotVirtualDeviceNet net : nets) {
if(StringUtils.isNotBlank(net.getNetUpTopic())){
topics.add(net.getNetUpTopic());
}
if(StringUtils.isNotBlank(net.getNetDownTopic())){
topics.add(net.getNetDownTopic());
}
}
}
return topics;
}
@Override
public void processCache(DeviceActionVo deviceActionVo) {
//token校验
boolean isOk = checkToken(deviceActionVo);
if(isOk){
DeviceActionType actionType = DeviceActionType.valueOfCode(deviceActionVo.getActionType());
SurvDeviceDeploy deploy = deviceDeployService.getById(deviceActionVo.getDeployId());
if(deploy!=null){
switch (actionType){
case DEVICE_QUERY_ALL:
//检查缓存
ModuleStatusResultVo deviceAllChache = getDeviceCache(deploy.getDeployCode());
log.warn("============={}===检查间隔缓存======{}======",deploy.getDeployCode(),deviceAllChache);
if(deviceAllChache!=null){//缓存直接传入设备mqtt
FIotVirtualDevice device = getDeviceByIotCode(deploy.getDeployCode());
List<FIotVirtualDevice> devices = new ArrayList<>();
if(device!=null){
devices.add(device);
}
log.warn("============={}====间隔缓存推入蓝海主题:{}=============",deviceAllChache,devices.size());
pubDeviceTopic(deviceAllChache, devices);
}
break;
}
}
}else{
log.error("间隔非法的mqtt操作设备{},模组:{},类型:{},行为:{}",deviceActionVo.getDeployId(),deviceActionVo.getModuleId(),deviceActionVo.getActionType(),deviceActionVo.getCmdType());
}
}
//将modus处理为json
public ModuleStatusResultVo processHexToJson(ModbusResponseParser.ModbusResult modbusResult, List<FIotVirtualDeviceModule> modules){
FunctionCode functionCode = FunctionCode.valueOfCode(modbusResult.getFunctionCode());
ModuleStatusResultVo moduleStatusResultVo = null;
switch (functionCode){
case READ_COIL:
case READ_DISCRETE_INPUT:
moduleStatusResultVo = BitsToHex(modbusResult.getBits(),modules);
break;
case READ_HOLDING_REGISTER:
case READ_INPUT_REGISTER:
moduleStatusResultVo = ByteArrToHex(modbusResult.getValues(),modules);
break;
case WRITE_COIL:
case WRITE_HOLDING_REGISTER:
moduleStatusResultVo = ByteToHex(modbusResult.getAddress(),modbusResult.getValue(),modules);
break;
}
return moduleStatusResultVo;
}
public ModuleStatusResultVo BitsToHex(boolean[] bits,List<FIotVirtualDeviceModule> modules){
ModuleStatusResultVo moduleStatusResultVo = new ModuleStatusResultVo();
if(bits!=null && bits.length>0){
List<ModuleStatusDetailVo> detailVos = new ArrayList<>();
log.warn("开始解析modbus_bits为json数据长度{},模组数量:{}",bits.length ,modules.size());
//遍历对应 模组和寄存器对应关系
if(!modules.isEmpty()){
Map<Integer,String> moduleMap = new HashMap<>();
for (FIotVirtualDeviceModule module : modules) {
moduleMap.put(module.getRegisterNum(),module.getId());
}
for (int i = 0; i < bits.length; i++) {
String modbusId = moduleMap.get(i);
if(StringUtils.isNotBlank(modbusId)){
log.warn("==========bits寄存器序列{}id:{}===========",i,modbusId);
ModuleStatusDetailVo moduleStatusDetailVo = new ModuleStatusDetailVo();
moduleStatusDetailVo.setModuleId(modbusId);
moduleStatusDetailVo.setModuleStatus(transBitsToStatus(bits[i]));
detailVos.add(moduleStatusDetailVo);
}else{
log.warn("bits跳过未配置的寄存器序列{}",i);
}
}
}
moduleStatusResultVo.setStatus(detailVos);
}else{
log.error("跳过无数据bits解析");
}
return moduleStatusResultVo;
}
public ModuleStatusResultVo ByteToHex(Integer address,Integer bytes,List<FIotVirtualDeviceModule> modules){
ModuleStatusResultVo moduleStatusResultVo = new ModuleStatusResultVo();
if(bytes!=null){
List<ModuleStatusDetailVo> detailVos = new ArrayList<>();
ModuleStatusDetailVo moduleStatusDetailVo = new ModuleStatusDetailVo();
//遍历对应 模组和寄存器对应关系
if(!modules.isEmpty()){
Map<Integer,String> moduleMap = new HashMap<>();
for (FIotVirtualDeviceModule module : modules) {
moduleMap.put(module.getRegisterNum(),module.getId());
}
String modbusId = moduleMap.get(address);
if(StringUtils.isNotBlank(modbusId)){
moduleStatusDetailVo.setModuleId(modbusId);
moduleStatusDetailVo.setModuleStatus(transIntToStatus(bytes));
detailVos.add(moduleStatusDetailVo);
moduleStatusResultVo.setStatus(detailVos);
}else{
log.error("byte跳过未配置的寄存器序列 :{}",address);
}
}
}
return moduleStatusResultVo;
}
public ModuleStatusResultVo ByteArrToHex(int[] modbusBytes,List<FIotVirtualDeviceModule> modules){
ModuleStatusResultVo moduleStatusResultVo = new ModuleStatusResultVo();
if(modbusBytes!=null && modbusBytes.length>0){
List<ModuleStatusDetailVo> detailVos = new ArrayList<>();
log.warn("开始解析modbus为json数据长度{},模组数量:{}",modbusBytes.length ,modules.size());
//遍历对应 模组和寄存器对应关系
if(!modules.isEmpty()){
Map<Integer,String> moduleMap = new HashMap<>();
for (FIotVirtualDeviceModule module : modules) {
moduleMap.put(module.getRegisterNum(),module.getId());
}
for (int i = 0; i < modbusBytes.length; i++) {
String modbusId = moduleMap.get(i);
if(StringUtils.isNotBlank(modbusId)){
log.warn("==========寄存器序列:{}id:{}===========",i,modbusId);
ModuleStatusDetailVo moduleStatusDetailVo = new ModuleStatusDetailVo();
moduleStatusDetailVo.setModuleId(modbusId);
moduleStatusDetailVo.setModuleStatus(transIntToStatus(modbusBytes[i]));
detailVos.add(moduleStatusDetailVo);
}else{
log.warn("跳过未配置的寄存器序列:{}",i);
}
}
}
moduleStatusResultVo.setStatus(detailVos);
}else{
log.error("跳过无数据modbus解析");
}
return moduleStatusResultVo;
}
/**
* 将modbus十六进制 转为可读的模块状态
* @param hexStatus
* @return
*/
public String transIntToStatus(int hexStatus){
String status = IotControlType.valueOfCode(hexStatus+"").getCode();
return status;
}
private String transBitsToStatus(boolean bits) {
if(bits){
return IotControlType.EQ_ON.getCode();
}else {
return IotControlType.EQ_OFF.getCode();
}
}
/**
* 将十六进制的字符串值转为Integer
* @param variableValue
* @param module
* @return
*/
public Integer HexTransToInteger(String variableValue,FIotVirtualDeviceModule module){
Integer result = null;
IotControlType controlType = IotControlType.valueOfCode(variableValue);
switch (controlType){
case EQ_ON://
result = Integer.decode(module.getRegisterCmdOn());
break;
case EQ_OFF://
result = Integer.decode(module.getRegisterCmdOff());
break;
case EQ_STOP://
result = Integer.decode(module.getRegisterCmdStop());
break;
}
return result;
}
public boolean sendIt(String topic,String cmd){
boolean result = false;
try {
byte[] modbusFrame = Hex.decodeHex(cmd.replaceAll("\\s", ""));
result = sendModbus(topic,modbusFrame,null);
}catch (Exception e){
e.printStackTrace();
}
return result;
}
public boolean sendModbus(String topic,byte[] msgContent,String content){
try {
log.warn("modbus指令发送======主题:{}========指令:{}",topic,msgContent);
String cmdId = "";
if(StringUtils.isNotBlank(content)){
cmdId = toUniqueString(content);
}else if(msgContent!=null){
cmdId = toUniqueString(new String(msgContent));
}
int expireSeconds=3000;//锁3秒
String lockerId = TopicConstant.MQTT_CMD_LOCKER + cmdId;
if(StringUtils.isNotBlank(content)){
mqttCustomerClient.publish(topic,content);
}else if(msgContent!=null){
mqttCustomerClient.publish(topic,msgContent);
}
}catch (Exception e){
log.error("=====mqtt指令发送失败========{}",e.getMessage());
e.printStackTrace();
}
return Boolean.TRUE;
}
// 转换为大写十六进制无分隔
public static String stringToHexUpperCase(String input) {
StringBuilder hexBuilder = new StringBuilder();
byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
for (byte b : bytes) {
hexBuilder.append(String.format("%02X", b));
}
return hexBuilder.toString();
}
/**
* 将字节数组转换为带空格的十六进制字符串便于阅读
*/
public static String bytesToHexWithSpaces(byte[] bytes) {
StringBuilder hexBuilder = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
if (i > 0) {
hexBuilder.append(" ");
}
hexBuilder.append(String.format("%02X", bytes[i]));
}
return hexBuilder.toString();
}
public static String toUniqueString(String jsonString) {
try {
ObjectMapper mapper = new ObjectMapper();
// 2. 生成MD5哈希作为唯一标识
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(jsonString.getBytes());
// 3. 转换为十六进制字符串
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
hexString.append(String.format("%02x", b));
}
return hexString.toString();
} catch (Exception e) {
throw new RuntimeException("生成唯一字符串失败", e);
}
}
}

View File

@ -611,4 +611,16 @@ public class SurvDeviceDeployServiceImpl extends ServiceImpl<SurvDeviceDeployMap
return input.replaceAll("[^\\u4e00-\\u9fa5]", ""); return input.replaceAll("[^\\u4e00-\\u9fa5]", "");
} }
/**
* 根据设备号刷新更新时间
* @param deploys
*/
public void refreshLastSyncTimeByDeployCode(List<String> deploys) {
if (!deploys.isEmpty()) {
lambdaUpdate()
.eq(SurvDeviceDeploy::getRunStatus, 0)
.in(SurvDeviceDeploy::getDeployCode, deploys).set(SurvDeviceDeploy::getLastsyncTime, new Date()).update();
}
}
} }

View File

@ -479,4 +479,5 @@ public class HttpRequestUtils {
HttpHeaders headers1 = responseEntity.getHeaders();//获取到头信息 HttpHeaders headers1 = responseEntity.getHeaders();//获取到头信息
return responseEntity.getBody(); return responseEntity.getBody();
} }
} }

View File

@ -0,0 +1,152 @@
package org.jeecg.modules.appmana.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StreamUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.*;
/**
* request 工具类
*/
@Slf4j
public class HttpServletRequestUtil {
/**
* 获取request对象
*
* @return
*/
public static HttpServletRequest getRequest() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request;
}
/**
* 获取getRequestURI
*
* @return /sys/user/getInfo?id=1
*/
public static String getRequestURI() {
HttpServletRequest request = getRequest();
String queryString = request.getQueryString();
if (StrUtil.isBlank(queryString)) {
return request.getRequestURI();
}
return request.getRequestURI() + "?" + queryString;
}
/**
* 获取getRequestURI
*
* @return
*/
public static UserAgent getRequestUserAgent() {
HttpServletRequest request = getRequest();
UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
return userAgent;
}
public static String getRemoteIP() {
return getRemoteIP(getRequest());
}
public static String getRemoteIP(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 多次反向代理后会有多个IP值第一个为真实IP
int index = ip.indexOf(',');
if (index != -1) {
ip = ip.substring(0, index);
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
/**
* 取得请求头信息 name:value
*/
public static Map getHeaders() {
HttpServletRequest request = getRequest();
Map<String, String> map = new HashMap<>(32);
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
return map;
}
/**
* 获取请求体信息
*/
public static String getBody() {
HttpServletRequest request = getRequest();
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
return StreamUtils.copyToString(inputStream, Charset.forName("utf-8"));
} catch (IOException e) {
e.printStackTrace();
log.error("HttpServletRequest.getBody", e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
log.error("HttpServletRequest.getBody", e);
}
}
}
return StrUtil.EMPTY;
}
public static String getAllRequestInfo() {
StringBuilder sb = new StringBuilder();
sb.append("请求详情为:").append(StrUtil.CRLF);
sb.append("RemoteAddress: ").append(getRemoteIP()).append(StrUtil.CRLF);
sb.append("Method: ").append(getRequest().getMethod()).append(StrUtil.CRLF);
sb.append("URI: ").append(getRequestURI()).append(StrUtil.CRLF);
sb.append("Headers: ").append(StrUtil.join(StrUtil.CRLF + " ", mapToList(getHeaders()))).append(StrUtil.CRLF);
sb.append("Body: ").append(getBody()).append(StrUtil.CRLF);
return sb.toString();
}
private static List mapToList(Map parameters) {
List parametersList = new ArrayList();
parameters.forEach((name, value) -> {
parametersList.add(name + "=" + value);
});
return parametersList;
}
}

View File

@ -10,13 +10,15 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import java.util.Arrays;
@Slf4j @Slf4j
@Configuration @Configuration
@ConditionalOnProperty( @ConditionalOnProperty(
prefix = "iot.mq", prefix = "iot.mq",
name = "enabled", name = "enabled",
havingValue = "true", havingValue = "true",
matchIfMissing = false // 默认注册除非显式设置为 false matchIfMissing = true // 默认注册除非显式设置为 false
) )
public class MqttConfig { public class MqttConfig {
@ -42,9 +44,9 @@ public class MqttConfig {
@Bean//注入Spring @Bean//注入Spring
public MyMqttClient myMqttClient() { public MyMqttClient myMqttClient() {
MyMqttClient myMqttClient = new MyMqttClient(host, username, password, clientId, timeOut, keepAlive, clearSession); MyMqttClient myMqttClient = new MyMqttClient(host, username, password, clientId, timeOut, keepAlive, clearSession);
String activeProfile = env.getActiveProfiles()[0]; // String activeProfile = env.getActiveProfiles()[0];
//正式环境才连接mqtt //正式环境才连接mqtt
if(activeProfile.contains("prod")){ // if(activeProfile.contains("prod")){
log.warn("-------------正式环境,MQTT启动初始化---------"); log.warn("-------------正式环境,MQTT启动初始化---------");
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
try { try {
@ -62,9 +64,9 @@ public class MqttConfig {
} }
} }
} }
}else{ // }else{
log.warn("-------------非正式环境跳过Mqtt订阅---------"); // log.warn("-------------非正式环境跳过Mqtt订阅---------");
} // }
return myMqttClient; return myMqttClient;
} }

View File

@ -7,12 +7,9 @@ import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.jeecg.common.util.SpringContextUtils; import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.config.RedisDistributedLock2; import org.jeecg.modules.appmana.service.IFIotVirtualDeviceService;
import org.jeecg.modules.iot.enums.IotInerfaceTopicType; import org.jeecg.common.iot.enums.IotInerfaceTopicType;
import org.jeecg.modules.iot.o.dto.DTOMqttMessage; import org.jeecg.common.iot.up.DeviceActionVo;
import org.jeecg.modules.iot.o.mqtt.up.DeviceActionVo;
import org.jeecg.modules.iot.service.IFIotVirtualDeviceService;
import org.jeecg.modules.rocketmq.service.RocketMqService;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import java.util.List; import java.util.List;
@ -29,7 +26,6 @@ public class MyMqttCallback implements MqttCallbackExtended {
private static RedisTemplate redisTemplate = SpringContextUtils.getBean("redisTemplate", RedisTemplate.class); private static RedisTemplate redisTemplate = SpringContextUtils.getBean("redisTemplate", RedisTemplate.class);
private static RocketMqService rocketMqService = SpringContextUtils.getBean(RocketMqService.class);
private MyMqttClient myMqttClient; private MyMqttClient myMqttClient;
@ -126,11 +122,7 @@ public class MyMqttCallback implements MqttCallbackExtended {
DeviceActionVo deviceQueryActionVo = JSONObject.toJavaObject(JSONObject.parseObject(message), DeviceActionVo.class); DeviceActionVo deviceQueryActionVo = JSONObject.toJavaObject(JSONObject.parseObject(message), DeviceActionVo.class);
//设备响应处理查询控制 //设备响应处理查询控制
deviceService.processIotAction(deviceQueryActionVo); deviceService.processIotAction(deviceQueryActionVo);
//MQ模式
// DTOMqttMessage dtoMqttMessage = new DTOMqttMessage();
// dtoMqttMessage.setTopic(topic);
// dtoMqttMessage.setMessage(message);
// rocketMqService.sendMqttMessage(dtoMqttMessage);
}catch (Exception e){ }catch (Exception e){
log.error("======处理蓝海主题设备报错================"+e.getMessage()); log.error("======处理蓝海主题设备报错================"+e.getMessage());
} }

View File

@ -0,0 +1,46 @@
package org.jeecg.common.constant;
public interface TopicConstant {
/**
* AI统计消费主题
*/
String AI_DISPATCH_TOPIC = "ai_dispatch_topic";
/**
* AI统计消费标签
*/
String AI_DISPATCH_TAG = "ai_dispatch_tag";
/**
* AI消费组
*/
String AI_DISPATCH_GROUP = "ai_dispatch_group";
/**
* mqtt消费主题
*/
String MQTT_DISPATCH_TOPIC = "mqtt_dispatch_topic";
/**
* mqtt消费标签
*/
String MQTT_DISPATCH_TAG = "mqtt_dispatch_tag";
/**
* mqtt消费组
*/
String MQTT_DISPATCH_GROUP = "mqtt_dispatch_group";
/**
* redis 指令过滤头
*/
String MQTT_MESSAGE_FILTER = "mqtt_message_filter:";
/**
* redis 指令过滤头
*/
String MQTT_CMD_LOCKER = "mqtt_cmd_locker:";
}

View File

@ -0,0 +1,218 @@
package org.jeecg.common.entity;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.JdbcType;
import org.jeecg.common.mybatis.typehandler.JsonTypeHandler;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @Description: 设备操作记录
* @Author: jeecg-boot
* @Date: 2023-11-04
* @Version: V1.06
*/
@Data
@TableName("surv_device_opration")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "设备操作记录", description = "设备操作记录")
public class FDeviceOpration implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**
* 公司ID
*/
@Excel(name = "公司ID", width = 15)
@ApiModelProperty(value = "公司ID")
private String companyId;
/**
* 农场ID
*/
@Excel(name = "农场ID", width = 15)
@ApiModelProperty(value = "农场ID")
private String farmId;
/**
* 设备部署ID
*/
@Excel(name = "设备部署ID", width = 15)
@ApiModelProperty(value = "设备部署ID")
private String deployId;
/**
* 采集id
*/
@Excel(name = "采集id", width = 15)
@ApiModelProperty(value = "采集id")
private String gatherId;
/**
* 变量Id
*/
@Excel(name = "变量id", width = 15)
@ApiModelProperty(value = "变量Id")
private String variableId;
@Excel(name = "变量中文", width = 15)
@ApiModelProperty(value = "变量中文")
private String variableDes;
@Excel(name = "操作值", width = 15)
@ApiModelProperty(value = "操作值0断开1闭合")
private String variableValue;
@Excel(name = "操作标记", width = 15)
@ApiModelProperty(value = "操作标记launch=启动function=功能,参数=params")
private String variableMark;
/**
* 操作名称
*/
@Excel(name = "操作名称", width = 15)
@ApiModelProperty(value = "操作名称")
private String oprationName;
/**
* 操作结果 0失败1成功
*/
@Excel(name = "操作名称", width = 15)
@ApiModelProperty(value = "操作名称")
private Integer operationResult;
/**
* 操作人ID
*/
@Excel(name = "操作人ID", width = 15)
@ApiModelProperty(value = "操作人ID")
private String operatorUserId;
/**
* 操作人名称
*/
@Excel(name = "操作人名称", width = 15)
@ApiModelProperty(value = "操作人名称")
private String operatorUserName;
/**
* 操作人头像
*/
@Excel(name = "操作人头像", width = 15)
@ApiModelProperty(value = "操作人头像")
private String operatorUserAvatar;
/**
* 操作时间
*/
@Excel(name = "操作时间", width = 15)
@ApiModelProperty(value = "操作时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime operatorTime;
/**
* 指令原文
*/
@ApiModelProperty(value = "指令原文")
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR, value = "OPERATOR_CONTENT")
private JSONObject operatorContent;
/**
* 操作描述
*/
@Excel(name = "操作描述", width = 15)
@ApiModelProperty(value = "操作描述")
private String operatorDes;
/**
* 日志是否已经核算0否1是
*/
@Excel(name = "是否已经核算", width = 15)
@ApiModelProperty(value = "是否已经核算")
private Integer calStatus;
/**
* 租户号
*/
@ApiModelProperty(value = "租户号")
private String tenantId;
/**
* 乐观锁
*/
@ApiModelProperty(value = "乐观锁")
private Integer reVision;
/**
* 创建人
*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**
* 创建时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private java.util.Date createTime;
/**
* 更新人
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 逻辑删除
*/
@ApiModelProperty(value = "逻辑删除")
private Integer isDel;
/**
* 更新时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private java.util.Date updateTime;
@ApiModelProperty(value = "IP")
private String ip;
@ApiModelProperty(value = "浏览器标识")
private String agent;
// @TableField(exist = false)
// @DateTimeFormat(pattern="yyyy-MM-dd")
// private LocalDate beginTime;
//
// @TableField(exist = false)
// @DateTimeFormat(pattern="yyyy-MM-dd")
// private LocalDate endTime;
@TableField(exist = false)
private String alertTimes;
}

View File

@ -0,0 +1,118 @@
package org.jeecg.common.entity;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.JdbcType;
import org.jeecg.common.mybatis.typehandler.JsonTypeHandler;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 物联网设备协议表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.06
*/
@Data
@TableName("surv_iot_protocol")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="物联网设备协议表", description="物联网设备协议表")
public class FIotProtocol implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**协议名称*/
@Excel(name = "协议名称", width = 15)
@ApiModelProperty(value = "协议名称")
private String protocolName;
/**所属厂家*/
@Excel(name = "所属厂家", width = 15)
@ApiModelProperty(value = "所属厂家")
private String manufacturerId;
/**协议类型;1=设备协议*/
@Excel(name = "协议类型;1=设备协议", width = 15)
@ApiModelProperty(value = "协议类型;1=设备协议")
private Integer protocolType;
/**对接方式;mqtt,http,tcp*/
@Excel(name = "对接方式;mqtt,http,tcp", width = 15)
@ApiModelProperty(value = "对接方式;mqtt,http,tcp")
private String integrateType;
/**参数指令模板*/
@Excel(name = "参数指令模板", width = 15)
@ApiModelProperty(value = "参数指令模板")
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR, value = "CMD_STR")
private JSONObject cmdStr;
/**启动指令模板*/
@Excel(name = "启动指令模板", width = 15)
@ApiModelProperty(value = "启动指令模板")
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR, value = "LAUNCH_CMD_STR")
private JSONObject launchCmdStr;
/**停止指令模板*/
@Excel(name = "停止指令模板", width = 15)
@ApiModelProperty(value = "停止指令模板")
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR, value = "STOP_CMD_STR")
private JSONObject stopCmdStr;
/**排序*/
@Excel(name = "排序", width = 15)
@ApiModelProperty(value = "排序")
private Integer sortNo;
/**租户号*/
@Excel(name = "租户号", width = 15)
@ApiModelProperty(value = "租户号")
private String tenantId;
/**乐观锁*/
@Excel(name = "乐观锁", width = 15)
@ApiModelProperty(value = "乐观锁")
private Integer reVision;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**逻辑删除*/
@Excel(name = "逻辑删除", width = 15)
@ApiModelProperty(value = "逻辑删除")
private Integer isDel;
/**更新时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}

View File

@ -0,0 +1,192 @@
package org.jeecg.common.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @Description: 虚拟设备表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.06
*/
@Data
@TableName("surv_iot_virtual_device")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="虚拟设备表", description="虚拟设备表")
public class FIotVirtualDevice implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**企业id*/
@Excel(name = "企业id", width = 15)
@ApiModelProperty(value = "企业id")
private String companyId;
/**农场ID*/
@Excel(name = "农场ID", width = 15)
@ApiModelProperty(value = "农场ID")
private String farmId;
/**分组*/
@Excel(name = "分组", width = 15)
@ApiModelProperty(value = "分组")
private String groupId;
/**业务关联id*/
@Excel(name = "业务关联id", width = 15)
@ApiModelProperty(value = "业务关联id")
private String busId;
/**设备物联网ID*/
@Excel(name = "设备物联网ID", width = 15)
@ApiModelProperty(value = "设备物联网ID")
private String iotId;
/**设备物联网编号*/
@Excel(name = "设备物联网编号", width = 15)
@ApiModelProperty(value = "设备物联网编号")
private String iotCode;
/**备用配置项*/
@Excel(name = "备用配置项", width = 15)
@ApiModelProperty(value = "备用配置项")
private String iotParams;
/**设备名称*/
@Excel(name = "设备名称", width = 15)
@ApiModelProperty(value = "设备名称")
private String deviceName;
/**设备主类型*/
@Excel(name = "设备主类型", width = 15)
@ApiModelProperty(value = "设备主类型")
private String deviceType;
/**设备副类型*/
@Excel(name = "设备副类型", width = 15)
@ApiModelProperty(value = "设备副类型")
private String deviceSecType;
/**协议ID*/
@Excel(name = "协议ID", width = 15)
@ApiModelProperty(value = "协议ID")
private String protocolId;
/**启动指令模板*/
@Excel(name = "启动指令模板", width = 15)
@ApiModelProperty(value = "启动指令模板")
private String cmdStr;
/**纬度*/
@Excel(name = "纬度", width = 15)
@ApiModelProperty(value = "纬度")
private String deviceLat;
/**经度*/
@Excel(name = "经度", width = 15)
@ApiModelProperty(value = "经度")
private String deviceLong;
/**经纬度*/
@Excel(name = "经纬度", width = 15)
@ApiModelProperty(value = "经纬度")
private String deviceLonglat;
/**备注*/
@Excel(name = "备注", width = 15)
@ApiModelProperty(value = "备注")
private String deviceNotes;
/**运行状态支持*/
@Excel(name = "运行状态支持", width = 15)
@ApiModelProperty(value = "运行状态支持")
private Integer statusSupport;
/**控制支持*/
@Excel(name = "控制支持", width = 15)
@ApiModelProperty(value = "控制支持")
private Integer controlSupport;
/**灌溉记录支持*/
@Excel(name = "灌溉记录支持", width = 15)
@ApiModelProperty(value = "灌溉记录支持")
private Integer recordSupport;
/**下行mqtt主题*/
@Excel(name = "下行mqtt主题", width = 15)
@ApiModelProperty(value = "下行mqtt主题")
private String lowerUrl;
/**上行mqtt主题*/
@Excel(name = "上行mqtt主题", width = 15)
@ApiModelProperty(value = "上行mqtt主题")
private String upperUrl;
/**排序值*/
@Excel(name = "排序值", width = 15)
@ApiModelProperty(value = "排序值")
private Integer sortNo;
/**
* 是否启用
*/
@Excel(name = "是否启用", width = 15)
@ApiModelProperty(value = "是否启用")
private Integer isEnable;
/**租户号*/
@Excel(name = "租户号", width = 15)
@ApiModelProperty(value = "租户号")
private String tenantId;
/**乐观锁*/
@Excel(name = "乐观锁", width = 15)
@ApiModelProperty(value = "乐观锁")
private Integer reVision;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**逻辑删除*/
@Excel(name = "逻辑删除", width = 15)
@ApiModelProperty(value = "逻辑删除")
@TableLogic
private Integer isDel;
@TableField(exist = false)
private List<FIotVirtualDeviceModule> modules;
/**更新时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}

View File

@ -0,0 +1,106 @@
package org.jeecg.common.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 虚拟设备模块分组
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.06
*/
@Data
@TableName("surv_iot_virtual_device_group")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="虚拟设备模块分组", description="虚拟设备模块分组")
public class FIotVirtualDeviceGroup implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**企业id*/
@Excel(name = "企业id", width = 15)
@ApiModelProperty(value = "企业id")
private String companyId;
/**农场ID*/
@Excel(name = "农场ID", width = 15)
@ApiModelProperty(value = "农场ID")
private String farmId;
/**分组类型;module=模块分组*/
@Excel(name = "分组类型;module=模块分组", width = 15)
@ApiModelProperty(value = "分组类型;module=模块分组")
private String groupType;
/**设备分组*/
@Excel(name = "设备分组", width = 15)
@ApiModelProperty(value = "设备分组")
private String groupName;
/**分组图标*/
@Excel(name = "分组图标", width = 15)
@ApiModelProperty(value = "分组图标")
private String groupIcon;
/**分组图标*/
@Excel(name = "分组图标", width = 15)
@ApiModelProperty(value = "分组图标")
private String groupNotes;
/**排序值*/
@Excel(name = "排序值", width = 15)
@ApiModelProperty(value = "排序值")
private Integer sortNo;
/**租户号*/
@Excel(name = "租户号", width = 15)
@ApiModelProperty(value = "租户号")
private String tenantId;
/**乐观锁*/
@Excel(name = "乐观锁", width = 15)
@ApiModelProperty(value = "乐观锁")
private Integer reVision;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**逻辑删除*/
@Excel(name = "逻辑删除", width = 15)
@ApiModelProperty(value = "逻辑删除")
private Integer isDel;
/**更新时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}

View File

@ -0,0 +1,224 @@
package org.jeecg.common.entity;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.JdbcType;
import org.jeecg.common.mybatis.typehandler.JsonTypeHandler;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 虚拟设备模组表
* @Author: jeecg-boot
* @Date: 2025-05-15
* @Version: V1.06
*/
@Data
@TableName("surv_iot_virtual_device_module")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="虚拟设备模组表", description="虚拟设备模组表")
public class FIotVirtualDeviceModule implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**企业id*/
@Excel(name = "企业id", width = 15)
@ApiModelProperty(value = "企业id")
private String companyId;
/**农场ID*/
@Excel(name = "农场ID", width = 15)
@ApiModelProperty(value = "农场ID")
private String farmId;
/**设备ID*/
@Excel(name = "设备ID", width = 15)
@ApiModelProperty(value = "设备ID")
private String deviceId;
/**模块编号*/
@Excel(name = "模块编号", width = 15)
@ApiModelProperty(value = "模块编号")
private String moduleCode;
/**模块序号*/
@Excel(name = "模块序号", width = 15)
@ApiModelProperty(value = "模块序号")
private String moduleNum;
/**模组业务ID*/
@Excel(name = "模组业务ID", width = 15)
@ApiModelProperty(value = "模组业务ID")
private String moduleBusId;
/**模块分组id*/
@Excel(name = "模块分组id", width = 15)
@ApiModelProperty(value = "模块分组id")
private String moduleGroupId;
/**模块网络id*/
@Excel(name = "模块网络id", width = 15)
@ApiModelProperty(value = "模块网络id")
private String moduleNetId;
/**模块主类型;sensor=传感器meter=测量仪*/
@Excel(name = "模块主类型;sensor=传感器meter=测量仪", width = 15)
@ApiModelProperty(value = "模块主类型;sensor=传感器meter=测量仪")
private String moduleType;
/**模块类型;flows=流量计valve=电磁阀*/
@Excel(name = "模块类型;flows=流量计valve=电磁阀", width = 15)
@ApiModelProperty(value = "模块类型;flows=流量计valve=电磁阀")
private String moduleSecType;
/**模块名称*/
@Excel(name = "模块名称", width = 15)
@ApiModelProperty(value = "模块名称")
private String moduleName;
/**模块备注*/
@Excel(name = "模块备注", width = 15)
@ApiModelProperty(value = "模块备注")
private String moduleNotes;
/**1=虚拟模块2=物理模块*/
@Excel(name = "模块模式", width = 15)
@ApiModelProperty(value = "模块模式")
private String moduleMode;
/**模块虚拟状态*/
@Excel(name = "模块虚拟状态", width = 15)
@ApiModelProperty(value = "模块虚拟状态")
private String moduleVirtualStatus;
/**模块配置*/
@Excel(name = "模块配置", width = 15)
@ApiModelProperty(value = "模块配置")
@TableField(typeHandler = JsonTypeHandler.class, jdbcType = JdbcType.VARCHAR, value = "MODULE_PATH")
private JSONObject modulePath;
/**
* 寄存器类型 4=保持寄存器0=线圈1=离散输入
*/
@Excel(name = "寄存器类型", width = 15)
@ApiModelProperty(value = "寄存器类型")
private Integer registerType;
/**
* 寄存器序号 通讯地址
*/
@Excel(name = "寄存器序号(通讯地址)", width = 15)
@ApiModelProperty(value = "寄存器序号(通讯地址)")
private Integer registerNum;
/**
* 开指令
*/
@Excel(name = "开指令", width = 15)
@ApiModelProperty(value = "开指令")
private String registerCmdOn;
/**
* 关指令
*/
@Excel(name = "关指令", width = 15)
@ApiModelProperty(value = "关指令")
private String registerCmdOff;
/**
* 停指令
*/
@Excel(name = "停指令", width = 15)
@ApiModelProperty(value = "停指令")
private String registerCmdStop;
/**
* 回执状态开
*/
@Excel(name = "回执状态开", width = 15)
@ApiModelProperty(value = "回执状态开")
private String registerOn;
/**
* 回执状态关
*/
@Excel(name = "回执状态关", width = 15)
@ApiModelProperty(value = "回执状态关")
private String registerOff;
/**
* 回执状态停
*/
@Excel(name = "回执状态停", width = 15)
@ApiModelProperty(value = "回执状态停")
private String registerStop;
/**排序值*/
@Excel(name = "排序值", width = 15)
@ApiModelProperty(value = "排序值")
private Integer sortNo;
/**
* 是否启用
*/
@Excel(name = "是否启用", width = 15)
@ApiModelProperty(value = "是否启用")
private Integer isEnable;
/**租户号*/
@Excel(name = "租户号", width = 15)
@ApiModelProperty(value = "租户号")
private String tenantId;
/**乐观锁*/
@Excel(name = "乐观锁", width = 15)
@ApiModelProperty(value = "乐观锁")
private Integer reVision;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**逻辑删除*/
@Excel(name = "逻辑删除", width = 15)
@ApiModelProperty(value = "逻辑删除")
@TableLogic
private Integer isDel;
/**更新时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@TableField(exist = false)
@ApiModelProperty("设备状态,-1=获取失败0=关闭1=开启2=异常")
private String moduleStatus;
}

View File

@ -0,0 +1,145 @@
package org.jeecg.common.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 虚拟设备网络模块
* @Author: jeecg-boot
* @Date: 2025-09-06
* @Version: V1.06
*/
@Data
@TableName("surv_iot_virtual_device_net")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="虚拟设备网络模块", description="虚拟设备网络模块")
public class FIotVirtualDeviceNet implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**企业id*/
@Excel(name = "企业id", width = 15)
@ApiModelProperty(value = "企业id")
private String companyId;
/**农场ID*/
@Excel(name = "农场ID", width = 15)
@ApiModelProperty(value = "农场ID")
private String farmId;
/**入网方式;dtu=数据传输单元wifi=无线网络cable=有线网络mobile=移动网络*/
@Excel(name = "入网方式;dtu=数据传输单元wifi=无线网络cable=有线网络mobile=移动网络", width = 15)
@ApiModelProperty(value = "入网方式;dtu=数据传输单元wifi=无线网络cable=有线网络mobile=移动网络")
private String netType;
/**网络名称*/
@Excel(name = "网络名称", width = 15)
@ApiModelProperty(value = "网络名称")
private String netName;
/**网络识别码,用于识别对应的物联网单元*/
@Excel(name = "网络识别码", width = 15)
@ApiModelProperty(value = "网络识别码")
private String netIdentCode;
/**备注*/
@Excel(name = "备注", width = 15)
@ApiModelProperty(value = "备注")
private String netNotes;
/**上行mqtt主题*/
@Excel(name = "上行mqtt主题", width = 15)
@ApiModelProperty(value = "上行mqtt主题")
private String netUpTopic;
/**下行mqtt主题*/
@Excel(name = "下行mqtt主题", width = 15)
@ApiModelProperty(value = "下行mqtt主题")
private String netDownTopic;
/**传输口令*/
@Excel(name = "传输口令", width = 15)
@ApiModelProperty(value = "传输口令")
private String netPass;
/**传输密钥*/
@Excel(name = "传输密钥", width = 15)
@ApiModelProperty(value = "传输密钥")
private String netSecret;
/**备用配置1*/
@Excel(name = "备用配置1", width = 15)
@ApiModelProperty(value = "备用配置1")
private String netSetOne;
/**备用配置2*/
@Excel(name = "备用配置2", width = 15)
@ApiModelProperty(value = "备用配置2")
private String netSetTwo;
/**排序*/
@Excel(name = "排序", width = 15)
@ApiModelProperty(value = "排序")
private Integer sortNo;
/**
* 是否启用
*/
@Excel(name = "是否启用", width = 15)
@ApiModelProperty(value = "是否启用")
private Integer isEnable;
/**租户号*/
@Excel(name = "租户号", width = 15)
@ApiModelProperty(value = "租户号")
private String tenantId;
/**乐观锁*/
@Excel(name = "乐观锁", width = 15)
@ApiModelProperty(value = "乐观锁")
private Integer reVision;
/**创建人*/
@ApiModelProperty(value = "创建人")
private String createBy;
/**创建时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**更新人*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**逻辑删除*/
@Excel(name = "逻辑删除", width = 15)
@ApiModelProperty(value = "逻辑删除")
@TableLogic
private Integer isDel;
/**更新时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}

View File

@ -0,0 +1,124 @@
package org.jeecg.common.iot.Fertilizer;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class VOFertilizerStats {
@ApiModelProperty(value = "是否在线")
private Integer isOnline;
/**施肥压力*/
@ApiModelProperty(value = "施肥压力")
private String fePressure;
/**注肥流量*/
@ApiModelProperty(value = "注肥流量")
private String feInjectFlows;
/**pH值*/
@ApiModelProperty(value = "pH值")
private String fePh;
/**电导率*/
@ApiModelProperty(value = "电导率")
private String feDdl;
/**瞬时流量*/
@ApiModelProperty(value = "瞬时流量")
private String feInstantFlows;
/**累计流量*/
@ApiModelProperty(value = "累计流量")
private String feTotalFlows;
/**流量1*/
@ApiModelProperty(value = "流量1")
private String feFlowsOne;
/**流量2*/
@ApiModelProperty(value = "流量2")
private String feFlowsTwo;
/**流量3*/
@ApiModelProperty(value = "流量3")
private String feFlowsThree;
/**流量4*/
@ApiModelProperty(value = "流量4")
private String feFlowsFour;
/**流量5*/
@ApiModelProperty(value = "流量5")
private String feFlowsFive;
/**流量6*/
@ApiModelProperty(value = "流量6")
private String feFlowsSix;
/**流量7*/
@ApiModelProperty(value = "流量7")
private String feFlowsSeven;
/**流量8*/
@ApiModelProperty(value = "流量8")
private String feFlowsEight;
/**流量9*/
@ApiModelProperty(value = "流量9")
private String feFlowsNine;
/**流量10*/
@ApiModelProperty(value = "流量10")
private String feFlowsTen;
/**监测数据*/
@ApiModelProperty(value = "监测数据")
private List<VOFertilizerStatsArr> statsList;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "数据更新时间")
@JsonDeserialize(using = LocalDateTimeDeserializer.class) // 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class) // 序列化
private LocalDateTime dataDateTime;
/**运行状态支持*/
@ApiModelProperty(value = "运行状态支持")
private Integer statusSupport = 1;
/**控制支持*/
@ApiModelProperty(value = "控制支持")
private Integer controlSupport = 1;
/**灌溉记录支持*/
@ApiModelProperty(value = "灌溉记录支持")
private Integer recordSupport = 1;
/**上行mqtt主题*/
@ApiModelProperty(value = "上行mqtt主题")
private String upperUrl;
/**下行mqtt主题*/
@ApiModelProperty(value = "下行mqtt主题")
private String lowerUrl;
@ApiModelProperty(value = "协议编号,用于识别对接方式")
private String protocolCode;
@ApiModelProperty(value = "协议类型http=httpmqtt=mqtt")
private String protocolType;
}

View File

@ -0,0 +1,56 @@
package org.jeecg.common.iot.Fertilizer;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
public class VOFertilizerStatsArr {
@ApiModelProperty("设备编号")
private String deployId;
@ApiModelProperty("监测类型")
private String eleType;
@ApiModelProperty("监测项名称")
private String eleName;
@ApiModelProperty("监测项字段名")
private String eleItem;
@ApiModelProperty("监测项图标名称")
private String eleIcon;
@ApiModelProperty("颜色")
private String eleColor;
@ApiModelProperty("监测项图标文件夹")
private String eleIconFolder;
@ApiModelProperty("监测项值")
private String eleValue;
@ApiModelProperty("监测项单位")
private String eleUnit;
@ApiModelProperty("更新时间")
private String lastUpdate;
@ApiModelProperty("h5图标路径")
private String h5IconPath;
@ApiModelProperty("中台图标路径")
private String midIconPath;
@ApiModelProperty("app图标路径")
private String appIconPath;
@ApiModelProperty("大屏图标路径")
private String bsIconPath;
@ApiModelProperty("大屏图标路径2")
private String bsIconPath2;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "数据更新时间")
@JsonDeserialize(using = LocalDateTimeDeserializer.class) // 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class) // 序列化
private LocalDateTime dataDateTime;
}

View File

@ -0,0 +1,27 @@
package org.jeecg.common.iot.common;
import lombok.Data;
import org.jeecg.common.entity.SurvDeviceDeploy;
@Data
public class DeviceLogVo {
/*设备id*/
private SurvDeviceDeploy deploy;
/*操作人*/
private LoginUser2 loginUser;
/*指令key*/
private String variableName;
/*指令中文*/
private String variableDes;
/*指令值*/
private String variableValue;
/*指令简单说明如设备x 开*/
private String actions;
/*详细日志如用户xx x点x分 操作设备 x 开*/
private String operationDetail;
/*操作结果*/
private boolean operationResult;
/*核算结果*/
private Integer calStatus = 0;
/*是否处理request mqtt等连接*/
private boolean processRequest = true;
}

View File

@ -0,0 +1,138 @@
package org.jeecg.common.iot.common;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* <p>
* 在线用户信息
* </p>
*
* @Author scott
* @since 2018-12-20
*/
@Data
public class LoginUser2 {
/**
* 登录人id
*/
private String id;
/**
* 登录人账号
*/
private String username;
/**
* 登录人名字
*/
private String realname;
/**
* 登录人密码
*/
private String password;
/**
* 当前登录部门code
*/
private String orgCode;
/**
* 头像
*/
private String avatar;
/**
* 生日
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
/**
* 性别1 2
*/
private Integer sex;
/**
* 电子邮件
*/
private String email;
/**
* 电话
*/
private String phone;
/**
* 状态(1正常 2冻结
*/
private Integer status;
private Integer delFlag;
/**
* 同步工作流引擎1同步0不同步
*/
private Integer activitiSync;
/**
* 创建时间
*/
private Date createTime;
/**
* 身份1 普通员工 2 上级
*/
private Integer userIdentity;
/**
* 管理部门ids
*/
private String departIds;
/**
* 职务关联职务表
*/
private String post;
/**
* 座机号
*/
private String telephone;
/** 多租户ids临时用不持久化数据库(数据库字段不存在) */
private String relTenantIds;
/**设备id uniapp推送用*/
private String clientId;
/**
* 当前登录租户
*/
private Integer loginTenantId;
//(name = "用户类型(1系统2农业前端3专家)", width = 15)
private Integer type;
//腾讯IM同步状态
private Boolean imstatus = false;
//农业角色ID
//角色ID
private String roleId;
//角色名称
private String roleName;
//企业系统logo
private String companySystemLogo;
// /**
// * 当前登录租户
// */
// private String companyName;
}

View File

@ -0,0 +1,51 @@
package org.jeecg.common.iot.enums;
/**
* 设备操作类型枚举
*/
public enum DeviceActionType {
DEVICE_QUERY_ALL("1","查询所有"),
DEVICE_QUERY_S("2","查询单个"),
DEVICE_CONTROL("3","控制设备"),
OTHER("99","其他")
;
DeviceActionType(String code, String desc) {
this.code = code;
this.desc = desc;
}
private String code;
private String desc;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 根据type获取枚举
*
* @return
*/
public static DeviceActionType valueOfCode(String code) {
for (DeviceActionType e : DeviceActionType.values()) {
if (e.getCode().equals(code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,39 @@
package org.jeecg.common.iot.enums;
import java.util.Objects;
/**
* 功能码枚举
*/
public enum FunctionCode {
READ_COIL(0x01), // 读线圈
READ_DISCRETE_INPUT(0x02), // 读离散输入
READ_HOLDING_REGISTER(0x03), // 读保持寄存器
READ_INPUT_REGISTER(0x04), // 读输入寄存器
WRITE_COIL(0x05), // 写单个线圈
WRITE_HOLDING_REGISTER(0x06), // 写单个保持寄存器
OTHER(0x99);
private final int code;
FunctionCode(int code) {
this.code = code;
}
public byte getCode() {
return (byte) code;
}
/**
* 根据type获取枚举
*
* @return
*/
public static FunctionCode valueOfCode(int code) {
for (FunctionCode e : FunctionCode.values()) {
if (Objects.equals(e.code, code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,51 @@
package org.jeecg.common.iot.enums;
/**
* 物联网设备控制枚举
*/
public enum IotControlType {
EQ_OFF("0",""),
EQ_ON("1",""),
EQ_STOP("2",""),
OTHER("other","其他")
;
IotControlType(String code, String desc) {
this.code = code;
this.desc = desc;
}
private String code;
private String desc;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 根据type获取枚举
*
* @return
*/
public static IotControlType valueOfCode(String code) {
for (IotControlType e : IotControlType.values()) {
if (e.getCode().equals(code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,52 @@
package org.jeecg.common.iot.enums;
/**
* 物联网设备主题头类型枚举
*/
public enum IotInerfaceTopicType {
DTU_TOPIC("/pub-","厂家DTU模块头上行"),
LH_IOT_TOPIC_UP("/lh-iot-up","蓝海虚拟设备头上行"),
LH_IOT_TOPIC_DOWN("/lh-iot-down","蓝海虚拟设备头下行"),
API_TOPIC("/api-","厂家api头"),
OTHER("other","其他")
;
IotInerfaceTopicType(String code, String desc) {
this.code = code;
this.desc = desc;
}
private String code;
private String desc;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 根据type获取枚举
*
* @return
*/
public static IotInerfaceTopicType valueOfCode(String code) {
for (IotInerfaceTopicType e : IotInerfaceTopicType.values()) {
if (e.getCode().equals(code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,56 @@
package org.jeecg.common.iot.enums;
/**
* 物联网厂家枚举
*/
public enum IotManufacturerEnum {
XPH("xph","武汉新普惠科技有限公司"),
OKQ("okq","郑州欧柯奇仪器制造有限公司"),
YunFei("yf","河南云飞科技发展有限公司"),
BoYun("by","南通博云物联网技术有限公司"),
Flexem("flexem","上海繁易信息科技股份有限公司"),
YouRen("YouRen","山东有人物联网股份有限公司"),
TuYa("TuYa","杭州涂鸦信息技术有限公司"),
RenKe("RenKe","山东仁科测控技术有限公司"),
OTHER("other","其他")
;
IotManufacturerEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
private String code;
private String desc;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 根据type获取枚举
*
* @return
*/
public static IotManufacturerEnum valueOfCode(String code) {
for (IotManufacturerEnum e : IotManufacturerEnum.values()) {
if (e.getCode().equals(code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,51 @@
package org.jeecg.common.iot.enums;
/**
* 物联网设备协议类型枚举
*/
public enum IotProtocolType {
MQTT("mqtt","mqtt协议"),
HTTP("http","http协议"),
BLANK("local","无协议"),
OTHER("other","其他")
;
IotProtocolType(String code, String desc) {
this.code = code;
this.desc = desc;
}
private String code;
private String desc;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 根据type获取枚举
*
* @return
*/
public static IotProtocolType valueOfCode(String code) {
for (IotProtocolType e : IotProtocolType.values()) {
if (e.getCode().equals(code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,9 @@
package org.jeecg.common.iot.enums;
/**
* 读写类型枚举
*/
public enum RWType {
READ, // 读操作
WRITE // 写操作
}

View File

@ -0,0 +1,52 @@
package org.jeecg.common.iot.enums;
/**
* 寄存器类型枚举
*/
public enum RegisterType {
COIL(0,"线圈"), // 线圈可读写单个位
DISCRETE_INPUT(1,"离散输入"), // 离散输入只读单个位
INPUT_REGISTER(3,"输入寄存器"), // 输入寄存器只读2字节
HOLDING_REGISTER(4,"保持寄存器"), // 保持寄存器可读写2字节
OTHER(99,"其他")
;
RegisterType(Integer code,String desc) {
this.code = code;
this.desc = desc;
}
private Integer code;
private String desc;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 根据type获取枚举
*
* @return
*/
public static RegisterType valueOfCode(Integer code) {
for (RegisterType e : RegisterType.values()) {
if (e.getCode().equals(code)) {
return e;
}
}
return OTHER;
}
}

View File

@ -0,0 +1,21 @@
package org.jeecg.common.iot.up;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 设备查询实体
*/
@Data
public class DeviceActionVo {
@ApiModelProperty("设备ID")
private String deployId;
@ApiModelProperty("行为类型,查询所有=1,查询单个=2,控制设备=3")
private String actionType;
@ApiModelProperty("控制类型actionType=3时传入0=关1=开2=停")
private String cmdType;
@ApiModelProperty("模组idactionType=2或3时传入")
private String moduleId;
@ApiModelProperty("token")
private String token;
}

View File

@ -0,0 +1,12 @@
package org.jeecg.common.iot.up;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ModuleStatusDetailVo {
@ApiModelProperty("模组id")
private String moduleId;
@ApiModelProperty("开关状态")
private String moduleStatus;
}

View File

@ -0,0 +1,10 @@
package org.jeecg.common.iot.up;
import lombok.Data;
import java.util.List;
@Data
public class ModuleStatusResultVo {
List<ModuleStatusDetailVo> status;
}

View File

@ -0,0 +1,16 @@
package org.jeecg.common.iot.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class DeviceControlResultVo {
@ApiModelProperty("设备执行结果")
private boolean actionResult;
@ApiModelProperty("设备信息")
private String deviceName;
@ApiModelProperty("设备键值")
private String deviceKey;
@ApiModelProperty("设备状态")
private String deviceStatus;
}

View File

@ -0,0 +1,11 @@
package org.jeecg.common.iot.vo;
import lombok.Data;
import org.jeecg.common.entity.SurvDeviceDeploy;
@Data
public class VOCmdPack {
private SurvDeviceDeploy deploy;
private String variableName;
private String variableValue;
}

View File

@ -0,0 +1,8 @@
package org.jeecg.common.iot.vo;
import lombok.Data;
@Data
public class VOCmdPackQ {
private String variableName;
}

View File

@ -0,0 +1,16 @@
package org.jeecg.common.iot.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class VODeviceCmd {
@ApiModelProperty("设备部署id")
private String deployId;
@ApiModelProperty("指令")
private String variableName;
@ApiModelProperty("指令值")
private String variableValue;
@ApiModelProperty("授权密钥,除大屏外勿传")
private String auths;
}

View File

@ -0,0 +1,17 @@
package org.jeecg.common.iot.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
public class VODeviceCmdQ {
@ApiModelProperty("设备部署id")
private String deployId;
@ApiModelProperty("指令集合")
private List<VOCmdPackQ> cmdPacks;
@ApiModelProperty("授权密钥,除大屏外勿传")
private String auths;
}

View File

@ -0,0 +1,134 @@
package org.jeecg.common.util;
import org.jeecg.common.iot.enums.FunctionCode;
import org.jeecg.common.iot.enums.RWType;
import org.jeecg.common.iot.enums.RegisterType;
public class ModbusCommandUtil {
/**
* 通过枚举获取功能码
*/
public static FunctionCode getFunctionCode(RegisterType regType, RWType rwType) {
switch (regType) {
case COIL:
return rwType == RWType.READ ? FunctionCode.READ_COIL : FunctionCode.WRITE_COIL;
case DISCRETE_INPUT:
if (rwType == RWType.READ) return FunctionCode.READ_DISCRETE_INPUT;
break;
case INPUT_REGISTER:
if (rwType == RWType.READ) return FunctionCode.READ_INPUT_REGISTER;
break;
case HOLDING_REGISTER:
return rwType == RWType.READ ? FunctionCode.READ_HOLDING_REGISTER : FunctionCode.WRITE_HOLDING_REGISTER;
}
throw new IllegalArgumentException("不支持的寄存器类型或读写类型");
}
/**
* 构建数据区
*/
private static byte[] buildDataArea(RWType rwType, int regAddr, Integer value, Integer quantity) {
if (rwType == RWType.READ) {
int qty = (quantity == null) ? 1 : quantity;
return new byte[]{
(byte) ((regAddr >> 8) & 0xFF),
(byte) (regAddr & 0xFF),
(byte) ((qty >> 8) & 0xFF),
(byte) (qty & 0xFF)
};
} else {
if (value == null)
throw new IllegalArgumentException("写操作必须提供value");
return new byte[]{
(byte) ((regAddr >> 8) & 0xFF),
(byte) (regAddr & 0xFF),
(byte) ((value >> 8) & 0xFF),
(byte) (value & 0xFF)
};
}
}
/**
* 构建报文不带CRC
*/
private static byte[] buildFrame(int slaveAddr, FunctionCode funcCode, byte[] data) {
byte[] frame = new byte[2 + data.length];
frame[0] = (byte) (slaveAddr & 0xFF);
frame[1] = funcCode.getCode();
System.arraycopy(data, 0, frame, 2, data.length);
return frame;
}
/**
* 添加CRC校验
*/
private static byte[] addCRC(byte[] frame) {
byte[] crc = crc16(frame);
byte[] command = new byte[frame.length + 2];
System.arraycopy(frame, 0, command, 0, frame.length);
command[command.length - 2] = crc[0];
command[command.length - 1] = crc[1];
return command;
}
/**
* 计算MODBUS CRC16
*/
public static byte[] crc16(byte[] data) {
int crc = 0xFFFF;
for (byte b : data) {
crc ^= (b & 0xFF);
for (int i = 0; i < 8; i++) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return new byte[]{(byte) (crc & 0xFF), (byte) ((crc >> 8) & 0xFF)};
}
public static String buildCommand(
int slaveAddr,
RegisterType regType,
RWType rwType,
int regAddr,
Integer value,
Integer quantity
) {
FunctionCode funcCode = getFunctionCode(regType, rwType);
byte[] data = buildDataArea(rwType, regAddr, value, quantity);
byte[] frame = buildFrame(slaveAddr, funcCode, data);
return bytesToHex(addCRC(frame));
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X ", b));
}
return sb.toString().trim();
}
// 示例
public static void main(String[] args) {
// // 读保持寄存器
// byte[] cmd1 = buildCommand(1, RegisterType.HOLDING_REGISTER, RWType.READ, 1, null, 2);
// System.out.println("读保持寄存器: " + bytesToHex(cmd1));
// // 写线圈
// byte[] cmd2 = buildCommand(1, RegisterType.COIL, RWType.WRITE, 5, 0xFF00, null);
// System.out.println("写线圈: " + bytesToHex(cmd2));
String hexString = "0xFF00";
int value = Integer.decode(hexString);
String cmd1 = buildCommand(1, RegisterType.HOLDING_REGISTER, RWType.READ, 1, null, 2);
System.out.println("读保持寄存器: " + cmd1);
// 写线圈
String cmd2 = buildCommand(1, RegisterType.COIL, RWType.WRITE, 0, value, null);
System.out.println("写线圈: " + cmd2);
}
}

View File

@ -0,0 +1,198 @@
package org.jeecg.common.util;
import java.util.Arrays;
public class ModbusResponseParser {
/**
* 解析Modbus响应报文
* @param response modbus响应字节数组
* @return 解析结果ModbusResult对象
*/
public static ModbusResult parse(byte[] response) {
if (response == null || response.length < 5) {
return ModbusResult.error("响应数据过短或为null");
}
int slaveId = response[0] & 0xFF;
int functionCode = response[1] & 0xFF;
// 检查异常响应
if ((functionCode & 0x80) != 0) {
int exceptionCode = response[2] & 0xFF;
return ModbusResult.error("从站返回异常响应,异常码:" + exceptionCode);
}
// 处理读保持寄存器0x03和输入寄存器0x04
if (functionCode == 0x03 || functionCode == 0x04) {
int byteCount = response[2] & 0xFF;
if (response.length != byteCount + 5) {
return ModbusResult.error("字节数或响应长度无效");
}
int registerCount = byteCount / 2;
int[] values = new int[registerCount];
for (int i = 0; i < registerCount; i++) {
int hi = response[3 + i * 2] & 0xFF;
int lo = response[4 + i * 2] & 0xFF;
values[i] = (hi << 8) | lo;
}
if (registerCount == 1) {
return ModbusResult.success(slaveId, functionCode, new int[]{values[0]});
} else {
return ModbusResult.success(slaveId, functionCode, values);
}
}
// 处理读线圈0x01和离散输入0x02
if (functionCode == 0x01 || functionCode == 0x02) {
int byteCount = response[2] & 0xFF;
if (response.length != byteCount + 5) {
return ModbusResult.error("字节数或响应长度无效");
}
boolean[] bits = new boolean[byteCount * 8];
for (int i = 0; i < byteCount; i++) {
for (int bit = 0; bit < 8; bit++) {
bits[i * 8 + bit] = ((response[3 + i] >> bit) & 0x01) != 0;
}
}
return ModbusResult.success(slaveId, functionCode, bits);
}
// 处理写单个线圈0x05或写单个寄存器0x06
if (functionCode == 0x05 || functionCode == 0x06) {
int address = ((response[2] & 0xFF) << 8) | (response[3] & 0xFF);
int value = ((response[4] & 0xFF) << 8) | (response[5] & 0xFF);
return ModbusResult.successValue(slaveId, functionCode,address, value);
}
// 处理写多个线圈/寄存器0x0F, 0x10
if (functionCode == 0x0F || functionCode == 0x10) {
int address = ((response[2] & 0xFF) << 8) | (response[3] & 0xFF);
int count = ((response[4] & 0xFF) << 8) | (response[5] & 0xFF);
return ModbusResult.success(slaveId, functionCode, address, count);
}
return ModbusResult.error("不支持的功能码:" + functionCode);
}
/**
* Modbus结果实体类
*/
public static class ModbusResult {
private boolean success;
private String errorMsg;
private int slaveId;
private int functionCode;
private Integer value; // 单个寄存器值
private int[] values; // 多个寄存器值
private boolean[] bits; // bit数组
private Integer address;
private Integer count;
public static ModbusResult successValue(int slaveId, int functionCode,int address, int value) {
ModbusResult r = new ModbusResult();
r.success = true;
r.slaveId = slaveId;
r.functionCode = functionCode;
r.value = value;
r.address = address;
return r;
}
public static ModbusResult success(int slaveId, int functionCode, int[] values) {
ModbusResult r = new ModbusResult();
r.success = true;
r.slaveId = slaveId;
r.functionCode = functionCode;
r.values = values;
return r;
}
public static ModbusResult success(int slaveId, int functionCode, boolean[] bits) {
ModbusResult r = new ModbusResult();
r.success = true;
r.slaveId = slaveId;
r.functionCode = functionCode;
r.bits = bits;
return r;
}
public static ModbusResult success(int slaveId, int functionCode, int address, int count) {
ModbusResult r = new ModbusResult();
r.success = true;
r.slaveId = slaveId;
r.functionCode = functionCode;
r.address = address;
r.count = count;
return r;
}
public static ModbusResult error(String msg) {
ModbusResult r = new ModbusResult();
r.success = false;
r.errorMsg = msg;
return r;
}
// Getter与toString方法
public boolean isSuccess() { return success; }
public String getErrorMsg() { return errorMsg; }
public int getSlaveId() { return slaveId; }
public int getFunctionCode() { return functionCode; }
public Integer getValue() { return value; }
public int[] getValues() { return values; }
public boolean[] getBits() { return bits; }
public Integer getAddress() { return address; }
public Integer getCount() { return count; }
@Override
public String toString() {
if (!success) {
return "ModbusResult{error='" + errorMsg + "'}";
}
StringBuilder sb = new StringBuilder("ModbusResult{slaveId=" + slaveId + ", functionCode=" + functionCode);
if (value != null) sb.append(", value=").append(value);
if (values != null) sb.append(", values=").append(Arrays.toString(values));
if (bits != null) sb.append(", bits=").append(Arrays.toString(bits));
if (address != null) sb.append(", address=").append(address);
if (count != null) sb.append(", count=").append(count);
sb.append('}');
return sb.toString();
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
/**
* 测试主方法
*/
public static void main(String[] args) {
// 示例1读单个寄存器响应 01 03 02 00 0A CRC CRC
// byte[] response1 = new byte[]{0x01, 0x03, 0x02, 0x00, 0x0A, 0x00, 0x00};
// System.out.println("读单个寄存器:" + parse(response1));
//
// // 示例2读多个寄存器响应 01 03 04 00 0A 01 02 CRC CRC
// // 0103 0800 0000 0000 0000 0095 d7
// byte[] response2 = new byte[]{0x01, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,(byte)0x95,(byte)0xd7};
// System.out.println("读多个寄存器:" + parse(response2));
//
// // 示例3异常响应 01 83 02 CRC CRC
//
// byte[] response3 = new byte[]{0x01, (byte)0x83, 0x02, 0x00, 0x00};
// System.out.println("异常响应:" + parse(response3));
//
// // 示例4读多个线圈响应 01 01 01 55 CRC CRC
// byte[] response4 = new byte[]{0x01, 0x01, 0x01, 0x55, 0x00, 0x00};
// System.out.println("读多个线圈:" + parse(response4));
// 示例1读单个寄存器响应 01 03 02 00 0A CRC CRC
byte[] response1 = new byte[]{0x01, 0x06, (byte) 0xCA, 0x00, 0x00, (byte) 0x89, (byte) 0xCA};
System.out.println("读单个寄存器:" + bytesToHex(response1));
}
}