defmodule Modbux.Request do @moduledoc """ Request helper, functions that handles Client & Master request messages. """ alias Modbux.Helper @spec pack({:fc | :phr | :rc | :rhr | :ri | :rir, integer, integer, maybe_improper_list | integer}) :: <<_::48, _::_*8>> def pack({:rc, slave, address, count}) do reads(:d, slave, 1, address, count) end def pack({:ri, slave, address, count}) do reads(:d, slave, 2, address, count) end def pack({:rhr, slave, address, count}) do reads(:a, slave, 3, address, count) end def pack({:rir, slave, address, count}) do reads(:a, slave, 4, address, count) end def pack({:fc, slave, address, value}) when is_integer(value) do write(:d, slave, 5, address, value) end def pack({:phr, slave, address, value}) when is_integer(value) do write(:a, slave, 6, address, value) end def pack({:fc, slave, address, values}) when is_list(values) do writes(:d, slave, 15, address, values) end def pack({:phr, slave, address, values}) when is_list(values) do writes(:a, slave, 16, address, values) end @spec parse(<<_::24, _::_*8>>) :: {:einval | :error | :fc | :phr | :rc | :rhr | :ri | :rir, byte, char, [any] | char} def parse(<>) do {:rc, slave, address, count} end def parse(<>) do {:ri, slave, address, count} end def parse(<>) do {:rhr, slave, address, count} end def parse(<>) do {:rir, slave, address, count} end def parse(<>) do {:fc, slave, address, 0} end def parse(<>) do {:fc, slave, address, 1} end def parse(<>) do {:phr, slave, address, value} end # Another slave response an error. def parse(<>) do ^bytes = Helper.byte_count(count) values = Helper.bin_to_bitlist(count, data) {:fc, slave, address, values} end def parse(<>) do ^bytes = 2 * count values = Helper.bin_to_reglist(count, data) {:phr, slave, address, values} end # Exceptions clauses def parse(<>) when fc in 129..144 do {:error, slave, fc, error_code} end def parse(<>) do {:einval, slave, fc, error_code} end @spec length({:fc | :phr | :rc | :rhr | :ri | :rir, any, any, any}) :: integer def length({:rc, _slave, _address, _count}) do 6 end def length({:ri, _slave, _address, _count}) do 6 end def length({:rhr, _slave, _address, _count}) do 6 end def length({:rir, _slave, _address, _count}) do 6 end def length({:fc, _slave, _address, value}) when is_integer(value) do 6 end def length({:phr, _slave, _address, value}) when is_integer(value) do 6 end def length({:fc, _slave, _address, values}) when is_list(values) do 7 + Helper.byte_count(Enum.count(values)) end def length({:phr, _slave, _address, values}) when is_list(values) do 7 + 2 * Enum.count(values) end defp reads(_type, slave, function, address, count) do <> end defp write(:d, slave, function, address, value) do <> end defp write(:a, slave, function, address, value) do <> end defp writes(:d, slave, function, address, values) do count = Enum.count(values) bytes = Helper.byte_count(count) data = Helper.bitlist_to_bin(values) <> end defp writes(:a, slave, function, address, values) do count = Enum.count(values) bytes = 2 * count data = Helper.reglist_to_bin(values) <> end end