scenic_sensor v0.7.0 Scenic.Sensor

A combination pub/sub server and data cache for sensors. It is intended to be the interface between sensors (or other data sources) and Scenic scenes, although it has no dependencies on Scenic and can be used in other applications.

Installation

Scenic.Sensor can be installed by adding :scenic_sensor to your list of dependencies in mix.exs:

def deps do
  [
    {:scenic_sensor, "~> 0.7.0"}
  ]
end

Startup

In order to use Scenic.Sensor, you must first add it to your supervision tree. It should be ordered in the tree so that it has a chance to initialize before other processes start making calls to it.

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    opts = [strategy: :one_for_one, name: ScenicExample]
    children = [
      {Scenic.Sensor, nil},
      ...
    ]
    Supervisor.start_link(children, strategy: :one_for_one)
  end

Registering Sensors

Before a process can start publishing data from a sensor, it must register that sensor with Scenic.Sensor. This both prevents other processes from stepping on that data and alerts any subscribing processes that the sensor is coming online.

  Scenic.Sensor.register( :sensor_id, version, description )

The :sensor_id parameter must be an atom that names the sensor. Subscribers will look for data from this sensor through that id.

The version and description paramters are bitstrings that describe this sensor. Scenic.Sensor itself does not process these values, but passes them to the listeners when the sensor comes online or when the sensors are listed.

Sensors can also unregister if they are no longer available.

Scenic.Sensor.unregister( :sensor_id )

Simply exiting the sensor does also cleans up its registration.

Publishing Data

When a sensor process publishes data, two things happen. First, that data is cached in an :ets table so that future requests for that data from scenes happen quickly and don’t need to bother the sensor. Second, any processes that have subscribed to that sensor are sent a message containing the new data.

  Scenic.Sensor.publish( :sensor_id, sensor_value )

The :sensor_id parameter must be an atom that was previously registered by calling process.

The sensor_value parameter can be anything that makes sense for the sensor.

Subscribing to a sensor

Scenes (or any other process) can subscribe to a sensor. They will receive messages when the sensor updates its data, comes online, or goes away.

  Scenic.Sensor.subscribe( :sensor_id )

The :sensor_id parameter is the atom registered for the sensor.

The subscribing process with then start receiving messages that can be handled with handle_info/2

eventmessage
data{:sensor, :data, {:sensor_id, data, timestamp}}
registered{:sensor, :registered, {:sensor_id, version, description}}
unregistered{:sensor, :unregistered, :sensor_id}

Scenes can also unsubscribe if they are no longer interested in updates.

  Scenic.Sensor.unsubscribe( :sensor_id )

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor

Retrieve the cached data for a named sensor

List the registered sensors

Publish a data point from a sensor

Register the calling process as a data source for a sensor

Subscribe the calling process to receive events about a sensor

Unregister the calling process as a data source for a sensor

Unsubscribe the calling process from receive events about a sensor

Link to this section Functions

Link to this function child_spec(arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function get(sensor_id)
get(sensor_id :: atom()) :: {:ok, any()} | {:error, :no_data}

Retrieve the cached data for a named sensor.

This data is pulled from an :ets table and does not put load on the sensor itself.

Parameters

  • sensor_id an atom that is registered to a sensor.

Return Value

  {:ok, {sensor_id, data, timestamp}}
  • sensor_id is the atom representing the sensor.
  • data is whatever data the sensor last published.
  • timestamp is the time - from :os.system_time(:micro_seconds) - the last data was published.

If the sensor is either not registered, or has not yet published any data, get returns

  {:error, :no_data} 
Link to this function list()
list() :: list()

List the registered sensors.

Return Value

list/0 returns a list of registered sensors

  [{sensor_id, version, description, pid}]
  • sensor_id is the atom representing the sensor.
  • version is the version string supplied by the sensor during registration.
  • description is the description string supplied by the sensor during registration.
  • pid is the pid of the sensor process.
Link to this function publish(sensor_id, data)
publish(sensor_id :: atom(), data :: any()) :: :ok

Publish a data point from a sensor.

When a sensor uses publish/2 to publish data, that data is recorded in the cache and a

  {:sensor, :data, {:sensor_id, data, timestamp}}

message is sent to each subsciber. The timestamp is the current time in microsecods as returned from :os.system_time(:micro_seconds).

Parameters

  • sensor_id an atom that is registered to a sensor.
  • data the data to publish.

Return Value

On success, returns :ok

It returns {:error, :not_registered} if the caller is not the registered process for the sensor.

Link to this function register(sensor_id, version, description)
register(sensor_id :: atom(), version :: String.t(), description :: String.t()) ::
  :ok

Register the calling process as a data source for a sensor.

Parameters

  • sensor_id the sensor it being registered.
  • version the sensor version string.
  • description a sensor description string.

Return Value

On success, returns :ok

If sensor_id is already registered to another process, it returns

{:error, :already_registered}
Link to this function subscribe(sensor_id)
subscribe(sensor_id :: atom()) :: :ok

Subscribe the calling process to receive events about a sensor.

The events the caller will start receiving about a sensor are:

eventmessage
data{:sensor, :data, {:sensor_id, data, timestamp}}
registered{:sensor, :registered, {:sensor_id, version, description}}
unregistered{:sensor, :unregistered, :sensor_id}

Parameters

  • sensor_id an atom that is registered to a sensor.

Return Value

On success, returns :ok

Link to this function unregister(sensor_id)
unregister(sensor_id :: atom()) :: :ok

Unregister the calling process as a data source for a sensor.

Parameters

  • sensor_id the sensor it being registered.

Return Value

Returns :ok

Link to this function unsubscribe(sensor_id)
unsubscribe(sensor_id :: atom()) :: :ok

Unsubscribe the calling process from receive events about a sensor.

The caller will stop receiving events about a sensor

Parameters

  • sensor_id an atom that is registered to a sensor.

Return Value

Returns :ok