ModBoss (modboss v0.1.0)
Human-friendly modbus reading, writing, and translation.
Read and write modbus values by name, with automatic encoding and decoding.
Summary
Types
@type read_func() :: (register_type(), starting_address :: integer(), count :: integer() -> {:ok, any()} | {:error, any()})
@type register_type() :: :holding_register | :input_register | :coil | :discrete_input
@type write_func() :: (register_type(), starting_address :: integer(), value_or_values :: any() -> :ok | {:error, any()})
Functions
Read from modbus using named mappings.
This function takes either an atom or a list of atoms representing the mappings to read, batches the mappings into contiguous addresses per type, then reads and decodes the values before returning them.
For each batch, read_func
will be called with the type of register (:holding_register
,
:input_register
, :coil
, or :discrete_input
), the starting address for the batch
to be read, and the count of addresses to read from. It must return either {:ok, result}
or {:error, message}
.
If a single name is requested, the result will be an :ok tuple including the singule result for that named mapping. If a list of names is requested, the result will be an :ok tuple including a map with mapping names as keys and mapping values as results.
Opts
:decode
— iffalse
, returns the "raw" result as provided byread_func
; defaults totrue
Examples
read_func = fn register_type, starting_address, count ->
result = custom_read_logic(…)
{:ok, result}
end
# Read one mapping
ModBoss.read(SchemaModule, read_func, :foo)
{:ok, 75}
# Read multiple mappings
ModBoss.read(SchemaModule, read_func, [:foo, :bar, :baz])
{:ok, %{foo: 75, bar: "ABC", baz: true}}
# Read *all* readable mappings
ModBoss.read(SchemaModule, read_func, :all)
{:ok, %{foo: 75, bar: "ABC", baz: true, qux: 1024}}
# Get "raw" Modbus values (as returned by `read_func`)
ModBoss.read(SchemaModule, read_func, :all, decode: false)
{:ok, %{foo: 75, bar: [16706, 17152], baz: 1, qux: 1024}}
@spec write(module(), write_func(), values_to_write()) :: :ok | {:error, any()}
Write to modbus using named mappings.
ModBoss automatically encodes your values
, then batches any encoded values destined for
contiguous registers—creating separate batches per register type.
For each batch, write_func
will be called with the type of register (:holding_register
or
:coil
), the starting address for the batch to be written, and a list of values to write.
It must return either :ok
or {:error, message}
.
Batch values
Each batch will contain either a list or an individual value based on the number of addresses to be written—so you should be prepared for both.
Non-atomic writes!
While ModBoss.write/3
has the feel of being atomic, it's important to recognize that it
is not! It's fully possible that a write might fail after prior writes within the same call to
ModBoss.write/3
have already succeeded.
Within ModBoss.write/3
, if any call to write_func
returns an error tuple,
the function will immediately abort, and any subsequent writes will be skipped.
Example
write_func = fn register_type, starting_address, value_or_values ->
result = custom_write_logic(…)
{:ok, result}
end
iex> ModBoss.write(MyDevice.Schema, write_func, foo: 75, bar: "ABC")
:ok