From 4a4ac3670994a3a629dbbec12ad29d4dfccb5577 Mon Sep 17 00:00:00 2001
From: chenshuichuan <1154693969@qq.com>
Date: Wed, 29 May 2024 15:04:54 +0800
Subject: [PATCH] add iot and machine
---
pom.xml | 1 +
.../module/iot/enums/ErrorCodeConstants.java | 13 +-
.../admin/device/DeviceController.java | 138 +++++++++++
.../admin/device/vo/DevicePageReqVO.java | 103 ++++++++
.../admin/device/vo/DeviceRespVO.java | 144 +++++++++++
.../admin/device/vo/DeviceSaveReqVO.java | 99 ++++++++
.../admin/formula/FormulaController.java | 138 +++++++++++
.../admin/formula/vo/FormulaPageReqVO.java | 43 ++++
.../admin/formula/vo/FormulaRespVO.java | 55 +++++
.../admin/formula/vo/FormulaSaveReqVO.java | 38 +++
.../admin/gateway/GatewayController.java | 138 +++++++++++
.../admin/gateway/vo/GatewayPageReqVO.java | 49 ++++
.../admin/gateway/vo/GatewayRespVO.java | 63 +++++
.../admin/gateway/vo/GatewaySaveReqVO.java | 43 ++++
.../IotOrganizationController.java | 93 +++++++
.../vo/IotOrganizationListReqVO.java | 47 ++++
.../vo/IotOrganizationRespVO.java | 66 +++++
.../vo/IotOrganizationSaveReqVO.java | 43 ++++
.../admin/kanban/KanbanController.java | 94 +++++++
.../admin/kanban/vo/KanbanPageReqVO.java | 42 ++++
.../admin/kanban/vo/KanbanRespVO.java | 54 ++++
.../admin/kanban/vo/KanbanSaveReqVO.java | 36 +++
.../dataobject/device/DeviceAttributeDO.java | 177 ++++++++++++++
.../iot/dal/dataobject/device/DeviceDO.java | 159 ++++++++++++
.../iot/dal/dataobject/formula/FormulaDO.java | 61 +++++
.../dataobject/formula/FormulaDetailDO.java | 83 +++++++
.../iot/dal/dataobject/gateway/GatewayDO.java | 69 ++++++
.../iotorganization/IotOrganizationDO.java | 77 ++++++
.../iot/dal/dataobject/kanban/KanbanDO.java | 61 +++++
.../mysql/device/DeviceAttributeMapper.java | 30 +++
.../iot/dal/mysql/device/DeviceMapper.java | 60 +++++
.../mysql/formula/FormulaDetailMapper.java | 30 +++
.../iot/dal/mysql/formula/FormulaMapper.java | 33 +++
.../iot/dal/mysql/gateway/GatewayMapper.java | 35 +++
.../IotOrganizationMapper.java | 43 ++++
.../iot/dal/mysql/kanban/KanbanMapper.java | 31 +++
.../config/SecurityConfiguration.java | 2 +-
.../web/config/IotWebConfiguration.java | 24 ++
.../iot/framework/web/package-info.java | 4 +
.../iot/service/device/DeviceService.java | 98 ++++++++
.../iot/service/device/DeviceServiceImpl.java | 127 ++++++++++
.../iot/service/formula/FormulaService.java | 97 ++++++++
.../service/formula/FormulaServiceImpl.java | 126 ++++++++++
.../iot/service/gateway/GatewayService.java | 96 ++++++++
.../service/gateway/GatewayServiceImpl.java | 125 ++++++++++
.../IotOrganizationService.java | 55 +++++
.../IotOrganizationServiceImpl.java | 133 ++++++++++
.../iot/service/kanban/KanbanService.java | 54 ++++
.../iot/service/kanban/KanbanServiceImpl.java | 76 ++++++
.../resources/mapper/device/DeviceMapper.xml | 12 +
.../mapper/formula/FormulaMapper.xml | 12 +
.../mapper/gateway/GatewayMapper.xml | 12 +
.../iotorganization/IotOrganizationMapper.xml | 12 +
.../resources/mapper/kanban/KanbanMapper.xml | 12 +
.../service/device/DeviceServiceImplTest.java | 231 ++++++++++++++++++
.../formula/FormulaServiceImplTest.java | 160 ++++++++++++
.../gateway/GatewayServiceImplTest.java | 168 +++++++++++++
.../IotOrganizationServiceImplTest.java | 165 +++++++++++++
.../service/kanban/KanbanServiceImplTest.java | 150 ++++++++++++
.../src/test/resources/sql/clean.sql | 24 +-
.../src/test/resources/sql/create_tables.sql | 217 +++++++++++++++-
.../module/mes/enums/ErrorCodeConstants.java | 6 +
.../machine/MachineComponentController.java | 93 +++++++
.../machine/vo/MachineComponentListReqVO.java | 60 +++++
.../machine/vo/MachineComponentRespVO.java | 81 ++++++
.../machine/vo/MachineComponentSaveReqVO.java | 62 +++++
.../machine/MachineComponentDO.java | 92 +++++++
.../mysql/machine/MachineComponentMapper.java | 47 ++++
.../machine/MachineComponentService.java | 56 +++++
.../machine/MachineComponentServiceImpl.java | 138 +++++++++++
.../mapper/machine/MachineComponentMapper.xml | 12 +
.../MachineComponentServiceImplTest.java | 181 ++++++++++++++
yudao-server/pom.xml | 6 +
.../server/controller/DefaultController.java | 11 +-
74 files changed, 5511 insertions(+), 15 deletions(-)
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePageReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceRespVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceSaveReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/FormulaController.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaPageReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaRespVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaSaveReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/GatewayController.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayPageReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayRespVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewaySaveReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/IotOrganizationController.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationListReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationRespVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationSaveReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/KanbanController.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanPageReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanRespVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanSaveReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceAttributeDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDetailDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/gateway/GatewayDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/iotorganization/IotOrganizationDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/kanban/KanbanDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceAttributeMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaDetailMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/gateway/GatewayMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/iotorganization/IotOrganizationMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/kanban/KanbanMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/config/IotWebConfiguration.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/package-info.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImpl.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImpl.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImpl.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/formula/FormulaMapper.xml
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/gateway/GatewayMapper.xml
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotorganization/IotOrganizationMapper.xml
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/kanban/KanbanMapper.xml
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImplTest.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImplTest.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImplTest.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImplTest.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/MachineComponentController.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentListReqVO.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentRespVO.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentSaveReqVO.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/machine/MachineComponentDO.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/machine/MachineComponentMapper.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentService.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImpl.java
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/machine/MachineComponentMapper.xml
create mode 100644 yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImplTest.java
diff --git a/pom.xml b/pom.xml
index ceefaaf86..dd007f4d2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
yudao-module-crm
yudao-module-erp
yudao-module-mes
+ yudao-module-iot
${project.artifactId}
diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
index 1acd4d78b..afbcc133e 100644
--- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
+++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -10,6 +10,17 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
public interface ErrorCodeConstants {
// ========== GoView 模块 1-003-000-000 ==========
- ErrorCode GO_VIEW_PROJECT_NOT_EXISTS = new ErrorCode(1_003_000_000, "GoView 项目不存在");
+ ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_003_000_000, "设备不存在");
+ ErrorCode DEVICE_ATTRIBUTE_NOT_EXISTS = new ErrorCode(1_003_000_000, "设备属性不存在");
+ ErrorCode FORMULA_NOT_EXISTS = new ErrorCode(1_003_000_000, "公式不存在");
+ ErrorCode FORMULA_DETAIL_NOT_EXISTS = new ErrorCode(1_003_000_000, "公式明细不存在");
+ ErrorCode GATEWAY_NOT_EXISTS = new ErrorCode(1_003_000_000, "网关不存在");
+ ErrorCode KANBAN_NOT_EXISTS = new ErrorCode(1_003_000_000, "看板不存在");
+ ErrorCode ORGANIZATION_EXITS_CHILDREN = new ErrorCode(1_003_000_000, "GoView 项目不存在");
+ ErrorCode ORGANIZATION_NOT_EXISTS = new ErrorCode(1_003_000_000, "GoView 项目不存在");
+ ErrorCode ORGANIZATION_PARENT_ERROR = new ErrorCode(1_003_000_000, "GoView 项目不存在");
+ ErrorCode ORGANIZATION_PARENT_NOT_EXITS = new ErrorCode(1_003_000_000, "GoView 项目不存在");
+ ErrorCode ORGANIZATION_PARENT_IS_CHILD = new ErrorCode(1_003_000_000, "GoView 项目不存在");
+ ErrorCode ORGANIZATION_NAME_DUPLICATE = new ErrorCode(1_003_000_000, "GoView 项目不存在");
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java
new file mode 100644
index 000000000..f6b59df8e
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/DeviceController.java
@@ -0,0 +1,138 @@
+package cn.iocoder.yudao.module.iot.controller.admin.device;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO;
+import cn.iocoder.yudao.module.iot.service.device.DeviceService;
+
+@Tag(name = "管理后台 - 物联设备")
+@RestController
+@RequestMapping("/iot/device")
+@Validated
+public class DeviceController {
+
+ @Resource
+ private DeviceService deviceService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建物联设备")
+ @PreAuthorize("@ss.hasPermission('iot:device:create')")
+ public CommonResult createDevice(@Valid @RequestBody DeviceSaveReqVO createReqVO) {
+ return success(deviceService.createDevice(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新物联设备")
+ @PreAuthorize("@ss.hasPermission('iot:device:update')")
+ public CommonResult updateDevice(@Valid @RequestBody DeviceSaveReqVO updateReqVO) {
+ deviceService.updateDevice(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除物联设备")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:device:delete')")
+ public CommonResult deleteDevice(@RequestParam("id") Long id) {
+ deviceService.deleteDevice(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得物联设备")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:device:query')")
+ public CommonResult getDevice(@RequestParam("id") Long id) {
+ DeviceDO device = deviceService.getDevice(id);
+ return success(BeanUtils.toBean(device, DeviceRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得物联设备分页")
+ @PreAuthorize("@ss.hasPermission('iot:device:query')")
+ public CommonResult> getDevicePage(@Valid DevicePageReqVO pageReqVO) {
+ PageResult pageResult = deviceService.getDevicePage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, DeviceRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出物联设备 Excel")
+ @PreAuthorize("@ss.hasPermission('iot:device:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportDeviceExcel(@Valid DevicePageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = deviceService.getDevicePage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "物联设备.xls", "数据", DeviceRespVO.class,
+ BeanUtils.toBean(list, DeviceRespVO.class));
+ }
+
+ // ==================== 子表(设备属性) ====================
+
+ @GetMapping("/device-attribute/page")
+ @Operation(summary = "获得设备属性分页")
+ @Parameter(name = "deviceId", description = "设备id")
+ @PreAuthorize("@ss.hasPermission('iot:device:query')")
+ public CommonResult> getDeviceAttributePage(PageParam pageReqVO,
+ @RequestParam("deviceId") Long deviceId) {
+ return success(deviceService.getDeviceAttributePage(pageReqVO, deviceId));
+ }
+
+ @PostMapping("/device-attribute/create")
+ @Operation(summary = "创建设备属性")
+ @PreAuthorize("@ss.hasPermission('iot:device:create')")
+ public CommonResult createDeviceAttribute(@Valid @RequestBody DeviceAttributeDO deviceAttribute) {
+ return success(deviceService.createDeviceAttribute(deviceAttribute));
+ }
+
+ @PutMapping("/device-attribute/update")
+ @Operation(summary = "更新设备属性")
+ @PreAuthorize("@ss.hasPermission('iot:device:update')")
+ public CommonResult updateDeviceAttribute(@Valid @RequestBody DeviceAttributeDO deviceAttribute) {
+ deviceService.updateDeviceAttribute(deviceAttribute);
+ return success(true);
+ }
+
+ @DeleteMapping("/device-attribute/delete")
+ @Parameter(name = "id", description = "编号", required = true)
+ @Operation(summary = "删除设备属性")
+ @PreAuthorize("@ss.hasPermission('iot:device:delete')")
+ public CommonResult deleteDeviceAttribute(@RequestParam("id") Long id) {
+ deviceService.deleteDeviceAttribute(id);
+ return success(true);
+ }
+
+ @GetMapping("/device-attribute/get")
+ @Operation(summary = "获得设备属性")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:device:query')")
+ public CommonResult getDeviceAttribute(@RequestParam("id") Long id) {
+ return success(deviceService.getDeviceAttribute(id));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePageReqVO.java
new file mode 100644
index 000000000..741c8c931
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DevicePageReqVO.java
@@ -0,0 +1,103 @@
+package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 物联设备分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class DevicePageReqVO extends PageParam {
+
+ @Schema(description = "设备配置id", example = "14050")
+ private String deviceConfigId;
+
+ @Schema(description = "设备编号")
+ private String deviceCode;
+
+ @Schema(description = "设备名称", example = "李四")
+ private String deviceName;
+
+ @Schema(description = "设备类型", example = "2")
+ private String deviceType;
+
+ @Schema(description = "Siemens系列(S7-300、S7-1500)")
+ private String siemensSeries;
+
+ @Schema(description = "连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ private String siemensConnectParam;
+
+ @Schema(description = "读取任务方式(0无,1有)", example = "2")
+ private String readCronType;
+
+ @Schema(description = "读取任务时间间隔")
+ private Integer readRepeatValue;
+
+ @Schema(description = "读取任务时间间隔单位")
+ private String readRepeatUnit;
+
+ @Schema(description = "读取任务时间表达式")
+ private String readCron;
+
+ @Schema(description = "写入任务时间间隔", example = "1")
+ private String writeCronType;
+
+ @Schema(description = "写入任务时间间隔")
+ private Integer writeRepeatValue;
+
+ @Schema(description = "写入任务时间间隔单位")
+ private String writeRepeatUnit;
+
+ @Schema(description = "写入任务时间表达式")
+ private String writeCron;
+
+ @Schema(description = "是否持久化(0不持久化,1持久化)")
+ private String localPersistent;
+
+ @Schema(description = "上传方式(1实时,2自定义)")
+ private String uploadRate;
+
+ @Schema(description = "上传频率", example = "19796")
+ private Integer rateCount;
+
+ @Schema(description = "modbus协议类型(serial-rtu)")
+ private String modbusProtocol;
+
+ @Schema(description = "modbus模式(client)")
+ private String modbusPattern;
+
+ @Schema(description = "modbus串口号", example = "李四")
+ private String portName;
+
+ @Schema(description = "连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ private String modbusConnectParam;
+
+ @Schema(description = "读地址是否连续(0否,1是)")
+ private String modbusReadAddrGap;
+
+ @Schema(description = "是否已下发(0下,1没下)")
+ private String isUpload;
+
+ @Schema(description = "网关id", example = "6304")
+ private Long gatewayId;
+
+ @Schema(description = "组织设备id", example = "23150")
+ private Long orgId;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceRespVO.java
new file mode 100644
index 000000000..22cb56850
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceRespVO.java
@@ -0,0 +1,144 @@
+package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - 物联设备 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class DeviceRespVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "8540")
+ @ExcelProperty("ID")
+ private Long id;
+
+ @Schema(description = "设备配置id", example = "14050")
+ @ExcelProperty("设备配置id")
+ private String deviceConfigId;
+
+ @Schema(description = "设备编号")
+ @ExcelProperty("设备编号")
+ private String deviceCode;
+
+ @Schema(description = "设备名称", example = "李四")
+ @ExcelProperty("设备名称")
+ private String deviceName;
+
+ @Schema(description = "设备类型", example = "2")
+ @ExcelProperty("设备类型")
+ private String deviceType;
+
+ @Schema(description = "Siemens系列(S7-300、S7-1500)")
+ @ExcelProperty(value = "Siemens系列(S7-300、S7-1500)", converter = DictConvert.class)
+ @DictFormat("iot_siemens_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String siemensSeries;
+
+ @Schema(description = "连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ @ExcelProperty("连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ private String siemensConnectParam;
+
+ @Schema(description = "读取任务方式(0无,1有)", example = "2")
+ @ExcelProperty(value = "读取任务方式(0无,1有)", converter = DictConvert.class)
+ @DictFormat("iot_1_or_0") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String readCronType;
+
+ @Schema(description = "读取任务时间间隔")
+ @ExcelProperty("读取任务时间间隔")
+ private Integer readRepeatValue;
+
+ @Schema(description = "读取任务时间间隔单位")
+ @ExcelProperty(value = "读取任务时间间隔单位", converter = DictConvert.class)
+ @DictFormat("iot_device_data_unit") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String readRepeatUnit;
+
+ @Schema(description = "读取任务时间表达式")
+ @ExcelProperty("读取任务时间表达式")
+ private String readCron;
+
+ @Schema(description = "写入任务时间间隔", example = "1")
+ @ExcelProperty("写入任务时间间隔")
+ private String writeCronType;
+
+ @Schema(description = "写入任务时间间隔")
+ @ExcelProperty("写入任务时间间隔")
+ private Integer writeRepeatValue;
+
+ @Schema(description = "写入任务时间间隔单位")
+ @ExcelProperty("写入任务时间间隔单位")
+ private String writeRepeatUnit;
+
+ @Schema(description = "写入任务时间表达式")
+ @ExcelProperty("写入任务时间表达式")
+ private String writeCron;
+
+ @Schema(description = "是否持久化(0不持久化,1持久化)")
+ @ExcelProperty(value = "是否持久化(0不持久化,1持久化)", converter = DictConvert.class)
+ @DictFormat("iot_1_or_0") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String localPersistent;
+
+ @Schema(description = "上传方式(1实时,2自定义)")
+ @ExcelProperty(value = "上传方式(1实时,2自定义)", converter = DictConvert.class)
+ @DictFormat("iot_device_uploading_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String uploadRate;
+
+ @Schema(description = "上传频率", example = "19796")
+ @ExcelProperty("上传频率")
+ private Integer rateCount;
+
+ @Schema(description = "modbus协议类型(serial-rtu)")
+ @ExcelProperty(value = "modbus协议类型(serial-rtu)", converter = DictConvert.class)
+ @DictFormat("iot_modbus_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String modbusProtocol;
+
+ @Schema(description = "modbus模式(client)")
+ @ExcelProperty(value = "modbus模式(client)", converter = DictConvert.class)
+ @DictFormat("iot_modbus_mold") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String modbusPattern;
+
+ @Schema(description = "modbus串口号", example = "李四")
+ @ExcelProperty(value = "modbus串口号", converter = DictConvert.class)
+ @DictFormat("iot_modbus_port") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String portName;
+
+ @Schema(description = "连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ @ExcelProperty("连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ private String modbusConnectParam;
+
+ @Schema(description = "读地址是否连续(0否,1是)")
+ @ExcelProperty(value = "读地址是否连续(0否,1是)", converter = DictConvert.class)
+ @DictFormat("iot_1_or_0") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String modbusReadAddrGap;
+
+ @Schema(description = "是否已下发(0下,1没下)")
+ @ExcelProperty(value = "是否已下发(0下,1没下)", converter = DictConvert.class)
+ @DictFormat("iot_1_or_0") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String isUpload;
+
+ @Schema(description = "网关id", requiredMode = Schema.RequiredMode.REQUIRED, example = "6304")
+ @ExcelProperty("网关id")
+ private Long gatewayId;
+
+ @Schema(description = "组织设备id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23150")
+ @ExcelProperty("组织设备id")
+ private Long orgId;
+
+ @Schema(description = "备注", example = "你猜")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceSaveReqVO.java
new file mode 100644
index 000000000..6a8fbae18
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/DeviceSaveReqVO.java
@@ -0,0 +1,99 @@
+package cn.iocoder.yudao.module.iot.controller.admin.device.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 物联设备新增/修改 Request VO")
+@Data
+public class DeviceSaveReqVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "8540")
+ private Long id;
+
+ @Schema(description = "设备配置id", example = "14050")
+ private String deviceConfigId;
+
+ @Schema(description = "设备编号")
+ private String deviceCode;
+
+ @Schema(description = "设备名称", example = "李四")
+ private String deviceName;
+
+ @Schema(description = "设备类型", example = "2")
+ private String deviceType;
+
+ @Schema(description = "Siemens系列(S7-300、S7-1500)")
+ private String siemensSeries;
+
+ @Schema(description = "连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ private String siemensConnectParam;
+
+ @Schema(description = "读取任务方式(0无,1有)", example = "2")
+ private String readCronType;
+
+ @Schema(description = "读取任务时间间隔")
+ private Integer readRepeatValue;
+
+ @Schema(description = "读取任务时间间隔单位")
+ private String readRepeatUnit;
+
+ @Schema(description = "读取任务时间表达式")
+ private String readCron;
+
+ @Schema(description = "写入任务时间间隔", example = "1")
+ private String writeCronType;
+
+ @Schema(description = "写入任务时间间隔")
+ private Integer writeRepeatValue;
+
+ @Schema(description = "写入任务时间间隔单位")
+ private String writeRepeatUnit;
+
+ @Schema(description = "写入任务时间表达式")
+ private String writeCron;
+
+ @Schema(description = "是否持久化(0不持久化,1持久化)")
+ private String localPersistent;
+
+ @Schema(description = "上传方式(1实时,2自定义)")
+ private String uploadRate;
+
+ @Schema(description = "上传频率", example = "19796")
+ private Integer rateCount;
+
+ @Schema(description = "modbus协议类型(serial-rtu)")
+ private String modbusProtocol;
+
+ @Schema(description = "modbus模式(client)")
+ private String modbusPattern;
+
+ @Schema(description = "modbus串口号", example = "李四")
+ private String portName;
+
+ @Schema(description = "连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)")
+ private String modbusConnectParam;
+
+ @Schema(description = "读地址是否连续(0否,1是)")
+ private String modbusReadAddrGap;
+
+ @Schema(description = "是否已下发(0下,1没下)")
+ private String isUpload;
+
+ @Schema(description = "网关id", requiredMode = Schema.RequiredMode.REQUIRED, example = "6304")
+ @NotNull(message = "网关id不能为空")
+ private Long gatewayId;
+
+ @Schema(description = "组织设备id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23150")
+ @NotNull(message = "组织设备id不能为空")
+ private Long orgId;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "是否启用不能为空")
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/FormulaController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/FormulaController.java
new file mode 100644
index 000000000..daf75f696
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/FormulaController.java
@@ -0,0 +1,138 @@
+package cn.iocoder.yudao.module.iot.controller.admin.formula;
+
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.iot.controller.admin.formula.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDetailDO;
+import cn.iocoder.yudao.module.iot.service.formula.FormulaService;
+
+@Tag(name = "管理后台 - 计算公式")
+@RestController
+@RequestMapping("/iot/formula")
+@Validated
+public class FormulaController {
+
+ @Resource
+ private FormulaService formulaService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建计算公式")
+ @PreAuthorize("@ss.hasPermission('iot:formula:create')")
+ public CommonResult createFormula(@Valid @RequestBody FormulaSaveReqVO createReqVO) {
+ return success(formulaService.createFormula(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新计算公式")
+ @PreAuthorize("@ss.hasPermission('iot:formula:update')")
+ public CommonResult updateFormula(@Valid @RequestBody FormulaSaveReqVO updateReqVO) {
+ formulaService.updateFormula(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除计算公式")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:formula:delete')")
+ public CommonResult deleteFormula(@RequestParam("id") Long id) {
+ formulaService.deleteFormula(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得计算公式")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:formula:query')")
+ public CommonResult getFormula(@RequestParam("id") Long id) {
+ FormulaDO formula = formulaService.getFormula(id);
+ return success(BeanUtils.toBean(formula, FormulaRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得计算公式分页")
+ @PreAuthorize("@ss.hasPermission('iot:formula:query')")
+ public CommonResult> getFormulaPage(@Valid FormulaPageReqVO pageReqVO) {
+ PageResult pageResult = formulaService.getFormulaPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, FormulaRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出计算公式 Excel")
+ @PreAuthorize("@ss.hasPermission('iot:formula:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportFormulaExcel(@Valid FormulaPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = formulaService.getFormulaPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "计算公式.xls", "数据", FormulaRespVO.class,
+ BeanUtils.toBean(list, FormulaRespVO.class));
+ }
+
+ // ==================== 子表(计算公式明细) ====================
+
+ @GetMapping("/formula-detail/page")
+ @Operation(summary = "获得计算公式明细分页")
+ @Parameter(name = "formulaId", description = "计算公式ID")
+ @PreAuthorize("@ss.hasPermission('iot:formula:query')")
+ public CommonResult> getFormulaDetailPage(PageParam pageReqVO,
+ @RequestParam("formulaId") Long formulaId) {
+ return success(formulaService.getFormulaDetailPage(pageReqVO, formulaId));
+ }
+
+ @PostMapping("/formula-detail/create")
+ @Operation(summary = "创建计算公式明细")
+ @PreAuthorize("@ss.hasPermission('iot:formula:create')")
+ public CommonResult createFormulaDetail(@Valid @RequestBody FormulaDetailDO formulaDetail) {
+ return success(formulaService.createFormulaDetail(formulaDetail));
+ }
+
+ @PutMapping("/formula-detail/update")
+ @Operation(summary = "更新计算公式明细")
+ @PreAuthorize("@ss.hasPermission('iot:formula:update')")
+ public CommonResult updateFormulaDetail(@Valid @RequestBody FormulaDetailDO formulaDetail) {
+ formulaService.updateFormulaDetail(formulaDetail);
+ return success(true);
+ }
+
+ @DeleteMapping("/formula-detail/delete")
+ @Parameter(name = "id", description = "编号", required = true)
+ @Operation(summary = "删除计算公式明细")
+ @PreAuthorize("@ss.hasPermission('iot:formula:delete')")
+ public CommonResult deleteFormulaDetail(@RequestParam("id") Long id) {
+ formulaService.deleteFormulaDetail(id);
+ return success(true);
+ }
+
+ @GetMapping("/formula-detail/get")
+ @Operation(summary = "获得计算公式明细")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:formula:query')")
+ public CommonResult getFormulaDetail(@RequestParam("id") Long id) {
+ return success(formulaService.getFormulaDetail(id));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaPageReqVO.java
new file mode 100644
index 000000000..7285bb28a
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaPageReqVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.iot.controller.admin.formula.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 计算公式分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class FormulaPageReqVO extends PageParam {
+
+ @Schema(description = "公式名称", example = "王五")
+ private String name;
+
+ @Schema(description = "公式编号")
+ private String formulaCode;
+
+ @Schema(description = "公式")
+ private String formula;
+
+ @Schema(description = "结果类型(产量,电耗,浆耗,水耗,气耗,参数)", example = "1")
+ private String resultType;
+
+ @Schema(description = "机台ID", example = "12374")
+ private Long machineId;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaRespVO.java
new file mode 100644
index 000000000..ea16cf237
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaRespVO.java
@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.iot.controller.admin.formula.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - 计算公式 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class FormulaRespVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31788")
+ @ExcelProperty("ID")
+ private Long id;
+
+ @Schema(description = "公式名称", example = "王五")
+ @ExcelProperty("公式名称")
+ private String name;
+
+ @Schema(description = "公式编号")
+ @ExcelProperty("公式编号")
+ private String formulaCode;
+
+ @Schema(description = "公式")
+ @ExcelProperty("公式")
+ private String formula;
+
+ @Schema(description = "结果类型(产量,电耗,浆耗,水耗,气耗,参数)", example = "1")
+ @ExcelProperty(value = "结果类型(产量,电耗,浆耗,水耗,气耗,参数)", converter = DictConvert.class)
+ @DictFormat("mes_data_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String resultType;
+
+ @Schema(description = "机台ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12374")
+ @ExcelProperty("机台ID")
+ private Long machineId;
+
+ @Schema(description = "备注", example = "你猜")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaSaveReqVO.java
new file mode 100644
index 000000000..e1ab0e7ff
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/formula/vo/FormulaSaveReqVO.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.iot.controller.admin.formula.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 计算公式新增/修改 Request VO")
+@Data
+public class FormulaSaveReqVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31788")
+ private Long id;
+
+ @Schema(description = "公式名称", example = "王五")
+ private String name;
+
+ @Schema(description = "公式编号")
+ private String formulaCode;
+
+ @Schema(description = "公式")
+ private String formula;
+
+ @Schema(description = "结果类型(产量,电耗,浆耗,水耗,气耗,参数)", example = "1")
+ private String resultType;
+
+ @Schema(description = "机台ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "12374")
+ @NotNull(message = "机台ID不能为空")
+ private Long machineId;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "是否启用不能为空")
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/GatewayController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/GatewayController.java
new file mode 100644
index 000000000..1a4310e16
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/GatewayController.java
@@ -0,0 +1,138 @@
+package cn.iocoder.yudao.module.iot.controller.admin.gateway;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.iot.controller.admin.gateway.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
+import cn.iocoder.yudao.module.iot.service.gateway.GatewayService;
+
+@Tag(name = "管理后台 - 网关")
+@RestController
+@RequestMapping("/iot/gateway")
+@Validated
+public class GatewayController {
+
+ @Resource
+ private GatewayService gatewayService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建网关")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:create')")
+ public CommonResult createGateway(@Valid @RequestBody GatewaySaveReqVO createReqVO) {
+ return success(gatewayService.createGateway(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新网关")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:update')")
+ public CommonResult updateGateway(@Valid @RequestBody GatewaySaveReqVO updateReqVO) {
+ gatewayService.updateGateway(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除网关")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:gateway:delete')")
+ public CommonResult deleteGateway(@RequestParam("id") Long id) {
+ gatewayService.deleteGateway(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得网关")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:query')")
+ public CommonResult getGateway(@RequestParam("id") Long id) {
+ GatewayDO gateway = gatewayService.getGateway(id);
+ return success(BeanUtils.toBean(gateway, GatewayRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得网关分页")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:query')")
+ public CommonResult> getGatewayPage(@Valid GatewayPageReqVO pageReqVO) {
+ PageResult pageResult = gatewayService.getGatewayPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, GatewayRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出网关 Excel")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportGatewayExcel(@Valid GatewayPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = gatewayService.getGatewayPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "网关.xls", "数据", GatewayRespVO.class,
+ BeanUtils.toBean(list, GatewayRespVO.class));
+ }
+
+ // ==================== 子表(物联设备) ====================
+
+ @GetMapping("/device/page")
+ @Operation(summary = "获得物联设备分页")
+ @Parameter(name = "gatewayId", description = "网关id")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:query')")
+ public CommonResult> getDevicePage(PageParam pageReqVO,
+ @RequestParam("gatewayId") Long gatewayId) {
+ return success(gatewayService.getDevicePage(pageReqVO, gatewayId));
+ }
+
+ @PostMapping("/device/create")
+ @Operation(summary = "创建物联设备")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:create')")
+ public CommonResult createDevice(@Valid @RequestBody DeviceDO device) {
+ return success(gatewayService.createDevice(device));
+ }
+
+ @PutMapping("/device/update")
+ @Operation(summary = "更新物联设备")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:update')")
+ public CommonResult updateDevice(@Valid @RequestBody DeviceDO device) {
+ gatewayService.updateDevice(device);
+ return success(true);
+ }
+
+ @DeleteMapping("/device/delete")
+ @Parameter(name = "id", description = "编号", required = true)
+ @Operation(summary = "删除物联设备")
+ @PreAuthorize("@ss.hasPermission('iot:gateway:delete')")
+ public CommonResult deleteDevice(@RequestParam("id") Long id) {
+ gatewayService.deleteDevice(id);
+ return success(true);
+ }
+
+ @GetMapping("/device/get")
+ @Operation(summary = "获得物联设备")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:gateway:query')")
+ public CommonResult getDevice(@RequestParam("id") Long id) {
+ return success(gatewayService.getDevice(id));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayPageReqVO.java
new file mode 100644
index 000000000..506d32eeb
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayPageReqVO.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.iot.controller.admin.gateway.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 网关分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class GatewayPageReqVO extends PageParam {
+
+ @Schema(description = "管理地址")
+ private String adminIp;
+
+ @Schema(description = "管理账号", example = "芋艿")
+ private String username;
+
+ @Schema(description = "管理密码")
+ private String password;
+
+ @Schema(description = "网关名字", example = "赵六")
+ private String gatewayName;
+
+ @Schema(description = "备注", example = "随便")
+ private String remark;
+
+ @Schema(description = "是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "网关编码")
+ private String gatewayCode;
+
+ @Schema(description = "网关状态", example = "1")
+ private String gatewayStatus;
+
+ @Schema(description = "订阅主题")
+ private String topic;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayRespVO.java
new file mode 100644
index 000000000..e6bdf5b77
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewayRespVO.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.iot.controller.admin.gateway.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - 网关 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class GatewayRespVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "28060")
+ @ExcelProperty("ID")
+ private Long id;
+
+ @Schema(description = "管理地址")
+ @ExcelProperty("管理地址")
+ private String adminIp;
+
+ @Schema(description = "管理账号", example = "芋艿")
+ @ExcelProperty("管理账号")
+ private String username;
+
+ @Schema(description = "管理密码")
+ @ExcelProperty("管理密码")
+ private String password;
+
+ @Schema(description = "网关名字", example = "赵六")
+ @ExcelProperty("网关名字")
+ private String gatewayName;
+
+ @Schema(description = "备注", example = "随便")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "网关编码")
+ @ExcelProperty("网关编码")
+ private String gatewayCode;
+
+ @Schema(description = "网关状态", example = "1")
+ @ExcelProperty(value = "网关状态", converter = DictConvert.class)
+ @DictFormat("iot_gateway_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String gatewayStatus;
+
+ @Schema(description = "订阅主题")
+ @ExcelProperty("订阅主题")
+ private String topic;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewaySaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewaySaveReqVO.java
new file mode 100644
index 000000000..d4b15462d
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/gateway/vo/GatewaySaveReqVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.iot.controller.admin.gateway.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 网关新增/修改 Request VO")
+@Data
+public class GatewaySaveReqVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "28060")
+ private Long id;
+
+ @Schema(description = "管理地址")
+ private String adminIp;
+
+ @Schema(description = "管理账号", example = "芋艿")
+ private String username;
+
+ @Schema(description = "管理密码")
+ private String password;
+
+ @Schema(description = "网关名字", example = "赵六")
+ private String gatewayName;
+
+ @Schema(description = "备注", example = "随便")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "是否启用不能为空")
+ private Boolean isEnable;
+
+ @Schema(description = "网关编码")
+ private String gatewayCode;
+
+ @Schema(description = "网关状态", example = "1")
+ private String gatewayStatus;
+
+ @Schema(description = "订阅主题")
+ private String topic;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/IotOrganizationController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/IotOrganizationController.java
new file mode 100644
index 000000000..4bd7cbb9d
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/IotOrganizationController.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.iot.controller.admin.iotorganization;
+
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization.IotOrganizationDO;
+import cn.iocoder.yudao.module.iot.service.iotorganization.IotOrganizationService;
+
+@Tag(name = "管理后台 - IOT组织")
+@RestController
+@RequestMapping("/iot/organization")
+@Validated
+public class IotOrganizationController {
+
+ @Resource
+ private IotOrganizationService organizationService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建IOT组织")
+ @PreAuthorize("@ss.hasPermission('iot:organization:create')")
+ public CommonResult createOrganization(@Valid @RequestBody IotOrganizationSaveReqVO createReqVO) {
+ return success(organizationService.createOrganization(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新IOT组织")
+ @PreAuthorize("@ss.hasPermission('iot:organization:update')")
+ public CommonResult updateOrganization(@Valid @RequestBody IotOrganizationSaveReqVO updateReqVO) {
+ organizationService.updateOrganization(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除IOT组织")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:organization:delete')")
+ public CommonResult deleteOrganization(@RequestParam("id") Long id) {
+ organizationService.deleteOrganization(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得IOT组织")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:organization:query')")
+ public CommonResult getOrganization(@RequestParam("id") Long id) {
+ IotOrganizationDO organization = organizationService.getOrganization(id);
+ return success(BeanUtils.toBean(organization, IotOrganizationRespVO.class));
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得IOT组织列表")
+ @PreAuthorize("@ss.hasPermission('iot:organization:query')")
+ public CommonResult> getOrganizationList(@Valid IotOrganizationListReqVO listReqVO) {
+ List list = organizationService.getOrganizationList(listReqVO);
+ return success(BeanUtils.toBean(list, IotOrganizationRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出IOT组织 Excel")
+ @PreAuthorize("@ss.hasPermission('iot:organization:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportOrganizationExcel(@Valid IotOrganizationListReqVO listReqVO,
+ HttpServletResponse response) throws IOException {
+ List list = organizationService.getOrganizationList(listReqVO);
+ // 导出 Excel
+ ExcelUtils.write(response, "IOT组织.xls", "数据", IotOrganizationRespVO.class,
+ BeanUtils.toBean(list, IotOrganizationRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationListReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationListReqVO.java
new file mode 100644
index 000000000..10ee5f7ff
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationListReqVO.java
@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import java.time.LocalDateTime;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - IOT组织列表 Request VO")
+@Data
+public class IotOrganizationListReqVO {
+
+ @Schema(description = "显示顺序")
+ private Integer sort;
+
+ @Schema(description = "负责人/工人", example = "11964")
+ private Long workerUserId;
+
+ @Schema(description = "绑定工位id", example = "21787")
+ private Long orgId;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "组织名称", example = "赵六")
+ private String name;
+
+ @Schema(description = "父组织id", example = "10729")
+ private Long parentId;
+
+ @Schema(description = "组织状态", example = "2")
+ private Integer status;
+
+ @Schema(description = "设备类型", example = "2")
+ private String deviceType;
+
+ @Schema(description = "组织等级")
+ private String orgClass;
+
+ @Schema(description = "机台类型", example = "2")
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationRespVO.java
new file mode 100644
index 000000000..379b4eb87
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationRespVO.java
@@ -0,0 +1,66 @@
+package cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - IOT组织 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotOrganizationRespVO {
+
+ @Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED, example = "24521")
+ @ExcelProperty("组织id")
+ private Long id;
+
+ @Schema(description = "显示顺序")
+ @ExcelProperty("显示顺序")
+ private Integer sort;
+
+ @Schema(description = "负责人/工人", example = "11964")
+ @ExcelProperty("负责人/工人")
+ private Long workerUserId;
+
+ @Schema(description = "绑定工位id", example = "21787")
+ @ExcelProperty("绑定工位id")
+ private Long orgId;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "组织名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+ @ExcelProperty("组织名称")
+ private String name;
+
+ @Schema(description = "父组织id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10729")
+ @ExcelProperty("父组织id")
+ private Long parentId;
+
+ @Schema(description = "组织状态", example = "2")
+ @ExcelProperty(value = "组织状态", converter = DictConvert.class)
+ @DictFormat("mes_machine_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private Integer status;
+
+ @Schema(description = "设备类型", example = "2")
+ @ExcelProperty(value = "设备类型", converter = DictConvert.class)
+ @DictFormat("iot_device_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String deviceType;
+
+ @Schema(description = "组织等级")
+ @ExcelProperty(value = "组织等级", converter = DictConvert.class)
+ @DictFormat("iot_org_class") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String orgClass;
+
+ @Schema(description = "机台类型", example = "2")
+ @ExcelProperty(value = "机台类型", converter = DictConvert.class)
+ @DictFormat("mes_org_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationSaveReqVO.java
new file mode 100644
index 000000000..8bcebeac3
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/iotorganization/vo/IotOrganizationSaveReqVO.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+@Schema(description = "管理后台 - IOT组织新增/修改 Request VO")
+@Data
+public class IotOrganizationSaveReqVO {
+
+ @Schema(description = "组织id", requiredMode = Schema.RequiredMode.REQUIRED, example = "24521")
+ private Long id;
+
+ @Schema(description = "显示顺序")
+ private Integer sort;
+
+ @Schema(description = "负责人/工人", example = "11964")
+ private Long workerUserId;
+
+ @Schema(description = "绑定工位id", example = "21787")
+ private Long orgId;
+
+ @Schema(description = "组织名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
+ @NotEmpty(message = "组织名称不能为空")
+ private String name;
+
+ @Schema(description = "父组织id", requiredMode = Schema.RequiredMode.REQUIRED, example = "10729")
+ @NotNull(message = "父组织id不能为空")
+ private Long parentId;
+
+ @Schema(description = "组织状态", example = "2")
+ private Integer status;
+
+ @Schema(description = "设备类型", example = "2")
+ private String deviceType;
+
+ @Schema(description = "组织等级")
+ private String orgClass;
+
+ @Schema(description = "机台类型", example = "2")
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/KanbanController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/KanbanController.java
new file mode 100644
index 000000000..6deda1064
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/KanbanController.java
@@ -0,0 +1,94 @@
+package cn.iocoder.yudao.module.iot.controller.admin.kanban;
+
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.iot.controller.admin.kanban.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.kanban.KanbanDO;
+import cn.iocoder.yudao.module.iot.service.kanban.KanbanService;
+
+@Tag(name = "管理后台 - 物联看板")
+@RestController
+@RequestMapping("/iot/kanban")
+@Validated
+public class KanbanController {
+
+ @Resource
+ private KanbanService kanbanService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建物联看板")
+ @PreAuthorize("@ss.hasPermission('iot:kanban:create')")
+ public CommonResult createKanban(@Valid @RequestBody KanbanSaveReqVO createReqVO) {
+ return success(kanbanService.createKanban(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新物联看板")
+ @PreAuthorize("@ss.hasPermission('iot:kanban:update')")
+ public CommonResult updateKanban(@Valid @RequestBody KanbanSaveReqVO updateReqVO) {
+ kanbanService.updateKanban(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除物联看板")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:kanban:delete')")
+ public CommonResult deleteKanban(@RequestParam("id") Long id) {
+ kanbanService.deleteKanban(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得物联看板")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:kanban:query')")
+ public CommonResult getKanban(@RequestParam("id") Long id) {
+ KanbanDO kanban = kanbanService.getKanban(id);
+ return success(BeanUtils.toBean(kanban, KanbanRespVO.class));
+ }
+
+ @GetMapping("/page")
+ @Operation(summary = "获得物联看板分页")
+ @PreAuthorize("@ss.hasPermission('iot:kanban:query')")
+ public CommonResult> getKanbanPage(@Valid KanbanPageReqVO pageReqVO) {
+ PageResult pageResult = kanbanService.getKanbanPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, KanbanRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出物联看板 Excel")
+ @PreAuthorize("@ss.hasPermission('iot:kanban:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportKanbanExcel(@Valid KanbanPageReqVO pageReqVO,
+ HttpServletResponse response) throws IOException {
+ pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+ List list = kanbanService.getKanbanPage(pageReqVO).getList();
+ // 导出 Excel
+ ExcelUtils.write(response, "物联看板.xls", "数据", KanbanRespVO.class,
+ BeanUtils.toBean(list, KanbanRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanPageReqVO.java
new file mode 100644
index 000000000..1bc4a8643
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanPageReqVO.java
@@ -0,0 +1,42 @@
+package cn.iocoder.yudao.module.iot.controller.admin.kanban.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 物联看板分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class KanbanPageReqVO extends PageParam {
+
+ @Schema(description = "编码")
+ private String code;
+
+ @Schema(description = "标题")
+ private String title;
+
+ @Schema(description = "缩略图")
+ private String img;
+ @Schema(description = "访问地址", example = "https://www.iocoder.cn")
+ private String viewUrl;
+
+ @Schema(description = "标签")
+ private String tags;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "是否启用")
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanRespVO.java
new file mode 100644
index 000000000..d92888ad2
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanRespVO.java
@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.iot.controller.admin.kanban.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - 物联看板 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class KanbanRespVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "22557")
+ @ExcelProperty("ID")
+ private Long id;
+
+ @Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("编码")
+ private String code;
+
+ @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("标题")
+ private String title;
+
+ @Schema(description = "缩略图")
+ @ExcelProperty("缩略图")
+ private String img;
+ @Schema(description = "访问地址", example = "https://www.iocoder.cn")
+ @ExcelProperty("访问地址")
+ private String viewUrl;
+
+ @Schema(description = "标签")
+ @ExcelProperty("标签")
+ private String tags;
+
+ @Schema(description = "备注", example = "你猜")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty(value = "是否启用", converter = DictConvert.class)
+ @DictFormat("infra_boolean_string") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private Boolean isEnable;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanSaveReqVO.java
new file mode 100644
index 000000000..8ce25ff59
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/kanban/vo/KanbanSaveReqVO.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.module.iot.controller.admin.kanban.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+@Schema(description = "管理后台 - 物联看板新增/修改 Request VO")
+@Data
+public class KanbanSaveReqVO {
+
+ @Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "22557")
+ private Long id;
+
+ @Schema(description = "编码", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "编码不能为空")
+ private String code;
+
+ @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "标题不能为空")
+ private String title;
+
+ @Schema(description = "缩略图")
+ private String img;
+ @Schema(description = "访问地址", example = "https://www.iocoder.cn")
+ private String viewUrl;
+
+ @Schema(description = "标签")
+ private String tags;
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "是否启用", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "是否启用不能为空")
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceAttributeDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceAttributeDO.java
new file mode 100644
index 000000000..6ea281530
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceAttributeDO.java
@@ -0,0 +1,177 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.device;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 设备属性 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_device_attribute")
+@KeySequence("iot_device_attribute_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DeviceAttributeDO extends BaseDO {
+
+ /**
+ * ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 地址编码
+ */
+ private String attributeCode;
+ /**
+ * 地址
+ */
+ private String address;
+ /**
+ * 地址名称
+ */
+ private String attributeName;
+ /**
+ * 地址描述
+ */
+ private String description;
+ /**
+ * 地址类型
+ */
+ private String addressType;
+ /**
+ * 地址偏移
+ */
+ private String addressOffset;
+ /**
+ * 地址2类型
+ */
+ private String address2Type;
+ /**
+ * 地址2偏移
+ */
+ private String address2Offset;
+ /**
+ * 所属组
+ */
+ private String groupName;
+ /**
+ * 所属组id
+ */
+ private Integer groupId;
+ /**
+ * 安全类别
+ */
+ private String securityType;
+ /**
+ * 读写状态
+ */
+ private String ioStatus;
+ /**
+ * 是否线性换算(0是,1否)
+ *
+ * 枚举 {@link TODO iot_1_or_0 对应的类}
+ */
+ private String isLinearTransfer;
+ /**
+ * 数据类型
+ *
+ * 枚举 {@link TODO iot_device_data_type 对应的类}
+ */
+ private String dataType;
+ /**
+ * 单位
+ */
+ private String unit;
+ /**
+ * 输入最小值
+ */
+ private String inMinValue;
+ /**
+ * 输入最大值
+ */
+ private String inMaxValue;
+ /**
+ * 输出最小值
+ */
+ private String outMinValue;
+ /**
+ * 输出最大值
+ */
+ private String outMaxValue;
+ /**
+ * 输出数据类型
+ */
+ private String outDataType;
+ /**
+ * 精度
+ */
+ private Integer siemensFieldPrecision;
+ /**
+ * 站号
+ */
+ private String modbusSlaveId;
+ /**
+ * 寄存器地址
+ */
+ private String modbusFieldAddress;
+ /**
+ * 寄存器类型
+ */
+ private String modbusAddressType;
+ /**
+ * 个数
+ */
+ private String modbusFieldSize;
+ /**
+ * 缩放因子(默认值为1,大于0的小数
+ */
+ private String modbusFieldPrecision;
+ /**
+ * 字节顺序
+ */
+ private String modbusFieldOrder;
+ /**
+ * mqtt进制类型binary,octal,hexadecimal,decimal
+ */
+ private String sourceDataType;
+ /**
+ * 转化进制类型binary,octal,hexadecimal,decimal
+ *
+ * 枚举 {@link TODO iot_device_data_transfer_type 对应的类}
+ */
+ private String transferDataType;
+ /**
+ * 系数
+ */
+ private String factor;
+ /**
+ * 网关id
+ */
+ private Long gatewayId;
+ /**
+ * 设备id
+ */
+ private Long deviceId;
+ /**
+ * 组织设备id
+ */
+ private Long orgId;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ */
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceDO.java
new file mode 100644
index 000000000..f08e1e4f8
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/DeviceDO.java
@@ -0,0 +1,159 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.device;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 物联设备 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_device")
+@KeySequence("iot_device_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DeviceDO extends BaseDO {
+
+ /**
+ * ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 设备配置id
+ */
+ private String deviceConfigId;
+ /**
+ * 设备编号
+ */
+ private String deviceCode;
+ /**
+ * 设备名称
+ */
+ private String deviceName;
+ /**
+ * 设备类型
+ */
+ private String deviceType;
+ /**
+ * Siemens系列(S7-300、S7-1500)
+ *
+ * 枚举 {@link TODO iot_siemens_type 对应的类}
+ */
+ private String siemensSeries;
+ /**
+ * 连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)
+ */
+ private String siemensConnectParam;
+ /**
+ * 读取任务方式(0无,1有)
+ *
+ * 枚举 {@link TODO iot_1_or_0 对应的类}
+ */
+ private String readCronType;
+ /**
+ * 读取任务时间间隔
+ */
+ private Integer readRepeatValue;
+ /**
+ * 读取任务时间间隔单位
+ *
+ * 枚举 {@link TODO iot_device_data_unit 对应的类}
+ */
+ private String readRepeatUnit;
+ /**
+ * 读取任务时间表达式
+ */
+ private String readCron;
+ /**
+ * 写入任务时间间隔
+ */
+ private String writeCronType;
+ /**
+ * 写入任务时间间隔
+ */
+ private Integer writeRepeatValue;
+ /**
+ * 写入任务时间间隔单位
+ */
+ private String writeRepeatUnit;
+ /**
+ * 写入任务时间表达式
+ */
+ private String writeCron;
+ /**
+ * 是否持久化(0不持久化,1持久化)
+ *
+ * 枚举 {@link TODO iot_1_or_0 对应的类}
+ */
+ private String localPersistent;
+ /**
+ * 上传方式(1实时,2自定义)
+ *
+ * 枚举 {@link TODO iot_device_uploading_type 对应的类}
+ */
+ private String uploadRate;
+ /**
+ * 上传频率
+ */
+ private Integer rateCount;
+ /**
+ * modbus协议类型(serial-rtu)
+ *
+ * 枚举 {@link TODO iot_modbus_type 对应的类}
+ */
+ private String modbusProtocol;
+ /**
+ * modbus模式(client)
+ *
+ * 枚举 {@link TODO iot_modbus_mold 对应的类}
+ */
+ private String modbusPattern;
+ /**
+ * modbus串口号
+ *
+ * 枚举 {@link TODO iot_modbus_port 对应的类}
+ */
+ private String portName;
+ /**
+ * 连接参数(波特率,数据位,停止位,校验位 例如:9600,8,1,N)
+ */
+ private String modbusConnectParam;
+ /**
+ * 读地址是否连续(0否,1是)
+ *
+ * 枚举 {@link TODO iot_1_or_0 对应的类}
+ */
+ private String modbusReadAddrGap;
+ /**
+ * 是否已下发(0下,1没下)
+ *
+ * 枚举 {@link TODO iot_1_or_0 对应的类}
+ */
+ private String isUpload;
+ /**
+ * 网关id
+ */
+ private Long gatewayId;
+ /**
+ * 组织设备id
+ */
+ private Long orgId;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ */
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDO.java
new file mode 100644
index 000000000..390395092
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDO.java
@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.formula;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 计算公式 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_formula")
+@KeySequence("iot_formula_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FormulaDO extends BaseDO {
+
+ /**
+ * ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 公式名称
+ */
+ private String name;
+ /**
+ * 公式编号
+ */
+ private String formulaCode;
+ /**
+ * 公式
+ */
+ private String formula;
+ /**
+ * 结果类型(产量,电耗,浆耗,水耗,气耗,参数)
+ *
+ * 枚举 {@link TODO mes_data_type 对应的类}
+ */
+ private String resultType;
+ /**
+ * 机台ID
+ */
+ private Long machineId;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ */
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDetailDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDetailDO.java
new file mode 100644
index 000000000..5cffae85a
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/formula/FormulaDetailDO.java
@@ -0,0 +1,83 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.formula;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 计算公式明细 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_formula_detail")
+@KeySequence("iot_formula_detail_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FormulaDetailDO extends BaseDO {
+
+ /**
+ * ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 计算公式ID
+ */
+ private Long formulaId;
+ /**
+ * 公式编号
+ */
+ private String formulaCode;
+ /**
+ * 变量名称
+ */
+ private String name;
+ /**
+ * 设备ID
+ */
+ private Long deviceId;
+ /**
+ * 地址ID
+ */
+ private Long attributeId;
+ /**
+ * 地址名称
+ */
+ private String attributeName;
+ /**
+ * 地址
+ */
+ private String address;
+ /**
+ * 示例值
+ */
+ private String demoValue;
+ /**
+ * 累积量类型sum:累加,max-min:最大值-最小值
+ *
+ * 枚举 {@link TODO iot_formula_var_type 对应的类}
+ */
+ private String sumType;
+ /**
+ * 计算范围,为空则不计算day:当天,week:当周,month:当月
+ *
+ * 枚举 {@link TODO iot_formula_cal_rang 对应的类}
+ */
+ private String sumRange;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ */
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/gateway/GatewayDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/gateway/GatewayDO.java
new file mode 100644
index 000000000..9db9a3ad2
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/gateway/GatewayDO.java
@@ -0,0 +1,69 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.gateway;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 网关 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_gateway")
+@KeySequence("iot_gateway_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class GatewayDO extends BaseDO {
+
+ /**
+ * ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 管理地址
+ */
+ private String adminIp;
+ /**
+ * 管理账号
+ */
+ private String username;
+ /**
+ * 管理密码
+ */
+ private String password;
+ /**
+ * 网关名字
+ */
+ private String gatewayName;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ */
+ private Boolean isEnable;
+ /**
+ * 网关编码
+ */
+ private String gatewayCode;
+ /**
+ * 网关状态
+ *
+ * 枚举 {@link TODO iot_gateway_status 对应的类}
+ */
+ private String gatewayStatus;
+ /**
+ * 订阅主题
+ */
+ private String topic;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/iotorganization/IotOrganizationDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/iotorganization/IotOrganizationDO.java
new file mode 100644
index 000000000..56abd6113
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/iotorganization/IotOrganizationDO.java
@@ -0,0 +1,77 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * IOT组织 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_iot_organization")
+@KeySequence("iot_iot_organization_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotOrganizationDO extends BaseDO {
+
+ public static final Long PARENT_ID_ROOT = 0L;
+
+ /**
+ * 组织id
+ */
+ @TableId
+ private Long id;
+ /**
+ * 显示顺序
+ */
+ private Integer sort;
+ /**
+ * 负责人/工人
+ */
+ private Long workerUserId;
+ /**
+ * 绑定工位id
+ */
+ private Long orgId;
+ /**
+ * 组织名称
+ */
+ private String name;
+ /**
+ * 父组织id
+ */
+ private Long parentId;
+ /**
+ * 组织状态
+ *
+ * 枚举 {@link TODO mes_machine_status 对应的类}
+ */
+ private Integer status;
+ /**
+ * 设备类型
+ *
+ * 枚举 {@link TODO iot_device_type 对应的类}
+ */
+ private String deviceType;
+ /**
+ * 组织等级
+ *
+ * 枚举 {@link TODO iot_org_class 对应的类}
+ */
+ private String orgClass;
+ /**
+ * 机台类型
+ *
+ * 枚举 {@link TODO mes_org_type 对应的类}
+ */
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/kanban/KanbanDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/kanban/KanbanDO.java
new file mode 100644
index 000000000..79900fb57
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/kanban/KanbanDO.java
@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.kanban;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 物联看板 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("iot_kanban")
+@KeySequence("iot_kanban_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class KanbanDO extends BaseDO {
+
+ /**
+ * ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 编码
+ */
+ private String code;
+ /**
+ * 标题
+ */
+ private String title;
+ /**
+ * 缩略图
+ */
+ private String img;
+ /**
+ * 访问地址
+ */
+ private String viewUrl;
+ /**
+ * 标签
+ */
+ private String tags;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 是否启用
+ *
+ * 枚举 {@link TODO infra_boolean_string 对应的类}
+ */
+ private Boolean isEnable;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceAttributeMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceAttributeMapper.java
new file mode 100644
index 000000000..4ac64c706
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceAttributeMapper.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.device;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 设备属性 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface DeviceAttributeMapper extends BaseMapperX {
+
+ default PageResult selectPage(PageParam reqVO, Long deviceId) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eq(DeviceAttributeDO::getDeviceId, deviceId)
+ .orderByDesc(DeviceAttributeDO::getId));
+ }
+
+ default int deleteByDeviceId(Long deviceId) {
+ return delete(DeviceAttributeDO::getDeviceId, deviceId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java
new file mode 100644
index 000000000..7ad141f04
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/DeviceMapper.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.device;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
+
+/**
+ * 物联设备 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface DeviceMapper extends BaseMapperX {
+
+ default PageResult selectPage(DevicePageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(DeviceDO::getDeviceConfigId, reqVO.getDeviceConfigId())
+ .eqIfPresent(DeviceDO::getDeviceCode, reqVO.getDeviceCode())
+ .likeIfPresent(DeviceDO::getDeviceName, reqVO.getDeviceName())
+ .eqIfPresent(DeviceDO::getDeviceType, reqVO.getDeviceType())
+ .eqIfPresent(DeviceDO::getSiemensSeries, reqVO.getSiemensSeries())
+ .eqIfPresent(DeviceDO::getSiemensConnectParam, reqVO.getSiemensConnectParam())
+ .eqIfPresent(DeviceDO::getReadCronType, reqVO.getReadCronType())
+ .eqIfPresent(DeviceDO::getReadRepeatValue, reqVO.getReadRepeatValue())
+ .eqIfPresent(DeviceDO::getReadRepeatUnit, reqVO.getReadRepeatUnit())
+ .eqIfPresent(DeviceDO::getReadCron, reqVO.getReadCron())
+ .eqIfPresent(DeviceDO::getWriteCronType, reqVO.getWriteCronType())
+ .eqIfPresent(DeviceDO::getWriteRepeatValue, reqVO.getWriteRepeatValue())
+ .eqIfPresent(DeviceDO::getWriteRepeatUnit, reqVO.getWriteRepeatUnit())
+ .eqIfPresent(DeviceDO::getWriteCron, reqVO.getWriteCron())
+ .eqIfPresent(DeviceDO::getLocalPersistent, reqVO.getLocalPersistent())
+ .eqIfPresent(DeviceDO::getUploadRate, reqVO.getUploadRate())
+ .eqIfPresent(DeviceDO::getRateCount, reqVO.getRateCount())
+ .eqIfPresent(DeviceDO::getModbusProtocol, reqVO.getModbusProtocol())
+ .eqIfPresent(DeviceDO::getModbusPattern, reqVO.getModbusPattern())
+ .eqIfPresent(DeviceDO::getPortName, reqVO.getPortName())
+ .eqIfPresent(DeviceDO::getModbusConnectParam, reqVO.getModbusConnectParam())
+ .eqIfPresent(DeviceDO::getModbusReadAddrGap, reqVO.getModbusReadAddrGap())
+ .eqIfPresent(DeviceDO::getIsUpload, reqVO.getIsUpload())
+ .eqIfPresent(DeviceDO::getGatewayId, reqVO.getGatewayId())
+ .eqIfPresent(DeviceDO::getOrgId, reqVO.getOrgId())
+ .eqIfPresent(DeviceDO::getRemark, reqVO.getRemark())
+ .eqIfPresent(DeviceDO::getIsEnable, reqVO.getIsEnable())
+ .betweenIfPresent(DeviceDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(DeviceDO::getId));
+ }
+ default PageResult selectPage(PageParam reqVO, Long gatewayId) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eq(DeviceDO::getGatewayId, gatewayId)
+ .orderByDesc(DeviceDO::getId));
+ }
+
+ default int deleteByGatewayId(Long gatewayId) {
+ return delete(DeviceDO::getGatewayId, gatewayId);
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaDetailMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaDetailMapper.java
new file mode 100644
index 000000000..b6be8d092
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaDetailMapper.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.formula;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDetailDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 计算公式明细 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface FormulaDetailMapper extends BaseMapperX {
+
+ default PageResult selectPage(PageParam reqVO, Long formulaId) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eq(FormulaDetailDO::getFormulaId, formulaId)
+ .orderByDesc(FormulaDetailDO::getId));
+ }
+
+ default int deleteByFormulaId(Long formulaId) {
+ return delete(FormulaDetailDO::getFormulaId, formulaId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaMapper.java
new file mode 100644
index 000000000..967d27151
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/formula/FormulaMapper.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.formula;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.iot.controller.admin.formula.vo.*;
+
+/**
+ * 计算公式 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface FormulaMapper extends BaseMapperX {
+
+ default PageResult selectPage(FormulaPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(FormulaDO::getName, reqVO.getName())
+ .eqIfPresent(FormulaDO::getFormulaCode, reqVO.getFormulaCode())
+ .eqIfPresent(FormulaDO::getFormula, reqVO.getFormula())
+ .eqIfPresent(FormulaDO::getResultType, reqVO.getResultType())
+ .eqIfPresent(FormulaDO::getMachineId, reqVO.getMachineId())
+ .eqIfPresent(FormulaDO::getRemark, reqVO.getRemark())
+ .eqIfPresent(FormulaDO::getIsEnable, reqVO.getIsEnable())
+ .betweenIfPresent(FormulaDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(FormulaDO::getId));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/gateway/GatewayMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/gateway/GatewayMapper.java
new file mode 100644
index 000000000..28a8a16bd
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/gateway/GatewayMapper.java
@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.gateway;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.iot.controller.admin.gateway.vo.*;
+
+/**
+ * 网关 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface GatewayMapper extends BaseMapperX {
+
+ default PageResult selectPage(GatewayPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(GatewayDO::getAdminIp, reqVO.getAdminIp())
+ .likeIfPresent(GatewayDO::getUsername, reqVO.getUsername())
+ .eqIfPresent(GatewayDO::getPassword, reqVO.getPassword())
+ .likeIfPresent(GatewayDO::getGatewayName, reqVO.getGatewayName())
+ .eqIfPresent(GatewayDO::getRemark, reqVO.getRemark())
+ .eqIfPresent(GatewayDO::getIsEnable, reqVO.getIsEnable())
+ .betweenIfPresent(GatewayDO::getCreateTime, reqVO.getCreateTime())
+ .eqIfPresent(GatewayDO::getGatewayCode, reqVO.getGatewayCode())
+ .eqIfPresent(GatewayDO::getGatewayStatus, reqVO.getGatewayStatus())
+ .eqIfPresent(GatewayDO::getTopic, reqVO.getTopic())
+ .orderByDesc(GatewayDO::getId));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/iotorganization/IotOrganizationMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/iotorganization/IotOrganizationMapper.java
new file mode 100644
index 000000000..ed78b4a49
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/iotorganization/IotOrganizationMapper.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.iotorganization;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization.IotOrganizationDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo.*;
+
+/**
+ * IOT组织 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface IotOrganizationMapper extends BaseMapperX {
+
+ default List selectList(IotOrganizationListReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .eqIfPresent(IotOrganizationDO::getSort, reqVO.getSort())
+ .eqIfPresent(IotOrganizationDO::getWorkerUserId, reqVO.getWorkerUserId())
+ .eqIfPresent(IotOrganizationDO::getOrgId, reqVO.getOrgId())
+ .betweenIfPresent(IotOrganizationDO::getCreateTime, reqVO.getCreateTime())
+ .likeIfPresent(IotOrganizationDO::getName, reqVO.getName())
+ .eqIfPresent(IotOrganizationDO::getParentId, reqVO.getParentId())
+ .eqIfPresent(IotOrganizationDO::getStatus, reqVO.getStatus())
+ .eqIfPresent(IotOrganizationDO::getDeviceType, reqVO.getDeviceType())
+ .eqIfPresent(IotOrganizationDO::getOrgClass, reqVO.getOrgClass())
+ .eqIfPresent(IotOrganizationDO::getMachineType, reqVO.getMachineType())
+ .orderByDesc(IotOrganizationDO::getId));
+ }
+
+ default IotOrganizationDO selectByParentIdAndName(Long parentId, String name) {
+ return selectOne(IotOrganizationDO::getParentId, parentId, IotOrganizationDO::getName, name);
+ }
+
+ default Long selectCountByParentId(Long parentId) {
+ return selectCount(IotOrganizationDO::getParentId, parentId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/kanban/KanbanMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/kanban/KanbanMapper.java
new file mode 100644
index 000000000..aa7a8f2fc
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/kanban/KanbanMapper.java
@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.kanban;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.kanban.KanbanDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.iot.controller.admin.kanban.vo.*;
+
+/**
+ * 物联看板 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface KanbanMapper extends BaseMapperX {
+
+ default PageResult selectPage(KanbanPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .eqIfPresent(KanbanDO::getCode, reqVO.getCode())
+ .eqIfPresent(KanbanDO::getTitle, reqVO.getTitle())
+ .eqIfPresent(KanbanDO::getImg, reqVO.getImg())
+ .eqIfPresent(KanbanDO::getRemark, reqVO.getRemark())
+ .eqIfPresent(KanbanDO::getIsEnable, reqVO.getIsEnable())
+ .betweenIfPresent(KanbanDO::getCreateTime, reqVO.getCreateTime())
+ .orderByDesc(KanbanDO::getId));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/security/config/SecurityConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/security/config/SecurityConfiguration.java
index bd59c82a6..74a05e6b2 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/security/config/SecurityConfiguration.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/security/config/SecurityConfiguration.java
@@ -24,7 +24,7 @@ public class SecurityConfiguration {
@Override
public void customize(ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry) {
- registry.antMatchers("/iot/**").permitAll(); // 积木报表
+ registry.antMatchers("/iot/open/**").permitAll(); // 积木报表
}
};
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/config/IotWebConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/config/IotWebConfiguration.java
new file mode 100644
index 000000000..40052d0c7
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/config/IotWebConfiguration.java
@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.iot.framework.web.config;
+
+import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration;
+import org.springdoc.core.GroupedOpenApi;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * mes 模块的 web 组件的 Configuration
+ *
+ * @author 芋道源码
+ */
+@Configuration(proxyBeanMethods = false)
+public class IotWebConfiguration {
+
+ /**
+ * crm 模块的 API 分组
+ */
+ @Bean
+ public GroupedOpenApi iotGroupedOpenApi() {
+ return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("iot");
+ }
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/package-info.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/package-info.java
new file mode 100644
index 000000000..755d12d4f
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/web/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * crm 模块的 web 拓展封装
+ */
+package cn.iocoder.yudao.module.iot.framework.web;
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java
new file mode 100644
index 000000000..aaf89ee20
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceService.java
@@ -0,0 +1,98 @@
+package cn.iocoder.yudao.module.iot.service.device;
+
+
+import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+
+import javax.validation.Valid;
+
+/**
+ * 物联设备 Service 接口
+ *
+ * @author 内蒙必硕
+ */
+public interface DeviceService {
+
+ /**
+ * 创建物联设备
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createDevice(@Valid DeviceSaveReqVO createReqVO);
+
+ /**
+ * 更新物联设备
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateDevice(@Valid DeviceSaveReqVO updateReqVO);
+
+ /**
+ * 删除物联设备
+ *
+ * @param id 编号
+ */
+ void deleteDevice(Long id);
+
+ /**
+ * 获得物联设备
+ *
+ * @param id 编号
+ * @return 物联设备
+ */
+ DeviceDO getDevice(Long id);
+
+ /**
+ * 获得物联设备分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 物联设备分页
+ */
+ PageResult getDevicePage(DevicePageReqVO pageReqVO);
+
+ // ==================== 子表(设备属性) ====================
+
+ /**
+ * 获得设备属性分页
+ *
+ * @param pageReqVO 分页查询
+ * @param deviceId 设备id
+ * @return 设备属性分页
+ */
+ PageResult getDeviceAttributePage(PageParam pageReqVO, Long deviceId);
+
+ /**
+ * 创建设备属性
+ *
+ * @param deviceAttribute 创建信息
+ * @return 编号
+ */
+ Long createDeviceAttribute(@Valid DeviceAttributeDO deviceAttribute);
+
+ /**
+ * 更新设备属性
+ *
+ * @param deviceAttribute 更新信息
+ */
+ void updateDeviceAttribute(@Valid DeviceAttributeDO deviceAttribute);
+
+ /**
+ * 删除设备属性
+ *
+ * @param id 编号
+ */
+ void deleteDeviceAttribute(Long id);
+
+ /**
+ * 获得设备属性
+ *
+ * @param id 编号
+ * @return 设备属性
+ */
+ DeviceAttributeDO getDeviceAttribute(Long id);
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java
new file mode 100644
index 000000000..005f5b587
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java
@@ -0,0 +1,127 @@
+package cn.iocoder.yudao.module.iot.service.device;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
+import org.springframework.stereotype.Service;
+
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceAttributeDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceAttributeMapper;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+
+/**
+ * 物联设备 Service 实现类
+ *
+ * @author 内蒙必硕
+ */
+@Service
+@Validated
+public class DeviceServiceImpl implements DeviceService {
+
+ @Resource
+ private DeviceMapper deviceMapper;
+ @Resource
+ private DeviceAttributeMapper deviceAttributeMapper;
+
+ @Override
+ public Long createDevice(DeviceSaveReqVO createReqVO) {
+ // 插入
+ DeviceDO device = BeanUtils.toBean(createReqVO, DeviceDO.class);
+ deviceMapper.insert(device);
+ // 返回
+ return device.getId();
+ }
+
+ @Override
+ public void updateDevice(DeviceSaveReqVO updateReqVO) {
+ // 校验存在
+ validateDeviceExists(updateReqVO.getId());
+ // 更新
+ DeviceDO updateObj = BeanUtils.toBean(updateReqVO, DeviceDO.class);
+ deviceMapper.updateById(updateObj);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteDevice(Long id) {
+ // 校验存在
+ validateDeviceExists(id);
+ // 删除
+ deviceMapper.deleteById(id);
+
+ // 删除子表
+ deleteDeviceAttributeByDeviceId(id);
+ }
+
+ private void validateDeviceExists(Long id) {
+ if (deviceMapper.selectById(id) == null) {
+ throw exception(DEVICE_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public DeviceDO getDevice(Long id) {
+ return deviceMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getDevicePage(DevicePageReqVO pageReqVO) {
+ return deviceMapper.selectPage(pageReqVO);
+ }
+
+ // ==================== 子表(设备属性) ====================
+
+ @Override
+ public PageResult getDeviceAttributePage(PageParam pageReqVO, Long deviceId) {
+ return deviceAttributeMapper.selectPage(pageReqVO, deviceId);
+ }
+
+ @Override
+ public Long createDeviceAttribute(DeviceAttributeDO deviceAttribute) {
+ deviceAttributeMapper.insert(deviceAttribute);
+ return deviceAttribute.getId();
+ }
+
+ @Override
+ public void updateDeviceAttribute(DeviceAttributeDO deviceAttribute) {
+ // 校验存在
+ validateDeviceAttributeExists(deviceAttribute.getId());
+ // 更新
+ deviceAttributeMapper.updateById(deviceAttribute);
+ }
+
+ @Override
+ public void deleteDeviceAttribute(Long id) {
+ // 校验存在
+ validateDeviceAttributeExists(id);
+ // 删除
+ deviceAttributeMapper.deleteById(id);
+ }
+
+ @Override
+ public DeviceAttributeDO getDeviceAttribute(Long id) {
+ return deviceAttributeMapper.selectById(id);
+ }
+
+ private void validateDeviceAttributeExists(Long id) {
+ if (deviceAttributeMapper.selectById(id) == null) {
+ throw exception(DEVICE_ATTRIBUTE_NOT_EXISTS);
+ }
+ }
+
+ private void deleteDeviceAttributeByDeviceId(Long deviceId) {
+ deviceAttributeMapper.deleteByDeviceId(deviceId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaService.java
new file mode 100644
index 000000000..833e1ef87
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaService.java
@@ -0,0 +1,97 @@
+package cn.iocoder.yudao.module.iot.service.formula;
+
+import javax.validation.Valid;
+import cn.iocoder.yudao.module.iot.controller.admin.formula.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDetailDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+
+/**
+ * 计算公式 Service 接口
+ *
+ * @author 内蒙必硕
+ */
+public interface FormulaService {
+
+ /**
+ * 创建计算公式
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createFormula(@Valid FormulaSaveReqVO createReqVO);
+
+ /**
+ * 更新计算公式
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateFormula(@Valid FormulaSaveReqVO updateReqVO);
+
+ /**
+ * 删除计算公式
+ *
+ * @param id 编号
+ */
+ void deleteFormula(Long id);
+
+ /**
+ * 获得计算公式
+ *
+ * @param id 编号
+ * @return 计算公式
+ */
+ FormulaDO getFormula(Long id);
+
+ /**
+ * 获得计算公式分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 计算公式分页
+ */
+ PageResult getFormulaPage(FormulaPageReqVO pageReqVO);
+
+ // ==================== 子表(计算公式明细) ====================
+
+ /**
+ * 获得计算公式明细分页
+ *
+ * @param pageReqVO 分页查询
+ * @param formulaId 计算公式ID
+ * @return 计算公式明细分页
+ */
+ PageResult getFormulaDetailPage(PageParam pageReqVO, Long formulaId);
+
+ /**
+ * 创建计算公式明细
+ *
+ * @param formulaDetail 创建信息
+ * @return 编号
+ */
+ Long createFormulaDetail(@Valid FormulaDetailDO formulaDetail);
+
+ /**
+ * 更新计算公式明细
+ *
+ * @param formulaDetail 更新信息
+ */
+ void updateFormulaDetail(@Valid FormulaDetailDO formulaDetail);
+
+ /**
+ * 删除计算公式明细
+ *
+ * @param id 编号
+ */
+ void deleteFormulaDetail(Long id);
+
+ /**
+ * 获得计算公式明细
+ *
+ * @param id 编号
+ * @return 计算公式明细
+ */
+ FormulaDetailDO getFormulaDetail(Long id);
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImpl.java
new file mode 100644
index 000000000..851806a82
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImpl.java
@@ -0,0 +1,126 @@
+package cn.iocoder.yudao.module.iot.service.formula;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import cn.iocoder.yudao.module.iot.controller.admin.formula.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDetailDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.iot.dal.mysql.formula.FormulaMapper;
+import cn.iocoder.yudao.module.iot.dal.mysql.formula.FormulaDetailMapper;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+
+/**
+ * 计算公式 Service 实现类
+ *
+ * @author 内蒙必硕
+ */
+@Service
+@Validated
+public class FormulaServiceImpl implements FormulaService {
+
+ @Resource
+ private FormulaMapper formulaMapper;
+ @Resource
+ private FormulaDetailMapper formulaDetailMapper;
+
+ @Override
+ public Long createFormula(FormulaSaveReqVO createReqVO) {
+ // 插入
+ FormulaDO formula = BeanUtils.toBean(createReqVO, FormulaDO.class);
+ formulaMapper.insert(formula);
+ // 返回
+ return formula.getId();
+ }
+
+ @Override
+ public void updateFormula(FormulaSaveReqVO updateReqVO) {
+ // 校验存在
+ validateFormulaExists(updateReqVO.getId());
+ // 更新
+ FormulaDO updateObj = BeanUtils.toBean(updateReqVO, FormulaDO.class);
+ formulaMapper.updateById(updateObj);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteFormula(Long id) {
+ // 校验存在
+ validateFormulaExists(id);
+ // 删除
+ formulaMapper.deleteById(id);
+
+ // 删除子表
+ deleteFormulaDetailByFormulaId(id);
+ }
+
+ private void validateFormulaExists(Long id) {
+ if (formulaMapper.selectById(id) == null) {
+ throw exception(FORMULA_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public FormulaDO getFormula(Long id) {
+ return formulaMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getFormulaPage(FormulaPageReqVO pageReqVO) {
+ return formulaMapper.selectPage(pageReqVO);
+ }
+
+ // ==================== 子表(计算公式明细) ====================
+
+ @Override
+ public PageResult getFormulaDetailPage(PageParam pageReqVO, Long formulaId) {
+ return formulaDetailMapper.selectPage(pageReqVO, formulaId);
+ }
+
+ @Override
+ public Long createFormulaDetail(FormulaDetailDO formulaDetail) {
+ formulaDetailMapper.insert(formulaDetail);
+ return formulaDetail.getId();
+ }
+
+ @Override
+ public void updateFormulaDetail(FormulaDetailDO formulaDetail) {
+ // 校验存在
+ validateFormulaDetailExists(formulaDetail.getId());
+ // 更新
+ formulaDetailMapper.updateById(formulaDetail);
+ }
+
+ @Override
+ public void deleteFormulaDetail(Long id) {
+ // 校验存在
+ validateFormulaDetailExists(id);
+ // 删除
+ formulaDetailMapper.deleteById(id);
+ }
+
+ @Override
+ public FormulaDetailDO getFormulaDetail(Long id) {
+ return formulaDetailMapper.selectById(id);
+ }
+
+ private void validateFormulaDetailExists(Long id) {
+ if (formulaDetailMapper.selectById(id) == null) {
+ throw exception(FORMULA_DETAIL_NOT_EXISTS);
+ }
+ }
+
+ private void deleteFormulaDetailByFormulaId(Long formulaId) {
+ formulaDetailMapper.deleteByFormulaId(formulaId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java
new file mode 100644
index 000000000..6cc34110c
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayService.java
@@ -0,0 +1,96 @@
+package cn.iocoder.yudao.module.iot.service.gateway;
+
+import javax.validation.Valid;
+import cn.iocoder.yudao.module.iot.controller.admin.gateway.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+/**
+ * 网关 Service 接口
+ *
+ * @author 内蒙必硕
+ */
+public interface GatewayService {
+
+ /**
+ * 创建网关
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createGateway(@Valid GatewaySaveReqVO createReqVO);
+
+ /**
+ * 更新网关
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateGateway(@Valid GatewaySaveReqVO updateReqVO);
+
+ /**
+ * 删除网关
+ *
+ * @param id 编号
+ */
+ void deleteGateway(Long id);
+
+ /**
+ * 获得网关
+ *
+ * @param id 编号
+ * @return 网关
+ */
+ GatewayDO getGateway(Long id);
+
+ /**
+ * 获得网关分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 网关分页
+ */
+ PageResult getGatewayPage(GatewayPageReqVO pageReqVO);
+
+ // ==================== 子表(物联设备) ====================
+
+ /**
+ * 获得物联设备分页
+ *
+ * @param pageReqVO 分页查询
+ * @param gatewayId 网关id
+ * @return 物联设备分页
+ */
+ PageResult getDevicePage(PageParam pageReqVO, Long gatewayId);
+
+ /**
+ * 创建物联设备
+ *
+ * @param device 创建信息
+ * @return 编号
+ */
+ Long createDevice(@Valid DeviceDO device);
+
+ /**
+ * 更新物联设备
+ *
+ * @param device 更新信息
+ */
+ void updateDevice(@Valid DeviceDO device);
+
+ /**
+ * 删除物联设备
+ *
+ * @param id 编号
+ */
+ void deleteDevice(Long id);
+
+ /**
+ * 获得物联设备
+ *
+ * @param id 编号
+ * @return 物联设备
+ */
+ DeviceDO getDevice(Long id);
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java
new file mode 100644
index 000000000..25ec07302
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImpl.java
@@ -0,0 +1,125 @@
+package cn.iocoder.yudao.module.iot.service.gateway;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import cn.iocoder.yudao.module.iot.controller.admin.gateway.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.iot.dal.mysql.gateway.GatewayMapper;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+
+/**
+ * 网关 Service 实现类
+ *
+ * @author 内蒙必硕
+ */
+@Service
+@Validated
+public class GatewayServiceImpl implements GatewayService {
+
+ @Resource
+ private GatewayMapper gatewayMapper;
+ @Resource
+ private DeviceMapper deviceMapper;
+
+ @Override
+ public Long createGateway(GatewaySaveReqVO createReqVO) {
+ // 插入
+ GatewayDO gateway = BeanUtils.toBean(createReqVO, GatewayDO.class);
+ gatewayMapper.insert(gateway);
+ // 返回
+ return gateway.getId();
+ }
+
+ @Override
+ public void updateGateway(GatewaySaveReqVO updateReqVO) {
+ // 校验存在
+ validateGatewayExists(updateReqVO.getId());
+ // 更新
+ GatewayDO updateObj = BeanUtils.toBean(updateReqVO, GatewayDO.class);
+ gatewayMapper.updateById(updateObj);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteGateway(Long id) {
+ // 校验存在
+ validateGatewayExists(id);
+ // 删除
+ gatewayMapper.deleteById(id);
+
+ // 删除子表
+ deleteDeviceByGatewayId(id);
+ }
+
+ private void validateGatewayExists(Long id) {
+ if (gatewayMapper.selectById(id) == null) {
+ throw exception(GATEWAY_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public GatewayDO getGateway(Long id) {
+ return gatewayMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getGatewayPage(GatewayPageReqVO pageReqVO) {
+ return gatewayMapper.selectPage(pageReqVO);
+ }
+
+ // ==================== 子表(物联设备) ====================
+
+ @Override
+ public PageResult getDevicePage(PageParam pageReqVO, Long gatewayId) {
+ return deviceMapper.selectPage(pageReqVO, gatewayId);
+ }
+
+ @Override
+ public Long createDevice(DeviceDO device) {
+ deviceMapper.insert(device);
+ return device.getId();
+ }
+
+ @Override
+ public void updateDevice(DeviceDO device) {
+ // 校验存在
+ validateDeviceExists(device.getId());
+ // 更新
+ deviceMapper.updateById(device);
+ }
+
+ @Override
+ public void deleteDevice(Long id) {
+ // 校验存在
+ validateDeviceExists(id);
+ // 删除
+ deviceMapper.deleteById(id);
+ }
+
+ @Override
+ public DeviceDO getDevice(Long id) {
+ return deviceMapper.selectById(id);
+ }
+
+ private void validateDeviceExists(Long id) {
+ if (deviceMapper.selectById(id) == null) {
+ throw exception(DEVICE_NOT_EXISTS);
+ }
+ }
+
+ private void deleteDeviceByGatewayId(Long gatewayId) {
+ deviceMapper.deleteByGatewayId(gatewayId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationService.java
new file mode 100644
index 000000000..c9de1e93a
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationService.java
@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.iot.service.iotorganization;
+
+import java.util.*;
+import javax.validation.Valid;
+import cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization.IotOrganizationDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+/**
+ * IOT组织 Service 接口
+ *
+ * @author 内蒙必硕
+ */
+public interface IotOrganizationService {
+
+ /**
+ * 创建IOT组织
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createOrganization(@Valid IotOrganizationSaveReqVO createReqVO);
+
+ /**
+ * 更新IOT组织
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateOrganization(@Valid IotOrganizationSaveReqVO updateReqVO);
+
+ /**
+ * 删除IOT组织
+ *
+ * @param id 编号
+ */
+ void deleteOrganization(Long id);
+
+ /**
+ * 获得IOT组织
+ *
+ * @param id 编号
+ * @return IOT组织
+ */
+ IotOrganizationDO getOrganization(Long id);
+
+ /**
+ * 获得IOT组织列表
+ *
+ * @param listReqVO 查询条件
+ * @return IOT组织列表
+ */
+ List getOrganizationList(IotOrganizationListReqVO listReqVO);
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImpl.java
new file mode 100644
index 000000000..3feb860a0
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImpl.java
@@ -0,0 +1,133 @@
+package cn.iocoder.yudao.module.iot.service.iotorganization;
+
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+import cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization.IotOrganizationDO;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.iot.dal.mysql.iotorganization.IotOrganizationMapper;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+
+/**
+ * IOT组织 Service 实现类
+ *
+ * @author 内蒙必硕
+ */
+@Service
+@Validated
+public class IotOrganizationServiceImpl implements IotOrganizationService {
+
+ @Resource
+ private IotOrganizationMapper iotOrganizationMapper;
+
+ @Override
+ public Long createOrganization(IotOrganizationSaveReqVO createReqVO) {
+ // 校验父组织id的有效性
+ validateParentOrganization(null, createReqVO.getParentId());
+ // 校验组织名称的唯一性
+ validateOrganizationNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
+
+ // 插入
+ IotOrganizationDO organization = BeanUtils.toBean(createReqVO, IotOrganizationDO.class);
+ iotOrganizationMapper.insert(organization);
+ // 返回
+ return organization.getId();
+ }
+
+ @Override
+ public void updateOrganization(IotOrganizationSaveReqVO updateReqVO) {
+ // 校验存在
+ validateOrganizationExists(updateReqVO.getId());
+ // 校验父组织id的有效性
+ validateParentOrganization(updateReqVO.getId(), updateReqVO.getParentId());
+ // 校验组织名称的唯一性
+ validateOrganizationNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
+
+ // 更新
+ IotOrganizationDO updateObj = BeanUtils.toBean(updateReqVO, IotOrganizationDO.class);
+ iotOrganizationMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteOrganization(Long id) {
+ // 校验存在
+ validateOrganizationExists(id);
+ // 校验是否有子IOT组织
+ if (iotOrganizationMapper.selectCountByParentId(id) > 0) {
+ throw exception(ORGANIZATION_EXITS_CHILDREN);
+ }
+ // 删除
+ iotOrganizationMapper.deleteById(id);
+ }
+
+ private void validateOrganizationExists(Long id) {
+ if (iotOrganizationMapper.selectById(id) == null) {
+ throw exception(ORGANIZATION_NOT_EXISTS);
+ }
+ }
+
+ private void validateParentOrganization(Long id, Long parentId) {
+ if (parentId == null || IotOrganizationDO.PARENT_ID_ROOT.equals(parentId)) {
+ return;
+ }
+ // 1. 不能设置自己为父IOT组织
+ if (Objects.equals(id, parentId)) {
+ throw exception(ORGANIZATION_PARENT_ERROR);
+ }
+ // 2. 父IOT组织不存在
+ IotOrganizationDO parentOrganization = iotOrganizationMapper.selectById(parentId);
+ if (parentOrganization == null) {
+ throw exception(ORGANIZATION_PARENT_NOT_EXITS);
+ }
+ // 3. 递归校验父IOT组织,如果父IOT组织是自己的子IOT组织,则报错,避免形成环路
+ if (id == null) { // id 为空,说明新增,不需要考虑环路
+ return;
+ }
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
+ // 3.1 校验环路
+ parentId = parentOrganization.getParentId();
+ if (Objects.equals(id, parentId)) {
+ throw exception(ORGANIZATION_PARENT_IS_CHILD);
+ }
+ // 3.2 继续递归下一级父IOT组织
+ if (parentId == null || IotOrganizationDO.PARENT_ID_ROOT.equals(parentId)) {
+ break;
+ }
+ parentOrganization = iotOrganizationMapper.selectById(parentId);
+ if (parentOrganization == null) {
+ break;
+ }
+ }
+ }
+
+ private void validateOrganizationNameUnique(Long id, Long parentId, String name) {
+ IotOrganizationDO organization = iotOrganizationMapper.selectByParentIdAndName(parentId, name);
+ if (organization == null) {
+ return;
+ }
+ // 如果 id 为空,说明不用比较是否为相同 id 的IOT组织
+ if (id == null) {
+ throw exception(ORGANIZATION_NAME_DUPLICATE);
+ }
+ if (!Objects.equals(organization.getId(), id)) {
+ throw exception(ORGANIZATION_NAME_DUPLICATE);
+ }
+ }
+
+ @Override
+ public IotOrganizationDO getOrganization(Long id) {
+ return iotOrganizationMapper.selectById(id);
+ }
+
+ @Override
+ public List getOrganizationList(IotOrganizationListReqVO listReqVO) {
+ return iotOrganizationMapper.selectList(listReqVO);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanService.java
new file mode 100644
index 000000000..be6821858
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanService.java
@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.iot.service.kanban;
+
+import javax.validation.Valid;
+import cn.iocoder.yudao.module.iot.controller.admin.kanban.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.kanban.KanbanDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+/**
+ * 物联看板 Service 接口
+ *
+ * @author 内蒙必硕
+ */
+public interface KanbanService {
+
+ /**
+ * 创建物联看板
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createKanban(@Valid KanbanSaveReqVO createReqVO);
+
+ /**
+ * 更新物联看板
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateKanban(@Valid KanbanSaveReqVO updateReqVO);
+
+ /**
+ * 删除物联看板
+ *
+ * @param id 编号
+ */
+ void deleteKanban(Long id);
+
+ /**
+ * 获得物联看板
+ *
+ * @param id 编号
+ * @return 物联看板
+ */
+ KanbanDO getKanban(Long id);
+
+ /**
+ * 获得物联看板分页
+ *
+ * @param pageReqVO 分页查询
+ * @return 物联看板分页
+ */
+ PageResult getKanbanPage(KanbanPageReqVO pageReqVO);
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImpl.java
new file mode 100644
index 000000000..83f76d6fb
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImpl.java
@@ -0,0 +1,76 @@
+package cn.iocoder.yudao.module.iot.service.kanban;
+
+import org.springframework.stereotype.Service;
+
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import cn.iocoder.yudao.module.iot.controller.admin.kanban.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.kanban.KanbanDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.iot.dal.mysql.kanban.KanbanMapper;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+
+/**
+ * 物联看板 Service 实现类
+ *
+ * @author 内蒙必硕
+ */
+@Service
+@Validated
+public class KanbanServiceImpl implements KanbanService {
+
+ @Resource
+ private KanbanMapper kanbanMapper;
+
+ @Override
+ public Long createKanban(KanbanSaveReqVO createReqVO) {
+ // 插入
+ KanbanDO kanban = BeanUtils.toBean(createReqVO, KanbanDO.class);
+ kanbanMapper.insert(kanban);
+ // 返回
+ return kanban.getId();
+ }
+
+ @Override
+ public void updateKanban(KanbanSaveReqVO updateReqVO) {
+ // 校验存在
+ validateKanbanExists(updateReqVO.getId());
+ // 更新
+ KanbanDO updateObj = BeanUtils.toBean(updateReqVO, KanbanDO.class);
+ kanbanMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteKanban(Long id) {
+ // 校验存在
+ validateKanbanExists(id);
+ // 删除
+ kanbanMapper.deleteById(id);
+ }
+
+ private void validateKanbanExists(Long id) {
+ if (kanbanMapper.selectById(id) == null) {
+ throw exception(KANBAN_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public KanbanDO getKanban(Long id) {
+ return kanbanMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getKanbanPage(KanbanPageReqVO pageReqVO) {
+ return kanbanMapper.selectPage(pageReqVO);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml
new file mode 100644
index 000000000..548b593d6
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/DeviceMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/formula/FormulaMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/formula/FormulaMapper.xml
new file mode 100644
index 000000000..40ee6dc37
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/formula/FormulaMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/gateway/GatewayMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/gateway/GatewayMapper.xml
new file mode 100644
index 000000000..a6dd8190f
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/gateway/GatewayMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotorganization/IotOrganizationMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotorganization/IotOrganizationMapper.xml
new file mode 100644
index 000000000..2afab458a
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotorganization/IotOrganizationMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/kanban/KanbanMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/kanban/KanbanMapper.xml
new file mode 100644
index 000000000..209bce2b2
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/kanban/KanbanMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java
new file mode 100644
index 000000000..a3d889112
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImplTest.java
@@ -0,0 +1,231 @@
+package cn.iocoder.yudao.module.iot.service.device;
+
+import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.device.DeviceMapper;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * {@link DeviceServiceImpl} 的单元测试类
+ *
+ * @author 内蒙必硕
+ */
+@Import(DeviceServiceImpl.class)
+public class DeviceServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private DeviceServiceImpl deviceService;
+
+ @Resource
+ private DeviceMapper deviceMapper;
+
+ @Test
+ public void testCreateDevice_success() {
+ // 准备参数
+ DeviceSaveReqVO createReqVO = randomPojo(DeviceSaveReqVO.class).setId(null);
+
+ // 调用
+ Long deviceId = deviceService.createDevice(createReqVO);
+ // 断言
+ assertNotNull(deviceId);
+ // 校验记录的属性是否正确
+ DeviceDO device = deviceMapper.selectById(deviceId);
+ assertPojoEquals(createReqVO, device, "id");
+ }
+
+ @Test
+ public void testUpdateDevice_success() {
+ // mock 数据
+ DeviceDO dbDevice = randomPojo(DeviceDO.class);
+ deviceMapper.insert(dbDevice);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ DeviceSaveReqVO updateReqVO = randomPojo(DeviceSaveReqVO.class, o -> {
+ o.setId(dbDevice.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ deviceService.updateDevice(updateReqVO);
+ // 校验是否更新正确
+ DeviceDO device = deviceMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, device);
+ }
+
+ @Test
+ public void testUpdateDevice_notExists() {
+ // 准备参数
+ DeviceSaveReqVO updateReqVO = randomPojo(DeviceSaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> deviceService.updateDevice(updateReqVO), DEVICE_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteDevice_success() {
+ // mock 数据
+ DeviceDO dbDevice = randomPojo(DeviceDO.class);
+ deviceMapper.insert(dbDevice);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbDevice.getId();
+
+ // 调用
+ deviceService.deleteDevice(id);
+ // 校验数据不存在了
+ assertNull(deviceMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteDevice_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> deviceService.deleteDevice(id), DEVICE_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetDevicePage() {
+ // mock 数据
+ DeviceDO dbDevice = randomPojo(DeviceDO.class, o -> { // 等会查询到
+ o.setDeviceConfigId(null);
+ o.setDeviceCode(null);
+ o.setDeviceName(null);
+ o.setDeviceType(null);
+ o.setSiemensSeries(null);
+ o.setSiemensConnectParam(null);
+ o.setReadCronType(null);
+ o.setReadRepeatValue(null);
+ o.setReadRepeatUnit(null);
+ o.setReadCron(null);
+ o.setWriteCronType(null);
+ o.setWriteRepeatValue(null);
+ o.setWriteRepeatUnit(null);
+ o.setWriteCron(null);
+ o.setLocalPersistent(null);
+ o.setUploadRate(null);
+ o.setRateCount(null);
+ o.setModbusProtocol(null);
+ o.setModbusPattern(null);
+ o.setPortName(null);
+ o.setModbusConnectParam(null);
+ o.setModbusReadAddrGap(null);
+ o.setIsUpload(null);
+ o.setGatewayId(null);
+ o.setOrgId(null);
+ o.setRemark(null);
+ o.setIsEnable(null);
+ o.setCreateTime(null);
+ });
+ deviceMapper.insert(dbDevice);
+ // 测试 deviceConfigId 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setDeviceConfigId(null)));
+ // 测试 deviceCode 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setDeviceCode(null)));
+ // 测试 deviceName 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setDeviceName(null)));
+ // 测试 deviceType 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setDeviceType(null)));
+ // 测试 siemensSeries 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setSiemensSeries(null)));
+ // 测试 siemensConnectParam 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setSiemensConnectParam(null)));
+ // 测试 readCronType 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setReadCronType(null)));
+ // 测试 readRepeatValue 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setReadRepeatValue(null)));
+ // 测试 readRepeatUnit 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setReadRepeatUnit(null)));
+ // 测试 readCron 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setReadCron(null)));
+ // 测试 writeCronType 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setWriteCronType(null)));
+ // 测试 writeRepeatValue 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setWriteRepeatValue(null)));
+ // 测试 writeRepeatUnit 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setWriteRepeatUnit(null)));
+ // 测试 writeCron 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setWriteCron(null)));
+ // 测试 localPersistent 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setLocalPersistent(null)));
+ // 测试 uploadRate 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setUploadRate(null)));
+ // 测试 rateCount 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setRateCount(null)));
+ // 测试 modbusProtocol 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setModbusProtocol(null)));
+ // 测试 modbusPattern 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setModbusPattern(null)));
+ // 测试 portName 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setPortName(null)));
+ // 测试 modbusConnectParam 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setModbusConnectParam(null)));
+ // 测试 modbusReadAddrGap 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setModbusReadAddrGap(null)));
+ // 测试 isUpload 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setIsUpload(null)));
+ // 测试 gatewayId 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setGatewayId(null)));
+ // 测试 orgId 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setOrgId(null)));
+ // 测试 remark 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setRemark(null)));
+ // 测试 isEnable 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setIsEnable(null)));
+ // 测试 createTime 不匹配
+ deviceMapper.insert(cloneIgnoreId(dbDevice, o -> o.setCreateTime(null)));
+ // 准备参数
+ DevicePageReqVO reqVO = new DevicePageReqVO();
+ reqVO.setDeviceConfigId(null);
+ reqVO.setDeviceCode(null);
+ reqVO.setDeviceName(null);
+ reqVO.setDeviceType(null);
+ reqVO.setSiemensSeries(null);
+ reqVO.setSiemensConnectParam(null);
+ reqVO.setReadCronType(null);
+ reqVO.setReadRepeatValue(null);
+ reqVO.setReadRepeatUnit(null);
+ reqVO.setReadCron(null);
+ reqVO.setWriteCronType(null);
+ reqVO.setWriteRepeatValue(null);
+ reqVO.setWriteRepeatUnit(null);
+ reqVO.setWriteCron(null);
+ reqVO.setLocalPersistent(null);
+ reqVO.setUploadRate(null);
+ reqVO.setRateCount(null);
+ reqVO.setModbusProtocol(null);
+ reqVO.setModbusPattern(null);
+ reqVO.setPortName(null);
+ reqVO.setModbusConnectParam(null);
+ reqVO.setModbusReadAddrGap(null);
+ reqVO.setIsUpload(null);
+ reqVO.setGatewayId(null);
+ reqVO.setOrgId(null);
+ reqVO.setRemark(null);
+ reqVO.setIsEnable(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+ // 调用
+ PageResult pageResult = deviceService.getDevicePage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbDevice, pageResult.getList().get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImplTest.java
new file mode 100644
index 000000000..07e315e6c
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/formula/FormulaServiceImplTest.java
@@ -0,0 +1,160 @@
+package cn.iocoder.yudao.module.iot.service.formula;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.iot.controller.admin.formula.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.formula.FormulaDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.formula.FormulaMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link FormulaServiceImpl} 的单元测试类
+ *
+ * @author 内蒙必硕
+ */
+@Import(FormulaServiceImpl.class)
+public class FormulaServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private FormulaServiceImpl formulaService;
+
+ @Resource
+ private FormulaMapper formulaMapper;
+
+ @Test
+ public void testCreateFormula_success() {
+ // 准备参数
+ FormulaSaveReqVO createReqVO = randomPojo(FormulaSaveReqVO.class).setId(null);
+
+ // 调用
+ Long formulaId = formulaService.createFormula(createReqVO);
+ // 断言
+ assertNotNull(formulaId);
+ // 校验记录的属性是否正确
+ FormulaDO formula = formulaMapper.selectById(formulaId);
+ assertPojoEquals(createReqVO, formula, "id");
+ }
+
+ @Test
+ public void testUpdateFormula_success() {
+ // mock 数据
+ FormulaDO dbFormula = randomPojo(FormulaDO.class);
+ formulaMapper.insert(dbFormula);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ FormulaSaveReqVO updateReqVO = randomPojo(FormulaSaveReqVO.class, o -> {
+ o.setId(dbFormula.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ formulaService.updateFormula(updateReqVO);
+ // 校验是否更新正确
+ FormulaDO formula = formulaMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, formula);
+ }
+
+ @Test
+ public void testUpdateFormula_notExists() {
+ // 准备参数
+ FormulaSaveReqVO updateReqVO = randomPojo(FormulaSaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> formulaService.updateFormula(updateReqVO), FORMULA_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteFormula_success() {
+ // mock 数据
+ FormulaDO dbFormula = randomPojo(FormulaDO.class);
+ formulaMapper.insert(dbFormula);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbFormula.getId();
+
+ // 调用
+ formulaService.deleteFormula(id);
+ // 校验数据不存在了
+ assertNull(formulaMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteFormula_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> formulaService.deleteFormula(id), FORMULA_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetFormulaPage() {
+ // mock 数据
+ FormulaDO dbFormula = randomPojo(FormulaDO.class, o -> { // 等会查询到
+ o.setName(null);
+ o.setFormulaCode(null);
+ o.setFormula(null);
+ o.setResultType(null);
+ o.setMachineId(null);
+ o.setRemark(null);
+ o.setIsEnable(null);
+ o.setCreateTime(null);
+ });
+ formulaMapper.insert(dbFormula);
+ // 测试 name 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setName(null)));
+ // 测试 formulaCode 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setFormulaCode(null)));
+ // 测试 formula 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setFormula(null)));
+ // 测试 resultType 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setResultType(null)));
+ // 测试 machineId 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setMachineId(null)));
+ // 测试 remark 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setRemark(null)));
+ // 测试 isEnable 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setIsEnable(null)));
+ // 测试 createTime 不匹配
+ formulaMapper.insert(cloneIgnoreId(dbFormula, o -> o.setCreateTime(null)));
+ // 准备参数
+ FormulaPageReqVO reqVO = new FormulaPageReqVO();
+ reqVO.setName(null);
+ reqVO.setFormulaCode(null);
+ reqVO.setFormula(null);
+ reqVO.setResultType(null);
+ reqVO.setMachineId(null);
+ reqVO.setRemark(null);
+ reqVO.setIsEnable(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+ // 调用
+ PageResult pageResult = formulaService.getFormulaPage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbFormula, pageResult.getList().get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImplTest.java
new file mode 100644
index 000000000..9c78970cc
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/gateway/GatewayServiceImplTest.java
@@ -0,0 +1,168 @@
+package cn.iocoder.yudao.module.iot.service.gateway;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.iot.controller.admin.gateway.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.gateway.GatewayDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.gateway.GatewayMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link GatewayServiceImpl} 的单元测试类
+ *
+ * @author 内蒙必硕
+ */
+@Import(GatewayServiceImpl.class)
+public class GatewayServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private GatewayServiceImpl gatewayService;
+
+ @Resource
+ private GatewayMapper gatewayMapper;
+
+ @Test
+ public void testCreateGateway_success() {
+ // 准备参数
+ GatewaySaveReqVO createReqVO = randomPojo(GatewaySaveReqVO.class).setId(null);
+
+ // 调用
+ Long gatewayId = gatewayService.createGateway(createReqVO);
+ // 断言
+ assertNotNull(gatewayId);
+ // 校验记录的属性是否正确
+ GatewayDO gateway = gatewayMapper.selectById(gatewayId);
+ assertPojoEquals(createReqVO, gateway, "id");
+ }
+
+ @Test
+ public void testUpdateGateway_success() {
+ // mock 数据
+ GatewayDO dbGateway = randomPojo(GatewayDO.class);
+ gatewayMapper.insert(dbGateway);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ GatewaySaveReqVO updateReqVO = randomPojo(GatewaySaveReqVO.class, o -> {
+ o.setId(dbGateway.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ gatewayService.updateGateway(updateReqVO);
+ // 校验是否更新正确
+ GatewayDO gateway = gatewayMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, gateway);
+ }
+
+ @Test
+ public void testUpdateGateway_notExists() {
+ // 准备参数
+ GatewaySaveReqVO updateReqVO = randomPojo(GatewaySaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> gatewayService.updateGateway(updateReqVO), GATEWAY_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteGateway_success() {
+ // mock 数据
+ GatewayDO dbGateway = randomPojo(GatewayDO.class);
+ gatewayMapper.insert(dbGateway);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbGateway.getId();
+
+ // 调用
+ gatewayService.deleteGateway(id);
+ // 校验数据不存在了
+ assertNull(gatewayMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteGateway_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> gatewayService.deleteGateway(id), GATEWAY_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetGatewayPage() {
+ // mock 数据
+ GatewayDO dbGateway = randomPojo(GatewayDO.class, o -> { // 等会查询到
+ o.setAdminIp(null);
+ o.setUsername(null);
+ o.setPassword(null);
+ o.setGatewayName(null);
+ o.setRemark(null);
+ o.setIsEnable(null);
+ o.setCreateTime(null);
+ o.setGatewayCode(null);
+ o.setGatewayStatus(null);
+ o.setTopic(null);
+ });
+ gatewayMapper.insert(dbGateway);
+ // 测试 adminIp 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setAdminIp(null)));
+ // 测试 username 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setUsername(null)));
+ // 测试 password 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setPassword(null)));
+ // 测试 gatewayName 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setGatewayName(null)));
+ // 测试 remark 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setRemark(null)));
+ // 测试 isEnable 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setIsEnable(null)));
+ // 测试 createTime 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setCreateTime(null)));
+ // 测试 gatewayCode 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setGatewayCode(null)));
+ // 测试 gatewayStatus 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setGatewayStatus(null)));
+ // 测试 topic 不匹配
+ gatewayMapper.insert(cloneIgnoreId(dbGateway, o -> o.setTopic(null)));
+ // 准备参数
+ GatewayPageReqVO reqVO = new GatewayPageReqVO();
+ reqVO.setAdminIp(null);
+ reqVO.setUsername(null);
+ reqVO.setPassword(null);
+ reqVO.setGatewayName(null);
+ reqVO.setRemark(null);
+ reqVO.setIsEnable(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setGatewayCode(null);
+ reqVO.setGatewayStatus(null);
+ reqVO.setTopic(null);
+
+ // 调用
+ PageResult pageResult = gatewayService.getGatewayPage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbGateway, pageResult.getList().get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImplTest.java
new file mode 100644
index 000000000..a4058ae0f
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/iotorganization/IotOrganizationServiceImplTest.java
@@ -0,0 +1,165 @@
+package cn.iocoder.yudao.module.iot.service.iotorganization;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.iot.controller.admin.iotorganization.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.iotorganization.IotOrganizationDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.iotorganization.IotOrganizationMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+
+import org.springframework.context.annotation.Import;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link IotOrganizationServiceImpl} 的单元测试类
+ *
+ * @author 内蒙必硕
+ */
+@Import(IotOrganizationServiceImpl.class)
+public class IotOrganizationServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private IotOrganizationServiceImpl organizationService;
+
+ @Resource
+ private IotOrganizationMapper organizationMapper;
+
+ @Test
+ public void testCreateOrganization_success() {
+ // 准备参数
+ IotOrganizationSaveReqVO createReqVO = randomPojo(IotOrganizationSaveReqVO.class).setId(null);
+
+ // 调用
+ Long organizationId = organizationService.createOrganization(createReqVO);
+ // 断言
+ assertNotNull(organizationId);
+ // 校验记录的属性是否正确
+ IotOrganizationDO organization = organizationMapper.selectById(organizationId);
+ assertPojoEquals(createReqVO, organization, "id");
+ }
+
+ @Test
+ public void testUpdateOrganization_success() {
+ // mock 数据
+ IotOrganizationDO dbOrganization = randomPojo(IotOrganizationDO.class);
+ organizationMapper.insert(dbOrganization);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ IotOrganizationSaveReqVO updateReqVO = randomPojo(IotOrganizationSaveReqVO.class, o -> {
+ o.setId(dbOrganization.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ organizationService.updateOrganization(updateReqVO);
+ // 校验是否更新正确
+ IotOrganizationDO organization = organizationMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, organization);
+ }
+
+ @Test
+ public void testUpdateOrganization_notExists() {
+ // 准备参数
+ IotOrganizationSaveReqVO updateReqVO = randomPojo(IotOrganizationSaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> organizationService.updateOrganization(updateReqVO), ORGANIZATION_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteOrganization_success() {
+ // mock 数据
+ IotOrganizationDO dbOrganization = randomPojo(IotOrganizationDO.class);
+ organizationMapper.insert(dbOrganization);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbOrganization.getId();
+
+ // 调用
+ organizationService.deleteOrganization(id);
+ // 校验数据不存在了
+ assertNull(organizationMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteOrganization_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> organizationService.deleteOrganization(id), ORGANIZATION_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetOrganizationList() {
+ // mock 数据
+ IotOrganizationDO dbOrganization = randomPojo(IotOrganizationDO.class, o -> { // 等会查询到
+ o.setSort(null);
+ o.setWorkerUserId(null);
+ o.setOrgId(null);
+ o.setCreateTime(null);
+ o.setName(null);
+ o.setParentId(null);
+ o.setStatus(null);
+ o.setDeviceType(null);
+ o.setOrgClass(null);
+ o.setMachineType(null);
+ });
+ organizationMapper.insert(dbOrganization);
+ // 测试 sort 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setSort(null)));
+ // 测试 workerUserId 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setWorkerUserId(null)));
+ // 测试 orgId 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setOrgId(null)));
+ // 测试 createTime 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setCreateTime(null)));
+ // 测试 name 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setName(null)));
+ // 测试 parentId 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setParentId(null)));
+ // 测试 status 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setStatus(null)));
+ // 测试 deviceType 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setDeviceType(null)));
+ // 测试 orgClass 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setOrgClass(null)));
+ // 测试 machineType 不匹配
+ organizationMapper.insert(cloneIgnoreId(dbOrganization, o -> o.setMachineType(null)));
+ // 准备参数
+ IotOrganizationListReqVO reqVO = new IotOrganizationListReqVO();
+ reqVO.setSort(null);
+ reqVO.setWorkerUserId(null);
+ reqVO.setOrgId(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setName(null);
+ reqVO.setParentId(null);
+ reqVO.setStatus(null);
+ reqVO.setDeviceType(null);
+ reqVO.setOrgClass(null);
+ reqVO.setMachineType(null);
+
+ // 调用
+ List list = organizationService.getOrganizationList(reqVO);
+ // 断言
+ assertEquals(1, list.size());
+ assertPojoEquals(dbOrganization, list.get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImplTest.java
new file mode 100644
index 000000000..51aaef1fe
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/kanban/KanbanServiceImplTest.java
@@ -0,0 +1,150 @@
+package cn.iocoder.yudao.module.iot.service.kanban;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.iot.controller.admin.kanban.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.kanban.KanbanDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.kanban.KanbanMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+
+import org.springframework.context.annotation.Import;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link KanbanServiceImpl} 的单元测试类
+ *
+ * @author 内蒙必硕
+ */
+@Import(KanbanServiceImpl.class)
+public class KanbanServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private KanbanServiceImpl kanbanService;
+
+ @Resource
+ private KanbanMapper kanbanMapper;
+
+ @Test
+ public void testCreateKanban_success() {
+ // 准备参数
+ KanbanSaveReqVO createReqVO = randomPojo(KanbanSaveReqVO.class).setId(null);
+
+ // 调用
+ Long kanbanId = kanbanService.createKanban(createReqVO);
+ // 断言
+ assertNotNull(kanbanId);
+ // 校验记录的属性是否正确
+ KanbanDO kanban = kanbanMapper.selectById(kanbanId);
+ assertPojoEquals(createReqVO, kanban, "id");
+ }
+
+ @Test
+ public void testUpdateKanban_success() {
+ // mock 数据
+ KanbanDO dbKanban = randomPojo(KanbanDO.class);
+ kanbanMapper.insert(dbKanban);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ KanbanSaveReqVO updateReqVO = randomPojo(KanbanSaveReqVO.class, o -> {
+ o.setId(dbKanban.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ kanbanService.updateKanban(updateReqVO);
+ // 校验是否更新正确
+ KanbanDO kanban = kanbanMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, kanban);
+ }
+
+ @Test
+ public void testUpdateKanban_notExists() {
+ // 准备参数
+ KanbanSaveReqVO updateReqVO = randomPojo(KanbanSaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> kanbanService.updateKanban(updateReqVO), KANBAN_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteKanban_success() {
+ // mock 数据
+ KanbanDO dbKanban = randomPojo(KanbanDO.class);
+ kanbanMapper.insert(dbKanban);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbKanban.getId();
+
+ // 调用
+ kanbanService.deleteKanban(id);
+ // 校验数据不存在了
+ assertNull(kanbanMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteKanban_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> kanbanService.deleteKanban(id), KANBAN_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetKanbanPage() {
+ // mock 数据
+ KanbanDO dbKanban = randomPojo(KanbanDO.class, o -> { // 等会查询到
+ o.setCode(null);
+ o.setTitle(null);
+ o.setImg(null);
+ o.setRemark(null);
+ o.setIsEnable(null);
+ o.setCreateTime(null);
+ });
+ kanbanMapper.insert(dbKanban);
+ // 测试 code 不匹配
+ kanbanMapper.insert(cloneIgnoreId(dbKanban, o -> o.setCode(null)));
+ // 测试 title 不匹配
+ kanbanMapper.insert(cloneIgnoreId(dbKanban, o -> o.setTitle(null)));
+ // 测试 img 不匹配
+ kanbanMapper.insert(cloneIgnoreId(dbKanban, o -> o.setImg(null)));
+ // 测试 remark 不匹配
+ kanbanMapper.insert(cloneIgnoreId(dbKanban, o -> o.setRemark(null)));
+ // 测试 isEnable 不匹配
+ kanbanMapper.insert(cloneIgnoreId(dbKanban, o -> o.setIsEnable(null)));
+ // 测试 createTime 不匹配
+ kanbanMapper.insert(cloneIgnoreId(dbKanban, o -> o.setCreateTime(null)));
+ // 准备参数
+ KanbanPageReqVO reqVO = new KanbanPageReqVO();
+ reqVO.setCode(null);
+ reqVO.setTitle(null);
+ reqVO.setImg(null);
+ reqVO.setRemark(null);
+ reqVO.setIsEnable(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+
+ // 调用
+ PageResult pageResult = kanbanService.getKanbanPage(reqVO);
+ // 断言
+ assertEquals(1, pageResult.getTotal());
+ assertEquals(1, pageResult.getList().size());
+ assertPojoEquals(dbKanban, pageResult.getList().get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/clean.sql b/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/clean.sql
index 152915143..3e1936e76 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/clean.sql
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/clean.sql
@@ -1 +1,23 @@
-DELETE FROM "report_go_view_project";
\ No newline at end of file
+
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_device";
+
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_formula";
+
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_device_attribute";
+
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_formula_detail";
+
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_gateway";
+
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_iot_organization";
+-- 将该删表 SQL 语句,添加到 yudao-module-iot-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "iot_kanban";
+
+-- 将该删表 SQL 语句,添加到 yudao-module-mes-biz 模块的 test/resources/sql/clean.sql 文件里
+DELETE FROM "mes_machine_component";
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql b/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql
index a77397fea..575033d30 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql
@@ -1,14 +1,209 @@
-CREATE TABLE IF NOT EXISTS "report_go_view_project" (
- "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
- "name" varchar NOT NULL,
- "pic_url" varchar,
- "content" varchar,
- "status" varchar NOT NULL,
- "remark" varchar,
- "creator" varchar DEFAULT '',
+CREATE TABLE IF NOT EXISTS "iot_device"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "device_config_id" varchar,
+ "device_code" varchar,
+ "device_name" varchar,
+ "device_type" varchar,
+ "siemens_series" varchar,
+ "siemens_connect_param" varchar,
+ "read_cron_type" varchar,
+ "read_repeat_value" int,
+ "read_repeat_unit" varchar,
+ "read_cron" varchar,
+ "write_cron_type" varchar,
+ "write_repeat_value" int,
+ "write_repeat_unit" varchar,
+ "write_cron" varchar,
+ "local_persistent" varchar,
+ "upload_rate" varchar,
+ "rate_count" int,
+ "modbus_protocol" varchar,
+ "modbus_pattern" varchar,
+ "port_name" varchar,
+ "modbus_connect_param" varchar,
+ "modbus_read_addr_gap" varchar,
+ "is_upload" varchar,
+ "gateway_id" bigint NOT NULL,
+ "org_id" bigint NOT NULL,
+ "remark" varchar,
+ "is_enable" bit NOT NULL,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint,
+ PRIMARY KEY ("id")
+) COMMENT '物联设备表';
+CREATE TABLE IF NOT EXISTS "iot_formula"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "name" varchar,
+ "formula_code" varchar,
+ "formula" varchar,
+ "result_type" varchar,
+ "machine_id" bigint NOT NULL,
+ "remark" varchar,
+ "is_enable" bit NOT NULL,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint,
+ PRIMARY KEY ("id")
+) COMMENT '计算公式';
+CREATE TABLE IF NOT EXISTS "iot_device_attribute"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "attribute_code" varchar NOT NULL,
+ "address" varchar,
+ "attribute_name" varchar NOT NULL,
+ "description" varchar,
+ "address_type" varchar,
+ "address_offset" varchar,
+ "address2_type" varchar,
+ "address2_offset" varchar,
+ "group_name" varchar,
+ "group_id" int,
+ "security_type" varchar,
+ "io_status" varchar,
+ "is_linear_transfer" varchar,
+ "data_type" varchar,
+ "unit" varchar,
+ "in_min_value" varchar,
+ "in_max_value" varchar,
+ "out_min_value" varchar,
+ "out_max_value" varchar,
+ "out_data_type" varchar,
+ "siemens_field_precision" int,
+ "modbus_slave_id" varchar,
+ "modbus_field_address" varchar,
+ "modbus_address_type" varchar,
+ "modbus_field_size" varchar,
+ "modbus_field_precision" varchar,
+ "modbus_field_order" varchar,
+ "source_data_type" varchar,
+ "transfer_data_type" varchar,
+ "factor" varchar,
+ "gateway_id" bigint NOT NULL,
+ "device_id" bigint NOT NULL,
+ "org_id" bigint NOT NULL,
+ "remark" varchar,
+ "is_enable" bit NOT NULL,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint,
+ PRIMARY KEY ("id")
+) COMMENT '设备属性表';
+CREATE TABLE IF NOT EXISTS "iot_formula_detail"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "formula_id" bigint NOT NULL,
+ "formula_code" varchar,
+ "name" varchar,
+ "device_id" bigint NOT NULL,
+ "attribute_id" bigint NOT NULL,
+ "attribute_name" varchar NOT NULL,
+ "address" varchar,
+ "demo_value" varchar,
+ "sum_type" varchar,
+ "sum_range" varchar,
+ "remark" varchar,
+ "is_enable" bit NOT NULL,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint,
+ PRIMARY KEY ("id")
+) COMMENT '计算公式明细';
+
+CREATE TABLE IF NOT EXISTS "iot_gateway"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "admin_ip" varchar,
+ "username" varchar,
+ "password" varchar,
+ "gateway_name" varchar,
+ "remark" varchar,
+ "is_enable" bit NOT NULL,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint,
+ "gateway_code" varchar,
+ "gateway_status" varchar,
+ "topic" varchar,
+ PRIMARY KEY ("id")
+) COMMENT '网关表';
+CREATE TABLE IF NOT EXISTS "iot_iot_organization"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "sort" int,
+ "worker_user_id" bigint,
+ "org_id" bigint,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint NOT NULL,
+ "name" varchar NOT NULL,
+ "parent_id" bigint NOT NULL,
+ "status" int,
+ "device_type" varchar,
+ "org_class" varchar,
+ "machine_type" varchar,
+ PRIMARY KEY ("id")
+) COMMENT 'IOT组织表';
+CREATE TABLE IF NOT EXISTS "iot_kanban"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "code" varchar NOT NULL,
+ "title" varchar NOT NULL,
+ "view_url" varchar,
+ "tags" varchar,
+ "img" varchar,
+ "remark" varchar,
+ "is_enable" bit NOT NULL,
+ "creator" varchar DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
- "updater" varchar DEFAULT '',
+ "updater" varchar DEFAULT '',
"update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
- "deleted" bit NOT NULL DEFAULT FALSE,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint,
+ PRIMARY KEY ("id")
+) COMMENT '物联看板';
+
+CREATE TABLE IF NOT EXISTS "mes_machine_component"
+(
+ "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+ "name" varchar NOT NULL,
+ "parent_id" bigint NOT NULL,
+ "sort" int NOT NULL,
+ "org_id" bigint NOT NULL,
+ "serial_code" varchar,
+ "outgoing_time" varchar,
+ "outgoing_report" varchar,
+ "position" varchar,
+ "standard" varchar,
+ "remark" varchar,
+ "creator" varchar DEFAULT '',
+ "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "updater" varchar DEFAULT '',
+ "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ "deleted" bit NOT NULL DEFAULT FALSE,
+ "tenant_id" bigint NOT NULL,
+ "status" int NOT NULL,
+ "component_type" int NOT NULL,
+ "machine_type" varchar,
PRIMARY KEY ("id")
-) COMMENT 'GoView 项目表';
+) COMMENT '机台组织表';
diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
index 0c9f084dc..e7d402108 100644
--- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
+++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -38,4 +38,10 @@ public interface ErrorCodeConstants {
ErrorCode WORK_TEAM_DETAIL_NOT_EXISTS = new ErrorCode(5_0071, "班组成员不存在");
ErrorCode PRODUCE_REPORT_NOT_EXISTS = new ErrorCode(5_008, "生产报工单不存在");
ErrorCode PRODUCE_REPORT_DETAIL_NOT_EXISTS = new ErrorCode(5_0081, "生产报工明细不存在");
+ ErrorCode MACHINE_COMPONENT_EXITS_CHILDREN = new ErrorCode(5_008, "生产报工单不存在");
+ ErrorCode MACHINE_COMPONENT_NOT_EXISTS = new ErrorCode(5_0081, "生产报工明细不存在");
+ ErrorCode MACHINE_COMPONENT_PARENT_ERROR = new ErrorCode(5_0081, "生产报工明细不存在");
+ ErrorCode MACHINE_COMPONENT_PARENT_NOT_EXITS = new ErrorCode(5_008, "生产报工单不存在");
+ ErrorCode MACHINE_COMPONENT_PARENT_IS_CHILD = new ErrorCode(5_0081, "生产报工明细不存在");
+ ErrorCode MACHINE_COMPONENT_NAME_DUPLICATE = new ErrorCode(5_0081, "生产报工明细不存在");
}
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/MachineComponentController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/MachineComponentController.java
new file mode 100644
index 000000000..e0b469fad
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/MachineComponentController.java
@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.mes.controller.admin.machine;
+
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.util.*;
+import java.io.IOException;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+import cn.iocoder.yudao.module.mes.controller.admin.machine.vo.*;
+import cn.iocoder.yudao.module.mes.dal.dataobject.machine.MachineComponentDO;
+import cn.iocoder.yudao.module.mes.service.machine.MachineComponentService;
+
+@Tag(name = "管理后台 - 机台")
+@RestController
+@RequestMapping("/mes/machine-component")
+@Validated
+public class MachineComponentController {
+
+ @Resource
+ private MachineComponentService machineComponentService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建机台")
+ @PreAuthorize("@ss.hasPermission('mes:machine-component:create')")
+ public CommonResult createMachineComponent(@Valid @RequestBody MachineComponentSaveReqVO createReqVO) {
+ return success(machineComponentService.createMachineComponent(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新机台")
+ @PreAuthorize("@ss.hasPermission('mes:machine-component:update')")
+ public CommonResult updateMachineComponent(@Valid @RequestBody MachineComponentSaveReqVO updateReqVO) {
+ machineComponentService.updateMachineComponent(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除机台")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('mes:machine-component:delete')")
+ public CommonResult deleteMachineComponent(@RequestParam("id") Long id) {
+ machineComponentService.deleteMachineComponent(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得机台")
+ @Parameter(name = "id", description = "编号", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('mes:machine-component:query')")
+ public CommonResult getMachineComponent(@RequestParam("id") Long id) {
+ MachineComponentDO machineComponent = machineComponentService.getMachineComponent(id);
+ return success(BeanUtils.toBean(machineComponent, MachineComponentRespVO.class));
+ }
+
+ @GetMapping("/list")
+ @Operation(summary = "获得机台列表")
+ @PreAuthorize("@ss.hasPermission('mes:machine-component:query')")
+ public CommonResult> getMachineComponentList(@Valid MachineComponentListReqVO listReqVO) {
+ List list = machineComponentService.getMachineComponentList(listReqVO);
+ return success(BeanUtils.toBean(list, MachineComponentRespVO.class));
+ }
+
+ @GetMapping("/export-excel")
+ @Operation(summary = "导出机台 Excel")
+ @PreAuthorize("@ss.hasPermission('mes:machine-component:export')")
+ @ApiAccessLog(operateType = EXPORT)
+ public void exportMachineComponentExcel(@Valid MachineComponentListReqVO listReqVO,
+ HttpServletResponse response) throws IOException {
+ List list = machineComponentService.getMachineComponentList(listReqVO);
+ // 导出 Excel
+ ExcelUtils.write(response, "机台.xls", "数据", MachineComponentRespVO.class,
+ BeanUtils.toBean(list, MachineComponentRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentListReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentListReqVO.java
new file mode 100644
index 000000000..3cd86b701
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentListReqVO.java
@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.module.mes.controller.admin.machine.vo;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import java.time.LocalDateTime;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 机台列表 Request VO")
+@Data
+public class MachineComponentListReqVO {
+
+ @Schema(description = "装备名称", example = "芋艿")
+ private String name;
+
+ @Schema(description = "父id", example = "24628")
+ private Long parentId;
+
+ @Schema(description = "显示顺序")
+ private Integer sort;
+
+ @Schema(description = "组织机台ID", example = "13753")
+ private Long orgId;
+
+ @Schema(description = "装备SN号")
+ private String serialCode;
+
+ @Schema(description = "出厂日期")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] outgoingTime;
+
+ @Schema(description = "出厂报告")
+ private String outgoingReport;
+
+ @Schema(description = "位置")
+ private String position;
+
+ @Schema(description = "规格")
+ private String standard;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "创建时间")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "状态", example = "1")
+ private Integer status;
+
+ @Schema(description = "组织类型", example = "1")
+ private Integer componentType;
+
+ @Schema(description = "机台类型", example = "1")
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentRespVO.java
new file mode 100644
index 000000000..6d24db824
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentRespVO.java
@@ -0,0 +1,81 @@
+package cn.iocoder.yudao.module.mes.controller.admin.machine.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
+import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
+
+@Schema(description = "管理后台 - 机台 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MachineComponentRespVO {
+
+ @Schema(description = "装备id", requiredMode = Schema.RequiredMode.REQUIRED, example = "12527")
+ @ExcelProperty("装备id")
+ private Long id;
+
+ @Schema(description = "装备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+ @ExcelProperty("装备名称")
+ private String name;
+
+ @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED, example = "24628")
+ @ExcelProperty("父id")
+ private Long parentId;
+
+ @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("显示顺序")
+ private Integer sort;
+
+ @Schema(description = "组织机台ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "13753")
+ @ExcelProperty("组织机台ID")
+ private Long orgId;
+
+ @Schema(description = "装备SN号")
+ @ExcelProperty("装备SN号")
+ private String serialCode;
+
+ @Schema(description = "出厂日期")
+ @ExcelProperty("出厂日期")
+ private LocalDateTime outgoingTime;
+
+ @Schema(description = "出厂报告")
+ @ExcelProperty("出厂报告")
+ private String outgoingReport;
+
+ @Schema(description = "位置")
+ @ExcelProperty("位置")
+ private String position;
+
+ @Schema(description = "规格")
+ @ExcelProperty("规格")
+ private String standard;
+
+ @Schema(description = "备注", example = "你猜")
+ @ExcelProperty("备注")
+ private String remark;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "状态", converter = DictConvert.class)
+ @DictFormat("mes_machine_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private Integer status;
+
+ @Schema(description = "组织类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @ExcelProperty(value = "组织类型", converter = DictConvert.class)
+ @DictFormat("mes_machine_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private Integer componentType;
+
+ @Schema(description = "机台类型", example = "1")
+ @ExcelProperty(value = "机台类型", converter = DictConvert.class)
+ @DictFormat("mes_org_type") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentSaveReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentSaveReqVO.java
new file mode 100644
index 000000000..9b4f85468
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/machine/vo/MachineComponentSaveReqVO.java
@@ -0,0 +1,62 @@
+package cn.iocoder.yudao.module.mes.controller.admin.machine.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 机台新增/修改 Request VO")
+@Data
+public class MachineComponentSaveReqVO {
+
+ @Schema(description = "装备id", requiredMode = Schema.RequiredMode.REQUIRED, example = "12527")
+ private Long id;
+
+ @Schema(description = "装备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
+ @NotEmpty(message = "装备名称不能为空")
+ private String name;
+
+ @Schema(description = "父id", requiredMode = Schema.RequiredMode.REQUIRED, example = "24628")
+ @NotNull(message = "父id不能为空")
+ private Long parentId;
+
+ @Schema(description = "显示顺序", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "显示顺序不能为空")
+ private Integer sort;
+
+ @Schema(description = "组织机台ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "13753")
+ @NotNull(message = "组织机台ID不能为空")
+ private Long orgId;
+
+ @Schema(description = "装备SN号")
+ private String serialCode;
+
+ @Schema(description = "出厂日期")
+ private LocalDateTime outgoingTime;
+
+ @Schema(description = "出厂报告")
+ private String outgoingReport;
+
+ @Schema(description = "位置")
+ private String position;
+
+ @Schema(description = "规格")
+ private String standard;
+
+ @Schema(description = "备注", example = "你猜")
+ private String remark;
+
+ @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "状态不能为空")
+ private Integer status;
+
+ @Schema(description = "组织类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @NotNull(message = "组织类型不能为空")
+ private Integer componentType;
+
+ @Schema(description = "机台类型", example = "1")
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/machine/MachineComponentDO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/machine/MachineComponentDO.java
new file mode 100644
index 000000000..b2db2e724
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/machine/MachineComponentDO.java
@@ -0,0 +1,92 @@
+package cn.iocoder.yudao.module.mes.dal.dataobject.machine;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 机台 DO
+ *
+ * @author 内蒙必硕
+ */
+@TableName("mes_machine_component")
+@KeySequence("mes_machine_component_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MachineComponentDO extends BaseDO {
+
+ public static final Long PARENT_ID_ROOT = 0L;
+
+ /**
+ * 装备id
+ */
+ @TableId
+ private Long id;
+ /**
+ * 装备名称
+ */
+ private String name;
+ /**
+ * 父id
+ */
+ private Long parentId;
+ /**
+ * 显示顺序
+ */
+ private Integer sort;
+ /**
+ * 组织机台ID
+ */
+ private Long orgId;
+ /**
+ * 装备SN号
+ */
+ private String serialCode;
+ /**
+ * 出厂日期
+ */
+ private LocalDateTime outgoingTime;
+ /**
+ * 出厂报告
+ */
+ private String outgoingReport;
+ /**
+ * 位置
+ */
+ private String position;
+ /**
+ * 规格
+ */
+ private String standard;
+ /**
+ * 备注
+ */
+ private String remark;
+ /**
+ * 状态
+ *
+ * 枚举 {@link TODO mes_machine_status 对应的类}
+ */
+ private Integer status;
+ /**
+ * 组织类型
+ *
+ * 枚举 {@link TODO mes_machine_type 对应的类}
+ */
+ private Integer componentType;
+ /**
+ * 机台类型
+ *
+ * 枚举 {@link TODO mes_org_type 对应的类}
+ */
+ private String machineType;
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/machine/MachineComponentMapper.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/machine/MachineComponentMapper.java
new file mode 100644
index 000000000..b87d3c24f
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/machine/MachineComponentMapper.java
@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.mes.dal.mysql.machine;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.mes.dal.dataobject.machine.MachineComponentDO;
+import org.apache.ibatis.annotations.Mapper;
+import cn.iocoder.yudao.module.mes.controller.admin.machine.vo.*;
+
+/**
+ * 机台 Mapper
+ *
+ * @author 内蒙必硕
+ */
+@Mapper
+public interface MachineComponentMapper extends BaseMapperX {
+
+ default List selectList(MachineComponentListReqVO reqVO) {
+ return selectList(new LambdaQueryWrapperX()
+ .likeIfPresent(MachineComponentDO::getName, reqVO.getName())
+ .eqIfPresent(MachineComponentDO::getParentId, reqVO.getParentId())
+ .eqIfPresent(MachineComponentDO::getSort, reqVO.getSort())
+ .eqIfPresent(MachineComponentDO::getOrgId, reqVO.getOrgId())
+ .eqIfPresent(MachineComponentDO::getSerialCode, reqVO.getSerialCode())
+ .betweenIfPresent(MachineComponentDO::getOutgoingTime, reqVO.getOutgoingTime())
+ .eqIfPresent(MachineComponentDO::getOutgoingReport, reqVO.getOutgoingReport())
+ .eqIfPresent(MachineComponentDO::getPosition, reqVO.getPosition())
+ .eqIfPresent(MachineComponentDO::getStandard, reqVO.getStandard())
+ .eqIfPresent(MachineComponentDO::getRemark, reqVO.getRemark())
+ .betweenIfPresent(MachineComponentDO::getCreateTime, reqVO.getCreateTime())
+ .eqIfPresent(MachineComponentDO::getStatus, reqVO.getStatus())
+ .eqIfPresent(MachineComponentDO::getComponentType, reqVO.getComponentType())
+ .eqIfPresent(MachineComponentDO::getMachineType, reqVO.getMachineType())
+ .orderByDesc(MachineComponentDO::getId));
+ }
+
+ default MachineComponentDO selectByParentIdAndName(Long parentId, String name) {
+ return selectOne(MachineComponentDO::getParentId, parentId, MachineComponentDO::getName, name);
+ }
+
+ default Long selectCountByParentId(Long parentId) {
+ return selectCount(MachineComponentDO::getParentId, parentId);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentService.java
new file mode 100644
index 000000000..162e26345
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentService.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.mes.service.machine;
+
+import java.util.*;
+import cn.iocoder.yudao.module.mes.controller.admin.machine.vo.*;
+import cn.iocoder.yudao.module.mes.dal.dataobject.machine.MachineComponentDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+
+import javax.validation.Valid;
+
+/**
+ * 机台 Service 接口
+ *
+ * @author 内蒙必硕
+ */
+public interface MachineComponentService {
+
+ /**
+ * 创建机台
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createMachineComponent(@Valid MachineComponentSaveReqVO createReqVO);
+
+ /**
+ * 更新机台
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateMachineComponent(@Valid MachineComponentSaveReqVO updateReqVO);
+
+ /**
+ * 删除机台
+ *
+ * @param id 编号
+ */
+ void deleteMachineComponent(Long id);
+
+ /**
+ * 获得机台
+ *
+ * @param id 编号
+ * @return 机台
+ */
+ MachineComponentDO getMachineComponent(Long id);
+
+ /**
+ * 获得机台列表
+ *
+ * @param listReqVO 查询条件
+ * @return 机台列表
+ */
+ List getMachineComponentList(MachineComponentListReqVO listReqVO);
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImpl.java
new file mode 100644
index 000000000..214cdf690
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImpl.java
@@ -0,0 +1,138 @@
+package cn.iocoder.yudao.module.mes.service.machine;
+
+import org.springframework.stereotype.Service;
+
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import cn.iocoder.yudao.module.mes.controller.admin.machine.vo.*;
+import cn.iocoder.yudao.module.mes.dal.dataobject.machine.MachineComponentDO;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import cn.iocoder.yudao.module.mes.dal.mysql.machine.MachineComponentMapper;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
+
+/**
+ * 机台 Service 实现类
+ *
+ * @author 内蒙必硕
+ */
+@Service
+@Validated
+public class MachineComponentServiceImpl implements MachineComponentService {
+
+ @Resource
+ private MachineComponentMapper machineComponentMapper;
+
+ @Override
+ public Long createMachineComponent(MachineComponentSaveReqVO createReqVO) {
+ // 校验父id的有效性
+ validateParentMachineComponent(null, createReqVO.getParentId());
+ // 校验装备名称的唯一性
+ validateMachineComponentNameUnique(null, createReqVO.getParentId(), createReqVO.getName());
+
+ // 插入
+ MachineComponentDO machineComponent = BeanUtils.toBean(createReqVO, MachineComponentDO.class);
+ machineComponentMapper.insert(machineComponent);
+ // 返回
+ return machineComponent.getId();
+ }
+
+ @Override
+ public void updateMachineComponent(MachineComponentSaveReqVO updateReqVO) {
+ // 校验存在
+ validateMachineComponentExists(updateReqVO.getId());
+ // 校验父id的有效性
+ validateParentMachineComponent(updateReqVO.getId(), updateReqVO.getParentId());
+ // 校验装备名称的唯一性
+ validateMachineComponentNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName());
+
+ // 更新
+ MachineComponentDO updateObj = BeanUtils.toBean(updateReqVO, MachineComponentDO.class);
+ machineComponentMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteMachineComponent(Long id) {
+ // 校验存在
+ validateMachineComponentExists(id);
+ // 校验是否有子机台
+ if (machineComponentMapper.selectCountByParentId(id) > 0) {
+ throw exception(MACHINE_COMPONENT_EXITS_CHILDREN);
+ }
+ // 删除
+ machineComponentMapper.deleteById(id);
+ }
+
+ private void validateMachineComponentExists(Long id) {
+ if (machineComponentMapper.selectById(id) == null) {
+ throw exception(MACHINE_COMPONENT_NOT_EXISTS);
+ }
+ }
+
+ private void validateParentMachineComponent(Long id, Long parentId) {
+ if (parentId == null || MachineComponentDO.PARENT_ID_ROOT.equals(parentId)) {
+ return;
+ }
+ // 1. 不能设置自己为父机台
+ if (Objects.equals(id, parentId)) {
+ throw exception(MACHINE_COMPONENT_PARENT_ERROR);
+ }
+ // 2. 父机台不存在
+ MachineComponentDO parentMachineComponent = machineComponentMapper.selectById(parentId);
+ if (parentMachineComponent == null) {
+ throw exception(MACHINE_COMPONENT_PARENT_NOT_EXITS);
+ }
+ // 3. 递归校验父机台,如果父机台是自己的子机台,则报错,避免形成环路
+ if (id == null) { // id 为空,说明新增,不需要考虑环路
+ return;
+ }
+ for (int i = 0; i < Short.MAX_VALUE; i++) {
+ // 3.1 校验环路
+ parentId = parentMachineComponent.getParentId();
+ if (Objects.equals(id, parentId)) {
+ throw exception(MACHINE_COMPONENT_PARENT_IS_CHILD);
+ }
+ // 3.2 继续递归下一级父机台
+ if (parentId == null || MachineComponentDO.PARENT_ID_ROOT.equals(parentId)) {
+ break;
+ }
+ parentMachineComponent = machineComponentMapper.selectById(parentId);
+ if (parentMachineComponent == null) {
+ break;
+ }
+ }
+ }
+
+ private void validateMachineComponentNameUnique(Long id, Long parentId, String name) {
+ MachineComponentDO machineComponent = machineComponentMapper.selectByParentIdAndName(parentId, name);
+ if (machineComponent == null) {
+ return;
+ }
+ // 如果 id 为空,说明不用比较是否为相同 id 的机台
+ if (id == null) {
+ throw exception(MACHINE_COMPONENT_NAME_DUPLICATE);
+ }
+ if (!Objects.equals(machineComponent.getId(), id)) {
+ throw exception(MACHINE_COMPONENT_NAME_DUPLICATE);
+ }
+ }
+
+ @Override
+ public MachineComponentDO getMachineComponent(Long id) {
+ return machineComponentMapper.selectById(id);
+ }
+
+ @Override
+ public List getMachineComponentList(MachineComponentListReqVO listReqVO) {
+ return machineComponentMapper.selectList(listReqVO);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/machine/MachineComponentMapper.xml b/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/machine/MachineComponentMapper.xml
new file mode 100644
index 000000000..7fa8dc26a
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/resources/mapper/machine/MachineComponentMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImplTest.java b/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImplTest.java
new file mode 100644
index 000000000..73ebacbfd
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/test/java/cn/iocoder/yudao/module/mes/service/machine/MachineComponentServiceImplTest.java
@@ -0,0 +1,181 @@
+package cn.iocoder.yudao.module.mes.service.machine;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.mes.controller.admin.machine.vo.*;
+import cn.iocoder.yudao.module.mes.dal.dataobject.machine.MachineComponentDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.machine.MachineComponentMapper;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+
+import javax.annotation.Resource;
+import org.springframework.context.annotation.Import;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link MachineComponentServiceImpl} 的单元测试类
+ *
+ * @author 内蒙必硕
+ */
+@Import(MachineComponentServiceImpl.class)
+public class MachineComponentServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private MachineComponentServiceImpl machineComponentService;
+
+ @Resource
+ private MachineComponentMapper machineComponentMapper;
+
+ @Test
+ public void testCreateMachineComponent_success() {
+ // 准备参数
+ MachineComponentSaveReqVO createReqVO = randomPojo(MachineComponentSaveReqVO.class).setId(null);
+
+ // 调用
+ Long machineComponentId = machineComponentService.createMachineComponent(createReqVO);
+ // 断言
+ assertNotNull(machineComponentId);
+ // 校验记录的属性是否正确
+ MachineComponentDO machineComponent = machineComponentMapper.selectById(machineComponentId);
+ assertPojoEquals(createReqVO, machineComponent, "id");
+ }
+
+ @Test
+ public void testUpdateMachineComponent_success() {
+ // mock 数据
+ MachineComponentDO dbMachineComponent = randomPojo(MachineComponentDO.class);
+ machineComponentMapper.insert(dbMachineComponent);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ MachineComponentSaveReqVO updateReqVO = randomPojo(MachineComponentSaveReqVO.class, o -> {
+ o.setId(dbMachineComponent.getId()); // 设置更新的 ID
+ });
+
+ // 调用
+ machineComponentService.updateMachineComponent(updateReqVO);
+ // 校验是否更新正确
+ MachineComponentDO machineComponent = machineComponentMapper.selectById(updateReqVO.getId()); // 获取最新的
+ assertPojoEquals(updateReqVO, machineComponent);
+ }
+
+ @Test
+ public void testUpdateMachineComponent_notExists() {
+ // 准备参数
+ MachineComponentSaveReqVO updateReqVO = randomPojo(MachineComponentSaveReqVO.class);
+
+ // 调用, 并断言异常
+ assertServiceException(() -> machineComponentService.updateMachineComponent(updateReqVO), MACHINE_COMPONENT_NOT_EXISTS);
+ }
+
+ @Test
+ public void testDeleteMachineComponent_success() {
+ // mock 数据
+ MachineComponentDO dbMachineComponent = randomPojo(MachineComponentDO.class);
+ machineComponentMapper.insert(dbMachineComponent);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbMachineComponent.getId();
+
+ // 调用
+ machineComponentService.deleteMachineComponent(id);
+ // 校验数据不存在了
+ assertNull(machineComponentMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteMachineComponent_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> machineComponentService.deleteMachineComponent(id), MACHINE_COMPONENT_NOT_EXISTS);
+ }
+
+ @Test
+ @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+ public void testGetMachineComponentList() {
+ // mock 数据
+ MachineComponentDO dbMachineComponent = randomPojo(MachineComponentDO.class, o -> { // 等会查询到
+ o.setName(null);
+ o.setParentId(null);
+ o.setSort(null);
+ o.setOrgId(null);
+ o.setSerialCode(null);
+ o.setOutgoingTime(null);
+ o.setOutgoingReport(null);
+ o.setPosition(null);
+ o.setStandard(null);
+ o.setRemark(null);
+ o.setCreateTime(null);
+ o.setStatus(null);
+ o.setComponentType(null);
+ o.setMachineType(null);
+ });
+ machineComponentMapper.insert(dbMachineComponent);
+ // 测试 name 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setName(null)));
+ // 测试 parentId 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setParentId(null)));
+ // 测试 sort 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setSort(null)));
+ // 测试 orgId 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setOrgId(null)));
+ // 测试 serialCode 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setSerialCode(null)));
+ // 测试 outgoingTime 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setOutgoingTime(null)));
+ // 测试 outgoingReport 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setOutgoingReport(null)));
+ // 测试 position 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setPosition(null)));
+ // 测试 standard 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setStandard(null)));
+ // 测试 remark 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setRemark(null)));
+ // 测试 createTime 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setCreateTime(null)));
+ // 测试 status 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setStatus(null)));
+ // 测试 componentType 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setComponentType(null)));
+ // 测试 machineType 不匹配
+ machineComponentMapper.insert(cloneIgnoreId(dbMachineComponent, o -> o.setMachineType(null)));
+ // 准备参数
+ MachineComponentListReqVO reqVO = new MachineComponentListReqVO();
+ reqVO.setName(null);
+ reqVO.setParentId(null);
+ reqVO.setSort(null);
+ reqVO.setOrgId(null);
+ reqVO.setSerialCode(null);
+ reqVO.setOutgoingTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setOutgoingReport(null);
+ reqVO.setPosition(null);
+ reqVO.setStandard(null);
+ reqVO.setRemark(null);
+ reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+ reqVO.setStatus(null);
+ reqVO.setComponentType(null);
+ reqVO.setMachineType(null);
+
+ // 调用
+ List list = machineComponentService.getMachineComponentList(reqVO);
+ // 断言
+ assertEquals(1, list.size());
+ assertPojoEquals(dbMachineComponent, list.get(0));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml
index 8884e86b6..b6e9cf6d3 100644
--- a/yudao-server/pom.xml
+++ b/yudao-server/pom.xml
@@ -119,6 +119,12 @@
yudao-module-mes-biz
${revision}
+
+
+ cn.iocoder.boot
+ yudao-module-iot-biz
+ ${revision}
+
diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java
index a9e690853..46ed3c7fd 100644
--- a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java
+++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java
@@ -58,5 +58,14 @@ public class DefaultController {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[支付模块 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
}
-
+ @RequestMapping(value = {"/admin-api/iot/**"})
+ public CommonResult iot404() {
+ return CommonResult.error(NOT_IMPLEMENTED.getCode(),
+ "[iot模块 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
+ }
+ @RequestMapping(value = {"/admin-api/mes/**"})
+ public CommonResult mes404() {
+ return CommonResult.error(NOT_IMPLEMENTED.getCode(),
+ "[mes模块 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]");
+ }
}