2026-06-24 f4bd1f3c89d906131495a0aca5aaf82966378510
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package cn.iocoder.yudao.module.iot.service.rule.scene.action;
 
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleActionTypeEnum;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
 
import java.util.List;
 
/**
 * IoT 设备属性设置的 {@link IotSceneRuleAction} 实现类
 *
 * @author 芋道源码
 */
@Component
@Slf4j
public class IotDevicePropertySetSceneRuleAction implements IotSceneRuleAction {
 
    @Resource
    private IotDeviceService deviceService;
    @Resource
    private IotDeviceMessageService deviceMessageService;
 
    @Override
    public void execute(IotDeviceMessage message,
                        IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig) {
        // 1. 参数校验
        if (actionConfig.getDeviceId() == null) {
            log.error("[execute][规则场景({}) 动作配置({}) 设备编号不能为空]", rule.getId(), actionConfig);
            return;
        }
        if (StrUtil.isEmpty(actionConfig.getIdentifier())) {
            log.error("[execute][规则场景({}) 动作配置({}) 属性标识符不能为空]", rule.getId(), actionConfig);
            return;
        }
 
        // 2. 判断是否为全部设备
        if (IotDeviceDO.DEVICE_ID_ALL.equals(actionConfig.getDeviceId())) {
            executeForAllDevices(message, rule, actionConfig);
        } else {
            executeForSingleDevice(message, rule, actionConfig);
        }
    }
 
    /**
     * 为单个设备执行属性设置
     */
    private void executeForSingleDevice(IotDeviceMessage message,
                                        IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig) {
        // 1. 获取设备信息
        IotDeviceDO device = deviceService.getDeviceFromCache(actionConfig.getDeviceId());
        if (device == null) {
            log.error("[executeForSingleDevice][规则场景({}) 动作配置({}) 对应的设备({}) 不存在]",
                    rule.getId(), actionConfig, actionConfig.getDeviceId());
            return;
        }
 
        // 2. 执行属性设置
        executePropertySetForDevice(rule, actionConfig, device);
    }
 
    /**
     * 为产品下的所有设备执行属性设置
     */
    private void executeForAllDevices(IotDeviceMessage message,
                                      IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig) {
        // 1. 参数校验
        if (actionConfig.getProductId() == null) {
            log.error("[executeForAllDevices][规则场景({}) 动作配置({}) 产品编号不能为空]", rule.getId(), actionConfig);
            return;
        }
 
        // 2. 获取产品下的所有设备
        List<IotDeviceDO> devices = deviceService.getDeviceListByProductId(actionConfig.getProductId());
        if (CollUtil.isEmpty(devices)) {
            log.warn("[executeForAllDevices][规则场景({}) 动作配置({}) 产品({}) 下没有设备]",
                    rule.getId(), actionConfig, actionConfig.getProductId());
            return;
        }
 
        // 3. 遍历所有设备执行属性设置
        for (IotDeviceDO device : devices) {
            executePropertySetForDevice(rule, actionConfig, device);
        }
    }
 
    /**
     * 为指定设备执行属性设置
     */
    private void executePropertySetForDevice(IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig, IotDeviceDO device) {
        // 1. 构建属性设置消息
        IotDeviceMessage downstreamMessage = buildPropertySetMessage(actionConfig, device);
        if (downstreamMessage == null) {
            log.error("[executePropertySetForDevice][规则场景({}) 动作配置({}) 设备({}) 构建属性设置消息失败]",
                    rule.getId(), actionConfig, device.getId());
            return;
        }
 
        // 2. 发送设备消息
        try {
            IotDeviceMessage result = deviceMessageService.sendDeviceMessage(downstreamMessage, device);
            log.info("[executePropertySetForDevice][规则场景({}) 动作配置({}) 设备({}) 属性设置消息({}) 发送成功]",
                    rule.getId(), actionConfig, device.getId(), result.getId());
        } catch (Exception e) {
            log.error("[executePropertySetForDevice][规则场景({}) 动作配置({}) 设备({}) 属性设置消息发送失败]",
                    rule.getId(), actionConfig, device.getId(), e);
        }
    }
 
    /**
     * 构建属性设置消息
     *
     * @param actionConfig 动作配置
     * @param device       设备信息
     * @return 设备消息
     */
    private IotDeviceMessage buildPropertySetMessage(IotSceneRuleDO.Action actionConfig, IotDeviceDO device) {
        try {
            // 属性设置参数格式: {"properties": {"identifier": value}}
            Object params = MapUtil.of("properties", MapUtil.of(actionConfig.getIdentifier(), actionConfig.getParams()));
            return IotDeviceMessage.requestOf(IotDeviceMessageMethodEnum.PROPERTY_SET.getMethod(), params);
        } catch (Exception e) {
            log.error("[buildPropertySetMessage][构建属性设置消息异常]", e);
            return null;
        }
    }
 
    @Override
    public IotSceneRuleActionTypeEnum getType() {
        return IotSceneRuleActionTypeEnum.DEVICE_PROPERTY_SET;
    }
 
}