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())
|
||||
);
|
||||
|
||||
// 从列表中移除要删除的定时控制(删除场景直接移出列表,回查时 targetIdx < 0 直接返回成功)
|
||||
allTimingCtrls.removeIf(tc -> tc.getId().equals(request.getId()));
|
||||
// 删除场景:保持槽位数组长度不变,将目标项的 isOpen 置为 0(isValid=0)
|
||||
// 不能直接移除,否则设备端槽位会错位,被删项数据残留
|
||||
allTimingCtrls.forEach(tc -> {
|
||||
if (tc.getId().equals(request.getId())) {
|
||||
tc.setIsOpen(0L);
|
||||
}
|
||||
});
|
||||
|
||||
// 调用设置属性方法,将更新后的定时控制列表同步到设备
|
||||
// 调用设置属性方法,将完整槽位列表(含已置无效的目标项)同步到设备
|
||||
boolean success = setPropertyTimeCtrl(deviceSwitch, device, allTimingCtrls, request.getId());
|
||||
if (!success) {
|
||||
return R.fail("设置定时控制失败");
|
||||
|
||||
Reference in New Issue
Block a user