feat: 短信告警

This commit is contained in:
dawnwinterLiu 2022-08-18 10:15:16 +08:00
parent 5f62485c93
commit 1abf585f99
7 changed files with 365 additions and 42 deletions

View File

@ -116,6 +116,24 @@ 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,Params),
Acc ++ [unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>,X)))]
end,[],Row);
% {1} {2}{3}{4}{5},:{6}
_ ->
pass
end,
{ok, State};
handle_message({sync_parse, Pid, 'after', get, _Token, <<"Notification">>, #{<<"results">> := _Results} = ResBody}, State) ->

View File

@ -13,7 +13,7 @@ aliyun.uploadCallbackUrl= http://127.0.0.1:8081
aliyun.uploadHost= http://dgiotpump.oss-cn-shanghai.aliyuncs.com
#百度地图
baidumap.appkey = S7pehghn5BdQeSGZAcpEk4bLQSQ8czvi
baidumap.appkey = WpeAb6pL4tsX2ZVd56GHbO9Ut6c4HZhG
#百度地图纠偏值
baidumap.lngoffset = 0.00000
baidumap.latoffset = 0.00000
@ -28,10 +28,10 @@ wechat.appid = wxb37f3990d2424ea0
wechat.secret = 0c8b9e229ebe48c6878727a9d2e0263d
#腾讯云短信
tencent_sms.appid = 1400214975
tencent_sms.appkey = 25c8c3a4d17367a8232931ff54d114a2
tencent_sms.tmplid = 340847
tencent_sms.sign = dgiot
tencent_sms.appid = 1400635630
tencent_sms.appkey = 40d9609b9e6212cbff051b4f1d4cabfc
tencent_sms.notification.templateId = 1473069
tencent_sms.sign = ae746ee803
# jwt
jwt.algorithm = rs256

View File

@ -28,27 +28,25 @@
%%--------------------------------------------------------------------
{mapping, "tencent_sms.appid", "dgiot_http.tencent_sms_appid", [
{default, "1400214975"},
{default, "1400635630"},
{datatype, string}
]}.
{mapping, "tencent_sms.appkey", "dgiot_http.tencent_sms_appkey", [
{default, "25c8c3a4d17367a8232931ff54d114a2"},
{default, "40d9609b9e6212cbff051b4f1d4cabfc"},
{datatype, string}
]}.
{mapping, "tencent_sms.tmplid", "dgiot_http.tencent_sms_tmplid", [
{default, "340847"},
{mapping, "tencent_sms.notification.templateId", "dgiot_http.tencent_sms_notification_templateId", [
{default, "1473069"},
{datatype, string}
]}.
{mapping, "tencent_sms.sign", "dgiot_http.tencent_sms_sign", [
{default, "dgiot"},
{default, "ae746ee803"},
{datatype, string}
]}.
%%--------------------------------------------------------------------
%% 百度地图配置
%%--------------------------------------------------------------------

View File

@ -8,6 +8,166 @@
"definitions": {
},
"paths": {
"/handlewarnsendsms": {
"post": {
"security": [],
"summary": "短信配置发送",
"description": "短信配置发送",
"consumes": [
"application/json"
],
"parameters": [
{
"in": "body",
"name": "user",
"required": true,
"schema": {
"type": "object",
"properties": {
"appId": {
"required": true,
"type": "string",
"example": "1400635630"
},
"appKey": {
"required": true,
"type": "string",
"example": "40d9609b9e6212cbff051b4f1d4cabfc"
},
"tplId": {
"required": true,
"type": "string",
"example": "1473069"
},
"sign": {
"required": true,
"type": "string",
"example": "ae746ee803"
},
"params": {
"required": true,
"type": "object",
"example": ["测试1","测试2","测试3","测试4","测试5","测试6"]
}
}
}
}
],
"responses": {
"200": {
"description": "Returns success"
},
"400": {
"description": "Bad Request"
},
"404": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/Error"
}
},
"500": {
"description": "Server Internal error",
"schema": {
"$ref": "#/definitions/Error"
}
}
},
"tags": [
"Notification"
]
}
},
"/warnsendsms": {
"post": {
"security": [],
"summary": "短信告警发送",
"description": "短信告警发送",
"consumes": [
"application/json"
],
"parameters": [
{
"in": "body",
"name": "user",
"required": true,
"schema": {
"type": "object",
"properties": {
"objectId": {
"required": true,
"type": "string",
"example": "dasssd54"
},
"branchId": {
"required": true,
"type": "string",
"example": "9256b5cf2e"
},
"docnumber": {
"required": true,
"type": "string",
"example": "MO000015"
},
"datetimes": {
"required": true,
"type": "string",
"example": "2022-12-15,14:20"
},
"username": {
"required": true,
"type": "string",
"example": "张三"
},
"workshop": {
"required": true,
"type": "string",
"example": "车间1-1"
},
"level": {
"required": true,
"type": "string",
"example": "1"
},
"desc": {
"required": true,
"type": "string",
"example": "desc"
},
"file": {
"required": true,
"type": "string",
"example": "img"
}
}
}
}
],
"responses": {
"200": {
"description": "Returns success"
},
"400": {
"description": "Bad Request"
},
"404": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/Error"
}
},
"500": {
"description": "Server Internal error",
"schema": {
"$ref": "#/definitions/Error"
}
}
},
"tags": [
"Notification"
]
}
},
"/wechat": {
"get": {
"security": [],
@ -40,6 +200,7 @@
"Notification"
]
},
"post": {
"security": [],
"summary": "wechat绑定",

View File

@ -74,6 +74,100 @@ do_request(get_file_signature, Args, _Context, _Req) ->
_ -> {404, #{<<"code">> => 1001, <<"error">> => <<"not support this type">>}}
end;
%dgiot通用告警
do_request(post_handlewarnsendsms, #{<<"appId">> := AppId, <<"appKey">> := AppKey, <<"tplId">> := TplId, <<"sign">> := Sign, <<"params">> := Params}, _Context, _Req) ->
%
application:set_env(dgiot_http, tencent_sms_appid, AppId),
application:set_env(dgiot_http, tencent_sms_appkey, AppKey),
application:set_env(dgiot_http, tencent_sms_notification_templateId, TplId),
%
application:set_env(dgiot_http, tencent_sms_sign, Sign),
application:set_env(dgiot_http, tencent_sms_params, Params),
case dgiot_parse:get_object(<<"_Role">>, Sign) 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),
PhoneList = lists:foldl(fun(X, Acc) ->
Phone = unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>, X))),
dgiot_notification:send_sms(Phone, application:get_env(dgiot_http, tencent_sms_params, Params)),
Acc ++ [unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>, X)))]
end, [], Row),
% {1} {2}{3}{4}{5},:{6}
Json = #{<<"phones">> => PhoneList},
{ok, #{
<<"status">> => 200,
<<"msg">> => <<"success">>,
<<"data">> => Json
}};
_ ->
{error, #{<<"status">> => 404, <<"msg">> => <<"部门ID错误"/utf8>>, <<"result">> => <<"_Role info null">>}}
end;
%
do_request(post_warnsendsms, #{<<"objectId">> := DeviceId, <<"branchId">> := BranchId, <<"datetimes">> := DateTimes, <<"docnumber">> := Docnumber, <<"username">> := UserName, <<"workshop">> := Workshop, <<"level">> := Level, <<"desc">> := Desc, <<"file">> := FileInfo}, _Context, _Req) ->
case Level of
<<"1">> ->
Warn = <<"待首检"/utf8>>,
dgiot_parse:update_object(<<"Device">>, DeviceId, #{<<"realstatus">> => 3});
<<"2">> ->
Warn = <<"待尾检"/utf8>>,
dgiot_parse:update_object(<<"Device">>, DeviceId, #{<<"realstatus">> => 5});
_ ->
Warn = <<"告警"/utf8>>,
{error, #{code => 1, error => ("level错误")}}
end,
Warns = Warn,
case dgiot_parse:get_object(<<"_Role">>, BranchId) of
{ok, #{<<"objectId">> := RolesId, <<"ACL">> := Acl}} ->
Map = #{
<<"type">> => DeviceId,
<<"name">> => <<"Manual alarm">>,
<<"status">> => 0,
<<"content">> => #{
<<"alarm">> => #{
<<"deviceId"/utf8>> => DeviceId,
<<"docnumber"/utf8>> => Docnumber,
<<"datetimes"/utf8>> => DateTimes,
<<"username"/utf8>> => UserName,
<<"workshop"/utf8>> => Workshop,
<<"level"/utf8>> => Level,
<<"desc"/utf8>> => Desc,
<<"imgurl"/utf8>> => FileInfo
},
<<"alertstatus">> => 1
},
<<"ACL">> => Acl
},
#{<<"objectId">> := ObjectId} = dgiot_parse_id:get_objectid(<<"Notification">>, Map),
NewMap = Map#{
<<"objectId">> => ObjectId
},
dgiot_parse:create_object(<<"Notification">>, NewMap),
%
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),
PhoneList = lists:foldl(fun(X, Acc) ->
Phone = unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>, X))),
dgiot_notification:send_sms(Phone, [DateTimes, <<"-">>, UserName, Docnumber, Workshop, Warns]),
Acc ++ [unicode:characters_to_binary(dgiot_utils:to_list(maps:get(<<"phone">>, X)))]
end, [], Row),
% {1} {2}{3}{4}{5},:{6}
Json = #{<<"phones">> => PhoneList},
{ok, #{
<<"status">> => 200,
<<"msg">> => <<"success">>,
<<"data">> => Json
}};
_ ->
{error, #{<<"status">> => 404, <<"msg">> => <<"部门ID错误"/utf8>>, <<"result">> => <<"_Role info null">>}}
end;
%% iot_hub : api资源 :jwt回调
%% OperationId:get_jwtlogin
%% :POST /iotapi/get_jwtlogin

View File

@ -21,7 +21,7 @@
-dgiot_data("ets").
-export([init_ets/0]).
%% API
-export([send_sms/3, send_sms/4, send_sms/5]).
-export([send_sms/2, send_sms/3, send_sms/5, send_sms/6, send_sms/7]).
-export([send_email/1, test_email/0]).
@ -41,8 +41,7 @@ send_verification_code(NationCode, Key) ->
rand:seed(exs1024),
Rand = 10000 + erlang:round(rand:uniform() * 10000),
TTL = 3,
Tpml = dgiot:get_env(dgiot_http, tencent_sms_tmplid,""),
case dgiot_notification:send_sms(NationCode, Key, Tpml, [Rand, TTL]) of
case dgiot_notification:send_sms(NationCode, Key, [Rand, TTL]) of
{ok, _Ext} ->
dgiot_cache:set(Key, Rand, TTL * 60),
{ok, #{<<"expire">> => TTL * 60}};
@ -62,46 +61,99 @@ check_verification_code(Key, Code) ->
send_sms(Mobile, TplId, Params) ->
send_sms("+86", Mobile, TplId, Params).
send_sms(NationCode, Mobile, TplId, Params) ->
send_sms(NationCode, Mobile, TplId, Params, <<>>).
send_sms(NationCode, Mobile, TplId, Params, Ext) ->
Random = integer_to_list(1000 + rand:uniform(1000)),
AppId = dgiot:get_env(dgiot_http, tencent_sms_appid,""),
AppKey = dgiot:get_env(dgiot_http, tencent_sms_appkey,""),
BaseUrl = "https://yun.tim.qq.com/v5/tlssmssvr/sendsms?sdkappid=~s&random=~s",
Url = io_lib:format(BaseUrl, [AppId, Random]),
Now = dgiot_datetime:nowstamp(),
case re:run(NationCode, <<"\\+(\\d{1,3})">>, [{capture, all, binary}]) of
send_sms(Mobile, Params) ->
send_sms("+86", Mobile, Params).
send_sms(NationCode, Mobile, Params) ->
TplId = dgiot_utils:to_list(application:get_env(dgiot_http, tencent_sms_notification_templateId, <<"">>)),
AppId = dgiot_utils:to_list(application:get_env(dgiot_http, tencent_sms_appid, <<"">>)),
AppKey = dgiot_utils:to_list(application:get_env(dgiot_http, tencent_sms_appkey, <<"">>)),
send_sms(NationCode, Mobile, Params, AppId, AppKey, TplId).
send_sms(Mobile, Params, AppId, AppKey, TplId) ->
send_sms("+86", Mobile, Params, AppId, AppKey, TplId, <<>>).
send_sms(NationCode, Mobile, Params, AppId, AppKey, TplId) ->
send_sms(NationCode, Mobile, Params, AppId, AppKey, TplId, <<>>).
send_sms(NationCode, Mobile, Params, AppId, AppKey, TplId, Ext) ->
AppId_b =
case is_binary(AppId) of
true ->
binary_to_list(AppId);
_ ->
AppId
end,
Random = dgiot_utils:to_list(1000 + rand:uniform(1000)),
Url =
case is_list(Mobile) of
true ->
"https://yun.tim.qq.com/v5/tlssmssvr/sendmultisms2?sdkappid=" ++ AppId_b ++ "&random=" ++ Random;
false ->
"https://yun.tim.qq.com/v5/tlssmssvr/sendsms?sdkappid=" ++ AppId_b ++ "&random=" ++ Random
end,
case re:run(NationCode, <<"\\+(\\d{1,3})">>, [{capture, all, binary}]) of % "+86"
{match, [_, NationCode1]} ->
{MobileStr, Tel_b} =
case is_list(Mobile) of
true -> %%
ListMobile = lists:foldl(fun(#{<<"mobile">> := Num}, Acc) -> Acc ++ [binary_to_list(Num)]
end, [], Mobile),
{string:join(ListMobile, ","), Mobile};
_ -> %%
case is_binary(Mobile) of
true ->
{Mobile, #{<<"mobile">> => Mobile, <<"nationcode">> => NationCode1}};
_ ->
{Mobile, #{<<"mobile">> => unicode:characters_to_binary(Mobile), <<"nationcode">> => NationCode1}}
end
end,
Now = dgiot_datetime:nowstamp(),
AppKey_b =
case is_binary(AppKey) of
true ->
binary_to_list(AppKey);
_ ->
AppKey
end,
SigStr = io_lib:format("appkey=~s&random=~s&time=~s&mobile=~s", [AppKey_b, Random, integer_to_list(Now), MobileStr]),
Sig_b = dgiot_utils:to_binary(string:to_lower(binary_to_list(<<<<Y>> || <<X:4>> <= crypto:hash(sha256, SigStr), Y <- integer_to_list(X, 16)>>))),
FunParams =
fun(X, Acc) ->
case is_binary(X) of
true ->
Acc ++ [X];
_ ->
Acc ++ [unicode:characters_to_binary(X)]
end
end,
Params_b = lists:foldl(FunParams, [], Params),
case is_binary(TplId) of
true ->
TplId_b = TplId;
_ ->
TplId_b = unicode:characters_to_binary(TplId)
end,
Data = #{
<<"tpl_id">> => dgiot_utils:to_binary(TplId),
<<"tpl_id">> => TplId_b,
<<"ext">> => Ext,
<<"extend">> => <<>>,
<<"params">> => Params,
<<"sign">> => dgiot_utils:to_binary(dgiot:get_env(dgiot_http, tencent_sms_sign,"")),
<<"tel">> => #{
<<"mobile">> => case is_binary(Mobile) of true -> Mobile; false -> list_to_binary(Mobile) end,
<<"nationcode">> => NationCode1
<<"params">> => Params_b,
<<"sign">> => <<"dgiot"/utf8>>,
<<"tel">> => Tel_b,
<<"time">> => Now,
<<"sig">> => Sig_b
},
<<"time">> => Now
},
SigStr = io_lib:format("appkey=~s&random=~s&time=~s&mobile=~s", [AppKey, Random, integer_to_list(Now), Mobile]),
Sig = string:to_lower(binary_to_list(<<<<Y>> || <<X:4>> <= crypto:hash(sha256, SigStr), Y <- integer_to_list(X, 16)>>)),
Body = Data#{<<"sig">> => list_to_binary(Sig)},
Request = {Url, [], "application/json", jsx:encode(Body)},
Request = {Url, [], "application/json", jsx:encode(Data)},
case catch httpc:request(post, Request, [], [{body_format, binary}]) of
{ok, {{_HTTPVersion, 200, "OK"}, _Header, ResBody}} ->
case jsx:decode(ResBody, [{labels, binary}, return_maps]) of
#{<<"result">> := 0, <<"ext">> := Ext} ->
{ok, Ext};
#{<<"errmsg">> := ErrMsg, <<"result">> := Code} ->
?LOG(error, "Send SMS ERROR: ~p->~ts, Request:~p~n", [list_to_binary(Url), unicode:characters_to_binary(ErrMsg), Body]),
?LOG(error, "Send SMS ERROR: ~p->~ts, Request:~p~n", [list_to_binary(Url), unicode:characters_to_binary(ErrMsg), Data]),
{error, #{code => Code, error => ErrMsg}}
end;
{Err, Reason} when Err == error; Err == 'EXIT' ->
?LOG(error, "Send SMS ERROR: ~p, ~p, ~p~n", [Url, Body, Reason]),
?LOG(error, "Send SMS ERROR: ~p, ~p, ~p~n", [Url, Data, Reason]),
{error, #{code => 1, error => list_to_binary(io_lib:format("~p", [Reason]))}}
end;
_ ->

View File

@ -33,7 +33,7 @@ init(_) ->
{ok, #{}}.
handle_info(connection_ready, #dclient{child = ChildState} = Dclient) ->
io:format("~s ~p ChildState = ~p.~n", [?FILE, ?LINE, ChildState]),
%% io:format("~s ~p ChildState = ~p.~n", [?FILE, ?LINE, ChildState]),
rand:seed(exs1024),
Time = erlang:round(rand:uniform() * 1 + 1) * 1000,
erlang:send_after(Time, self(), read),