From f8fd7d0c43d93a260c135d77566a6b98d981cf46 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Fri, 13 Jun 2025 16:46:20 +0800 Subject: [PATCH] fix parser --- apps/modbus/src/modbus_crc.erl | 33 ++++++++++++++++++++++++++ apps/modbus/src/modbus_parser.erl | 38 ++++++++++++++++++++++++++---- apps/modbus/src/modbus_service.erl | 26 ++++++++++++++++++-- rebar.lock | 4 +++- 4 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 apps/modbus/src/modbus_crc.erl diff --git a/apps/modbus/src/modbus_crc.erl b/apps/modbus/src/modbus_crc.erl new file mode 100644 index 0000000..aeb2900 --- /dev/null +++ b/apps/modbus/src/modbus_crc.erl @@ -0,0 +1,33 @@ +%%%------------------------------------------------------------------- +%%% @author anlicheng +%%% @copyright (C) 2025, +%%% @doc +%%% +%%% @end +%%% Created : 13. 6月 2025 15:08 +%%%------------------------------------------------------------------- +-module(modbus_crc). +-author("anlicheng"). + +%% CRC16 constants +-define(CRC_POLY, 16#A001). + +-export([crc16/1]). + +-spec crc16(binary()) -> binary(). +crc16(Data) -> + crc16(Data, 16#FFFF). + +crc16(<<>>, CRC) -> + <>; +crc16(<>, CRC0) -> + CRC1 = CRC0 bxor Byte, + CRC2 = lists:foldl(fun(_, C) -> + if C band 1 =:= 1 -> (C bsr 1) bxor ?CRC_POLY; + true -> C bsr 1 + end + end, + CRC1, + lists:seq(1,8)), + + crc16(Rest, CRC2). diff --git a/apps/modbus/src/modbus_parser.erl b/apps/modbus/src/modbus_parser.erl index 841e076..844e8a8 100644 --- a/apps/modbus/src/modbus_parser.erl +++ b/apps/modbus/src/modbus_parser.erl @@ -150,8 +150,8 @@ parse_ast0(#block{ident = <<"modbus">>, props = Props}) -> MapProps = parse_ast1(Props), #modbus { transport = maps:get(<<"transport">>, MapProps, undefined), - access_log = maps:get(<<"access_log">>, MapProps, undefined), - error_log = maps:get(<<"error_log">>, MapProps, undefined) + access_log = map_of_string(<<"access_log">>, MapProps, undefined), + error_log = map_of_string(<<"error_log">>, MapProps, undefined) }; parse_ast0(#block{ident = <<"device", Name0/binary>>, props = Props}) -> MapProps = parse_ast1(Props), @@ -213,9 +213,9 @@ parse_ast1([#block{ident = <<"transport", Name0/binary>>, props = Props}|T], Acc }; <<"tcp">> -> #modbus_transport_tcp { - host = maps:get(<<"host">>, PropsMap, undefined), - port = maps:get(<<"port">>, PropsMap, undefined), - timeout = maps:get(<<"timeout">>, PropsMap, undefined) + host = map_of_string(<<"host">>, PropsMap, undefined), + port = map_of_integer(<<"port">>, PropsMap, undefined), + timeout = map_of_time(<<"timeout">>, PropsMap, undefined) } end, parse_ast1(T, [{<<"transport">>, Transport}|Acc]). @@ -260,3 +260,31 @@ map_of_integer(Key, M, Def) -> Def end. +map_of_string(Key, M, Def) -> + case maps:is_key(Key, M) of + true -> + [Val0] = maps:get(Key, M), + binary_to_list(Val0); + false -> + Def + end. + +map_of_time(Key, M, Def) -> + case maps:is_key(Key, M) of + true -> + [Val0] = maps:get(Key, M), + case re:run(Val0, <<"^(\\d+(?:\\.\\d+)?)(\\D+)$">>, [{capture, all_but_first, binary}]) of + {match, [Val, Unit]} -> + Digit = binary_to_integer(Val), + case Unit of + <<"ms">> -> + Digit; + <<"s">> -> + Digit * 1000 + end; + _ -> + Def + end; + false -> + Def + end. \ No newline at end of file diff --git a/apps/modbus/src/modbus_service.erl b/apps/modbus/src/modbus_service.erl index 8d26537..48d0c45 100644 --- a/apps/modbus/src/modbus_service.erl +++ b/apps/modbus/src/modbus_service.erl @@ -14,6 +14,7 @@ %% API -export([start_link/1]). +-export([test/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -24,6 +25,12 @@ }). +test() -> + {ok, Config} = file:read_file("/usr/local/code/cloudkit/modbus/modbus.conf"), + %lager:debug("config is: ~ts", [Config]), + {ok, AST} = modbus_parser:parse(Config), + start_link(AST). + %%%=================================================================== %%% API %%%=================================================================== @@ -32,7 +39,7 @@ -spec(start_link(AST :: #ast{}) -> {ok, Pid :: pid()} | ignore | {error, Reason :: term()}). start_link(AST) -> - gen_server:start_link({local, ?SERVER}, ?MODULE, [], []). + gen_server:start_link(?MODULE, [AST], []). %%%=================================================================== %%% gen_server callbacks @@ -43,7 +50,10 @@ start_link(AST) -> -spec(init(Args :: term()) -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). -init([]) -> +init([AST = #ast{modbus = Modbus}]) -> + + lager:debug("modbus is: ~p", [Modbus]), + {ok, #state{}}. %% @private @@ -98,3 +108,15 @@ code_change(_OldVsn, State = #state{}, _Extra) -> %%%=================================================================== %%% Internal functions %%%=================================================================== + +x(#modbus{transport = #modbus_transport_rtu{port = Port, baudrate = Baudrate, stopbits = Stopbits, timeout = Timeout}}) -> + ok; +x(#modbus{transport = #modbus_transport_tcp{host = Host, port = Port, timeout = Timeout0}}) -> + Timeout = case is_integer(Timeout0) andalso Timeout0 > 0 of + true -> + Timeout0; + false -> + 2000 + end, + gen_tcp:connect(Host, Port, [binary], Timeout). + diff --git a/rebar.lock b/rebar.lock index 8e4ce5d..c2e1289 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,5 +1,6 @@ {"1.2.0", -[{<<"fs">>,{pkg,<<"fs">>,<<"6.1.1">>},1}, +[ + {<<"fs">>,{pkg,<<"fs">>,<<"6.1.1">>},1}, {<<"goldrush">>,{pkg,<<"goldrush">>,<<"0.1.9">>},1}, {<<"gpb">>, {git,"https://github.com/tomas-abrahamsson/gpb.git", @@ -17,6 +18,7 @@ {git,"https://github.com/uwiger/parse_trans", {ref,"6f3645afb43c7c57d61b54ef59aecab288ce1013"}}, 0}, + {<<"sync">>, {git,"https://github.com/rustyio/sync.git", {ref,"7dc303ed4ce8d26db82e171dbbd7c41067852c65"}},