【删除】 删除IOT相关模块,删除无用代码块,注释掉无用的代码保证代码。

This commit is contained in:
dlaren
2025-07-29 16:07:34 +08:00
parent 04f12616ac
commit fd22f75657
325 changed files with 1 additions and 23063 deletions

View File

@@ -1,53 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>exam-module-iot</artifactId>
<groupId>pc.exam.gg</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>exam-module-iot-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<!-- TODO 芋艿:需要在整理下,特别是 PF4J -->
<description>
物联网 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-common</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope> <!-- 设置为 provided只有工具类需要使用到 -->
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope> <!-- 设置为 provided只有工具类需要使用到 -->
</dependency>
<dependency>
<groupId>org.pf4j</groupId> <!-- PF4J内置插件机制 -->
<artifactId>pf4j-spring</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -1,93 +0,0 @@
package pc.exam.pp.module.iot.api.device;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.module.iot.api.device.dto.control.upstream.*;
import pc.exam.pp.module.iot.enums.ApiConstants;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* 设备数据 Upstream 上行 API
*
* 目的:设备 -> 插件 -> 服务端
*
* @author haohao
*/
public interface IotDeviceUpstreamApi {
String PREFIX = ApiConstants.PREFIX + "/device/upstream";
// ========== 设备相关 ==========
/**
* 更新设备状态
*
* @param updateReqDTO 更新设备状态 DTO
*/
@PostMapping(PREFIX + "/update-state")
CommonResult<Boolean> updateDeviceState(@Valid @RequestBody IotDeviceStateUpdateReqDTO updateReqDTO);
/**
* 上报设备属性数据
*
* @param reportReqDTO 上报设备属性数据 DTO
*/
@PostMapping(PREFIX + "/report-property")
CommonResult<Boolean> reportDeviceProperty(@Valid @RequestBody IotDevicePropertyReportReqDTO reportReqDTO);
/**
* 上报设备事件数据
*
* @param reportReqDTO 设备事件
*/
@PostMapping(PREFIX + "/report-event")
CommonResult<Boolean> reportDeviceEvent(@Valid @RequestBody IotDeviceEventReportReqDTO reportReqDTO);
// TODO @芋艿:这个需要 plugins 接入下
/**
* 注册设备
*
* @param registerReqDTO 注册设备 DTO
*/
@PostMapping(PREFIX + "/register")
CommonResult<Boolean> registerDevice(@Valid @RequestBody IotDeviceRegisterReqDTO registerReqDTO);
// TODO @芋艿:这个需要 plugins 接入下
/**
* 注册子设备
*
* @param registerReqDTO 注册子设备 DTO
*/
@PostMapping(PREFIX + "/register-sub")
CommonResult<Boolean> registerSubDevice(@Valid @RequestBody IotDeviceRegisterSubReqDTO registerReqDTO);
// TODO @芋艿:这个需要 plugins 接入下
/**
* 注册设备拓扑
*
* @param addReqDTO 注册设备拓扑 DTO
*/
@PostMapping(PREFIX + "/add-topology")
CommonResult<Boolean> addDeviceTopology(@Valid @RequestBody IotDeviceTopologyAddReqDTO addReqDTO);
// TODO @芋艿:考虑 http 认证
/**
* 认证 Emqx 连接
*
* @param authReqDTO 认证 Emqx 连接 DTO
*/
@PostMapping(PREFIX + "/authenticate-emqx-connection")
CommonResult<Boolean> authenticateEmqxConnection(@Valid @RequestBody IotDeviceEmqxAuthReqDTO authReqDTO);
// ========== 插件相关 ==========
/**
* 心跳插件实例
*
* @param heartbeatReqDTO 心跳插件实例 DTO
*/
@PostMapping(PREFIX + "/heartbeat-plugin-instance")
CommonResult<Boolean> heartbeatPluginInstance(@Valid @RequestBody IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO);
}

View File

@@ -1,22 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.downstream;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.Map;
/**
* IoT 设备【配置】设置 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceConfigSetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
/**
* 配置
*/
@NotNull(message = "配置不能为空")
private Map<String, Object> config;
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.downstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
/**
* IoT 设备下行的抽象 Request DTO
*
* @author 朋辰
*/
@Data
public abstract class IotDeviceDownstreamAbstractReqDTO {
/**
* 请求编号
*/
private String requestId;
/**
* 产品标识
*/
@NotEmpty(message = "产品标识不能为空")
private String productKey;
/**
* 设备名称
*/
@NotEmpty(message = "设备名称不能为空")
private String deviceName;
}

View File

@@ -1,66 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.downstream;
import cn.hutool.core.map.MapUtil;
import lombok.Data;
import java.util.Map;
/**
* IoT 设备【OTA】升级下发 Request DTO更新固件消息
*
* @author 朋辰
*/
@Data
public class IotDeviceOtaUpgradeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
/**
* 固件编号
*/
private Long firmwareId;
/**
* 固件版本
*/
private String version;
/**
* 签名方式
*
* 例如说MD5、SHA256
*/
private String signMethod;
/**
* 固件文件签名
*/
private String fileSign;
/**
* 固件文件大小
*/
private Long fileSize;
/**
* 固件文件 URL
*/
private String fileUrl;
/**
* 自定义信息,建议使用 JSON 格式
*/
private String information;
public static IotDeviceOtaUpgradeReqDTO build(Map<?, ?> map) {
return new IotDeviceOtaUpgradeReqDTO()
.setFirmwareId(MapUtil.getLong(map, "firmwareId")).setVersion((String) map.get("version"))
.setSignMethod((String) map.get("signMethod")).setFileSign((String) map.get("fileSign"))
.setFileSize(MapUtil.getLong(map, "fileSize")).setFileUrl((String) map.get("fileUrl"))
.setInformation((String) map.get("information"));
}
public static Map<?, ?> build(IotDeviceOtaUpgradeReqDTO dto) {
return MapUtil.builder()
.put("firmwareId", dto.getFirmwareId()).put("version", dto.getVersion())
.put("signMethod", dto.getSignMethod()).put("fileSign", dto.getFileSign())
.put("fileSize", dto.getFileSize()).put("fileUrl", dto.getFileUrl())
.put("information", dto.getInformation())
.build();
}
}

View File

@@ -1,24 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.downstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
// TODO @芋艿:从 server => plugin => device 是否有必要?从阿里云 iot 来看,没有这个功能?!
// TODO @芋艿:是不是改成 read 更好?在看看阿里云的 topic 设计
/**
* IoT 设备【属性】获取 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDevicePropertyGetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
/**
* 属性标识数组
*/
@NotEmpty(message = "属性标识数组不能为空")
private List<String> identifiers;
}

View File

@@ -1,22 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.downstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.Map;
/**
* IoT 设备【属性】设置 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDevicePropertySetReqDTO extends IotDeviceDownstreamAbstractReqDTO {
/**
* 属性参数
*/
@NotEmpty(message = "属性参数不能为空")
private Map<String, Object> properties;
}

View File

@@ -1,26 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.downstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.Map;
/**
* IoT 设备【服务】调用 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceServiceInvokeReqDTO extends IotDeviceDownstreamAbstractReqDTO {
/**
* 服务标识
*/
@NotEmpty(message = "服务标识不能为空")
private String identifier;
/**
* 调用参数
*/
private Map<String, Object> params;
}

View File

@@ -1,34 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
// TODO @芋艿:要不要继承 IotDeviceUpstreamAbstractReqDTO
// TODO @芋艿:@haohao后续其它认证的设计
/**
* IoT 认证 Emqx 连接 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceEmqxAuthReqDTO {
/**
* 客户端 ID
*/
@NotEmpty(message = "客户端 ID 不能为空")
private String clientId;
/**
* 用户名
*/
@NotEmpty(message = "用户名不能为空")
private String username;
/**
* 密码
*/
@NotEmpty(message = "密码不能为空")
private String password;
}

View File

@@ -1,26 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.Map;
/**
* IoT 设备【事件】上报 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceEventReportReqDTO extends IotDeviceUpstreamAbstractReqDTO {
/**
* 事件标识
*/
@NotEmpty(message = "事件标识不能为空")
private String identifier;
/**
* 事件参数
*/
private Map<String, Object> params;
}

View File

@@ -1,35 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import lombok.Data;
// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/progress
/**
* IoT 设备【OTA】升级进度 Request DTO上报更新固件进度
*
* @author 朋辰
*/
@Data
public class IotDeviceOtaProgressReqDTO extends IotDeviceUpstreamAbstractReqDTO {
/**
* 固件编号
*/
private Long firmwareId;
/**
* 升级状态
*
* 枚举 {@link pc.exam.pp.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
*/
private Integer status;
/**
* 升级进度,百分比
*/
private Integer progress;
/**
* 升级进度描述
*/
private String description;
}

View File

@@ -1,21 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/pull
/**
* IoT 设备【OTA】升级下拉 Request DTO拉取固件更新
*
* @author 朋辰
*/
public class IotDeviceOtaPullReqDTO {
/**
* 固件编号
*/
private Long firmwareId;
/**
* 固件版本
*/
private String version;
}

View File

@@ -1,21 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
// TODO @芋艿:待实现:/ota/${productKey}/${deviceName}/report
/**
* IoT 设备【OTA】上报 Request DTO上报固件版本
*
* @author 朋辰
*/
public class IotDeviceOtaReportReqDTO {
/**
* 固件编号
*/
private Long firmwareId;
/**
* 固件版本
*/
private String version;
}

View File

@@ -1,22 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.Map;
/**
* IoT 设备【属性】上报 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDevicePropertyReportReqDTO extends IotDeviceUpstreamAbstractReqDTO {
/**
* 属性参数
*/
@NotEmpty(message = "属性参数不能为空")
private Map<String, Object> properties;
}

View File

@@ -1,12 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import lombok.Data;
/**
* IoT 设备【注册】自己 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceRegisterReqDTO extends IotDeviceUpstreamAbstractReqDTO {
}

View File

@@ -1,43 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* IoT 设备【注册】子设备 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceRegisterSubReqDTO extends IotDeviceUpstreamAbstractReqDTO {
// TODO @芋艿:看看要不要优化命名
/**
* 子设备数组
*/
@NotEmpty(message = "子设备不能为空")
private List<Device> params;
/**
* 设备信息
*/
@Data
public static class Device {
/**
* 产品标识
*/
@NotEmpty(message = "产品标识不能为空")
private String productKey;
/**
* 设备名称
*/
@NotEmpty(message = "设备名称不能为空")
private String deviceName;
}
}

View File

@@ -1,23 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.device.IotDeviceStateEnum;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* IoT 设备【状态】更新 Request DTO
*
* @author 朋辰
*/
@Data
public class IotDeviceStateUpdateReqDTO extends IotDeviceUpstreamAbstractReqDTO {
/**
* 设备状态
*/
@NotNull(message = "设备状态不能为空")
@InEnum(IotDeviceStateEnum.class) // 只使用:在线、离线
private Integer state;
}

View File

@@ -1,44 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
// TODO @芋艿:要写清楚,是来自设备网关,还是设备。
/**
* IoT 设备【拓扑】添加 Request DTO
*/
@Data
public class IotDeviceTopologyAddReqDTO extends IotDeviceUpstreamAbstractReqDTO {
// TODO @芋艿:看看要不要优化命名
/**
* 子设备数组
*/
@NotEmpty(message = "子设备不能为空")
private List<IotDeviceRegisterSubReqDTO.Device> params;
/**
* 设备信息
*/
@Data
public static class Device {
/**
* 产品标识
*/
@NotEmpty(message = "产品标识不能为空")
private String productKey;
/**
* 设备名称
*/
@NotEmpty(message = "设备名称不能为空")
private String deviceName;
// TODO @芋艿:阿里云还有 sign 签名
}
}

View File

@@ -1,45 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import pc.exam.pp.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.time.LocalDateTime;
/**
* IoT 设备上行的抽象 Request DTO
*
* @author 朋辰
*/
@Data
public abstract class IotDeviceUpstreamAbstractReqDTO {
/**
* 请求编号
*/
private String requestId;
/**
* 插件实例的进程编号
*/
private String processId;
/**
* 产品标识
*/
@NotEmpty(message = "产品标识不能为空")
private String productKey;
/**
* 设备名称
*/
@NotEmpty(message = "设备名称不能为空")
private String deviceName;
/**
* 上报时间
*/
@JsonSerialize(using = TimestampLocalDateTimeSerializer.class) // 解决 iot plugins 序列化 LocalDateTime 是数组,导致无法解析的问题
private LocalDateTime reportTime;
}

View File

@@ -1,44 +0,0 @@
package pc.exam.pp.module.iot.api.device.dto.control.upstream;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* IoT 插件实例心跳 Request DTO
*
* @author 朋辰
*/
@Data
public class IotPluginInstanceHeartbeatReqDTO {
/**
* 请求编号
*/
@NotEmpty(message = "请求编号不能为空")
private String processId;
/**
* 插件包标识符
*/
@NotEmpty(message = "插件包标识符不能为空")
private String pluginKey;
/**
* 插件实例所在 IP
*/
@NotEmpty(message = "插件实例所在 IP 不能为空")
private String hostIp;
/**
* 插件实例的进程编号
*/
@NotNull(message = "插件实例的进程编号不能为空")
private Integer downstreamPort;
/**
* 是否在线
*/
@NotNull(message = "是否在线不能为空")
private Boolean online;
}

View File

@@ -1,4 +0,0 @@
/**
* TODO 芋艿:占位
*/
package pc.exam.pp.module.iot.api.device.dto;

View File

@@ -1,6 +0,0 @@
/**
* 占位
*
* TODO 芋艿:后续删除
*/
package pc.exam.pp.module.iot.api;

View File

@@ -1,16 +0,0 @@
package pc.exam.pp.module.iot.enums;
import pc.exam.pp.framework.common.enums.RpcConstants;
/**
* API 相关的枚举
*
* @author 朋辰
*/
public class ApiConstants {
public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/iot";
public static final String VERSION = "1.0.0";
}

View File

@@ -1,22 +0,0 @@
package pc.exam.pp.module.iot.enums;
/**
* IoT 字典类型的枚举类
*
* @author 朋辰
*/
public class DictTypeConstants {
public static final String PRODUCT_STATUS = "iot_product_status";
public static final String PRODUCT_DEVICE_TYPE = "iot_product_device_type";
public static final String NET_TYPE = "iot_net_type";
public static final String PROTOCOL_TYPE = "iot_protocol_type";
public static final String DATA_FORMAT = "iot_data_format";
public static final String VALIDATE_TYPE = "iot_validate_type";
public static final String DEVICE_STATE = "iot_device_state";
public static final String IOT_DATA_BRIDGE_DIRECTION_ENUM = "iot_data_bridge_direction_enum";
public static final String IOT_DATA_BRIDGE_TYPE_ENUM = "iot_data_bridge_type_enum";
}

View File

@@ -1,75 +0,0 @@
package pc.exam.pp.module.iot.enums;
import pc.exam.pp.framework.common.exception.ErrorCode;
/**
* iot 错误码枚举类
* <p>
* iot 系统,使用 1-050-000-000 段
*/
public interface ErrorCodeConstants {
// ========== 产品相关 1-050-001-000 ============
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在");
ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在");
ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除");
ErrorCode PRODUCT_STATUS_NOT_ALLOW_THING_MODEL = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型");
// ========== 产品物模型 1-050-002-000 ============
ErrorCode THING_MODEL_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
ErrorCode THING_MODEL_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在");
ErrorCode THING_MODEL_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。");
ErrorCode THING_MODEL_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。");
ErrorCode THING_MODEL_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效");
// ========== 设备 1-050-003-000 ============
ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在");
ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一");
ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除");
ErrorCode DEVICE_KEY_EXISTS = new ErrorCode(1_050_003_003, "设备标识已经存在");
ErrorCode DEVICE_GATEWAY_NOT_EXISTS = new ErrorCode(1_050_003_004, "网关设备不存在");
ErrorCode DEVICE_NOT_GATEWAY = new ErrorCode(1_050_003_005, "设备不是网关设备");
ErrorCode DEVICE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_003_006, "导入设备数据不能为空!");
ErrorCode DEVICE_DOWNSTREAM_FAILED = new ErrorCode(1_050_003_007, "执行失败,原因:{}");
// ========== 产品分类 1-050-004-000 ==========
ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在");
// ========== 设备分组 1-050-005-000 ==========
ErrorCode DEVICE_GROUP_NOT_EXISTS = new ErrorCode(1_050_005_000, "设备分组不存在");
ErrorCode DEVICE_GROUP_DELETE_FAIL_DEVICE_EXISTS = new ErrorCode(1_050_005_001, "设备分组下存在设备,不允许删除");
// ========== 插件配置 1-050-006-000 ==========
ErrorCode PLUGIN_CONFIG_NOT_EXISTS = new ErrorCode(1_050_006_000, "插件配置不存在");
ErrorCode PLUGIN_INSTALL_FAILED = new ErrorCode(1_050_006_001, "插件安装失败");
ErrorCode PLUGIN_INSTALL_FAILED_FILE_NAME_NOT_MATCH = new ErrorCode(1_050_006_002, "插件安装失败文件名与原插件id不匹配");
ErrorCode PLUGIN_CONFIG_DELETE_FAILED_RUNNING = new ErrorCode(1_050_006_003, "请先停止插件");
ErrorCode PLUGIN_STATUS_INVALID = new ErrorCode(1_050_006_004, "插件状态无效");
ErrorCode PLUGIN_CONFIG_KEY_DUPLICATE = new ErrorCode(1_050_006_005, "插件标识已存在");
ErrorCode PLUGIN_START_FAILED = new ErrorCode(1_050_006_006, "插件启动失败");
ErrorCode PLUGIN_STOP_FAILED = new ErrorCode(1_050_006_007, "插件停止失败");
// ========== 插件实例 1-050-007-000 ==========
// ========== 固件相关 1-050-008-000 ==========
ErrorCode OTA_FIRMWARE_NOT_EXISTS = new ErrorCode(1_050_008_000, "固件信息不存在");
ErrorCode OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE = new ErrorCode(1_050_008_001, "产品版本号重复");
ErrorCode OTA_UPGRADE_TASK_NOT_EXISTS = new ErrorCode(1_050_008_100, "升级任务不存在");
ErrorCode OTA_UPGRADE_TASK_NAME_DUPLICATE = new ErrorCode(1_050_008_101, "升级任务名称重复");
ErrorCode OTA_UPGRADE_TASK_DEVICE_IDS_EMPTY = new ErrorCode(1_050_008_102, "设备编号列表不能为空");
ErrorCode OTA_UPGRADE_TASK_DEVICE_LIST_EMPTY = new ErrorCode(1_050_008_103, "设备列表不能为空");
ErrorCode OTA_UPGRADE_TASK_CANNOT_CANCEL = new ErrorCode(1_050_008_104, "升级任务不能取消");
ErrorCode OTA_UPGRADE_RECORD_NOT_EXISTS = new ErrorCode(1_050_008_200, "升级记录不存在");
ErrorCode OTA_UPGRADE_RECORD_DUPLICATE = new ErrorCode(1_050_008_201, "升级记录重复");
ErrorCode OTA_UPGRADE_RECORD_CANNOT_RETRY = new ErrorCode(1_050_008_202, "升级记录不能重试");
// ========== MQTT 通信相关 1-050-009-000 ==========
ErrorCode MQTT_TOPIC_ILLEGAL = new ErrorCode(1_050_009_000, "topic illegal");
// ========== IoT 数据桥梁 1-050-010-000 ==========
ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
}

View File

@@ -1,44 +0,0 @@
package pc.exam.pp.module.iot.enums.device;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
// TODO @芋艿:需要添加对应的 DTO以及上下行的链路网关、网关服务、设备等
/**
* IoT 设备消息标识符枚举
*/
@Getter
@RequiredArgsConstructor
public enum IotDeviceMessageIdentifierEnum {
PROPERTY_GET("get"), // 下行 TODO 芋艿【讨论】貌似这个“上行”更合理device 主动拉取配置。和 IotDevicePropertyGetReqDTO 一样的配置
PROPERTY_SET("set"), // 下行
PROPERTY_REPORT("report"), // 上行
STATE_ONLINE("online"), // 上行
STATE_OFFLINE("offline"), // 上行
CONFIG_GET("get"), // 上行 TODO 芋艿:【讨论】暂时没有上行的场景
CONFIG_SET("set"), // 下行
SERVICE_INVOKE("${identifier}"), // 下行
SERVICE_REPLY_SUFFIX("_reply"), // 芋艿TODO 芋艿:【讨论】上行 or 下行
OTA_UPGRADE("upgrade"), // 下行
OTA_PULL("pull"), // 上行
OTA_PROGRESS("progress"), // 上行
OTA_REPORT("report"), // 上行
REGISTER_REGISTER("register"), // 上行
REGISTER_REGISTER_SUB("register_sub"), // 上行
REGISTER_UNREGISTER_SUB("unregister_sub"), // 下行
TOPOLOGY_ADD("topology_add"), // 下行;
;
/**
* 标志符
*/
private final String identifier;
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.device;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 设备消息类型枚举
*/
@Getter
@RequiredArgsConstructor
public enum IotDeviceMessageTypeEnum implements ArrayValuable<String> {
STATE("state"), // 设备状态
PROPERTY("property"), // 设备属性:可参考 https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services 设备属性、事件、服务
EVENT("event"), // 设备事件:可参考 https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services 设备属性、事件、服务
SERVICE("service"), // 设备服务:可参考 https://help.aliyun.com/zh/iot/user-guide/device-properties-events-and-services 设备属性、事件、服务
CONFIG("config"), // 设备配置:可参考 https://help.aliyun.com/zh/iot/user-guide/remote-configuration-1 远程配置
OTA("ota"), // 设备 OTA可参考 https://help.aliyun.com/zh/iot/user-guide/ota-update OTA 升级
REGISTER("register"), // 设备注册:可参考 https://help.aliyun.com/zh/iot/user-guide/register-devices 设备身份注册
TOPOLOGY("topology"),; // 设备拓扑:可参考 https://help.aliyun.com/zh/iot/user-guide/manage-topological-relationships 设备拓扑
public static final String[] ARRAYS = Arrays.stream(values()).map(IotDeviceMessageTypeEnum::getType).toArray(String[]::new);
/**
* 属性
*/
private final String type;
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,42 +0,0 @@
package pc.exam.pp.module.iot.enums.device;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 设备状态枚举
*
* @author haohao
*/
@RequiredArgsConstructor
@Getter
public enum IotDeviceStateEnum implements ArrayValuable<Integer> {
INACTIVE(0, "未激活"),
ONLINE(1, "在线"),
OFFLINE(2, "离线");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDeviceStateEnum::getState).toArray(Integer[]::new);
/**
* 状态
*/
private final Integer state;
/**
* 状态名
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
public static boolean isOnline(Integer state) {
return ONLINE.getState().equals(state);
}
}

View File

@@ -1,38 +0,0 @@
package pc.exam.pp.module.iot.enums.ota;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT OTA 升级记录的范围枚举
*
* @author haohao
*/
@RequiredArgsConstructor
@Getter
public enum IotOtaUpgradeRecordStatusEnum implements ArrayValuable<Integer> {
PENDING(0), // 待推送
PUSHED(10), // 已推送
UPGRADING(20), // 升级中
SUCCESS(30), // 升级成功
FAILURE(40), // 升级失败
CANCELED(50),; // 已取消
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeRecordStatusEnum::getStatus).toArray(Integer[]::new);
/**
* 范围
*/
private final Integer status;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,33 +0,0 @@
package pc.exam.pp.module.iot.enums.ota;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT OTA 升级任务的范围枚举
*
* @author haohao
*/
@RequiredArgsConstructor
@Getter
public enum IotOtaUpgradeTaskScopeEnum implements ArrayValuable<Integer> {
ALL(1), // 全部设备:只包括当前产品下的设备,不包括未来创建的设备
SELECT(2); // 指定设备
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeTaskScopeEnum::getScope).toArray(Integer[]::new);
/**
* 范围
*/
private final Integer scope;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,35 +0,0 @@
package pc.exam.pp.module.iot.enums.ota;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT OTA 升级任务的范围枚举
*
* @author haohao
*/
@RequiredArgsConstructor
@Getter
public enum IotOtaUpgradeTaskStatusEnum implements ArrayValuable<Integer> {
IN_PROGRESS(10), // 进行中:升级中
COMPLETED(20), // 已完成:已结束,全部升级完成
INCOMPLETE(21), // 未完成:已结束,部分升级完成
CANCELED(30),; // 已取消:一般是主动取消任务
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotOtaUpgradeTaskStatusEnum::getStatus).toArray(Integer[]::new);
/**
* 范围
*/
private final Integer status;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.plugin;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 部署方式枚举
*
* @author haohao
*/
@RequiredArgsConstructor
@Getter
public enum IotPluginDeployTypeEnum implements ArrayValuable<Integer> {
JAR(0, "JAR 部署"),
STANDALONE(1, "独立部署");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginDeployTypeEnum::getDeployType).toArray(Integer[]::new);
/**
* 部署方式
*/
private final Integer deployType;
/**
* 部署方式名
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.plugin;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 插件状态枚举
*
* @author haohao
*/
@RequiredArgsConstructor
@Getter
public enum IotPluginStatusEnum implements ArrayValuable<Integer> {
STOPPED(0, "停止"),
RUNNING(1, "运行");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginStatusEnum::getStatus).toArray(Integer[]::new);
/**
* 状态
*/
private final Integer status;
/**
* 状态名
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.plugin;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 插件类型枚举
*
* @author haohao
*/
@AllArgsConstructor
@Getter
public enum IotPluginTypeEnum implements ArrayValuable<Integer> {
NORMAL(0, "普通插件"),
DEVICE(1, "设备插件");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotPluginTypeEnum::getType).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer type;
/**
* 类型名
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,38 +0,0 @@
package pc.exam.pp.module.iot.enums.product;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 产品数据格式枚举类
*
* @author ahh
* @see <a href="https://help.aliyun.com/zh/iot/user-guide/message-parsing">阿里云 - 什么是消息解析</a>
*/
@AllArgsConstructor
@Getter
public enum IotDataFormatEnum implements ArrayValuable<Integer> {
JSON(0, "标准数据格式JSON"),
CUSTOMIZE(1, "透传/自定义");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataFormatEnum::getType).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer type;
/**
* 描述
*/
private final String description;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,39 +0,0 @@
package pc.exam.pp.module.iot.enums.product;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 联网方式枚举类
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotNetTypeEnum implements ArrayValuable<Integer> {
WIFI(0, "Wi-Fi"),
CELLULAR(1, "Cellular"),
ETHERNET(2, "Ethernet"),
OTHER(3, "其他");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotNetTypeEnum::getType).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer type;
/**
* 描述
*/
private final String description;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,59 +0,0 @@
package pc.exam.pp.module.iot.enums.product;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品的设备类型
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotProductDeviceTypeEnum implements ArrayValuable<Integer> {
DIRECT(0, "直连设备"),
GATEWAY_SUB(1, "网关子设备"),
GATEWAY(2, "网关设备");
/**
* 类型
*/
private final Integer type;
/**
* 描述
*/
private final String description;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProductDeviceTypeEnum::getType).toArray(Integer[]::new);
@Override
public Integer[] array() {
return ARRAYS;
}
/**
* 判断是否是网关
*
* @param type 类型
* @return 是否是网关
*/
public static boolean isGateway(Integer type) {
return GATEWAY.getType().equals(type);
}
/**
* 判断是否是网关子设备
*
* @param type 类型
* @return 是否是网关子设备
*/
public static boolean isGatewaySub(Integer type) {
return GATEWAY_SUB.getType().equals(type);
}
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.product;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品的状态枚举类
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotProductStatusEnum implements ArrayValuable<Integer> {
UNPUBLISHED(0, "开发中"),
PUBLISHED(1, "已发布");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProductStatusEnum::getStatus).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer status;
/**
* 描述
*/
private final String description;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,40 +0,0 @@
package pc.exam.pp.module.iot.enums.product;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 接入网关协议枚举类
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotProtocolTypeEnum implements ArrayValuable<Integer> {
CUSTOM(0, "自定义"),
MODBUS(1, "Modbus"),
OPC_UA(2, "OPC UA"),
ZIGBEE(3, "ZigBee"),
BLE(4, "BLE");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotProtocolTypeEnum::getType).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer type;
/**
* 描述
*/
private final String description;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.product;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 数据校验级别枚举类
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotValidateTypeEnum implements ArrayValuable<Integer> {
WEAK(0, "弱校验"),
NONE(1, "免校验");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotValidateTypeEnum::getType).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer type;
/**
* 描述
*/
private final String description;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,31 +0,0 @@
package pc.exam.pp.module.iot.enums.rule;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 告警配置的接收方式枚举
*
* @author 朋辰
*/
@RequiredArgsConstructor
@Getter
public enum IotAlertConfigReceiveTypeEnum implements ArrayValuable<Integer> {
SMS(1), // 短信
MAIL(2), // 邮箱
NOTIFY(3); // 通知
private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotAlertConfigReceiveTypeEnum::getType).toArray(Integer[]::new);
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.enums.rule;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 数据桥接的方向枚举
*
* @author 朋辰
*/
@RequiredArgsConstructor
@Getter
public enum IotDataBridgeDirectionEnum implements ArrayValuable<Integer> {
INPUT(1), // 输入
OUTPUT(2); // 输出
private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgeDirectionEnum::getType).toArray(Integer[]::new);
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,42 +0,0 @@
package pc.exam.pp.module.iot.enums.rule;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 数据桥接的类型枚举
*
* @author 朋辰
*/
@RequiredArgsConstructor
@Getter
public enum IotDataBridgeTypeEnum implements ArrayValuable<Integer> {
HTTP(1, "HTTP"),
TCP(2, "TCP"),
WEBSOCKET(3, "WEBSOCKET"),
MQTT(10, "MQTT"),
DATABASE(20, "DATABASE"),
REDIS_STREAM(21, "REDIS_STREAM"),
ROCKETMQ(30, "ROCKETMQ"),
RABBITMQ(31, "RABBITMQ"),
KAFKA(32, "KAFKA");
private final Integer type;
private final String name;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgeTypeEnum::getType).toArray(Integer[]::new);
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,31 +0,0 @@
package pc.exam.pp.module.iot.enums.rule;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 规则场景的触发类型枚举
*
* 设备触发,定时触发
*/
@RequiredArgsConstructor
@Getter
public enum IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> {
DEVICE_CONTROL(1), // 设备执行
ALERT(2), // 告警执行
DATA_BRIDGE(3); // 桥接执行
private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneActionTypeEnum::getType).toArray(Integer[]::new);
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,64 +0,0 @@
package pc.exam.pp.module.iot.enums.rule;
import cn.hutool.core.util.ArrayUtil;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 场景触发条件参数的操作符枚举
*
* @author 朋辰
*/
@RequiredArgsConstructor
@Getter
public enum IotRuleSceneTriggerConditionParameterOperatorEnum implements ArrayValuable<String> {
EQUALS("=", "#source == #value"),
NOT_EQUALS("!=", "!(#source == #value)"),
GREATER_THAN(">", "#source > #value"),
GREATER_THAN_OR_EQUALS(">=", "#source >= #value"),
LESS_THAN("<", "#source < #value"),
LESS_THAN_OR_EQUALS("<=", "#source <= #value"),
IN("in", "#values.contains(#source)"),
NOT_IN("not in", "!(#values.contains(#source))"),
BETWEEN("between", "(#source >= #values.get(0)) && (#source <= #values.get(1))"),
NOT_BETWEEN("not between", "(#source < #values.get(0)) || (#source > #values.get(1))"),
LIKE("like", "#source.contains(#value)"), // 字符串匹配
NOT_NULL("not null", "#source != null && #source.length() > 0"); // 非空
private final String operator;
private final String springExpression;
public static final String[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerConditionParameterOperatorEnum::getOperator).toArray(String[]::new);
/**
* Spring 表达式 - 原始值
*/
public static final String SPRING_EXPRESSION_SOURCE = "source";
/**
* Spring 表达式 - 目标值
*/
public static final String SPRING_EXPRESSION_VALUE = "value";
/**
* Spring 表达式 - 目标值数组
*/
public static final String SPRING_EXPRESSION_VALUE_List = "values";
public static IotRuleSceneTriggerConditionParameterOperatorEnum operatorOf(String operator) {
return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values());
}
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.enums.rule;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
/**
* IoT 场景流转的触发类型枚举
*
* @author 朋辰
*/
@RequiredArgsConstructor
@Getter
public enum IotRuleSceneTriggerTypeEnum implements ArrayValuable<Integer> {
DEVICE(1), // 设备触发
TIMER(2); // 定时触发
private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerTypeEnum::getType).toArray(Integer[]::new);
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.enums.thingmodel;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 数据定义的数据类型枚举类
*
* @author 朋辰
*/
@AllArgsConstructor
@Getter
public enum IotDataSpecsDataTypeEnum implements ArrayValuable<String> {
INT("int"),
FLOAT("float"),
DOUBLE("double"),
ENUM("enum"),
BOOL("bool"),
TEXT("text"),
DATE("date"),
STRUCT("struct"),
ARRAY("array");
public static final String[] ARRAYS = Arrays.stream(values()).map(IotDataSpecsDataTypeEnum::getDataType).toArray(String[]::new);
private final String dataType;
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.enums.thingmodel;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品物模型属性读取类型枚举
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotThingModelAccessModeEnum implements ArrayValuable<String> {
READ_ONLY("r"),
READ_WRITE("rw");
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelAccessModeEnum::getMode).toArray(String[]::new);
private final String mode;
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,31 +0,0 @@
package pc.exam.pp.module.iot.enums.thingmodel;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品物模型参数是输入参数还是输出参数枚举
*
* @author HUIHUI
*/
@AllArgsConstructor
@Getter
public enum IotThingModelParamDirectionEnum implements ArrayValuable<String> {
INPUT("input"), // 输入参数
OUTPUT("output"); // 输出参数
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelParamDirectionEnum::getDirection).toArray(String[]::new);
private final String direction;
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.enums.thingmodel;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品物模型服务调用方式枚举
*
* @author HUIHUI
*/
@AllArgsConstructor
@Getter
public enum IotThingModelServiceCallTypeEnum implements ArrayValuable<String> {
ASYNC("async"), // 异步调用
SYNC("sync"); // 同步调用
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelServiceCallTypeEnum::getType).toArray(String[]::new);
private final String type;
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,31 +0,0 @@
package pc.exam.pp.module.iot.enums.thingmodel;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品物模型事件类型枚举
*
* @author HUIHUI
*/
@AllArgsConstructor
@Getter
public enum IotThingModelServiceEventTypeEnum implements ArrayValuable<String> {
INFO("info"), // 信息
ALERT("alert"), // 告警
ERROR("error"); // 故障
public static final String[] ARRAYS = Arrays.stream(values()).map(IotThingModelServiceEventTypeEnum::getType).toArray(String[]::new);
private final String type;
@Override
public String[] array() {
return ARRAYS;
}
}

View File

@@ -1,38 +0,0 @@
package pc.exam.pp.module.iot.enums.thingmodel;
import pc.exam.pp.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* IoT 产品功能(物模型)类型枚举类
*
* @author ahh
*/
@AllArgsConstructor
@Getter
public enum IotThingModelTypeEnum implements ArrayValuable<Integer> {
PROPERTY(1, "属性"),
SERVICE(2, "服务"),
EVENT(3, "事件");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotThingModelTypeEnum::getType).toArray(Integer[]::new);
/**
* 类型
*/
private final Integer type;
/**
* 描述
*/
private final String description;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@@ -1,132 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>exam-module-iot</artifactId>
<groupId>pc.exam.gg</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>exam-module-iot-biz</artifactId>
<name>${project.artifactId}</name>
<description>
物联网 模块,主要实现 产品管理、设备管理、协议管理等功能。
<!-- TODO 芋艿:后续补充下 -->
</description>
<dependencies>
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-module-iot-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
</dependency>
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-redis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-test</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>pc.exam.gg</groupId>
<artifactId>exam-spring-boot-starter-excel</artifactId>
</dependency>
<!-- 消息队列相关 -->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.pf4j</groupId> <!-- PF4J内置插件机制 -->
<artifactId>pf4j-spring</artifactId>
</dependency>
<!-- TODO @芋艿bom 管理 -->
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>4.0.25</version>
<type>pom</type>
</dependency>
<!-- TODO @芋艿bom 管理 -->
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
<version>24.1.2</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>24.1.2</version>
</dependency>
<!-- TODO @芋艿:合理注释 -->
<!-- IoT 数据桥梁的执行器所需消息队列。如果您只需要使用 rocketmq 那么则注释掉其它消息队列即可 -->
<!-- <dependency>-->
<!-- <groupId>org.apache.rocketmq</groupId>-->
<!-- <artifactId>rocketmq-spring-boot-starter</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.kafka</groupId>-->
<!-- <artifactId>spring-kafka</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-amqp</artifactId>-->
<!-- </dependency>-->
</dependencies>
</project>

View File

@@ -1,61 +0,0 @@
package pc.exam.pp.module.iot;
import cn.hutool.script.ScriptUtil;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
/**
* TODO 芋艿:测试脚本的接入
*/
public class ScriptTest {
public static void main2(String[] args) {
// 创建一个 Groovy 脚本引擎
ScriptEngine engine = ScriptUtil.createGroovyEngine();
// 创建绑定参数
Bindings bindings = engine.createBindings();
bindings.put("name", "Alice");
bindings.put("age", 30);
// 定义一个稍微复杂的 Groovy 脚本
String script = "def greeting = 'Hello, ' + name + '!';\n" +
"def ageInFiveYears = age + 5;\n" +
"def message = greeting + ' In five years, you will be ' + ageInFiveYears + ' years old.';\n" +
"return message.toUpperCase();\n";
try {
// 执行脚本并获取结果
Object result = engine.eval(script, bindings);
System.out.println(result); // 输出: HELLO, ALICE! IN FIVE YEARS, YOU WILL BE 35 YEARS OLD.
} catch (ScriptException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 创建一个 JavaScript 脚本引擎
ScriptEngine jsEngine = ScriptUtil.createJsEngine();
// 创建绑定参数
Bindings jsBindings = jsEngine.createBindings();
jsBindings.put("name", "Bob");
jsBindings.put("age", 25);
// 定义一个简单的 JavaScript 脚本
String jsScript = "var greeting = 'Hello, ' + name + '!';\n" +
"var ageInTenYears = age + 10;\n" +
"var message = greeting + ' In ten years, you will be ' + ageInTenYears + ' years old.';\n" +
"message.toUpperCase();\n";
try {
// 执行脚本并获取结果
Object jsResult = jsEngine.eval(jsScript, jsBindings);
System.out.println(jsResult); // 输出: HELLO, BOB! IN TEN YEARS, YOU WILL BE 35 YEARS OLD.
} catch (ScriptException e) {
e.printStackTrace();
}
}
}

View File

@@ -1,77 +0,0 @@
package pc.exam.pp.module.iot.api.device;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.module.iot.api.device.dto.control.upstream.*;
import pc.exam.pp.module.iot.service.device.control.IotDeviceUpstreamService;
import pc.exam.pp.module.iot.service.plugin.IotPluginInstanceService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
/**
* * 设备数据 Upstream 上行 API 实现类
*/
@RestController
@Validated
public class IoTDeviceUpstreamApiImpl implements IotDeviceUpstreamApi {
@Resource
private IotDeviceUpstreamService deviceUpstreamService;
@Resource
private IotPluginInstanceService pluginInstanceService;
// ========== 设备相关 ==========
@Override
public CommonResult<Boolean> updateDeviceState(IotDeviceStateUpdateReqDTO updateReqDTO) {
deviceUpstreamService.updateDeviceState(updateReqDTO);
return success(true);
}
@Override
public CommonResult<Boolean> reportDeviceProperty(IotDevicePropertyReportReqDTO reportReqDTO) {
deviceUpstreamService.reportDeviceProperty(reportReqDTO);
return success(true);
}
@Override
public CommonResult<Boolean> reportDeviceEvent(IotDeviceEventReportReqDTO reportReqDTO) {
deviceUpstreamService.reportDeviceEvent(reportReqDTO);
return success(true);
}
@Override
public CommonResult<Boolean> registerDevice(IotDeviceRegisterReqDTO registerReqDTO) {
deviceUpstreamService.registerDevice(registerReqDTO);
return success(true);
}
@Override
public CommonResult<Boolean> registerSubDevice(IotDeviceRegisterSubReqDTO registerReqDTO) {
deviceUpstreamService.registerSubDevice(registerReqDTO);
return success(true);
}
@Override
public CommonResult<Boolean> addDeviceTopology(IotDeviceTopologyAddReqDTO addReqDTO) {
deviceUpstreamService.addDeviceTopology(addReqDTO);
return success(true);
}
@Override
public CommonResult<Boolean> authenticateEmqxConnection(IotDeviceEmqxAuthReqDTO authReqDTO) {
boolean result = deviceUpstreamService.authenticateEmqxConnection(authReqDTO);
return success(result);
}
// ========== 插件相关 ==========
@Override
public CommonResult<Boolean> heartbeatPluginInstance(IotPluginInstanceHeartbeatReqDTO heartbeatReqDTO) {
pluginInstanceService.heartbeatPluginInstance(heartbeatReqDTO);
return success(true);
}
}

View File

@@ -1,6 +0,0 @@
/**
* 占位
*
* TODO 芋艿:后续删除
*/
package pc.exam.pp.module.iot.api;

View File

@@ -1,75 +0,0 @@
### 请求 /iot/device/downstream 接口(服务调用) => 成功
POST {{baseUrl}}/iot/device/downstream
Content-Type: application/json
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
"id": 25,
"type": "service",
"identifier": "temperature",
"data": {
"xx": "yy"
}
}
### 请求 /iot/device/downstream 接口(属性设置) => 成功
POST {{baseUrl}}/iot/device/downstream
Content-Type: application/json
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
"id": 25,
"type": "property",
"identifier": "set",
"data": {
"xx": "yy"
}
}
### 请求 /iot/device/downstream 接口(属性获取) => 成功
POST {{baseUrl}}/iot/device/downstream
Content-Type: application/json
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
"id": 25,
"type": "property",
"identifier": "get",
"data": ["xx", "yy"]
}
### 请求 /iot/device/downstream 接口(配置设置) => 成功
POST {{baseUrl}}/iot/device/downstream
Content-Type: application/json
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
"id": 25,
"type": "config",
"identifier": "set"
}
### 请求 /iot/device/downstream 接口OTA 升级) => 成功
POST {{baseUrl}}/iot/device/downstream
Content-Type: application/json
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
"id": 25,
"type": "ota",
"identifier": "upgrade",
"data": {
"firmwareId": 1,
"version": "1.0.0",
"signMethod": "MD5",
"fileSign": "d41d8cd98f00b204e9800998ecf8427e",
"fileSize": 1024,
"fileUrl": "http://example.com/firmware.bin",
"information": "{\"desc\":\"升级到最新版本\"}"
}
}

View File

@@ -1,188 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device;
import pc.exam.pp.framework.apilog.core.annotation.ApiAccessLog;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.framework.excel.core.util.ExcelUtils;
import pc.exam.pp.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
import pc.exam.pp.module.iot.controller.admin.device.vo.control.IotDeviceUpstreamReqVO;
import pc.exam.pp.module.iot.controller.admin.device.vo.device.*;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO;
import pc.exam.pp.module.iot.service.device.IotDeviceService;
import pc.exam.pp.module.iot.service.device.control.IotDeviceDownstreamService;
import pc.exam.pp.module.iot.service.device.control.IotDeviceUpstreamService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static pc.exam.pp.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 设备")
@RestController
@RequestMapping("/iot/device")
@Validated
public class IotDeviceController {
@Resource
private IotDeviceService deviceService;
@Resource
private IotDeviceUpstreamService deviceUpstreamService;
@Resource
private IotDeviceDownstreamService deviceDownstreamService;
@PostMapping("/create")
@Operation(summary = "创建设备")
@PreAuthorize("@ss.hasPermission('iot:device:create')")
public CommonResult<Long> createDevice(@Valid @RequestBody IotDeviceSaveReqVO createReqVO) {
return success(deviceService.createDevice(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新设备")
@PreAuthorize("@ss.hasPermission('iot:device:update')")
public CommonResult<Boolean> updateDevice(@Valid @RequestBody IotDeviceSaveReqVO updateReqVO) {
deviceService.updateDevice(updateReqVO);
return success(true);
}
// TODO @芋艿参考阿里云1绑定网关2解绑网关
@PutMapping("/update-group")
@Operation(summary = "更新设备分组")
@PreAuthorize("@ss.hasPermission('iot:device:update')")
public CommonResult<Boolean> updateDeviceGroup(@Valid @RequestBody IotDeviceUpdateGroupReqVO updateReqVO) {
deviceService.updateDeviceGroup(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除单个设备")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('iot:device:delete')")
public CommonResult<Boolean> deleteDevice(@RequestParam("id") Long id) {
deviceService.deleteDevice(id);
return success(true);
}
@DeleteMapping("/delete-list")
@Operation(summary = "删除多个设备")
@Parameter(name = "ids", description = "编号数组", required = true)
@PreAuthorize("@ss.hasPermission('iot:device:delete')")
public CommonResult<Boolean> deleteDeviceList(@RequestParam("ids") Collection<Long> ids) {
deviceService.deleteDeviceList(ids);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得设备")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:device:query')")
public CommonResult<IotDeviceRespVO> getDevice(@RequestParam("id") Long id) {
IotDeviceDO device = deviceService.getDevice(id);
return success(BeanUtils.toBean(device, IotDeviceRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得设备分页")
@PreAuthorize("@ss.hasPermission('iot:device:query')")
public CommonResult<PageResult<IotDeviceRespVO>> getDevicePage(@Valid IotDevicePageReqVO pageReqVO) {
PageResult<IotDeviceDO> pageResult = deviceService.getDevicePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotDeviceRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出设备 Excel")
@PreAuthorize("@ss.hasPermission('iot:device:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportDeviceExcel(@Valid IotDevicePageReqVO exportReqVO,
HttpServletResponse response) throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
CommonResult<PageResult<IotDeviceRespVO>> result = getDevicePage(exportReqVO);
// 导出 Excel
ExcelUtils.write(response, "设备.xls", "数据", IotDeviceRespVO.class,
result.getData().getList());
}
@GetMapping("/count")
@Operation(summary = "获得设备数量")
@Parameter(name = "productId", description = "产品编号", example = "1")
@PreAuthorize("@ss.hasPermission('iot:device:query')")
public CommonResult<Long> getDeviceCount(@RequestParam("productId") Long productId) {
return success(deviceService.getDeviceCountByProductId(productId));
}
@GetMapping("/simple-list")
@Operation(summary = "获取设备的精简信息列表", description = "主要用于前端的下拉选项")
@Parameter(name = "deviceType", description = "设备类型", example = "1")
public CommonResult<List<IotDeviceRespVO>> getSimpleDeviceList(
@RequestParam(value = "deviceType", required = false) Integer deviceType) {
List<IotDeviceDO> list = deviceService.getDeviceListByDeviceType(deviceType);
return success(convertList(list, device -> // 只返回 id、name 字段
new IotDeviceRespVO().setId(device.getId()).setDeviceName(device.getDeviceName())));
}
@PostMapping("/import")
@Operation(summary = "导入设备")
@PreAuthorize("@ss.hasPermission('iot:device:import')")
public CommonResult<IotDeviceImportRespVO> importDevice(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport)
throws Exception {
List<IotDeviceImportExcelVO> list = ExcelUtils.read(file, IotDeviceImportExcelVO.class);
return success(deviceService.importDevice(list, updateSupport));
}
@GetMapping("/get-import-template")
@Operation(summary = "获得导入设备模板")
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<IotDeviceImportExcelVO> list = Arrays.asList(
IotDeviceImportExcelVO.builder().deviceName("温度传感器001").parentDeviceName("gateway110")
.productKey("1de24640dfe").groupNames("灰度分组,生产分组").build(),
IotDeviceImportExcelVO.builder().deviceName("biubiu")
.productKey("YzvHxd4r67sT4s2B").groupNames("").build());
// 输出
ExcelUtils.write(response, "设备导入模板.xls", "数据", IotDeviceImportExcelVO.class, list);
}
@PostMapping("/upstream")
@Operation(summary = "设备上行", description = "可用于设备模拟")
@PreAuthorize("@ss.hasPermission('iot:device:upstream')")
public CommonResult<Boolean> upstreamDevice(@Valid @RequestBody IotDeviceUpstreamReqVO upstreamReqVO) {
deviceUpstreamService.upstreamDevice(upstreamReqVO);
return success(true);
}
@PostMapping("/downstream")
@Operation(summary = "设备下行", description = "可用于设备模拟")
@PreAuthorize("@ss.hasPermission('iot:device:downstream')")
public CommonResult<Boolean> downstreamDevice(@Valid @RequestBody IotDeviceDownstreamReqVO downstreamReqVO) {
deviceDownstreamService.downstreamDevice(downstreamReqVO);
return success(true);
}
// TODO @haohao是不是默认详情接口不返回 secret然后这个接口用于统一返回。然后接口名可以更通用一点。
@GetMapping("/mqtt-connection-params")
@Operation(summary = "获取 MQTT 连接参数")
@PreAuthorize("@ss.hasPermission('iot:device:mqtt-connection-params')")
public CommonResult<IotDeviceMqttConnectionParamsRespVO> getMqttConnectionParams(@RequestParam("deviceId") Long deviceId) {
return success(deviceService.getMqttConnectionParams(deviceId));
}
}

View File

@@ -1,88 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device;
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.device.vo.group.IotDeviceGroupPageReqVO;
import pc.exam.pp.module.iot.controller.admin.device.vo.group.IotDeviceGroupRespVO;
import pc.exam.pp.module.iot.controller.admin.device.vo.group.IotDeviceGroupSaveReqVO;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceGroupDO;
import pc.exam.pp.module.iot.service.device.IotDeviceGroupService;
import pc.exam.pp.module.iot.service.device.IotDeviceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 设备分组")
@RestController
@RequestMapping("/iot/device-group")
@Validated
public class IotDeviceGroupController {
@Resource
private IotDeviceGroupService deviceGroupService;
@Resource
private IotDeviceService deviceService;
@PostMapping("/create")
@Operation(summary = "创建设备分组")
@PreAuthorize("@ss.hasPermission('iot:device-group:create')")
public CommonResult<Long> createDeviceGroup(@Valid @RequestBody IotDeviceGroupSaveReqVO createReqVO) {
return success(deviceGroupService.createDeviceGroup(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新设备分组")
@PreAuthorize("@ss.hasPermission('iot:device-group:update')")
public CommonResult<Boolean> updateDeviceGroup(@Valid @RequestBody IotDeviceGroupSaveReqVO updateReqVO) {
deviceGroupService.updateDeviceGroup(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除设备分组")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('iot:device-group:delete')")
public CommonResult<Boolean> deleteDeviceGroup(@RequestParam("id") Long id) {
deviceGroupService.deleteDeviceGroup(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得设备分组")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:device-group:query')")
public CommonResult<IotDeviceGroupRespVO> getDeviceGroup(@RequestParam("id") Long id) {
IotDeviceGroupDO deviceGroup = deviceGroupService.getDeviceGroup(id);
return success(BeanUtils.toBean(deviceGroup, IotDeviceGroupRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得设备分组分页")
@PreAuthorize("@ss.hasPermission('iot:device-group:query')")
public CommonResult<PageResult<IotDeviceGroupRespVO>> getDeviceGroupPage(@Valid IotDeviceGroupPageReqVO pageReqVO) {
PageResult<IotDeviceGroupDO> pageResult = deviceGroupService.getDeviceGroupPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotDeviceGroupRespVO.class,
group -> group.setDeviceCount(deviceService.getDeviceCountByGroupId(group.getId()))));
}
@GetMapping("/simple-list")
@Operation(summary = "获取设备分组的精简信息列表", description = "只包含被开启的分组,主要用于前端的下拉选项")
public CommonResult<List<IotDeviceGroupRespVO>> getSimpleDeviceGroupList() {
List<IotDeviceGroupDO> list = deviceGroupService.getDeviceGroupListByStatus(CommonStatusEnum.ENABLE.getStatus());
return success(convertList(list, group -> // 只返回 id、name 字段
new IotDeviceGroupRespVO().setId(group.getId()).setName(group.getName())));
}
}

View File

@@ -1,39 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO;
import pc.exam.pp.module.iot.controller.admin.device.vo.data.IotDeviceLogRespVO;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceLogDO;
import pc.exam.pp.module.iot.service.device.data.IotDeviceLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT 设备日志")
@RestController
@RequestMapping("/iot/device/log")
@Validated
public class IotDeviceLogController {
@Resource
private IotDeviceLogService deviceLogService;
@GetMapping("/page")
@Operation(summary = "获得设备日志分页")
@PreAuthorize("@ss.hasPermission('iot:device:log-query')")
public CommonResult<PageResult<IotDeviceLogRespVO>> getDeviceLogPage(@Valid IotDeviceLogPageReqVO pageReqVO) {
PageResult<IotDeviceLogDO> pageResult = deviceLogService.getDeviceLogPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotDeviceLogRespVO.class));
}
}

View File

@@ -1,95 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.module.iot.controller.admin.device.vo.data.IotDevicePropertyHistoryPageReqVO;
import pc.exam.pp.module.iot.controller.admin.device.vo.data.IotDevicePropertyRespVO;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import pc.exam.pp.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
import pc.exam.pp.module.iot.service.device.IotDeviceService;
import pc.exam.pp.module.iot.service.device.data.IotDevicePropertyService;
import pc.exam.pp.module.iot.service.thingmodel.IotThingModelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 设备属性")
@RestController
@RequestMapping("/iot/device/property")
@Validated
public class IotDevicePropertyController {
@Resource
private IotDevicePropertyService devicePropertyService;
@Resource
private IotThingModelService thingModelService;
@Resource
private IotDeviceService deviceService;
@GetMapping("/latest")
@Operation(summary = "获取设备属性最新属性")
@Parameters({
@Parameter(name = "deviceId", description = "设备编号", required = true),
@Parameter(name = "identifier", description = "标识符"),
@Parameter(name = "name", description = "名称")
})
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
public CommonResult<List<IotDevicePropertyRespVO>> getLatestDeviceProperties(
@RequestParam("deviceId") Long deviceId,
@RequestParam(value = "identifier", required = false) String identifier,
@RequestParam(value = "name", required = false) String name) {
Map<String, IotDevicePropertyDO> properties = devicePropertyService.getLatestDeviceProperties(deviceId);
// 拼接数据
IotDeviceDO device = deviceService.getDevice(deviceId);
Assert.notNull(device, "设备不存在");
List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(device.getProductId());
return success(convertList(properties.entrySet(), entry -> {
IotThingModelDO thingModel = CollUtil.findOne(thingModels,
item -> item.getIdentifier().equals(entry.getKey()));
if (thingModel == null || thingModel.getProperty() == null) {
return null;
}
if (StrUtil.isNotEmpty(identifier) && !StrUtil.contains(thingModel.getIdentifier(), identifier)) {
return null;
}
if (StrUtil.isNotEmpty(name) && !StrUtil.contains(thingModel.getName(), name)) {
return null;
}
// 构建对象
IotDevicePropertyDO property = entry.getValue();
return new IotDevicePropertyRespVO().setProperty(thingModel.getProperty())
.setValue(property.getValue()).setUpdateTime(LocalDateTimeUtil.toEpochMilli(property.getUpdateTime()));
}));
}
@GetMapping("/history-page")
@Operation(summary = "获取设备属性历史数据")
@PreAuthorize("@ss.hasPermission('iot:device:property-query')")
public CommonResult<PageResult<IotDevicePropertyRespVO>> getHistoryDevicePropertyPage(
@Valid IotDevicePropertyHistoryPageReqVO pageReqVO) {
Assert.notEmpty(pageReqVO.getIdentifier(), "标识符不能为空");
return success(devicePropertyService.getHistoryDevicePropertyPage(pageReqVO));
}
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.control;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.device.IotDeviceMessageTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备下行 Request VO") // 服务调用、属性设置、属性获取等
@Data
public class IotDeviceDownstreamReqVO {
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
@NotNull(message = "设备编号不能为空")
private Long id;
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
@NotEmpty(message = "消息类型不能为空")
@InEnum(IotDeviceMessageTypeEnum.class)
private String type;
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "report")
@NotEmpty(message = "标识符不能为空")
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举类
@Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED)
private Object data; // 例如说:服务调用的 params、属性设置的 properties
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.control;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.device.IotDeviceMessageTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备上行 Request VO") // 属性上报、事件上报、状态变更等
@Data
public class IotDeviceUpstreamReqVO {
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
@NotNull(message = "设备编号不能为空")
private Long id;
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
@NotEmpty(message = "消息类型不能为空")
@InEnum(IotDeviceMessageTypeEnum.class)
private String type;
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "report")
@NotEmpty(message = "标识符不能为空")
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举类
@Schema(description = "请求参数", requiredMode = Schema.RequiredMode.REQUIRED)
private Object data; // 例如说:属性上报的 properties、事件上报的 params
}

View File

@@ -1,22 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.data;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备日志分页查询 Request VO")
@Data
public class IotDeviceLogPageReqVO extends PageParam {
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
@NotEmpty(message = "设备标识不能为空")
private String deviceKey;
@Schema(description = "消息类型", example = "property")
private String type; // 参见 IotDeviceMessageTypeEnum 枚举,精准匹配
@Schema(description = "标识符", example = "temperature")
private String identifier; // 参见 IotDeviceMessageIdentifierEnum 枚举,模糊匹配
}

View File

@@ -1,36 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.data;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - IoT 设备日志 Response VO")
@Data
public class IotDeviceLogRespVO {
@Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private String id;
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "product123")
private String productKey;
@Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "device123")
private String deviceKey;
@Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "property")
private String type;
@Schema(description = "标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "temperature")
private String identifier;
@Schema(description = "日志内容", requiredMode = Schema.RequiredMode.REQUIRED)
private String content;
@Schema(description = "上报时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime reportTime;
@Schema(description = "记录时间戳", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime ts;
}

View File

@@ -1,35 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.data;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - IoT 设备属性历史分页 Request VO")
@Data
public class IotDevicePropertyHistoryPageReqVO extends PageParam {
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
@NotNull(message = "设备编号不能为空")
private Long deviceId;
@Schema(description = "设备 Key", hidden = true)
private String deviceKey; // 非前端传递,后端自己查询设置
@Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "属性标识符不能为空")
private String identifier;
@Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Size(min = 2, max = 2, message = "请选择时间范围")
private LocalDateTime[] times;
}

View File

@@ -1,20 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.data;
import pc.exam.pp.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备属性 Response VO")
@Data
public class IotDevicePropertyRespVO {
@Schema(description = "属性定义", requiredMode = Schema.RequiredMode.REQUIRED)
private ThingModelProperty property;
@Schema(description = "最新值", requiredMode = Schema.RequiredMode.REQUIRED)
private Object value;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private Long updateTime; // 由于从 TDengine 查询出来的是 Long 类型,所以这里也使用 Long 类型
}

View File

@@ -1,37 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* 设备 Excel 导入 VO
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false避免设备导入有问题
public class IotDeviceImportExcelVO {
@ExcelProperty("设备名称")
@NotEmpty(message = "设备名称不能为空")
private String deviceName;
@ExcelProperty("父设备名称")
@Schema(description = "父设备名称", example = "网关001")
private String parentDeviceName;
@ExcelProperty("产品标识")
@NotEmpty(message = "产品标识不能为空")
private String productKey;
@ExcelProperty("设备分组")
private String groupNames;
}

View File

@@ -1,23 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import java.util.List;
import java.util.Map;
@Schema(description = "管理后台 - IoT 设备导入 Response VO")
@Data
@Builder
public class IotDeviceImportRespVO {
@Schema(description = "创建成功的设备名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> createDeviceNames;
@Schema(description = "更新成功的设备名称数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> updateDeviceNames;
@Schema(description = "导入失败的设备集合,key为设备名称,value为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
private Map<String, String> failureDeviceNames;
}

View File

@@ -1,25 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备 MQTT 连接参数 Response VO")
@Data
@ExcelIgnoreUnannotated
public class IotDeviceMqttConnectionParamsRespVO {
@Schema(description = "MQTT 客户端 ID", example = "24602")
@ExcelProperty("MQTT 客户端 ID")
private String mqttClientId;
@Schema(description = "MQTT 用户名", example = "芋艿")
@ExcelProperty("MQTT 用户名")
private String mqttUsername;
@Schema(description = "MQTT 密码")
@ExcelProperty("MQTT 密码")
private String mqttPassword;
}

View File

@@ -1,34 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.device.IotDeviceStateEnum;
import pc.exam.pp.module.iot.enums.product.IotProductDeviceTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备分页 Request VO")
@Data
public class IotDevicePageReqVO extends PageParam {
@Schema(description = "设备名称", example = "王五")
private String deviceName;
@Schema(description = "备注名称", example = "张三")
private String nickname;
@Schema(description = "产品编号", example = "26202")
private Long productId;
@Schema(description = "设备类型", example = "1")
@InEnum(IotProductDeviceTypeEnum.class)
private Integer deviceType;
@Schema(description = "设备状态", example = "1")
@InEnum(IotDeviceStateEnum.class)
private Integer status;
@Schema(description = "设备分组编号", example = "1024")
private Long groupId;
}

View File

@@ -1,93 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import pc.exam.pp.framework.excel.core.annotations.DictFormat;
import pc.exam.pp.framework.excel.core.convert.DictConvert;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Set;
import static pc.exam.pp.module.iot.enums.DictTypeConstants.DEVICE_STATE;
@Schema(description = "管理后台 - IoT 设备 Response VO")
@Data
@ExcelIgnoreUnannotated
public class IotDeviceRespVO {
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
private Long id;
@Schema(description = "设备唯一标识符", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("设备唯一标识符")
private String deviceKey;
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
@ExcelProperty("设备名称")
private String deviceName;
@Schema(description = "设备备注名称", example = "张三")
@ExcelProperty("设备备注名称")
private String nickname;
@Schema(description = "设备序列号", example = "1024")
@ExcelProperty("设备序列号")
private String serialNumber;
@Schema(description = "设备图片", example = "我是一名码农")
@ExcelProperty("设备图片")
private String picUrl;
@Schema(description = "设备分组编号数组", example = "1,2")
private Set<Long> groupIds;
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26202")
@ExcelProperty("产品编号")
private Long productId;
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品 Key")
private String productKey;
@Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("设备类型")
private Integer deviceType;
@Schema(description = "网关设备 ID", example = "16380")
private Long gatewayId;
@Schema(description = "设备状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty(value = "设备状态", converter = DictConvert.class)
@DictFormat(DEVICE_STATE)
private Integer state;
@Schema(description = "最后上线时间")
@ExcelProperty("最后上线时间")
private LocalDateTime onlineTime;
@Schema(description = "最后离线时间")
@ExcelProperty("最后离线时间")
private LocalDateTime offlineTime;
@Schema(description = "设备激活时间")
@ExcelProperty("设备激活时间")
private LocalDateTime activeTime;
@Schema(description = "设备密钥,用于设备认证")
@ExcelProperty("设备密钥")
private String deviceSecret;
@Schema(description = "认证类型(如一机一密、动态注册)", example = "2")
@ExcelProperty("认证类型(如一机一密、动态注册)")
private String authType;
@Schema(description = "设备配置", example = "{\"abc\": \"efg\"}")
private String config;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@@ -1,44 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.Set;
@Schema(description = "管理后台 - IoT 设备新增/修改 Request VO")
@Data
public class IotDeviceSaveReqVO {
@Schema(description = "设备编号", example = "177")
private Long id;
@Schema(description = "设备编号", requiredMode = Schema.RequiredMode.AUTO, example = "177")
@Size(max = 50, message = "设备编号长度不能超过 50 个字符")
private String deviceKey;
@Schema(description = "设备名称", requiredMode = Schema.RequiredMode.AUTO, example = "王五")
private String deviceName;
@Schema(description = "备注名称", example = "张三")
private String nickname;
@Schema(description = "设备序列号", example = "123456")
private String serialNumber;
@Schema(description = "设备图片", example = "https://iocoder.cn/1.png")
private String picUrl;
@Schema(description = "设备分组编号数组", example = "1,2")
private Set<Long> groupIds;
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26202")
private Long productId;
@Schema(description = "网关设备 ID", example = "16380")
private Long gatewayId;
@Schema(description = "设备配置", example = "{\"abc\": \"efg\"}")
private String config;
}

View File

@@ -1,21 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.device;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.Set;
@Schema(description = "管理后台 - IoT 设备更新分组 Request VO")
@Data
public class IotDeviceUpdateGroupReqVO {
@Schema(description = "设备编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
@NotEmpty(message = "设备编号列表不能为空")
private Set<Long> ids;
@Schema(description = "分组编号列表", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,2,3")
@NotEmpty(message = "分组编号列表不能为空")
private Set<Long> groupIds;
}

View File

@@ -1,25 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.group;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - IoT 设备分组分页 Request VO")
@Data
public class IotDeviceGroupPageReqVO extends PageParam {
@Schema(description = "分组名字", example = "李四")
private String name;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -1,30 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.group;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - IoT 设备分组 Response VO")
@Data
public class IotDeviceGroupRespVO {
@Schema(description = "分组 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3583")
private Long id;
@Schema(description = "分组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
private String name;
@Schema(description = "分组状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "分组描述", example = "你说的对")
private String description;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long deviceCount;
}

View File

@@ -1,26 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.device.vo.group;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - IoT 设备分组新增/修改 Request VO")
@Data
public class IotDeviceGroupSaveReqVO {
@Schema(description = "分组 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3583")
private Long id;
@Schema(description = "分组名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotEmpty(message = "分组名字不能为空")
private String name;
@Schema(description = "分组状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "分组状态不能为空")
private Integer status;
@Schema(description = "分组描述", example = "你说的对")
private String description;
}

View File

@@ -1,62 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwarePageReqVO;
import pc.exam.pp.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareRespVO;
import pc.exam.pp.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareCreateReqVO;
import pc.exam.pp.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareUpdateReqVO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
import pc.exam.pp.module.iot.service.ota.IotOtaFirmwareService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT OTA 固件")
@RestController
@RequestMapping("/iot/ota-firmware")
@Validated
public class IotOtaFirmwareController {
@Resource
private IotOtaFirmwareService otaFirmwareService;
@PostMapping("/create")
@Operation(summary = "创建 OTA 固件")
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:create')")
public CommonResult<Long> createOtaFirmware(@Valid @RequestBody IotOtaFirmwareCreateReqVO createReqVO) {
return success(otaFirmwareService.createOtaFirmware(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新 OTA 固件")
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:update')")
public CommonResult<Boolean> updateOtaFirmware(@Valid @RequestBody IotOtaFirmwareUpdateReqVO updateReqVO) {
otaFirmwareService.updateOtaFirmware(updateReqVO);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得 OTA 固件")
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:query')")
public CommonResult<IotOtaFirmwareRespVO> getOtaFirmware(@RequestParam("id") Long id) {
IotOtaFirmwareDO otaFirmware = otaFirmwareService.getOtaFirmware(id);
return success(BeanUtils.toBean(otaFirmware, IotOtaFirmwareRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得 OTA 固件分页")
@PreAuthorize("@ss.hasPermission('iot:ota-firmware:query')")
public CommonResult<PageResult<IotOtaFirmwareRespVO>> getOtaFirmwarePage(@Valid IotOtaFirmwarePageReqVO pageReqVO) {
PageResult<IotOtaFirmwareDO> pageResult = otaFirmwareService.getOtaFirmwarePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotOtaFirmwareRespVO.class));
}
}

View File

@@ -1,75 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.record.IotOtaUpgradeRecordPageReqVO;
import pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.record.IotOtaUpgradeRecordRespVO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaUpgradeRecordDO;
import pc.exam.pp.module.iot.service.ota.IotOtaUpgradeRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT OTA 升级记录")
@RestController
@RequestMapping("/iot/ota-upgrade-record")
@Validated
public class IotOtaUpgradeRecordController {
@Resource
private IotOtaUpgradeRecordService upgradeRecordService;
@GetMapping("/get-statistics")
@Operation(summary = "固件升级设备统计")
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
@Parameter(name = "firmwareId", description = "固件编号", required = true, example = "1024")
public CommonResult<Map<Integer, Long>> getOtaUpgradeRecordStatistics(@RequestParam(value = "firmwareId") Long firmwareId) {
return success(upgradeRecordService.getOtaUpgradeRecordStatistics(firmwareId));
}
@GetMapping("/get-count")
@Operation(summary = "获得升级记录分页 tab 数量")
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
public CommonResult<Map<Integer, Long>> getOtaUpgradeRecordCount(
@Valid IotOtaUpgradeRecordPageReqVO pageReqVO) {
return success(upgradeRecordService.getOtaUpgradeRecordCount(pageReqVO));
}
@GetMapping("/page")
@Operation(summary = "获得升级记录分页")
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
public CommonResult<PageResult<IotOtaUpgradeRecordRespVO>> getUpgradeRecordPage(
@Valid IotOtaUpgradeRecordPageReqVO pageReqVO) {
PageResult<IotOtaUpgradeRecordDO> pageResult = upgradeRecordService.getUpgradeRecordPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotOtaUpgradeRecordRespVO.class));
}
@GetMapping("/get")
@Operation(summary = "获得升级记录")
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')")
@Parameter(name = "id", description = "升级记录编号", required = true, example = "1024")
public CommonResult<IotOtaUpgradeRecordRespVO> getUpgradeRecord(@RequestParam("id") Long id) {
IotOtaUpgradeRecordDO upgradeRecord = upgradeRecordService.getUpgradeRecord(id);
return success(BeanUtils.toBean(upgradeRecord, IotOtaUpgradeRecordRespVO.class));
}
@PutMapping("/retry")
@Operation(summary = "重试升级记录")
@PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:retry')")
@Parameter(name = "id", description = "升级记录编号", required = true, example = "1024")
public CommonResult<Boolean> retryUpgradeRecord(@RequestParam("id") Long id) {
upgradeRecordService.retryUpgradeRecord(id);
return success(true);
}
}

View File

@@ -1,64 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskPageReqVO;
import pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskRespVO;
import pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.task.IotOtaUpgradeTaskSaveReqVO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaUpgradeTaskDO;
import pc.exam.pp.module.iot.service.ota.IotOtaUpgradeTaskService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT OTA 升级任务")
@RestController
@RequestMapping("/iot/ota-upgrade-task")
@Validated
public class IotOtaUpgradeTaskController {
@Resource
private IotOtaUpgradeTaskService upgradeTaskService;
@PostMapping("/create")
@Operation(summary = "创建升级任务")
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:create')")
public CommonResult<Long> createUpgradeTask(@Valid @RequestBody IotOtaUpgradeTaskSaveReqVO createReqVO) {
return success(upgradeTaskService.createUpgradeTask(createReqVO));
}
@PostMapping("/cancel")
@Operation(summary = "取消升级任务")
@Parameter(name = "id", description = "升级任务编号", required = true)
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:cancel')")
public CommonResult<Boolean> cancelUpgradeTask(@RequestParam("id") Long id) {
upgradeTaskService.cancelUpgradeTask(id);
return success(true);
}
@GetMapping("/page")
@Operation(summary = "获得升级任务分页")
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:query')")
public CommonResult<PageResult<IotOtaUpgradeTaskRespVO>> getUpgradeTaskPage(@Valid IotOtaUpgradeTaskPageReqVO pageReqVO) {
PageResult<IotOtaUpgradeTaskDO> pageResult = upgradeTaskService.getUpgradeTaskPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotOtaUpgradeTaskRespVO.class));
}
@GetMapping("/get")
@Operation(summary = "获得升级任务")
@Parameter(name = "id", description = "升级任务编号", required = true, example = "1024")
@PreAuthorize(value = "@ss.hasPermission('iot:ota-upgrade-task:query')")
public CommonResult<IotOtaUpgradeTaskRespVO> getUpgradeTask(@RequestParam("id") Long id) {
IotOtaUpgradeTaskDO upgradeTask = upgradeTaskService.getUpgradeTask(id);
return success(BeanUtils.toBean(upgradeTask, IotOtaUpgradeTaskRespVO.class));
}
}

View File

@@ -1,40 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.firmware;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Schema(description = "管理后台 - IoT OTA 固件创建 Request VO")
@Data
public class IotOtaFirmwareCreateReqVO {
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "智能开关固件")
@NotEmpty(message = "固件名称不能为空")
private String name;
@Schema(description = "固件描述", example = "某品牌型号固件,测试用")
private String description;
@Schema(description = "版本号", requiredMode = REQUIRED, example = "1.0.0")
@NotEmpty(message = "版本号不能为空")
private String version;
@Schema(description = "产品编号", requiredMode = REQUIRED, example = "1024")
@NotNull(message = "产品编号不能为空")
private String productId;
@Schema(description = "签名方式", example = "MD5")
// TODO @li是不是必传哈
private String signMethod;
@Schema(description = "固件文件 URL", requiredMode = REQUIRED, example = "https://www.iocoder.cn/exam-firmware.zip")
@NotEmpty(message = "固件文件 URL 不能为空")
private String fileUrl;
@Schema(description = "自定义信息,建议使用 JSON 格式", example = "{\"key1\":\"value1\",\"key2\":\"value2\"}")
private String information;
}

View File

@@ -1,23 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.firmware;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "管理后台 - IoT OTA 固件分页 Request VO")
public class IotOtaFirmwarePageReqVO extends PageParam {
/**
* 固件名称
*/
@Schema(description = "固件名称", example = "智能开关固件")
private String name;
/**
* 产品标识
*/
@Schema(description = "产品标识", example = "1024")
private String productId;
}

View File

@@ -1,85 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.firmware;
import pc.exam.pp.module.iot.dal.dataobject.product.IotProductDO;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Data
@Schema(description = "管理后台 - IoT OTA 固件 Response VO")
public class IotOtaFirmwareRespVO implements VO {
/**
* 固件编号
*/
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
private Long id;
/**
* 固件名称
*/
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "OTA固件")
private String name;
/**
* 固件描述
*/
@Schema(description = "固件描述")
private String description;
/**
* 版本号
*/
@Schema(description = "版本号", requiredMode = REQUIRED, example = "1.0.0")
private String version;
/**
* 产品编号
* <p>
* 关联 {@link pc.exam.pp.module.iot.dal.dataobject.product.IotProductDO#getId()}
*/
@Schema(description = "产品编号", requiredMode = REQUIRED, example = "1024")
@Trans(type = TransType.SIMPLE, target = IotProductDO.class, fields = {"name"}, refs = {"productName"})
private String productId;
/**
* 产品标识
* <p>
* 冗余 {@link pc.exam.pp.module.iot.dal.dataobject.product.IotProductDO#getProductKey()}
*/
@Schema(description = "产品标识", requiredMode = REQUIRED, example = "iot-product-key")
private String productKey;
/**
* 产品名称
*/
@Schema(description = "产品名称", requiredMode = REQUIRED, example = "OTA产品")
private String productName;
/**
* 签名方式
* <p>
* 例如说MD5、SHA256
*/
@Schema(description = "签名方式", example = "MD5")
private String signMethod;
/**
* 固件文件签名
*/
@Schema(description = "固件文件签名", example = "1024")
private String fileSign;
/**
* 固件文件大小
*/
@Schema(description = "固件文件大小", requiredMode = REQUIRED, example = "1024")
private Long fileSize;
/**
* 固件文件 URL
*/
@Schema(description = "固件文件 URL", requiredMode = REQUIRED, example = "https://www.iocoder.cn")
private String fileUrl;
/**
* 自定义信息,建议使用 JSON 格式
*/
@Schema(description = "自定义信息,建议使用 JSON 格式")
private String information;
}

View File

@@ -1,26 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.firmware;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Schema(description = "管理后台 - IoT OTA 固件更新 Request VO")
@Data
public class IotOtaFirmwareUpdateReqVO {
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
@NotNull(message = "固件编号不能为空")
private Long id;
// TODO @liname 是不是可以飞必传哈
@Schema(description = "固件名称", requiredMode = REQUIRED, example = "智能开关固件")
@NotEmpty(message = "固件名称不能为空")
private String name;
@Schema(description = "固件描述", example = "某品牌型号固件,测试用")
private String description;
}

View File

@@ -1,32 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.record;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Data
@Schema(description = "管理后台 - IoT OTA 升级记录分页 Request VO")
public class IotOtaUpgradeRecordPageReqVO extends PageParam {
// TODO @li已经有注解不用重复注释
/**
* 升级任务编号字段。
* <p>
* 该字段用于标识升级任务的唯一编号,不能为空。
*/
@Schema(description = "升级任务编号", requiredMode = REQUIRED, example = "1024")
@NotNull(message = "升级任务编号不能为空")
private Long taskId;
/**
* 设备标识字段。
* <p>
* 该字段用于标识设备的名称,通常用于区分不同的设备。
*/
@Schema(description = "设备标识", requiredMode = REQUIRED, example = "摄像头A1-1")
private String deviceName;
}

View File

@@ -1,109 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.record;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaUpgradeTaskDO;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Data
@Schema(description = "管理后台 - IoT OTA 升级记录 Response VO")
public class IotOtaUpgradeRecordRespVO {
/**
* 升级记录编号
*/
@Schema(description = "升级记录编号", requiredMode = REQUIRED, example = "1024")
private Long id;
/**
* 固件编号
* <p>
* 关联 {@link IotOtaFirmwareDO#getId()}
*/
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
@Trans(type = TransType.SIMPLE, target = IotOtaFirmwareDO.class, fields = {"version"}, refs = {"firmwareVersion"})
private Long firmwareId;
/**
* 固件版本
*/
@Schema(description = "固件版本", requiredMode = REQUIRED, example = "v1.0.0")
private String firmwareVersion;
/**
* 任务编号
* <p>
* 关联 {@link IotOtaUpgradeTaskDO#getId()}
*/
@Schema(description = "任务编号", requiredMode = REQUIRED, example = "1024")
private Long taskId;
/**
* 产品标识
* <p>
* 关联 {@link pc.exam.pp.module.iot.dal.dataobject.product.IotProductDO#getId()}
*/
@Schema(description = "产品标识", requiredMode = REQUIRED, example = "iot")
private String productKey;
/**
* 设备名称
* <p>
* 关联 {@link pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
*/
@Schema(description = "设备名称", requiredMode = REQUIRED, example = "iot")
private String deviceName;
/**
* 设备编号
* <p>
* 关联 {@link pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO#getId()}
*/
@Schema(description = "设备编号", requiredMode = REQUIRED, example = "1024")
private String deviceId;
/**
* 来源的固件编号
* <p>
* 关联 {@link IotDeviceDO#getFirmwareId()}
*/
@Schema(description = "来源的固件编号", requiredMode = REQUIRED, example = "1024")
@Trans(type = TransType.SIMPLE, target = IotOtaFirmwareDO.class, fields = {"version"}, refs = {"fromFirmwareVersion"})
private Long fromFirmwareId;
/**
* 来源的固件版本
*/
@Schema(description = "来源的固件版本", requiredMode = REQUIRED, example = "v1.0.0")
private String fromFirmwareVersion;
/**
* 升级状态
* <p>
* 关联 {@link pc.exam.pp.module.iot.enums.ota.IotOtaUpgradeRecordStatusEnum}
*/
@Schema(description = "升级状态", requiredMode = REQUIRED, allowableValues = {"0", "10", "20", "30", "40", "50"})
private Integer status;
/**
* 升级进度,百分比
*/
@Schema(description = "升级进度,百分比", requiredMode = REQUIRED, example = "10")
private Integer progress;
/**
* 升级进度描述
* <p>
* 注意,只记录设备最后一次的升级进度描述
* 如果想看历史记录,可以查看 {@link pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceLogDO} 设备日志
*/
@Schema(description = "升级进度描述", requiredMode = REQUIRED, example = "10")
private String description;
/**
* 升级开始时间
*/
@Schema(description = "升级开始时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
private LocalDateTime startTime;
/**
* 升级结束时间
*/
@Schema(description = "升级结束时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
private LocalDateTime endTime;
}

View File

@@ -1,27 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.task;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Data
@Schema(description = "管理后台 - IoT OTA 升级任务分页 Request VO")
public class IotOtaUpgradeTaskPageReqVO extends PageParam {
/**
* 任务名称字段,用于描述任务的名称
*/
@Schema(description = "任务名称", example = "升级任务")
private String name;
/**
* 固件编号字段,用于唯一标识固件,不能为空
*/
@NotNull(message = "固件编号不能为空")
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
private Long firmwareId;
}

View File

@@ -1,84 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.task;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
import com.fhs.core.trans.vo.VO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Data
@Schema(description = "管理后台 - IoT OTA 升级任务 Response VO")
public class IotOtaUpgradeTaskRespVO implements VO {
/**
* 任务编号
*/
@Schema(description = "任务编号", requiredMode = REQUIRED, example = "1024")
private Long id;
/**
* 任务名称
*/
@Schema(description = "任务名称", requiredMode = REQUIRED, example = "升级任务")
private String name;
/**
* 任务描述
*/
@Schema(description = "任务描述", example = "升级任务")
private String description;
/**
* 固件编号
* <p>
* 关联 {@link IotOtaFirmwareDO#getId()}
*/
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
private Long firmwareId;
/**
* 任务状态
* <p>
* 关联 {@link pc.exam.pp.module.iot.enums.ota.IotOtaUpgradeTaskStatusEnum}
*/
@Schema(description = "任务状态", requiredMode = REQUIRED, allowableValues = {"10", "20", "21", "30"})
private Integer status;
/**
* 任务状态名称
*/
@Schema(description = "任务状态名称", requiredMode = REQUIRED, example = "进行中")
private String statusName;
/**
* 升级范围
* <p>
* 关联 {@link pc.exam.pp.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
*/
@Schema(description = "升级范围", requiredMode = REQUIRED, allowableValues = {"1", "2"})
private Integer scope;
/**
* 设备数量
*/
@Schema(description = "设备数量", requiredMode = REQUIRED, example = "1024")
private Long deviceCount;
/**
* 选中的设备编号数组
* <p>
* 关联 {@link IotDeviceDO#getId()}
*/
@Schema(description = "选中的设备编号数组", example = "1024")
private List<Long> deviceIds;
/**
* 选中的设备名字数组
* <p>
* 关联 {@link IotDeviceDO#getDeviceName()}
*/
@Schema(description = "选中的设备名字数组", example = "1024")
private List<String> deviceNames;
/**
* 创建时间
*/
@Schema(description = "创建时间", requiredMode = REQUIRED, example = "2022-07-08 07:30:00")
private LocalDateTime createTime;
}

View File

@@ -1,63 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.ota.vo.upgrade.task;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.dal.dataobject.device.IotDeviceDO;
import pc.exam.pp.module.iot.dal.dataobject.ota.IotOtaFirmwareDO;
import pc.exam.pp.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Data
@Schema(description = "管理后台 - IoT OTA 升级任务创建/修改 Request VO")
public class IotOtaUpgradeTaskSaveReqVO {
// TODO @li已经有注解不用重复注释
// TODO @li @Schema 写在参数校验前面。先有定义;其他的,也检查下;
/**
* 任务名称
*/
@NotEmpty(message = "任务名称不能为空")
@Schema(description = "任务名称", requiredMode = REQUIRED, example = "升级任务")
private String name;
/**
* 任务描述
*/
@Schema(description = "任务描述", example = "升级任务")
private String description;
/**
* 固件编号
* <p>
* 关联 {@link IotOtaFirmwareDO#getId()}
*/
@NotNull(message = "固件编号不能为空")
@Schema(description = "固件编号", requiredMode = REQUIRED, example = "1024")
private Long firmwareId;
/**
* 升级范围
* <p>
* 关联 {@link pc.exam.pp.module.iot.enums.ota.IotOtaUpgradeTaskScopeEnum}
*/
@NotNull(message = "升级范围不能为空")
@InEnum(value = IotOtaUpgradeTaskScopeEnum.class)
@Schema(description = "升级范围", requiredMode = REQUIRED, example = "1")
private Integer scope;
/**
* 选中的设备编号数组
* <p>
* 关联 {@link IotDeviceDO#getId()}
*/
@Schema(description = "选中的设备编号数组", requiredMode = REQUIRED, example = "[1,2,3,4]")
private List<Long> deviceIds;
}

View File

@@ -1,90 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.plugin.vo.config.PluginConfigImportReqVO;
import pc.exam.pp.module.iot.controller.admin.plugin.vo.config.PluginConfigPageReqVO;
import pc.exam.pp.module.iot.controller.admin.plugin.vo.config.PluginConfigRespVO;
import pc.exam.pp.module.iot.controller.admin.plugin.vo.config.PluginConfigSaveReqVO;
import pc.exam.pp.module.iot.controller.admin.plugin.vo.config.PluginConfigStatusReqVO;
import pc.exam.pp.module.iot.dal.dataobject.plugin.IotPluginConfigDO;
import pc.exam.pp.module.iot.service.plugin.IotPluginConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT 插件配置")
@RestController
@RequestMapping("/iot/plugin-config")
@Validated
public class PluginConfigController {
@Resource
private IotPluginConfigService pluginConfigService;
@PostMapping("/create")
@Operation(summary = "创建插件配置")
@PreAuthorize("@ss.hasPermission('iot:plugin-config:create')")
public CommonResult<Long> createPluginConfig(@Valid @RequestBody PluginConfigSaveReqVO createReqVO) {
return success(pluginConfigService.createPluginConfig(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新插件配置")
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
public CommonResult<Boolean> updatePluginConfig(@Valid @RequestBody PluginConfigSaveReqVO updateReqVO) {
pluginConfigService.updatePluginConfig(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除插件配置")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('iot:plugin-config:delete')")
public CommonResult<Boolean> deletePluginConfig(@RequestParam("id") Long id) {
pluginConfigService.deletePluginConfig(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得插件配置")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:plugin-config:query')")
public CommonResult<PluginConfigRespVO> getPluginConfig(@RequestParam("id") Long id) {
IotPluginConfigDO pluginConfig = pluginConfigService.getPluginConfig(id);
return success(BeanUtils.toBean(pluginConfig, PluginConfigRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得插件配置分页")
@PreAuthorize("@ss.hasPermission('iot:plugin-config:query')")
public CommonResult<PageResult<PluginConfigRespVO>> getPluginConfigPage(@Valid PluginConfigPageReqVO pageReqVO) {
PageResult<IotPluginConfigDO> pageResult = pluginConfigService.getPluginConfigPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, PluginConfigRespVO.class));
}
@PostMapping("/upload-file")
@Operation(summary = "上传插件文件")
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
public CommonResult<Boolean> uploadFile(@Valid PluginConfigImportReqVO reqVO) {
pluginConfigService.uploadFile(reqVO.getId(), reqVO.getFile());
return success(true);
}
@PutMapping("/update-status")
@Operation(summary = "修改插件状态")
@PreAuthorize("@ss.hasPermission('iot:plugin-config:update')")
public CommonResult<Boolean> updatePluginConfigStatus(@Valid @RequestBody PluginConfigStatusReqVO reqVO) {
pluginConfigService.updatePluginStatus(reqVO.getId(), reqVO.getStatus());
return success(true);
}
}

View File

@@ -1,19 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.config;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
@Schema(description = "管理后台 - IoT 插件上传 Request VO")
@Data
public class PluginConfigImportReqVO {
@Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
private Long id;
@Schema(description = "插件文件", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "插件文件不能为空")
private MultipartFile file;
}

View File

@@ -1,20 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.config;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.plugin.IotPluginStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - IoT 插件配置分页 Request VO")
@Data
public class PluginConfigPageReqVO extends PageParam {
@Schema(description = "插件名称", example = "http")
private String name;
@Schema(description = "状态", example = "1")
@InEnum(IotPluginStatusEnum.class)
private Integer status;
}

View File

@@ -1,54 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.config;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - IoT 插件配置 Response VO")
@Data
public class PluginConfigRespVO {
@Schema(description = "主键 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
private Long id;
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
private String pluginKey;
@Schema(description = "插件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
private String name;
@Schema(description = "描述", example = "你猜")
private String description;
@Schema(description = "部署方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer deployType;
@Schema(description = "插件包文件名", requiredMode = Schema.RequiredMode.REQUIRED)
private String fileName;
@Schema(description = "插件版本", requiredMode = Schema.RequiredMode.REQUIRED)
private String version;
@Schema(description = "插件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer type;
@Schema(description = "设备插件协议类型")
private String protocol;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer status;
@Schema(description = "插件配置项描述信息")
private String configSchema;
@Schema(description = "插件配置信息")
private String config;
@Schema(description = "插件脚本")
private String script;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -1,56 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.config;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.plugin.IotPluginStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - IoT 插件配置新增/修改 Request VO")
@Data
public class PluginConfigSaveReqVO {
// TODO @haohao新增的字段有点多每个都需要哇
// TODO @haohao一些枚举字段需要加枚举校验。例如说deployType、status、type 等
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
private Long id;
@Schema(description = "插件包标识符", requiredMode = Schema.RequiredMode.REQUIRED, example = "24627")
private String pluginKey;
@Schema(description = "插件名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
private String name;
@Schema(description = "描述", example = "你猜")
private String description;
@Schema(description = "部署方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer deployType;
@Schema(description = "插件包文件名", requiredMode = Schema.RequiredMode.REQUIRED)
private String fileName;
@Schema(description = "插件版本", requiredMode = Schema.RequiredMode.REQUIRED)
private String version;
@Schema(description = "插件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Integer type;
@Schema(description = "设备插件协议类型")
private String protocol;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
@InEnum(IotPluginStatusEnum.class)
private Integer status;
@Schema(description = "插件配置项描述信息")
private String configSchema;
@Schema(description = "插件配置信息")
private String config;
@Schema(description = "插件脚本")
private String script;
}

View File

@@ -1,19 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.config;
import pc.exam.pp.framework.common.validation.InEnum;
import pc.exam.pp.module.iot.enums.plugin.IotPluginStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - IoT 插件配置状态 Request VO")
@Data
public class PluginConfigStatusReqVO {
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11546")
private Long id;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
@InEnum(IotPluginStatusEnum.class)
private Integer status;
}

View File

@@ -1,35 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.instance;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import pc.exam.pp.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
// TODO @haohao后续需要使用下
@Schema(description = "管理后台 - IoT 插件实例分页 Request VO")
@Data
public class PluginInstancePageReqVO extends PageParam {
@Schema(description = "插件主程序编号", example = "23738")
private String mainId;
@Schema(description = "插件id", example = "26498")
private Long pluginId;
@Schema(description = "插件主程序所在ip")
private String ip;
@Schema(description = "插件主程序端口")
private Integer port;
@Schema(description = "心跳时间心路时间超过30秒需要剔除")
private Long heartbeatAt;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@@ -1,34 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.plugin.vo.instance;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
// TODO @haohao后续需要使用下
@Schema(description = "管理后台 - IoT 插件实例 Response VO")
@Data
public class PluginInstanceRespVO {
@Schema(description = "主键编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23864")
private Long id;
@Schema(description = "插件主程序id", requiredMode = Schema.RequiredMode.REQUIRED, example = "23738")
private String mainId;
@Schema(description = "插件id", requiredMode = Schema.RequiredMode.REQUIRED, example = "26498")
private Long pluginId;
@Schema(description = "插件主程序所在ip", requiredMode = Schema.RequiredMode.REQUIRED)
private String ip;
@Schema(description = "插件主程序端口", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer port;
@Schema(description = "心跳时间心路时间超过30秒需要剔除", requiredMode = Schema.RequiredMode.REQUIRED)
private Long heartbeatAt;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -1,86 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.product;
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO;
import pc.exam.pp.module.iot.controller.admin.product.vo.category.IotProductCategoryRespVO;
import pc.exam.pp.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO;
import pc.exam.pp.module.iot.dal.dataobject.product.IotProductCategoryDO;
import pc.exam.pp.module.iot.service.product.IotProductCategoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 产品分类")
@RestController
@RequestMapping("/iot/product-category")
@Validated
public class IotProductCategoryController {
@Resource
private IotProductCategoryService productCategoryService;
@PostMapping("/create")
@Operation(summary = "创建产品分类")
@PreAuthorize("@ss.hasPermission('iot:product-category:create')")
public CommonResult<Long> createProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO createReqVO) {
return success(productCategoryService.createProductCategory(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新产品分类")
@PreAuthorize("@ss.hasPermission('iot:product-category:update')")
public CommonResult<Boolean> updateProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO updateReqVO) {
productCategoryService.updateProductCategory(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除产品分类")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('iot:product-category:delete')")
public CommonResult<Boolean> deleteProductCategory(@RequestParam("id") Long id) {
productCategoryService.deleteProductCategory(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得产品分类")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:product-category:query')")
public CommonResult<IotProductCategoryRespVO> getProductCategory(@RequestParam("id") Long id) {
IotProductCategoryDO productCategory = productCategoryService.getProductCategory(id);
return success(BeanUtils.toBean(productCategory, IotProductCategoryRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得产品分类分页")
@PreAuthorize("@ss.hasPermission('iot:product-category:query')")
public CommonResult<PageResult<IotProductCategoryRespVO>> getProductCategoryPage(@Valid IotProductCategoryPageReqVO pageReqVO) {
PageResult<IotProductCategoryDO> pageResult = productCategoryService.getProductCategoryPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotProductCategoryRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得所有产品分类列表")
@PreAuthorize("@ss.hasPermission('iot:product-category:query')")
public CommonResult<List<IotProductCategoryRespVO>> getSimpleProductCategoryList() {
List<IotProductCategoryDO> list = productCategoryService.getProductCategoryListByStatus(
CommonStatusEnum.ENABLE.getStatus());
return success(convertList(list, category ->
new IotProductCategoryRespVO().setId(category.getId()).setName(category.getName())));
}
}

View File

@@ -1,132 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.product;
import pc.exam.pp.framework.apilog.core.annotation.ApiAccessLog;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.util.collection.MapUtils;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.framework.excel.core.util.ExcelUtils;
import pc.exam.pp.module.iot.controller.admin.product.vo.product.IotProductPageReqVO;
import pc.exam.pp.module.iot.controller.admin.product.vo.product.IotProductRespVO;
import pc.exam.pp.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO;
import pc.exam.pp.module.iot.dal.dataobject.product.IotProductCategoryDO;
import pc.exam.pp.module.iot.dal.dataobject.product.IotProductDO;
import pc.exam.pp.module.iot.service.product.IotProductCategoryService;
import pc.exam.pp.module.iot.service.product.IotProductService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static pc.exam.pp.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - IoT 产品")
@RestController
@RequestMapping("/iot/product")
@Validated
public class IotProductController {
@Resource
private IotProductService productService;
@Resource
private IotProductCategoryService categoryService;
@PostMapping("/create")
@Operation(summary = "创建产品")
@PreAuthorize("@ss.hasPermission('iot:product:create')")
public CommonResult<Long> createProduct(@Valid @RequestBody IotProductSaveReqVO createReqVO) {
return success(productService.createProduct(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新产品")
@PreAuthorize("@ss.hasPermission('iot:product:update')")
public CommonResult<Boolean> updateProduct(@Valid @RequestBody IotProductSaveReqVO updateReqVO) {
productService.updateProduct(updateReqVO);
return success(true);
}
@PutMapping("/update-status")
@Operation(summary = "更新产品状态")
@Parameter(name = "id", description = "编号", required = true)
@Parameter(name = "status", description = "状态", required = true)
@PreAuthorize("@ss.hasPermission('iot:product:update')")
public CommonResult<Boolean> updateProductStatus(@RequestParam("id") Long id,
@RequestParam("status") Integer status) {
productService.updateProductStatus(id, status);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除产品")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('iot:product:delete')")
public CommonResult<Boolean> deleteProduct(@RequestParam("id") Long id) {
productService.deleteProduct(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得产品")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:product:query')")
public CommonResult<IotProductRespVO> getProduct(@RequestParam("id") Long id) {
IotProductDO product = productService.getProduct(id);
// 拼接数据
IotProductCategoryDO category = categoryService.getProductCategory(product.getCategoryId());
return success(BeanUtils.toBean(product, IotProductRespVO.class, bean -> {
if (category != null) {
bean.setCategoryName(category.getName());
}
}));
}
@GetMapping("/page")
@Operation(summary = "获得产品分页")
@PreAuthorize("@ss.hasPermission('iot:product:query')")
public CommonResult<PageResult<IotProductRespVO>> getProductPage(@Valid IotProductPageReqVO pageReqVO) {
PageResult<IotProductDO> pageResult = productService.getProductPage(pageReqVO);
// 拼接数据
Map<Long, IotProductCategoryDO> categoryMap = categoryService.getProductCategoryMap(
convertList(pageResult.getList(), IotProductDO::getCategoryId));
return success(BeanUtils.toBean(pageResult, IotProductRespVO.class, bean -> {
MapUtils.findAndThen(categoryMap, bean.getCategoryId(),
category -> bean.setCategoryName(category.getName()));
}));
}
@GetMapping("/export-excel")
@Operation(summary = "导出产品 Excel")
@PreAuthorize("@ss.hasPermission('iot:product:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportProductExcel(@Valid IotProductPageReqVO exportReqVO,
HttpServletResponse response) throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
CommonResult<PageResult<IotProductRespVO>> result = getProductPage(exportReqVO);
// 导出 Excel
ExcelUtils.write(response, "产品.xls", "数据", IotProductRespVO.class,
result.getData().getList());
}
@GetMapping("/simple-list")
@Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<IotProductRespVO>> getSimpleProductList() {
List<IotProductDO> list = productService.getProductList();
return success(convertList(list, product -> // 只返回 id、name 字段
new IotProductRespVO().setId(product.getId()).setName(product.getName())
.setDeviceType(product.getDeviceType())));
}
}

View File

@@ -1,23 +0,0 @@
package pc.exam.pp.module.iot.controller.admin.product.vo.category;
import pc.exam.pp.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - IoT 产品分类分页 Request VO")
@Data
public class IotProductCategoryPageReqVO extends PageParam {
@Schema(description = "分类名字", example = "王五")
private String name;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

Some files were not shown because too many files have changed in this diff Show More