From 4a3f30230858aef2981978a380eb605275cf6769 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Sat, 28 Jun 2025 22:42:07 +0800 Subject: [PATCH] fix --- apps/modbus/include/modbus_ast.hrl | 18 +++++++++++--- apps/modbus/src/modbus_device.erl | 3 +++ apps/modbus/src/modbus_parser.erl | 39 ++++++++++++++++++++++++------ apps/modbus/src/modbus_service.erl | 19 ++++++++------- modbus.conf | 25 ++++++++++++++++--- 5 files changed, 80 insertions(+), 24 deletions(-) diff --git a/apps/modbus/include/modbus_ast.hrl b/apps/modbus/include/modbus_ast.hrl index e04751f..412189f 100644 --- a/apps/modbus/include/modbus_ast.hrl +++ b/apps/modbus/include/modbus_ast.hrl @@ -28,7 +28,7 @@ access_log = "" :: string() }). --record(modbus_collect_template, { +-record(modbus_device_io, { name :: binary(), %% 轮询间隔 poll_interval :: integer() | undefined, @@ -37,7 +37,10 @@ retry_timeout :: integer(), %% 数据定义 - metrics = #{} :: map() + metrics :: list() | undefined, + + %% 写入控制器 + controls :: list() | undefined }). -record(modbus_device, { @@ -49,7 +52,7 @@ model :: string() | undefined, description :: string() | undefined, - collect_template :: binary() | undefined, + device_io :: binary() | undefined, %% 轮询间隔 poll_interval :: integer() | undefined, @@ -71,6 +74,13 @@ unit }). +-record(modbus_control, { + name, + address, + type, + precision +}). + -record(modbus_processor, { name :: string(), input :: string(), @@ -103,7 +113,7 @@ -record(ast, { modbus, - collect_templates = [], + device_ios = [], devices = [], processors = [], alarms = [] diff --git a/apps/modbus/src/modbus_device.erl b/apps/modbus/src/modbus_device.erl index f3eb04a..2d3a6fb 100644 --- a/apps/modbus/src/modbus_device.erl +++ b/apps/modbus/src/modbus_device.erl @@ -47,6 +47,9 @@ start_link(ParentPid, Device = #modbus_device{}) when is_pid(ParentPid) -> {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {stop, Reason :: term()} | ignore). init([ParentPid, Device = #modbus_device{metrics = Metrics0, poll_interval = PollInterval}]) -> + + lager:debug("device is: ~p", [Device]), + %% 处理采集项目 MetricsMap = maps:from_list(lists:map(fun(Metric0 = #modbus_metric{name = Name}) -> {Name, Metric0} end, Metrics0)), %% 初步启动的过程中按照step提交任务 diff --git a/apps/modbus/src/modbus_parser.erl b/apps/modbus/src/modbus_parser.erl index 853c269..d55d559 100644 --- a/apps/modbus/src/modbus_parser.erl +++ b/apps/modbus/src/modbus_parser.erl @@ -33,7 +33,7 @@ parse(Input) when is_binary(Input) -> Templates = lists:filter(fun(E) -> case E of - #modbus_collect_template{} -> + #modbus_device_io{} -> true; _ -> false @@ -66,7 +66,7 @@ parse(Input) when is_binary(Input) -> case length(Modbus) == 1 of true -> - AST = #ast{modbus = hd(Modbus), collect_templates = Templates, devices = Devices, processors = Processors, alarms = Alarms }, + AST = #ast{modbus = hd(Modbus), device_ios = Templates, devices = Devices, processors = Processors, alarms = Alarms }, {ok, AST}; false -> {error, modbus_block_error} @@ -168,21 +168,22 @@ parse_ast0(#block{ident = <<"modbus">>, props = Props}) -> access_log = map_of_binary(<<"access_log">>, MapProps, undefined), error_log = map_of_binary(<<"error_log">>, MapProps, undefined) }; -parse_ast0(#block{ident = <<"collect_template", Name0/binary>>, props = Props}) -> +parse_ast0(#block{ident = <<"device_io", Name0/binary>>, props = Props}) -> MapProps = parse_ast1(Props), - #modbus_collect_template { + #modbus_device_io { name = string:trim(Name0), poll_interval = map_of_time(<<"poll_interval">>, MapProps, 0), retries = map_of_integer(<<"retries">>, MapProps, 0), retry_timeout = maps:get(<<"retry_timeout">>, MapProps, undefined), - metrics = maps:get(<<"metrics">>, MapProps, undefined) + metrics = maps:get(<<"metrics">>, MapProps, undefined), + controls = maps:get(<<"controls">>, MapProps, undefined) }; parse_ast0(#block{ident = <<"device", Name0/binary>>, props = Props}) -> MapProps = parse_ast1(Props), #modbus_device { name = string:trim(Name0), slave_id = map_of_integer(<<"slave_id">>, MapProps, 0), - collect_template = map_of_binary(<<"collect_template">>, MapProps, undefined), + device_io = map_of_binary(<<"device_io">>, MapProps, undefined), model = maps:get(<<"model">>, MapProps, undefined), description = maps:get(<<"description">>, MapProps, undefined), poll_interval = map_of_time(<<"poll_interval">>, MapProps, 0), @@ -237,8 +238,21 @@ parse_ast1([#block{ident = <<"metrics">>, props = Metrics0}|T], Acc) -> end, Metrics0), parse_ast1(T, [{<<"metrics">>, Metrics}|Acc]); -parse_ast1([#block{ident = <<"controls">>, props = Props}|T], Acc) -> - parse_ast1(T, [{<<"controls">>, Props}|Acc]); +parse_ast1([#block{ident = <<"controls">>, props = Controls0}|T], Acc) -> + Controls = lists:map(fun(#block{ident = MetricName, props = Props0}) -> + Props = lists:map(fun(Prop0) -> + [Name|Vars] = binary:split(Prop0, <<" ">>, [trim]), + {Name, Vars} + end, Props0), + PropsMap = maps:from_list(Props), + #modbus_control{ + name = MetricName, + address = map_of_integer(<<"address">>, PropsMap, 0), + type = map_of_binary(<<"type">>, PropsMap, <<"">>), + precision = map_of_float(<<"precision">>, PropsMap, <<"">>) + } + end, Controls0), + parse_ast1(T, [{<<"controls">>, Controls}|Acc]); parse_ast1([#block{ident = <<"transport", Name0/binary>>, props = Props}|T], Acc) -> PropsMap = parse_ast1(Props), Transport = case string:trim(Name0) of @@ -308,6 +322,15 @@ map_of_binary(Key, M, Def) -> Def end. +map_of_float(Key, M, Def) -> + case maps:is_key(Key, M) of + true -> + [Val0] = maps:get(Key, M), + binary_to_float(Val0); + false -> + Def + end. + map_of_time(Key, M, Def) -> case maps:is_key(Key, M) of true -> diff --git a/apps/modbus/src/modbus_service.erl b/apps/modbus/src/modbus_service.erl index 72cbcfe..ce443f1 100644 --- a/apps/modbus/src/modbus_service.erl +++ b/apps/modbus/src/modbus_service.erl @@ -82,9 +82,9 @@ start_link(AST = #ast{}) -> %% @doc Whenever a gen_statem is started using gen_statem:start/[3,4] or %% gen_statem:start_link/[3,4], this function is called by the new %% process to initialize. -init([AST = #ast{modbus = Modbus = #modbus{error_log = ErrorLog, access_log = AccessLog}, collect_templates = CollectTemplates, devices = Devices, alarms = Alarms}]) -> - lager:debug("[modbus_service] modbus is: ~p", [Modbus]), - lager:debug("[modbus_service] templates is: ~p", [CollectTemplates]), +init([AST = #ast{modbus = Modbus = #modbus{error_log = ErrorLog, access_log = AccessLog}, device_ios = IOs, devices = Devices, alarms = Alarms}]) -> + lager:debug("[modbus_service] ast is: ~p", [AST]), + lager:debug("[modbus_service] io is: ~p", [IOs]), lager:debug("[modbus_service] devices is: ~p", [Devices]), %% 建立连接 @@ -92,7 +92,7 @@ init([AST = #ast{modbus = Modbus = #modbus{error_log = ErrorLog, access_log = Ac %% 启动设备相关的进程 DevicesPids = lists:map(fun(Device = #modbus_device{slave_id = SlaveId}) -> - {ok, DevicePid} = modbus_device:start_link(self(), merge_template(Device, CollectTemplates)), + {ok, DevicePid} = modbus_device:start_link(self(), merge_io(Device, IOs)), {SlaveId, DevicePid} end, Devices), DevicesMap = maps:from_list(DevicesPids), @@ -286,17 +286,18 @@ create_log_file(FileName) when is_binary(FileName) -> undefined end. -merge_template(Device = #modbus_device{collect_template = undefined}, _Templates) -> +merge_io(Device = #modbus_device{device_io = undefined}, _Templates) -> Device; -merge_template(Device = #modbus_device{collect_template = TemplateName}, Templates) -> - case lists:search(fun(#modbus_collect_template{name = T0}) -> TemplateName =:= T0 end, Templates) of - {value, #modbus_collect_template{poll_interval = PollInterval, retries = Retries, retry_timeout = RetryTimeout, metrics = Metrics}} -> +merge_io(Device = #modbus_device{device_io = IOName}, Templates) -> + case lists:search(fun(#modbus_device_io{name = T0}) -> IOName =:= T0 end, Templates) of + {value, #modbus_device_io{poll_interval = PollInterval, retries = Retries, retry_timeout = RetryTimeout, metrics = Metrics, controls = Controls}} -> %% 合并配置项目 Device#modbus_device{ poll_interval = PollInterval, retries = Retries, retry_timeout = RetryTimeout, - metrics = Metrics + metrics = Metrics, + controls = Controls }; false -> Device diff --git a/modbus.conf b/modbus.conf index 8f5c467..1853668 100644 --- a/modbus.conf +++ b/modbus.conf @@ -20,7 +20,7 @@ modbus { access_log /var/log/modbus_access.log; } -collect_template t1 { +device_io t1 { # 轮询间隔 poll_interval 5s; @@ -48,6 +48,26 @@ collect_template t1 { poll on; } } + + # 写入控制 + controls { + # 启停控制 + power_switch { + address 00010; + type bool; + safe_value off; + } + + # PID设定值 + pid_setpoint { + address 40010; + type float32; + min 0.0; + max 100.0; + precision 0.1; + } + } + } device boiler_controller { @@ -56,8 +76,7 @@ device boiler_controller { model "Siemens S7-1200"; description "Main boiler controller"; - collect_template t1; - + io t1; # 写入控制 controls {