I’m trying to use emqtt with quic over mqtt on Erlang/OTP 27 [erts-15.1.2] to communicate with a EK9160 Bus Coupler. I can establish communication with the device from the the command line using these instructions.
cd ~/emqtt/_build/emqtt/rel/emqtt/bin
With quic option - -enable quic and QoS 1
./emqtt sub -h '192.168.178.33' -p '14567' --enable-quic=true -q '1' -k '300' -t 'EK9160/EK-98EFB6/Stream1/Json/Tx/Data'
./emqtt pub -h '192.168.178.33' -p '14567' --enable-quic=true -q '1' -k '300' -t 'EK9160/EK-98EFB6/Stream1/Json/Rx/Data' -k '30' --payload '{"Values":{"Slave 2 (EL2008).Channel 1.Output":false}}'
To communicate with emqtt using an Erlang/OTP gen_server, I created a new myapp application project using rebar3 and the following rebar.config file
alberto@debian:~/myapp$ cat rebar.config
{erl_opts, [debug_info]}.
{deps, [{emqtt, {git, "https://github.com/emqx/emqtt.git", {branch, "master"}}} ]}.
{shell, [
%% {config, "config/sys.config"},
{apps, [myapp]}
]}.
And then placed the following ek9160.erl file I created in the src directory of myapp
alberto@debian:~/myapp/_build/default/lib$ ls
cowlib emqtt getopt gun myapp quicer snabbkaffe
Here is a copy of the Erlang module
-module(ek9160).
-behaviour(gen_server).
-export([start/0, cnct/0, sub/0, ping/0]).
-export([init/1, handle_call/3, handle_cast/2]).
-record(state, {clientID}).
cnct() ->
gen_server:call(ek9160, cnct).
sub()->
gen_server:call(ek9160, sub).
ping() ->
gen_server:call(ek9160, ping).
start() ->
gen_server:start_link({local, ek9160}, ek9160, [], []).
init(_Args) ->
{ok, ConnPid} = emqtt:start_link([{host, '192.168.178.33'}, {port, 14567}, {keepalive,300}]),
State = #state{clientID = ConnPid},
{ok, State}.
handle_call(cnct, _From, State) ->
{ok, Props} = emqtt:quic_connect(State#state.clientID),
io:fromat("Props ~p~n", [Props]),
{reply, ok, State};
handle_call(sub, _From, State) ->
Properties = #{'Payload-Format-Indicator' => 0,
%'Content-Type' => binary(),
'Server-Keep-Alive' => 300,
'Maximum-QoS' => 1,
'Retain-Available' => 1},
SubOpts = [{qos, 1}],
Subscriptions = [{<<"EK9160/EK-98EFB6/Stream1/Json/Tx/Data">>, SubOpts}],
{ok, _Props, _ReasonCodes} = emqtt:subscribe(State#state.clientID, Properties, Subscriptions),
{reply, ok, State};
handle_call(ping, _From, State) ->
pong = emqtt:ping(State#state.clientID),
{reply, ok, State}.
handle_cast(_Msg, _State) ->
NewState = {},
{noreply, NewState}.
Unfortunately when run the module I get the following error report.
alberto@debian:~/myapp$ rebar3 shell
===> Verifying dependencies...
===> Analyzing applications...
===> Compiling myapp
Erlang/OTP 27 [erts-15.1.2] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [jit:ns]
Eshell V15.1.2 (press Ctrl+G to abort, type help(). for help)
===> Booted cowlib
===> Booted gun
===> Booted emqtt
===> Booted myapp
1> ek9160:start().
{ok,<0.218.0>}
2> ek9160:sub().
=ERROR REPORT==== 9-Dec-2024::18:46:34.324796 ===
state: initialized
msg: unexpected_event
clientid: <<"emqtt-debian-d12747649e95ead816f4">>
event: {subscribe,#{'Payload-Format-Indicator' => 0,
'Server-Keep-Alive' => 300,'Maximum-QoS' => 1,
'Retain-Available' => 1},
[{<<"EK9160/EK-98EFB6/Stream1/Json/Tx/Data">>,
#{nl => 0,qos => 1,rap => 0,rh => 0}}]}
event_type: {call,{<0.218.0>,#Ref<0.2299435312.546570241.15840>}}
=ERROR REPORT==== 9-Dec-2024::18:46:39.347036 ===
** State machine <0.219.0> terminating
** When server state = {initialized,
{state,undefined,<0.218.0>,undefined,
'192.168.178.33',14567,[],emqtt_sock,
undefined,[],60000,false,
<<"emqtt-debian-d12747649e95ead816f4">>,true,
undefined,undefined,4,<<"MQTT">>,300,
undefined,false,false,undefined,#{},[],#{},
#{seq => 1,sent => #{},
max_inflight => infinity},
#{},true,30000,undefined,30000,undefined,
undefined,1,false,
{none,
#{version => 4,max_size => 268435455,
strict_mode => false}},
0,5000,false,undefined,
{[],[]},
#{}}}
** Reason for termination = exit:{{timeout,{gen_server,call,[ek9160,sub]}},
[{gen_server,call,2,
[{file,"gen_server.erl"},{line,1142}]},
{erl_eval,do_apply,7,
[{file,"erl_eval.erl"},{line,904}]},
{shell,exprs,7,
[{file,"shell.erl"},{line,893}]},
{shell,eval_exprs,7,
[{file,"shell.erl"},{line,849}]},
{shell,eval_loop,4,
[{file,"shell.erl"},{line,834}]}]}
** Callback modules = [emqtt]
** Callback mode = state_functions
** Stacktrace =
** [{gen_statem,loop_receive,3,[{file,"gen_statem.erl"},{line,3625}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,329}]}]
=CRASH REPORT==== 9-Dec-2024::18:46:39.352544 ===
crasher:
initial call: emqtt:init/1
pid: <0.219.0>
registered_name: []
exception exit: {{timeout,{gen_server,call,[ek9160,sub]}},
[{gen_server,call,2,
[{file,"gen_server.erl"},{line,1142}]},
{erl_eval,do_apply,7,[{file,"erl_eval.erl"},{line,904}]},
{shell,exprs,7,[{file,"shell.erl"},{line,893}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,849}]},
{shell,eval_loop,4,[{file,"shell.erl"},{line,834}]}]}
in function gen_statem:loop_receive/3 (gen_statem.erl, line 3625)
ancestors: [ek9160,<0.214.0>,<0.208.0>,<0.207.0>,<0.66.0>,<0.70.0>,
<0.65.0>,kernel_sup,<0.47.0>]
message_queue_len: 0
messages: []
links: []
dictionary: [{rand_seed,{#{max => 288230376151711743,type => exsplus,
next => #Fun<rand.5.40079776>,
jump => #Fun<rand.3.40079776>},
[242607169756497238|259535589815849374]}}]
trap_exit: true
status: running
heap_size: 6772
stack_size: 29
reductions: 21367
neighbours:
** exception exit: {timeout,{gen_server,call,[ek9160,sub]}}
in function gen_server:call/2 (gen_server.erl, line 1142)
3>
The crux of the error is ** Reason for termination = exit:{{timeout,{gen_server,call,[ek9160,sub]}},
I tried to remedy this problem by adding an extended server timeout for the following call, but that didn’t fix the problem.
sub()->
gen_server:call(ek9160, sub, 6000).
I don’t know if the problem is related to the properties and options I added to the subscription instructions or if I’m calling the emqtt methods incorrectly resulting in the OTP error report.
Would any of you in the Erlang Forum know what I should do to fix the communication problem?