Current section
Files
Jump to
Current section
Files
lib/driver.ex
defmodule Driver do
@moduledoc false
use GenServer, restart: :permanent
# Macros
# --------------------------------------------
@call_timeout 1000
@button_map %{:up => 0, :down => 1, :cab => 2}
@state_map %{:on => 1, :off => 0}
@direction_map %{:up => 1, :down => 255, :stop => 0}
# Public Functions
# --------------------------------------------
def start_link([]), do: start_link([{127, 0, 0, 1}, 15657])
def start_link([address, port]),
do: GenServer.start_link(__MODULE__, [address, port], name: __MODULE__)
def stop, do: GenServer.stop(__MODULE__)
def init([address, port]),
do: {:ok, socket} = :gen_tcp.connect(address, port, [{:active, false}])
def terminate(_, socket) do
:gen_tcp.close(socket)
{:ok, socket}
end
# User API
# --------------------------------------------
# direction can be :up/:down/:stop
def set_motor_direction(direction),
do: GenServer.cast(__MODULE__, {:set_motor_direction, direction})
# button_type can be :up/:down/:cab
# state can be :on/:off
# slightly modified to be able to set order lights on other nodes
def set_order_button_light(nodeList \\ [node()], button_type, floor, state),
do:
GenServer.abcast(nodeList, __MODULE__, {:set_order_button_light, button_type, floor, state})
def set_floor_indicator(floor), do: GenServer.cast(__MODULE__, {:set_floor_indicator, floor})
# state can be :on/:off
def set_door_open_light(state), do: GenServer.cast(__MODULE__, {:set_door_open_light, state})
def get_order_button_state(floor, button_type),
do: GenServer.call(__MODULE__, {:get_order_button_state, floor, button_type})
def get_floor_sensor_state, do: GenServer.call(__MODULE__, :get_floor_sensor_state)
# Casts
# --------------------------------------------
def handle_cast({:set_motor_direction, direction}, socket) do
:gen_tcp.send(socket, [1, @direction_map[direction], 0, 0])
{:noreply, socket}
end
def handle_cast({:set_order_button_light, button_type, floor, state}, socket) do
:gen_tcp.send(socket, [2, @button_map[button_type], floor, @state_map[state]])
{:noreply, socket}
end
def handle_cast({:set_floor_indicator, floor}, socket) do
:gen_tcp.send(socket, [3, floor, 0, 0])
{:noreply, socket}
end
def handle_cast({:set_door_open_light, state}, socket) do
:gen_tcp.send(socket, [4, @state_map[state], 0, 0])
{:noreply, socket}
end
# Calls
# --------------------------------------------
def handle_call({:get_order_button_state, floor, order_type}, _from, socket) do
:gen_tcp.send(socket, [6, @button_map[order_type], floor, 0])
button_state =
case :gen_tcp.recv(socket, 4, @call_timeout) do
{:ok, [6, 1, 0, 0]} -> :on
{:ok, [6, 0, 0, 0]} -> :off
end
{:reply, button_state, socket}
end
def handle_call(:get_floor_sensor_state, _from, socket) do
:gen_tcp.send(socket, [7, 0, 0, 0])
sensor_state =
case :gen_tcp.recv(socket, 4, @call_timeout) do
{:ok, [7, 0, _, 0]} -> :between_floors
{:ok, [7, 1, floor, 0]} -> floor
end
{:reply, sensor_state, socket}
end
end