Thank you for your feedback. It’s very useful for us to get it during developing new API.
Using same Lua API and same plugins were main requirements for new plugins engine. We have wide range of smart controllers on the market and a few new controllers will be released soon( You can find our new controllers on CES 2020 reviews ). Ezlo Atom, PlugHub, VeraEdge, Ezlo Plus have the same Lua API. Main idea is integrate device once and deploy on all controllers. Linux based controllers support a bit more Lua modules as atom but Core, Z-Wave, Storage, Timers modules are the same. Base functionality and API architecture are limited by atom hardware possibility. It means for atom: providing the same functionality as Linux controller have but It’s also share all memory and speed improvements with Linux controllers.
As I said in pre-Alpha/Beta topic: we are not ready to share our API with community because we don’t have external development tools and well organized public documentation. But It’s good policy for product to share functionality/API as soon as possible with community and clients and now you could read part of our internal documentation.
@rigpapa
There’s little description of plugin structure and the theory of the plugin architecture to guide implementation. This is largely reference documentation for individual APIs, and while that provides some information, it requires us to “read your mind” about how you are thinking plugins are built, packaged, and interact with the system. We don’t know when they are loaded, or how they are initialized, for example.
Yes. It’s internal documentation. We will work on better way of API representation.
In a few words:
- all plugin information described in config.json file( you can find examples of this file on your controllers with new firmware: /opt/firmware/plugins );
- each plugin has own “virtual” space and doesn’t have access to space of other plugins;
- each script has 3 minute execution time limit;
- Storage module should be used for saving states between scripts execution;
- Timers module should be used for “endless” checking;
- plugins implement all business logic, modules just provide access to specific functionality;
- UI displays devices from Core module only;
My gut reaction to having subscribed event notifications dispatched to scripts, which are presumably separate Lua files, rather than functions within a Lua script/file directly–this makes me very uneasy. It seems like a potential mess for systems that will need to respond to a large number of events/event types. A lot of that depends also on…
Atom cannot run a few Lua scripts in the same moment of time. Each script should be finished and don’t take a lot of execution time. event/subscription architecture is main possible option for now. But it also gives benefits : less reaction time and more time and RAM memory for main functionality of firmware. Yes, it also forces you to keep clear the structure of the plugin and split it into “modules”.
What is the Lua environment in which the scripts run? Is there one environment for the entire plugin? One per script? One per instance? Is/are they consistent/persistent across invocations of scripts? If one script file declares a Lua global, is it visible to another script file? If you’re imagining “storage” is the way to persist necessary data between calls in a running plugin, that a substantially higher load on the plugin and whatever backs that storage than the current in-memory model of plugin runtime state. I don’t see clearly how you are diffentiating “runtime” state from long-term (across reload/reboot) persistence, and the docs don’t say.
One per script. We only have persist plugins storage. I think, we will add API for temporary/runtime storage in the future.
Your network module…
Yes. Our network module. It’s prototype. We don’t have any plugin which requires this API. Only Berkeley sockets are available. We will support other protocols in the future.
The network.connect() docs don’t describe how to ask for sync or async, it just describes the possibility.
connection will be established just after call but sending/receiving data should be done via “events”.
Since the network module seems to have internal buffering, it would be nice to have a call to flush it (dump the buffer contents without having to read it). What’s the size of the buffer? If the plugin has a bug that causes it to stop reading on a connection to a frequently-transmitting endpoint, will the buffer grow until it consumes all system memory?
Plugin will receive event with received new data. if plugin doesn’t save it : data would be lost.
What version of Lua?
5.3.5
Why is it (again) necessary to restart the entire firmware? Can not the initialization script for a plugin just be called on all demand? Why not?
It’s possible but not for custom plugins which were installed via SSH.
How are UIs defined for plugins?
Part of that is missed now and we are working on it. UI displays devices and items from core module. List of supported items will be described in the future.
What device types are defined in the system?
New plugins use almost the same categories and subcategories of devices as Luup. It will be shared in the future.
How do plugins define new device types? Can they? Or are plugins expected to accrete instances of predefined types into a functional representation of the new device they are implementing? If that’s the case, how to users see and manipulate specific settings that may apply to the gateway or its devices?
Plugin can use custom device type for own devices but if UI doesn’t support it : it can be displayed wrong.
Specific gateway/device preferences will be added in the future.
Why are capabilities like lock codes and lock schedules in the Zwave module?
Core module - protocol independent device/items model. UI uses this abstraction layer for displaying available devices.
Z-Wave module - protocol specific API for working with Z-Wave stack directly.
Each of this layers doesn’t know each other. It’s possible to implement own Z-Wave plugin instead of our. Or work with Z-Wave specific API from your plugin and our plugin will receive all new changes.
Can I subscribe to a device or item? How does a plugin respond to changes in its devices or other devices in the system?
We have one main request for changing value of item from UI: hub.item.value.set. Author of plugin should define own script for this request in config.json file. After that all new values for his items will be sent to this script.
There aren’t really any detailed descriptions of the event model or what’s passed to the script for context for each of the different types of events (except a brush for network)–that’s important to judge the usability of an API that relies heavily on event notifications.
We will improve documentation. Main events were described. Core module does not have Lua events now but It can be easily added.
I’m a bit concerned about all APIs throwing errors rather than returning error codes
Thank you for your recommendation we will think about described approach. Yes, now we use string errors and calculate “Lua call stack” for each error.
Does a non-interval timer “exist” after it fires, or is it necessary to call cancel() on such a timer to destroy its instance? If so, why? And docs be clear about this as a requirement, otherwise you will have plugins leaking memory due to completed but undisposed timers.
You can create timers as much as you want. exist and cancel methods help to build different business logic on timers without saving special data in storage.
Timer IDs should be strings, not numbers. In my experience, timers tend to be task-based, so it’s beneficial to sanity to be able to identify them as “background-refresh” or “dev395query”. If you’re trying to assign numbers, you quickly lose track of what the numbers mean, particularly if you are creating multiple timers for tasks for multiple devices.
Timer id - is string.
The storage module description… I can’t make out what it means.
key / value storage. Each plugin has own storage space.
Can plugins communicate with one-another? If so, how?
No. But we think about it.
@therealdb
Since we’re at it, I’d really like to have an emulator rubbing on Linux (and so on Windows subsystem for Linux) to develop. Right now I have to use openluup on WSL,
Sorry, we don’t have it now.