2756 lines
91 KiB
Erlang
2756 lines
91 KiB
Erlang
%%--------------------------------------------------------------------
|
|
%% Copyright (c) 2023-2024 EMQ Technologies Co., Ltd. All Rights Reserved.
|
|
%%--------------------------------------------------------------------
|
|
|
|
-module(emqx_jt808_SUITE).
|
|
|
|
-compile(export_all).
|
|
-compile(nowarn_export_all).
|
|
|
|
-include("emqx_jt808.hrl").
|
|
-include_lib("emqx/include/emqx.hrl").
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-include_lib("common_test/include/ct.hrl").
|
|
|
|
-define(FRM_FLAG, 16#7e:8).
|
|
-define(RESERVE, 0).
|
|
-define(NO_FRAGMENT, 0).
|
|
-define(WITH_FRAGMENT, 1).
|
|
-define(NO_ENCRYPT, 0).
|
|
-define(MSG_SIZE(X), X:10 / big - integer).
|
|
|
|
-define(WORD, 16 / big - integer).
|
|
-define(DWORD, 32 / big - integer).
|
|
|
|
-define(PORT, 6207).
|
|
-define(PORT_STR, "6207").
|
|
-define(LOGT(Format, Args), ct:pal("TEST_SUITE: " ++ Format, Args)).
|
|
|
|
-define(PROTO_REG_SERVER_HOST, "http://127.0.0.1:8991").
|
|
-define(PROTO_REG_AUTH_PATH, "/jt808/auth").
|
|
-define(PROTO_REG_REGISTRY_PATH, "/jt808/registry").
|
|
|
|
-define(JT808_PHONE, "000123456789").
|
|
%% <<"jt808/000123456789/">>
|
|
-define(JT808_MOUNTPOINT, "jt808/" ?JT808_PHONE "/").
|
|
%% <<"jt808/000123456789/000123456789/up">>
|
|
-define(JT808_UP_TOPIC, <<?JT808_MOUNTPOINT, ?JT808_PHONE, "/up">>).
|
|
%% <<"jt808/000123456789/000123456789/dn">>
|
|
-define(JT808_DN_TOPIC, <<?JT808_MOUNTPOINT, ?JT808_PHONE, "/dn">>).
|
|
|
|
%% erlfmt-ignore
|
|
-define(CONF_DEFAULT, <<"
|
|
gateway.jt808 {
|
|
listeners.tcp.default {
|
|
bind = ", ?PORT_STR, "
|
|
}
|
|
proto {
|
|
auth {
|
|
allow_anonymous = false
|
|
registry = \"", ?PROTO_REG_SERVER_HOST, ?PROTO_REG_REGISTRY_PATH, "\"
|
|
authentication = \"", ?PROTO_REG_SERVER_HOST, ?PROTO_REG_AUTH_PATH, "\"
|
|
}
|
|
}
|
|
}
|
|
">>).
|
|
|
|
%% erlfmt-ignore
|
|
-define(CONF_ANONYMOUS, <<"
|
|
gateway.jt808 {
|
|
listeners.tcp.default {
|
|
bind = ", ?PORT_STR, "
|
|
}
|
|
proto {
|
|
auth {
|
|
allow_anonymous = true
|
|
}
|
|
}
|
|
}
|
|
">>).
|
|
|
|
all() ->
|
|
emqx_common_test_helpers:all(?MODULE).
|
|
|
|
init_per_suite(Config) ->
|
|
Config.
|
|
|
|
end_per_suite(_Config) ->
|
|
ok.
|
|
|
|
init_per_testcase(Case = t_case02_anonymous_register_and_auth, Config) ->
|
|
Apps = boot_apps(Case, ?CONF_ANONYMOUS, Config),
|
|
[{suite_apps, Apps} | Config];
|
|
init_per_testcase(Case, Config) when
|
|
Case =:= t_create_ALLOW_invalid_auth_config;
|
|
Case =:= t_create_DISALLOW_invalid_auth_config
|
|
->
|
|
Apps = boot_apps(Case, <<>>, Config),
|
|
[{suite_apps, Apps} | Config];
|
|
init_per_testcase(Case, Config) ->
|
|
Apps = boot_apps(Case, ?CONF_DEFAULT, Config),
|
|
[{suite_apps, Apps} | Config].
|
|
|
|
end_per_testcase(_Case, Config) ->
|
|
try
|
|
ok = emqx_jt808_auth_http_test_server:stop()
|
|
catch
|
|
exit:noproc ->
|
|
ok
|
|
end,
|
|
ok = emqx_cth_suite:stop(?config(suite_apps, Config)),
|
|
ok.
|
|
|
|
boot_apps(Case, JT808Conf, Config) ->
|
|
Apps = emqx_cth_suite:start(
|
|
[
|
|
emqx,
|
|
{emqx_conf, JT808Conf},
|
|
emqx_gateway
|
|
],
|
|
#{work_dir => emqx_cth_suite:work_dir(Case, Config)}
|
|
),
|
|
{ok, _Pid} = emqx_jt808_auth_http_test_server:start_link(),
|
|
timer:sleep(1000),
|
|
Apps.
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% helper functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
gen_packet(Header, Body) ->
|
|
S1 = <<Header/binary, Body/binary>>,
|
|
Crc = make_crc(S1, undefined),
|
|
S2 = do_escape(<<S1/binary, Crc:8>>),
|
|
Stream = <<16#7e:8, S2/binary, 16#7e:8>>,
|
|
?LOGT("encode a packet=~p", [binary_to_hex_string(Stream)]),
|
|
Stream.
|
|
|
|
make_crc(<<>>, Xor) ->
|
|
?LOGT("crc is ~p", [Xor]),
|
|
Xor;
|
|
make_crc(<<C:8, Rest/binary>>, undefined) ->
|
|
make_crc(Rest, C);
|
|
make_crc(<<C:8, Rest/binary>>, Xor) ->
|
|
make_crc(Rest, C bxor Xor).
|
|
|
|
do_escape(Binary) ->
|
|
do_escape(Binary, <<>>).
|
|
|
|
do_escape(<<>>, Acc) ->
|
|
Acc;
|
|
do_escape(<<16#7e, Rest/binary>>, Acc) ->
|
|
do_escape(Rest, <<Acc/binary, 16#7d, 16#02>>);
|
|
do_escape(<<16#7d, Rest/binary>>, Acc) ->
|
|
do_escape(Rest, <<Acc/binary, 16#7d, 16#01>>);
|
|
do_escape(<<C, Rest/binary>>, Acc) ->
|
|
do_escape(Rest, <<Acc/binary, C:8>>).
|
|
|
|
client_regi_procedure(Socket) ->
|
|
client_regi_procedure(Socket, <<"123456">>).
|
|
|
|
client_regi_procedure(Socket, ExpectedCode) ->
|
|
%
|
|
% send REGISTER
|
|
%
|
|
Manuf = <<"examp">>,
|
|
Model = <<"33333333333333333333">>,
|
|
DevId = <<"1234567">>,
|
|
|
|
Color = 3,
|
|
Plate = <<"ujvl239">>,
|
|
RegisterPacket =
|
|
<<58:?WORD, 59:?WORD, Manuf/binary, Model/binary, DevId/binary, Color, Plate/binary>>,
|
|
MsgId = ?MC_REGISTER,
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
MsgSn = 78,
|
|
Size = size(RegisterPacket),
|
|
Header =
|
|
<<MsgId:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size), PhoneBCD/binary,
|
|
MsgSn:?WORD>>,
|
|
S1 = gen_packet(Header, RegisterPacket),
|
|
|
|
ok = gen_tcp:send(Socket, S1),
|
|
{ok, Packet} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
AckPacket = <<MsgSn:?WORD, 0, ExpectedCode/binary>>,
|
|
Size2 = size(AckPacket),
|
|
MsgId2 = ?MS_REGISTER_ACK,
|
|
MsgSn2 = 0,
|
|
Header2 =
|
|
<<MsgId2:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size2),
|
|
PhoneBCD/binary, MsgSn2:?WORD>>,
|
|
S2 = gen_packet(Header2, AckPacket),
|
|
?LOGT("S2=~p", [binary_to_hex_string(S2)]),
|
|
?LOGT("Packet=~p", [binary_to_hex_string(Packet)]),
|
|
?assertEqual(S2, Packet),
|
|
{ok, ExpectedCode}.
|
|
|
|
client_auth_procedure(Socket, AuthCode) ->
|
|
?LOGT("start auth procedure", []),
|
|
%
|
|
% send AUTH
|
|
%
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
MsgId = ?MC_AUTH,
|
|
MsgSn = 78,
|
|
Size = size(AuthCode),
|
|
Header =
|
|
<<MsgId:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size), PhoneBCD/binary,
|
|
MsgSn:?WORD>>,
|
|
S1 = gen_packet(Header, AuthCode),
|
|
?LOGT("auth S1=~p", [S1]),
|
|
|
|
ok = gen_tcp:send(Socket, S1),
|
|
%% timer:sleep(200),
|
|
{ok, Packet} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket = <<MsgSn:?WORD, MsgId:?WORD, 0>>,
|
|
Size2 = size(GenAckPacket),
|
|
MsgId2 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn2 = 1,
|
|
Header2 =
|
|
<<MsgId2:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size2),
|
|
PhoneBCD/binary, MsgSn2:?WORD>>,
|
|
S2 = gen_packet(Header2, GenAckPacket),
|
|
?assertEqual(S2, Packet),
|
|
?assert(lists:member(?JT808_DN_TOPIC, emqx:topics())),
|
|
|
|
?LOGT("============= auth procedure success ===============", []).
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD) ->
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MC_GENERAL_RESPONSE,
|
|
MsgSn4 = 1,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
ok.
|
|
|
|
location_report() ->
|
|
Alarm = 2,
|
|
Status = 3,
|
|
Latitude = 1000,
|
|
Longitude = 1001,
|
|
Altitude = 2000,
|
|
Speed = 135,
|
|
Direction = 32,
|
|
TimeBCD = <<16#17, 16#10, 16#22, 16#11, 16#15, 16#53>>,
|
|
Time = <<"171022111553">>,
|
|
MileAge = 12379,
|
|
FuelMeter = 972,
|
|
Speed2 = 29,
|
|
AlarmID = 18,
|
|
OA_Type = 2,
|
|
OA_Id = 29,
|
|
IOA_Type = 8,
|
|
IOA_Id = 23,
|
|
IOA_Direction = 89,
|
|
PTA_ID = 45,
|
|
PTA_Time = 21,
|
|
PTA_Result = 1,
|
|
Binary =
|
|
<<Alarm:?DWORD, Status:?DWORD, Latitude:?DWORD, Longitude:?DWORD, Altitude:?WORD,
|
|
Speed:?WORD, Direction:?WORD, TimeBCD:6/binary, 16#01:8, 4:8, MileAge:?DWORD, 16#02:8,
|
|
2:8, FuelMeter:?WORD, 16#03:8, 2:8, Speed2:?WORD, 16#04:8, 2:8, AlarmID:?WORD, 16#11:8,
|
|
5:8, OA_Type:8, OA_Id:?DWORD, 16#12:8, 6:8, IOA_Type:8, IOA_Id:?DWORD, IOA_Direction:8,
|
|
16#13:8, 7:8, PTA_ID:?DWORD, PTA_Time:?WORD, PTA_Result:8>>,
|
|
Json = #{
|
|
<<"alarm">> => Alarm,
|
|
<<"status">> => Status,
|
|
<<"latitude">> => Latitude,
|
|
<<"longitude">> => Longitude,
|
|
<<"altitude">> => Altitude,
|
|
<<"speed">> => Speed,
|
|
<<"direction">> => Direction,
|
|
<<"time">> => Time,
|
|
<<"extra">> => #{
|
|
<<"mileage">> => MileAge,
|
|
<<"fuel_meter">> => FuelMeter,
|
|
<<"speed">> => Speed2,
|
|
<<"alarm_id">> => AlarmID,
|
|
<<"overspeed_alarm">> =>
|
|
#{
|
|
<<"type">> => OA_Type,
|
|
<<"id">> => OA_Id
|
|
},
|
|
<<"in_out_alarm">> =>
|
|
#{
|
|
<<"type">> => IOA_Type,
|
|
<<"id">> => IOA_Id,
|
|
<<"direction">> => IOA_Direction
|
|
},
|
|
<<"path_time_alarm">> =>
|
|
#{
|
|
<<"id">> => PTA_ID,
|
|
<<"time">> => PTA_Time,
|
|
<<"result">> => PTA_Result
|
|
}
|
|
}
|
|
},
|
|
{Binary, Json}.
|
|
|
|
location_report_28bytes() ->
|
|
Alarm = 2,
|
|
Status = 3,
|
|
Latitude = 1000,
|
|
Longitude = 1001,
|
|
Altitude = 2000,
|
|
Speed = 135,
|
|
Direction = 32,
|
|
TimeBCD = <<16#17, 16#10, 16#22, 16#11, 16#15, 16#53>>,
|
|
Time = <<"171022111553">>,
|
|
Binary =
|
|
<<Alarm:?DWORD, Status:?DWORD, Latitude:?DWORD, Longitude:?DWORD, Altitude:?WORD,
|
|
Speed:?WORD, Direction:?WORD, TimeBCD:6/binary>>,
|
|
Json = #{
|
|
<<"alarm">> => Alarm,
|
|
<<"status">> => Status,
|
|
<<"latitude">> => Latitude,
|
|
<<"longitude">> => Longitude,
|
|
<<"altitude">> => Altitude,
|
|
<<"speed">> => Speed,
|
|
<<"direction">> => Direction,
|
|
<<"time">> => Time
|
|
},
|
|
{Binary, Json}.
|
|
|
|
binary_to_hex_string(Data) ->
|
|
lists:flatten([io_lib:format("~2.16.0B ", [X]) || <<X:8>> <= Data]).
|
|
|
|
receive_msg() ->
|
|
receive
|
|
{deliver, Topic, #message{payload = Payload}} ->
|
|
{Topic, Payload}
|
|
after 100 ->
|
|
{error, timeout}
|
|
end.
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% test cases %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
t_case00_register(_) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
?assertEqual(AuthCode, <<"123456">>),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case01_auth(_) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}, {nodelay, true}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case02_anonymous_register_and_auth(_) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
|
|
{ok, AuthCode} = client_regi_procedure(Socket, <<>>),
|
|
?assertEqual(AuthCode, <<>>),
|
|
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case03_heartbeat(_) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
%
|
|
% send heartbeat
|
|
%
|
|
MsgId = ?MC_HEARTBEAT,
|
|
MsgSn = 78,
|
|
Size = 0,
|
|
Header =
|
|
<<MsgId:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size), PhoneBCD/binary,
|
|
MsgSn:?WORD>>,
|
|
S1 = gen_packet(Header, <<>>),
|
|
|
|
ok = gen_tcp:send(Socket, S1),
|
|
%% timer:sleep(200),
|
|
{ok, Packet} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
GenAckPacket = <<MsgSn:?WORD, MsgId:?WORD, 0>>,
|
|
Size2 = size(GenAckPacket),
|
|
MsgId2 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn2 = 2,
|
|
Header2 =
|
|
<<MsgId2:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size2),
|
|
PhoneBCD/binary, MsgSn2:?WORD>>,
|
|
S2 = gen_packet(Header2, GenAckPacket),
|
|
?assertEqual(S2, Packet),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case04(_) ->
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
%% send event report
|
|
EventReportId = 98,
|
|
MsgBody3 = <<EventReportId>>,
|
|
MsgId3 = ?MC_EVENT_REPORT,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
timer:sleep(100),
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{<<"id">> => EventReportId}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case05(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
Flag = 15,
|
|
Text = <<"who are you">>,
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SEND_TEXT},
|
|
<<"body">> => #{<<"flag">> => Flag, <<"text">> => Text}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
%
|
|
% client get downlink "send text"
|
|
%
|
|
|
|
MsgBody3 = <<Flag:8, Text/binary>>,
|
|
MsgId3 = ?MS_SEND_TEXT,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
?LOGT("S3=~p", [S3]),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
% client send "client general response"
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MC_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
%% timer:sleep(300),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case06_downlink_retx(_) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
Flag = 15,
|
|
Text = <<"who are you">>,
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SEND_TEXT},
|
|
<<"body">> => #{<<"flag">> => Flag, <<"text">> => Text}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
%
|
|
% client get downlink "send text"
|
|
%
|
|
|
|
MsgBody3 = <<Flag:8, Text/binary>>,
|
|
MsgId3 = ?MS_SEND_TEXT,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
?LOGT("S3=~p", [S3]),
|
|
|
|
%% wait emqx-jt808 to retx "send text"
|
|
timer:sleep(100),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
% client send "client general response"
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MC_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
%% timer:sleep(300),
|
|
|
|
% wait again, there should be no retx packet
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case07_dl_0x8302_send_question(_) ->
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
Flag = 16#10,
|
|
Question = <<"who are you">>,
|
|
Length = size(Question),
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SEND_QUESTION},
|
|
<<"body">> => #{
|
|
<<"flag">> => Flag,
|
|
<<"length">> => Length,
|
|
<<"question">> => Question,
|
|
<<"answers">> => [
|
|
#{<<"id">> => 1, <<"len">> => 3, <<"answer">> => <<"Tom">>},
|
|
#{<<"id">> => 2, <<"len">> => 4, <<"answer">> => <<"Mike">>}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%% client get downlink "send text"
|
|
MsgBody3 =
|
|
<<Flag:8, Length:8, Question/binary, 1:8, 3:?WORD, <<"Tom">>/binary, 2:8, 4:?WORD,
|
|
<<"Mike">>/binary>>,
|
|
MsgId3 = ?MS_SEND_QUESTION,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
% client send "client answer"
|
|
Answer = <<MsgSn3:?WORD, 2:8>>,
|
|
Size4 = size(Answer),
|
|
MsgId4 = ?MC_QUESTION_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, Answer),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId4,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size4,
|
|
<<"msg_sn">> => MsgSn4
|
|
},
|
|
<<"body">> => #{<<"seq">> => MsgSn3, <<"id">> => 2}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case08_dl_0x8500_vehicle_ctrl(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
Flag = 16#0,
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_VEHICLE_CONTROL},
|
|
<<"body">> => #{<<"flag">> => Flag}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink "vehicle ctrl"
|
|
%
|
|
MsgBody3 = <<Flag:8>>,
|
|
MsgId3 = ?MS_VEHICLE_CONTROL,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
% client send "client answer"
|
|
CtrlAck =
|
|
<<126, 5, 0, 0, 30, 1, 136, 118, 99, 137, 114, 1, 244, 0, 7, 0, 0, 0, 0, 0, 4, 0, 0, 1, 49,
|
|
122, 103, 6, 147, 104, 81, 0, 24, 0, 0, 0, 121, 23, 16, 32, 18, 3, 25, 69, 126>>,
|
|
?LOGT("S4 = ~p", [CtrlAck]),
|
|
|
|
ok = gen_tcp:send(Socket, CtrlAck),
|
|
timer:sleep(300),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> =>
|
|
#{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => 30,
|
|
<<"msg_id">> => 1280,
|
|
<<"msg_sn">> => 500,
|
|
<<"phone">> => <<"018876638972">>
|
|
},
|
|
<<"body">> =>
|
|
#{
|
|
<<"seq">> => 7,
|
|
<<"location">> => #{
|
|
<<"alarm">> => 0,
|
|
<<"altitude">> => 24,
|
|
<<"direction">> => 121,
|
|
<<"latitude">> => 20019815,
|
|
<<"longitude">> => 110323793,
|
|
<<"speed">> => 0,
|
|
<<"status">> => 262144,
|
|
<<"time">> => <<"171020120319">>
|
|
}
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case09_dl_0x8103_set_client_param(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
Length = 2,
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_CLIENT_PARAM},
|
|
<<"body">> => #{
|
|
<<"length">> => Length,
|
|
<<"params">> => [
|
|
#{<<"id">> => 16#0013, <<"value">> => <<"www.example.com">>},
|
|
#{<<"id">> => 16#0059, <<"value">> => 1200}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink "vehicle ctrl"
|
|
%
|
|
MsgBody3 =
|
|
<<Length:8, 16#0013:?DWORD, 15:8, <<"www.example.com">>/binary, 16#0059:?DWORD, 4:8,
|
|
1200:?DWORD>>,
|
|
MsgId3 = ?MS_SET_CLIENT_PARAM,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
% client send "general response"
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MC_GENERAL_RESPONSE,
|
|
MsgSn4 = 1,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
|
|
% no retrasmition of 0x8103
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case10_dl_0x8104_query_client_all_param(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_CLIENT_CONTROL},
|
|
<<"body">> => #{<<"command">> => 200, <<"param">> => <<"ABCD">>}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<200:8, <<"ABCD">>/binary>>,
|
|
MsgId3 = ?MS_CLIENT_CONTROL,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
% client send ack
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
%% timer:sleep(200),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case11_dl_0x8106_query_client_param(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_QUERY_CLIENT_PARAM},
|
|
<<"body">> => #{<<"length">> => 2, <<"ids">> => [16#0092, 16#0031]}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<2:8, 16#0092:?DWORD, 16#0031:?DWORD>>,
|
|
MsgId3 = ?MS_QUERY_CLIENT_PARAM,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
UlPacket4 = <<MsgSn3:?WORD, 2:8, 16#0031:?DWORD, 2:8, 379:?WORD, 16#0092:?DWORD, 1:8, 2:8>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_QUERY_PARAM_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_QUERY_PARAM_ACK,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"seq">> => MsgSn3,
|
|
<<"length">> => 2,
|
|
<<"params">> => [
|
|
#{<<"id">> => 16#0031, <<"value">> => 379},
|
|
#{<<"id">> => 16#0092, <<"value">> => 2}
|
|
]
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
%% timer:sleep(200),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case11_dl_0x8107_query_client_attrib(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{<<"header">> => #{<<"msg_id">> => ?MS_QUERY_CLIENT_ATTRIB}},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<>>,
|
|
MsgId3 = ?MS_QUERY_CLIENT_ATTRIB,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
timer:sleep(100),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
UlPacket4 =
|
|
<<12:?WORD, <<"manu3">>/binary, <<"A1B2C3D4E5F6G7H8I9J0">>:20/binary,
|
|
<<"dev1234">>:7/binary,
|
|
<<16#33, 16#33, 16#33, 16#33, 16#33, 16#44, 16#44, 16#44, 16#44, 16#44>>:10/binary, 6:8,
|
|
<<"v2.3.7">>:6/binary, 5:8, <<"v1.26">>:5/binary, 101:8, 102:8>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_QUERY_ATTRIB_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_QUERY_ATTRIB_ACK,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"type">> => 12,
|
|
<<"manufacturer">> => <<"manu3">>,
|
|
<<"model">> => <<"A1B2C3D4E5F6G7H8I9J0">>,
|
|
<<"id">> => <<"dev1234">>,
|
|
<<"iccid">> => <<"33333333334444444444">>,
|
|
<<"hardware_version">> => <<"v2.3.7">>,
|
|
<<"firmware_version">> => <<"v1.26">>,
|
|
<<"gnss_prop">> => 101,
|
|
<<"comm_prop">> => 102
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case15_dl_0x8201_query_location(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{<<"header">> => #{<<"msg_id">> => ?MS_QUERY_LOCATION}},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<>>,
|
|
MsgId3 = ?MS_QUERY_LOCATION,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
{LocationReportBinary, LocationReportJson} = location_report(),
|
|
UlPacket4 = <<MsgSn3:?WORD, LocationReportBinary/binary>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_QUERY_LOCATION_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_QUERY_LOCATION_ACK,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"seq">> => MsgSn3,
|
|
<<"params">> => LocationReportJson
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
%% timer:sleep(200),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_location_report(_) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
{LocationReportBinary, LocationReportJson} = location_report(),
|
|
UlPacket = <<LocationReportBinary/binary>>,
|
|
Size = size(UlPacket),
|
|
MsgId = ?MC_LOCATION_REPORT,
|
|
MsgSn = 1,
|
|
Header =
|
|
<<MsgId:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size), PhoneBCD/binary,
|
|
MsgSn:?WORD>>,
|
|
S = gen_packet(Header, UlPacket),
|
|
?LOGT("S = ~p", [S]),
|
|
|
|
ok = gen_tcp:send(Socket, S),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size,
|
|
<<"msg_id">> => ?MC_LOCATION_REPORT,
|
|
<<"msg_sn">> => MsgSn,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => LocationReportJson
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
% receive general response
|
|
{ok, Packet} = gen_tcp:recv(Socket, 0, 500),
|
|
GenAckPacket = <<MsgSn:?WORD, MsgId:?WORD, 0>>,
|
|
Size2 = size(GenAckPacket),
|
|
MsgId2 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn2 = 2,
|
|
Header2 =
|
|
<<MsgId2:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size2),
|
|
PhoneBCD/binary, MsgSn2:?WORD>>,
|
|
S2 = gen_packet(Header2, GenAckPacket),
|
|
?assertEqual(S2, Packet),
|
|
|
|
% no retrasmition of downlink message
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case15_dl_0x8202_trace_location(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_TRACE_LOCATION},
|
|
<<"body">> => #{<<"period">> => 23, <<"expiry">> => 183}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<23:?WORD, 183:?DWORD>>,
|
|
MsgId3 = ?MS_TRACE_LOCATION,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case50_ul_0x0303_info_request_cancel(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
%
|
|
% send event report
|
|
%
|
|
MsgBody3 = <<1:8, 6:8>>,
|
|
MsgId3 = ?MC_INFO_REQ_CANCEL,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
%%timer:sleep(600),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{<<"id">> => 1, <<"flag">> => 6}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case51_ul_0x0701_waybill_report(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
%
|
|
% send event report
|
|
%
|
|
MsgBody3 = <<7:?DWORD, <<"ABCDEFG">>/binary>>,
|
|
MsgId3 = ?MC_WAYBILL_REPORT,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
%% timer:sleep(600),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{<<"length">> => 7, <<"data">> => base64:encode(<<"ABCDEFG">>)}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case52_ul_0x0705_can_bus_report(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
%
|
|
% send event report
|
|
%
|
|
MsgBody3 =
|
|
<<2:?WORD, <<16#09, 16#23, 16#46, 16#07, 16#25>>/binary, 0:1, 1:1, 0:1, 35:29,
|
|
<<"11111111">>/binary, 1:1, 0:1, 1:1, 36:29, <<"22222222">>/binary>>,
|
|
MsgId3 = ?MC_CAN_BUS_REPORT,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
%% timer:sleep(600),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{
|
|
<<"length">> => 2,
|
|
<<"time">> => <<"0923460725">>,
|
|
<<"can_data">> => [
|
|
#{
|
|
<<"channel">> => 0,
|
|
<<"frame_type">> => 1,
|
|
<<"data_method">> => 0,
|
|
<<"id">> => 35,
|
|
<<"data">> => base64:encode(<<"11111111">>)
|
|
},
|
|
#{
|
|
<<"channel">> => 1,
|
|
<<"frame_type">> => 0,
|
|
<<"data_method">> => 1,
|
|
<<"id">> => 36,
|
|
<<"data">> => base64:encode(<<"22222222">>)
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case53_ul_0x0800_multimedia_event_report(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
%
|
|
% send event report
|
|
%
|
|
MsgBody3 = <<65:?DWORD, 2:8, 1:8, 4:8, 103:8>>,
|
|
MsgId3 = ?MC_MULTIMEDIA_EVENT_REPORT,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
%% timer:sleep(600),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{
|
|
<<"id">> => 65,
|
|
<<"type">> => 2,
|
|
<<"format">> => 1,
|
|
<<"event">> => 4,
|
|
<<"channel">> => 103
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case54_ul_0x0900_send_transparent_data(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
%
|
|
% send event report
|
|
%
|
|
MsgBody3 = <<39:8, <<"oufwei">>/binary>>,
|
|
MsgId3 = ?MC_SEND_TRANSPARENT_DATA,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
%% timer:sleep(600),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% Receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{<<"type">> => 39, <<"data">> => base64:encode(<<"oufwei">>)}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case55_ul_0x0901_send_zip_data(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
%
|
|
% send event report
|
|
%
|
|
MsgBody3 = <<4:?DWORD, <<"1234">>/binary>>,
|
|
MsgId3 = ?MC_SEND_ZIP_DATA,
|
|
MsgSn3 = 79,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
ok = gen_tcp:send(Socket, S3),
|
|
%% timer:sleep(600),
|
|
{ok, Packet4} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
% receive general response
|
|
GenAckPacket4 = <<MsgSn3:?WORD, MsgId3:?WORD, 0>>,
|
|
Size4 = size(GenAckPacket4),
|
|
MsgId4 = ?MS_GENERAL_RESPONSE,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, GenAckPacket4),
|
|
?assertEqual(S4, Packet4),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"msg_id">> => MsgId3,
|
|
<<"encrypt">> => ?NO_ENCRYPT,
|
|
<<"phone">> => <<"000123456789">>,
|
|
<<"len">> => Size3,
|
|
<<"msg_sn">> => MsgSn3
|
|
},
|
|
<<"body">> => #{
|
|
<<"length">> => 4,
|
|
<<"data">> => base64:encode(<<"1234">>)
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case16_dl_0x8301_set_event(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_EVENT},
|
|
<<"body">> => #{
|
|
<<"type">> => 3,
|
|
<<"length">> => 2,
|
|
<<"events">> =>
|
|
[
|
|
#{<<"id">> => 56, <<"length">> => 3, <<"content">> => <<"111">>},
|
|
#{<<"id">> => 7, <<"length">> => 5, <<"content">> => <<"nwKdmww">>}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<3:8, 2:8, 56:8, 3:8, <<"111">>/binary, 7:8, 5:8, <<"nwKdmww">>/binary>>,
|
|
MsgId3 = ?MS_SET_EVENT,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case17_dl_0x8303_set_menu(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_MENU},
|
|
<<"body">> => #{
|
|
<<"type">> => 3,
|
|
<<"length">> => 2,
|
|
<<"menus">> =>
|
|
[
|
|
#{<<"type">> => 56, <<"length">> => 3, <<"info">> => <<"111">>},
|
|
#{<<"type">> => 7, <<"length">> => 5, <<"info">> => <<"nwKdmww">>}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%% client get downlink command
|
|
MsgBody3 = <<3:8, 2:8, 56:8, 3:?WORD, <<"111">>/binary, 7:8, 5:?WORD, <<"nwKdmww">>/binary>>,
|
|
MsgId3 = ?MS_SET_MENU,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case18_dl_0x8304_info_content(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_INFO_CONTENT},
|
|
<<"body">> => #{<<"type">> => 3, <<"length">> => 2, <<"info">> => <<"NY">>}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%% client get downlink command
|
|
MsgBody3 = <<3:8, 2:?WORD, <<"NY">>/binary>>,
|
|
MsgId3 = ?MS_INFO_CONTENT,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case19_dl_0x8400_phone_callback(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_PHONE_CALLBACK},
|
|
<<"body">> => #{<<"type">> => 0, <<"phone">> => <<"15632597856">>}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%% client get downlink command
|
|
MsgBody3 = <<0:8, <<"15632597856">>/binary>>,
|
|
MsgId3 = ?MS_PHONE_CALLBACK,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case20_dl_0x8401_set_phone_number(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_PHONE_NUMBER},
|
|
<<"body">> => #{
|
|
<<"type">> => 2,
|
|
<<"length">> => 2,
|
|
<<"contacts">> =>
|
|
[
|
|
#{
|
|
<<"type">> => 2,
|
|
<<"phone_len">> => 10,
|
|
<<"phone">> => <<"13011112222">>,
|
|
<<"name_len">> => 3,
|
|
<<"name">> => <<"Tom">>
|
|
},
|
|
#{
|
|
<<"type">> => 3,
|
|
<<"phone_len">> => 11,
|
|
<<"phone">> => <<"013011113333">>,
|
|
<<"name_len">> => 4,
|
|
<<"name">> => <<"Mike">>
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 =
|
|
<<2:8, 2:8, 2:8, 10:8, <<"13011112222">>/binary, 3:8, <<"Tom">>/binary, 3:8, 11:8,
|
|
<<"013011113333">>/binary, 4:8, <<"Mike">>/binary>>,
|
|
MsgId3 = ?MS_SET_PHONE_NUMBER,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case21_dl_0x8600_set_circle_area(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_CIRCLE_AREA},
|
|
<<"body">> => #{
|
|
<<"type">> => 0,
|
|
<<"length">> => 2,
|
|
<<"areas">> =>
|
|
[
|
|
#{
|
|
<<"id">> => 267,
|
|
<<"flag">> => 36,
|
|
<<"center_latitude">> => 20057,
|
|
<<"center_longitude">> => 4529,
|
|
<<"radius">> => 279,
|
|
<<"start_time">> => <<"170912103253">>,
|
|
<<"end_time">> => <<"170913103253">>,
|
|
<<"max_speed">> => 120,
|
|
<<"overspeed_duration">> => 36
|
|
},
|
|
#{
|
|
<<"id">> => 355,
|
|
<<"flag">> => 36,
|
|
<<"center_latitude">> => 20057,
|
|
<<"center_longitude">> => 4529,
|
|
<<"radius">> => 132,
|
|
<<"start_time">> => <<"170912103253">>,
|
|
<<"end_time">> => <<"170913103253">>,
|
|
<<"max_speed">> => 120,
|
|
<<"overspeed_duration">> => 36
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%% client get downlink command
|
|
MsgBody3 =
|
|
<<0:8, 2:8, 267:?DWORD, 36:?WORD, 20057:?DWORD, 4529:?DWORD, 279:?DWORD,
|
|
<<16#17, 16#09, 16#12, 16#10, 16#32, 16#53>>/binary,
|
|
<<16#17, 16#09, 16#13, 16#10, 16#32, 16#53>>/binary, 120:?WORD, 36:8, 355:?DWORD,
|
|
36:?WORD, 20057:?DWORD, 4529:?DWORD, 132:?DWORD,
|
|
<<16#17, 16#09, 16#12, 16#10, 16#32, 16#53>>/binary,
|
|
<<16#17, 16#09, 16#13, 16#10, 16#32, 16#53>>/binary, 120:?WORD, 36:8>>,
|
|
MsgId3 = ?MS_SET_CIRCLE_AREA,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case22_dl_0x8601_del_circle_area(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_DEL_CIRCLE_AREA},
|
|
<<"body">> => #{<<"length">> => 2, <<"ids">> => [3, 78]}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<2:8, 3:?DWORD, 78:?DWORD>>,
|
|
MsgId3 = ?MS_DEL_CIRCLE_AREA,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case23_dl_0x8602_set_rect_area(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_RECT_AREA},
|
|
<<"body">> => #{
|
|
<<"type">> => 0,
|
|
<<"length">> => 2,
|
|
<<"areas">> =>
|
|
[
|
|
#{
|
|
<<"id">> => 267,
|
|
<<"flag">> => 36,
|
|
<<"lt_lat">> => 20057,
|
|
<<"lt_lng">> => 4529,
|
|
<<"rb_lat">> => 30057,
|
|
<<"rb_lng">> => 5529,
|
|
<<"start_time">> => <<"170912103253">>,
|
|
<<"end_time">> => <<"170913103253">>,
|
|
<<"max_speed">> => 120,
|
|
<<"overspeed_duration">> => 36
|
|
},
|
|
#{
|
|
<<"id">> => 355,
|
|
<<"flag">> => 36,
|
|
<<"lt_lat">> => 20057,
|
|
<<"lt_lng">> => 4529,
|
|
<<"rb_lat">> => 30057,
|
|
<<"rb_lng">> => 5529,
|
|
<<"start_time">> => <<"170912103253">>,
|
|
<<"end_time">> => <<"170913103253">>,
|
|
<<"max_speed">> => 120,
|
|
<<"overspeed_duration">> => 36
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 =
|
|
<<0:8, 2:8, 267:?DWORD, 36:?WORD, 20057:?DWORD, 4529:?DWORD, 30057:?DWORD, 5529:?DWORD,
|
|
<<16#17, 16#09, 16#12, 16#10, 16#32, 16#53>>/binary,
|
|
<<16#17, 16#09, 16#13, 16#10, 16#32, 16#53>>/binary, 120:?WORD, 36:8, 355:?DWORD,
|
|
36:?WORD, 20057:?DWORD, 4529:?DWORD, 30057:?DWORD, 5529:?DWORD,
|
|
<<16#17, 16#09, 16#12, 16#10, 16#32, 16#53>>/binary,
|
|
<<16#17, 16#09, 16#13, 16#10, 16#32, 16#53>>/binary, 120:?WORD, 36:8>>,
|
|
MsgId3 = ?MS_SET_RECT_AREA,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case24_dl_0x8603_del_circle_area(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_DEL_RECT_AREA},
|
|
<<"body">> => #{<<"length">> => 2, <<"ids">> => [3, 78]}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<2:8, 3:?DWORD, 78:?DWORD>>,
|
|
MsgId3 = ?MS_DEL_RECT_AREA,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case25_dl_0x8604_set_poly_area(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_POLY_AREA},
|
|
<<"body">> => #{
|
|
<<"id">> => 267,
|
|
<<"flag">> => 36,
|
|
<<"start_time">> => <<"170912103253">>,
|
|
<<"end_time">> => <<"170913103253">>,
|
|
<<"max_speed">> => 120,
|
|
<<"overspeed_duration">> => 36,
|
|
<<"length">> => 3,
|
|
<<"points">> =>
|
|
[
|
|
#{<<"lat">> => 20057, <<"lng">> => 4529},
|
|
#{<<"lat">> => 21057, <<"lng">> => 14569},
|
|
#{<<"lat">> => 7032, <<"lng">> => 429}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 =
|
|
<<267:?DWORD, 36:?WORD, <<16#17, 16#09, 16#12, 16#10, 16#32, 16#53>>/binary,
|
|
<<16#17, 16#09, 16#13, 16#10, 16#32, 16#53>>/binary, 120:?WORD, 36:8, 3:?WORD,
|
|
20057:?DWORD, 4529:?DWORD, 21057:?DWORD, 14569:?DWORD, 7032:?DWORD, 429:?DWORD>>,
|
|
MsgId3 = ?MS_SET_POLY_AREA,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case26_dl_0x8605_del_poly_area(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_DEL_POLY_AREA},
|
|
<<"body">> => #{<<"length">> => 2, <<"ids">> => [3, 78]}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<2:8, 3:?DWORD, 78:?DWORD>>,
|
|
MsgId3 = ?MS_DEL_POLY_AREA,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case27_dl_0x8606_set_path(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SET_PATH},
|
|
<<"body">> => #{
|
|
<<"id">> => 267,
|
|
<<"flag">> => 36,
|
|
<<"start_time">> => <<"170912103253">>,
|
|
<<"end_time">> => <<"170913103253">>,
|
|
<<"length">> => 2,
|
|
<<"points">> =>
|
|
[
|
|
#{
|
|
<<"point_id">> => 3,
|
|
<<"path_id">> => 71,
|
|
<<"point_lat">> => 7324,
|
|
<<"point_lng">> => 9732,
|
|
<<"width">> => 54,
|
|
<<"attrib">> => 23,
|
|
<<"passed">> => 0,
|
|
<<"uncovered">> => 1,
|
|
<<"max_speed">> => 132,
|
|
<<"overspeed_duration">> => 4
|
|
},
|
|
#{
|
|
<<"point_id">> => 4,
|
|
<<"path_id">> => 72,
|
|
<<"point_lat">> => 7324,
|
|
<<"point_lng">> => 9732,
|
|
<<"width">> => 54,
|
|
<<"attrib">> => 23,
|
|
<<"passed">> => 0,
|
|
<<"uncovered">> => 1,
|
|
<<"max_speed">> => 169,
|
|
<<"overspeed_duration">> => 69
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 =
|
|
<<267:?DWORD, 36:?WORD, <<16#17, 16#09, 16#12, 16#10, 16#32, 16#53>>/binary,
|
|
<<16#17, 16#09, 16#13, 16#10, 16#32, 16#53>>/binary, 2:?WORD, 3:?DWORD, 71:?DWORD,
|
|
7324:?DWORD, 9732:?DWORD, 54:8, 23:8, 0:?WORD, 1:?WORD, 132:?WORD, 4:8, 4:?DWORD,
|
|
72:?DWORD, 7324:?DWORD, 9732:?DWORD, 54:8, 23:8, 0:?WORD, 1:?WORD, 169:?WORD, 69:8>>,
|
|
MsgId3 = ?MS_SET_PATH,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case26_dl_0x8607_del_path(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_DEL_PATH},
|
|
<<"body">> => #{<<"length">> => 2, <<"ids">> => [3, 78]}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<2:8, 3:?DWORD, 78:?DWORD>>,
|
|
MsgId3 = ?MS_DEL_PATH,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case27_dl_0x8700_drive_record_capture(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
CaptureCmd = 2,
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_DRIVE_RECORD_CAPTURE},
|
|
<<"body">> => #{
|
|
<<"command">> => CaptureCmd, <<"param">> => base64:encode(<<"000123456789">>)
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<2:8, <<"000123456789">>/binary>>,
|
|
MsgId3 = ?MS_DRIVE_RECORD_CAPTURE,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
% client send "drive record report"
|
|
UlPacket4 = <<MsgSn3:?WORD, CaptureCmd:8, <<"77777">>/binary>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_DRIVE_RECORD_REPORT,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_DRIVE_RECORD_REPORT,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"seq">> => MsgSn3,
|
|
<<"command">> => CaptureCmd,
|
|
<<"data">> => base64:encode(<<"77777">>)
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
% no retrasmition of downlink message
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case28_dl_0x8701_drive_record_param_send(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
CaptureCmd = 2,
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_DRIVE_REC_PARAM_SEND},
|
|
<<"body">> => #{
|
|
<<"command">> => CaptureCmd, <<"param">> => base64:encode(<<"000123456789">>)
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<CaptureCmd:8, <<"000123456789">>/binary>>,
|
|
MsgId3 = ?MS_DRIVE_REC_PARAM_SEND,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case29_dl_0x8702_request_driver_id(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{<<"header">> => #{<<"msg_id">> => ?MS_REQ_DRIVER_ID}},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<>>,
|
|
MsgId3 = ?MS_REQ_DRIVER_ID,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
% client send "drive record report"
|
|
UlPacket4 =
|
|
<<1:8, 16#17, 16#10, 16#12, 16#09, 16#03, 16#52, 0:8, 3:8, <<"Tom">>/binary,
|
|
<<"77778888999900001111">>/binary, 6:8, <<"org123">>/binary, 16#20, 16#30, 16#12,
|
|
16#31>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_DRIVER_ID_REPORT,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_DRIVER_ID_REPORT,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"status">> => 1,
|
|
<<"time">> => <<"171012090352">>,
|
|
<<"ic_result">> => 0,
|
|
<<"driver_name">> => <<"Tom">>,
|
|
<<"certificate">> => <<"77778888999900001111">>,
|
|
<<"organization">> => <<"org123">>,
|
|
<<"cert_expiry">> => <<"20301231">>
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case30_dl_0x8801_camera_shot(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_CAMERA_SHOT},
|
|
<<"body">> => #{
|
|
<<"channel_id">> => 172,
|
|
<<"command">> => 5,
|
|
<<"period">> => 2,
|
|
<<"save">> => 1,
|
|
<<"resolution">> => 8,
|
|
<<"quality">> => 3,
|
|
<<"bright">> => 4,
|
|
<<"contrast">> => 5,
|
|
<<"saturate">> => 6,
|
|
<<"chromaticity">> => 7
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<172:8, 5:?WORD, 2:?WORD, 1:8, 8:8, 3:8, 4:8, 5:8, 6:8, 7:8>>,
|
|
MsgId3 = ?MS_CAMERA_SHOT,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
% client send "camera shot ack"
|
|
UlPacket4 = <<MsgSn3:?WORD, 0:8, 2:?WORD, 220:?DWORD, 221:?DWORD>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_CAMERA_SHOT_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_CAMERA_SHOT_ACK,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"seq">> => MsgSn3,
|
|
<<"result">> => 0,
|
|
<<"length">> => 2,
|
|
<<"ids">> => [220, 221]
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
% No retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case31_dl_0x8802_mm_data_search(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_MM_DATA_SEARCH},
|
|
<<"body">> => #{
|
|
<<"type">> => 0,
|
|
<<"channel">> => 17,
|
|
<<"event">> => 2,
|
|
<<"start_time">> => <<"170923144607">>,
|
|
<<"end_time">> => <<"170923145826">>
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 =
|
|
<<0:8, 17:8, 2:8, 16#17, 16#09, 16#23, 16#14, 16#46, 16#07, 16#17, 16#09, 16#23, 16#14,
|
|
16#58, 16#26>>,
|
|
MsgId3 = ?MS_MM_DATA_SEARCH,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
% client send "mm data search ack"
|
|
{LocBin, LocJson} = location_report_28bytes(),
|
|
UlPacket4 =
|
|
<<MsgSn3:?WORD, 2:?WORD, 25:?DWORD, 1:8, 97:8, 1:8, LocBin/binary, 26:?DWORD, 2:8, 98:8,
|
|
3:8, LocBin/binary>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_MM_DATA_SEARCH_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_MM_DATA_SEARCH_ACK,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"seq">> => MsgSn3,
|
|
<<"length">> => 2,
|
|
<<"result">> => [
|
|
#{
|
|
<<"id">> => 25,
|
|
<<"type">> => 1,
|
|
<<"channel">> => 97,
|
|
<<"event">> => 1,
|
|
<<"location">> => LocJson
|
|
},
|
|
#{
|
|
<<"id">> => 26,
|
|
<<"type">> => 2,
|
|
<<"channel">> => 98,
|
|
<<"event">> => 3,
|
|
<<"location">> => LocJson
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
%% No retrasmition of downlink message
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case32_dl_0x8803_mm_data_upload(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_MM_DATA_UPLOAD},
|
|
<<"body">> => #{
|
|
<<"type">> => 0,
|
|
<<"channel">> => 17,
|
|
<<"event">> => 2,
|
|
<<"start_time">> => <<"170923144607">>,
|
|
<<"end_time">> => <<"170923145826">>,
|
|
<<"delete">> => 1
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 =
|
|
<<0:8, 17:8, 2:8, 16#17, 16#09, 16#23, 16#14, 16#46, 16#07, 16#17, 16#09, 16#23, 16#14,
|
|
16#58, 16#26, 1:8>>,
|
|
MsgId3 = ?MS_MM_DATA_UPLOAD,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case33_dl_0x8804_voice_record(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_VOICE_RECORD},
|
|
<<"body">> => #{
|
|
<<"command">> => 1,
|
|
<<"time">> => 2,
|
|
<<"save">> => 3,
|
|
<<"rate">> => 4
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%
|
|
% client get downlink command
|
|
%
|
|
MsgBody3 = <<1:8, 2:?WORD, 3:8, 4:8>>,
|
|
MsgId3 = ?MS_VOICE_RECORD,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
client_send_general_response(Socket, MsgId3, MsgSn3, PhoneBCD),
|
|
|
|
% no retrasmition of downlink message
|
|
%% timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_case34_dl_0x8805_single_mm_data_ctrl(_Config) ->
|
|
{ok, Socket} = gen_tcp:connect({127, 0, 0, 1}, ?PORT, [binary, {active, false}]),
|
|
{ok, AuthCode} = client_regi_procedure(Socket),
|
|
ok = client_auth_procedure(Socket, AuthCode),
|
|
PhoneBCD = <<16#00, 16#01, 16#23, 16#45, 16#67, 16#89>>,
|
|
|
|
ok = emqx:subscribe(?JT808_UP_TOPIC),
|
|
|
|
DlCommand = #{
|
|
<<"header">> => #{<<"msg_id">> => ?MS_SINGLE_MM_DATA_CTRL},
|
|
<<"body">> => #{
|
|
<<"id">> => 30,
|
|
<<"flag">> => 40
|
|
}
|
|
},
|
|
emqx:publish(emqx_message:make(?JT808_DN_TOPIC, emqx_utils_json:encode(DlCommand))),
|
|
|
|
%% client get downlink command
|
|
MsgBody3 = <<30:?DWORD, 40:8>>,
|
|
MsgId3 = ?MS_SINGLE_MM_DATA_CTRL,
|
|
MsgSn3 = 2,
|
|
Size3 = size(MsgBody3),
|
|
Header3 =
|
|
<<MsgId3:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size3),
|
|
PhoneBCD/binary, MsgSn3:?WORD>>,
|
|
S3 = gen_packet(Header3, MsgBody3),
|
|
|
|
%% timer:sleep(600),
|
|
{ok, Packet3} = gen_tcp:recv(Socket, 0, 500),
|
|
?LOGT(" S3=~p", [binary_to_hex_string(S3)]),
|
|
?LOGT("Packet3=~p", [binary_to_hex_string(Packet3)]),
|
|
?assertEqual(S3, Packet3),
|
|
|
|
?LOGT("client receive command from server ~p", [S3]),
|
|
|
|
{LocBin, LocJson} = location_report_28bytes(),
|
|
UlPacket4 =
|
|
<<MsgSn3:?WORD, 2:?WORD, 25:?DWORD, 1:8, 97:8, 1:8, LocBin/binary, 26:?DWORD, 2:8, 98:8,
|
|
3:8, LocBin/binary>>,
|
|
Size4 = size(UlPacket4),
|
|
MsgId4 = ?MC_MM_DATA_SEARCH_ACK,
|
|
MsgSn4 = 2,
|
|
Header4 =
|
|
<<MsgId4:?WORD, ?RESERVE:2, ?NO_FRAGMENT:1, ?NO_ENCRYPT:3, ?MSG_SIZE(Size4),
|
|
PhoneBCD/binary, MsgSn4:?WORD>>,
|
|
S4 = gen_packet(Header4, UlPacket4),
|
|
?LOGT("S4 = ~p", [S4]),
|
|
|
|
ok = gen_tcp:send(Socket, S4),
|
|
timer:sleep(100),
|
|
|
|
{?JT808_UP_TOPIC, Payload} = receive_msg(),
|
|
?assertEqual(
|
|
#{
|
|
<<"header">> => #{
|
|
<<"encrypt">> => 0,
|
|
<<"len">> => Size4,
|
|
<<"msg_id">> => ?MC_MM_DATA_SEARCH_ACK,
|
|
<<"msg_sn">> => 2,
|
|
<<"phone">> => <<"000123456789">>
|
|
},
|
|
<<"body">> => #{
|
|
<<"seq">> => MsgSn3,
|
|
<<"length">> => 2,
|
|
<<"result">> => [
|
|
#{
|
|
<<"id">> => 25,
|
|
<<"type">> => 1,
|
|
<<"channel">> => 97,
|
|
<<"event">> => 1,
|
|
<<"location">> => LocJson
|
|
},
|
|
#{
|
|
<<"id">> => 26,
|
|
<<"type">> => 2,
|
|
<<"channel">> => 98,
|
|
<<"event">> => 3,
|
|
<<"location">> => LocJson
|
|
}
|
|
]
|
|
}
|
|
},
|
|
emqx_utils_json:decode(Payload, [return_maps])
|
|
),
|
|
|
|
% no retrasmition of downlink message
|
|
%%timer:sleep(10000),
|
|
{error, timeout} = gen_tcp:recv(Socket, 0, 500),
|
|
|
|
ok = gen_tcp:close(Socket).
|
|
|
|
t_create_ALLOW_invalid_auth_config(_Config) ->
|
|
test_invalid_config(create, true).
|
|
|
|
t_create_DISALLOW_invalid_auth_config(_Config) ->
|
|
test_invalid_config(create, false).
|
|
|
|
t_update_ALLOW_invalid_auth_config(_Config) ->
|
|
test_invalid_config(update, true).
|
|
|
|
t_update_DISALLOW_invalid_auth_config(_Config) ->
|
|
test_invalid_config(update, false).
|
|
|
|
test_invalid_config(CreateOrUpdate, AnonymousAllowed) ->
|
|
InvalidConfig = raw_jt808_config(AnonymousAllowed),
|
|
UpdateResult = create_or_update(CreateOrUpdate, InvalidConfig),
|
|
?assertMatch(
|
|
{error, #{
|
|
kind := validation_error,
|
|
reason := matched_no_union_member,
|
|
path := "gateway.jt808.proto.auth"
|
|
}},
|
|
UpdateResult
|
|
).
|
|
|
|
create_or_update(create, InvalidConfig) ->
|
|
emqx_gateway_conf:load_gateway(jt808, InvalidConfig);
|
|
create_or_update(update, InvalidConfig) ->
|
|
emqx_gateway_conf:update_gateway(jt808, InvalidConfig).
|
|
|
|
%% Allow: allow anonymous connection, registry and authentication URL not required.
|
|
raw_jt808_config(Allow = true) ->
|
|
AuthConfig = #{
|
|
<<"auth">> => #{
|
|
<<"allow_anonymous">> => Allow,
|
|
%% registry and authentication `NOT REQUIRED`, but can be configured
|
|
<<"registry">> => <<?PROTO_REG_SERVER_HOST, ?PROTO_REG_REGISTRY_PATH>>,
|
|
<<"authentication">> => <<?PROTO_REG_SERVER_HOST, ?PROTO_REG_AUTH_PATH>>,
|
|
<<"BADKEY_registry_url">> => <<?PROTO_REG_SERVER_HOST, ?PROTO_REG_REGISTRY_PATH>>
|
|
}
|
|
},
|
|
emqx_utils_maps:deep_merge(raw_jt808_config(), #{<<"proto">> => AuthConfig});
|
|
%% DisAllow: required registry and authentication URL configuration to auth client.
|
|
raw_jt808_config(DisAllow = false) ->
|
|
AuthConfig = #{
|
|
<<"auth">> => #{
|
|
<<"allow_anonymous">> => DisAllow
|
|
%% registry and authentication are required but missed here
|
|
%%
|
|
%% <<"registry">> => <<?PROTO_REG_SERVER_HOST, ?PROTO_REG_REGISTRY_PATH>>,
|
|
%% <<"authentication">> => <<?PROTO_REG_SERVER_HOST, ?PROTO_REG_AUTH_PATH>>
|
|
}
|
|
},
|
|
emqx_utils_maps:deep_merge(raw_jt808_config(), #{<<"proto">> => AuthConfig}).
|
|
|
|
raw_jt808_config() ->
|
|
#{
|
|
<<"enable">> => true,
|
|
<<"enable_stats">> => true,
|
|
<<"frame">> => #{<<"max_length">> => 8192},
|
|
<<"idle_timeout">> => <<"30s">>,
|
|
<<"max_retry_times">> => 3,
|
|
<<"message_queue_len">> => 10,
|
|
<<"mountpoint">> => <<"jt808/${clientid}/">>,
|
|
<<"proto">> =>
|
|
#{
|
|
<<"dn_topic">> => <<"jt808/${clientid}/${phone}/dn">>,
|
|
<<"up_topic">> => <<"jt808/${clientid}/${phone}/up">>
|
|
},
|
|
<<"retry_interval">> => <<"8s">>
|
|
}.
|