Skip to content

Commit

Permalink
Merge pull request #1 from finkandreas/master
Browse files Browse the repository at this point in the history
*add* add write_multiple_registers
  • Loading branch information
hirschenberger committed Feb 23, 2016
2 parents 090a040 + 6b06cd4 commit bd87054
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 12 deletions.
25 changes: 25 additions & 0 deletions lib/ex_modbus/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ defmodule ExModbus.Client do
GenServer.call(pid, {:write_single_coil, %{unit_id: unit_id, start_address: address, state: state}})
end


def write_single_register(pid, unit_id, address, data) do
GenServer.call(pid, {:write_single_register, %{unit_id: unit_id, start_address: address, state: data}})
end


def write_multiple_registers(pid, unit_id, address, data) do
GenServer.call(pid, {:write_multiple_registers, %{unit_id: unit_id, start_address: address, state: data}})
end


def generic_call(pid, unit_id, {call, address, count, transform}) do
%{data: {_type, data}} = GenServer.call(pid, {call, %{unit_id: unit_id, start_address: address, count: count}})
transform.(data)
Expand Down Expand Up @@ -72,6 +83,20 @@ defmodule ExModbus.Client do
{:reply, response, socket}
end

def handle_call({:write_single_register, %{unit_id: unit_id, start_address: address, state: data}}, _from, socket) do
response = Modbus.Packet.write_single_register(address,data)
|> Modbus.Tcp.wrap_packet(unit_id)
|> send_and_rcv_packet(socket)
{:reply, response, socket}
end

def handle_call({:write_multiple_registers, %{unit_id: unit_id, start_address: address, state: data}}, _from, socket) do
response = Modbus.Packet.write_multiple_registers(address, data)
|> Modbus.Tcp.wrap_packet(unit_id)
|> send_and_rcv_packet(socket)
{:reply, response, socket}
end

def handle_call(msg, _from, state) do
Logger.info "Unknown handle_cast msg: #{inspect msg}"
{:reply, "unknown call message", state}
Expand Down
58 changes: 46 additions & 12 deletions lib/modbus/packet.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@ defmodule Modbus.Packet do
"""

# Function Codes
@read_coils 0x01
@read_coils_exception 0x81
@read_discrete_inputs 0x02
@read_holding_registers 0x03
@read_holding_registers_exception 0x83
@read_input_registers 0x04

@write_single_coil 0x05
@write_single_coil_exception 0x85
@write_single_register 0x06
@write_multiple_coils 0x0f
@write_multiple_registers 0x10
@read_coils 0x01
@read_coils_exception 0x81
@read_discrete_inputs 0x02
@read_holding_registers 0x03
@read_holding_registers_exception 0x83
@read_input_registers 0x04

@write_single_coil 0x05
@write_single_coil_exception 0x85
@write_single_register 0x06
@write_single_register_exception 0x86
@write_multiple_coils 0x0f
@write_multiple_registers 0x10
@write_multiple_registers_exception 0x90

@single_coil_off 0x0000
@single_coil_on 0xff00
Expand Down Expand Up @@ -50,6 +52,13 @@ defmodule Modbus.Packet do
end
end

defmacrop write_multiple(function_code, starting_address, count, data) do
quote do
<<unquote(function_code), unquote(starting_address)::size(16)-big, unquote(count)::size(16)-big, unquote(data)::binary>>
end
end


@doc """
Read status from a contiguous range of coils.
`starting_address` is 0-indexed.
Expand Down Expand Up @@ -92,6 +101,15 @@ defmodule Modbus.Packet do
end
end


def write_single_register(starting_address, data) do
write_single(@write_single_register, starting_address, data)
end

def write_multiple_registers(starting_address, data) do
write_multiple(@write_multiple_registers, starting_address, round(byte_size(data)/2), data)
end

@doc """
Parse a ModbusTCP response packet
"""
Expand Down Expand Up @@ -127,6 +145,22 @@ defmodule Modbus.Packet do
{:ok, {:write_single_coil_exception, exception_code(exception)}}
end

def parse_response_packet(<<@write_single_register, _size, data::binary>>) do
{:ok, {:write_single_register, data}}
end

def parse_response_packet(<<@write_single_register_exception, exception>>) do
{:ok, {:write_single_register_exception, exception_code(exception)}}
end

def parse_response_packet(<<@write_multiple_registers, _size, data::binary>>) do
{:ok, {:write_multiple_registers, data}}
end

def parse_response_packet(<<@write_multiple_registers_exception, exception>>) do
{:ok, {:write_multiple_registers_exception, exception_code(exception)}}
end

def parse_response_packet(packet = <<function_code, _byte_count, _data::binary>>) do
{:error, "Unknown function code #{function_code}, pkt = #{inspect packet}"}
end
Expand Down

0 comments on commit bd87054

Please sign in to comment.