fix: 控制器定时控制删除时,实际未删除。
This commit is contained in:
@@ -2634,6 +2634,77 @@ public class IotController extends BaseController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强制同步开关定时控制到设备(运维补救接口)
|
||||||
|
* 用于修复历史上因错误删除逻辑导致设备端槽位残留的问题:
|
||||||
|
* 将数据库中该开关当前全量定时列表推送给设备,设备端多余的历史槽位将被覆盖为 isValid=0
|
||||||
|
*
|
||||||
|
* @param switchId 开关ID
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
@Operation(summary = "强制同步定时控制到设备")
|
||||||
|
@PostMapping("/timingCtrl/syncToDevice")
|
||||||
|
public R<Void> syncTimingCtrlToDevice(@RequestParam Long switchId) {
|
||||||
|
try {
|
||||||
|
// 查询开关信息
|
||||||
|
DeviceSwitch deviceSwitch = deviceSwitchMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<DeviceSwitch>()
|
||||||
|
.eq(DeviceSwitch::getId, switchId)
|
||||||
|
.select(DeviceSwitch::getId,
|
||||||
|
DeviceSwitch::getDeviceId,
|
||||||
|
DeviceSwitch::getIndex,
|
||||||
|
DeviceSwitch::getSwitchName)
|
||||||
|
);
|
||||||
|
if (deviceSwitch == null) {
|
||||||
|
return R.fail("开关不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询设备信息
|
||||||
|
Device device = deviceMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Device>()
|
||||||
|
.eq(Device::getId, deviceSwitch.getDeviceId())
|
||||||
|
.select(Device::getId, Device::getUserId, Device::getDeviceName,
|
||||||
|
Device::getIotId, Device::getSerialNum, Device::getWarnCode, Device::getDeadTime)
|
||||||
|
);
|
||||||
|
if (device == null) {
|
||||||
|
return R.fail("设备不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询该开关在数据库中的全量定时控制
|
||||||
|
java.util.List<TimingCtrl> allTimingCtrls = timingCtrlMapper.selectList(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<TimingCtrl>()
|
||||||
|
.eq(TimingCtrl::getSwitchId, switchId)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 直接构建属性并推送到设备,传 timeCtrlId=-1(无匹配项,跳过特殊时间重算)
|
||||||
|
// 数据库中不存在的历史槽位不会出现在 listTimingCtrl 中,设备收到后会用 isValid=0 的空槽覆盖
|
||||||
|
Map<String, Object> properties = new java.util.HashMap<>();
|
||||||
|
java.util.List<Object> listTimingCtrl = new java.util.ArrayList<>();
|
||||||
|
for (TimingCtrl tc : allTimingCtrls) {
|
||||||
|
Map<String, Object> timeCtrl = new java.util.HashMap<>();
|
||||||
|
timeCtrl.put("timerMode", tc.getLoopType() != null ? tc.getLoopType() - 1 : 0);
|
||||||
|
timeCtrl.put("isValid", tc.getIsOpen() != null && tc.getIsOpen() == 1 ? 1 : 0);
|
||||||
|
timeCtrl.put("onTime", String.valueOf(tc.getOpenTime().getTime() / 1000));
|
||||||
|
timeCtrl.put("offTime", String.valueOf(tc.getCloseTime().getTime() / 1000));
|
||||||
|
listTimingCtrl.add(timeCtrl);
|
||||||
|
}
|
||||||
|
String propertyKey = IOTPropertyName.LOCAL_TIMER_SWITCH + deviceSwitch.getIndex();
|
||||||
|
properties.put(propertyKey, listTimingCtrl);
|
||||||
|
|
||||||
|
boolean setOk = iotCloudService.setProperty(device.getIotId(), properties, false, 0);
|
||||||
|
if (!setOk) {
|
||||||
|
return R.fail("推送设备失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("[SyncTimingCtrl] 强制同步定时控制完成: switchId={}, device={}, 共{}条",
|
||||||
|
switchId, device.getDeviceName(), listTimingCtrl.size());
|
||||||
|
return R.ok();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("强制同步定时控制失败: {}", e.getMessage(), e);
|
||||||
|
return R.fail("同步失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置定时控制开关
|
* 设置定时控制开关
|
||||||
*
|
*
|
||||||
@@ -3043,10 +3114,15 @@ public class IotController extends BaseController {
|
|||||||
.eq(TimingCtrl::getSwitchId, dbTimeCtrl.getSwitchId())
|
.eq(TimingCtrl::getSwitchId, dbTimeCtrl.getSwitchId())
|
||||||
);
|
);
|
||||||
|
|
||||||
// 从列表中移除要删除的定时控制(删除场景直接移出列表,回查时 targetIdx < 0 直接返回成功)
|
// 删除场景:保持槽位数组长度不变,将目标项的 isOpen 置为 0(isValid=0)
|
||||||
allTimingCtrls.removeIf(tc -> tc.getId().equals(request.getId()));
|
// 不能直接移除,否则设备端槽位会错位,被删项数据残留
|
||||||
|
allTimingCtrls.forEach(tc -> {
|
||||||
|
if (tc.getId().equals(request.getId())) {
|
||||||
|
tc.setIsOpen(0L);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 调用设置属性方法,将更新后的定时控制列表同步到设备
|
// 调用设置属性方法,将完整槽位列表(含已置无效的目标项)同步到设备
|
||||||
boolean success = setPropertyTimeCtrl(deviceSwitch, device, allTimingCtrls, request.getId());
|
boolean success = setPropertyTimeCtrl(deviceSwitch, device, allTimingCtrls, request.getId());
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return R.fail("设置定时控制失败");
|
return R.fail("设置定时控制失败");
|
||||||
|
|||||||
Reference in New Issue
Block a user