Writing Your First Lua Driver
Looking for a step-by-step, real-world tutorial? Visit the SmartThings Community tutorials!
Startup
The Lua sandbox will initially start the file init.lua
from the base
directory of your src
folder. All the other folders and files in the
src
directory will be collected, added to the package, and sent to the
hub on package install.
Adding Required Libraries
Every init.lua
file should begin with require
statements to import
the libraries the driver will use.
local capabilities = require "st.capabilities"
local Driver = require "st.driver"
These two statements will load the SmartThings-provided libraries for capability support and for driver utility functions. In unison, they provide the core functionality all drivers need.
Basic Driver Initialization
local example_driver = Driver("example driver", {
discovery = discovery.handle_discovery,
lifecycle_handlers = {
added = device_added,
init = device_init,
removed = device_removed
},
capability_handlers = {
[capabilities.switch.ID] = {
[capabilities.switch.commands.on.NAME] = command_handlers.switch_on,
[capabilities.switch.commands.off.NAME] = command_handlers.switch_off,
},
}
})
The code above creates a driver object called example_driver
. Upon
initialization, it passes a name and a template.
Capabilities
As part of driver initialization, a Lua table is populated with the SmartThings Capabilities and their corresponding commands and the command handlers to call when a command is sent to a device.
Through properly implemented command handlers, this structure is all that is needed to allow SmartThings commands to be received by a driver, routed to a command handler, and then to the appropriate device communication to control a device. The device control will differ based upon the type of device being controlled.
local function handle_on(driver, device, command)
-- Send command to device
end
local function handle_off(driver, device, command)
-- Send command to device
end
All of this handles how SmartThings can control a device. Now let's look at how to report a device's status back to SmartThings.
A different API is required to generate device statuses (also known as attributes). Device attributes use the Capability library.
In the example below an attribute event is generated from the device
object, resulting in a switch.on
status for the device.
device:emit_event(capabilities.switch.switch.on())
Getting raw data from devices will differ based on the type of device. For Matter, ZigBee, and Z-Wave devices, libraries provided by SmartThings will facilitate receiving these messages. For LAN devices, a socket will be necessary to communicate with the device.
For more information regarding Capabilities, visit the Capabilities documentation.
Running the Driver
The driver library has a run function which never returns and runs the driver in a pseudo event-driven model. Where the handlers connected in prior lines get called when events are sent to the driver for handling. Any code after the run call to the driver library will not be executed since run() never returns. Once run() is called, your code is only called when events occur.
example_driver:run()
Putting It All Together
Here's an example of a completed basic driver:
-- init.lua
local log = require "log"
local capabilities = require "st.capabilities"
local Driver = require "st.driver"
local function handle_on(driver, device, command)
log.info("Send on command to device")
-- for real devices you should make a request to a device and wait for the
-- response confirming the device was switched on before emitting this
device:emit_event(capabilities.switch.switch.on())
end
local function handle_off(driver, device, command)
log.info("Send off command to device")
-- for real devices you should make a request to a device and wait for the
-- response confirming the device was switched off before emitting this
device:emit_event(capabilities.switch.switch.off())
end
-- Driver library initialization
local example_driver =
Driver("example_driver",
{
capability_handlers = {
[capabilities.switch.ID] =
{
[capabilities.switch.commands.on.NAME] = handle_on,
[capabilities.switch.commands.off.NAME] = handle_off
}
}
}
)
-- Put other setup code here
example_driver:run()
If you intend to seek Works with SmartThings certification for your custom Edge Driver and device, ensure your code adheres to the Code Formatting and Submission Criteria.