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
143
144
145
146
147
148
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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
/**
 * IoT 设备服务调用的 {@link IotSceneRuleAction} 实现类
 *
 * @author HUIHUI
 */
@Component
@Slf4j
public class IotDeviceServiceInvokeSceneRuleAction 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. 执行服务调用
        executeServiceInvokeForDevice(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) {
            executeServiceInvokeForDevice(rule, actionConfig, device);
        }
    }
 
    /**
     * 为指定设备执行服务调用
     */
    private void executeServiceInvokeForDevice(IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig, IotDeviceDO device) {
        // 1. 构建服务调用消息
        IotDeviceMessage downstreamMessage = buildServiceInvokeMessage(actionConfig, device);
        if (downstreamMessage == null) {
            log.error("[executeServiceInvokeForDevice][规则场景({}) 动作配置({}) 设备({}) 构建服务调用消息失败]",
                    rule.getId(), actionConfig, device.getId());
            return;
        }
 
        // 2. 发送设备消息
        try {
            IotDeviceMessage result = deviceMessageService.sendDeviceMessage(downstreamMessage, device);
            log.info("[executeServiceInvokeForDevice][规则场景({}) 动作配置({}) 设备({}) 服务调用消息({}) 发送成功]",
                    rule.getId(), actionConfig, device.getId(), result.getId());
        } catch (Exception e) {
            log.error("[executeServiceInvokeForDevice][规则场景({}) 动作配置({}) 设备({}) 服务调用消息发送失败]",
                    rule.getId(), actionConfig, device.getId(), e);
        }
    }
 
    /**
     * 构建服务调用消息
     *
     * @param actionConfig 动作配置
     * @param device       设备信息
     * @return 设备消息
     */
    private IotDeviceMessage buildServiceInvokeMessage(IotSceneRuleDO.Action actionConfig, IotDeviceDO device) {
        try {
            // 服务调用参数格式: {"identifier": "serviceId", "params": {...}}
            Object params = MapUtil.builder()
                    .put("identifier", actionConfig.getIdentifier())
                    .put("params", actionConfig.getParams() != null ? actionConfig.getParams() : Collections.emptyMap())
                    .build();
            return IotDeviceMessage.requestOf(IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod(), params);
        } catch (Exception e) {
            log.error("[buildServiceInvokeMessage][构建服务调用消息异常]", e);
            return null;
        }
    }
 
    @Override
    public IotSceneRuleActionTypeEnum getType() {
        return IotSceneRuleActionTypeEnum.DEVICE_SERVICE_INVOKE;
    }
 
}