Hi - I’ve been writing some LAN-based edge drivers for the new Edge platform (started pre-beta) and wanted to share some personal experiences in hopes it may help others who are just getting started. This is targeted to developers, as opposed to users.
This is not meant to replace all the great documentation and posts from the SmartThings team, but rather just to give more of a community member perspective. I apologize up front if any my thoughts or recommendations are erroneous. This is a rapidly evolving platform, so I’ll make updates as needed to keep this useful and accurate. And I hope that others can contribute to this topic as well.
I don’t profess to be an expert by any means, but am happy to answer any questions that I can.
Mine has been super-simple & cheap, but thoroughly sufficient for LAN-based device development: a Raspberry Pi 4b with 4GB of RAM running Raspberry Pi OS (Debian Linux)! I’d definitely recommend Linux over Windows.
I don’t use an IDE for Lua, so can’t recommend anything in particular there. Unfortunately there is no debugger available for Lua so plan on liberal use of log and print messages. (See comments regarding Logging below)
It’s a simple enough language to learn. Key concepts to fully pay attention to because you’ll use them a lot: require, tables (big topic in Lua), nil, forward referencing. Also understand the coroutine concept because it’s central to how your Lua code will be executed, however much of this will be managed by Edge (see below).
Install version 5.3. There are more recent versions available, but there have been problems with those during alpha.
Unfortunately, the Lua website charges money for the latest programming guide, but you can read the free one available on their website from the original release. And the language reference is also available online for free. (I’ve suggested to the SmartThings team that they should be able to get us a discount code with all the developers they are driving to Lua now!)
Also install Luarocks, which lets you get additionally available Lua libraries you may want to use, e.g. sockets, dkjson, xml2lua, etc. Stick with the libraries you know are supported on the hub per the documentation. Keep in mind that all Lua libraries your driver will use are already loaded and available on the hub. Installing them on your development machine is only needed for off-hub testing.
This will need to be defined to ensure you are picking up the right libraries as you test on your development machine. The syntax and way it’s used to search is not typical Linux, so be careful here.
The Edge platform
The key concept you’ll have to wrap your head around is that this is NOT a multi-threaded processing environment as far as your Driver is concerned. (Lua was designed as an embedded scripting language most typically called by C programs.) The Lua coroutine concept is one where code is synchronously executed in chunks with a yield and resume mechanism. On the hub, the Edge platform manages that mechanism. The result is that your driver will be primarily composed of lifecycle handlers, channel handlers, and callback routines that are invoked by Edge. It forces you to re-think how you would handle communications tasks with the devices that you might ordinarily implement in multiple threads.
Development and Testing
I’d highly recommend writing as much of your driver code as you can ‘off-hub’ and testing it that way - especially as you are just getting up to speed with the Lua syntax. You’ll have to temporarily restructure your code differently from how it will be in your final on-hub Edge driver, but it will be MUCH easier to rapidly find errors, fix, and retest. Once you start moving your Driver to the hub, error messages can be quite obtuse and if you are using multiple layers of require modules, even pinpointing the line number of the error gets very difficult if not impossible (hopefully this will be improved in the future). See my tip below.
Testing / Errors Tip
EDIT: the following is for when you are testing your driver ON the hub:
As mentioned above, if you are getting some kind of runtime or fatal error as seen in your log messages while you are testing your driver, sometimes the messages aren’t very helpful - they can be difficult to decipher, or the exact line number within the offending module is not shown. In those cases I will temporarily comment out the Edge-specific require statements in the module where you think the error is coming from, and then in a Lua interactive session on your development machine, require the module in, and then you can get a more helpful and pinpointed error message. I’ve found this tip can save an enormous amount of time hunting for simple Lua syntax errors.
Once you are running your code on the hub, this will be the only way to see your driver’s activity. So you will make liberal use of log messages within your Driver to track what’s going on. And because of the various handlers and callbacks that are being invoked in a non-sequential manner, you’ll find the need to include sufficient information in each of your log messages that identifies it to a specific function and device. Otherwise, you won’t be able to logically link your log messages together for a particular device or routine because they will appear as almost a random mishmash of messages!
Logging output can get rather noisey because there is currently no way to suppress log messages coming from Edge itself. There is no one message type used, so filtering won’t help.
There is an irritating problem with running the cli logger on Windows (which is one of the reasons I prefer Linux). Scrolling back through prior messages while the logger is still running is a problem because it keeps wanting to snap back to the latest one as soon as you let go of the mouse button.
Loading Drivers to the Hub
EDIT: I’ve removed my comments in this section; please see Patrick’s posts on this topic below.
The more I learn, the more I realize I have much learn
All the work I’ve done is with LAN devices, so there are a couple things to note on this topic:
Your driver cannot currently request a specific IP port number on the hub. Ports are randomly assigned. Hopefully this limitation will be addressed in the future, but unfortunately for now, this will preclude drivers for devices like Shelly’s wifi motion sensor that allow you to configure to send motion updates to a specific IP and port.
When initially coding and testing before moving to the hub, you can use the Lua socket library for all your LAN communications needs. This gets replaced by the cosock library when running on the hub, with no change needed to your code except for the require statements.
Device discovery is an important function of any LAN-based driver. Examples are forthcoming (see my UPnP comment below). Once you discover the device, you can implement any protocol you need (TCP, HTTP / RESTful API, SOAP, etc) to interact with your device.
You’ll need to figure out how you are going to address maintaining the online/offline status of your device, either through polling or through periodic device ‘I’m alive’ messages. How often this is needed will obviously be based on various factors.
Finally, a shameless plug - I have a full-function UPnP control point Edge driver I will soon be making available to the community with the intention of making it easy to create drivers using the complete UPnP architecture standard. (This also addresses the device online/offline monitoring)