fix: 新增太阳能网控添加接口。
This commit is contained in:
@@ -209,6 +209,8 @@ device-type:
|
|||||||
water-quality-monitor: a15hA3oBPmB # TODO: 请替换为实际的水质检测仪 ProductKey
|
water-quality-monitor: a15hA3oBPmB # TODO: 请替换为实际的水质检测仪 ProductKey
|
||||||
# 2-控制一体机 ProductKey(请填写实际的 ProductKey)
|
# 2-控制一体机 ProductKey(请填写实际的 ProductKey)
|
||||||
control-integrated: a1Xj9dagTIx # TODO: 请替换为实际的控制一体机 ProductKey
|
control-integrated: a1Xj9dagTIx # TODO: 请替换为实际的控制一体机 ProductKey
|
||||||
|
# 3-太阳能网控 ProductKey
|
||||||
|
solar-controller: a1ZLJkYlSjs
|
||||||
--- # 阿里云生活物联网平台(飞燕平台)配置
|
--- # 阿里云生活物联网平台(飞燕平台)配置
|
||||||
aliyun:
|
aliyun:
|
||||||
living-iot:
|
living-iot:
|
||||||
|
|||||||
@@ -24,10 +24,15 @@ public class DeviceTypeProperties {
|
|||||||
*/
|
*/
|
||||||
private String controlIntegrated;
|
private String controlIntegrated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 太阳能网控 ProductKey
|
||||||
|
*/
|
||||||
|
private String solarController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 ProductKey 判断设备类型
|
* 根据 ProductKey 判断设备类型
|
||||||
* @param productKey ProductKey
|
* @param productKey ProductKey
|
||||||
* @return 设备类型: 1-水质检测仪, 2-控制一体机, null-未知类型
|
* @return 设备类型: 1-水质检测仪, 2-控制一体机, 3-太阳能网控, null-未知类型
|
||||||
*/
|
*/
|
||||||
public Integer getDeviceTypeByProductKey(String productKey) {
|
public Integer getDeviceTypeByProductKey(String productKey) {
|
||||||
if (productKey == null) {
|
if (productKey == null) {
|
||||||
@@ -37,13 +42,15 @@ public class DeviceTypeProperties {
|
|||||||
return 1;
|
return 1;
|
||||||
} else if (productKey.equals(controlIntegrated)) {
|
} else if (productKey.equals(controlIntegrated)) {
|
||||||
return 2;
|
return 2;
|
||||||
|
} else if (productKey.equals(solarController)) {
|
||||||
|
return 3;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据设备类型获取 ProductKey
|
* 根据设备类型获取 ProductKey
|
||||||
* @param deviceType 1-水质检测仪, 2-控制一体机
|
* @param deviceType 1-水质检测仪, 2-控制一体机, 3-太阳能网控
|
||||||
* @return ProductKey
|
* @return ProductKey
|
||||||
*/
|
*/
|
||||||
public String getProductKeyByType(Integer deviceType) {
|
public String getProductKeyByType(Integer deviceType) {
|
||||||
@@ -55,6 +62,8 @@ public class DeviceTypeProperties {
|
|||||||
return waterQualityMonitor;
|
return waterQualityMonitor;
|
||||||
case 2:
|
case 2:
|
||||||
return controlIntegrated;
|
return controlIntegrated;
|
||||||
|
case 3:
|
||||||
|
return solarController;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ public class IotController extends BaseController {
|
|||||||
@Operation(summary = "查询设备当前状态(从物联网平台)")
|
@Operation(summary = "查询设备当前状态(从物联网平台)")
|
||||||
@GetMapping("/device/status")
|
@GetMapping("/device/status")
|
||||||
public R<Integer> queryDeviceStatus(
|
public R<Integer> queryDeviceStatus(
|
||||||
@Parameter(description = "设备类型(1-水质检测仪, 2-控制一体机)") @RequestParam Integer devicetype,
|
@Parameter(description = "设备类型(1-水质检测仪, 2-控制一体机, 3-太阳能网控)") @RequestParam Integer devicetype,
|
||||||
@Parameter(description = "设备编号/设备名称") @RequestParam String serialnum) {
|
@Parameter(description = "设备编号/设备名称") @RequestParam String serialnum) {
|
||||||
try {
|
try {
|
||||||
if (iotDeviceService == null) {
|
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 = "设备校准")
|
@Operation(summary = "设备校准")
|
||||||
@PostMapping("/device/calibrate")
|
@PostMapping("/device/calibrate")
|
||||||
public R<Void> setCalibrate(@RequestBody DeviceCalibrateBo request) {
|
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