Writing Your First Blueprint
Enapter Blueprint has the same purpose as a real device blueprint. It tells the platform about device interfaces and capabilities. The platform uses this information to properly show your device in mobile and web applications and to setup device-related logic in an energy system.
You will normally use the same blueprint to setup any device of the same or similar model.
The minimal blueprint consists of two components:
- The Manifest defines your device interface and capabilities. It's always represented as a
manifest.yml
file. - UCM Lua Script implements the logic required for communication with your endpoint device. Usually you'll find it as a
ucm.lua
file.
Long story short, you will just create these two files on your computer or in Enapter Web IDE, upload it using CLI or with one-click IDE button to the UCM and the platform, and you are done, ready to explore your device in Enapter Web and mobile applications.
Example Device​
For the purpose of this tutorial we are implementing a simple blueprint for a fictional hydrogen sensor. Let's say it works over the RS-485 communication standard and supports Modbus RTU protocol, so we will be using ENP-RS485 UCM in our examples. Note that you do not necessarily need ENP-RS485, any other Lua-powered UCM will work for the tutorial as well.
The hydrogen sensor provides its serial number and H2 concentration from the Modbus registers. It has a sound alarm for critical H2 levels. For checking purposes it will make the sound if you write into a specific Modbus register.
Manifest File​
Blueprint manifest describes your device in a few core concepts:
properties
— device metadata which does not change during normal device operation. "Firmware version", "Device model" and "Serial number" fit this well.telemetry
— device sensors data and internal state which must be tracked during device operation. Examples are "Engine temperature" and "Connection status".alerts
— alerts that the device can raise during operation. An example is "Engine overheating".commands
— commands which can be performed on the device. An example is "Turn on engine".
- Web IDE
- CLI
Create new blueprint in Enapter Cloud, you'll get into an editor with manifest.yml
opened. Substitute the whole file contents with the listing below.
Create an empty directory that will contain blueprint files and add the manifest.yml
file from the listing below (the file name is important).
The file is based on YAML standard which is sensible to lines indentation. We highly recommend using a text editor or an IDE with YAML support.
# Blueprint specification version
blueprint_spec: device/1.0
display_name: H2 Sensor
description: Tutorial example of hydrogen sensor.
icon: enapter-gauge
# Communication module describes a UCM which should be used
# to implement device integration
communication_module:
# Product code of the UCM
product: ENP-RS485
# File name of Lua script file located in the same directory.
# It will be uploaded to the UCM.
lua_file: ucm.lua
# Properties are metadata that does not change during device normal operation
properties:
# Property reference name
serial_number:
# Property type, one of: boolean, float, integer, string
type: string
display_name: Serial Number
# Sensors data and internal device state, operational data
telemetry:
# Telemetry attribute reference name
h2_concentration:
# Attribute type, one of: boolean, float, integer, string
type: float
# Unit of measurement
unit: "%LEL"
display_name: H2 Concentration
# Alerts which the device can raise during operation
alerts:
# Alert reference name
h2_high:
# Alert severity, one of: info, warning, error.
severity: error
display_name: High H2 Concentration
# Commands which can be performed on the device
commands:
# Command reference name
beep:
display_name: Beep
# Command group name (declared below)
group: checks
ui:
# Command icon to show in a user interface
icon: bell-ring-outline
# Show command in quick access list on mobile
quick_access: true
silence:
display_name: Silence
group: checks
ui:
icon: bell-off-outline
quick_access: true
# Commands can be grouped in the UI
command_groups:
checks:
display_name: Checks
Read the details about the manifest file below or jump directly to adding the UCM script file.
Device Icon​
icon
section defines which image will be used for your device.
icon: enapter-gauge
Use Enapter branded icons for the most commonly used energy devices from the Enapter icon set. Prepend an icon name with enapter-
.
icon: alarm-light-outline
Alternatively you can use the community list of icons.
Communication Module​
communication_module
section describes a UCMs which should be used for your device integration. For our example we are using the ENP-RS485 communication module which has built-in Modbus RTU support.
One blueprint can also be backed by several UCMs in complex scenarios, but this is out of the scope of this tutorial.
communication_module:
product: ENP-RS485
lua_file: ucm.lua
product
is a product code of Enapter UCM. The full list of UCM products is available in the handbook.
communication_module:
product: ENP-RS485
lua_file: ucm.lua
lua_file
references the UCM Lua script which is uploaded to the related UCM once the blueprint is assigned to it. The file should be located in the same directory as the manifest file.
More information about communication module configuration can be found in the communication modules reference.
Properties​
Properties are device metadata which unlike sensor data (telemetry) does not change during device normal operation. It could be firmware version, device model, serial number, and similar. Property reference names must be used for sending property values from the UCM Lua script.
serial_number:
type: string
display_name: Serial Number
Property name used for referencing it from Lua implementation and other parts of the blueprint. It must be unique within a single blueprint.
serial_number:
type: string
display_name: Serial Number
Property value type, one of: boolean
, float
, integer
, or string
. The same type must be used for the value of this property in the Lua script.
serial_number:
type: string
display_name: Serial Number
display_name
will be shown as a property name in a user interface.
More information about properties can be found in the properties reference.
Telemetry​
The telemetry
section defines telemetry attributes supported by the device. Usually, it represents sensor readings and internal device state. Every attribute must be sent from the Lua script under the same name as in the manifest.
h2_concentration:
type: float
unit: "%LEL"
display_name: H2 Concentration
Telemetry attribute name used for referencing this telemetry attribute from Lua implementation and other parts of the blueprint. It must be unique within a single blueprint.
h2_concentration:
type: float
unit: "%LEL"
display_name: H2 Concentration
Attribute value type, one of: boolean
, float
, integer
, or string
. The same type must be used for the value of this attribute in the Lua script.
h2_concentration:
type: float
unit: "%LEL"
display_name: H2 Concentration
Optional unit of measurement, only applicable to a numeric attribute type.
h2_concentration:
type: float
unit: "%LEL"
display_name: H2 Concentration
display_name
will be shown as an attribute name in a user interface.
More information about telemetry attributes can be found in the telemetry reference.
Alerts​
Alerts are faulty device states which device sometimes raises during the operation.
Usually, it gets acquired directly from the device over its communication protocol (e.g. by reading it from a Modbus registers similar to normal telemetry). Or it can be calculated in the Lua script as a reaction on some telemetry values (e.g. if H2 concentration is higher than 1%).
Alerts are defined in the alerts
manifest section.
h2_high:
severity: error
display_name: High H2 Concentration
Alert name. Lua script must send this name in the alerts
field inside telemetry data if the device has this alert active at the moment.
h2_high:
severity: error
display_name: High H2 Concentration
Alert severity is used in notification rules, should be one of: info
, warning
, error
.
h2_high:
severity: error
display_name: High H2 Concentration
display_name
will be shown as an alert name in a user interface.
If device is sending undeclared alert (not defined in the manifest) in alerts
telemetry field, it will be considered as alert of severity error
with display_name
equal to alert reference name.
More information about alerts can be found in the alerts reference.
Commands​
commands
section defines what commands are supported by the device. Every command defined in the manifest must be implemented in the Lua script under the same name as in the manifest.
beep:
display_name: Beep
ui:
icon: alarm-light-outline
quick_access: true
Command name is used for referencing it from Lua implementation and other parts of the blueprint. It must be unique within a single blueprint.
beep:
display_name: Beep
ui:
icon: alarm-light-outline
quick_access: true
display_name
will be shown as a command name in a user interface.
beep:
display_name: Beep
ui:
icon: alarm-light-outline
quick_access: true
The icon
which will be used for the command in a user interface. Must be one from the full list of available icons.
beep:
display_name: Beep
ui:
icon: alarm-light-outline
quick_access: true
quick_access
adds command into quick access list in Enapter mobile app.
Use the remote control button on the device screen in Enapter mobile application to trigger a quick access list.
Blueprint commands also support confirmations and passing user-defined arguments, read more about it in the commands reference.
UCM Script​
UCM script implements device interface declared in the manifest file using Lua programming language. Device communication APIs exposed to Lua depend on a UCM model and communication standard it supports. For this example we skip everything related to communication with the connected device and just return sample properties and telemetry.
- Web IDE
- CLI
Substitute the contents of the ucm.lua
file with the code from the listing below.
Create a file from the listing below in the same directory as your manifest.yml
under the ucm.lua
name (as it is in the manifest).
-- Obtain device properties and send it to Enapter Cloud
function send_properties()
enapter.send_properties({
-- We could have called Modbus API here, but use
-- constant value for the example simplicity
serial_number = "AC001215"
})
end
-- Store active alerts as a global array
-- Empty array means there are no alerts by default
active_alerts = {}
-- Obtain device telemetry attributes and send it to Enapter Cloud
function send_telemetry()
enapter.send_telemetry({
-- Again, we use constant value for simplicity
h2_concentration = 0.01,
-- Pass active_alerts into telemetry
alerts = active_alerts
})
end
-- "beep" command implementation
function beep_command(ctx, args)
-- Add h2_high to active alerts array
active_alerts = {"h2_high"}
-- Send some reply back to the user as a text message
return "Sound alarm started"
end
-- "silence" command implementation
function silence_command(ctx, args)
-- Clean active alerts array
active_alerts = {}
return "Sound alarm stopped"
end
-- Register periodic function, will send properties every 30 seconds
scheduler.add(30000, send_properties)
-- Register periodic function, will send telemetry every 1 second
scheduler.add(1000, send_telemetry)
-- Register "beep" and "silence" commands, the function passed as a second argument
-- will be executed every time user starts the command from UI
enapter.register_command_handler("beep", beep_command)
enapter.register_command_handler("silence", silence_command)
Sending Properties and Telemetry​
The system uses a few API calls to send device properties and telemetry.
scheduler.add(1000, send_telemetry)
Registers a periodic function execution. send_telemetry
function will be called every 1000
milliseconds.
enapter.send_properties(data)
enapter.send_telemetry(data)
Sends device properties and telemetry, data
is a Lua table (key-value pairs).
Sending Alerts​
When a connected device has some active alert, UCM shall send its identifier in alerts
telemetry attribute along with other attributes.
If you are using alerts mechanism in your blueprint, always send alerts
attribute in telemetry:
- Keep sending alert name in the
alerts
array until the alert is resolved. - If there are no active alerts, keep sending an empty array.
enapter.send_telemetry({
h2_concentration = 0.02,
alerts = {"h2_high"}
})
alerts
attribute holds Lua array with alert identifiers that are active at the moment.
Executing Commands​
To implement commands described in the manifest one has to define the handler function for every command with a call to register_command_handler
.
function beep_command(ctx, args)
-- command execution code
end
Command execution function must accept two parameters. ctx
is a command execution context. args
holds command arguments (passed from user) as a Lua table.
enapter.register_command_handler(
"beep",
beep_command
)
Registers handler for the command named beep
. The name must be equal to the command reference name from the manifest. The function beep_command
passed as a second argument will be executed every time user starts the command from a web, mobile, or an API.
Now we have our blueprint prepared for being uploaded to the UCM.