Skip to content
Oleksiy Kebkal edited this page Jan 26, 2017 · 4 revisions

MODULE

role_worker behavior

MODULE SUMMARY

The role_worker behavior takes care of communication via interfaces supported in the framework. For a behavior implementation it is required to define callbacks, responsible for parsing a raw data into user defined data structures (Module:to_term/3) and for generation of raw data from a user defined data structure (Module:from_term/2), initialization callback Module:start/3, configuration callback Module:ctrl/2 and Module:stop/1 called when the process is terminated. One fsm_mod_supervisor can supervise several interface processors according to the agent configuration. Useful examples of the interfaces processors are role_at (EvoLogics modem interface processor) and role_nmea (NMEA interface procerssor).

DESCRIPTION

Interface types

Agents can interact with other agents and with external applications using interface processors of different types, as shown on the figure below:

  • TCP socket: tcp. This is the most common interface type, used by the interface processors, that can be used both for agent-to-agent and agent-to-external application interaction
  • Erlang port: port. Ports provide the basic mechanism for communication with the external world, providing a byte-oriented interface to an external program. This interface type can be used for the interaction of the agents with external applications only
  • Erlang message queue: erlang. The interface can be used for direct message exchange between agents without data parsing by interface processors
  • Web interface: cowboy. This interface type converts user actions in a web browser to messages delivered via interface processors to agents and generates necessary responses to the user requests. Server side is implemented using cowboy HTTP server. Cowboy is a small, fast and modular HTTP server written in Erlang

Configuration

Interface processor configuration is defined by one of the following tuples

{role, Name, iface, Interface}
or
{role, Name, param, Param, iface, Interface}
where
  • Name is an atom, unequally identifying the interface processor
  • Param is an optional parameter passed as params of mm record to Module:start/3
  • Interface defines specific for the supported types interface parameters

TCP socket

Interface parameters of a TCP socket interface processor is defined by described below tuple

{socket, Address, Port, Type}
where
  • Address is an IPv4 address string
  • Port a socket port number
  • Side is an atom client or server
Configuration example
{role, nmea, iface, {socket, "10.1.0.12", 12000, server}}

Erlang port

Interface parameters of an Erlang port interface processor is defined by described below tuple

{port, Port, PortSettings}
where
  • Port a double tuple describing an external program to run
  • PortSettings port settings, directly passed as the second argument to erlang:open_port/2 call
If the first item of Port is one of the following atoms - spawn, spawn_driver, spawn_executable, fd, this tuple is passed as the first argument to erlang:open_port/2, otherwise it assumed to have the following format {Application,Executable} and tries to run an Executable for the Application private directory.

Configuration example

{role,ext_example,iface,{port,{ext_example,ext_example},[]}}

Web interface

tbd

Erlang message queue

tbd

DATA TYPES

mm() = 
  #mm{role = atom,
      role_id = atom,
      status = true | false,
      params = [any()],
      iface = iface()}

cfg() = any()

ip4_address() = {0..255, 0..255, 0..255, 0..255}

iface() = socket_iface() | port_iface() | cowboy_iface() | erlang_iface()

socket_iface() = 
  {socket,
   IP :: ip4_address(),
   Port :: integer() > 0,
   Type :: client | server}

port_iface() =
  {port,
   PortName,
   PortSettings} %% see erlang:open_port/2 type specification

cowboy_iface() =
  {cowboy,
   IP :: string(),
   Port :: integer() > 0}

erlang_iface() =
  {erlang, ModuleID :: atom} |
  {erlang, {ModuleID :: atom, Remote :: node()}

parse_state() = 
 [TermList :: [any()],
  ErrorList:: [{error, any()}],
  Raw :: binary(),
  More :: binary(),
  NewCfg :: cfg()] 

EXPORTS

to_term(Module, Tail, Chunk, Cfg) -> Result

Types

  Module = atom()
  Tail = binary()
  Chunk = binary()
  Cfg = cfg()
Implement simplified raw data parser, calling optional callback function Module:split/2.

CALLBACK FUNCTIONS

The following functions must be exported from a role_worker callback module.

EXPORTS

Module:start(RoleID, ModID, MiddleMen) -> Result

Types:

 RoleID = atom
 ModID = atom
 MiddleMen = mm()
 Result = {ok,pid()} | ignore | {error,any()}
Module::stop(Cfg) -> ok

Types:

  Cfg = cfg()
Module:to_term(Tail, Bin, Cfg) -> Result

Types:

  Tail = binary()
  Bin = binary() | list()
  Cfg = cfg()
  Result = parse_state()
Module:from_term(Term, Cfg) -> Result

Types:

  Term = any()
  Cfg = cfg()
  Result = {error, Reason} | [Bin :: binary(), NewCfg :: cfg()]
Module:ctrl(Ctrl, Cfg) -> Result

Types:

  Ctrl = any()
  Cfg = cfg()
  Result = cfg()

OPTIONAL CALLBACK

Module:split(Raw, Cfg) -> Result

Types:

  Raw = binary()
  Cfg = cfg()
  Result = [{more,binary()} | {error,any()} | {ctrl, any()} | any()]

SEE ALSO

fsm, fsm_worker