Commit a71d5b7ee4627e843ad0c8687c69b037468c8e93

Authored by xp.Huang
2 parents 0919bfe5 f1b33f6e

Merge branch '20220317' into 'master'

refactor: 动作之设备输出

See merge request huang/thingsboard3.3.2!66
Showing 17 changed files with 424 additions and 395 deletions
@@ -28,17 +28,18 @@ import java.net.InetAddress; @@ -28,17 +28,18 @@ import java.net.InetAddress;
28 @RequiredArgsConstructor 28 @RequiredArgsConstructor
29 @Slf4j 29 @Slf4j
30 @Api(tags = {"告警通知"}) 30 @Api(tags = {"告警通知"})
  31 +@Deprecated
31 public class YtAlarmNoticeController { 32 public class YtAlarmNoticeController {
32 33
33 private final YtNoticeService service; 34 private final YtNoticeService service;
34 35
35 - @PostMapping("/alert") 36 + @PostMapping("/alert/{alarmProfileId}")
36 public void alertNotice(@RequestParam(value = "token", required = true) String token, 37 public void alertNotice(@RequestParam(value = "token", required = true) String token,
37 - @RequestBody AlarmInfoDTO alarmInfo) { 38 + @PathVariable("alarmProfileId") String alarmProfileId, @RequestBody AlarmInfoDTO alarmInfo) {
38 Assert.notNull(token, "token cannot be null"); 39 Assert.notNull(token, "token cannot be null");
39 Assert.notNull(alarmInfo, "alarm info cannot be null"); 40 Assert.notNull(alarmInfo, "alarm info cannot be null");
40 if (parseTokenClaims(token, alarmInfo)) { 41 if (parseTokenClaims(token, alarmInfo)) {
41 - service.alert(alarmInfo); 42 + service.alert(alarmProfileId, alarmInfo);
42 } 43 }
43 } 44 }
44 45
@@ -47,221 +47,220 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant. @@ -47,221 +47,220 @@ import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.
47 @RequestMapping("api/yt/convert") 47 @RequestMapping("api/yt/convert")
48 @Api(tags = {"数据流转控制器"}) 48 @Api(tags = {"数据流转控制器"})
49 public class YtConvertDataToController extends BaseController { 49 public class YtConvertDataToController extends BaseController {
50 - private final YtRuleChainService ytRuleChainService; 50 + private final YtRuleChainService ytRuleChainService;
51 51
52 - @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")  
53 - private boolean debugPerTenantEnabled; 52 + @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
  53 + private boolean debugPerTenantEnabled;
54 54
55 - @Autowired(required = false)  
56 - private ActorSystemContext actorContext; 55 + @Autowired(required = false)
  56 + private ActorSystemContext actorContext;
57 57
58 - private final ConvertConfigService convertConfigService;  
59 - private final SceneLinkageService sceneLinkageService; 58 + private final ConvertConfigService convertConfigService;
  59 + private final SceneLinkageService sceneLinkageService;
60 60
61 - @GetMapping(params = {PAGE_SIZE, PAGE})  
62 - @ApiOperation("分页查询")  
63 - public YtPageData<ConvertConfigDTO> pageMessageConfig(  
64 - @RequestParam(PAGE_SIZE) int pageSize,  
65 - @RequestParam(PAGE) int page,  
66 - @ApiParam(value = "0:转换脚本 1:数据流转") @RequestParam(value = "nodeType") Integer nodeType,  
67 - @RequestParam(value = "name", required = false) String name,  
68 - @RequestParam(value = "status", required = false) Integer status,  
69 - @RequestParam(value = ORDER_FILED, required = false) String orderBy,  
70 - @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType)  
71 - throws ThingsboardException { 61 + @GetMapping(params = {PAGE_SIZE, PAGE})
  62 + @ApiOperation("分页查询")
  63 + public YtPageData<ConvertConfigDTO> pageMessageConfig(
  64 + @RequestParam(PAGE_SIZE) int pageSize,
  65 + @RequestParam(PAGE) int page,
  66 + @ApiParam(value = "0:转换脚本 1:数据流转") @RequestParam(value = "nodeType") Integer nodeType,
  67 + @RequestParam(value = "name", required = false) String name,
  68 + @RequestParam(value = "status", required = false) Integer status,
  69 + @RequestParam(value = ORDER_FILED, required = false) String orderBy,
  70 + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType)
  71 + throws ThingsboardException {
72 72
73 - HashMap<String, Object> queryMap = new HashMap<>();  
74 - queryMap.put(PAGE_SIZE, pageSize);  
75 - queryMap.put(PAGE, page);  
76 - queryMap.put(ORDER_FILED, orderBy);  
77 - queryMap.put("nodeType", nodeType);  
78 - queryMap.put("name", name);  
79 - queryMap.put("status", status);  
80 - if (orderType != null) {  
81 - queryMap.put(ORDER_TYPE, orderType.name()); 73 + HashMap<String, Object> queryMap = new HashMap<>();
  74 + queryMap.put(PAGE_SIZE, pageSize);
  75 + queryMap.put(PAGE, page);
  76 + queryMap.put(ORDER_FILED, orderBy);
  77 + queryMap.put("nodeType", nodeType);
  78 + queryMap.put("name", name);
  79 + queryMap.put("status", status);
  80 + if (orderType != null) {
  81 + queryMap.put(ORDER_TYPE, orderType.name());
  82 + }
  83 + return convertConfigService.page(getCurrentUser().getCurrentTenantId(), queryMap);
82 } 84 }
83 - return convertConfigService.page(getCurrentUser().getCurrentTenantId(), queryMap);  
84 - }  
85 -  
86 - @PostMapping("config")  
87 - @ApiOperation("添加或修改转换配置")  
88 - public ResponseEntity<ConvertConfigDTO> createOrUpdateConvertData(  
89 - @Validated @RequestBody ConvertConfigDTO convertConfigDTO) throws ThingsboardException {  
90 - convertConfigDTO.setTenantId(getCurrentUser().getCurrentTenantId());  
91 - convertConfigDTO.setNodeType(FastIotConstants.CONVERT_DATA);  
92 - return ResponseEntity.ok(convertConfigService.createOrUpdate(convertConfigDTO));  
93 - }  
94 85
95 - @PostMapping("js")  
96 - @ApiOperation("添加或修改转换脚本")  
97 - public ResponseEntity<ConvertConfigDTO> createOrUpdateConvertJS(  
98 - @Validated @RequestBody ConvertConfigDTO convertConfigDTO) throws ThingsboardException {  
99 - convertConfigDTO.setTenantId(getCurrentUser().getCurrentTenantId());  
100 - convertConfigDTO.setNodeType(FastIotConstants.JAVA_SCRIPT);  
101 - return ResponseEntity.ok(convertConfigService.createOrUpdate(convertConfigDTO));  
102 - }  
103 -  
104 - @PostMapping("/check/config")  
105 - @ApiOperation("检查配置名称是否存在")  
106 - public ResponseEntity<Boolean> checkConvertConfig(@RequestBody Map<String, String> checkParam)  
107 - throws ThingsboardException {  
108 - String type = checkParam.get("type");  
109 - String name = checkParam.get("name");  
110 - if (StringUtils.isEmpty(type) || StringUtils.isEmpty(name)) {  
111 - throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); 86 + @PostMapping("config")
  87 + @ApiOperation("添加或修改转换配置")
  88 + public ResponseEntity<ConvertConfigDTO> createOrUpdateConvertData(
  89 + @Validated @RequestBody ConvertConfigDTO convertConfigDTO) throws ThingsboardException {
  90 + convertConfigDTO.setTenantId(getCurrentUser().getCurrentTenantId());
  91 + convertConfigDTO.setNodeType(FastIotConstants.CONVERT_DATA);
  92 + return ResponseEntity.ok(convertConfigService.createOrUpdate(convertConfigDTO));
112 } 93 }
113 - return ResponseEntity.ok(  
114 - convertConfigService.checkConvertConfigNameExist(  
115 - null, name, type, getCurrentUser().getCurrentTenantId()));  
116 - }  
117 94
118 - @DeleteMapping("config")  
119 - @ApiOperation("删除转换配置")  
120 - public ResponseEntity<Boolean> deleteConfig(  
121 - @Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO) throws ThingsboardException {  
122 - return delete(deleteDTO, FastIotConstants.CONVERT_DATA);  
123 - } 95 + @PostMapping("js")
  96 + @ApiOperation("添加或修改转换脚本")
  97 + public ResponseEntity<ConvertConfigDTO> createOrUpdateConvertJS(
  98 + @Validated @RequestBody ConvertConfigDTO convertConfigDTO) throws ThingsboardException {
  99 + convertConfigDTO.setTenantId(getCurrentUser().getCurrentTenantId());
  100 + convertConfigDTO.setNodeType(FastIotConstants.JAVA_SCRIPT);
  101 + return ResponseEntity.ok(convertConfigService.createOrUpdate(convertConfigDTO));
  102 + }
124 103
125 - @DeleteMapping("js")  
126 - @ApiOperation("删除转换脚本")  
127 - public ResponseEntity<Boolean> deleteJS(  
128 - @Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO) throws ThingsboardException {  
129 - return delete(deleteDTO, FastIotConstants.JAVA_SCRIPT);  
130 - } 104 + @PostMapping("/check/config")
  105 + @ApiOperation("检查配置名称是否存在")
  106 + public ResponseEntity<Boolean> checkConvertConfig(@RequestBody Map<String, String> checkParam)
  107 + throws ThingsboardException {
  108 + String type = checkParam.get("type");
  109 + String name = checkParam.get("name");
  110 + if (StringUtils.isEmpty(type) || StringUtils.isEmpty(name)) {
  111 + throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  112 + }
  113 + return ResponseEntity.ok(
  114 + convertConfigService.checkConvertConfigNameExist(
  115 + null, name, type, getCurrentUser().getCurrentTenantId()));
  116 + }
131 117
132 - @PostMapping("update/config")  
133 - @ApiOperation("启用或禁用配置")  
134 - public RuleChainMetaData updateConfig(  
135 - @Validated(UpdateGroup.class) @RequestBody ConvertConfigReqDTO convertConfigReqDTO)  
136 - throws ThingsboardException {  
137 - if (convertConfigService.checkConvertConfigStatusExist(  
138 - convertConfigReqDTO.getConvertIds(),  
139 - convertConfigReqDTO.getStatus(),  
140 - getCurrentUser().getCurrentTenantId())) {  
141 - throw new YtDataValidationException(ErrorMessage.DATA_ALREADY_EXISTS.getMessage()); 118 + @DeleteMapping("config")
  119 + @ApiOperation("删除转换配置")
  120 + public ResponseEntity<Boolean> deleteConfig(
  121 + @Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO) throws ThingsboardException {
  122 + return delete(deleteDTO, FastIotConstants.CONVERT_DATA);
142 } 123 }
143 - List<String> ids = convertConfigReqDTO.getConvertIds();  
144 - int status = convertConfigReqDTO.getStatus();  
145 - List<RuleNode> nodes =  
146 - convertConfigService.getRuleNodesByConvertConfigIds(  
147 - ids, null, FastIotConstants.CONVERT_DATA);  
148 - RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();  
149 - if (null != nodes && nodes.size() > 0) {  
150 - ruleChainMetaData = saveRuleChain(nodes, status, FastIotConstants.CONVERT_DATA); 124 +
  125 + @DeleteMapping("js")
  126 + @ApiOperation("删除转换脚本")
  127 + public ResponseEntity<Boolean> deleteJS(
  128 + @Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO) throws ThingsboardException {
  129 + return delete(deleteDTO, FastIotConstants.JAVA_SCRIPT);
151 } 130 }
152 - convertConfigService.updateConvertStatusByIds(  
153 - ids, status, getCurrentUser().getCurrentTenantId());  
154 - return ruleChainMetaData;  
155 - }  
156 131
157 - @PostMapping("update/js")  
158 - @ApiOperation("启用或禁用转换脚本")  
159 - public RuleChainMetaData updateJs(  
160 - @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertJSReqDTO)  
161 - throws ThingsboardException {  
162 - int status = convertJSReqDTO.getStatus();  
163 - if (status == FastIotConstants.StateValue.ENABLE  
164 - && convertConfigService.checkConvertJSStatusEnable(getCurrentUser().getCurrentTenantId())) {  
165 - throw new YtDataValidationException(ErrorMessage.CONVERT_JS_IS_ALONE.getMessage()); 132 + @PostMapping("update/config")
  133 + @ApiOperation("启用或禁用配置")
  134 + public RuleChainMetaData updateConfig(
  135 + @Validated(UpdateGroup.class) @RequestBody ConvertConfigReqDTO convertConfigReqDTO)
  136 + throws ThingsboardException {
  137 + if (convertConfigService.checkConvertConfigStatusExist(
  138 + convertConfigReqDTO.getConvertIds(),
  139 + convertConfigReqDTO.getStatus(),
  140 + getCurrentUser().getCurrentTenantId())) {
  141 + throw new YtDataValidationException(ErrorMessage.DATA_ALREADY_EXISTS.getMessage());
  142 + }
  143 + List<String> ids = convertConfigReqDTO.getConvertIds();
  144 + int status = convertConfigReqDTO.getStatus();
  145 + List<RuleNode> nodes =
  146 + convertConfigService.getRuleNodesByConvertConfigIds(
  147 + ids, null, FastIotConstants.CONVERT_DATA);
  148 + RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
  149 + if (null != nodes && nodes.size() > 0) {
  150 + ruleChainMetaData = saveRuleChain(nodes, status, FastIotConstants.CONVERT_DATA);
  151 + }
  152 + convertConfigService.updateConvertStatusByIds(
  153 + ids, status, getCurrentUser().getCurrentTenantId());
  154 + return ruleChainMetaData;
166 } 155 }
167 - List<String> ids = new ArrayList<>();  
168 - ids.add(convertJSReqDTO.getId());  
169 - List<RuleNode> nodes =  
170 - convertConfigService.getRuleNodesByConvertConfigIds(  
171 - ids, null, FastIotConstants.JAVA_SCRIPT);  
172 156
173 - RuleChainMetaData ruleChainMetaData =  
174 - saveRuleChain(nodes, status, FastIotConstants.JAVA_SCRIPT);  
175 - convertConfigService.updateConvertStatusByIds(  
176 - ids, status, getCurrentUser().getCurrentTenantId());  
177 - return ruleChainMetaData;  
178 - } 157 + @PostMapping("update/js")
  158 + @ApiOperation("启用或禁用转换脚本")
  159 + public RuleChainMetaData updateJs(
  160 + @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertJSReqDTO)
  161 + throws ThingsboardException {
  162 + int status = convertJSReqDTO.getStatus();
  163 + if (status == FastIotConstants.StateValue.ENABLE
  164 + && convertConfigService.checkConvertJSStatusEnable(getCurrentUser().getCurrentTenantId())) {
  165 + throw new YtDataValidationException(ErrorMessage.CONVERT_JS_IS_ALONE.getMessage());
  166 + }
  167 + List<String> ids = new ArrayList<>();
  168 + ids.add(convertJSReqDTO.getId());
  169 + List<RuleNode> nodes =
  170 + convertConfigService.getRuleNodesByConvertConfigIds(
  171 + ids, null, FastIotConstants.JAVA_SCRIPT);
179 172
180 - @PostMapping("update/scene")  
181 - @ApiOperation("启用或禁用场景联动")  
182 - public RuleChainMetaData updateScene(  
183 - @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertReqDTO)  
184 - throws ThingsboardException {  
185 - //TODO 通过接口获取JsonNode  
186 - int status = -1;  
187 - String sceneId = convertReqDTO.getId();  
188 - String currentTenant = getCurrentUser().getCurrentTenantId();  
189 - Integer sceneStatus = convertReqDTO.getStatus();  
190 - JsonNode configuration = sceneLinkageService.getRuleNodeConfig(sceneId,currentTenant,getCurrentUser().getCustomerId().getId().toString(),sceneStatus);  
191 - boolean noValue = configuration == null;  
192 - if (noValue && convertReqDTO.getStatus() == FastIotConstants.StateValue.DISABLE) {  
193 - status = FastIotConstants.StateValue.DISABLE; 173 + RuleChainMetaData ruleChainMetaData =
  174 + saveRuleChain(nodes, status, FastIotConstants.JAVA_SCRIPT);
  175 + convertConfigService.updateConvertStatusByIds(
  176 + ids, status, getCurrentUser().getCurrentTenantId());
  177 + return ruleChainMetaData;
194 } 178 }
195 - if (!noValue) {  
196 - status = FastIotConstants.StateValue.ENABLE;  
197 - }  
198 - List<RuleNode> ruleNodes = new ArrayList<>();  
199 - RuleNode scene = new RuleNode();  
200 - scene.setName("Scene");  
201 - scene.setType("org.thingsboard.rule.engine.yunteng.scene.TbSceneReactNode");  
202 - scene.setConfiguration(configuration);  
203 - ruleNodes.add(scene);  
204 - RuleChainMetaData result = saveRuleChain(ruleNodes, status, FastIotConstants.SCENE_REACT);  
205 - sceneLinkageService.updateSceneStatus(sceneId,sceneStatus,currentTenant);  
206 - return result;  
207 - }  
208 179
209 - /**  
210 - * 保存规则链  
211 - *  
212 - * @param nodes 规则节点  
213 - * @param status 0禁用 1启用  
214 - * @return 规则节点数据  
215 - */  
216 - private RuleChainMetaData saveRuleChain(List<RuleNode> nodes, Integer status, Integer nodeType)  
217 - throws ThingsboardException {  
218 - boolean needSaveRuleNode;  
219 - TenantId tenantId = getTenantId();  
220 - // 1. GET DEFAULT RULE CHAIN  
221 - RuleChain ruleChain = ytRuleChainService.getRootTenantRuleChain(getTenantId());  
222 - // 2. GET RULE CHAIN METADATA  
223 - RuleChainMetaData ruleChainMetaData =  
224 - ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChain.getId());  
225 - // 3. SETUP CONNECTION AND ADD OR DELETE RULE NODE  
226 - if (status == FastIotConstants.MagicNumber.ZERO) {  
227 - needSaveRuleNode = convertConfigService.deleteRuleNode(nodes, ruleChainMetaData, nodeType);  
228 - } else {  
229 - convertConfigService.addRuleNode(nodes, ruleChainMetaData, nodeType);  
230 - needSaveRuleNode = true; 180 + @PostMapping("update/scene")
  181 + @ApiOperation("启用或禁用场景联动")
  182 + public RuleChainMetaData updateScene(
  183 + @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertReqDTO)
  184 + throws ThingsboardException {
  185 + int status = -1;
  186 + String sceneId = convertReqDTO.getId();
  187 + String currentTenant = getCurrentUser().getCurrentTenantId();
  188 + Integer sceneStatus = convertReqDTO.getStatus();
  189 + JsonNode configuration = sceneLinkageService.getRuleNodeConfig(sceneId, currentTenant, getCurrentUser().getCustomerId().getId().toString(), sceneStatus);
  190 + boolean noValue = configuration == null;
  191 + if (noValue && convertReqDTO.getStatus() == FastIotConstants.StateValue.DISABLE) {
  192 + status = FastIotConstants.StateValue.DISABLE;
  193 + }
  194 + if (!noValue) {
  195 + status = FastIotConstants.StateValue.ENABLE;
  196 + }
  197 + List<RuleNode> ruleNodes = new ArrayList<>();
  198 + RuleNode scene = new RuleNode();
  199 + scene.setName("Scene");
  200 + scene.setType("org.thingsboard.rule.engine.yunteng.scene.TbSceneReactNode");
  201 + scene.setConfiguration(configuration);
  202 + ruleNodes.add(scene);
  203 + RuleChainMetaData result = saveRuleChain(ruleNodes, status, FastIotConstants.SCENE_REACT);
  204 + sceneLinkageService.updateSceneStatus(sceneId, sceneStatus, currentTenant);
  205 + return result;
231 } 206 }
232 - // 4. SAVE METADATA  
233 - RuleChainMetaData savedRuleChainMetaData = null;  
234 - if (needSaveRuleNode) {  
235 - if (debugPerTenantEnabled) {  
236 - ConcurrentMap<TenantId, DebugTbRateLimits> debugPerTenantLimits =  
237 - actorContext.getDebugPerTenantLimits();  
238 - DebugTbRateLimits debugTbRateLimits = debugPerTenantLimits.getOrDefault(tenantId, null);  
239 - if (debugTbRateLimits != null) {  
240 - debugPerTenantLimits.remove(tenantId, debugTbRateLimits); 207 +
  208 + /**
  209 + * 保存规则链
  210 + *
  211 + * @param nodes 规则节点
  212 + * @param status 0禁用 1启用
  213 + * @return 规则节点数据
  214 + */
  215 + private RuleChainMetaData saveRuleChain(List<RuleNode> nodes, Integer status, Integer nodeType)
  216 + throws ThingsboardException {
  217 + boolean needSaveRuleNode;
  218 + TenantId tenantId = getTenantId();
  219 + // 1. GET DEFAULT RULE CHAIN
  220 + RuleChain ruleChain = ytRuleChainService.getRootTenantRuleChain(getTenantId());
  221 + // 2. GET RULE CHAIN METADATA
  222 + RuleChainMetaData ruleChainMetaData =
  223 + ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChain.getId());
  224 + // 3. SETUP CONNECTION AND ADD OR DELETE RULE NODE
  225 + if (status == FastIotConstants.MagicNumber.ZERO) {
  226 + needSaveRuleNode = convertConfigService.deleteRuleNode(nodes, ruleChainMetaData, nodeType);
  227 + } else {
  228 + convertConfigService.addRuleNode(nodes, ruleChainMetaData, nodeType);
  229 + needSaveRuleNode = true;
241 } 230 }
242 - }  
243 - checkNotNull(  
244 - ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData) ? true : null);  
245 - savedRuleChainMetaData =  
246 - checkNotNull(  
247 - ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId())); 231 + // 4. SAVE METADATA
  232 + RuleChainMetaData savedRuleChainMetaData = null;
  233 + if (needSaveRuleNode) {
  234 + if (debugPerTenantEnabled) {
  235 + ConcurrentMap<TenantId, DebugTbRateLimits> debugPerTenantLimits =
  236 + actorContext.getDebugPerTenantLimits();
  237 + DebugTbRateLimits debugTbRateLimits = debugPerTenantLimits.getOrDefault(tenantId, null);
  238 + if (debugTbRateLimits != null) {
  239 + debugPerTenantLimits.remove(tenantId, debugTbRateLimits);
  240 + }
  241 + }
  242 + checkNotNull(
  243 + ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData) ? true : null);
  244 + savedRuleChainMetaData =
  245 + checkNotNull(
  246 + ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId()));
248 247
249 - if (RuleChainType.CORE.equals(ruleChain.getType())) {  
250 - tbClusterService.broadcastEntityStateChangeEvent(  
251 - ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);  
252 - } 248 + if (RuleChainType.CORE.equals(ruleChain.getType())) {
  249 + tbClusterService.broadcastEntityStateChangeEvent(
  250 + ruleChain.getTenantId(), ruleChain.getId(), ComponentLifecycleEvent.UPDATED);
  251 + }
  252 + }
  253 + return savedRuleChainMetaData;
253 } 254 }
254 - return savedRuleChainMetaData;  
255 - }  
256 255
257 - private ResponseEntity<Boolean> delete(DeleteDTO deleteDTO, Integer nodeType)  
258 - throws ThingsboardException {  
259 - List<RuleNode> nodes =  
260 - convertConfigService.getRuleNodesByConvertConfigIds(  
261 - new ArrayList<>(deleteDTO.getIds()), FastIotConstants.StateValue.ENABLE, nodeType);  
262 - if (nodes != null && nodes.size() > FastIotConstants.MagicNumber.ZERO) {  
263 - saveRuleChain(nodes, 0, nodeType); 256 + private ResponseEntity<Boolean> delete(DeleteDTO deleteDTO, Integer nodeType)
  257 + throws ThingsboardException {
  258 + List<RuleNode> nodes =
  259 + convertConfigService.getRuleNodesByConvertConfigIds(
  260 + new ArrayList<>(deleteDTO.getIds()), FastIotConstants.StateValue.ENABLE, nodeType);
  261 + if (nodes != null && nodes.size() > FastIotConstants.MagicNumber.ZERO) {
  262 + saveRuleChain(nodes, 0, nodeType);
  263 + }
  264 + return ResponseEntity.ok(convertConfigService.deleteConvertConfig(deleteDTO, nodeType));
264 } 265 }
265 - return ResponseEntity.ok(convertConfigService.deleteConvertConfig(deleteDTO, nodeType));  
266 - }  
267 } 266 }
@@ -72,14 +72,14 @@ public interface FastIotConstants { @@ -72,14 +72,14 @@ public interface FastIotConstants {
72 } 72 }
73 73
74 interface ReceiverType { 74 interface ReceiverType {
75 - String PERSONAL = "3";  
76 - String DEPARTMENT = "2";  
77 - String ORGANIZATION = "1";  
78 - String ALL = "0"; 75 + int PERSONAL = 3;
  76 + int DEPARTMENT = 2;
  77 + int ORGANIZATION = 1;
  78 + int ALL = 0;
79 } 79 }
80 80
81 interface DraftStatus { 81 interface DraftStatus {
82 - String PUBLISHED = "1";  
83 - String DRAFT = "0"; 82 + int PUBLISHED = 1;
  83 + int DRAFT = 0;
84 } 84 }
85 } 85 }
@@ -12,19 +12,14 @@ import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum; @@ -12,19 +12,14 @@ import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
12 import java.util.List; 12 import java.util.List;
13 13
14 /** 14 /**
15 - * @Description 场景联动动作告警通知 15 + * @Description 场景联动动作告警通知
16 * @Author cxy 16 * @Author cxy
17 * @Date 2021/11/24 17:32 17 * @Date 2021/11/24 17:32
18 */ 18 */
19 @Data 19 @Data
20 -public class ActionAlarmDTO extends TenantDTO{ 20 +public class ActionAlarmDTO extends TenantDTO {
21 21
22 22
23 - private List<ActionTypeEnum> noticeType;  
24 -  
25 - /**告警联系人*/  
26 - private List<String> noticeUser;  
27 -  
28 private AlarmSeverity alarmLevel; 23 private AlarmSeverity alarmLevel;
29 24
30 25
@@ -6,37 +6,38 @@ import lombok.EqualsAndHashCode; @@ -6,37 +6,38 @@ import lombok.EqualsAndHashCode;
6 6
7 import javax.validation.constraints.NotEmpty; 7 import javax.validation.constraints.NotEmpty;
8 8
9 -/** @Description @Author cxy @Date 2021/11/16 17:49 */ 9 +/**
  10 + * @Description @Author cxy @Date 2021/11/16 17:49
  11 + */
10 @Data 12 @Data
11 @EqualsAndHashCode(callSuper = true) 13 @EqualsAndHashCode(callSuper = true)
12 public class AlarmInfoDTO extends TenantDTO { 14 public class AlarmInfoDTO extends TenantDTO {
13 - @ApiModelProperty(value = "告警时间")  
14 - private long createTs; 15 + @ApiModelProperty(value = "告警时间")
  16 + private long createTs;
15 17
16 - @ApiModelProperty(value = "告警类型")  
17 - private String type; 18 + @ApiModelProperty(value = "告警名称")
  19 + private String type;
18 20
19 - @ApiModelProperty(value = "告警详情")  
20 - private String details; 21 + @ApiModelProperty(value = "告警详情")
  22 + private String details;
21 23
22 24
23 - @ApiModelProperty(value = "告警开始时间")  
24 - private long startTs; 25 + @ApiModelProperty(value = "告警开始时间")
  26 + private long startTs;
25 27
26 - @ApiModelProperty(value = "告警结束时间")  
27 - private long endTs; 28 + @ApiModelProperty(value = "告警结束时间")
  29 + private long endTs;
28 30
29 - @ApiModelProperty(value = "告警状态")  
30 - private String status; 31 + @ApiModelProperty(value = "告警状态")
  32 + private String status;
31 33
32 - @ApiModelProperty(value = "告警程度")  
33 - private String severity; 34 + @ApiModelProperty(value = "告警程度")
  35 + private String severity;
34 36
35 37
36 -  
37 - @ApiModelProperty(value = "告警设备名称")  
38 - private String deviceName;  
39 - @ApiModelProperty(value = "告警设备ID")  
40 - @NotEmpty(message = "设备ID不能为空")  
41 - private String deviceId; 38 + @ApiModelProperty(value = "告警设备名称")
  39 + private String deviceName;
  40 + @ApiModelProperty(value = "告警设备ID")
  41 + @NotEmpty(message = "设备ID不能为空")
  42 + private String deviceId;
42 } 43 }
@@ -31,13 +31,13 @@ public class SysNoticeDTO extends TenantDTO { @@ -31,13 +31,13 @@ public class SysNoticeDTO extends TenantDTO {
31 private String content; 31 private String content;
32 32
33 @ApiModelProperty(value = "接收者(字典值receiver_type) 0:全部 1:组织 2:部门 3:个人",required = true) 33 @ApiModelProperty(value = "接收者(字典值receiver_type) 0:全部 1:组织 2:部门 3:个人",required = true)
34 - private String receiverType; 34 + private Integer receiverType;
35 35
36 @ApiModelProperty(value = "根据receiverType不同变化,0:传null,1:组织id,2:部门id,3:用户id",required = true) 36 @ApiModelProperty(value = "根据receiverType不同变化,0:传null,1:组织id,2:部门id,3:用户id",required = true)
37 private String pointId; 37 private String pointId;
38 38
39 @ApiModelProperty(value = "发送状态(字典值draft_status) 0:草稿 1:已发布") 39 @ApiModelProperty(value = "发送状态(字典值draft_status) 0:草稿 1:已发布")
40 - private String status; 40 + private Integer status;
41 41
42 @ApiModelProperty(value = "发送者") 42 @ApiModelProperty(value = "发送者")
43 private String senderName; 43 private String senderName;
@@ -27,9 +27,9 @@ public class SysNotice extends TenantBaseEntity { @@ -27,9 +27,9 @@ public class SysNotice extends TenantBaseEntity {
27 /** 内容 */ 27 /** 内容 */
28 private String content; 28 private String content;
29 /** 接收者(字典值receiver_type) 0:全部 1:组织 2:部门 3:个人 */ 29 /** 接收者(字典值receiver_type) 0:全部 1:组织 2:部门 3:个人 */
30 - private String receiverType; 30 + private int receiverType;
31 /** 发送状态(字典值draft_status) 0:草稿 1:已发布 */ 31 /** 发送状态(字典值draft_status) 0:草稿 1:已发布 */
32 - private String status; 32 + private int status;
33 /** 发送者 */ 33 /** 发送者 */
34 private String senderName; 34 private String senderName;
35 /** 发送时间 */ 35 /** 发送时间 */
@@ -30,5 +30,5 @@ public class SysNoticeUser extends TenantBaseEntity { @@ -30,5 +30,5 @@ public class SysNoticeUser extends TenantBaseEntity {
30 /** 阅读时间 */ 30 /** 阅读时间 */
31 private LocalDateTime readDate; 31 private LocalDateTime readDate;
32 /** 通知用户状态: 0 草稿 1已发布 */ 32 /** 通知用户状态: 0 草稿 1已发布 */
33 - private String status; 33 + private Integer status;
34 } 34 }
@@ -73,7 +73,7 @@ public class SysNoticeUserServiceImpl @@ -73,7 +73,7 @@ public class SysNoticeUserServiceImpl
73 73
74 @Override 74 @Override
75 public void saveSysNoticeUser( 75 public void saveSysNoticeUser(
76 - List<String> userIds, String tenantId, String noticeId, String status) { 76 + List<String> userIds, String tenantId, String noticeId, Integer status) {
77 List<User> userList = userMapper 77 List<User> userList = userMapper
78 .selectList( 78 .selectList(
79 new LambdaQueryWrapper<User>().in(User::getId, userIds)) 79 new LambdaQueryWrapper<User>().in(User::getId, userIds))
@@ -108,8 +108,8 @@ public class SysNoticeUserServiceImpl @@ -108,8 +108,8 @@ public class SysNoticeUserServiceImpl
108 } 108 }
109 109
110 @Override 110 @Override
111 - public boolean updateSysNoticeUsersStatusByNoticeId(String id, String status) {  
112 - if (StringUtils.isAllEmpty(id) || StringUtils.isAllEmpty(status)) { 111 + public boolean updateSysNoticeUsersStatusByNoticeId(String id, Integer status) {
  112 + if (StringUtils.isAllEmpty(id) || status == null) {
113 throw new YtDataValidationException(ErrorMessage.INTERNAL_ERROR.name()); 113 throw new YtDataValidationException(ErrorMessage.INTERNAL_ERROR.name());
114 } 114 }
115 return baseMapper.updateSysNoticeUsersStatusByNoticeId(id, status); 115 return baseMapper.updateSysNoticeUsersStatusByNoticeId(id, status);
@@ -13,13 +13,10 @@ import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; @@ -13,13 +13,10 @@ import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum;
13 import org.thingsboard.server.common.data.yunteng.utils.YtDateTimeUtils; 13 import org.thingsboard.server.common.data.yunteng.utils.YtDateTimeUtils;
14 import org.thingsboard.server.dao.yunteng.entities.*; 14 import org.thingsboard.server.dao.yunteng.entities.*;
15 import org.thingsboard.server.dao.yunteng.mapper.*; 15 import org.thingsboard.server.dao.yunteng.mapper.*;
16 -import org.thingsboard.server.dao.yunteng.service.YtNoticeService;  
17 import org.thingsboard.server.dao.yunteng.service.YtMailService; 16 import org.thingsboard.server.dao.yunteng.service.YtMailService;
  17 +import org.thingsboard.server.dao.yunteng.service.YtNoticeService;
18 import org.thingsboard.server.dao.yunteng.service.YtSmsService; 18 import org.thingsboard.server.dao.yunteng.service.YtSmsService;
19 19
20 -import java.time.LocalDateTime;  
21 -import java.time.OffsetDateTime;  
22 -import java.time.format.DateTimeFormatter;  
23 import java.util.*; 20 import java.util.*;
24 import java.util.stream.Collectors; 21 import java.util.stream.Collectors;
25 22
@@ -47,7 +44,7 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -47,7 +44,7 @@ public class YtNoticeServiceImpl implements YtNoticeService {
47 private final YtMailService mailService; 44 private final YtMailService mailService;
48 45
49 @Override 46 @Override
50 - public void alert(AlarmInfoDTO alarmInfo) { 47 + public void alert(String profileId, AlarmInfoDTO alarmInfo) {
51 48
52 /** 49 /**
53 * 1、查找设备和设备所属组织 50 * 1、查找设备和设备所属组织
@@ -68,11 +65,8 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -68,11 +65,8 @@ public class YtNoticeServiceImpl implements YtNoticeService {
68 .eq(Organization::getId, device.getOrganizationId()); 65 .eq(Organization::getId, device.getOrganizationId());
69 Organization organization = organizationMapper.selectOne(organizationQueryWrapper); 66 Organization organization = organizationMapper.selectOne(organizationQueryWrapper);
70 67
71 - QueryWrapper<AlarmProfile> alarmProfileQueryWrapper = new QueryWrapper<AlarmProfile>();  
72 - //TODO junlianglee 修改通知  
73 -// alarmProfileQueryWrapper.lambda()  
74 -// .eq(AlarmProfile::getDeviceProfileId, device.getProfileId());  
75 - AlarmProfile alarmProfile = alarmProfileMapper.selectOne(alarmProfileQueryWrapper); 68 +
  69 + AlarmProfile alarmProfile = alarmProfileMapper.selectById(profileId);
76 70
77 71
78 if (alarmProfile == null || alarmProfile.getAlarmContactId().isEmpty() || alarmProfile.getMessageMode().isEmpty()) { 72 if (alarmProfile == null || alarmProfile.getAlarmContactId().isEmpty() || alarmProfile.getMessageMode().isEmpty()) {
@@ -80,7 +74,7 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -80,7 +74,7 @@ public class YtNoticeServiceImpl implements YtNoticeService {
80 } 74 }
81 String messageCode = alarmProfile.getMessageMode(); 75 String messageCode = alarmProfile.getMessageMode();
82 List<AlarmContact> alarmContactList = alarmContactMapper.selectBatchIds(Arrays.stream(alarmProfile.getAlarmContactId().split(",")).distinct().collect(Collectors.toList())); 76 List<AlarmContact> alarmContactList = alarmContactMapper.selectBatchIds(Arrays.stream(alarmProfile.getAlarmContactId().split(",")).distinct().collect(Collectors.toList()));
83 - noticeAll(messageCode, alarmContactList, alarmInfo, organization,alarmProfile.getTenantId()); 77 + noticeAll(messageCode, alarmContactList, alarmInfo, organization, alarmProfile.getTenantId());
84 78
85 79
86 } 80 }
@@ -93,7 +87,7 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -93,7 +87,7 @@ public class YtNoticeServiceImpl implements YtNoticeService {
93 * @param alarmInfo 通知内容 87 * @param alarmInfo 通知内容
94 * @param organization 设备所属组织 88 * @param organization 设备所属组织
95 */ 89 */
96 - private void noticeAll(String messageCode, List<AlarmContact> alarmContactList, AlarmInfoDTO alarmInfo, Organization organization,String tenantId) { 90 + private void noticeAll(String messageCode, List<AlarmContact> alarmContactList, AlarmInfoDTO alarmInfo, Organization organization, String tenantId) {
97 Optional.ofNullable(alarmContactList).ifPresent(contacts -> { 91 Optional.ofNullable(alarmContactList).ifPresent(contacts -> {
98 92
99 /**可用的告警通知模板*/ 93 /**可用的告警通知模板*/
@@ -113,35 +107,36 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -113,35 +107,36 @@ public class YtNoticeServiceImpl implements YtNoticeService {
113 107
114 if (messageCode.contains(MessageTypeEnum.PHONE_MESSAGE.name()) 108 if (messageCode.contains(MessageTypeEnum.PHONE_MESSAGE.name())
115 && templatesMap.containsKey(MessageTypeEnum.PHONE_MESSAGE.name())) { 109 && templatesMap.containsKey(MessageTypeEnum.PHONE_MESSAGE.name())) {
116 - sms4Alarm(alarmInfo,templatesMap.get(MessageTypeEnum.PHONE_MESSAGE.name()),organization,contacts); 110 + sms4Alarm(alarmInfo, templatesMap.get(MessageTypeEnum.PHONE_MESSAGE.name()), organization, contacts);
117 } 111 }
118 112
119 if (messageCode.contains(MessageTypeEnum.EMAIL_MESSAGE.name()) 113 if (messageCode.contains(MessageTypeEnum.EMAIL_MESSAGE.name())
120 && templatesMap.containsKey(MessageTypeEnum.EMAIL_MESSAGE.name())) { 114 && templatesMap.containsKey(MessageTypeEnum.EMAIL_MESSAGE.name())) {
121 - email4Alarm(alarmInfo,templatesMap.get(MessageTypeEnum.EMAIL_MESSAGE.name()),organization,contacts); 115 + email4Alarm(alarmInfo, templatesMap.get(MessageTypeEnum.EMAIL_MESSAGE.name()), organization, contacts);
122 } 116 }
123 117
124 118
125 if (messageCode.contains(MessageTypeEnum.DING_TALK_MESSAGE.name()) 119 if (messageCode.contains(MessageTypeEnum.DING_TALK_MESSAGE.name())
126 && templatesMap.containsKey(MessageTypeEnum.DING_TALK_MESSAGE.name())) { 120 && templatesMap.containsKey(MessageTypeEnum.DING_TALK_MESSAGE.name())) {
127 - dingTalk4Alarm(alarmInfo,templatesMap.get(MessageTypeEnum.DING_TALK_MESSAGE.name()),organization,contacts); 121 + dingTalk4Alarm(alarmInfo, templatesMap.get(MessageTypeEnum.DING_TALK_MESSAGE.name()), organization, contacts);
128 } 122 }
129 123
130 if (messageCode.contains(MessageTypeEnum.WECHAT_MESSAGE.name()) 124 if (messageCode.contains(MessageTypeEnum.WECHAT_MESSAGE.name())
131 && templatesMap.containsKey(MessageTypeEnum.WECHAT_MESSAGE.name())) { 125 && templatesMap.containsKey(MessageTypeEnum.WECHAT_MESSAGE.name())) {
132 - weChat4Alarm(alarmInfo,templatesMap.get(MessageTypeEnum.WECHAT_MESSAGE.name()),organization,contacts); 126 + weChat4Alarm(alarmInfo, templatesMap.get(MessageTypeEnum.WECHAT_MESSAGE.name()), organization, contacts);
133 } 127 }
134 }); 128 });
135 } 129 }
136 130
137 /** 131 /**
138 * 短信通知设备告警信息 132 * 短信通知设备告警信息
139 - * @param alarmInfo 告警信息  
140 - * @param templateId 告警模板主键  
141 - * @param organization 设备所属组织  
142 - * @param contacts 设备告警联系人 133 + *
  134 + * @param alarmInfo 告警信息
  135 + * @param templateId 告警模板主键
  136 + * @param organization 设备所属组织
  137 + * @param contacts 设备告警联系人
143 */ 138 */
144 - private void sms4Alarm(AlarmInfoDTO alarmInfo,String templateId, Organization organization,List<AlarmContact> contacts){ 139 + private void sms4Alarm(AlarmInfoDTO alarmInfo, String templateId, Organization organization, List<AlarmContact> contacts) {
145 SmsReqDTO info = new SmsReqDTO(); 140 SmsReqDTO info = new SmsReqDTO();
146 info.setId(templateId); 141 info.setId(templateId);
147 info.setTemplatePurpose(MsgTemplatePurposeEnum.FOR_ALARM_NOTICE.name()); 142 info.setTemplatePurpose(MsgTemplatePurposeEnum.FOR_ALARM_NOTICE.name());
@@ -163,12 +158,13 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -163,12 +158,13 @@ public class YtNoticeServiceImpl implements YtNoticeService {
163 158
164 /** 159 /**
165 * 邮件通知设备告警信息 160 * 邮件通知设备告警信息
166 - * @param alarmInfo 告警信息  
167 - * @param templateId 告警模板主键  
168 - * @param organization 设备所属组织  
169 - * @param contacts 设备告警联系人 161 + *
  162 + * @param alarmInfo 告警信息
  163 + * @param templateId 告警模板主键
  164 + * @param organization 设备所属组织
  165 + * @param contacts 设备告警联系人
170 */ 166 */
171 - private void email4Alarm(AlarmInfoDTO alarmInfo,String templateId, Organization organization,List<AlarmContact> contacts){ 167 + private void email4Alarm(AlarmInfoDTO alarmInfo, String templateId, Organization organization, List<AlarmContact> contacts) {
172 List<String> emailReceivers = new ArrayList<>(); 168 List<String> emailReceivers = new ArrayList<>();
173 contacts.stream().parallel().forEach(item -> { 169 contacts.stream().parallel().forEach(item -> {
174 if (!item.getEmail().isEmpty()) { 170 if (!item.getEmail().isEmpty()) {
@@ -178,12 +174,12 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -178,12 +174,12 @@ public class YtNoticeServiceImpl implements YtNoticeService {
178 if (!emailReceivers.isEmpty()) { 174 if (!emailReceivers.isEmpty()) {
179 EmailReqDTO info = new EmailReqDTO(); 175 EmailReqDTO info = new EmailReqDTO();
180 info.setTo(emailReceivers.toArray(new String[emailReceivers.size()])); 176 info.setTo(emailReceivers.toArray(new String[emailReceivers.size()]));
181 - info.setSubject(String.format("【%s】告警通知",alarmInfo.getDeviceName()));  
182 - String body =String.format("%s位于【%s】的设备【%s】触发【%s】级的【%s】,请尽快处理!"  
183 - ,YtDateTimeUtils.formate(alarmInfo.getCreateTs()) 177 + info.setSubject(String.format("【%s】告警通知", alarmInfo.getDeviceName()));
  178 + String body = String.format("%s位于【%s】的设备【%s】触发【%s】级的【%s】,请尽快处理!"
  179 + , YtDateTimeUtils.formate(alarmInfo.getCreateTs())
184 , organization != null ? organization.getName() : "" 180 , organization != null ? organization.getName() : ""
185 - ,alarmInfo.getDeviceName()  
186 - ,alarmInfo.getSeverity() 181 + , alarmInfo.getDeviceName()
  182 + , alarmInfo.getSeverity()
187 , alarmInfo.getType()); 183 , alarmInfo.getType());
188 info.setBody(body); 184 info.setBody(body);
189 info.setEmailFormatEnum(EmailFormatEnum.TEXT.name()); 185 info.setEmailFormatEnum(EmailFormatEnum.TEXT.name());
@@ -196,12 +192,13 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -196,12 +192,13 @@ public class YtNoticeServiceImpl implements YtNoticeService {
196 192
197 /** 193 /**
198 * 钉钉通知设备告警信息 194 * 钉钉通知设备告警信息
199 - * @param alarmInfo 告警信息  
200 - * @param templateId 告警模板主键  
201 - * @param organization 设备所属组织  
202 - * @param contacts 设备告警联系人 195 + *
  196 + * @param alarmInfo 告警信息
  197 + * @param templateId 告警模板主键
  198 + * @param organization 设备所属组织
  199 + * @param contacts 设备告警联系人
203 */ 200 */
204 - private void dingTalk4Alarm(AlarmInfoDTO alarmInfo,String templateId, Organization organization,List<AlarmContact> contacts){ 201 + private void dingTalk4Alarm(AlarmInfoDTO alarmInfo, String templateId, Organization organization, List<AlarmContact> contacts) {
205 // TODO 推送钉钉消息 202 // TODO 推送钉钉消息
206 SmsReqDTO info = new SmsReqDTO(); 203 SmsReqDTO info = new SmsReqDTO();
207 info.setId(templateId); 204 info.setId(templateId);
@@ -224,12 +221,13 @@ public class YtNoticeServiceImpl implements YtNoticeService { @@ -224,12 +221,13 @@ public class YtNoticeServiceImpl implements YtNoticeService {
224 221
225 /** 222 /**
226 * 微信通知设备告警信息 223 * 微信通知设备告警信息
227 - * @param alarmInfo 告警信息  
228 - * @param templateId 告警模板主键  
229 - * @param organization 设备所属组织  
230 - * @param contacts 设备告警联系人 224 + *
  225 + * @param alarmInfo 告警信息
  226 + * @param templateId 告警模板主键
  227 + * @param organization 设备所属组织
  228 + * @param contacts 设备告警联系人
231 */ 229 */
232 - private void weChat4Alarm(AlarmInfoDTO alarmInfo,String templateId, Organization organization,List<AlarmContact> contacts){ 230 + private void weChat4Alarm(AlarmInfoDTO alarmInfo, String templateId, Organization organization, List<AlarmContact> contacts) {
233 // TODO 推送微信通知 231 // TODO 推送微信通知
234 SmsReqDTO info = new SmsReqDTO(); 232 SmsReqDTO info = new SmsReqDTO();
235 info.setId(templateId); 233 info.setId(templateId);
@@ -30,7 +30,7 @@ public interface SysNoticeUserMapper extends BaseMapper<SysNoticeUser> { @@ -30,7 +30,7 @@ public interface SysNoticeUserMapper extends BaseMapper<SysNoticeUser> {
30 */ 30 */
31 SysNoticeUserDTO get(@Param("id") String id, @Param("tenantId") String tenantId); 31 SysNoticeUserDTO get(@Param("id") String id, @Param("tenantId") String tenantId);
32 32
33 - boolean updateSysNoticeUsersStatusByNoticeId(@Param("noticeId")String noticeId, @Param("status")String status); 33 + boolean updateSysNoticeUsersStatusByNoticeId(@Param("noticeId")String noticeId, @Param("status")Integer status);
34 34
35 35
36 } 36 }
@@ -21,11 +21,11 @@ public interface SysNoticeUserService extends BaseService<SysNoticeUser>{ @@ -21,11 +21,11 @@ public interface SysNoticeUserService extends BaseService<SysNoticeUser>{
21 21
22 SysNoticeUserDTO get(String id,String tenantId); 22 SysNoticeUserDTO get(String id,String tenantId);
23 23
24 - void saveSysNoticeUser (List<String> userIds, String tenantId,String noticeId,String status); 24 + void saveSysNoticeUser (List<String> userIds, String tenantId,String noticeId,Integer status);
25 25
26 List<String> getSysNoticeUserIdsByNoticeId(String noticeId); 26 List<String> getSysNoticeUserIdsByNoticeId(String noticeId);
27 27
28 - boolean updateSysNoticeUsersStatusByNoticeId(String noticeId, String status); 28 + boolean updateSysNoticeUsersStatusByNoticeId(String noticeId, Integer status);
29 29
30 boolean deleteNoticUserByNoticeId(List<String> noticeId); 30 boolean deleteNoticUserByNoticeId(List<String> noticeId);
31 } 31 }
@@ -18,8 +18,9 @@ public interface YtNoticeService { @@ -18,8 +18,9 @@ public interface YtNoticeService {
18 * 设备告警通知负责人 18 * 设备告警通知负责人
19 * * @param alarmInfo 19 * * @param alarmInfo
20 * 20 *
  21 + * @param profileId 告警配置主键
21 * @param alarmInfo 告警数据 22 * @param alarmInfo 告警数据
22 */ 23 */
23 - void alert(AlarmInfoDTO alarmInfo); 24 + void alert(String profileId, AlarmInfoDTO alarmInfo);
24 25
25 } 26 }
@@ -32,15 +32,15 @@ @@ -32,15 +32,15 @@
32 sn.id id, 32 sn.id id,
33 sn.type AS type, 33 sn.type AS type,
34 sn.title title, 34 sn.title title,
35 - sn.content AS content,  
36 - (  
37 - <include refid="dict"/>  
38 - AND sd.dict_code = 'receiver_type' AND sdi.item_value = sn.receiver_type  
39 - ) receiver_type,  
40 - (  
41 - <include refid="dict"/>  
42 - AND sd.dict_code = 'draft_status' AND sdi.item_value = sn.status  
43 - ) status, 35 + sn.content AS content,sn.receiver_type,sn.status,
  36 +<!-- (-->
  37 +<!-- <include refid="dict"/>-->
  38 +<!-- AND sd.dict_code = 'receiver_type' AND sdi.item_value = sn.receiver_type-->
  39 +<!-- ) receiver_type,-->
  40 +<!-- (-->
  41 +<!-- <include refid="dict"/>-->
  42 +<!-- AND sd.dict_code = 'draft_status' AND sdi.item_value = sn.status-->
  43 +<!-- ) status,-->
44 sn.sender_name sender_name, 44 sn.sender_name sender_name,
45 sn.sender_date sender_date, 45 sn.sender_date sender_date,
46 sn.creator creator, 46 sn.creator creator,
@@ -33,15 +33,9 @@ import java.net.InetAddress; @@ -33,15 +33,9 @@ import java.net.InetAddress;
33 import static org.thingsboard.common.util.DonAsynchron.withCallback; 33 import static org.thingsboard.common.util.DonAsynchron.withCallback;
34 34
35 @Slf4j 35 @Slf4j
36 -@RuleNode(  
37 - type = ComponentType.EXTERNAL,  
38 - name = "alarm notice",  
39 - configClazz = AlarmNoticeNodeConfiguration.class,  
40 - nodeDescription = "while device alarm, notice some people.",  
41 - nodeDetails = "notice method include sms,email and so on.", 36 +@RuleNode(type = ComponentType.EXTERNAL, name = "alarm notice", configClazz = AlarmNoticeNodeConfiguration.class, nodeDescription = "while device alarm, notice some people.", nodeDetails = "notice method include sms,email and so on.",
42 // configDirective = "tbActionNodeSendSmsConfig", 37 // configDirective = "tbActionNodeSendSmsConfig",
43 - icon = "sms"  
44 -) 38 + icon = "sms")
45 public class AlarmNoticeNode implements TbNode { 39 public class AlarmNoticeNode implements TbNode {
46 40
47 private AlarmNoticeNodeConfiguration config; 41 private AlarmNoticeNodeConfiguration config;
@@ -64,11 +58,11 @@ public class AlarmNoticeNode implements TbNode { @@ -64,11 +58,11 @@ public class AlarmNoticeNode implements TbNode {
64 public void onMsg(TbContext ctx, TbMsg msg) { 58 public void onMsg(TbContext ctx, TbMsg msg) {
65 try { 59 try {
66 withCallback(ctx.getSmsExecutor().executeAsync(() -> { 60 withCallback(ctx.getSmsExecutor().executeAsync(() -> {
67 - posetApi(ctx, msg);  
68 - return null;  
69 - }),  
70 - ok -> {ctx.tellSuccess(msg);},  
71 - fail -> ctx.tellFailure(msg, fail)); 61 + posetApi(ctx, msg);
  62 + return null;
  63 + }), ok -> {
  64 + ctx.tellSuccess(msg);
  65 + }, fail -> ctx.tellFailure(msg, fail));
72 } catch (Exception ex) { 66 } catch (Exception ex) {
73 ctx.tellFailure(msg, ex); 67 ctx.tellFailure(msg, ex);
74 } 68 }
@@ -96,7 +90,7 @@ public class AlarmNoticeNode implements TbNode { @@ -96,7 +90,7 @@ public class AlarmNoticeNode implements TbNode {
96 formData.setTenantId(tenantId); 90 formData.setTenantId(tenantId);
97 formData.setSeverity(severity); 91 formData.setSeverity(severity);
98 92
99 - service.alert(formData); 93 + service.alert(null, formData);
100 } 94 }
101 95
102 @Override 96 @Override
@@ -9,11 +9,14 @@ import org.apache.commons.lang3.StringUtils; @@ -9,11 +9,14 @@ import org.apache.commons.lang3.StringUtils;
9 import org.jetbrains.annotations.NotNull; 9 import org.jetbrains.annotations.NotNull;
10 import org.thingsboard.rule.engine.api.TbContext; 10 import org.thingsboard.rule.engine.api.TbContext;
11 import org.thingsboard.server.common.data.DataConstants; 11 import org.thingsboard.server.common.data.DataConstants;
  12 +import org.thingsboard.server.common.data.alarm.Alarm;
12 import org.thingsboard.server.common.data.device.profile.AlarmCondition; 13 import org.thingsboard.server.common.data.device.profile.AlarmCondition;
13 import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter; 14 import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter;
14 import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey; 15 import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey;
15 import org.thingsboard.server.common.data.device.profile.AlarmRule; 16 import org.thingsboard.server.common.data.device.profile.AlarmRule;
16 import org.thingsboard.server.common.data.rule.RuleNodeState; 17 import org.thingsboard.server.common.data.rule.RuleNodeState;
  18 +import org.thingsboard.server.common.data.yunteng.dto.ActionAlarmDTO;
  19 +import org.thingsboard.server.common.data.yunteng.dto.AlarmInfoDTO;
17 import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO; 20 import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO;
18 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; 21 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil;
19 import org.thingsboard.server.common.data.yunteng.utils.SpringBeanUtils; 22 import org.thingsboard.server.common.data.yunteng.utils.SpringBeanUtils;
@@ -25,7 +28,9 @@ import org.thingsboard.server.dao.yunteng.entities.DoCondition; @@ -25,7 +28,9 @@ import org.thingsboard.server.dao.yunteng.entities.DoCondition;
25 import org.thingsboard.server.dao.yunteng.service.DoActionService; 28 import org.thingsboard.server.dao.yunteng.service.DoActionService;
26 import org.thingsboard.server.dao.yunteng.service.DoConditionService; 29 import org.thingsboard.server.dao.yunteng.service.DoConditionService;
27 import org.thingsboard.server.dao.yunteng.service.TriggerService; 30 import org.thingsboard.server.dao.yunteng.service.TriggerService;
  31 +import org.thingsboard.server.dao.yunteng.service.YtNoticeService;
28 32
  33 +import java.net.InetAddress;
29 import java.util.*; 34 import java.util.*;
30 import java.util.concurrent.ConcurrentHashMap; 35 import java.util.concurrent.ConcurrentHashMap;
31 import java.util.concurrent.ExecutionException; 36 import java.util.concurrent.ExecutionException;
@@ -33,121 +38,122 @@ import java.util.concurrent.ExecutionException; @@ -33,121 +38,122 @@ import java.util.concurrent.ExecutionException;
33 @Slf4j 38 @Slf4j
34 class ReactState { 39 class ReactState {
35 40
36 - /**场景联动主键*/ 41 + /**
  42 + * 场景联动主键
  43 + */
37 String reactId; 44 String reactId;
38 45
39 - /**场景联动的触发器状态 46 + /**
  47 + * 场景联动的触发器状态
40 * 键:设备主键 48 * 键:设备主键
41 * 值:设备指标参与的触发器 49 * 值:设备指标参与的触发器
42 */ 50 */
43 - private ConcurrentHashMap<String, TriggerState > triggerState = new ConcurrentHashMap<>(); 51 + private ConcurrentHashMap<String, TriggerState> triggerState = new ConcurrentHashMap<>();
44 52
45 private ConcurrentHashMap<String, TriggerState> clearState = new ConcurrentHashMap<>(); 53 private ConcurrentHashMap<String, TriggerState> clearState = new ConcurrentHashMap<>();
46 54
47 - /**场景联动的执行条件状态 55 + /**
  56 + * 场景联动的执行条件状态
48 * 键:设备主键 57 * 键:设备主键
49 * 值:设备指标参与的触发器 58 * 值:设备指标参与的触发器
50 */ 59 */
51 private ConcurrentHashMap<String, TriggerState> conditionState = new ConcurrentHashMap<>(); 60 private ConcurrentHashMap<String, TriggerState> conditionState = new ConcurrentHashMap<>();
52 61
53 62
54 -  
55 -  
56 -  
57 private final List<TriggerDTO> triggers; 63 private final List<TriggerDTO> triggers;
58 - /**【场景联动的执行条件】懒加载*/ 64 + /**
  65 + * 【场景联动的执行条件】懒加载
  66 + */
59 private final List<DoCondition> conditions; 67 private final List<DoCondition> conditions;
60 - /**【场景联动的执行集合】懒加载*/ 68 + /**
  69 + * 【场景联动的执行集合】懒加载
  70 + */
61 private final List<DoAction> actions; 71 private final List<DoAction> actions;
62 -  
63 -  
64 - 72 + private final YtNoticeService noticeService;
65 73
66 74
67 private RuleNodeState state; 75 private RuleNodeState state;
68 76
69 77
70 - ReactState(String reactId,TbContext ctx, TbSceneReactNodeConfig config) { 78 + ReactState(String reactId, TbContext ctx, TbSceneReactNodeConfig config) {
71 this.reactId = reactId; 79 this.reactId = reactId;
72 TriggerService triggerService = SpringBeanUtils.getBean(TriggerService.class); 80 TriggerService triggerService = SpringBeanUtils.getBean(TriggerService.class);
73 this.triggers = triggerService.getTrigger(reactId); 81 this.triggers = triggerService.getTrigger(reactId);
74 DoConditionService conditionService = SpringBeanUtils.getBean(DoConditionService.class); 82 DoConditionService conditionService = SpringBeanUtils.getBean(DoConditionService.class);
75 this.conditions = conditionService.getConditions(reactId); 83 this.conditions = conditionService.getConditions(reactId);
76 DoActionService actionService = SpringBeanUtils.getBean(DoActionService.class); 84 DoActionService actionService = SpringBeanUtils.getBean(DoActionService.class);
77 - this.actions =actionService.getActions(reactId); 85 + this.actions = actionService.getActions(reactId);
  86 + this.noticeService = SpringBeanUtils.getBean(YtNoticeService.class);
78 87
79 } 88 }
80 89
81 90
82 -  
83 - public void process(TbContext ctx, TbMsg msg,String deviceId) throws ExecutionException, InterruptedException {  
84 -  
85 - 91 + public void process(TbContext ctx, TbMsg msg, String deviceId) throws ExecutionException, InterruptedException {
86 92
87 93
88 - if( actions == null){ 94 + StringBuilder detail = new StringBuilder();
  95 + if (actions == null) {
89 ctx.tellSuccess(msg); 96 ctx.tellSuccess(msg);
90 } 97 }
91 98
92 boolean matched; 99 boolean matched;
93 - if(triggers == null || triggers.isEmpty()){ 100 + if (triggers == null || triggers.isEmpty()) {
94 matched = true; 101 matched = true;
95 - }else{ 102 + } else {
96 matched = false; 103 matched = false;
97 - for(TriggerDTO trigger: triggers){  
98 - TriggerState triggerState = getOrCreateTriggerState(trigger,deviceId);  
99 - matched = triggerState.process(ctx,msg);  
100 - if(matched){ 104 + for (TriggerDTO trigger : triggers) {
  105 + TriggerState triggerState = getOrCreateTriggerState(trigger, deviceId);
  106 + matched = triggerState.process(ctx, msg);
  107 + if (matched) {
  108 + detail.append(triggerState.getAlarmDetails());
101 break; 109 break;
102 } 110 }
103 } 111 }
104 } 112 }
105 113
106 114
107 - if(matched && conditions.size() >0 ){ 115 + if (matched && conditions.size() > 0) {
108 matched = false; 116 matched = false;
109 - for(DoCondition item:conditions){ 117 + for (DoCondition item : conditions) {
110 List<String> entityIds = item.getEntityId(); 118 List<String> entityIds = item.getEntityId();
111 - if(entityIds == null || entityIds.isEmpty()){ 119 + if (entityIds == null || entityIds.isEmpty()) {
112 matched = true; 120 matched = true;
113 break; 121 break;
114 } 122 }
115 - for(String id:entityIds){  
116 - TriggerState conditionState = getOrCreateConditionState(item.getId(),id,item.getTriggerCondition());  
117 - if( conditionState == null  
118 - || conditionState.process(ctx,msg)){ 123 + for (String id : entityIds) {
  124 + TriggerState conditionState = getOrCreateConditionState(item.getId(), id, item.getTriggerCondition());
  125 + if (conditionState == null
  126 + || conditionState.process(ctx, msg)) {
  127 + detail.append(";");
  128 + detail.append(conditionState.getAlarmDetails());
119 matched = true; 129 matched = true;
120 break; 130 break;
121 } 131 }
122 } 132 }
123 - if(matched){ 133 + if (matched) {
124 break; 134 break;
125 } 135 }
126 } 136 }
127 } 137 }
128 138
129 - if(matched){  
130 - for(DoAction item: actions){  
131 - pushMsg(ctx, msg, item); 139 + if (matched) {
  140 + for (DoAction item : actions) {
  141 + pushMsg(ctx, msg, item,detail.toString());
132 } 142 }
133 - }else{ 143 + } else {
134 ctx.tellSuccess(msg); 144 ctx.tellSuccess(msg);
135 } 145 }
136 146
137 } 147 }
138 148
139 149
140 -  
141 -  
142 -  
143 -  
144 - protected TriggerState getOrCreateTriggerState(TriggerDTO trigger,String deviceId) { 150 + protected TriggerState getOrCreateTriggerState(TriggerDTO trigger, String deviceId) {
145 String triggerId = trigger.getId(); 151 String triggerId = trigger.getId();
146 - String cacheKey =triggerId+deviceId;  
147 - if(triggerState.containsKey(cacheKey)){ 152 + String cacheKey = triggerId + deviceId;
  153 + if (triggerState.containsKey(cacheKey)) {
148 return triggerState.get(cacheKey); 154 return triggerState.get(cacheKey);
149 } 155 }
150 - if(trigger.getEntityId().contains(deviceId)){ 156 + if (trigger.getEntityId().contains(deviceId)) {
151 TriggerState state = createTriggerState(deviceId, trigger.getTriggerCondition()); 157 TriggerState state = createTriggerState(deviceId, trigger.getTriggerCondition());
152 triggerState.put(cacheKey, state); 158 triggerState.put(cacheKey, state);
153 return state; 159 return state;
@@ -157,13 +163,13 @@ class ReactState { @@ -157,13 +163,13 @@ class ReactState {
157 } 163 }
158 164
159 protected TriggerState getOrCreateConditionState(String conditionId, String deviceId, AlarmRule condition) { 165 protected TriggerState getOrCreateConditionState(String conditionId, String deviceId, AlarmRule condition) {
160 - String cacheKey =conditionId+deviceId;  
161 - if(conditionState.containsKey(cacheKey)){ 166 + String cacheKey = conditionId + deviceId;
  167 + if (conditionState.containsKey(cacheKey)) {
162 return conditionState.get(cacheKey); 168 return conditionState.get(cacheKey);
163 - }else{ 169 + } else {
164 TriggerState state = createTriggerState(deviceId, condition); 170 TriggerState state = createTriggerState(deviceId, condition);
165 conditionState.put(cacheKey, state); 171 conditionState.put(cacheKey, state);
166 - return state; 172 + return state;
167 } 173 }
168 174
169 } 175 }
@@ -171,51 +177,97 @@ class ReactState { @@ -171,51 +177,97 @@ class ReactState {
171 @NotNull 177 @NotNull
172 private TriggerState createTriggerState(String deviceId, AlarmRule rule) { 178 private TriggerState createTriggerState(String deviceId, AlarmRule rule) {
173 Set<AlarmConditionFilterKey> filterKeys = new HashSet<>(); 179 Set<AlarmConditionFilterKey> filterKeys = new HashSet<>();
174 - for(AlarmConditionFilter filter :rule.getCondition().getCondition()){ 180 + for (AlarmConditionFilter filter : rule.getCondition().getCondition()) {
175 filterKeys.add(filter.getKey()); 181 filterKeys.add(filter.getKey());
176 } 182 }
177 - TriggerState state = new TriggerState(deviceId,rule, filterKeys,null); 183 + TriggerState state = new TriggerState(deviceId, rule, filterKeys, rule.getAlarmDetails(),null);
178 184
179 - return state; 185 + return state;
180 } 186 }
181 187
182 - private void pushMsg(TbContext ctx, TbMsg msg, DoAction action) { 188 + private void pushMsg(TbContext ctx, TbMsg msg, DoAction action,String detail) {
183 TbMsgMetaData metaData = //lastMsgMetaData != null ? lastMsgMetaData.copy() : 189 TbMsgMetaData metaData = //lastMsgMetaData != null ? lastMsgMetaData.copy() :
184 new TbMsgMetaData(); 190 new TbMsgMetaData();
185 String relationType = ""; 191 String relationType = "";
186 TbMsg newMsg = null; 192 TbMsg newMsg = null;
187 - switch(action.getOutTarget()){ 193 + switch (action.getOutTarget()) {
188 case DEVICE_OUT: 194 case DEVICE_OUT:
189 - relationType = "RPC Request";  
190 - newMsg = rpcMsg(ctx,msg,action.getDoContext()); 195 + rpcMsg(ctx, msg, action.getDeviceId(), action.getDoContext());
191 break; 196 break;
192 case SCENE_ACT: 197 case SCENE_ACT:
193 - //TODO: 场景联动关联场景联动  
194 - relationType = "Alarm Updated"; 198 + reactMsg(ctx, msg, action);
195 break; 199 break;
196 case MSG_NOTIFY: 200 case MSG_NOTIFY:
197 - relationType = "Message"; 201 + noticeMsg(ctx, msg, action,detail);
198 break; 202 break;
199 default: 203 default:
200 ctx.tellSuccess(msg); 204 ctx.tellSuccess(msg);
201 break; 205 break;
202 } 206 }
  207 + }
203 208
204 - if(newMsg != null){  
205 - ctx.tellNext(newMsg, relationType); 209 + /**
  210 + * 设备输出
  211 + *
  212 + * @param ctx
  213 + * @param msg
  214 + * @param devices
  215 + * @param context
  216 + */
  217 + private void rpcMsg(TbContext ctx, TbMsg msg, List<String> devices, JsonNode context) {
  218 + String lastMsgQueueName = msg.getQueueName();
  219 + TbMsgMetaData metaData = msg.getMetaData();
  220 + for (String id : devices) {
  221 + TbMsg newMsg = ctx.newMsg(lastMsgQueueName != null ? lastMsgQueueName : ServiceQueue.MAIN
  222 + , msg.getType()
  223 + , msg.getOriginator()
  224 + , msg != null ? msg.getCustomerId() : null
  225 + , metaData
  226 + , JacksonUtil.toString(context));
  227 + ctx.tellNext(newMsg, "RPC Request");
206 } 228 }
207 } 229 }
208 230
209 - private TbMsg rpcMsg(TbContext ctx, TbMsg msg, JsonNode context){ 231 + /**
  232 + * 告警通知
  233 + *
  234 + * @param ctx
  235 + * @param msg
  236 + * @param action
  237 + */
  238 + private void noticeMsg(TbContext ctx, TbMsg msg, DoAction action,String detail) {
  239 + Alarm alarm = JacksonUtil.convertValue(msg.getData(), Alarm.class);
  240 + String tenantId = alarm.getTenantId().getId().toString();
  241 + String deviceId = alarm.getOriginator().getId().toString();
  242 + String severity = alarm.getSeverity().name();
  243 + ActionAlarmDTO actionAlarm = JacksonUtil.convertValue(action.getDoContext(),ActionAlarmDTO.class);
  244 +
  245 +
  246 + AlarmInfoDTO formData = new AlarmInfoDTO();
  247 + formData.setDeviceName(msg.getMetaData().getData().get("deviceName"));
  248 + formData.setDetails(detail);
  249 + formData.setType(alarm.getType());
  250 + formData.setCreateTs(alarm.getCreatedTime());
  251 + formData.setStartTs(alarm.getStartTs());
  252 + formData.setEndTs(alarm.getEndTs());
  253 + formData.setStatus(alarm.getStatus().name());
  254 + formData.setDeviceId(deviceId);
  255 + formData.setTenantId(tenantId);
  256 + formData.setSeverity(actionAlarm.getAlarmLevel().name());
  257 + noticeService.alert(action.getAlarmProfileId(),formData);
  258 + }
  259 +
  260 + private void reactMsg(TbContext ctx, TbMsg msg, DoAction action) {
  261 + //TODO: 场景联动关联消息通知
210 String lastMsgQueueName = msg.getQueueName(); 262 String lastMsgQueueName = msg.getQueueName();
211 TbMsgMetaData metaData = msg.getMetaData(); 263 TbMsgMetaData metaData = msg.getMetaData();
212 - metaData.putValue(DataConstants.IS_CLEARED_ALARM, Boolean.TRUE.toString()); 264 + metaData.putValue(DataConstants.IS_CLEARED_ALARM, Boolean.TRUE.toString());
213 TbMsg newMsg = ctx.newMsg(lastMsgQueueName != null ? lastMsgQueueName : ServiceQueue.MAIN 265 TbMsg newMsg = ctx.newMsg(lastMsgQueueName != null ? lastMsgQueueName : ServiceQueue.MAIN
214 , msg.getType() 266 , msg.getType()
215 , msg.getOriginator() 267 , msg.getOriginator()
216 , msg != null ? msg.getCustomerId() : null 268 , msg != null ? msg.getCustomerId() : null
217 , metaData 269 , metaData
218 - , JacksonUtil.toString(context));  
219 - return newMsg; 270 + , JacksonUtil.toString(action.getDoContext()));
  271 + ctx.tellNext(newMsg, "Message");
220 } 272 }
221 } 273 }
@@ -72,13 +72,15 @@ class TriggerState { @@ -72,13 +72,15 @@ class TriggerState {
72 private DataSnapshot latestValues; 72 private DataSnapshot latestValues;
73 73
74 private final Set<AlarmConditionFilterKey> entityKeys; 74 private final Set<AlarmConditionFilterKey> entityKeys;
  75 + private final String alarmDetails;
75 76
76 - TriggerState( String originator, AlarmRule rule,Set<AlarmConditionFilterKey> filterKeys,DynamicPredicateValueCtx dynamicPredicateValueCtx) { 77 + TriggerState(String originator, AlarmRule rule, Set<AlarmConditionFilterKey> filterKeys, String alarmDetails, DynamicPredicateValueCtx dynamicPredicateValueCtx) {
77 78
78 this.originator = originator; 79 this.originator = originator;
79 this.dynamicPredicateValueCtx = dynamicPredicateValueCtx; 80 this.dynamicPredicateValueCtx = dynamicPredicateValueCtx;
80 - ruleState = new TriggerRuleState(rule.getCondition(), filterKeys, new PersistedAlarmRuleState(),rule.getSchedule()); 81 + ruleState = new TriggerRuleState(rule.getCondition(), filterKeys, new PersistedAlarmRuleState(), rule.getSchedule());
81 this.entityKeys = filterKeys; 82 this.entityKeys = filterKeys;
  83 + this.alarmDetails = alarmDetails;
82 } 84 }
83 85
84 86
@@ -88,10 +90,10 @@ class TriggerState { @@ -88,10 +90,10 @@ class TriggerState {
88 } 90 }
89 lastMsgMetaData = msg.getMetaData(); 91 lastMsgMetaData = msg.getMetaData();
90 SnapshotUpdate update = null; 92 SnapshotUpdate update = null;
91 - if(msg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name())){  
92 - update = processTelemetry(ctx,msg);  
93 - }else{  
94 - update = processAttributes(ctx,msg); 93 + if (msg.getType().equals(SessionMsgType.POST_TELEMETRY_REQUEST.name())) {
  94 + update = processTelemetry(ctx, msg);
  95 + } else {
  96 + update = processAttributes(ctx, msg);
95 } 97 }
96 98
97 if (update != null && update.hasUpdate()) { 99 if (update != null && update.hasUpdate()) {
@@ -101,7 +103,6 @@ class TriggerState { @@ -101,7 +103,6 @@ class TriggerState {
101 } 103 }
102 104
103 105
104 -  
105 public boolean process(TbContext ctx, long ts) throws ExecutionException, InterruptedException { 106 public boolean process(TbContext ctx, long ts) throws ExecutionException, InterruptedException {
106 return createOrClearAlarms(ctx, null, ts, null, (alarmState, tsParam) -> alarmState.eval(tsParam, latestValues)); 107 return createOrClearAlarms(ctx, null, ts, null, (alarmState, tsParam) -> alarmState.eval(tsParam, latestValues));
107 } 108 }
@@ -142,8 +143,6 @@ class TriggerState { @@ -142,8 +143,6 @@ class TriggerState {
142 } 143 }
143 144
144 145
145 -  
146 -  
147 protected void setAlarmConditionMetadata(TriggerRuleState ruleState, TbMsgMetaData metaData) { 146 protected void setAlarmConditionMetadata(TriggerRuleState ruleState, TbMsgMetaData metaData) {
148 if (ruleState.getSpec().getType() == AlarmConditionSpecType.REPEATING) { 147 if (ruleState.getSpec().getType() == AlarmConditionSpecType.REPEATING) {
149 metaData.putValue(DataConstants.ALARM_CONDITION_REPEATS, String.valueOf(ruleState.getState().getEventCount())); 148 metaData.putValue(DataConstants.ALARM_CONDITION_REPEATS, String.valueOf(ruleState.getState().getEventCount()));
@@ -154,9 +153,6 @@ class TriggerState { @@ -154,9 +153,6 @@ class TriggerState {
154 } 153 }
155 154
156 155
157 -  
158 -  
159 -  
160 public void processAckAlarm(Alarm alarm) { 156 public void processAckAlarm(Alarm alarm) {
161 if (currentAlarm != null && currentAlarm.getId().equals(alarm.getId())) { 157 if (currentAlarm != null && currentAlarm.getId().equals(alarm.getId())) {
162 currentAlarm.setStatus(alarm.getStatus()); 158 currentAlarm.setStatus(alarm.getStatus());
@@ -165,16 +161,6 @@ class TriggerState { @@ -165,16 +161,6 @@ class TriggerState {
165 } 161 }
166 162
167 163
168 -  
169 -  
170 -  
171 -  
172 -  
173 -  
174 -  
175 -  
176 -  
177 -  
178 protected SnapshotUpdate processAttributes(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException { 164 protected SnapshotUpdate processAttributes(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException {
179 Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())); 165 Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData()));
180 if (!attributes.isEmpty()) { 166 if (!attributes.isEmpty()) {
@@ -188,14 +174,13 @@ class TriggerState { @@ -188,14 +174,13 @@ class TriggerState {
188 for (Map.Entry<Long, List<KvEntry>> entry : tsKvMap.entrySet()) { 174 for (Map.Entry<Long, List<KvEntry>> entry : tsKvMap.entrySet()) {
189 Long ts = entry.getKey(); 175 Long ts = entry.getKey();
190 List<KvEntry> data = entry.getValue(); 176 List<KvEntry> data = entry.getValue();
191 - return merge( ts, data); 177 + return merge(ts, data);
192 } 178 }
193 179
194 return null; 180 return null;
195 } 181 }
196 182
197 183
198 -  
199 private DataSnapshot fetchLatestValues(TbContext ctx, String originator) throws ExecutionException, InterruptedException { 184 private DataSnapshot fetchLatestValues(TbContext ctx, String originator) throws ExecutionException, InterruptedException {
200 DataSnapshot result = new DataSnapshot(entityKeys); 185 DataSnapshot result = new DataSnapshot(entityKeys);
201 addEntityKeysToSnapshot(ctx, originator, result); 186 addEntityKeysToSnapshot(ctx, originator, result);
@@ -254,6 +239,7 @@ class TriggerState { @@ -254,6 +239,7 @@ class TriggerState {
254 addToSnapshot(result, ctx.getAttributesService().find(ctx.getTenantId(), new DeviceId(UUID.fromString(originator)), DataConstants.SERVER_SCOPE, attributeKeys).get()); 239 addToSnapshot(result, ctx.getAttributesService().find(ctx.getTenantId(), new DeviceId(UUID.fromString(originator)), DataConstants.SERVER_SCOPE, attributeKeys).get());
255 } 240 }
256 } 241 }
  242 +
257 private void addToSnapshot(DataSnapshot snapshot, List<AttributeKvEntry> data) { 243 private void addToSnapshot(DataSnapshot snapshot, List<AttributeKvEntry> data) {
258 for (AttributeKvEntry entry : data) { 244 for (AttributeKvEntry entry : data) {
259 if (entry.getValue() != null) { 245 if (entry.getValue() != null) {
@@ -262,6 +248,7 @@ class TriggerState { @@ -262,6 +248,7 @@ class TriggerState {
262 } 248 }
263 } 249 }
264 } 250 }
  251 +
265 public static EntityKeyValue toEntityValue(KvEntry entry) { 252 public static EntityKeyValue toEntityValue(KvEntry entry) {
266 switch (entry.getDataType()) { 253 switch (entry.getDataType()) {
267 case STRING: 254 case STRING:
@@ -278,7 +265,8 @@ class TriggerState { @@ -278,7 +265,8 @@ class TriggerState {
278 throw new RuntimeException("Can't parse entry: " + entry.getDataType()); 265 throw new RuntimeException("Can't parse entry: " + entry.getDataType());
279 } 266 }
280 } 267 }
281 - private SnapshotUpdate merge( Long newTs, List<KvEntry> data) { 268 +
  269 + private SnapshotUpdate merge(Long newTs, List<KvEntry> data) {
282 Set<AlarmConditionFilterKey> keys = new HashSet<>(); 270 Set<AlarmConditionFilterKey> keys = new HashSet<>();
283 for (KvEntry entry : data) { 271 for (KvEntry entry : data) {
284 AlarmConditionFilterKey entityKey = new AlarmConditionFilterKey(AlarmConditionKeyType.TIME_SERIES, entry.getKey()); 272 AlarmConditionFilterKey entityKey = new AlarmConditionFilterKey(AlarmConditionKeyType.TIME_SERIES, entry.getKey());