Commit b4179664 authored by dawnwinterLiu's avatar dawnwinterLiu
Browse files

feat: 告警触发短信发送

Showing with 409 additions and 157 deletions
+409 -157
......@@ -116,25 +116,12 @@ handle_message({rule, #{clientid := _DevAddr, disconnected_at := _DisconnectedAt
%% SELECT payload.electricity as electricity FROM "$dg/user/alarm/94656917ab/157d0ff60f/#" where electricity > 20
handle_message({rule, #{metadata := #{rule_id := <<"rule:Notification_", Ruleid/binary>>}, clientid := DeviceId, payload := _Payload, topic := _Topic} = _Msg, Context}, State) ->
dgiot_umeng:add_notification(Ruleid, DeviceId, Context),
case dgiot_parse:get_object(<<"_Role">>, application:get_env(dgiot_http, tencent_sms_sign, "ae746ee803")) of
{ok, #{<<"objectId">> := RolesId}} ->
%循环得到部门下所有的手机号
Users = dgiot_parse_auth:get_UserIds(unicode:characters_to_binary(RolesId)),
UsersQuery = #{<<"where">> => #{<<"objectId">> => #{<<"$in">> => Users}}},
{ok, #{<<"results">> := Row}} = dgiot_parse:query_object(<<"_User">>, UsersQuery),
Params = lists:foldl(fun(X, Acc) ->
Acc ++ [X ++ ":" ++ DeviceId]
end, [], application:get_env(dgiot_http, tencent_sms_params, ["aaa", "bbb", "ccc", "ddd", "eee", "fff"])),
lists:foldl(fun(X, Acc) ->
Phone = unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>, X))),
dgiot_notification:send_sms(Phone, <<"TplId">>, Params),
Acc ++ [unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>, X)))]
end, [], Row);
% 模板格式:时间:{1} {2}(发起人:{3})(单据编号{4})(车间:{5})产生异常,警告等级为:{6}。
_ ->
pass
end,
NewContext =
maps:fold(fun(Key, Value, Acc) ->
Acc#{<<"dgiot_alarmkey">> => Key, <<"dgiot_alarmvalue">> => Value}
end, #{}, Context),
Content = dgiot_umeng:add_notification(Ruleid, DeviceId, NewContext),
dgiot_umeng:send_msg(Content),
{ok, State};
handle_message({sync_parse, Pid, 'after', get, _Token, <<"Notification">>, #{<<"results">> := _Results} = ResBody}, State) ->
......
......@@ -58,7 +58,7 @@ put('after', #{<<"channel">> := Channel, <<"objectId">> := ProductId}) ->
TdchannelId = maps:get(<<"tdchannel">>, Channel, <<"">>),
TaskchannelId = maps:get(<<"taskchannel">>, Channel, <<"">>),
Otherchannel = maps:get(<<"otherchannel">>, Channel, []),
dgiot_product:add_product_relation(Otherchannel ++ [TdchannelId] ++ [TaskchannelId], ProductId);
dgiot_product:add_product_relation(lists:flatten([Otherchannel]) ++ [TdchannelId] ++ [TaskchannelId], ProductId);
put(_, _) ->
pass.
......
{
"type": "page",
"body": [
{
"id": "u:2c72c2d76916",
"api": {
"url": "iotapi/sendsms/parse_objectid",
"data": {
"tplid": "${tplid}",
"params": [
"${updatedAt}",
"${product_name}",
"${name}",
"${devaddr}",
"${alarm_level}",
"${alarm_message}"
]
},
"method": "post",
"headers": {
"store": "localStorage",
"dgiotReplace": "parse_objectid"
},
"dataType": "json",
"requestAdaptor": "console.log('ffds ', ...api.data)\r\nreturn {\r\n ...api,\r\n data: {\r\n tplid: ...api.data.tplid\r\n }\r\n}"
},
"body": [
{
"hint": "1519757",
"name": "tplid",
"type": "input-text",
"label": "模板编号",
"value": "1519757",
"visible": false,
"disabled": "",
"readOnly": true,
"visibleOn": "",
"clearValueOnHidden": false
},
{
"mode": "horizontal",
"name": "alarm_createdAt",
"size": "md",
"type": "input-datetime",
"label": "告警时间",
"value": "now",
"format": "YYYY-MM-DD HH:mm:ss",
"maxDate": "",
"minDate": "",
"clearable": false,
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "sm"
},
"placeholder": "请选择日期时间",
"validateApi": ""
},
{
"id": "u:55d89cd2eb42",
"api": "",
"body": [
{
"hint": "",
"mode": "horizontal",
"name": "product_name",
"size": "md",
"type": "input-text",
"label": "产品名称",
"inline": false,
"readOnly": true,
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "sm"
},
"submitOnChange": false
}
],
"mode": "inline",
"type": "form",
"title": "",
"target": "alarm_form",
"initApi": {
"url": "iotapi/classes/Product/${_productid}",
"data": null,
"method": "get",
"adaptor": "return {\r\n \"status\":0,\r\n \"msg\":\"\",\r\n \"data\":response.data\r\n }",
"responseData": {
"product_name": "${name}"
},
"requestAdaptor": ""
},
"className": "m-t-lg m-b-lg",
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "normal"
},
"submitText": "",
"wrapWithPanel": false
},
{
"id": "u:55d89cd2eb42",
"api": "",
"body": [
{
"hint": "",
"mode": "horizontal",
"name": "name",
"size": "md",
"type": "input-text",
"label": "设备名称",
"inline": false,
"readOnly": true,
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "sm"
}
},
{
"id": "u:a656b5747025",
"hint": "",
"mode": "horizontal",
"name": "devaddr",
"size": "md",
"type": "input-text",
"label": "设备地址",
"inline": false,
"readOnly": true,
"horizontal": {
"left": 1,
"right": 11,
"leftFixed": "sm"
}
}
],
"mode": "normal",
"type": "form",
"title": "",
"target": "alarm_form",
"initApi": {
"url": "iotapi/classes/Device/${_deviceid}",
"data": null,
"method": "get",
"adaptor": "return {\r\n \"status\":0,\r\n \"msg\":\"\",\r\n \"data\":response.data\r\n }",
"responseData": {
"name": "${name}",
"devaddr": "${devaddr}"
},
"requestAdaptor": ""
},
"className": "m-b-lg",
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "normal"
},
"submitText": "",
"wrapWithPanel": false
},
{
"id": "u:b5d871f9d40f",
"mode": "horizontal",
"name": "alarm_level",
"size": "md",
"type": "input-text",
"label": "告警等级",
"value": "二级告警(自行填写)",
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "sm"
}
},
{
"id": "u:2739169db893",
"mode": "horizontal",
"name": "alarm_message",
"size": "md",
"type": "input-text",
"label": "告警信息",
"value": "温度过高(自行填写)",
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "sm"
}
},
{
"id": "u:cdfa428176ab",
"hint": "字段名改为物模型标识符",
"mode": "horizontal",
"name": "dgiot_alarmvalue",
"size": "md",
"type": "input-text",
"label": "告警值",
"readOnly": true,
"horizontal": {
"left": 2,
"right": 10,
"leftFixed": "sm"
}
}
],
"name": "alarm_form",
"type": "form",
"rules": [
],
"title": "",
"initApi": "",
"submitText": ""
}
],
"style": {
},
"initApi": {
"url": "/iotapi/classes/Notification/parse_notificationid",
"method": "get",
"adaptor": "return {\r\n \"status\":0,\r\n \"msg\":\"\",\r\n \"data\":response.data.content\r\n }",
"headers": {
"store": "localStorage",
"dgiotReplace": "parse_notificationid"
},
"dataType": "json"
},
"messages": {
},
"initFetch": true
}
......@@ -30,12 +30,14 @@
test_customizedcast/0,
add_notification/3,
save_devicestatus/2,
save_notification/3,
save_notification/4,
update_notification/2,
sendSubscribe/3,
create_maintenance/2,
get_operations/0,
send_message_to3D/3,
triggeralarm/1
triggeralarm/1,
send_msg/1
]).
test_broadcast() ->
......@@ -189,147 +191,78 @@ post_notification(Notification) ->
}).
add_notification(<<"start_", Ruleid/binary>>, DeviceId, Payload) ->
case dgiot_data:get(?NOTIFICATION, {DeviceId, Ruleid}) of
{start, _Time} ->
pass;
_ ->
save_notification(Ruleid, DeviceId, Payload#{<<"alertstatus">> => true})
end,
dgiot_data:insert(?NOTIFICATION, {DeviceId, Ruleid}, {start, dgiot_datetime:now_secs()});
NotificationId = dgiot_parse_id:get_notificationid(Ruleid),
Result =
case dgiot_data:get(dgiot_notification, {DeviceId, Ruleid}) of
{start, _Time, _} ->
<<>>;
_ ->
save_notification(Ruleid, DeviceId, Payload, NotificationId)
end,
dgiot_data:insert(?NOTIFICATION, {DeviceId, Ruleid}, {start, dgiot_datetime:now_secs(), NotificationId}),
Result;
add_notification(<<"stop_", Ruleid/binary>>, DeviceId, Payload) ->
case dgiot_data:get(?NOTIFICATION, {DeviceId, Ruleid}) of
{start, _Time} ->
save_notification(Ruleid, DeviceId, Payload#{<<"alertstatus">> => false});
_ ->
pass
end,
dgiot_data:insert(?NOTIFICATION, {DeviceId, Ruleid}, {stop, dgiot_datetime:now_secs()});
Result =
case dgiot_data:get(?NOTIFICATION, {DeviceId, Ruleid}) of
{start, _Time, NotificationId} ->
update_notification(NotificationId, Payload);
_ ->
<<>>
end,
dgiot_data:insert(?NOTIFICATION, {DeviceId, Ruleid}, {stop, dgiot_datetime:now_secs(), <<>>}),
Result;
add_notification(Ruleid, _DevAddr, _Payload) ->
?LOG(error, "Ruleid ~p", [Ruleid]),
ok.
save_notification(Ruleid, DeviceId, Payload) ->
save_notification(Ruleid, DeviceId, Payload, NotificationId) ->
Alarm_createdAt = dgiot_datetime:format("YYYY-MM-DD HH:NN:SS"),
case binary:split(Ruleid, <<$_>>, [global, trim]) of
[ProductId, ViewId] ->
case dgiot_device:lookup(DeviceId) of
{ok, #{<<"acl">> := Acl}} ->
Requests =
{ok, #{<<"acl">> := Acls}} ->
Acl =
lists:foldl(fun(X, Acc) ->
BinX = atom_to_binary(X),
case BinX of
<<"role:", Name/binary>> ->
%% RoleId = dgiot_parse_id:get_roleid(<<"dgiot">>),
case dgiot_parse:query_object(<<"_Role">>, #{<<"order">> => <<"updatedAt">>, <<"limit">> => 1,
<<"where">> => #{<<"name">> => Name}}) of
{ok, #{<<"results">> := [Role]}} ->
#{<<"objectId">> := RoleId} = Role,
UserIds = dgiot_parse_id:get_userids(RoleId),
lists:foldl(fun(UserId, Acc1) ->
ObjectId = dgiot_parse_id:get_notificationid(Ruleid),
Content = Payload#{<<"_deviceid">> => DeviceId, <<"_productid">> => ProductId, <<"_viewid">> => ViewId},
%% sendSubscribe(Ruleid, Content, UserId),
Acc1 ++ [#{
<<"method">> => <<"POST">>,
<<"path">> => <<"/classes/Notification">>,
<<"body">> => #{
<<"objectId">> => ObjectId,
<<"ACL">> => #{
UserId => #{
<<"read">> => true,
<<"write">> => true
}
},
<<"content">> => Content,
<<"public">> => false,
<<"status">> => 0,
<<"sender">> => #{
<<"__type">> => <<"Pointer">>,
<<"className">> => <<"_User">>,
<<"objectId">> => <<"Klht7ERlYn">>
},
<<"process">> => <<"">>,
<<"type">> => Ruleid,
<<"user">> => #{
<<"__type">> => <<"Pointer">>,
<<"className">> => <<"_User">>,
<<"objectId">> => UserId
}
}
}]
end, Acc, UserIds);
_ ->
Acc
end;
<<"*">> ->
ObjectId = dgiot_parse_id:get_notificationid(Ruleid),
Acc ++ [#{
<<"method">> => <<"POST">>,
<<"path">> => <<"/classes/Notification">>,
<<"body">> => #{
<<"objectId">> => ObjectId,
<<"ACL">> => #{
<<"*">> => #{
<<"read">> => true,
<<"write">> => true
}
},
<<"content">> => Payload#{<<"_deviceid">> => DeviceId, <<"_productid">> => ProductId, <<"_viewid">> => ViewId},
<<"public">> => false,
<<"status">> => 0,
<<"sender">> => #{
<<"__type">> => <<"Pointer">>,
<<"className">> => <<"_User">>,
<<"objectId">> => <<"Klht7ERlYn">>
},
<<"type">> => Ruleid,
<<"user">> => #{
<<"__type">> => <<"Pointer">>,
<<"className">> => <<"_User">>,
<<"objectId">> => <<"">>
}
}
}];
UserId ->
ObjectId = dgiot_parse_id:get_notificationid(Ruleid),
Content = Payload#{<<"_deviceid">> => DeviceId, <<"_productid">> => ProductId, <<"_viewid">> => ViewId},
%% sendSubscribe(Ruleid, Content, UserId),
Acc ++ [#{
<<"method">> => <<"POST">>,
<<"path">> => <<"/classes/Notification">>,
<<"body">> => #{
<<"objectId">> => ObjectId,
<<"ACL">> => #{
UserId => #{
<<"read">> => true,
<<"write">> => true
}
},
<<"content">> => Content,
<<"public">> => false,
<<"status">> => 0,
<<"sender">> => #{
<<"__type">> => <<"Pointer">>,
<<"className">> => <<"_User">>,
<<"objectId">> => <<"Klht7ERlYn">>
},
<<"type">> => Ruleid,
<<"user">> => #{
<<"__type">> => <<"Pointer">>,
<<"className">> => <<"_User">>,
<<"objectId">> => UserId
}
}
}]
end
end, [], Acl),
dgiot_parse:batch(Requests);
Acc#{
dgiot_utils:to_binary(X) => #{
<<"read">> => true,
<<"write">> => true
}}
end, #{}, Acls),
Content = Payload#{<<"alarm_createdAt">> => Alarm_createdAt, <<"_deviceid">> => DeviceId, <<"_productid">> => ProductId, <<"_viewid">> => ViewId},
dgiot_parse:create_object(<<"Notification">>, #{
<<"objectId">> => NotificationId,
<<"ACL">> => Acl,
<<"content">> => Content,
<<"public">> => false,
<<"status">> => 0,
<<"process">> => <<"">>,
<<"type">> => Ruleid
}),
Content#{<<"send_alarm_status">> => <<"start">>};
_ ->
pass
<<>>
end;
_ ->
pass
<<>>
end.
%% 0 未确认 1 误报 2 手动恢复 3 自动恢复
update_notification(NotificationId, Payload) ->
case dgiot_parse:get_object(<<"Notification">>, NotificationId) of
{ok, #{<<"content">> := Content}} ->
NewContent = maps:merge(Content, Payload),
dgiot_parse:update_object(<<"Notification">>, NotificationId, #{
<<"public">> => true,
<<"status">> => 3,
<<"content">> => NewContent,
<<"process">> => <<"自动恢复"/utf8>>
}),
NewContent#{<<"send_alarm_status">> => <<"stop">>};
_ ->
<<>>
end.
sendSubscribe(Type, Content, UserId) ->
......@@ -736,14 +669,115 @@ triggeralarm(DeviceId) ->
end.
%% 触发
send_msg(#{<<"send_alarm_status">> := <<"start">>, <<"alarm_createdAt">> := Alarm_createdAt, <<"_deviceid">> := DeviceId, <<"_productid">> := ProductId, <<"dgiot_alarmkey">> := Key, <<"dgiot_alarmvalue">> := Value}) ->
case dgiot_parse:get_object(<<"Product">>, ProductId) of
{ok, #{<<"name">> := ProductName, <<"content">> := #{<<"sms">> := #{<<"params">> := Params, <<"tplid">> := TplId} = Sms}}} when is_list(Params) ->
NewParams =
lists:foldl(fun(Param, Acc) ->
Acc ++ [replace_param(Param, ProductName, ProductId, DeviceId, Key, Value, Alarm_createdAt, <<"触发"/utf8>>)]
end, [], Params),
Mobile =
case maps:find(<<"users">>, Sms) of
{ok, Users} ->
UsersQuery = #{<<"where">> => #{<<"objectId">> => #{<<"$in">> => Users}}},
case dgiot_parse:query_object(<<"_User">>, UsersQuery) of
{ok, #{<<"results">> := Row}} ->
lists:foldl(fun(User, Acc) ->
Phone = maps:get(<<"phone">>, User, ""),
case dgiot_utils:is_phone(Phone) of
true ->
Acc ++ [#{<<"mobile">> => Phone, <<"nationcode">> => <<"86">>}];
_ ->
Acc
end
end, [], Row);
_ ->
dgiot_notification:get_Mobile(DeviceId)
end;
_ ->
dgiot_notification:get_Mobile(DeviceId)
end,
dgiot_notification:send_sms(Mobile, TplId, NewParams);
_ ->
pass
end;
%% 恢复
send_msg(#{<<"send_alarm_status">> := <<"stop">>, <<"alarm_createdAt">> := Alarm_createdAt, <<"_deviceid">> := DeviceId, <<"_productid">> := ProductId, <<"dgiot_alarmkey">> := Key, <<"dgiot_alarmvalue">> := Value}) ->
case dgiot_parse:get_object(<<"Product">>, ProductId) of
{ok, #{<<"name">> := ProductName, <<"content">> := #{<<"sms">> := #{<<"params">> := Params, <<"tplid">> := TplId} = Sms}}} when is_list(Params) ->
NewParams =
lists:foldl(fun(Param, Acc) ->
Acc ++ [replace_param(Param, ProductName, ProductId, DeviceId, Key, Value, Alarm_createdAt, <<"恢复"/utf8>>)]
end, [], Params),
Mobile =
case maps:find(<<"users">>, Sms) of
{ok, Users} ->
UsersQuery = #{<<"where">> => #{<<"objectId">> => #{<<"$in">> => Users}}},
case dgiot_parse:query_object(<<"_User">>, UsersQuery) of
{ok, #{<<"results">> := Row}} ->
lists:foldl(fun(User, Acc) ->
Phone = maps:get(<<"phone">>, User, ""),
case dgiot_utils:is_phone(Phone) of
true ->
Acc ++ [#{<<"mobile">> => Phone, <<"nationcode">> => <<"86">>}];
_ ->
Acc
end
end, [], Row);
_ ->
dgiot_notification:get_Mobile(DeviceId)
end;
_ ->
dgiot_notification:get_Mobile(DeviceId)
end,
dgiot_notification:send_sms(Mobile, TplId, NewParams);
_ ->
pass
end;
send_msg(_) ->
pass.
%% 产品名称:%PRODUCTNAME%
%% 设备名称:%DEVICENAME%
%% 设备地址:%DEVICEADDR%
%% 日期:%DATE%
%% 时间:%DATETIME%
%% 用户名称:%USERNAME%
%% 报警时间:%TRIGGERTIME%
%% 变量名称:%DATAPOINTNAME%
%% 当前值:%NOWVALUE%
%% 触发描述:%TRIGGERDESCRIPTION%
replace_param(Param, ProductName, ProductId, DeviceId, Key, Value, Alarm_createdAt, TriggerdeScription) ->
Date = dgiot_datetime:format("YYYY-MM-DD"),
DateTime = dgiot_datetime:format("YYYY-MM-DD HH:NN:SS"),
{DeviceName, DeviceAddr} =
case dgiot_parse:get_object(<<"Device">>, DeviceId) of
{ok, #{<<"name">> := Name, <<"devaddr">> := Devaddr}} ->
{Name, Devaddr};
_ ->
{<<"--">>, <<"--">>}
end,
DataPointname =
case dgiot_data:get({product, <<ProductId/binary, Key/binary>>}) of
not_find ->
<<"--">>;
{ThingName, _, _} ->
ThingName
end,
Str1 = re:replace(Param, "%PRODUCTNAME%", ProductName, [global, {return, list}]),
Str2 = re:replace(Str1, "%DEVICENAME%", DeviceName, [global, {return, list}]),
Str3 = re:replace(Str2, "%DEVICEADDR%", DeviceAddr, [global, {return, list}]),
Str4 = re:replace(Str3, "%DATE%", Date, [global, {return, list}]),
Str4 = re:replace(Str3, "%DATETIME%", DateTime, [global, {return, list}]),
Str5 = re:replace(Str4, "%USERNAME%", <<"admin">>, [global, {return, list}]),
Str6 = re:replace(Str5, "%TRIGGERTIME%", Alarm_createdAt, [global, {return, list}]),
Str7 = re:replace(Str6, "%DATAPOINTNAME%", DataPointname, [global, {return, list}]),
Str8 = re:replace(Str7, "%TRIGGERDESCRIPTION%", TriggerdeScription, [global, {return, list}]),
re:replace(Str8, "%NOWVALUE%", dgiot_utils:to_list(Value), [global, {return, binary}]).
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment