mirror of
https://gitee.com/dgiiot/dgiot.git
synced 2024-11-29 18:57:41 +08:00
feat: add gb26875
This commit is contained in:
parent
a5ecc007b0
commit
497f375f2c
@ -20,7 +20,7 @@
|
|||||||
-include_lib("dgiot/include/logger.hrl").
|
-include_lib("dgiot/include/logger.hrl").
|
||||||
-export([
|
-export([
|
||||||
create_amis/3,
|
create_amis/3,
|
||||||
put_amis_device/3,
|
put_amis_device/2,
|
||||||
del_amis_device/1,
|
del_amis_device/1,
|
||||||
created_amis_device/3
|
created_amis_device/3
|
||||||
]).
|
]).
|
||||||
@ -29,7 +29,7 @@
|
|||||||
del_amis_device(DeviceId) ->
|
del_amis_device(DeviceId) ->
|
||||||
dgiot_device:delete(DeviceId).
|
dgiot_device:delete(DeviceId).
|
||||||
%%修改设备
|
%%修改设备
|
||||||
put_amis_device(put_amis_device, #{<<"objectId">> := Deviceid} = Body, SessionToken) ->
|
put_amis_device( #{<<"objectId">> := Deviceid} = Body, SessionToken) ->
|
||||||
case dgiot_parse:get_object(<<"Device">>, Deviceid,
|
case dgiot_parse:get_object(<<"Device">>, Deviceid,
|
||||||
[{"X-Parse-Session-Token", SessionToken}], [{from, rest}]) of
|
[{"X-Parse-Session-Token", SessionToken}], [{from, rest}]) of
|
||||||
{ok, #{<<"data">> := OldRole}} ->
|
{ok, #{<<"data">> := OldRole}} ->
|
||||||
|
@ -115,9 +115,9 @@ do_request(get_amis_device, #{<<"deviceid">> := Deviceid}, _Context, _Req) ->
|
|||||||
%% Role模版 概要: 修改amis设备
|
%% Role模版 概要: 修改amis设备
|
||||||
%% OperationId:put_amis_device
|
%% OperationId:put_amis_device
|
||||||
%% 请求:POST /iotapi/put_amis_device
|
%% 请求:POST /iotapi/put_amis_device
|
||||||
do_request(put_amis_device, #{<<"objectId">> := Deviceid} = _Body,_Context, _Req0) ->
|
do_request(put_amis_device, Body, #{<<"sessionToken">> := SessionToken}, _Req0) ->
|
||||||
%% io:format("Body ~p~n", [Body]),
|
%% io:format("Body ~p~n", [Body]),
|
||||||
case dgiot_bamis:put_amis_device(Deviceid) of
|
case dgiot_bamis:put_amis_device(Body, SessionToken) of
|
||||||
{ok, Info} ->
|
{ok, Info} ->
|
||||||
{ok, Info};
|
{ok, Info};
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -11,3 +11,6 @@
|
|||||||
+ GB 26875.7-2015 城市消防远程监控系统 第7部分:消防设施维护管理软件功能要求
|
+ GB 26875.7-2015 城市消防远程监控系统 第7部分:消防设施维护管理软件功能要求
|
||||||
+ GB 26875.8-2015 城市消防远程监控系统 第8部分:监控中心对外数据交换协议
|
+ GB 26875.8-2015 城市消防远程监控系统 第8部分:监控中心对外数据交换协议
|
||||||
|
|
||||||
|
### 控制命令流程示意图
|
||||||
|
|
||||||
|
|
@ -2,15 +2,10 @@
|
|||||||
-record(state, {
|
-record(state, {
|
||||||
id,
|
id,
|
||||||
devaddr = <<>>,
|
devaddr = <<>>,
|
||||||
heartcount = 0,
|
|
||||||
regtype = <<>>,
|
|
||||||
head = "xxxxxx0eee",
|
|
||||||
len = 0,
|
len = 0,
|
||||||
app = <<>>,
|
app = <<>>,
|
||||||
product = <<>>,
|
product = <<>>,
|
||||||
deviceId = <<>>,
|
deviceId = <<>>,
|
||||||
scale = 10,
|
|
||||||
temperature = 0,
|
|
||||||
env = <<>>,
|
env = <<>>,
|
||||||
dtutype = <<>>
|
dtutype = <<>>
|
||||||
}).
|
}).
|
||||||
@ -19,7 +14,7 @@
|
|||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%% 命令
|
%% 命令
|
||||||
-define(COMMAND_RESERVED, 0). % 预留
|
-define(COMMAND_RESERVED(Name), lists:member(Name, [0 |lists:seq(7, 127)]). % 预留
|
||||||
-define(COMMAND_CONTROL, 1). % 控制命令 时间同步
|
-define(COMMAND_CONTROL, 1). % 控制命令 时间同步
|
||||||
-define(COMMAND_SEND_DATA, 2). % 发送数据 发送火灾报警和建筑消防设施运行状态等信息
|
-define(COMMAND_SEND_DATA, 2). % 发送数据 发送火灾报警和建筑消防设施运行状态等信息
|
||||||
-define(COMMAND_CONFIRM, 3). % 确认 对控制命令和发送信息的确认回答
|
-define(COMMAND_CONFIRM, 3). % 确认 对控制命令和发送信息的确认回答
|
||||||
@ -29,12 +24,25 @@
|
|||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
%% 类型标志定义表 8.1.1
|
%% 类型标志定义表 8.1.1
|
||||||
-define(TYPE_RESERVED(Name), lists:member(Name, [0 |lists:seq(26, 29)| lists:seq(45, 49)| lists:seq(54, 59)| lists:seq(63, 68)| lists:seq(70, 73)| lists:seq(75, 77)])). % 预留
|
%% 类型标志为l字节二进制数,取值范围0~255,类型标志见表3。
|
||||||
-define(TYPE_UP_SYSTEM_STATE, 1). % 8.2.1.1 4个字节, 上传建筑消防设施系统状态
|
-define(CLASS_UP_SYSTEM_STATE, 1). % 8.2.1.1 4个字节, 上传建筑消防设施系统状态
|
||||||
-define(TYPE_UP_RUNNING_STATUS, 2). % 上传建筑消防设施部件运行状态
|
-define(CLASS_UP_RUNNING_STATUS, 2). % 上传建筑消防设施部件运行状态
|
||||||
-define(TYPE_UP_ANALOG_QUANTITY, 3). % 上传建筑消防设施部件模拟量值
|
-define(CLASS_UP_ANALOG_QUANTITY, 3). % 上传建筑消防设施部件模拟量值
|
||||||
-define(TYPE_UP_OPERATING_INFORMATION, 4). % 上传建筑消防设施操作信息
|
-define(CLASS_UP_OPERATING_INFORMATION, 4). % 上传建筑消防设施操作信息
|
||||||
-define(TYPE_UP_SOFTWARE_VERSION, 5). % 上传建筑消防设施软件版本
|
-define(CLASS_UP_SOFTWARE_VERSION, 5). % 上传建筑消防设施软件版本
|
||||||
-define(TYPE_UP_SYSTEM_CONFIGURATION, 6). % 上传建筑消防设施系统配置情况
|
-define(CLASS_UP_SYSTEM_CONFIGURATION, 6). % 上传建筑消防设施系统配置情况
|
||||||
-define(TYPE_UP_PARTS_CONFIGURATION, 7). % 上传建筑消防设施部件配置情况
|
-define(CLASS_UP_PARTS_CONFIGURATION, 7). % 上传建筑消防设施部件配置情况
|
||||||
-define(TYPE_UP_SYSTEM_TIME, 8). % 上传建筑消防设施系统时间
|
-define(CLASS_UP_SYSTEM_TIME, 8). % 上传建筑消防设施系统时间
|
||||||
|
-define(CLASS_UP_RESERVED(Name), lists:member(Name, [22, 23, 27 | lists:seq(9, 20)] | lists:seq(29, 60)] ).
|
||||||
|
-define(CLASS_UP_USERDEV_RUNINFO, 21). % 上传用户信息传输装置运行状态
|
||||||
|
-define(CLASS_UP_USERDEV_OPINFO, 24). % 上传用户信息传输装置操作信息
|
||||||
|
-define(CLASS_UP_USERDEV_SOFTVER, 25). % 上传用户信息传输装置软件版本
|
||||||
|
-define(CLASS_UP_USERDEV_CONFIG, 26). % 上传用户信息传输装置配置情况
|
||||||
|
-define(CLASS_UP_USERDEV_SYSTIME, 28). % 上传用户信息传输装置系统时间
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
%% 建筑消防设施系统状态 8.2.1.1
|
||||||
|
%% 系统类型定义表
|
||||||
|
-define(SYS_TYPE_COMMOM , 0). % 通用
|
||||||
|
-define(SYS_TYPE_FIRE_ALARM, 0). % 火灾报警系统
|
@ -19,7 +19,7 @@
|
|||||||
-include_lib("dgiot_bridge/include/dgiot_bridge.hrl").
|
-include_lib("dgiot_bridge/include/dgiot_bridge.hrl").
|
||||||
-include("dgiot_gb26875.hrl").
|
-include("dgiot_gb26875.hrl").
|
||||||
-include_lib("dgiot/include/logger.hrl").
|
-include_lib("dgiot/include/logger.hrl").
|
||||||
-define(TYPE, <<"GB26875">>).
|
-define(TYPE, <<"gb26875">>).
|
||||||
%% API
|
%% API
|
||||||
-export([start/2]).
|
-export([start/2]).
|
||||||
|
|
||||||
@ -31,10 +31,10 @@
|
|||||||
cType => ?TYPE,
|
cType => ?TYPE,
|
||||||
type => ?PROTOCOL_CHL,
|
type => ?PROTOCOL_CHL,
|
||||||
title => #{
|
title => #{
|
||||||
zh => <<"GB26875采集通道"/utf8>>
|
zh => <<"GB26875"/utf8>>
|
||||||
},
|
},
|
||||||
description => #{
|
description => #{
|
||||||
zh => <<"GB26875采集通道"/utf8>>
|
zh => <<"gb26875"/utf8>>
|
||||||
}
|
}
|
||||||
}).
|
}).
|
||||||
%% 注册通道参数
|
%% 注册通道参数
|
||||||
@ -43,7 +43,7 @@
|
|||||||
order => 1,
|
order => 1,
|
||||||
type => integer,
|
type => integer,
|
||||||
required => true,
|
required => true,
|
||||||
default => 20110,
|
default => 7533,
|
||||||
title => #{
|
title => #{
|
||||||
zh => <<"端口"/utf8>>
|
zh => <<"端口"/utf8>>
|
||||||
},
|
},
|
||||||
@ -51,47 +51,23 @@
|
|||||||
zh => <<"侦听端口"/utf8>>
|
zh => <<"侦听端口"/utf8>>
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
<<"regtype">> => #{
|
<<"dtutype">> => #{
|
||||||
order => 2,
|
order => 2,
|
||||||
type => string,
|
type => string,
|
||||||
required => true,
|
required => true,
|
||||||
default => <<"上传Mac"/utf8>>,
|
default => <<"消防电子"/utf8>>,
|
||||||
title => #{
|
title => #{
|
||||||
zh => <<"注册类型"/utf8>>
|
zh => <<"消防电子"/utf8>>
|
||||||
},
|
},
|
||||||
description => #{
|
description => #{
|
||||||
zh => <<"上传Mac"/utf8>>
|
zh => <<"消防电子"/utf8>>
|
||||||
}
|
|
||||||
},
|
|
||||||
<<"regular">> => #{
|
|
||||||
order => 3,
|
|
||||||
type => string,
|
|
||||||
required => true,
|
|
||||||
default => <<"9C-A5-25-**-**-**">>,
|
|
||||||
title => #{
|
|
||||||
zh => <<"登录报文帧头"/utf8>>
|
|
||||||
},
|
|
||||||
description => #{
|
|
||||||
zh => <<"填写正则表达式匹配login"/utf8>>
|
|
||||||
}
|
|
||||||
},
|
|
||||||
<<"dtutype">> => #{
|
|
||||||
order => 4,
|
|
||||||
type => string,
|
|
||||||
required => true,
|
|
||||||
default => <<"usr">>,
|
|
||||||
title => #{
|
|
||||||
zh => <<"控制器厂商"/utf8>>
|
|
||||||
},
|
|
||||||
description => #{
|
|
||||||
zh => <<"控制器厂商"/utf8>>
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
<<"ico">> => #{
|
<<"ico">> => #{
|
||||||
order => 102,
|
order => 102,
|
||||||
type => string,
|
type => string,
|
||||||
required => false,
|
required => false,
|
||||||
default => <<"http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/shuwa_tech/zh/product/dgiot/channel/GB26875.png">>,
|
default => <<"http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/shuwa_tech/zh/product/dgiot/channel/modbus.png">>,
|
||||||
title => #{
|
title => #{
|
||||||
en => <<"channel ICO">>,
|
en => <<"channel ICO">>,
|
||||||
zh => <<"通道ICO"/utf8>>
|
zh => <<"通道ICO"/utf8>>
|
||||||
@ -109,24 +85,17 @@ start(ChannelId, ChannelArgs) ->
|
|||||||
%% 通道初始化
|
%% 通道初始化
|
||||||
init(?TYPE, ChannelId, #{
|
init(?TYPE, ChannelId, #{
|
||||||
<<"port">> := Port,
|
<<"port">> := Port,
|
||||||
<<"regtype">> := Type,
|
|
||||||
<<"regular">> := Regular,
|
|
||||||
<<"product">> := Products,
|
<<"product">> := Products,
|
||||||
<<"dtutype">> := Dtutype
|
<<"dtutype">> := Dtutype
|
||||||
} = _Args) ->
|
} = _Args) ->
|
||||||
[{ProdcutId, App} | _] = get_app(Products),
|
[{ProdcutId, App} | _] = get_app(Products),
|
||||||
{Header, Len} = get_header(Regular),
|
|
||||||
State = #state{
|
State = #state{
|
||||||
id = ChannelId,
|
id = ChannelId,
|
||||||
regtype = Type,
|
|
||||||
head = Header,
|
|
||||||
len = Len,
|
|
||||||
app = App,
|
app = App,
|
||||||
product = ProdcutId,
|
product = ProdcutId,
|
||||||
dtutype = Dtutype
|
dtutype = Dtutype
|
||||||
},
|
},
|
||||||
|
|
||||||
%% dgiot_data:insert({ChannelId, heartbeat}, {Heartbeat, Port}),
|
|
||||||
{ok, State, dgiot_gb26875_tcp:start(Port, State)};
|
{ok, State, dgiot_gb26875_tcp:start(Port, State)};
|
||||||
|
|
||||||
init(?TYPE, _ChannelId, _Args) ->
|
init(?TYPE, _ChannelId, _Args) ->
|
||||||
@ -172,14 +141,3 @@ get_app(Products) ->
|
|||||||
{ProdcutId, App}
|
{ProdcutId, App}
|
||||||
end, Products).
|
end, Products).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
get_header(Regular) ->
|
|
||||||
lists:foldl(fun(X, {Header, Len}) ->
|
|
||||||
case X of
|
|
||||||
"**" -> {Header, Len + length(X)};
|
|
||||||
"*" -> {Header, Len + length(X)};
|
|
||||||
_ -> {Header ++ X, Len + length(X)}
|
|
||||||
end
|
|
||||||
end, {[], 0},
|
|
||||||
re:split(dgiot_utils:to_list(Regular), "-", [{return, list}])).
|
|
||||||
|
@ -32,11 +32,6 @@
|
|||||||
start(Port, State) ->
|
start(Port, State) ->
|
||||||
dgiot_tcp_server:child_spec(?MODULE, dgiot_utils:to_int(Port), State).
|
dgiot_tcp_server:child_spec(?MODULE, dgiot_utils:to_int(Port), State).
|
||||||
|
|
||||||
%% =======================
|
|
||||||
%% {ok, State} | {stop, Reason}
|
|
||||||
%%init(TCPState) ->
|
|
||||||
%% erlang:send_after(5 * 1000, self(), login),.
|
|
||||||
%% {ok, TCPState}.
|
|
||||||
|
|
||||||
init(#tcp{state = #state{id = ChannelId}} = TCPState) ->
|
init(#tcp{state = #state{id = ChannelId}} = TCPState) ->
|
||||||
?LOG(info, "ChannelId ~p", [ChannelId]),
|
?LOG(info, "ChannelId ~p", [ChannelId]),
|
||||||
@ -47,53 +42,25 @@ init(#tcp{state = #state{id = ChannelId}} = TCPState) ->
|
|||||||
{stop, not_find_channel}
|
{stop, not_find_channel}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% 9C A5 25 CD 00 DB
|
|
||||||
%% 11 04 02 06 92 FA FE
|
|
||||||
handle_info({tcp, Buff}, #tcp{socket = Socket, state = #state{id = ChannelId, devaddr = <<>>, head = Head, len = Len, product = ProductId, dtutype = Dtutype} = State} = TCPState) ->
|
|
||||||
dgiot_bridge:send_log(ChannelId, "DTU revice from ~p", [dgiot_utils:binary_to_hex(Buff)]),
|
|
||||||
DTUIP = dgiot_utils:get_ip(Socket),
|
|
||||||
DtuAddr = dgiot_utils:binary_to_hex(Buff),
|
|
||||||
List = dgiot_utils:to_list(DtuAddr),
|
|
||||||
List1 = dgiot_utils:to_list(Buff),
|
|
||||||
#{<<"objectId">> := DeviceId} =
|
|
||||||
dgiot_parse:get_objectid(<<"Device">>, #{<<"product">> => ProductId, <<"devaddr">> => DtuAddr}),
|
|
||||||
case re:run(DtuAddr, Head, [{capture, first, list}]) of
|
|
||||||
{match, [Head]} when length(List) == Len ->
|
|
||||||
{DevId, Devaddr} =
|
|
||||||
case create_device(DeviceId, ProductId, DtuAddr, DTUIP, Dtutype) of
|
|
||||||
{<<>>, <<>>} ->
|
|
||||||
{<<>>, <<>>};
|
|
||||||
{DevId1, Devaddr1} ->
|
|
||||||
{DevId1, Devaddr1}
|
|
||||||
end,
|
|
||||||
{noreply, TCPState#tcp{buff = <<>>, state = State#state{devaddr = Devaddr, deviceId = DevId}}};
|
|
||||||
_Error ->
|
|
||||||
case re:run(Buff, Head, [{capture, first, list}]) of
|
|
||||||
{match, [Head]} when length(List1) == Len ->
|
|
||||||
create_device(DeviceId, ProductId, Buff, DTUIP, Dtutype),
|
|
||||||
{noreply, TCPState#tcp{buff = <<>>, state = State#state{devaddr = Buff}}};
|
|
||||||
Error1 ->
|
|
||||||
?LOG(info, "Error1 ~p Buff ~p ", [Error1, dgiot_utils:to_list(Buff)]),
|
|
||||||
{noreply, TCPState#tcp{buff = <<>>}}
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
|
|
||||||
%% 3D302E30303030203D302E303030303530303138200D0A
|
|
||||||
handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId, devaddr = _DevAddr, product = _ProductId} = State} = TCPState) ->
|
handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId, devaddr = _DevAddr, product = _ProductId} = State} = TCPState) ->
|
||||||
dgiot_bridge:send_log(ChannelId, "revice from ~p", [Buff]),
|
dgiot_bridge:send_log(ChannelId, "revice from ~p", [dgiot_utils:binary_to_hex(Buff)]),
|
||||||
|
io:format("revice from Buff ~p ~n", [dgiot_utils:binary_to_hex(Buff)]),
|
||||||
case dgiot_gb26875_decoder:parse_frame(Buff, State) of
|
case dgiot_gb26875_decoder:parse_frame(Buff, State) of
|
||||||
|
{ok, #{<<"ack">> := Ack} = _Result} ->
|
||||||
|
dgiot_tcp_server:send(TCPState, Ack);
|
||||||
{ok, Result} ->
|
{ok, Result} ->
|
||||||
io:format("Result ~p~n", [Result]),
|
io:format("revice from Buff ~p ~n", [dgiot_utils:binary_to_hex(Buff)]),
|
||||||
dgiot_bridge:send_log(ChannelId, "parse_frame Buff ~p", [Result]),
|
io:format("Result ~p ~n", [Result]),
|
||||||
R = dgiot_gb26875_decoder:to_frame(Result),
|
dgiot_bridge:send_log(ChannelId, "parse_frame Buff ~p", [Result]);
|
||||||
case R =:= Buff of
|
%% R = dgiot_gb26875_decoder:to_frame(Result),
|
||||||
true ->
|
%% case R =:= Buff of
|
||||||
io:format("success to_frame Buff ~p~n", [Buff]),
|
%% true ->
|
||||||
dgiot_bridge:send_log(ChannelId, "success to_frame Buff ~p", [Buff]);
|
%% io:format("success to_frame Buff ~p~n", [Buff]),
|
||||||
_ ->
|
%% dgiot_bridge:send_log(ChannelId, "success to_frame Buff ~p", [Buff]);
|
||||||
io:format("error to_frame R ~p~n", [R]),
|
%% _ ->
|
||||||
dgiot_bridge:send_log(ChannelId, "error to_frame Buff ~p", [R])
|
%% io:format("error to_frame R ~p~n", [R]),
|
||||||
end;
|
%% dgiot_bridge:send_log(ChannelId, "error to_frame Buff ~p", [R])
|
||||||
|
%% end;
|
||||||
_ ->
|
_ ->
|
||||||
pass
|
pass
|
||||||
end,
|
end,
|
||||||
@ -123,55 +90,3 @@ get_deviceid(ProdcutId, DevAddr) ->
|
|||||||
#{<<"objectId">> := DeviceId} =
|
#{<<"objectId">> := DeviceId} =
|
||||||
dgiot_parse:get_objectid(<<"Device">>, #{<<"product">> => ProdcutId, <<"devaddr">> => DevAddr}),
|
dgiot_parse:get_objectid(<<"Device">>, #{<<"product">> => ProdcutId, <<"devaddr">> => DevAddr}),
|
||||||
DeviceId.
|
DeviceId.
|
||||||
|
|
||||||
create_device(DeviceId, ProductId, DTUMAC, DTUIP, Dtutype) ->
|
|
||||||
case dgiot_parse:get_object(<<"Product">>, ProductId) of
|
|
||||||
{ok, #{<<"ACL">> := Acl, <<"devType">> := DevType}} ->
|
|
||||||
case dgiot_parse:get_object(<<"Device">>, DeviceId) of
|
|
||||||
{ok, #{<<"devaddr">> := _GWAddr}} ->
|
|
||||||
dgiot_parse:update_object(<<"Device">>, DeviceId, #{<<"ip">> => DTUIP, <<"status">> => <<"ONLINE">>});
|
|
||||||
_ ->
|
|
||||||
dgiot_device:create_device(#{
|
|
||||||
<<"devaddr">> => DTUMAC,
|
|
||||||
<<"name">> => <<Dtutype/binary, DTUMAC/binary>>,
|
|
||||||
<<"ip">> => DTUIP,
|
|
||||||
<<"isEnable">> => true,
|
|
||||||
<<"product">> => ProductId,
|
|
||||||
<<"ACL">> => Acl,
|
|
||||||
<<"status">> => <<"ONLINE">>,
|
|
||||||
<<"location">> => #{<<"__type">> => <<"GeoPoint">>, <<"longitude">> => 120.161324, <<"latitude">> => 30.262441},
|
|
||||||
<<"brand">> => Dtutype,
|
|
||||||
<<"devModel">> => DevType
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
Productname =
|
|
||||||
case dgiot_parse:get_object(<<"Product">>, ProductId) of
|
|
||||||
{ok, #{<<"name">> := Productname1}} ->
|
|
||||||
Productname1;
|
|
||||||
_ ->
|
|
||||||
<<"">>
|
|
||||||
end,
|
|
||||||
?MLOG(info, #{<<"clientid">> => DeviceId, <<"devaddr">> => DTUMAC, <<"productid">> => ProductId, <<"productname">> => Productname, <<"devicename">> => <<Dtutype/binary, DTUMAC/binary>>, <<"status">> => <<"上线"/utf8>>}, ['device_statuslog']),
|
|
||||||
{DeviceId, DTUMAC};
|
|
||||||
Error2 ->
|
|
||||||
?LOG(info, "Error2 ~p ", [Error2]),
|
|
||||||
{<<>>, <<>>}
|
|
||||||
end.
|
|
||||||
|
|
||||||
%%create_instruct(ACL, DtuProductId, DtuDevId) ->
|
|
||||||
%% case dgiot_product:lookup_prod(DtuProductId) of
|
|
||||||
%% {ok, #{<<"thing">> := #{<<"properties">> := Properties}}} ->
|
|
||||||
%% lists:map(fun(Y) ->
|
|
||||||
%% case Y of
|
|
||||||
%% #{<<"dataForm">> := #{<<"slaveid">> := 256}} -> %%不做指令
|
|
||||||
%% pass;
|
|
||||||
%% #{<<"dataForm">> := #{<<"slaveid">> := SlaveId}} ->
|
|
||||||
%% Pn = dgiot_utils:to_binary(SlaveId),
|
|
||||||
%%%% ?LOG(info,"DtuProductId ~p DtuDevId ~p Pn ~p ACL ~p", [DtuProductId, DtuDevId, Pn, ACL]),
|
|
||||||
%%%% ?LOG(info,"Y ~p", [Y]),
|
|
||||||
%% dgiot_instruct:create(DtuProductId, DtuDevId, Pn, ACL, <<"all">>, #{<<"properties">> => [Y]});
|
|
||||||
%% _ -> pass
|
|
||||||
%% end
|
|
||||||
%% end, Properties);
|
|
||||||
%% _ -> pass
|
|
||||||
%% end.
|
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
test() ->
|
test() ->
|
||||||
Buff = <<16#40, 16#40, 16#00, 16#00, 16#01, 16#01, 16#18, 16#0d, 16#11, 16#16, 16#0a, 16#14, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#06, 16#05, 16#04, 16#03, 16#02, 16#01, 16#30, 16#00, 16#02, 16#02, 16#01, 16#01, 16#03, 16#00, 16#d9, 16#00, 16#06, 16#00, 16#02, 16#00, 16#a3, 16#c1, 16#c7, 16#f8, 16#a3, 16#b1, 16#b2, 16#e3, 16#df, 16#c8, 16#b2, 16#b8, 16#d7, 16#df, 16#c0, 16#c8, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#30, 16#12, 16#13, 16#01, 16#08, 16#14, 16#68, 16#23, 16#23>>,
|
Buff = <<16#40, 16#40, 16#00, 16#00, 16#01, 16#01, 16#18, 16#0d, 16#11, 16#16, 16#0a, 16#14, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#06, 16#05, 16#04, 16#03, 16#02, 16#01, 16#30, 16#00, 16#02, 16#02, 16#01, 16#01, 16#03, 16#00, 16#d9, 16#00, 16#06, 16#00, 16#02, 16#00, 16#a3, 16#c1, 16#c7, 16#f8, 16#a3, 16#b1, 16#b2, 16#e3, 16#df, 16#c8, 16#b2, 16#b8, 16#d7, 16#df, 16#c0, 16#c8, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#00, 16#30, 16#12, 16#13, 16#01, 16#08, 16#14, 16#68, 16#23, 16#23>>,
|
||||||
{ok, Result} = parse_frame(Buff, #{}),
|
{ok, Result} = parse_frame(Buff, #{}),
|
||||||
?LOG(info, "Result ~p~n", [Result]),
|
|
||||||
io:format("Result ~p~n", [Result]),
|
io:format("Result ~p~n", [Result]),
|
||||||
R = to_frame(Result),
|
R = to_frame(Result),
|
||||||
case R =:= Buff of
|
case R =:= Buff of
|
||||||
@ -38,32 +37,117 @@ test() ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
parse_frame(Buff, Opts) ->
|
parse_frame(Buff, Opts) ->
|
||||||
?LOG(info, "Buff ~p~n", [Buff]),
|
|
||||||
parse_frame(Buff, #{}, Opts).
|
parse_frame(Buff, #{}, Opts).
|
||||||
|
|
||||||
parse_frame(<<"@@", Header:22/binary, Length:16/little-integer, Tail/binary>> = Buff, Acc, Opts) when size(Tail) >= Length + 4 ->
|
parse_frame(<<>>, Acc, _Opts) ->
|
||||||
|
{ok, Acc};
|
||||||
|
|
||||||
|
%%GB/T 26875.3—2011
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%% 定 义 | 描 述 |
|
||||||
|
%------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 启动符‘@@’ | |
|
||||||
|
%% (2字节) | 数据包的第1、2字节,为固定值64,64 |
|
||||||
|
%-------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% | 数据包的第3、4字节。发送/确认模式下,业务流水号由发送端在发送新的数据包 |
|
||||||
|
%% | 时按顺序加一,确认方按发送包的业务流水号返回;请求/应答模式下,业务流水号 |
|
||||||
|
%% 业务流水号 | 由请求端在发送新的请求命令时按顺序加一,应答方按请求包的业务流水号返回。 |
|
||||||
|
%% (2字节) | 低字节传输在前。业务流水号是一个2字节的正整数,由通信双方第一次建立网络 (2字节) |
|
||||||
|
%% | 连接时确定,初始值为o。业务流水号由业务发起方(业务发起方指发送/确认模式 |
|
||||||
|
%% | 下的发送端或者请求/应答模式下的请求端)独立管理。业务发起方负责业务流水 |
|
||||||
|
%% | 号的分配和回收,保证在业务存续期间业务流水号的唯一性 |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 协议版本号 | 协议版本号包含主版本号(第5字节)和用户版本号(第6字节)。主版本号为固定 |
|
||||||
|
%% (2字节) | 值l,用户版本号由用户自行定义 |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 时间标签 | 数据包的第7~12字节,为数据包发出的时间,具体定义见8.2.2 |
|
||||||
|
%% (6字节) | |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 源地址 | 数据包的第13~18字节,为数据包的源地址(监控中心或用户信息传输装置地 |
|
||||||
|
%% (6字节) 址)。 | 低字节传输在前 |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 目的地址 | 数据包的第19~24字节,为数据包的目的地址(监控中心或用户信息传输装置地 |
|
||||||
|
%% (6字节) | 址)。低字节传输在前 |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 应用数据单元长度 | 数据包的第25,26字节,为应用数据单元的长度,长度不应大于l 024;低字节传输在前 |
|
||||||
|
%% (2字节) | |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 命令字节 | |
|
||||||
|
%% (1字节) | 数据包的第27字节,为控制单元的命令字节,具体定义见表2 |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 应用数据单元 | 应用数据单元,基本格式见图5,对于确认/否认等命令包,此单元可为空 |
|
||||||
|
%% (最大1 024字节) | |
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 校验和 | 控制单元中各字节数据(第3~27字节)及应用数据单元的算术校验和,舍去8位 |
|
||||||
|
%% (1字节) | 以上的进位位后所形成的l字节二进制数 |
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% 结束符‘##, | 为固定值35,35 |
|
||||||
|
%% (2字节) | |
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%启动符 业务流水号 协议版本号 时间标签 源地址 目的地址 应用数据单元长度 命令字节 应用数据单元 校验和 结束符
|
||||||
|
%%4040 F809 1000 081E09030316 000000000000 C0A801046D1D 0100 02 16 6C 2323
|
||||||
|
|
||||||
|
%%启动符 业务流水号 协议版本号 时间标签 源地址 目的地址 应用数据单元长度 命令字节 应用数据单元 校验和 结束符
|
||||||
|
%% 握手请求
|
||||||
|
%%4040 6900 1000 0a110e030615 000000000000 ac103cd56d1d 0100 02 16 30 2323
|
||||||
|
%%应答
|
||||||
|
%%4040 6900 1000 0a110e030615 ac103cd56d1d 000000000000 0100 03 17 30 2323
|
||||||
|
parse_frame(<<"@@", SerialId:16, Version:16, Time:6/binary, Source:6/binary, Destination:6/binary, Length:16/little, ?COMMAND_SEND_DATA:8, UserZone:1/binary, Crc:1/binary, "##", Rest/binary>> = Buff,
|
||||||
|
Acc, Opts) when Length == 1 ->
|
||||||
|
<<"@@", Head:25/binary, _/binary>> = Buff,
|
||||||
|
CheckCrc = dgiot_utils:get_parity(<<Head/binary, UserZone/binary>>),
|
||||||
|
{Acc1, Rest1} =
|
||||||
|
case <<CheckCrc>> =:= Crc of
|
||||||
|
true ->
|
||||||
|
AckBuff = <<"@@", SerialId:16, Version:16, Time:6/binary, Destination:6/binary, Source:6/binary, Length:16/little, ?COMMAND_CONFIRM:8, UserZone:1/binary, Crc:1/binary, "##">>,
|
||||||
|
NewAcc = Acc#{
|
||||||
|
<<"msgtype">> => ?GB26875,
|
||||||
|
<<"header">> => #{
|
||||||
|
<<"serialid">> => SerialId,
|
||||||
|
<<"version">> => Version,
|
||||||
|
<<"timestamp">> => get_timestamp(Time),
|
||||||
|
<<"source">> => get_address(Source),
|
||||||
|
<<"destination">> => get_address(Destination)
|
||||||
|
},
|
||||||
|
<<"command">> => ?COMMAND_SEND_DATA,
|
||||||
|
<<"appdata">> => dgiot_utils:binary_to_hex(UserZone),
|
||||||
|
<<"ack">> => AckBuff
|
||||||
|
},
|
||||||
|
{NewAcc, Rest};
|
||||||
|
false ->
|
||||||
|
{Acc, Rest}
|
||||||
|
end,
|
||||||
|
parse_frame(Rest1, Acc1, Opts);
|
||||||
|
|
||||||
|
parse_frame(<<"@@", SerialId:16, Version:16, Time:6/binary, Source:6/binary, Destination:6/binary, Length:16/little, Command:8, Tail/binary>> = Buff, Acc, Opts)
|
||||||
|
when size(Tail) >= Length + 3 andalso Length > 2 ->
|
||||||
<<"@@", Head:25/binary, _/binary>> = Buff,
|
<<"@@", Head:25/binary, _/binary>> = Buff,
|
||||||
<<SerialId:16, Version:16, Time:6/binary, Source:6/binary, Destination:6/binary>> = Header,
|
|
||||||
{Acc1, Rest1} =
|
{Acc1, Rest1} =
|
||||||
case Tail of
|
case Tail of
|
||||||
<<Action:8, Appdata:Length/binary, Crc:1/binary, "##", Rest/binary>> ->
|
<<UserZone:Length/binary, Crc:1/binary, "##", Rest/binary>> ->
|
||||||
CheckCrc = dgiot_utils:get_parity(<<Head/binary, Appdata/binary>>),
|
CheckCrc = dgiot_utils:get_parity(<<Head/binary, UserZone/binary>>),
|
||||||
case <<CheckCrc>> =:= Crc of
|
case <<CheckCrc>> =:= Crc of
|
||||||
true ->
|
true ->
|
||||||
<<Type:1/binary, Len:1/binary, Bodys/binary>> = Appdata,
|
Map = maps:merge(Acc#{
|
||||||
{maps:merge(Acc#{
|
|
||||||
<<"msgtype">> => ?GB26875,
|
<<"msgtype">> => ?GB26875,
|
||||||
<<"header">> => #{
|
<<"header">> => #{
|
||||||
<<"serialid">> => SerialId,
|
<<"serialid">> => SerialId,
|
||||||
<<"version">> => Version,
|
<<"version">> => Version,
|
||||||
<<"timestamp">> => get_timestamp(Time),
|
<<"timestamp">> => get_timestamp(Time),
|
||||||
<<"source">> => dgiot_utils:binary_to_hex(reverse(Source)),
|
<<"source">> => get_address(Source),
|
||||||
<<"target">> => dgiot_utils:binary_to_hex(reverse(Destination))
|
<<"destination">> => get_address(Destination)
|
||||||
},
|
},
|
||||||
<<"action">> => Action,
|
<<"command">> => Command,
|
||||||
<<"appdata">> => dgiot_utils:binary_to_hex(Appdata)
|
<<"appdata">> => dgiot_utils:binary_to_hex(UserZone),
|
||||||
}, decoder_appdata(dgiot_utils:to_int(dgiot_utils:binary_to_hex(Type)), dgiot_utils:to_int(dgiot_utils:binary_to_hex(Len)), Bodys)), Rest};
|
<<"rawdata">> => #{
|
||||||
false ->
|
<<"timestamp">> => Time,
|
||||||
|
<<"source">> => Source,
|
||||||
|
<<"destination">> => Destination,
|
||||||
|
<<"appdata">> => UserZone
|
||||||
|
}
|
||||||
|
}, parse_userzone(UserZone)),
|
||||||
|
{Map, Rest};
|
||||||
|
_ ->
|
||||||
{Acc, <<>>}
|
{Acc, <<>>}
|
||||||
end;
|
end;
|
||||||
_Oth ->
|
_Oth ->
|
||||||
@ -72,12 +156,8 @@ parse_frame(<<"@@", Header:22/binary, Length:16/little-integer, Tail/binary>> =
|
|||||||
end,
|
end,
|
||||||
parse_frame(Rest1, Acc1, Opts);
|
parse_frame(Rest1, Acc1, Opts);
|
||||||
|
|
||||||
%%parse_frame(<<_:8, _/binary>> = Rest, Acc, Opts) ->
|
parse_frame(<<_:8, _/binary>> = Rest, Acc, Opts) ->
|
||||||
%% ?LOG(info, "Rest ~p~n", [Rest]),
|
parse_frame(Rest, Acc, Opts);
|
||||||
%% parse_frame(Rest, Acc, Opts);
|
|
||||||
|
|
||||||
parse_frame(<<>>, Acc, _Opts) ->
|
|
||||||
{ok, Acc};
|
|
||||||
|
|
||||||
parse_frame(Buff, Acc, Opts) ->
|
parse_frame(Buff, Acc, Opts) ->
|
||||||
?LOG(info, "Buff ~p", [Buff]),
|
?LOG(info, "Buff ~p", [Buff]),
|
||||||
@ -85,48 +165,110 @@ parse_frame(Buff, Acc, Opts) ->
|
|||||||
?LOG(info, "Opts ~p", [Opts]),
|
?LOG(info, "Opts ~p", [Opts]),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
get_address(<<A:8, B:8, C:8, D:8, Port:16>>) ->
|
||||||
|
Address = lists:concat([A, ".", B, ".", C, ".", D, ":", Port]),
|
||||||
|
dgiot_utils:to_binary(Address).
|
||||||
|
|
||||||
reverse(Bin) -> reverse(Bin, <<>>).
|
reverse(Bin) -> reverse(Bin, <<>>).
|
||||||
reverse(<<>>, Acc) -> Acc;
|
reverse(<<>>, Acc) -> Acc;
|
||||||
reverse(<<H:1/binary, Rest/binary>>, Acc) ->
|
reverse(<<H:1/binary, Rest/binary>>, Acc) ->
|
||||||
reverse(Rest, <<H/binary, Acc/binary>>).
|
reverse(Rest, <<H/binary, Acc/binary>>).
|
||||||
|
|
||||||
get_delen(Type) ->
|
get_flag(Type, Flag) ->
|
||||||
case Type of
|
{_, Flags} =
|
||||||
?TYPE_UP_SYSTEM_STATE -> {<<"systemstate">>, 4};
|
lists:foldl(fun(X, {Num, Acc}) ->
|
||||||
?TYPE_UP_RUNNING_STATUS -> {<<"runningstatus">>, 40};
|
FlagId = dgiot_utils:to_binary(dgiot_utils:to_list(Type) ++ "." ++ dgiot_utils:to_list(Num)),
|
||||||
_ ->
|
case X of
|
||||||
{<<"unknow">>, 4}
|
1 ->
|
||||||
end.
|
{Num + 1, Acc#{FlagId => X}};
|
||||||
|
0 ->
|
||||||
|
{Num + 1, Acc}
|
||||||
|
end
|
||||||
|
end, {0, #{}}, [X || <<X:1>> <= Flag]),
|
||||||
|
Flags.
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 数据单元标识符 | 类型标志 | 1字节 |
|
||||||
|
%% | 信息对象数目 | 1字节 |
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 信息对象1 | 信息体 |根据类型不周长度不同 |
|
||||||
|
%% | 时间标签1(a) | 6字节 |
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% | | |
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 信息对象n | 信息体n | 根据类型不同长度不同 |
|
||||||
|
%% | 时闻标签(b) | 6字节 |
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 对于某些特殊数据类型(a)(b),此项可为空
|
||||||
|
%% 数据单元标识符
|
||||||
|
|
||||||
decoder_appdata(Type, Len, Bodys) ->
|
%%启动符 业务流水号 协议版本号 时间标签 源地址 目的地址 应用数据单元长度 命令字节 应用数据单元 校验和 结束符
|
||||||
{Key, BodyLen} = get_delen(Type),
|
%%火警
|
||||||
?LOG(info, "BodyLen ~p", [BodyLen]),
|
%%4040 3113 1000 160F11030316 000000000000 C0A801046D1D 0A00 02 18010200160F11030316 16 2323
|
||||||
ShortLen = Len * BodyLen,
|
parse_userzone(<<Type:8, Num:8, InfoBodys/binary>>) ->
|
||||||
LongLen = Len * (BodyLen + 6),
|
{Key, Len} = get_infobody_len(Type),
|
||||||
|
?LOG(info, "Type ~p Num ~p Len ~p", [Type, Num, Len]),
|
||||||
|
ShortLen = Num * Len,
|
||||||
|
LongLen = Num * (Len + 6),
|
||||||
NewBodys =
|
NewBodys =
|
||||||
case size(Bodys) of
|
case size(InfoBodys) of
|
||||||
ShortLen ->
|
ShortLen ->
|
||||||
[decoder_appdata(Type, {Body, #{}}) || <<Body:BodyLen/binary>> <= Bodys];
|
[parse_infobody(Type, {InfoBody, #{}}) || <<InfoBody:Len/binary>> <= InfoBodys];
|
||||||
LongLen ->
|
LongLen ->
|
||||||
[decoder_appdata(Type, {Body, #{<<"timestamp">> => get_timestamp(Time)}}) || <<Body:BodyLen/binary, Time:6/binary>> <= Bodys];
|
[parse_infobody(Type, {InfoBody, #{<<"timestamp">> => get_timestamp(Time)}}) || <<InfoBody:Len/binary, Time:6/binary>> <= InfoBodys];
|
||||||
_ ->
|
_ ->
|
||||||
[]
|
[]
|
||||||
end,
|
end,
|
||||||
?LOG(info, "Key ~p~n", [Key]),
|
|
||||||
?LOG(info, "Bodys ~p~n", [NewBodys]),
|
|
||||||
#{Key => NewBodys}.
|
#{Key => NewBodys}.
|
||||||
|
|
||||||
decoder_appdata(?TYPE_UP_SYSTEM_STATE, {<<Type:8, Addr:8, Flag:16>>, Timestamp}) ->
|
%%--------------------------------------------------------
|
||||||
|
%% 18 01 |
|
||||||
|
%%--------------------------------------------------------
|
||||||
|
%%| 02 | 00 | 160F | 11030316 |
|
||||||
|
%%--------------------------------------------------------
|
||||||
|
%%| 系统类型标记 | 系统地址 | 系统状态 | 状态发生时间 |
|
||||||
|
%%---------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% |bit15|bit14|bit13|bit12 |bit11 |bit10 |bit9 |bit8 |bit7 |bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0 |
|
||||||
|
%% 1 |预留 |预留 |复位 |配置改变 |手动状态|总线故障|备电故障|主电故障|延时状态|反馈 |启动(开启)|监管 |屏蔽 |故障 |火警 |正常运行状态 |
|
||||||
|
%% 0 |预留 |预留 |正常 |无配置改变|自动状态|总线正常|备电正常|主电异常|未延时 |无反馈 |停止(关闭)|无监管|无屏蔽|无故障|无火警 |测试状态 |
|
||||||
|
%%---------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
parse_infobody(?CLASS_UP_SYSTEM_STATE, {<<Type:8, Addr:8, Flag:2/binary>>, Timestamp}) ->
|
||||||
maps:merge(#{<<"equ">> => #{
|
maps:merge(#{<<"equ">> => #{
|
||||||
<<"ctrl">> => #{
|
<<"ctrl">> => #{
|
||||||
<<"type">> => Type,
|
<<"type">> => Type,
|
||||||
<<"addr">> => Addr
|
<<"addr">> => Addr
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
<<"flag">> => dgiot_utils:binary_to_hex(reverse(Flag))
|
<<"flag">> => get_flag(?CLASS_UP_SYSTEM_STATE, reverse(Flag))
|
||||||
}, Timestamp);
|
}, Timestamp);
|
||||||
|
|
||||||
decoder_appdata(?TYPE_UP_RUNNING_STATUS, {<<Type:8, Addr:8, Type2:8, Addr2:4/binary, Flag:2/binary, Description:31/binary>>, Timestamp}) ->
|
%%------------------------
|
||||||
|
%%光电探测器火警(光电感烟)|
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%40 40 14 00 10 00 05 09 09 1b 07 15 2c 31 2c 32 00 00 78 4d 07 91 8e 23 30 00 02 02 01 01 01 2a 01 00 01 00 02 00 31 ba c5 bd d3 bf da b0 e5 31 bb d8 c2 b7 31 ba c5 00 ba c5 d6 f7 bb fa f8 98 cf a0 00 00 00 25 11 03 01 06 0c 47 23 23|
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%|启动符 |业务流水号| 协议版本号 |时间标签 |源地址 |目的地址|应用数据单元长度|命令字节|应用数据单元|校验和|结束符|
|
||||||
|
%%|40401400| 1000 | 0509091b0715|2c312c320000|784d07918e23|3000 |0202 |01 |XXXX..XX | 47 | 2323 |
|
||||||
|
%%-----------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%| 类型标识符(1字节)|信息对象数目(1字节) |
|
||||||
|
%%| 02 | 02 |
|
||||||
|
%%见8.2.1.1的定义
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%|系统类型|系统地址|部件类型|部件地址|部件状态|部件说明 | 状态发生时间|
|
||||||
|
%%|(1字节) |(1字节)|(1字节) |(4字节) |(2字节) |(31字节) |6字节 |
|
||||||
|
%%|01 | 01 |2a |01000100|0200 |31bac5bdd3bfdab0e531bbd8c2b731bac500bac5d6f7bbfaf898cfa0000000|25110301060c|
|
||||||
|
%%------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%建筑消防设施系统类型标志、系统地址分别为1字节二进制数
|
||||||
|
%%建筑消防设施部件类型标志符为1字节二进制数,定义如表5所示。
|
||||||
|
%%建筑消防设施部件地址为4字节二进制数,建筑消防设施部件状态数据为2字节,低字节先传输。
|
||||||
|
%%|部件状态|
|
||||||
|
%%-------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%% |bit15|bit14|bit13|bit12|bit11|bit10|bit9|bit8 |bit7 |bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0 |
|
||||||
|
%% 1 |预留 |预留 |预留 |预留 |预留 |预留 |预留 |电源故障|延时状态|反馈 |启动(开启)|监管 |屏蔽 |故障 |火警 |正常运行状态|
|
||||||
|
%% 0 |预留 |预留 |预留 |预留 |预留 |预留 |预留 |电源正常|未延时 |无反馈 |停止(关闭)|无监管|无屏蔽|无故障|无火警 |测试状态 |
|
||||||
|
%%-------------------------------------------------------------------------------------------------------------------------
|
||||||
|
%%建筑消防设施部件说明为31字节的字符串,采用GB 18030--2005规定的编码。
|
||||||
|
%%状态发生时间
|
||||||
|
parse_infobody(?CLASS_UP_RUNNING_STATUS, {<<Type:8, Addr:8, Type2:8, Addr2:4/binary, Flag:2/binary, Description:31/binary>>, Timestamp}) ->
|
||||||
maps:merge(#{<<"equ">> => #{
|
maps:merge(#{<<"equ">> => #{
|
||||||
<<"ctrl">> => #{
|
<<"ctrl">> => #{
|
||||||
<<"type">> => Type,
|
<<"type">> => Type,
|
||||||
@ -135,59 +277,65 @@ decoder_appdata(?TYPE_UP_RUNNING_STATUS, {<<Type:8, Addr:8, Type2:8, Addr2:4/bin
|
|||||||
<<"type">> => Type2,
|
<<"type">> => Type2,
|
||||||
<<"addr">> => dgiot_utils:binary_to_hex(reverse(Addr2))
|
<<"addr">> => dgiot_utils:binary_to_hex(reverse(Addr2))
|
||||||
},
|
},
|
||||||
<<"flag">> => dgiot_utils:binary_to_hex(reverse(Flag)),
|
<<"flag">> => get_flag(?CLASS_UP_RUNNING_STATUS, reverse(Flag)),
|
||||||
<<"description">> => dgiot_utils:binary_to_hex(Description)
|
<<"description">> => dgiot_utils:binary_to_hex(Description)
|
||||||
}, Timestamp);
|
}, Timestamp);
|
||||||
|
|
||||||
%%decoder_appdata(?TYPE_UP_ANALOG_QUANTITY, Len, Body) ->
|
|
||||||
%%
|
|
||||||
%% #{};
|
|
||||||
%%decoder_appdata(?TYPE_UP_OPERATING_INFORMATION, Len, Body) ->
|
|
||||||
%%
|
|
||||||
%% #{};
|
|
||||||
%%decoder_appdata(?TYPE_UP_SYSTEM_CONFIGURATION, Len, Body) ->
|
|
||||||
%%
|
|
||||||
%% #{};
|
|
||||||
%%decoder_appdata(?TYPE_UP_PARTS_CONFIGURATION, Len, Body) ->
|
|
||||||
%%
|
|
||||||
%% #{};
|
|
||||||
%%decoder_appdata(?TYPE_UP_SYSTEM_TIME, Len, Body) ->
|
|
||||||
%%
|
|
||||||
%% #{};
|
|
||||||
|
|
||||||
|
%%---------------------------------------------------------------------------------------------
|
||||||
|
%% |bit7|bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0 |
|
||||||
|
%%---------------------------------------------------------------------------------------------
|
||||||
|
%% 1|预留|监测连接线路故障|与监控中心通信信道故障 |备电故障|主电故障 |故障 |火警 |正常监视状态|
|
||||||
|
%% 0|预留|监测连接线路正常|通信倍道正常 |备电异常|主电异常 |无故障 |无火警|测试状态 |
|
||||||
|
%%---------------------------------------------------------------------------------------------
|
||||||
|
%% 类型标志符 21
|
||||||
|
parse_infobody(?CLASS_UP_USERDEV_RUNINFO, {<<Flag:1/binary>>, Timestamp}) ->
|
||||||
|
maps:merge(#{
|
||||||
|
<<"equ">> => #{
|
||||||
|
<<"ctrl">> => #{
|
||||||
|
<<"type">> => ?CLASS_UP_USERDEV_RUNINFO}
|
||||||
|
},
|
||||||
|
<<"flag">> => get_flag(?CLASS_UP_USERDEV_RUNINFO, Flag)
|
||||||
|
}, Timestamp);
|
||||||
|
%%
|
||||||
|
%%-------------------------------------------------------------
|
||||||
|
%% |bit7|bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0 |
|
||||||
|
%%-------------------------------------------------------------
|
||||||
|
%% 1|预留|测试 |查岗应答|自检 |警情消除|手动报警|消音 |复位 |
|
||||||
|
%% 0|预留|无操作|无操作 |无操作|无操作 |无操作 |无操作|无操作|
|
||||||
|
%%-------------------------------------------------------------
|
||||||
|
%% 类型标志符 24
|
||||||
|
%%
|
||||||
|
parse_infobody(?CLASS_UP_USERDEV_OPINFO, {<<Flag:1/binary, Addr:8>>, Timestamp}) ->
|
||||||
|
maps:merge(#{
|
||||||
|
<<"equ">> => #{
|
||||||
|
<<"ctrl">> => #{
|
||||||
|
<<"type">> => ?CLASS_UP_USERDEV_OPINFO,
|
||||||
|
<<"addr">> => Addr}
|
||||||
|
},
|
||||||
|
<<"flag">> => get_flag(?CLASS_UP_USERDEV_OPINFO, Flag)
|
||||||
|
}, Timestamp);
|
||||||
|
|
||||||
decoder_appdata(_Type, {_Body, _Timestamp}) ->
|
parse_infobody(_Type, {_InfoBody, _Acc}) ->
|
||||||
?LOG(info, "_Type ~p", [_Type]),
|
?LOG(info, "_Type ~p", [_Type]),
|
||||||
?LOG(info, "_Body ~p", [_Body]),
|
?LOG(info, "_InfoBody ~p", [_InfoBody]),
|
||||||
?LOG(info, "_Timestamp ~p", [_Timestamp]),
|
?LOG(info, "_Acc ~p", [_Acc]),
|
||||||
#{}.
|
#{}.
|
||||||
|
|
||||||
%%
|
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := ?COMMAND_CONTROL, <<"data">> := Appdata}, Opts) ->
|
get_infobody_len(Type) ->
|
||||||
%%
|
case Type of
|
||||||
%% ok;
|
?CLASS_UP_SYSTEM_STATE ->
|
||||||
%%
|
{<<"systemstate">>, 4};
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := ?COMMAND_SEND_DATA, <<"data">> := Appdata}, Opts) ->
|
?CLASS_UP_RUNNING_STATUS ->
|
||||||
%%
|
{<<"runningstatus">>, 40};
|
||||||
%% ok;
|
?CLASS_UP_USERDEV_RUNINFO ->
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := ?COMMAND_CONFIRM, <<"data">> := Appdata}, Opts) ->
|
{<<"userdev_runinfo">>, 1};
|
||||||
%%
|
?CLASS_UP_USERDEV_OPINFO ->
|
||||||
%% ok;
|
{<<"userdev_opinfo">>, 2};
|
||||||
%%
|
_ ->
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := ?COMMAND_REQUEST, <<"data">> := Appdata}, Opts) ->
|
{<<"unknow">>, 4}
|
||||||
%%
|
end.
|
||||||
%% ok;
|
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := ?COMMAND_RESPONSE, <<"data">> := Appdata}, Opts) ->
|
|
||||||
%%
|
|
||||||
%% ok;
|
|
||||||
%%
|
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := ?COMMAND_DENY, <<"data">> := Appdata}, Opts) ->
|
|
||||||
%%
|
|
||||||
%% ok;
|
|
||||||
%%
|
|
||||||
%%parse_userzone(#{<<"msgtype">> := ?GB26875, <<"command">> := _, <<"data">> := _}, _Opts) ->
|
|
||||||
%%
|
|
||||||
%% ok.
|
|
||||||
|
|
||||||
to_frame(Frame) ->
|
to_frame(Frame) ->
|
||||||
to_frame_last(Frame).
|
to_frame_last(Frame).
|
||||||
@ -198,7 +346,7 @@ to_frame_last(#{
|
|||||||
<<"version">> := Version,
|
<<"version">> := Version,
|
||||||
<<"timestamp">> := Timestamp,
|
<<"timestamp">> := Timestamp,
|
||||||
<<"source">> := Source,
|
<<"source">> := Source,
|
||||||
<<"target">> := Target
|
<<"destination">> := Destination
|
||||||
},
|
},
|
||||||
<<"action">> := Action
|
<<"action">> := Action
|
||||||
} = Frame) ->
|
} = Frame) ->
|
||||||
@ -212,7 +360,7 @@ to_frame_last(#{
|
|||||||
put(number, SerialId),
|
put(number, SerialId),
|
||||||
Time = get_time(Timestamp),
|
Time = get_time(Timestamp),
|
||||||
ReverseSource = reverse(dgiot_utils:hex_to_binary(Source)),
|
ReverseSource = reverse(dgiot_utils:hex_to_binary(Source)),
|
||||||
ReverseTarget = reverse(dgiot_utils:hex_to_binary(Target)),
|
ReverseTarget = reverse(dgiot_utils:hex_to_binary(Destination)),
|
||||||
Header = <<SerialId:16, Version:16, Time:6/binary, ReverseSource:6/binary, ReverseTarget:6/binary>>,
|
Header = <<SerialId:16, Version:16, Time:6/binary, ReverseSource:6/binary, ReverseTarget:6/binary>>,
|
||||||
Appdata = encoder_appdata(Frame),
|
Appdata = encoder_appdata(Frame),
|
||||||
Length = size(Appdata),
|
Length = size(Appdata),
|
||||||
@ -243,8 +391,11 @@ set_time(Body) ->
|
|||||||
|
|
||||||
get_enlen(Type) ->
|
get_enlen(Type) ->
|
||||||
case Type of
|
case Type of
|
||||||
<<"systemstate">> -> {?TYPE_UP_SYSTEM_STATE, 4};
|
<<"systemstate">> ->
|
||||||
<<"runningstatus">> -> {?TYPE_UP_RUNNING_STATUS, 40};
|
{?CLASS_UP_SYSTEM_STATE, 4};
|
||||||
|
<<"runningstatus">> ->
|
||||||
|
%% 40 40 14 00 10 00 05 09 09 1b 07 15 2c 31 2c 32 00 00 78 4d 07 91 8e 23 30 00 02 02 01 01 01 2a 01 00 01 00 02 00 31 ba c5 bd d3 bf da b0 e5 31 bb d8 c2 b7 31 ba c5 00 ba c5 d6 f7 bb fa f8 98 cf a0 00 00 00 25 11 03 01 06 0c 47 23 23
|
||||||
|
{?CLASS_UP_RUNNING_STATUS, 40};
|
||||||
_ ->
|
_ ->
|
||||||
{<<"unknow">>, 4}
|
{<<"unknow">>, 4}
|
||||||
end.
|
end.
|
||||||
|
27
apps/dgiot_gb26875/src/protocol/dgiot_gb26875_utils.erl
Normal file
27
apps/dgiot_gb26875/src/protocol/dgiot_gb26875_utils.erl
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Copyright (c) 2020-2021 DGIOT Technologies Co., Ltd. All Rights Reserved.
|
||||||
|
%%
|
||||||
|
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
%% you may not use this file except in compliance with the License.
|
||||||
|
%% You may obtain a copy of the License at
|
||||||
|
%%
|
||||||
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
%%
|
||||||
|
%% Unless required by applicable law or agreed to in writing, software
|
||||||
|
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
%% See the License for the specific language governing permissions and
|
||||||
|
%% limitations under the License.
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(dgiot_gb26875_utils).
|
||||||
|
-include_lib("dgiot_gb26875.hrl").
|
||||||
|
-author("stoneliu").
|
||||||
|
-include_lib("dgiot/include/logger.hrl").
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([get_equ_type/1]).
|
||||||
|
|
||||||
|
|
||||||
|
get_equ_type(_Type) ->
|
||||||
|
ok.
|
@ -1216,15 +1216,24 @@ function pre_build_dgiot() {
|
|||||||
|
|
||||||
cd ${script_dir}/
|
cd ${script_dir}/
|
||||||
|
|
||||||
if [ ! -d ${script_dir}/dgiot/ ]; then
|
if [ ! -d ${script_dir}/$plugin/ ]; then
|
||||||
git clone root@git.iotn2n.com:dgiot/dgiot.git
|
git clone https://gitee.com/dgiiot/dgiot.git $plugin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ${script_dir}/dgiot/
|
cd ${script_dir}/$plugin/
|
||||||
git reset --hard
|
git reset --hard
|
||||||
git pull
|
git pull
|
||||||
|
|
||||||
rm ${script_dir}/dgiot/_build/emqx/rel/ -rf
|
if [ $plugin == 'dgiot' ]; then
|
||||||
|
echo "dgiot plugin"
|
||||||
|
else
|
||||||
|
cd ${script_dir}/$plugin/apps/
|
||||||
|
rm $plugin -rf
|
||||||
|
git clone root@git.iotn2n.com:dgiot/$plugin.git
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd ${script_dir}
|
||||||
|
rm ${script_dir}/$plugin/_build/emqx/rel/ -rf
|
||||||
|
|
||||||
if [ -d ${script_dir}/dgiot_dashboard/dist ]; then
|
if [ -d ${script_dir}/dgiot_dashboard/dist ]; then
|
||||||
rm ${script_dir}/$plugin/_build/emqx/lib/dgiot_api -rf
|
rm ${script_dir}/$plugin/_build/emqx/lib/dgiot_api -rf
|
||||||
@ -1236,19 +1245,6 @@ function pre_build_dgiot() {
|
|||||||
rm ${script_dir}/dgiot/emqx/rel -rf
|
rm ${script_dir}/dgiot/emqx/rel -rf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -d ${script_dir}/$plugin/ ]; then
|
|
||||||
git clone https://gitee.com/dgiiot/dgiot.git $plugin
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d ${script_dir}/$plugin/apps/$plugin/ ]; then
|
|
||||||
cd ${script_dir}/$plugin/apps/
|
|
||||||
git clone root@git.iotn2n.com:dgiot/$plugin.git
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ${script_dir}/$plugin/
|
|
||||||
git reset --hard
|
|
||||||
git pull
|
|
||||||
|
|
||||||
rm ${script_dir}/$plugin/rebar.config -rf
|
rm ${script_dir}/$plugin/rebar.config -rf
|
||||||
cp ${script_dir}/$plugin/apps/$plugin/conf/rebar.config ${script_dir}/$plugin/rebar.config -rf
|
cp ${script_dir}/$plugin/apps/$plugin/conf/rebar.config ${script_dir}/$plugin/rebar.config -rf
|
||||||
rm ${script_dir}/$plugin/rebar.config.erl -rf
|
rm ${script_dir}/$plugin/rebar.config.erl -rf
|
||||||
@ -1355,4 +1351,4 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "`date +%F_%T` $LINENO: ${GREEN} dgiot ${verType} deploy success end${NC}"
|
echo -e "`date +%F_%T` $LINENO: ${GREEN} dgiot ${verType} deploy success end${NC}"
|
Loading…
Reference in New Issue
Block a user