Driver installation on the Remote
Starting with firmware v1.9.0, custom installation drivers can be installed on the Remote.
‼️ Custom integration drivers is a developer preview and not all features are implemented yet. See missing features.
Installation archive format
Integration driver archive requirements:
- TAR GZip archive (either .tgz or .tar.gz file suffix) with a maximum size of 100 MB.
- In the root of the archive, there must be a
driver.jsonmetadata file describing the custom integration driver. - The driver binary must be in the
./binsubdirectory.- Either a statically linked aarch64 executable named
driver. - Or a Node.js file named
driver.js.
- Either a statically linked aarch64 executable named
- All application files must be in one of the following subdirectories, other locations are not accessible at runtime:
./bin: application binary folder../config: optional configuration data. Path is accessible withUC_CONFIG_HOMEenvironment variable../data: optional application data. Path is accessible withUC_DATA_HOMEenvironment variable.
Metadata file
The driver.json metadata file in the root of the archive describes the integration driver.
‼️ The data schema is not yet included in the Core-API, the full object is shown below.
It is a reduced version of the IntegrationDriver object, without driver connection fields like driver_url, token etc.
{
"driver_id": "foobar",
"version": "1.0.0",
"min_core_api": "0.20.0",
"name": {
"en": "Foobar special"
},
"icon": "custom:foobar.png",
"description": {
"en": "Control Foobar products",
"de": "Steuere Foobar Produkte"
},
"features": [
{
"name": "auth.external_tokens",
"required": true
}
],
"developer": {
"name": "Unfolded Circle ApS",
"email": "hello@unfoldedcircle.com",
"url": "https://www.unfoldedcircle.com"
},
"home_page": "https://www.unfoldedcircle.com",
"setup_data_schema": {
"title": {
"en": "Integration setup",
"de": "Integrationssetup"
},
"settings": [
{
"id": "info",
"label": {
"en": "Setup process",
"de": "Setup Fortschritt"
},
"field": {
"label": {
"value": {
"en": "The integration will discover your Foobar products on your network. This process is automatic and can take a few minutes.",
"de": "Diese Integration wird Foobar Produkte im Netzwerk finden. Dies ist ein Automatischer Prozess der ein paar Minuten dauern kann."
}
}
}
}
]
},
"release_date": "2024-07-21"
}
driver_idmust be at least 5 characters long and start with a lower-case letter.- Only lower-case letters, digits and
-,_are allowed. - Common system identifiers are not allowed and will be rejected (e.g.
daemon,backup, etc.). - The
uc_prefix should not be used. This is reserved for pre-installed integrations. Any custom integrations using this prefix might get removed during a future firmware update.
- Only lower-case letters, digits and
- Multiple language fields are not required, but recommended.
- If only a single language is provided, it should use the
enkey.
- If only a single language is provided, it should use the
setup_data_schemais optional if the driver provides a setup flow.- This is the first screen of the setup, all further screens are dynamically provided by the driver.
- ⚠️
min_core_apiis not yet used.
Driver icon
A driver icon can either use a predefined icon or a custom icon. Predefined icons are prefixed with uc:, followed by
the icon identifier in lowercase.
A custom driver icon can be installed automatically as custom icon resource.
- In
driver.jsonset the icon field tocustom:$ICON_FILENAME - Include
$ICON_FILENAMEin the root of the archive.
Example driver.json (other fields omitted for simplicity):
{
"icon": "custom:foobar.png"
}
The icon file called foobar.png must be added to the root of the archive.
Icons must be of size 90x90 pixels and either in PNG or JPG format. Maximum size is 32 KB.
Installation archive example
Example of a Node.js based integration driver archive (contents of bin/node_modules are not shown for a clearer overview):
.
├── bin
│ ├── driver.js
│ ├── node_modules
│ │ ├── ...
│ │ ├── foobar
│ │ ├── uc-integration-api
│ │ ├── ws
│ │ └── ...
│ └── foobar.js
├── config
├── data
├── driver.json
└── foobar.png
- If the driver doesn't require any data or configuration files, the
./dataand./configdirectories can be omitted from the archive.- During the installation, the data and config directories are automatically created and can be accessed by the driver at runtime, no matter if they were provided in the installation archive or not.
- The
driver.jsonfile in the root folder is automatically copied to the./binfolder during installation if it is missing.- If the driver requires a different
driver.jsonfile, simply include a file in the./binfolder.
The one in the root folder won't be copied anymore.
- If the driver requires a different
Restrictions
- Maximum 10 custom integrations can be installed.
- Only Node.js is supported besides a statically linked binary. Other runtimes are not supported at the moment.
- Python integrations must pack the Python runtime into the archive.
- The integration driver runs in a sandbox. Access to devices and the filesystem is restricted.
- No symlinks are allowed. They are automatically removed during the installation.
- Executable files are only allowed in the
./bindirectory.- No other tools are provided in the runtime environment. E.g. there is no shell available and no other tools
like
cpormv.
- No other tools are provided in the runtime environment. E.g. there is no shell available and no other tools
like
Missing features
- Resource restrictions for integration drivers: limit maximum amount of memory and CPU usage.
-
Update an installed integrations.
- Workaround: remove and re-install.
-
Resource usage: provide memory and CPU usage per integration.
- Only the overall resource usage can be monitored with
GET /api/pub/status.
- Only the overall resource usage can be monitored with
Runtime environment
The driver runs in a sandbox with limited access to the host system.
- Environment variables for the Websocket integration-API server:
UC_INTEGRATION_INTERFACE: network interface to bind to.UC_INTEGRATION_HTTP_PORT: port number.
- The working directory is set to the binary directory.
- The binary directory is read-only.
- Node.js version: v20.16 (firmware release 1.9.3 and newer).
- There are no pre-installed node modules.
- An integration driver must include all required modules in the installation archive, including
uc-integration-api(if used).
- File access with relative paths between
bin,config, anddatais not possible.- Environment variables must be used to retrieve the full path of these directories.
UC_CONFIG_HOMEandHOME: configuration directory.UC_DATA_HOME: data directory.
- The returned path may not be stored, it may change with future software updates.
- Environment variables must be used to retrieve the full path of these directories.
- Only the
$UC_CONFIG_HOMEand$UC_DATA_HOMEdirectories are writeable and persisted between restarts.- The
/tmpdirectory can be used for small temporary files.- This is a RAM file system and limited by the available free memory.
- Temporary files are not persisted between restarts.
- The
- A dynamic user and group is allocated when the driver is started.
- The user and group IDs may change between driver restarts.
- Write access to the
$UC_CONFIG_HOME,$UC_DATA_HOMEand/tmpdirectories is ensured.
⚠️ CPU and memory restrictions are not yet in place but will be enforced in a future firmware update!
- A single integration driver should not use more than 100 MB of memory.
TODO more details about sandbox environment
Network
The integration runs on the same network environment as the Remote. There is no network bridge or firewall.
- Binding ports below 1024 is not possible.
⚠️ A port-binding filter might be added in the future to prevent integrations to steal away ports of other integrations. The port range 8000-9200 and port 13333 are not allowed to be used!
Native integration drivers
TODO sysroot, available dynamic libraries
The Remote Two Cross Compile Toolchain can be used to cross-compile a native binary for the Remote.
- The driver must be compiled as a static binary for libc.
- Most dynamic libraries in the cross-compile sysroot are NOT available in the custom integration runtime environment!
Install driver
curl --location 'http://$IP/api/intg/install' \
--user 'web-configurator:$PIN' \
--form 'file=@"custom-intg.tar.gz"'
See REST Core API for more details.
Delete driver
To delete a custom integration, use the regular endpoints to delete an integration instance and driver. These are the same endpoints as for an external network integration driver:
- Delete integration instance
DELETE /api/intg/instances/:intgId. - Delete driver and installation files:
DELETE /api/intg/drivers/:driverId.
See REST Core API for more details.
The instance and driver can also be deleted in the web-configurator.
Log access
Output to stdout and stderr are automatically stored with a timestamp and accessible as the other system logs:
- Get log services:
GET /api/system/logs/services. - Query logs:
GET /api/system/logs?....
See REST Core API for more details.
Log files can also be downloaded in the web-configurator: Settings, Development: Logs
Web-app log viewer
⚠️ Available from firmware release v2.1.0
The Logdy web application is installed on the device to monitor integration driver log events in near real time.
- URL:
http://$IP/log/ - This function is deactivated by default and the endpoint returns 503.
- The log viewer must be started using the REST Core API
with the
/api/system/logs/webendpoint:GETrequest returns the current state.PUTrequest allows to start, stop or to permanently enable the log app. A password can be set to restrict access to the web app.
- Available logs:
- Remote core service
- All pre-installed and custom integrations
- Custom remote-ui service if installed
- ❗️The log processing and logdy daemon require around 170 MB of the custom integration memory pool.
Using curl to start the app:
curl --request PUT 'http://$IP/api/system/logs/web' \
--header 'Content-Type: application/json' \
--user web-configurator:$PIN \
--data '{"enabled": true}'
Start and permanently enable the app, even after a reboot:
curl --request PUT 'http://$IP/api/system/logs/web' \
--header 'Content-Type: application/json' \
--user web-configurator:$PIN \
--data '{"enabled": true; "autostart": true}'
Recommendations
- Node.js should be preferred for writing integration drivers.
- If using Python:
- Use PyInstaller to create a binary distribution.
- Use the default one-folder bundle containing an executable (
--onedir). Avoid the one-file bundled executable, since it will easily use an additional 100 MB of memory! - See Android TV integration or Apple TV integration as an example.
- An integration driver should be limited to one process and not launch other processes.
- Use ports above 10000 if the integration needs to create an IPv4 or IPv6 server socket (besides the required WebSocket server for the integration-API).
- Preserve resources, use as little memory and CPU as possible.
- Use stdout & stderr for logging.
- Only use
/tmpfor small, temporary files since it is a RAM file system.
Example integrations
The following Python based integration drivers create a custom integration installation archive during build with a GitHub action: