Resources

Resources

Resources are the heart of Octave edge device. The Resources of a device define the services, sensors, and actuators that make up a solution, and are defined and organized as a tree on a device, similar to that of a file system on your computer.

More generally Resources represents "things" that create, receive, or store Events. Since resources are organized into a tree, each Resource will have a path that identifies its location. For example, a sensor defined as a resource, might be represented as /redSensor/light, an actuator defined by the LCD driver might be called /lcd/txt, and the configuration for a GPIO service might be defined in /io/config.

Your Device will initially broadcast its Resource Tree, such that it is available to view in the Octave Dashboard as well as through the Device object in the Octave REST API.

All resources are either an input or output, and are stateful (i.e. they hold the last single value sent to them). Inputs are tied to sensors and generate new Events from the underlying application or hardware (e.g. the temperature data from a temperature sensor). Outputs (actuators) forward Events to the application or hardware (e.g. to move a robotic arm.)

Inputs move data from the application to the Data Hub and Outputs move data from the DataHub, to the application. However, the direction is not strictly enforced and is used primarily to advertise the expected direction of flow. Applications may read / subscribe to Inputs if they want to and they may also write values to Outputs.

Each Resource is also of a particular data type which can be a trigger, boolean, numeric, string, or JSON. Values of the wrong type are sometimes coerced to the right type. For example, if you send any non-zero number to a boolean type, it will be coerced to true.

Additional Resources

A Sensor or Actuator will normally expose multiple Resources - both for direct access to the hardware and for configuration purposes. For example, a light sensor might expose the following resources:

PathTypeData TypeMandatoryDefault Value
/sensor/light/valueinputnumeric--
/sensor/light/enableoutputbooleanfalsefalse
/sensor/light/periodoutputnumerictrue-
/sensor/light/calibrationoutputJSONfalse{min: 1234, max:5678}

The value Resource is the standardized naming convention for the Resource which generates the Events the Sensor is named for. So in this example, /sensor/light/value will generate light readings. For additional information about naming see Resource Names and Data Representations Across Contexts below.

A Sensor also exposes other Resources for configuration. The period Resource accepts a numeric value (in seconds) for how frequently the hardware should be polled, and emit a new Event on the value Resource. For example, a temperature sensor might have a polling frequency. If the sensor exposes a numeric Output called /polling_frequency, it can then receive values pushed to that Resource, and update its polling frequency accordingly.

Interrupt-based sensors, such as alarms, might not have this Resource. The Sensor driver has marked this Resource mandatory, indicating that a numeric value must be sent to this Resource for the Sensor to work.

The enable Resource allows the system to turn the Sensor on or off.

The calibration Resource allows the system to provide calibration information to the driver. It is marked non-mandatory, so the Sensor can be used without providing this information. If a value is not provided, it will default to the default value. The Resource's data type is JSON, indicating that it receives a string value containing valid JSON.

Initial Configuration

Before a Resource such as light sensor can do work, you must configure the output Resources enable and period. To do so, you must push a new Event to the Resource, either immediately or every time the Device powers on. The latter is the preferred approach, and involves adding our values to the Device.state object.

The Device object has a state attribute, which contains a map of keys (Resource path) and associated values. Any updates to Resource Configuration, Observations or Edge Actions will be sent to the Device when it is next connected to the cellular network, and then persisted locally such that it will survive restarts.

Types of Resources

Digital Input (GPIO)

GPIO pins configured as inputs in Octave will report their value as true or false depending on if the voltage, which varies by pin, is above or below the midpoint of a voltage range (within some tolerance). Internal pull-up or pull-down resistors can also be enabled.

If edge detection is enabled, the IO Service will update the value of the digital input and emit an event to any Observation attached to the Resource any time the state changes from high to low, or vice versa. Without edge detection, you must configure a period on your IO Resource and the IO Service will report a boolean value at the specified periodicity. This "interrupt" functionality can be very useful when detecting events like a button push or switch throw that you might otherwise miss between polls when observing boolean values at a set period.

Digital Output (GPIO)

Digital output pins are also represented as boolean values. When these Resources are set, they drive a low or high output voltage over the pin. Common use cases for Digital Output pins include lighting an LED or controlling a relay.

Analog Input (ADC)

Depending on your hardware, one or more analog-to-digital converters are available for converting the sensed voltage on a particular pin to a numeric Resource value.

Virtual Resources

Virtual Resources are used on a device to store:

  • the state of a device;
  • a JSON document of the parameters to be reported to the Cloud; or
  • configuration parameters which can be updated from the Cloud.

A Virtual Resource can be used, for example, with a setpoint for an asset controller, or an alert threshold, which must be configured per device and can change over time.

The value of a Virtual Resource can be modified from the cloud by sending an event to the stream :command of the device.

Virtual resources are stored in the device tree. Resource path scheme is: /virtual//value.
Primary creation mechanism is using the /virtual/config output Resource.

Up to 50 Virtual Resources can be created. Each virtual resource can be of any of these types: boolean, numeric, string or json.

Virtual resources are observable like any other resource: their value can be sent to the Cloud on each update or to an edge action.

Persistence of Virtual Resources

There is no specific option to persist the Virtual Resources: any Virtual Resource defined in the /virtual/config resource is persisted on the device.

The values of the resources are written in the flash memory :

  • every 60 seconds,
  • when the Virtual Resource configuration is updated,
  • when the edge goes to low power mode,
  • when edge reboot command is triggered: /util/reboot/trigger.

When the edge is switched on, the virtual application reads the new value from the internal storage and initialize the resource with the latest value stored. If there is no value stored in the non volatile memory, the configured value is applied.

When a blueprint is applied, the configured value in the cloud is not used to set the new value of the virtual resource. This way the persisted value on the edge remains.

When a new configuration is sent from the cloud, if it is set, the Configured value is applied to the virtual resource which may change.

From the Cloud it is also possible to update any virtual resource sending an event with the virtual resource value path to the :command stream of the device.

It is also possible to create non persisted Virtual Resource from an edge action, using the following syntax, in this case the resource will not be persisted.

return { "vr://my_resource_name": [my_resource_value] }

Resource Names and Data Representations Across Contexts

Octave features various ways of naming resources and representing data depending on the context of use.

Data

Event in Streams and input to Cloud Action

When an Event is received in a Cloud action, the event parameter is deserialized from the following JSON.
Note that the resource 'value' is not included in the event sent to the Cloud, the actual value is reported under the resource name directly.

{
  "elems": { 
    //event JSON
    "virtual" : { 
      "NAME" : value
    }
  },
  "tags": {},
  "metadata": null
}

Event in Edge Action
When an Event is received in a Cloud action, the event parameter is deserialized from the following JSON.

function(event) {
 
  //edge action script
 var Val = event.value;
  
}
 
//event JSON 
{
  "value" : value,
  "timestamp" : ts // ex: 1582827837.235676 (float)
}

For example, the code can read the value of a light sensor Resource from event.value:

function(event){
  var lightReading = event.value;
  var lightDescription;

  if (lightReading > 1500) {
    lightDescription = "bright";
  } else if (lightReading > 300) {
    lightDescription = "a bit dim";
  } else {
    lightDescription = "dark";
  }

  var s = "It's " + lightDescription + " in here.";

  return {
    "dh://lcd/txt3":[s]
  }
}

Resource Names

Virtual Resources

ContextValue
Resource Name/virtual/NAME/value
Action Result Objectvr://NAME or dh://virtual/NAME/value
Datahub.read() / Datahub.query()/virtual/NAME/value

Resource Trigger

ContextValue
Resource Name/util/reboot/trigger
Action Result Objectdh://util/reboot/trigger