|  Developer
Updated on November 1, 2022

Plugin File Structure

Minimal File Structure

Every plugin uploaded must be in a `tar.gz` archive with a plugin prefix followed by your plugin name. The prefix is a must and is used by EZLogic to internally identify your plugin, but will not be visible to end-users. Only the plugin name is shown to users in EZLogic.

Contained in each .tar.gz is a `config.json` file, `interface.json` file, and a `scripts` folder.

The minimal file structure for a plugin is the following:

				
					```
plugin_prefix.plugin_name.tar.gz/
  config.json
  interface.json
  scripts/
    startup.lua
    teardown.lua

```
				
			

We’ll now go into details for each of these files:

config.json

This file is where you define the internal settings for the plugin. Here’s a minimal ``:

				
					```json
{
  "id": "prefix.ezlo.minimal",
  "version": "1.0.0",
  "meta": {
    "name": {
      "text": "Minimal Test Plugin"
    },
    "description": {
      "text": "A plugin with the bare minimal configs, and no functionality, used purely for exposition."
    },
    "author": {
      "text": "Ezlo Innovation"
    },
    "type": "node",
    "language": "lua",
    "placement": {
        "static": true,
        "custom": true
    }
  },
  "type": "gateway",
  "dependencies": {
    "firmware": "2.0",
    "addons": [
      {
        "id": "lua",
        "version": "1.0"
      }
    ]
  },
  "permissions": [
    "core",
    "logging",
    "storage"
  ],
  "executionPolicy": "restoreLastScriptState",
  "startup": "scripts/startup",
  "teardown": "scripts/teardown",
  "gateway": {
    "name": "ezlo.minimal",
    "label": "Minimal test plugin",
    "setItemValueCommand": "HUB:prefix.ezlo.minimal/scripts/set_item_value",
    "setSettingValueCommand": "HUB:prefix.ezlo.minimal/scripts/set_setting_value",
    "forceRemoveDeviceCommand": "HUB:prefix.ezlo.minimal/scripts/delete_device"
  }
}
```
				
			

Most of these are simply sane defaults. Here are the most noteworthy ones:

  • id: This is a unique identifier for the plugin. It consists of a prefix and a name. If you’re developing a plugin for Ezlo Innovations, the prefix should be `ezlo`. If not, you can grab a prefix for yourself in the ‘Plugins -> Plugin Settings’ tab on ezlogic. It’ll be used throughout the plugin’s code, and should be unique for your plugin.
  • version: This is the version of the plugin. It is mostly decided by you, but it should be $\ge$ 1.0.0
  • meta: Holds some data about the plugin, such as name, description, and author. These will be displayed in the UI to the user.
  • permissions: This specifies the modules that the plugin will access. You will NOT be able to `require` a module without specifying it here.
  • startup: This file will execute when first installing the plugin. It should contain some initial setup.
  • teardown: This file will execute when uninstalling or upgrading the plugin. It should contain some cleanup code.
  • Gateway: The scripts specified here are executed when certain actions or events happen, such as an item or setting being changed, or a device being removed. The full list of available commands are specified in the API Docs.
interface.json

In this script, you specify details about the user interface. Here’s an example:

				
					```json
{
  "configuration":{
    "type":"static",
    "script":"HUB:prefix.ezlo.minimal/scripts/configure_new",
    "inputs":[
      {
        "name":"String",
        "description":"String input",
        "field":"input",
        "required":true,
        "type":"string"
      },
      {
        "name":"Integer",
        "description":"Integer input",
        "field":"input",
        "required":false,
        "type":"int"
      }
    ]
  },
"contents":[
		{
			"id": "my_action_id",
			"ui": {
				"name": "plugin call",
				"description": "Performs some action to the device",
				"placement": "plugin"
			},
			"type": "setter-api",
			"apply": [
				{
					"element": "item",
					"when": {
						"property": "name",
						"operator": "=",
						"value": "my_action"
					},
					"to_api": "hub.item.value.set"
				}
			],
			"inputs":[
				{
					"name":"First Input",
					"type": "string",
					"required": true,
					"description": "A string input."
				},
				{
					"name":"Second Input",
					"type": "number",
					"required": false,
					"description": "A numerical input."
				}
			]
		}
	]
}

```
				
			
  • configuration.script: This file will execute when the user creates a new configuration. When it executes, it’ll receive all of the inputs specified, which will be present as fields in the “`…`” lua variable.
  • configuration.inputs: A list of all of the inputs the configuration should take. This includes the UI name and description, type, if it is required or not, and the field that will be used when the configuration script is called.
scripts folder

This folder will contain the code for your plugin. It may contain any amount of (nested) folders and lua files to be executed. Any file can be accessed/executed using the command by any of the usual lua means (i.e. `require`, `loadfile`, etc).

For example, will import the file that is inside the scripts folder.

configure _new_lua

“HUB:prefix.minimal_plugin/scripts/configure_new.lua”

				
					local logging = require("logging")
local core = require("core")

logging.info('Configuring new device')

local args = ...

local str = args.string or ''
local num = args.numerical or 0

logging.debug('Params: '..str..', '..tostring(num))

local device_id = core.add_device{
		type = 'device',
		device_type_id = 'minimal_device',
		category = 'generic_io',
		subcategory = 'generic_io',
		battery_powered = false,
		gateway_id = core.get_gateway().id,
		name = 'Minimal Device',
}

local address_setting_id = core.add_setting{
	device_id = device_id,
	label = {
		text = "Server Address"
	},
	description = {
		text = "e.g. '127.0.0.1'"
	},
	value_type = "string",
	value = "127.0.0.1",
	status = "synced",
	has_setter = false,
}

local timeout_setting_id = core.add_setting{
	device_id = device_id,
	label = {
		text = "Timeout"
	},
	description = {
		text = "The maximum amount of time to wait for response before trying again (in seconds)"
	},
	value_type = "int",
	value = 10,
	status = "synced",
	has_setter = true,
}

local my_trigger = core.add_item{
	device_id = device_id,
	name = 'My Trigger',
	has_getter = true,
	has_setter = false,
	show = true,
	value_type = 'string',
	value = '',
}

local my_action = core.add_item{
	device_id = device_id,
	name = 'my_action',
	has_getter = false,
	has_setter = true,
	show = true,
	value_type = 'dictionary.string',
	value = {},
}

logging.info('Device created (id '..device_id..')')

core.send_ui_broadcast{
	status = 'success',
	message = 'Success',
}
				
			
delete_device.lua

“HUB:prefix.minimal_plugin/scripts/delete_device.lua”

				
					local logging = require("logging")
local core = require("logging")

core.send_ui_broadcast{
	status = 'success',
	message = 'A device was removed!',
}

logging.info('Device removed')
logging.debug(...)				
			
set_item_value.lua

“HUB:prefix.minimal_plugin/scripts/set_item_value.lua”

				
					local logging = require("logging")

local args = ...
local value = args.value

local input_string = value["First Input"] or ''
local input_numerical = value["Second Input"] or 0

logging.debug("First Input: "..input_string)
logging.debug("Second Input: "..tostring(input_numerical))				
			
set_setting_value.lua

“HUB:prefix.minimal_plugin/scripts/set_setting_value.lua”

				
					local logging = require("logging")

logging.info(‘Setting Changed’)
logging.debug(...)				
			
startup.lua

“HUB:prefix.minimal_plugin/scripts/startup.lua”

				
					local logging = require("logging")
--local core = require("core")
--local network = require("core")

logging.info("Minimal plugin starting...")

--core.send_ui_broadcast{
--  status = 'success',
--  message = 'Plugin Installed',
--}
--
--network.connect{
--  ip = '127.0.0.1',
--  port = '5000',
--  connection_type = 'TCP',
--}

logging.info("Minimal plugin started")				
			
teardown.lua

“HUB:prefix.minimal_plugin/scripts/teardown.lua”

				
					local logging = require("logging")
local core = require("logging")

core.send_ui_broadcast{
	status = 'success',
	message = 'A device was removed!',
}

logging.info('Device removed')
logging.debug(...)