AVModbus.Client (avmodbus v0.1.0)

Copy Markdown View Source

serial bus または TCP connection を所有する managed Modbus client です。

通常の serial application では start_link/1 で process が UART を所有し、 request を順番に処理します。low-level transaction API は host-side tests や UART ownership を application 側で管理する用途に利用できます。

serial client では active transaction を 1 件に制限し、送信待ちは :max_queue で制限します。 queue saturation は {:error, :queue_full} を返します。unit 0 への write は broadcast として扱い、 response を読まず configured turnaround delay の後に transaction を完了します。 TCP の unit id は 0..255 を routing identifier として扱います。

start_link(transport: :tcp, host: host) では複数 request を transaction id で照合しながら並行送信する Modbus TCP client を起動します。wire 上の request は :max_pending、送信待ちは :max_queue で制限し、queue saturation は {:error, :queue_full} を返します。

child specification を実装しているため supervision tree に直接追加できます。 supervised child の raw PID、:name で登録した atom、start_link が返す tagged handle の いずれも全 managed client API で利用できます。

request function の最後の引数には timeout:、retries:、backoff: の keyword options を 指定できます。retry は明示的に指定した idempotent read にだけ適用され、write は再送しません。

managed client の :timeout option は request ごとの既定 deadline を指定します。 request 側の timeout を省略するとこの値を使い、明示した timeout: は client の既定値を 上書きします。

現在の AtomVM SSL API は Modbus/TCP Security が要求する mutual authentication を提供できないため、 tls: または ssl: option は {:error, :tls_not_supported} を返します。

Summary

Functions

user-defined public Function Code の request を送ります。

diagnostics sub-function を実行します。

任意の MEI type で Encapsulated Interface Transport を実行します。

communication event counter を読み取ります。

communication event log を読み取ります。

mask を使って 1 個の Holding Register を変更します。

指定 category の device identification を全 page 読み、object map として返します。

server の exception status を読み取ります。

FIFO queue を読み取ります。

file record group を読み取ります。

複数の Holding Register の書き込みと読み取りを 1 transaction で実行します。

server identification を読み取ります。

request を送信し、result を待ちます。

transient failure の場合だけ idempotent read request を再試行します。

transaction の完了を待たず managed client に request を送ります。

transport を指定しないため {:error, :missing_transport_option} を返します。

client option を使って configured UART を開き、その lifecycle を所有します。

managed client の現在の connection state を返します。

managed client を停止し、connection または所有する UART を閉じます。

file record group を書き込みます。

複数の Holding Register を書き込みます。

1 個の Holding Register を書き込みます。

Types

async_option()

@type async_option() :: {:timeout, non_neg_integer()} | {:to, pid()}

device_identification_category()

@type device_identification_category() :: :basic | :regular | :extended

device_identification_option()

@type device_identification_option() ::
  retry_option() | {:category, device_identification_category()}

option()

@type option() ::
  {:transport, :rtu | :ascii | :tcp}
  | {:host, term()}
  | {:echo, boolean()}
  | {:turnaround, pos_integer()}
  | {:silence, pos_integer()}
  | {:gap, non_neg_integer()}
  | {:serial, keyword()}
  | {:backoff, {pos_integer(), pos_integer()}}
  | {:port, 1..65535}
  | {:max_pending, 1..65536}
  | {:max_queue, non_neg_integer() | :infinity}
  | {:check_unit, boolean()}
  | {:connect_timeout, pos_integer()}
  | {:timeout, pos_integer()}
  | {:name, atom()}

request_result()

@type request_result() :: :ok | {:ok, term()} | {:error, term()}

retry_option()

@type retry_option() ::
  {:timeout, non_neg_integer()}
  | {:retries, non_neg_integer()}
  | {:backoff, {pos_integer(), pos_integer()}}

server()

@type server() :: pid() | atom()

t()

@opaque t()

Functions

custom(client, unit_id, function, data, options \\ [])

@spec custom(term(), 0..255, 1..127, binary(), [retry_option()]) :: request_result()

user-defined public Function Code の request を送ります。

diagnostics(client, unit_id, sub_function, data, options \\ [])

@spec diagnostics(term(), 0..255, AVModbus.word(), [AVModbus.word()], [retry_option()]) ::
  request_result()

diagnostics sub-function を実行します。

encapsulated_interface_transport(client, unit_id, mei_type, data, options \\ [])

@spec encapsulated_interface_transport(term(), 0..255, byte(), binary(), [
  retry_option()
]) ::
  request_result()

任意の MEI type で Encapsulated Interface Transport を実行します。

get_comm_event_counter(client, unit_id, options \\ [])

@spec get_comm_event_counter(term(), 0..255, [retry_option()]) :: request_result()

communication event counter を読み取ります。

get_comm_event_log(client, unit_id, options \\ [])

@spec get_comm_event_log(term(), 0..255, [retry_option()]) :: request_result()

communication event log を読み取ります。

mask_write_register(client, unit_id, address, and_mask, or_mask, options \\ [])

@spec mask_write_register(
  term(),
  0..255,
  AVModbus.address(),
  AVModbus.word(),
  AVModbus.word(),
  [retry_option()]
) :: request_result()

mask を使って 1 個の Holding Register を変更します。

read_coils(client, unit_id, address, quantity, options \\ [])

@spec read_coils(term(), 0..255, AVModbus.address(), pos_integer(), [retry_option()]) ::
  request_result()

Coil を読み取ります。

read_device_identification(client, unit_id, options \\ [])

@spec read_device_identification(term(), 0..255, [device_identification_option()]) ::
  {:ok, map()} | {:error, term()}

指定 category の device identification を全 page 読み、object map として返します。

category は :category option で指定し、既定値は :basic です。request 共通の :timeout、:retries、:backoff も指定できます。

read_discrete_inputs(client, unit_id, address, quantity, options \\ [])

@spec read_discrete_inputs(term(), 0..255, AVModbus.address(), pos_integer(), [
  retry_option()
]) ::
  request_result()

Discrete Input を読み取ります。

read_exception_status(client, unit_id, options \\ [])

@spec read_exception_status(term(), 0..255, [retry_option()]) :: request_result()

server の exception status を読み取ります。

read_fifo_queue(client, unit_id, address, options \\ [])

@spec read_fifo_queue(term(), 0..255, AVModbus.address(), [retry_option()]) ::
  request_result()

FIFO queue を読み取ります。

read_file_record(client, unit_id, groups, options \\ [])

@spec read_file_record(term(), 0..255, [term()], [retry_option()]) :: request_result()

file record group を読み取ります。

read_holding_registers(client, unit_id, address, quantity, options \\ [])

@spec read_holding_registers(term(), 0..255, AVModbus.address(), pos_integer(), [
  retry_option()
]) ::
  request_result()

Holding Register を読み取ります。

read_input_registers(client, unit_id, address, quantity, options \\ [])

@spec read_input_registers(term(), 0..255, AVModbus.address(), pos_integer(), [
  retry_option()
]) ::
  request_result()

Input Register を読み取ります。

read_write_multiple_registers(client, unit_id, read_address, read_quantity, write_address, write_values, options \\ [])

@spec read_write_multiple_registers(
  term(),
  0..255,
  AVModbus.address(),
  pos_integer(),
  AVModbus.address(),
  [AVModbus.word()],
  [retry_option()]
) :: request_result()

複数の Holding Register の書き込みと読み取りを 1 transaction で実行します。

report_server_id(client, unit_id, options \\ [])

@spec report_server_id(term(), 0..255, [retry_option()]) :: request_result()

server identification を読み取ります。

request(client, unit_id, request, options \\ [])

@spec request(term(), 0..255, AVModbus.PDU.request(), [retry_option()]) ::
  {:ok, term()} | :ok | {:error, term()}

request を送信し、result を待ちます。

最後の引数は timeout:、retries:、backoff: の keyword options です。 retries: は既定で 0 です。正の retry 回数は idempotent read にだけ許可し、:timeout と :closed の場合だけ再送します。

retry_request(client, unit_id, request, options \\ [])

@spec retry_request(term(), 0..255, AVModbus.PDU.request(), [retry_option()]) ::
  {:ok, term()} | {:error, term()}

transient failure の場合だけ idempotent read request を再試行します。

:timeout は各 attempt の timeout、:retries は最初の attempt 後に許可する追加回数、 :backoff は attempt 間の {first, maximum} delay です。timeout の省略時は managed client の startup default(既定 1000 ms)、unmanaged UART では 1000 ms を 使います。retry と backoff の既定値は 1 回、{100, 1000} ms です。

:timeout と :closed だけを retry します。write、diagnostics、custom request、 Modbus exception、invalid response は replay しません。

send_request(client, unit_id, request, options \\ [])

@spec send_request(t() | server(), 0..255, AVModbus.PDU.request(), [async_option()]) ::
  reference() | {:error, term()}

transaction の完了を待たず managed client に request を送ります。

request を受け付けた場合は reference を返し、recipient は後で {AVModbus.Client, reference, result} を 1 回受信します。受付時点で client を利用できない場合や queue が満杯の場合は reference を作らず {:error, reason} を返します。 request/4 と同様に、受付までの時間と queue 待ち時間も timeout に含まれます。

第 4 引数には timeout: と to: の keyword options を指定できます。

start_link()

@spec start_link() :: {:ok, t()} | {:error, term()}

transport を指定しないため {:error, :missing_transport_option} を返します。

start_link(transport: :rtu)、start_link(transport: :ascii)、または start_link(transport: :tcp, host: host) を使用してください。

start_link(options_or_uart)

@spec start_link([option()] | term()) :: {:ok, t()} | {:error, term()}

client option を使って configured UART を開き、その lifecycle を所有します。

:transport は必須で、:rtu、:ascii、:tcp のいずれかを指定します。 TCP では :host も必須です。serial の主な option は adapter echo を除去する :echo、 broadcast 後の :turnaround、送信前の :gap、unknown-length response を区切る :silence、instance UART 設定の :serial、待機 request 上限の :max_queue、request の既定 deadline を指定する :timeout、UART reopen delay を指定する :backoff ({first, maximum}) です。 時間指定は millisecond 単位です。

status(server)

@spec status(t() | server()) :: :connected | :connecting | {:disconnected, term()}

managed client の現在の connection state を返します。

stop(server)

@spec stop(t() | server()) :: :ok

managed client を停止し、connection または所有する UART を閉じます。

write_file_record(client, unit_id, groups, options \\ [])

@spec write_file_record(term(), 0..255, [term()], [retry_option()]) ::
  request_result()

file record group を書き込みます。

write_multiple_coils(client, unit_id, address, values, options \\ [])

@spec write_multiple_coils(term(), 0..255, AVModbus.address(), [boolean()], [
  retry_option()
]) ::
  request_result()

複数の Coil を書き込みます。

write_multiple_registers(client, unit_id, address, values, options \\ [])

@spec write_multiple_registers(
  term(),
  0..255,
  AVModbus.address(),
  [AVModbus.word()],
  [retry_option()]
) ::
  request_result()

複数の Holding Register を書き込みます。

write_single_coil(client, unit_id, address, value, options \\ [])

@spec write_single_coil(term(), 0..255, AVModbus.address(), boolean(), [
  retry_option()
]) ::
  request_result()

1 個の Coil を書き込みます。

write_single_register(client, unit_id, address, value, options \\ [])

@spec write_single_register(
  term(),
  0..255,
  AVModbus.address(),
  AVModbus.word(),
  [retry_option()]
) :: request_result()

1 個の Holding Register を書き込みます。