diff --git a/apps/modbus/src/modbus_parser.erl b/apps/modbus/src/modbus_parser.erl index d55d559..393dd98 100644 --- a/apps/modbus/src/modbus_parser.erl +++ b/apps/modbus/src/modbus_parser.erl @@ -258,11 +258,11 @@ parse_ast1([#block{ident = <<"transport", Name0/binary>>, props = Props}|T], Acc Transport = case string:trim(Name0) of <<"rtu">> -> #modbus_transport_rtu{ - port = maps:get(<<"port">>, PropsMap, undefined), - baudrate = maps:get(<<"baudrate">>, PropsMap, undefined), - parity = maps:get(<<"parity">>, PropsMap, undefined), - stopbits = maps:get(<<"stopbits">>, PropsMap, undefined), - timeout = maps:get(<<"timeout">>, PropsMap, undefined) + port = map_of_binary(<<"port">>, PropsMap, undefined), + baudrate = map_of_integer(<<"baudrate">>, PropsMap, undefined), + parity = map_of_binary(<<"parity">>, PropsMap, undefined), + stopbits = map_of_integer(<<"stopbits">>, PropsMap, undefined), + timeout = map_of_time(<<"timeout">>, PropsMap, undefined) }; <<"tcp">> -> #modbus_transport_tcp { @@ -276,12 +276,13 @@ parse_ast1([#block{ident = <<"transport", Name0/binary>>, props = Props}|T], Acc %% 语义验证:检查AST的合法性和一致性 validate([]) -> ok; -validate([#modbus{transport = #modbus_transport_rtu{port = Port, baudrate = Baudrate}}|T]) -> - case filelib:is_file(Port) andalso Baudrate > 0 of +validate([#modbus{transport = #modbus_transport_rtu{port = Port0, baudrate = Baudrate}}|T]) -> + Port = binary_to_list(Port0), + case filename:validate(Port) andalso Baudrate > 0 of true -> validate(T); false -> - throw({invalid_transport_rtu, {Port, Baudrate}}) + throw({invalid_transport_rtu, {Port0, Baudrate}}) end; validate([#modbus{transport = #modbus_transport_tcp{host = Host, port = Port}}|T]) -> case Host /= undefined andalso Port > 0 of diff --git a/apps/modbus/src/modbus_service.erl b/apps/modbus/src/modbus_service.erl index 93568e2..693ee6c 100644 --- a/apps/modbus/src/modbus_service.erl +++ b/apps/modbus/src/modbus_service.erl @@ -198,7 +198,8 @@ handle_event(info, {tcp_error, Socket, Reason}, ?CONNECTED, State = #state{mode {next_state, ?DISCONNECTED, State#state{socket = undefined}}; %% 建立连接, todo is_pending的状态要形成闭环 -handle_event(info, modbus_connect, ?DISCONNECTED, State = #state{ast = #ast{modbus = #modbus{transport = Transport}}, queue = Q}) -> +handle_event(info, {timeout, _Ref, modbus_connect}, ?DISCONNECTED, State = #state{ast = #ast{modbus = #modbus{transport = Transport}}, queue = Q}) -> + lager:debug("call me will connect, transport: ~p", [Transport]), case connect(Transport) of {ok, ConnectResult} -> Actions = case not queue:is_empty(Q) of @@ -207,8 +208,8 @@ handle_event(info, modbus_connect, ?DISCONNECTED, State = #state{ast = #ast{modb end, case ConnectResult of {rtu, Port, DelayMs} -> - %% 触发读取下一条 - erlang:start_timer(0, self(), read_next), + %% todo 触发读取下一条 + % erlang:start_timer(0, self(), read_next), {next_state, ?CONNECTED, State#state{mode = rtu, port = Port, delay_ms = DelayMs, is_pending = false}, Actions}; Socket -> {next_state, ?CONNECTED, State#state{mode = tcp, socket = Socket}, Actions} @@ -218,11 +219,7 @@ handle_event(info, modbus_connect, ?DISCONNECTED, State = #state{ast = #ast{modb %% 5秒后重试 retry_connect(), {keep_state, State} - end; - -handle_event(_EventType, _EventContent, _StateName, State = #state{}) -> - NextStateName = the_next_state_name, - {next_state, NextStateName, State}. + end. %% @private %% @doc This function is called by a gen_statem when it is about to @@ -244,16 +241,29 @@ code_change(_OldVsn, StateName, State = #state{}, _Extra) -> -spec connect(Transport :: #modbus_transport_rtu{} | #modbus_transport_tcp{}) -> {ok, {rtu, Port :: port(), DelayMs :: integer()}} | {ok, Socket :: gen_tcp:socket()} | {error, Reason :: any()}. %% databits为8位 -connect(#modbus_transport_rtu{port = Port, baudrate = BaudRate, stopbits = StopBits, parity = Parity, timeout = Timeout}) -> - RealExecCmd = "", - Port = erlang:open_port({spawn_executable, RealExecCmd}, [binary, {packet, 2}, exit_status]), +connect(#modbus_transport_rtu{port = SerialPort, baudrate = BaudRate, stopbits = StopBits, parity = Parity0, timeout = Timeout}) -> + lager:warning("call me here connect, serial_port: ~p", [SerialPort]), + %% 奇偶校验 + Parity = case Parity0 of + <<"none">> -> 0; + <<"odd">> -> 1; + <<"even">> -> 2; + _ -> 0 + end, + RealExecCmd = "/usr/local/code/cloudkit/modbus/apps/modbus/priv/bin/modbus_agent", + Args = [ + "--port " ++ binary_to_list(SerialPort), + "--baud_rate " ++ integer_to_list(BaudRate), + "--stop_bits " ++ integer_to_list(StopBits), + "--parity " ++ integer_to_list(Parity), + "--timeout " ++ integer_to_list(Timeout) + ], + Port = erlang:open_port({spawn_executable, RealExecCmd}, [binary, {packet, 2}, exit_status, {args, Args}]), + lager:debug("args: ~p", [Args]), DelayMs = frame_delay(BaudRate, 8, Parity, StopBits), - - Len0 = byte_size(Port), - ConnectCmd = <>, + lager:debug("port is: ~p", [Port]), %% 建立连接 - Port ! {self(), {command, ConnectCmd}}, {ok, {rtu, Port, DelayMs}}; connect(#modbus_transport_tcp{host = Host, port = Port, timeout = Timeout0}) -> Timeout = case is_integer(Timeout0) andalso Timeout0 > 0 of diff --git a/modbus.conf b/modbus.conf index bfa0acb..b96d0c4 100644 --- a/modbus.conf +++ b/modbus.conf @@ -9,11 +9,11 @@ modbus { } # 或TCP配置 - transport tcp { - host 192.168.1.100; - port 502; - timeout 500ms; - } + #transport tcp { + # host 192.168.1.100; + # port 502; + # timeout 500ms; + #} # 日志设置 error_log /var/log/modbus_error.log;