fix: 新增太阳能网控添加接口。
This commit is contained in:
@@ -209,6 +209,8 @@ device-type:
|
||||
water-quality-monitor: a15hA3oBPmB # TODO: 请替换为实际的水质检测仪 ProductKey
|
||||
# 2-控制一体机 ProductKey(请填写实际的 ProductKey)
|
||||
control-integrated: a1Xj9dagTIx # TODO: 请替换为实际的控制一体机 ProductKey
|
||||
# 3-太阳能网控 ProductKey
|
||||
solar-controller: a1ZLJkYlSjs
|
||||
--- # 阿里云生活物联网平台(飞燕平台)配置
|
||||
aliyun:
|
||||
living-iot:
|
||||
|
||||
@@ -24,10 +24,15 @@ public class DeviceTypeProperties {
|
||||
*/
|
||||
private String controlIntegrated;
|
||||
|
||||
/**
|
||||
* 太阳能网控 ProductKey
|
||||
*/
|
||||
private String solarController;
|
||||
|
||||
/**
|
||||
* 根据 ProductKey 判断设备类型
|
||||
* @param productKey ProductKey
|
||||
* @return 设备类型: 1-水质检测仪, 2-控制一体机, null-未知类型
|
||||
* @return 设备类型: 1-水质检测仪, 2-控制一体机, 3-太阳能网控, null-未知类型
|
||||
*/
|
||||
public Integer getDeviceTypeByProductKey(String productKey) {
|
||||
if (productKey == null) {
|
||||
@@ -37,13 +42,15 @@ public class DeviceTypeProperties {
|
||||
return 1;
|
||||
} else if (productKey.equals(controlIntegrated)) {
|
||||
return 2;
|
||||
} else if (productKey.equals(solarController)) {
|
||||
return 3;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据设备类型获取 ProductKey
|
||||
* @param deviceType 1-水质检测仪, 2-控制一体机
|
||||
* @param deviceType 1-水质检测仪, 2-控制一体机, 3-太阳能网控
|
||||
* @return ProductKey
|
||||
*/
|
||||
public String getProductKeyByType(Integer deviceType) {
|
||||
@@ -55,6 +62,8 @@ public class DeviceTypeProperties {
|
||||
return waterQualityMonitor;
|
||||
case 2:
|
||||
return controlIntegrated;
|
||||
case 3:
|
||||
return solarController;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ public class IotController extends BaseController {
|
||||
@Operation(summary = "查询设备当前状态(从物联网平台)")
|
||||
@GetMapping("/device/status")
|
||||
public R<Integer> queryDeviceStatus(
|
||||
@Parameter(description = "设备类型(1-水质检测仪, 2-控制一体机)") @RequestParam Integer devicetype,
|
||||
@Parameter(description = "设备类型(1-水质检测仪, 2-控制一体机, 3-太阳能网控)") @RequestParam Integer devicetype,
|
||||
@Parameter(description = "设备编号/设备名称") @RequestParam String serialnum) {
|
||||
try {
|
||||
if (iotDeviceService == null) {
|
||||
@@ -1540,6 +1540,201 @@ public class IotController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "添加设备(太阳能网控)")
|
||||
@PostMapping("/device/add_device_solar_detector")
|
||||
public R<Void> addDeviceSolarController(@RequestBody com.intc.iot.domain.bo.AddDeviceSolarControllerBo bo, @RequestParam Long rootUserId) {
|
||||
try {
|
||||
if (iotDeviceService == null) {
|
||||
return R.fail("飞燕平台配置未启用");
|
||||
}
|
||||
if (deviceMapper == null) {
|
||||
return R.fail("设备数据库服务未启用");
|
||||
}
|
||||
|
||||
// 获取用户ID(从 URL 查询参数 rootUserId 获取)
|
||||
if (rootUserId == null) {
|
||||
return R.fail("根用户ID不能为空");
|
||||
}
|
||||
|
||||
// 验证塘口是否存在且属于当前用户
|
||||
if (bo.getPondId() != null && bo.getPondId() > 0 && pondMapper != null) {
|
||||
long count = pondMapper.selectCount(
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Pond>()
|
||||
.eq(Pond::getUserId, rootUserId)
|
||||
.eq(Pond::getId, bo.getPondId())
|
||||
);
|
||||
if (count == 0) {
|
||||
return R.fail("塘口不存在或无权限访问");
|
||||
}
|
||||
}
|
||||
|
||||
// 检查设备是否已被绑定
|
||||
Device existDevice = deviceMapper.selectOne(
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getDeviceType, 3) // 3-太阳能网控
|
||||
.eq(Device::getSerialNum, bo.getSerialNum())
|
||||
);
|
||||
if (existDevice != null && existDevice.getUserId() != null) {
|
||||
return R.fail("该设备号已被绑定");
|
||||
}
|
||||
|
||||
// 获取太阳能网控的 ProductKey
|
||||
String productKey = deviceTypeProperties.getSolarController();
|
||||
if (productKey == null || productKey.isEmpty()) {
|
||||
return R.fail("未配置太阳能网控的 ProductKey");
|
||||
}
|
||||
|
||||
// 查询设备基础信息
|
||||
Map<String, Object> deviceInfo = iotDeviceService.findDeviceByProductKeyAndName(productKey, bo.getSerialNum());
|
||||
if (deviceInfo == null || !Boolean.TRUE.equals(deviceInfo.get("success"))) {
|
||||
return R.fail("设备不存在");
|
||||
}
|
||||
|
||||
// 提取设备数据
|
||||
Map<String, Object> data = (Map<String, Object>) deviceInfo.get("data");
|
||||
if (data == null || !data.containsKey("deviceList")) {
|
||||
return R.fail("设备信息格式异常");
|
||||
}
|
||||
|
||||
java.util.List<?> deviceList = (java.util.List<?>) data.get("deviceList");
|
||||
if (deviceList == null || deviceList.isEmpty()) {
|
||||
return R.fail("设备不存在");
|
||||
}
|
||||
|
||||
Object deviceObj = deviceList.get(0);
|
||||
String iotId = null;
|
||||
String status = null;
|
||||
|
||||
// 提取 iotId 和 status
|
||||
if (deviceObj instanceof Map) {
|
||||
Map<?, ?> deviceMap = (Map<?, ?>) deviceObj;
|
||||
iotId = (String) deviceMap.get("iotId");
|
||||
Object statusObj = deviceMap.get("status");
|
||||
status = statusObj != null ? statusObj.toString() : null;
|
||||
} else {
|
||||
try {
|
||||
iotId = (String) deviceObj.getClass().getMethod("getIotId").invoke(deviceObj);
|
||||
Object statusObj = deviceObj.getClass().getMethod("getStatus").invoke(deviceObj);
|
||||
status = statusObj != null ? statusObj.toString() : null;
|
||||
} catch (Exception ex) {
|
||||
log.error("无法从设备对象中获取信息: {}", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (iotId == null || iotId.isEmpty()) {
|
||||
return R.fail("设备 iotId 为空");
|
||||
}
|
||||
|
||||
// 检查设备状态
|
||||
if (status != null) {
|
||||
if ("UNACTIVE".equalsIgnoreCase(status)) {
|
||||
return R.fail("设备未激活");
|
||||
}
|
||||
if ("DISABLE".equalsIgnoreCase(status)) {
|
||||
return R.fail("设备禁用");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取设备属性
|
||||
Map<String, Object> deviceProperties = iotDeviceService.queryDeviceProperties(iotId);
|
||||
|
||||
// 计算设备数量,用于生成设备名称
|
||||
long deviceCount = deviceMapper.selectCount(
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Device>()
|
||||
.eq(Device::getUserId, rootUserId)
|
||||
.eq(Device::getDeviceType, 3)
|
||||
);
|
||||
|
||||
// 创建或更新设备信息
|
||||
Date now = new Date();
|
||||
boolean isNew = (existDevice == null);
|
||||
Device device = isNew ? new Device() : existDevice;
|
||||
|
||||
if (isNew) {
|
||||
device.setIotId(iotId);
|
||||
device.setSerialNum(bo.getSerialNum());
|
||||
device.setDeviceType(3); // 3-太阳能网控
|
||||
device.setDeadTime(new Date(now.getTime() + 365L * 24 * 60 * 60 * 1000)); // 一年后到期
|
||||
}
|
||||
|
||||
// 设置基本信息
|
||||
device.setUserId(rootUserId);
|
||||
device.setDeviceName("太阳能网控" + (deviceCount + 1));
|
||||
device.setBindTime(now);
|
||||
device.setPondId(bo.getPondId() != null && bo.getPondId() > 0 ? bo.getPondId() : null);
|
||||
device.setBatteryWarnCallOpen(bo.getBatteryWarnCallOpen());
|
||||
device.setBatteryWarnCallNoDis(bo.getBatteryWarnCallNoDis());
|
||||
device.setBatteryWarnLower(bo.getBatteryWarnLower());
|
||||
|
||||
// 解析并设置设备属性(ICCID 等)
|
||||
if (deviceProperties != null && Boolean.TRUE.equals(deviceProperties.get("success"))) {
|
||||
Object propData = deviceProperties.get("data");
|
||||
if (propData != null) {
|
||||
try {
|
||||
java.lang.reflect.Method getListMethod = propData.getClass().getMethod("getList");
|
||||
Object listObj = getListMethod.invoke(propData);
|
||||
if (listObj instanceof java.util.List) {
|
||||
java.util.List<?> propList = (java.util.List<?>) listObj;
|
||||
for (Object item : propList) {
|
||||
if (item != null) {
|
||||
try {
|
||||
java.lang.reflect.Method getIdentifierMethod = item.getClass().getMethod("getIdentifier");
|
||||
java.lang.reflect.Method getValueMethod = item.getClass().getMethod("getValue");
|
||||
String attribute = (String) getIdentifierMethod.invoke(item);
|
||||
Object value = getValueMethod.invoke(item);
|
||||
if (attribute != null && value != null) {
|
||||
switch (attribute) {
|
||||
case "ICCID": // 物联网卡号
|
||||
device.setIccId(value.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("无法从 SDK 对象中获取属性: {}", ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("无法从 SDK 对象中获取属性列表: {}", ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化警告码
|
||||
int warnCode = 0;
|
||||
|
||||
// 如果设备离线,添加离线警告
|
||||
if (status != null && "OFFLINE".equalsIgnoreCase(status)) {
|
||||
warnCode |= 0x0080; // 设备离线
|
||||
}
|
||||
|
||||
device.setWarnCode(warnCode);
|
||||
|
||||
// 验证 ICCID 是否存在
|
||||
if (device.getIccId() == null || device.getIccId().isEmpty()) {
|
||||
return R.fail("设备缺少物联网卡号(ICCID)");
|
||||
}
|
||||
|
||||
// 添加绑定记录
|
||||
addNewDeviceBindRecord(device, true);
|
||||
|
||||
// 保存到数据库
|
||||
if (isNew) {
|
||||
deviceMapper.insert(device);
|
||||
log.info("新设备添加成功: userId={}, iotId={}, serialNum={}", rootUserId, iotId, bo.getSerialNum());
|
||||
} else {
|
||||
deviceMapper.updateById(device);
|
||||
log.info("设备更新成功: userId={}, iotId={}, serialNum={}", rootUserId, iotId, bo.getSerialNum());
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
} catch (Exception e) {
|
||||
log.error("添加太阳能网控失败: {}", e.getMessage(), e);
|
||||
return R.fail("添加太阳能网控失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "设备校准")
|
||||
@PostMapping("/device/calibrate")
|
||||
public R<Void> setCalibrate(@RequestBody DeviceCalibrateBo request) {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.intc.iot.domain.bo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 添加太阳能网控业务对象
|
||||
*
|
||||
* @author intc
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "添加太阳能网控请求对象")
|
||||
public class AddDeviceSolarControllerBo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 设备编号/序列号
|
||||
*/
|
||||
@Schema(description = "设备编号/序列号")
|
||||
@NotBlank(message = "设备编号不能为空")
|
||||
private String serialNum;
|
||||
|
||||
/**
|
||||
* 塘口ID
|
||||
*/
|
||||
@Schema(description = "塘口ID")
|
||||
private Long pondId;
|
||||
|
||||
/**
|
||||
* 电量电话告警开关(0-关闭, 1-开启)
|
||||
*/
|
||||
@Schema(description = "电量电话告警开关(0-关闭, 1-开启)")
|
||||
@NotNull(message = "电量电话告警开关不能为空")
|
||||
private Long batteryWarnCallOpen;
|
||||
|
||||
/**
|
||||
* 电量告警免打扰(0-关闭, 1-开启)
|
||||
*/
|
||||
@Schema(description = "电量告警免打扰(0-关闭, 1-开启)")
|
||||
@NotNull(message = "电量告警免打扰不能为空")
|
||||
private Long batteryWarnCallNoDis;
|
||||
|
||||
/**
|
||||
* 电量电话告警下限(百分比)
|
||||
*/
|
||||
@Schema(description = "电量电话告警下限(百分比)")
|
||||
@NotNull(message = "电量电话告警下限不能为空")
|
||||
private Long batteryWarnLower;
|
||||
}
|
||||
Reference in New Issue
Block a user