
Security News
AI Has Taken Over Open Source
Vibe coding at scale is reshaping how packages are created, contributed, and selected across the software supply chain
@uboness/homebridge-mqtt
Advanced tools
This plugin enables the configuration of devices (HomeKit accessories) that are driven by MQTT topics.
baseTopic a "prefix" topic that will be prepended to all topics configured by the devices & templatesA device configuration is made out of:
id - This identifies the device in homebridge, so it needs to be unique within the Homebridge instance.type - The primary service typename - Serves as both the primary service name and the HomeKit accessory namedeviceName - If set, serves as the accessory name (used to separate the accessory and primary service names)topics - Defines the characteristics of the primary service and their associated (read/write) topics from/to which values will be read/writtenservices - An array of additional (secondary) services that are part of the HomeKit accessory.Here's an example of a simple lightbulb accessory that happens to have a built-in light sensor:
{
"id": "my-ceiling-light",
"type": "lightbulb",
"name": "My Ceiling Lamp",
"topics": {
"on": {
"get": "my-home/my-room/my-ceiling-light/on",
"set": "my-home/my-room/my-ceiling-light/on/set",
"converter": "boolean"
},
"brightness": {
"get": "my-home/my-room/my-ceiling-light/brightness",
"set": "my-home/my-room/my-ceiling-light/brightness/set"
}
},
"services": [
{
"type": "light-sensor",
"name": "Light Sensor",
"topics": {
"ambientLevel": {
"get": "my-home/my-room/my-ceiling-light/lux",
"set": "my-home/my-room/my-ceiling-light/lux/set"
}
}
}
]
}
Each service type defines a set of required characteristics which must be configured within the topics configuration
(e.g. A switch service must define the on characteristic).
There may also be optional characteristics that a service can support (e.g. all sensor services support the
statusLowBattery characteristic, though it's optional).
The HomeKit Accessory Protocol (HAP) Specification define the services supported in homekit and their required/optional characteristics. This plugin roughly follows these specifications with a few exceptions here and there.
In the example above, the configured MQTT topics hold the values that will eventually be read/published by
the relevant characteristics. MQTT values are strings and therefore we need a way to convert these values to the appropriate
type that is expected by each characteristic. This is the role of the converter. Each characteristic support a set of
converters that helps in converting different formats. For example, as in the above, by default, the on characteristic
expects 1 (for "on") and 0 (for "off") values. But if the MQTT value holds true and false instead, the boolean
converter will be able to handle it. What if the MQTT values is YES and NO? Well, there's a converter
for that too - a more generic one: converter: { "on": "YES", "off": "NO" } - in this case, we indicate which MQTT
values represent on and off.
Some systems (e.g. zigbee2mqtt) publish JSON values to their MQTT topic. To fetch a JSON value, you append
the "path" to the value within the JSON to the topic itself, using the $ sign as a separator. For example,
the following hum characteristic configuration reads/writes the hue values from/to JSON values in the MQTT topics:
{
"hue": {
"get": "zigbee2mqtt/Garage Led$color.hue", // reads from
"set": "zigbee2mqtt/Garage Led/set$color.hue" // publishes to
}
}
In the above, the topic is zigbee2mqtt/Garage Led holds a JSON object of the form:
{
//...
"color": {
"hue": 212,
"saturation": 10,
"x": 0.3131,
"y": 0.3232
}
//...
}
With the $ syntax, the plugin knows how to read it and extract the appropriate value.
Similarly, when publishing a value to the zigbee2mqtt/Garage Led/set topic, the plugin will create a JSON value of
the following form:
{ "color": { "hue": 200 }}
At the moment, not all HAP services are supported by this plugins, but certainly a big chunk of the most common ones. More services/characteristics may be added in the future.
There are many service types to choose from and many characteristic types as well, all of which are
Here's an example of the plugin configuration:
{
"name": "Mqtt",
"platform": "Mqtt",
"logger": {
"trace": false // change to 'true' to output extensive logs (only works when HB runs in debug mode)
},
"servers": [
{
"id": "knx",
"host": "mqtt.local",
"port": 1883,
"auth": { // optional, remove if your MQTT broker doesn't require authentication
"username": "<username>",
"password": "<password>"
},
"baseTopic": "knx",
"templates": [
// all the KNX device templates are configued here (see below)
],
"devices": [
// all the KNX devices are configured here
]
},
{
"id": "zigbee2mqtt",
"host": "mqtt.local",
"port": 1883,
"auth": { // optional, remove if your MQTT broker doesn't require authentication
"username": "<username>",
"password": "<password>"
},
"baseTopic": "z2m",
"templates": [
// all the z2m device templates are configued here (see below)
],
"devices": [
// all the z2m devices are configured here
]
}
]
}
In the example above, the plugin is configured with 2 brokers - one that holds all KNX devices values and another that is the zigbee2mqtt broker.
If you look closely thought, they are actually pointing to
the same server - they could point to different servers, but in this case it's the same server and the only thing that
really differentiate them is the baseTopic - all KNX values are under the knx base topic while all the zigbee2mqtt
topics are under the z2m base topic.
In this case, we could have also use a single MQTT connection by dropping the baseTopic setting and make sure that the
devices use the full MQTT topic paths in their configurations. So there are a lot of possibilities to design this in a
way to best fit your setup.
We've seen above an example of a device configuration. These configurations may vary from simple to complex, depending on
the type of services (and the number of services) each device/accessory has. But event in its simplest form, like a simple
switch device with a single primary switch service that only has one on characteristic, when you have many of such
services defined, the configuration may look quite cumbersome. More over, it really depends on the setup you have at home,
but it is often the case that the same physical device types are used across the house, for example:
If you have KNX installed in the house, the setups for all your switches in the house is most likely similar and the only thing that changes between them is the KNX group addresses that are associated with them.
If you have a Hue bridge at home, and you're using Hue motion sensor, it's very likely you have a bunch of those and zigbee2mqtt will expose their state in similar ways (just under a different base topic)
There can be many examples as the two above, but the point is, with the normal device configuration as we've seen, you'll find yourself copy-pasting configurations all over the place. This is where Templates enter the picture.
But first, lets say we have 2 Hue motion sensors in the house and we configure them without templates, here's how it might look like:
{
//...
"devices": [
{
"id": "garage-motion",
"name": "Garage Motion",
"type": "motion-sensor",
"topics": {
"motionDetected": {
"get": "Garage Motion$occupancy",
"converter": "boolean"
}
},
"services": [
{
"name": "Battery Level",
"type": "battery",
"topics": {
"batteryLevel": {
"get": "Garage Motion$battery"
}
}
},
{
"name": "Light Sensor",
"type": "light-sensor",
"topics": {
"ambientLevel": {
"get": "Garage Motion$illuminance_lux"
}
}
},
{
"name": "Temperature Sensor",
"type": "temperature-sensor",
"topics": {
"currentTemperature": {
"get": "Garage Motion$temperature"
}
}
}
]
},
{
"id": "stairs-motion",
"name": "Stairs Motion",
"type": "motion-sensor",
"topics": {
"motionDetected": {
"get": "Stairs Motion$occupancy",
"converter": "boolean"
}
},
"services": [
{
"name": "Battery Level",
"type": "battery",
"topics": {
"batteryLevel": {
"get": "Stairs Motion$battery"
}
}
},
{
"name": "Light Sensor",
"type": "light-sensor",
"topics": {
"ambientLevel": {
"get": "Stairs Motion$illuminance_lux"
}
}
},
{
"name": "Temperature Sensor",
"type": "temperature-sensor",
"topics": {
"currentTemperature": {
"get": "Stairs Motion$temperature"
}
}
}
]
}
]
}
Ouch... as you can see, just defining 2 motion sensors already looks quite cumbersome and complex. And even more annoying, the two configurations are almost identical - the only thing that differs them is the base topic of the device (which makes sense, because these are both Hue motion sensors, supporting the same characteristics and controlled by the same system (zigbee2mqtt)).
Surely we can do better - We can define a template for a hue motion sensor and have both devices point to it:
{
"templates": [
{
"id": "hue-motion-sensor",
"type": "motion-sensor",
"topics": {
"motionDetected": {
"get": "{{baseTopic}}$occupancy",
"converter": "boolean"
}
},
"services": [
{
"name": "Battery Level",
"type": "battery",
"topics": {
"batteryLevel": {
"get": "{{baseTopic}}$battery"
}
}
},
{
"name": "Light Sensor",
"type": "light-sensor",
"topics": {
"ambientLevel": {
"get": "Stairs {{baseTopic}}$illuminance_lux"
}
}
},
{
"name": "Temperature Sensor",
"type": "temperature-sensor",
"topics": {
"currentTemperature": {
"get": "{{baseTopic}}$temperature"
}
}
}
]
}
],
"devices": [
{
"id": "garage-motion",
"name": "Garage Motion",
"baseTopic": "Garage Motion",
"template": "hue-motion-sensor"
},
{
"id": "stairs-motion",
"name": "Stairs Motion",
"baseTopic": "Stairs Motion",
"template": "hue-motion-sensor"
}
]
}
The template above defines the typical structure of a Hue motion sensor device and it uses parameter placeholders to
make it reusable. Then, when defining the devices, all that is required is to point to the template and provide a value
to the template parameters (baseTopic in this case). Now imagine you have 10 such motion sensors in the house - this
makes their configuration a breeze. More over, it's great for maintenance - if you need to change how you handle a motion
sensor, you just need to change the template and all motion sensor devices will automatically be updated.
It's also possible to use parameter placeholder in normal device configuration. For example
{
"devices": [
{
"id": "garage-motion",
"name": "Garage Motion",
"type": "motion-sensor",
"topic": "Garage Motion",
"topics": {
"motionDetected": {
"get": "{{topic}}$occupancy",
"converter": "boolean"
}
},
"services": [
{
"name": "Battery Level",
"type": "battery",
"topics": {
"batteryLevel": {
"get": "{{topic}}$battery"
}
}
},
{
"name": "Light Sensor",
"type": "light-sensor",
"topics": {
"ambientLevel": {
"get": "{{topic}}$illuminance_lux"
}
}
},
{
"name": "Temperature Sensor",
"type": "temperature-sensor",
"topics": {
"currentTemperature": {
"get": "{{topic}}$temperature"
}
}
}
]
}
]
}
In the above example, we only need to define the topic of the accessory once in a parameter and
have all topics reference it. If the topic changes, we only need to change one place. Though again, the use
of templates has the potential of a greater added value overall.
boolean - Converts "true" and "false" string values or true and false JSON values.zero-one - Converts "1" and "0" to true and false (also 1 and 0 numeric JSON values){ "on": "<on_value>", "off": "<off_value>" } - Indicates the values that represent true (on) and false (off)homekit - Homekit expects numbers between 0 - 100.decimal - Converts numbers between 0 - 1 (0.34 indicates 34%){ "min": <number>, "max": <number> } - Translate any number between these bounds to a percentage value. Any number above the max will be converted to max and any number below the min will be converted to min.[ "value1", "value2", ... ] - The values in the array represent the MQTT values, the index of each value in the array determines the 0-100 HomeKit value the MQTT value maps to.
for example [ "low", "mid", "high" ] will map low to 0, mid to 50 and high to 100. The converter will also
make sure that 0, 50, and 100 are the only possible values the characteristic will have (rounding other values to one of these values)homekit - Homekit expects numbers representing arc degrees (0 - 360)percent-integer - Converts a percentage value between 0 - 100percent-decimal - Converts a percentage value between 0 - 1homekit - Homekit expects numbers in mirek units ($mirek = \frac{1,000,000}{Kelvin}$)mirek - same as homekitkelvin - Converts numbers in kelvin unitshomekit - Homekit expects numbers in lux unitslux - same as homekitlog-scale-lux - Expects number in log scale values as used by Hue ($lux =(\frac{logscale-1}{10000})^{10}$)homekit - Homekit expects temperature to be in Celsiuscelsius - same as homekitfahrenheit - Expects temperatures to be in Fahrenheit unitsThe HomeKit spec. define a list of characteristics for every service type. Some are mandatory and some are options.
The characteristics here are defined under the topics field as a JSON object where the keys identify
the characteristic types and the values are the configurations for those characteristics. Since we're
dealing with MQTT here, all the characteristics are driven by MQTT topics.
Generally, every characteristic that can be read (e.g. currentTemperature) will have a get configuration which defines the topic to which
the characteristic will subscribe to and the published values will be set on the characteristic. Similarly,
a characteristic that can be set, will have a set configuration which holds the topic to which the characteristic will
publish its values when they change. Quite a few characteristics are both read and write and so they have
both get and set settings.
In addition to set and get it's also possible to configure a converter for the characteristic which determines how
the MQTT values are converted to the HomeKit values and vice versa. There are a fixed set of converters that are built in
which you can pick from.
For write characteristics, in addition to the set topic, it's possible to define a preSet configuration. These are
essentially a list of actions that will be executed prior to publishing the value to MQTT. If any of the actions
fail, the value will be not be published to the MQTT.
The following actions are current supported:
Publishes a value to a MQTT topic. In addition, a feedback can be configured indicating that as a result
of publishing the value, another value should be published (as a sort of confirmation) to another topic, in which
case the action will subscribe to that topic and wait for that value. Once the value arrives, the action
is considered as "executed successfully". It's also possible to define a timeout for the feedback, in which
case when the timeout has passed and the feedback value is not yet published, the action execution will be
considered as "failed".
{
"set": "...",
"preSet": [
{
"type": "mqtt-publish",
"topic": "<the topic to publish the value to>",
"value": "<the value to publish>",
"feedback?": { // optional
"topic": "<feedback topic>",
"value": "<expected feedback value>",
"timeout?": <number> // timeout in milliseconds
}
}
]
}
An action that simply stalls the execution for the configured timeout (in milliseconds). This can be useful when the system on the other side requires some "breathing space" between commands
{
"set": "...",
"preSet": [
{
"type": "wait",
"timeout": <number> // the time to wait before continuing execution
}
]
}
Here's a small use-case for the use of actions. Let's say you have a window-covering service representing blinds.
You can control the blinds by opening or closing them, but also send a "hold" command to command them to stop at their
current position. In some systems, when you want to move directly from "closing" to "opening" you first need to send
a "hold" command. This is where actions can help, by publishing a "hold" value prior to publishing the set value for
the targetPosition. Here is how this configuration may look like:
{
...
"topics": {
"targetPosition": {
"preSet": [
{
"type": "mqtt-publish",
"topic": "blinds/targetPosition/set",
"value": "50", // 50 represents a "hold" value
"feedback": {
"topic": "blinds/targetPosition",
"value": "50", // expecting 50 in return
"timeout": 4000
}
}
],
"set": "test/blinds/targetPosition/set",
"get": "test/blinds/targetPosition",
"converter": [ "100", "50", "0" ]
},
"currentPosition": {
"get": "test/blinds/currentPosition",
"converter": [ "100", "50", "0"]
}
}
}
The following characteristic are optional and may be configured on any service type
In addition to the above common characteristics, sensor devices may also support the following ones:
activeIndicates whether the service is currently active. By default, will look for values 0 or 1 where 1 indicates
on/true and 0 indicates off/false.
Values can be converted using the Booleans converter.
{
"topics": {
"active": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "min": <number>, "max": <number> }
}
}
}
airQualityDescribes the subject assessment of air quality. By default, will look for the following values:
0 - indicates "unknown"1 - indicates "excellent"2 - indicates "good"3 - indicates "fair"4 - indicates "inferior"5 - indicates "poor"You can customize the read/published values using a value map converter (as shown below)
{
"topics": {
"airQuality": {
"get": "<read_topic>",
"converter"?: {
"unknown"?: "<value representing 'unknown'>",
"excellent"?: "<value representing 'excellent'>",
"good"?: "<value representing 'good'>",
"fair"?: "<value representing 'fair'>",
"inferior"?: "<value representing 'inferior'>",
"poor"?: "<value representing 'poor'>"
}
}
}
}
ambientLightLevelIndicates the current light level in lux numeric units.
Values can be converted using the Illuminance converter.
{
"topics": {
"ambientLightLevel": {
"get": "<read_topic>",
"converter"?: log-scale-lux"
}
}
}
batteryLevelDescribes the current level of the battery in a numeric value representing a percentage. Values can be converted using the Percentages converter.
{
"topics": {
"batteryLevel": {
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
brightnessDescribes a level of brightness in a numeric value representing a percentage. Values can be converted using the Percentages converter.
{
"topics": {
"brightness": {
"get": "<read_topic>",
"get": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
co2DetectedIndicates if a sensor detects abnormal levels of Carbon Dioxide. By default, will look for 0 (indicating "not detected")
or 1 (indicating "detected").
Values can be converted using the Booleans converter.
{
"topics": {
"co2Detected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'detected' value", "off": "'not-detected' value" }
}
}
}
co2LevelIndicates the detected level of Carbon Dioxide - a numeric value indicating parts per million (ppm).
{
"topics": {
"co2Level": {
"get": "<read_topic>"
}
}
}
co2PeakLevelIndicates the highest detected level of Carbon Dioxide detected by a sensor - a numeric value indicating parts per million (ppm).
{
"topics": {
"co2PeakLevel": {
"get": "<read_topic>"
}
}
}
coDetectedIndicates if a sensor detects abnormal levels of Carbon Monoxide. By default, will look for 0 (indicating "not detected")
or 1 (indicating "detected").
Values can be converted using the Booleans converter.
{
"topics": {
"coDetected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'detected' value", "off": "'not-detected' value" }
}
}
}
coLevelIndicates the detected level of Carbon Monoxide - a numeric value indicating parts per million (ppm).
{
"topics": {
"coLevel": {
"get": "<read_topic>"
}
}
}
coPeakLevelIndicates the highest detected level of Carbon Monoxide detected by a sensor - a numeric value indicating parts per million (ppm).
{
"topics": {
"coPeakLevel": {
"get": "<read_topic>"
}
}
}
chargingStateIndicates whether the battery-ran device is currently charging or not. Values can be converted using the Booleans converter.
{
"topics": {
"chargingState": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'charging' value", "off": "'not-charging' value" }
}
}
}
colorTemperatureDescribes color temperature - a numeric value in the mirek scale Values can be converted using the Color Temperatures converter.
{
"topics": {
"colorTemperature": {
"get": "<read_topic>",
"set": "<read_topic>",
"converter"?: "kelvin"
}
}
}
contactSensorStateDescribes the state of a contact sensor. By default, will look for 0 (indicating "no contact") and 1 (indicating "contact")
Values can be converted using the Booleans converter.
{
"topics": {
"contactSensorState": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'contact' value", "off": "'no-contact' value" }
}
}
}
coolingThresholdDescribes the cooling threshold in Celsius for accessories that support heating and cooling. If the thermostat operates in an "auto" mode and the current temperature goes above this threshold the thermostat will start cooling. Values can be converted using the Temperatures converter.
{
"topics": {
"coolingThreshold": {
"get": "<read_topic>",
"set": "<read_topic>",
"converter"?: "fahrenheit"
}
}
}
currentFanState[!NOTE] When used as part of a
fanservice, this can be shorten tocurrentState
Describes the current state of the fan. Expects the following numeric values:
0 - indicating "inactive" state1 - indicating "idle" state2 - indicating "blowing air" stateOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"currentFanState": {
"get": "<read_topic>",
"converter"?: {
"inactive"?: "'inactive' state value",
"idle"?: "'idle' state value",
"blowingAir"?: "'blowing air' state value"
}
}
}
}
currentHeatingCoolingState[!NOTE] When used as part of a
thermostatservice, this can be shorten tocurrentState
Describes the current mode of a thermostat. Expects the following numeric values:
0 - indicating "off" state1 - indicating "heat" state2 - indicating "cool" stateOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"currentHeatingCoolingState": {
"get": "<read_topic>",
"converter"?: {
"off"?: "'off' state value",
"heat"?: "'heat' state value",
"cool"?: "'cool' state value"
}
}
}
}
currentHorizontalTiltAngleDescribes the current angle of the horizontal slats of the device. A numeric value in arc degrees, ranging
between -90 - 90.
{
"topics": {
"currentHorizontalTiltAngle": {
"get": "<read_topic>"
}
}
}
currentHumidifierDehumidifierState[!NOTE] When used as part of a
humidifier-dehumidifierservice, this can be shorten tocurrentState
Describes the current state of a humidifier or/and a dehumidifier. Expecting the following numeric values:
0 - indicating inactive state1 - indicating idle state2 - indicating humidifying state3 - indicating dehumidifying stateOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"currentHumidifierDehumidifierState": {
"get": "<read_topic>",
"converter"?: {
"inactive"?: "'inactive' state value",
"idle"?: "'idle' state value",
"humidifying"?: "'humidifying' state value",
"dehumidifying"?: "'dehumidifying' state value"
}
}
}
}
currentPositionDescribes the current position of accessories as a percentage value. 0 typically indicates "fully closed" while 100
indicates "fully open". Some services (e.g. window-covering let you reverse this).
Other values can be converted using the Percentages converter.
{
"topics": {
"currentPosition": {
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
currentRelativeHumidityDescribes the current relative humidity of the device's environment. By default, expecting a numeric value
between 0 and 100 representing a percentage.
Other values can be converted using the Percentages converter.
{
"topics": {
"currentRelativeHumidity": {
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
currentTemperatureDescribes the current temperature of the environment in Celsius Other values can be converted using the Temperatures converter.
By default, values range between 10.0 and 38.0 with a minimum step of 0.1. This can be adjusted in
the configuration (as shown below).
{
"topics": {
"currentTemperature": {
"get": "<read_topic>",
"converter"?: "fahrenheit",
"minValue"?: <number>, // in celsius (regardless of the converter), defaut: 10.0
"maxValue"?: <number>, // in celsius (regardless of the converter), defaut: 38.0
"minStep"?: <number> // in celsius (regardless of the converter), defaut: 0.1
}
}
}
currentVerticalTiltAngleDescribes the current angle of the vertical slats of the device. Expecting a numeric value representing arc degrees
between -90 and 90.
{
"topics": {
"currentVerticalTiltAngle": {
"get": "<read_topic>"
}
}
}
faultMessageA non-standard homekit characteristic indicating a fault message in case the device if faulty.
[!NOTE] As a non-standard characteristic, this will no show up in the Home app, though other apps that support this custom characteristic will show it (e.g. Eve)
This characteristic is optional and can be configured on all service types.
{
"topics": {
"faultMessage": {
"get": "<read_topic>"
}
}
}
heatingThresholdDescribes the heating threshold in Celsius for accessories that support heating and cooling. If the thermostat operates in an "auto" mode and the current temperature goes below this threshold the thermostat will start heating. Values can be converted using the Temperatures converter.
{
"topics": {
"heatingThreshold": {
"get": "<read_topic>",
"set": "<read_topic>",
"converter"?: "fahrenheit"
}
}
}
holdPositionUsed to signal a device that it should stop it current operations in its current position (typically used for
window-covering). This characteristic doesn't hold a value. To signal a "hold" it sets a value in the configured
set topic. By default, it sets the value to 1, though this can be changed in the configuration (as shown below).
{
"topics": {
"holdPosition": {
"set": "<write_topic>",
"value"?: "any value that the device will understand as a 'hold' command"
}
}
}
hueDescribes hue or color. A hue is typically measured as an arc degree in a Hue Wheel. Expects, a numeric value
between 0 and 360.
Percentage values (e.g. 34% of 360) are also supported and be configured using the Hue Converter
{
"topics": {
"hue": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "percent-integer" | "percent-decimal"
}
}
}
leakDetectedIndicates if a sensor detected a leak (e.g. water leak, gas leak). By default, will look for 0 (indicating "not detected")
or 1 (indicating "detected").
Values can be converted using the Booleans converter.
{
"topics": {
"leakDetected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
}
}
}
lockCurrentState[!NOTE] When used as part of a
lockservice, this can be shorten tocurrentState
Describes the current state of a lock. Expecting the following numeric values:
0 - indicating "unsecured" state1 - indicating "secured" state2 - indicating "jammed" state3 - indicating "unknown" stateOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"lockCurrentState": {
"get": "<read_topic>",
"converter"?: {
"unsecured"?: "'unsecured' state value",
"secured"?: "'secured' state value",
"jammed"?: "'jammed' state value",
"unknown"?: "'unknown' state value"
}
}
}
}
lockPhysicalControlsDescribes a way to lock a set of physical controls on an accessory (eg. child lock). By default, will look for 0
(indicating "not detected") or 1 (indicating "detected").
Values can be converted using the Booleans converter.
{
"topics": {
"lockPhysicalControls": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "": "<value indicating 'locked'>", "off": "value indicating 'not-locked'" }
}
}
}
lockTargetState[!NOTE] When used as part of a
lock-mechansimservice, this can be shorten totargetState
Describes the current state of a lock. Expecting the following numeric values:
0 - indicating "unsecured" state1 - indicating "secured" stateOther values can be converted using a converter (as shown below).
{
"topics": {
"lockTargetState": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "secured": "<value indicating 'secured'>", "unsecured": "value indicating 'unsecured'" } // a boolean 'true' indicates 'secured'
}
}
}
momentaryOnThis is a special case of an 'on' characteristic when turned on it immediately turns back off. When turned on, it publishes the configured value to the configured topic.
{
"topics": {
"momentaryOn": {
"set": "<read_topic>",
"value": number | string | boolean // the momentary published value
"resetValue"?: number | string | boolean // will be set as the value immediately right after the momentary value above is set
}
}
}
motionDetectedIndicates if a sensor detected motion. By default, will look for true (indicating "detected")
or false (indicating "not-detected").
Values can be converted using the Booleans converter.
{
"topics": {
"motionDetected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
}
}
}
muteAllows the control of audio input or output accessory. By default, will look for true (indicating "muted")
or false (indicating "not-muted").
Values can be converted using the Booleans converter.
{
"topics": {
"motionDetected": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'muted'>", "off": "value indicating 'not-muted'" }
}
}
}
no2DensityIndicates the current Nitrogen Dioxide density. A numeric value in $micrograms/m^3$ units.
{
"topics": {
"no2Density": {
"get": "<read_topic>"
}
}
}
obstructionDetectedDescribes the current state of an obstruction sensor. By default, will look for true (indicating "detected")
or false (indicating "not detected").
Values can be converted using the Booleans converter.
{
"topics": {
"obstructionDetected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
}
}
}
occupancyDetectedIndicates if occupancy was detected (e.g. a person present). By default, will look for 1 (indicating "detected")
or 0 (indicating "not detected").
Values can be converted using the Booleans converter.
{
"topics": {
"occupancyDetected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
}
}
}
onRepresents the states for “on” and “off”. By default, will look for true (indicating "on")
or false (indicating "off").
Values can be converted using the Booleans converter.
{
"topics": {
"on": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'on'>", "off": "value indicating 'off'" }
}
}
}
outletInUsedescribes if the power outlet has an appliance physically plugged in. By default, will look for true (indicating "in-use")
or false (indicating "not-in-use").
Values can be converted using the Booleans converter.
{
"topics": {
"outletInUse": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'in-use'>", "off": "value indicating 'not-in-use'" }
}
}
}
ozoneDensityIndicates the current ozone density. A numeric value in $micrograms/m^3$ units.
{
"topics": {
"ozoneDensity": {
"get": "<read_topic>"
}
}
}
pm10DensityIndicates the current PM10 micrometer particulate density. A numeric value in $micrograms/m^3$ units.
{
"topics": {
"pm10Density": {
"get": "<read_topic>"
}
}
}
pm25DensityIndicates the current PM2.5 micrometer particulate density. A numeric value in $micrograms/m^3$ units.
{
"topics": {
"pm25Density": {
"get": "<read_topic>"
}
}
}
positionStateDescribes the state of the position of accessories. Expecting the following numeric values:
0 - indicating "closing" state1 - indicating "opening" state2 - indicating "stopped" stateOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"lockCurrentState": {
"get": "<read_topic>",
"converter"?: {
"closing"?: "'closing' state value",
"opening"?: "'opening' state value",
"stopped"?: "'stopped' state value"
}
}
}
}
pressEventDescribes a press event generated by a button. This characteristic doesn't hold a value nor publishes a value to an MQTT topic. All it does is monitor an MQTT topic and based on the value received it triggers the appropriate event. By default, it expects the following numeric values:
0 - indicating "single-press" event1 - indicating "double-press" event2 - indicating "long-press" eventOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"pressEvent": {
"get": "<read_topic>",
"converter"?: {
"single"?: "value indicating a 'single' press event",
"double"?: "value indicating a 'double' press event",
"long"?: "value indicating a 'long' press event"
}
}
}
}
dehumidifierThresholdDescribes the relative humidity dehumidifier threshold, representing the maximum relative humidity that must be reached
before a dehumidifier is turned on. Expects a numeric value indicating the humidity in percentage between
0 and 100.
Other values can be converted using a Percentages converter (as shown below).
{
"topics": {
"dehumidifierThreshold": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
humidifierThresholdDescribes the relative humidity humidifier threshold, representing the minimum relative humidity that must be reached
before a humidifier is turned on. Expects a numeric value indicating the humidity in percentage between
0 and 100.
Other values can be converted using a Percentages converter (as shown below).
{
"topics": {
"humidifierThreshold": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
rotationDirectiondescribes the direction of rotation of a fan. Expects the following numeric values:
0 - indicates clockwise direction1 - indicates counter-clockwise directionOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"rotationDirection": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: { "clockwise": "value representing 'clockwise'", "counter-clockwise": "value representing 'counter-clockwise'" }
}
}
}
rotationSpeedDescribes the rotation speed of a fan. A numeric value representing the speed as a percentage between
0 and 100, where 0 indicates no speed and 100 indicates maximum speed.
Other values are supported using the following converters:
decimal - expects a values representing the speed as a percentage value between 0 and 1 (e.g. 0.36 indicates 36%){ "min": <number>, "max": <number> } - expects a value between the min and max value, from which it deduce the speed percentage.<number> - A converter holding a number indicates the number of supported speed levels, expecting a number between 0 and the configured number.
For example, converter: 5 indicates there are 6 speed levels to look for - 0, 1, 2, 3, 4, 5.string[] - A converter holding an array of values, each representing a level. The speed level of each value is the index
of that value in the array - the first value will always represent "no speed". For example, converter: [ "off", "low", "medium", "high" ] will expect all to
receive any of these values. If, for example, it receives a low value, then it knows this value represents
33% speed level, as it's the first out of 3 possible speed levels (excl. the first one which is "no-speed").{
"topics": {
"rotationDirection": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> } | <number> | string[]
}
}
}
saturationDescribes color saturation. A numeric value indicating a percentage.
Values can be converted using the Percentages converter.
{
"topics": {
"saturation": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
alarmTypedescribes the type of alarm triggered by a security system. The only alarm type that is currently supported by homekit is an "unknown" type. For this reason, by default, these are the values it expects:
0 - indicating the alarm is clearedIt is possible to configure a different values to indicate the cleared state (as shown below)
{
"topics": {
"alarmType": {
"get": "<read_topic>",
"converter"?: { "cleared": "value representing a 'cleared` state"}
}
}
}
securitySystemCurrentState[!NOTE] When used as part of a
security-systemservice, this can be shorten tocurrentState
Describes the state of a security system. Expecting the following numeric values:
0 - "stay" state1 - "away" state2 - "night" state3 - "disarmed" state4 - "triggered" stateOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"securitySystemCurrentState": {
"get": "<read_topic>",
"converter"?: {
"stay"?: "'stay' state value",
"away"?: "'away' state value",
"night"?: "'night' state value",
"disarmed"?: "'disarmed' state value",
"triggered"?: "'triggered' state value",
}
}
}
}
securitySystemTargetState[!NOTE] When used as part of a
security-systemservice, this can be shorten totargetState
Describes the target state of the security system. Expecting the following numeric values:
0 - "stay" state1 - "away" state2 - "night" state3 - "disarm" stateOther values can be converted using a value-map converter (as shown below).
It is also possible to limit the supported values using the validValues settings.
{
"topics": {
"securitySystemTargetState": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: {
"stay"?: "'stay' state value",
"away"?: "'away' state value",
"night"?: "'night' state value",
"disarm"?: "'disarm' state value",
},
"validValues"?: string[] // e.g. [ "stay", "away", "disarm" ] to not show the 'night' option.
}
}
}
smokeDetectedIndicates if a sensor detects abnormal levels of smoke. By default, will look for 0 (indicating "not detected")
or 1 (indicating "detected").
Values can be converted using the Booleans converter.
{
"topics": {
"smokeDetected": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
}
}
}
so2DensityIndicates the current Sulphur Dioxide density. A numeric value in $micrograms/m^3$ units.
{
"topics": {
"so2Density": {
"get": "<read_topic>"
}
}
}
statusFaultIndicates the device is faulty. Expecting a 1 indicating a "general fault" and 0 indicating there's no fault.
Other values can be converted using the Booleans converter.
This characteristic is optional on all services.
{
"topics": {
"statusFault": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
}
}
}
statusLowBatteryDescribes an accessory which has been tampered with. By default, will look for 0 indicating battery
level is not low, and 1 indicating "low-battery" status.
Other values can be converted using the Booleans converter.
This characteristic is optional on all sensor services.
{
"topics": {
"statusLowBattery": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
}
}
}
statusTamperedIndicates if a battery-ran device is running low on battery. By default, will look for 0 indicating battery
level is not low, and 1 indicating "low-battery" status.
Other values can be converted using the Booleans converter.
This characteristic is optional on all sensor services.
{
"topics": {
"statusTampered": {
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
stickyOnThis is a special case of an 'on' characteristic that is associated with a value. When turned on,
it publishes this value to the configured set topic, and it stays turned on until it receives a
different value from the configured get topic. Trying to force it off will cause it to "silently" turn back
on ("silently" in that it will not publish the value to the set topic).
{
"topics": {
"stickyOn": {
"get": "<read_topic>",
"set": "<write_topic>",
"value": number | string | boolean // the published value
}
}
}
swingModeIndicates if swing mode is enabled. By default, will look for 0 indicating swing "disabled" mode, and 1
indicating swing "enabled" mode.
Other values can be converted using the Booleans converter.
{
"topics": {
"swingMode": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "'enabled' mode value", "off": "'disabled' mode value"}
}
}
}
targetFanState[!NOTE] When used as part of a
fanservice, this can be shorten totargetState
Describes the target state of the fan. Expecting the following numeric values:
0 - indicates a "manual" state1 - indicates an "auto" stateOther values can be converted using the value-map converter (as show below).
{
"topics": {
"targetFanState": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: { "auto": "'auto' state value", "manual": "'manual' state value"}
}
}
}
targetHeatingCoolingState[!NOTE] When used as part of a
thermostatservice, this can be shorten totargetState
Describes the target mode of a thermostat. Expects the following numeric values:
0 - indicating "off" state1 - indicating "heat" state2 - indicating "cool" state3 - indicating "auto" stateOther values can be converted using a value-map converter (as shown below).
It is also possible to limit the possible values using the validValues setting.
{
"topics": {
"targetHeatingCoolingState": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: {
"off"?: "'off' state value",
"heat"?: "'heat' state value",
"cool"?: "'cool' state value",
"auto"?: "'auto' state value",
},
"validValues": string[] // e.g. [ "off", "auto" ] to only provide the user to stop the operation of the device
}
}
}
targetHorizontalTiltAngleDescribes the target angle of the horizontal slats of the device. A numeric value in arc degrees, ranging
between -90 - 90.
{
"topics": {
"targetHorizontalTiltAngle": {
"get": "<read_topic>",
"set": "<write_topic>"
}
}
}
targetHumidifierDehumidifierState[!NOTE] When used as part of a
humidifier-dehumidifierservice, this can be shorten totargetState
Describes the target state of a humidifier or/and a dehumidifier. Expecting the following numeric values:
0 - indicating humidifierDehumidifier state - only applicable to devices that are both humidifiers and dehumidifiers,
this indicates that the device should always keep the humidity at bay, by both humidifying when humidity is low and
dehumidifying when humidity is high (both low and high humidity levels are determined by the
humidifierThreshold and
dehumidifierThreshold characteristics.
1 - indicating humidifier state - only applicable to devices that are humidifiers. Indicating that the device should
humidify if the humidity level is too low (reaches the humidifierThreshold).
2 - indicating dehumidifier state - only applicable to devices that are dehumidifiers. Indicating that the device should
dehumidify if the humidity level is too hight (reaches the dehumidifierThreshold).
Other values can be converted using a value-map converter (as shown below).
{
"topics": {
"targetHumidifierDehumidifierState": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: {
"humidifierDehumidifier"?: "'humidifierDehumidifier' state value",
"humidifier"?: "'humidifier' state value",
"dehumidifier"?: "'dehumidifier' state value"
}
}
}
}
targetPositionDescribes the target position of accessories as a percentage value. 0 typically indicates "fully closed" while 100
indicates "fully open". Some services (e.g. window-covering let you reverse this).
Other values can be converted using the Percentages converter.
{
"topics": {
"targetPosition": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
targetRelativeHumidityDescribes the target relative humidity that the device should actively attempt to reach. By default, expecting a numeric
value between 0 and 100 representing a percentage.
Other values can be converted using the Percentages converter.
{
"topics": {
"targetRelativeHumidity": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
targetTemperatureDescribes the target temperature of the environment in Celsius. Other values can be converted using the Temperatures converter.
By default, values range between 10.0 and 38.0 with a minimum step of 0.1. This can be adjusted in
the configuration (as shown below).
{
"topics": {
"currentTemperature": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "fahrenheit",
"minValue"?: <number>, // in celsius (regardless of the converter), defaut: 10.0
"maxValue"?: <number>, // in celsius (regardless of the converter), defaut: 38.0
"minStep"?: <number> // in celsius (regardless of the converter), defaut: 0.1
}
}
}
targetVerticalTiltAngleDescribes the target angle of the vertical slats of the device. Expecting a numeric value representing arc degrees
between -90 and 90.
{
"topics": {
"targetVerticalTiltAngle": {
"get": "<read_topic>",
"set": "<write_topic>"
}
}
}
temperatureDisplayUnitsDescribes units of temperature used for presentation purposes. Expecting the following numeric values:
0 - indicating celsius1 - indicating fahrentheitOther values can be converted using a value-map converter (as shown below).
{
"topics": {
"temperatureDisplayUnits": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: { "celsius": "value indicating 'celsius'", "fahrenheit": "value indicating 'fahrenheit'" }
}
}
}
vocDensityIndicates the current volatile organic compound density. A numeric value in $micrograms/m^3$ units.
{
"topics": {
"vocDensity": {
"get": "<read_topic>"
}
}
}
volumeEnables controlling the input or output volume of an audio device. By default, expecting a numeric value
between 0 and 100 representing a percentage.
Other values can be converted using the Percentages converter.
{
"topics": {
"volume": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
waterLevelIndicating the current water level of the device. By default, expecting a numeric value between 0 and 100
representing a percentage.
Other values can be converted using the Percentages converter.
{
"topics": {
"waterLevel": {
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "air-quality-sensor",
"topics": {
"airQuality": { //required
"get": "<topic>",
"converter"?: { "unknown": string, "excellent": stirng, "good": string, "fair": string, "inferior": stirng, "port": string }
},
"ozoneDensity"?: { // optional
"get": "<topic>"
},
"no2Density"?: { // optional
"get": "<topic>"
},
"so2Density"?: { // optional
"get": "<topic>"
},
"pm25Density"?: { // optional
"get": "<topic>"
},
"pm10Density"?: { // optional
"get": "<topic>"
},
"vocDensity"?: { // optional
"get": "<topic>"
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "battery",
"topics": {
"batteryLevel": { //required
"get": "<topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"chargingState"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'charging' value", "off": "'not-charging' value" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "button",
"topics": {
"pressEvent": { //required
"get": "<read_topic>",
"converter"?: {
"single"?: "value indicating a 'single' press event",
"double"?: "value indicating a 'double' press event",
"long"?: "value indicating a 'long' press event"
}
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "co2-sensor",
"topics": {
"co2Detected": { //required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'detected' value", "off": "'not-detected' value" }
},
"co2Level"?: { // optional
"get": "<read_topic>"
},
"co2PeakLevel"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "contact-sensor",
"topics": {
"contactSensorState": { //required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'contact' value", "off": "'no-contact' value" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "co-sensor",
"topics": {
"coDetected": { //required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'detected' value", "off": "'not-detected' value" }
},
"coLevel"?: { // optional
"get": "<read_topic>"
},
"coPeakLevel"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "door",
"topics": {
"currentPosition": { //required
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"targetPosition": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"positionState": { // required
"get": "<read_topic>",
"converter"?: {
"closing"?: "'closing' state value",
"opening"?: "'opening' state value",
"stopped"?: "'stopped' state value"
}
},
"holdPosition"?: { // optional
"set": "<write_topic>",
"value"?: "any value that the device will understand as a 'hold' command"
},
"obstructionDetected"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "doorbell",
"topics": {
"pressEvent": { //required
"get": "<read_topic>",
"converter"?: {
"single"?: "value indicating a 'single' press event",
"double"?: "value indicating a 'double' press event",
"long"?: "value indicating a 'long' press event"
}
},
"volume"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"brightness"?: { // optional
"get": "<read_topic>",
"get": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
rotationSpeed is not configured)active is not configured)currentFanState)targetFanState){
"name": "<custom name>",
"type": "fan",
"topics": {
"active": { // required if 'rotationSpeed' is not configured
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "'active' state value'", "off": "'inactive' state value" }
},
"rotationSpeed"?: { // required if 'active' is not configured
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> } | <number> | string[]
},
"currentState"?: { // optional
"get": "<read_topic>",
"converter"?: {
"inactive"?: "'inactive' state value",
"idle"?: "'idle' state value",
"blowingAir"?: "'blowing air' state value"
}
},
"targetState"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: { "auto": "'auto' state value", "manual": "'manual' state value"}
},
"rotationDirection"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: { "clockwise": "value representing 'clockwise'", "counter-clockwise": "value representing 'counter-clockwise'" }
},
"swingMode"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "'enabled' mode value", "off": "'disabled' mode value"}
},
"lockPhysicalControls"?: {// optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'locked'>", "off": "value indicating 'not-locked'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
currentHumidifierDehumidifierState)targetHumidifierDehumidifierState){
"name": "<custom name>",
"type": "humidifier-dehumidifier",
"topics": {
"currentState": { // required
"get": "<read_topic>",
"converter"?: {
"inactive"?: "'inactive' state value",
"idle"?: "'idle' state value",
"humidifying"?: "'humidifying' state value",
"dehumidifying"?: "'dehumidifying' state value"
}
},
"targetState": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: {
"humidifierDehumidifier"?: "'humidifierDehumidifier' state value",
"humidifier"?: "'humidifier' state value",
"dehumidifier"?: "'dehumidifier' state value"
}
},
"humidifierThreshold"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"dehumidifierThreshold"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"rotationSpeed"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> } | <number> | string[]
},
"swingMode"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "'enabled' mode value", "off": "'disabled' mode value"}
},
"waterLevel": { // optional
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
}
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "humidity-sensor",
"topics": {
"currentRelativeHumidity": { // required
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "leak-sensor",
"topics": {
"leakDetected": { // required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "lightbulb",
"topics": {
"on": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'on'>", "off": "value indicating 'off'" }
},
"brightness": { // optional
"get": "<read_topic>",
"get": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"saturation": { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"hue": { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "percent-integer" | "percent-decimal"
},
"colorTemperature": { // optional
"get": "<read_topic>",
"set": "<read_topic>",
"converter"?: "kelvin"
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "light-sensor",
"topics": {
"ambientLightLevel": { // required
"get": "<read_topic>",
"converter"?: log-scale-lux"
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
lockCurrentState)lockTargetState){
"name": "<custom name>",
"type": "lock",
"topics": {
"currentState": { // required
"get": "<read_topic>",
"converter"?: {
"unsecured"?: "'unsecured' state value",
"secured"?: "'secured' state value",
"jammed"?: "'jammed' state value",
"unknown"?: "'unknown' state value"
}
},
"targetState": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "secured": "<value indicating 'secured'>", "unsecured": "value indicating 'unsecured'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "microphone",
"topics": {
"mute": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'muted'>", "off": "value indicating 'not-muted'" }
},
"volume": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "motion-sensor",
"topics": {
"motionDetected": { // required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "occupancy-sensor",
"topics": {
"occupancyDetected": { // required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "outlet",
"topics": {
"on": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'on'>", "off": "value indicating 'off'" }
},
"outletInUse": { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'in-use'>", "off": "value indicating 'not-in-use'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
securitySystemCurrentState)securitySystemTargetState){
"name": "<custom name>",
"type": "security-system",
"topics": {
"currentState": { // required
"get": "<read_topic>",
"converter"?: {
"stay"?: "'stay' state value",
"away"?: "'away' state value",
"night"?: "'night' state value",
"disarmed"?: "'disarmed' state value",
"triggered"?: "'triggered' state value",
}
},
"targetState": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: {
"stay"?: "'stay' state value",
"away"?: "'away' state value",
"night"?: "'night' state value",
"disarm"?: "'disarm' state value",
},
"validValues"?: string[] // e.g. [ "stay", "away", "disarm" ] to not show the 'night' option.
},
"alarmType": { // optional
"get": "<read_topic>",
"converter"?: { "cleared": "value representing a 'cleared` state"}
},
"statusTampered": { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "smoke-sensor",
"topics": {
"smokeDetected": { // required
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "speaker",
"topics": {
"mute": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'muted'>", "off": "value indicating 'not-muted'" }
},
"volume": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
This can be a useful tool to implement a multi-state switch over a single topic. For example,
if there is a device that can have 3 states = off, low and high. These states are published
to a single topic. You can then set up a stateful-scene device. The primary service will
represent the off state, and two additional stateful-scene sub-services will represent the other
low and high states. This will translate to a HomeKit grouped accessory with 3 switches where
only the switch representing the current state can be on at any given time. Trying to turn it off
will fail - it will only turn off if you turn on any of the other switches (which effectively changing
the state of the device).
Characteristics:
{
"name": "<custom name>",
"type": "speaker",
"topics": {
"stickyOn": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"value": string | number | boolean // the published value
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
This can be useful to define a device that simply triggers a scene. It only publishes a value and ignores any other values that are published on the MQTT broker.
Characteristics:
{
"name": "<custom name>",
"type": "stateless-scene",
"topics": {
"momentaryOn": { // required
"set": "<write_topic>",
"value": string | number | boolean // the published value
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "switch",
"topics": {
"on": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'on'>", "off": "value indicating 'off'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "smoke-sensor",
"topics": {
"currentTemperature": { // required
"get": "<read_topic>",
"converter"?: "fahrenheit",
"minValue"?: <number>, // in celsius (regardless of the converter), defaut: 10.0
"maxValue"?: <number>, // in celsius (regardless of the converter), defaut: 38.0
"minStep"?: <number> // in celsius (regardless of the converter), defaut: 0.1
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
},
"statusLowBattery"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'low' status value", "off": "'not-low' status value"}
},
"statusTampered"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'tampered' status value", "off": "'not-tampered' status value"}
}
}
}
Characteristics:
currentHeatingCoolingState)targetHeatingCoolingState)Additional Settings:
hvacType (optional) - only used when currentHeatingCoolingState is not set. Can have one of the following values:
heat-cool: depending on the current and target temp. heat/cool/off will be set as the current stateheat-only: depending on the current and target temp. heat/off will be set as the current statecool-only: depending on the current and target temp. cool/off will be set as the current statestateThreshold (optional) - Only used when currentHeatingCoolingState is not set. A numeric values that determines
when the current state will change (based on the current and target temperatures). e.g.
target > current + threshold the state will either be heat or off (depending on the hvacType)target < current - threshold the state will either be cool or off (depending on the hvacType)off{
"name": "<custom name>",
"type": "thermostat",
"hvacType"?: "heat-cool" | "heat-only" | "cool-only",
"stateThreshold"?: <number>,
"topics": {
"currentTemperature": { // required
"get": "<read_topic>",
"converter"?: "fahrenheit",
"minValue"?: <number>, // in celsius (regardless of the converter), defaut: 10.0
"maxValue"?: <number>, // in celsius (regardless of the converter), defaut: 38.0
"minStep"?: <number> // in celsius (regardless of the converter), defaut: 0.1
},
"targetTemperature": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "fahrenheit",
"minValue"?: <number>, // in celsius (regardless of the converter), defaut: 10.0
"maxValue"?: <number>, // in celsius (regardless of the converter), defaut: 38.0
"minStep"?: <number> // in celsius (regardless of the converter), defaut: 0.1
},
"currentState": { // optional
"get": "<read_topic>",
"converter"?: {
"off"?: "'off' state value",
"heat"?: "'heat' state value",
"cool"?: "'cool' state value"
}
},
"targetState": {
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: {
"off"?: "'off' state value",
"heat"?: "'heat' state value",
"cool"?: "'cool' state value",
"auto"?: "'auto' state value",
},
"validValues": string[] // e.g. [ "off", "auto" ] to only provide the user to stop the operation of the device
},
"temperatureDisplayUnits": { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: { "celsius": "value indicating 'celsius'", "fahrenheit": "value indicating 'fahrenheit'" }
},
"coolingThreshold": { // optional
"get": "<read_topic>",
"set": "<read_topic>",
"converter"?: "fahrenheit"
},
"heatingThreshold": { // optional
"get": "<read_topic>",
"set": "<read_topic>",
"converter"?: "fahrenheit"
},
"currentRelativeHumidity": { // optional
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"targetRelativeHumidity": { // optional
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "window",
"topics": {
"currentPosition": { //required
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"targetPosition": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"positionState": { // required
"get": "<read_topic>",
"converter"?: {
"closing"?: "'closing' state value",
"opening"?: "'opening' state value",
"stopped"?: "'stopped' state value"
}
},
"holdPosition"?: { // optional
"set": "<write_topic>",
"value"?: "any value that the device will understand as a 'hold' command"
},
"obstructionDetected"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
Characteristics:
{
"name": "<custom name>",
"type": "window-covering",
"topics": {
"currentPosition": { //required
"get": "<read_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"targetPosition": { // required
"get": "<read_topic>",
"set": "<write_topic>",
"converter"?: "decimal" | { "min": <number>, "max": <number> }
},
"positionState?": { // optional
"get": "<read_topic>",
"converter"?: {
"closing"?: "'closing' state value",
"opening"?: "'opening' state value",
"stopped"?: "'stopped' state value"
}
},
"holdPosition"?: { // optional
"set": "<write_topic>",
"value"?: "any value that the device will understand as a 'hold' command"
},
"obstructionDetected"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "<value indicating 'detected'>", "off": "value indicating 'not-detected'" }
},
"currentHorizontalTiltAngle"?: { // optional
"get": "<read_topic>"
},
"targetHorizontalTiltAngle"?: {
"get": "<read_topic>",
"set": "<write_topic>"
},
"currentVerticalTiltAngle"?: { // optional
"get": "<read_topic>"
},
"targetVerticalTiltAngle"?: { // optional
"get": "<read_topic>",
"set": "<write_topic>"
}
"statusFault"?: { // optional
"get": "<read_topic>",
"converter"?: "boolean" | { "on": "'fault' value", "off": "'no fault' value"}
},
"faultMessage"?: { // optional
"get": "<topic>"
}
}
}
FAQs
Homebridge Mqtt Plugin
The npm package @uboness/homebridge-mqtt receives a total of 54 weekly downloads. As such, @uboness/homebridge-mqtt popularity was classified as not popular.
We found that @uboness/homebridge-mqtt demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Vibe coding at scale is reshaping how packages are created, contributed, and selected across the software supply chain

Security News
npm invalidated all granular access tokens that bypass 2FA after a fresh Mini Shai-Hulud wave compromised 323 npm packages. Staged publishing also entered public preview.

Research
/Security News
Compromised npm package art-template delivered a Coruna-like iOS Safari exploit framework through a watering-hole attack.