GithubHelp home page GithubHelp logo

hemtjanst / tradfri-mqtt Goto Github PK

View Code? Open in Web Editor NEW
38.0 8.0 9.0 123 KB

Mirrors Trådfri gateways endpoints into MQTT and send commands to the gateway from MQTT

Home Page: https://hemtjan.st/tradfri-mqtt

License: Apache License 2.0

JavaScript 0.79% TypeScript 97.60% Dockerfile 1.61%
mqtt tradfri nodejs smarthome home-automation domotic

tradfri-mqtt's Introduction

Hemtjänst

Hemtjänst is:

  • A Swedish word for home care or home service
  • A specification of sorts on how devices should register with an MQTT broker
  • An MQTT to HomeKit bridge

This project was started so that a collection of $platform-to-MQTT bridges could be created or adapted that announce the devices they have in a similar enough fashion that we can automatically generate HomeKit accessories from it. Though the aim for now is HomeKit the metadata published should be enough to also be able to create bridges for other platforms, like SmartThings.

Installation

Using Go 1.15+ with modules support you can:

  • go install github.com/hemtjanst/hemtjanst

Development

Using Go 1.15+ with modules support:

  • git clone this repo or your fork and cd into it
  • go mod download

Usage

Once you've go installed the project a binary will be in your $GOPATH/bin. If you do not have explicitly set a $GOPATH environment variable it defaults to $HOME/go. Ensure to add $GOPATH/bin to your $PATH or use the full path to the binary.

By default it will connect to an MQTT broker on localhost:1883 and expose a HomeKit bridge on port 12345 with pairing pin-code 01020304.

Pass a --help for all available options.

Specification

Discovery

In order to not have to continuously scan for new devices, or to subscribe to every event, a discovery mechanism has to be implemented.

A discover topic with retain set must exist. Any device that joins the network must subscribe to discover. Since the retain bit is set they will receive the discovery request and must now announce themselves to the rest of the network. If someone then wants to initiate a full discovery all they need to do is publish again to discover (with the retain bit set).

An announce is done by publishing to the announce/YOUR NAME topic with persistence. The body of the message must be the meta content for the entity that joined. The topic layout is entirely arbitrary and so is the naming of the device. Anyone interested in knowing about devices now simply subscribes to announce/# and gets to know any device that joins.

Please note, the topic of the device is used to generate a unique identifier for this device, so if you change it it'll be like you removed the existing device and added a new one.

Whenever a device leaves it publishes its "root" topic to the leave topic. Similarly to announce this allows other clients to cancel their subscriptions if they were explicitly wathcing that device or take any other ation.

Last Will and Testament

MQTT includes a Last Will And Testament feature that will cause the broker to publish a message on a specific topic when the client is gone, gracefully or not.

If every device sets up its own MQTT client it can hence specify that as a last will and testament the broker should publish to leave with its original topic. This ensures that we can always properly clean up, even if the device falls of a cliff.

However, for bridged clients, lets say IKEA Trådfri lights that are published through a trådfri-to-mqtt broker, the bridge is the only MQTT client. Since we can't specify multiple actions in a last will and testament the bridge can still tell the broker to publish to a message to the topic, the content being a string representing a "leave ID". Every device that the bridge used to bridge must specify that same "leave ID" in its metadata so that a mapping can be maintained between "leave ID"s and devices for any cleanup purposes, such as no longer announcing this accessory to HomeKit.

Metadata

When a device receives a discover it must publish it's meta underneath announce/YOUR NAME as detailed in the discovery protocol.

Meta is a JSON object serialised as a string that contains any additional information needed for Hemtjänst to do its thing and generate HomeKit accessories.

As it currently stands the types and features in meta follow the exact names in the HomeKit specification. To support another platform like SmartThings a similar mapping would need to be created.

The meta document contains a number of required and optional entries. The required ones are: name, type, feature`. The rest is optional.

Optional keys are: topic, lastWillID.

The naming of the keys follows Google's JSON style guide and as such are in camelCase. However, ID is always fully uppercase and any chemical formula expressed in chemical symbols follows its relevant casing, so CO2, not Co2 for carbon dioxide.

name

A human friendly device name. Can be the same thing as the topic name or something else entirely. This will be the name of the accessory as HomeKit sees it so do pick something that makes sense and allows you to relatively easily identify the accessory.

type

The type of device, for example light or CO2Sensor. These map directly onto HomeKit services and are considered the "primary" service. There is currently no support for hidden, secondary or linked services.

You can find the supported devices here and how they map to HomeKit services.

feature

Every device needs at least one feature to be defined for it, the usual required characteristic (it can be more than one). Similarly to device the characteristics mapping contains a list of which feature names map to what HomeKit characteristics.

A feature is an object itself, which can be empty, in which case the defaults apply for the min, max and step value as defined in the HomeKit spec. In order to override them you can specify min, max and step keys and set the appropriate value. Do note that you cannot change the type of the value, so if the HomeKit specifies something as a uint8 it will be deserialised as a uint8.

Similarly, we expect that in order to get and set the value of a feature a "root topic"/<feature>/get and set topic exist that we can use. If those topics are named differently you have to specify a getTopic and a setTopic key that have the full path to a topic (so not necessarily nested under the "root" topic) that should be used instead.

topic

The "root" topic of this device, for example lightbulb/kitchen. This may also be the name that you publish to underneath announce, so announce/lightbulb/kitchen is entirely valid and will be used as the root topic unless the topic key is present.

If you publish as announce/lightbulb/kitchen but the topic is set to light/kitchen the topic in meta takes precedence.

lastWillID

The lastWillID only has to be set for bridged devices, so in cases where each device doesn't itself maintain a connection to the MQTT broker. When that is the case the Last Will And Testament should be set instead to publish the "root" topic name to the leave topic.

The lastWillID can be anything but needs to be unique. As such it's recommended to use a UUIDv4 for this.

Examples

The meta topic for a light that can just be turned on and off looks like this:

{
  "name": "kitchen stove light",
  "type": "light",
  "feature": {
    "on": {}
  }
}

Most smart lights however can also dim and usually set the colour temperature too, so it's more likely you'll want to publish something like this:

{
  "name": "living room light",
  "type": "light",
  "feature": {
    "on": {},
    "brightness": {},
    "colorTemperature": {
      "getTopic": "light/ground_floor/living_room/warmth/get",
      "setTopic": "light/ground_floor/living_room/warmth/set",
    },
  }
}

A contact sensor, something you might put on a window to detect if it is open or closed (as part of a security system for example) can be defined like this:

{
  "name": "bathroom window",
  "type": "contactSensor",
  "feature": {
   "contactSensorState": {}
  },
  "lastWillID": "f56ad37c-aa0f-45f4-8e92-f9a6dba39d84"
}

tradfri-mqtt's People

Contributors

benochsson avatar bonan avatar cipher2k avatar daenney avatar dependabot[bot] avatar rjbez17 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tradfri-mqtt's Issues

tradfri-cmd for getting moods

Hello,
thank you for this great library I just wanted to know if there is a tradfri-cmd to explicitly receive all available moods? If so, how ist the url?
Thanks in advance,
Regards

oberserving all possible topics and debugging

Hi,

whats about the following changes?

a) observing all possible "topics"; you get the list when get the following url from the gateway: cmd {"method":"get","url":".well-known/core","id":"well-known","replyTopic":"ikea/response"}; publish the cmd and read the respone. For myself it Looks like this:
Format 40 --> link list
all items with obs set can be observed:
{"id":"well-known","code":"2.05","format":40,"payload":"<//15006>;ct=0;obs,<//15001>;ct=0;obs,<//15004>;ct=0;obs,<//15004/add>;ct=0,<//15004/remove>;ct=0,<//15010>;ct=0;obs,<//15005>;ct=0;obs,<//15011/15012>;ct=0;obs,<//15011/9034>;ct=0,<//15011/9030>;ct=0,<//15011/9031>;ct=0,<//15011/9102>;ct=0,<//15011/9094>;ct=0;obs,<//15011/9095>;ct=0;obs,<//15011/9104>;ct=0;obs,<//15004/161295>;ct=0;obs,<//15005/161295>;ct=0;obs,<//15005/146016/226828>;ct=0;obs,<//15005/161303/226835>;ct=0;obs,<//15005/161303/226836>;ct=0;obs,<//15005/161303/226837>;ct=0;obs,<//15004/146016>;ct=0;obs,<//15005/146016>;ct=0;obs,<//15001/65557>;ct=0;obs,<//15001/65558>;ct=0;obs,<//15001/65542>;ct=0;obs,<//15001/65538>;ct=0;obs,<//15001/65551>;ct=0;obs,<//15001/65552>;ct=0;obs,<//15001/65560>;ct=0;obs,<//15001/65540>;ct=0;obs,<//15001/65554>;ct=0;obs,<//15001/65539>;ct=0;obs,<//15001/65548>;ct=0;obs,<//15001/65537>;ct=0;obs,<//15001/65550>;ct=0;obs,<//15001/65543>;ct=0;obs,<//15001/65541>;ct=0;obs,<//15001/65549>;ct=0;obs,<//15005/161295/211896>;ct=0;obs,<//15005/161295/224865>;ct=0;obs,<//15005/161295/204477>;ct=0;obs,<//15004/161303>;ct=0;obs,<//15005/161303>;ct=0;obs,<//15005/161304/226838>;ct=0;obs,<//15005/161304/226839>;ct=0;obs,<//15005/161304/226840>;ct=0;obs,<//15004/161304>;ct=0;obs,<//15005/161304>;ct=0;obs,<//15005/146016/212837>;ct=0;obs,<//15005/146016/226810>;ct=0;obs,<//15005/146016/212663>;ct=0;obs,<//15005/146016/202403>;ct=0;obs,<//15004/161299>;ct=0;obs,<//15005/161299>;ct=0;obs,<//15005/161305/226841>;ct=0;obs,<//15005/161305/226842>;ct=0;obs,<//15005/161305/226843>;ct=0;obs,<//15004/161305>;ct=0;obs,<//15005/161305>;ct=0;obs,<//15005/161299/226822>;ct=0;obs,<//15005/161299/226823>;ct=0;obs,<//15005/161299/226824>;ct=0;obs,<//15011/9063>;ct=0,<//15005/146016/226844>;ct=0;obs,<//15010/313073>;ct=0;obs"}

b) send debug Information into topic debug?

Kind regards

Ralf

The DTLS handshake timeout error returned

See reaction of @olem10 in last closed issue. The fix in the last build worked for me, but this error shows again since the last Tradfri update:. Hub software version is 1.15.55. Hope there's a fix for this.

Error discovering Trådfri endpoints Error: The DTLS handshake timed out
at normalizeReason (/app/node_modules/node-coap-client/build/lib/DeferredPromise.js:6:16)
at Promise.rej [as reject] (/app/node_modules/node-coap-client/build/lib/DeferredPromise.js:14:34)
at Socket.onError (/app/node_modules/node-coap-client/build/CoapClient.js:1012:29)
at Object.onceWrapper (node:events:514:26)
at Socket.emit (node:events:394:28)
at Socket.killConnection (/app/node_modules/node-dtls-client/build/dtls.js:227:22)
at Socket.expectHandshake (/app/node_modules/node-dtls-client/build/dtls.js:144:22)
at Timeout. (/app/node_modules/node-dtls-client/build/dtls.js:102:61)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)

Originally posted by @Arnootjoo in #15 (comment)

Error: Connection refused: Not authorized

Hi, I'm having an issue running tradfri-mqtt on a RPi -

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: Connection refused: Not authorized
    at MqttClient._handleConnack (/usr/lib/node_modules/tradfri-mqtt/node_modules/mqtt/lib/client.js:920:15)
    at MqttClient._handlePacket (/usr/lib/node_modules/tradfri-mqtt/node_modules/mqtt/lib/client.js:350:12)
    at work (/usr/lib/node_modules/tradfri-mqtt/node_modules/mqtt/lib/client.js:292:12)
    at Writable.writable._write (/usr/lib/node_modules/tradfri-mqtt/node_modules/mqtt/lib/client.js:302:5)
    at doWrite (/usr/lib/node_modules/tradfri-mqtt/node_modules/readable-stream/lib/_stream_writable.js:428:64)
    at writeOrBuffer (/usr/lib/node_modules/tradfri-mqtt/node_modules/readable-stream/lib/_stream_writable.js:417:5)
    at Writable.write (/usr/lib/node_modules/tradfri-mqtt/node_modules/readable-stream/lib/_stream_writable.js:334:11)
    at Socket.ondata (_stream_readable.js:558:20)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)

Any ideas?

Possibility to control (activate) scenes?

Is there a possibility to activate the scenes created in the Tradfri app through tradfri-mqtt?

They are under mqtt-topic "tradfri-raw/15005". I have an example from my home "tradfri-raw/15005/131073/196608". This turns off all lighting in one room (group).

[NFR] Friendly topic and payload

Thnx for releasing v0.0.5, it works really well.
I'm wondering if I could drop a New Feature Request here.

It would be really handy if we can subscribe and publish to the same endpoint where the endpoint contains parsed attributes.

For example if I have a group called "outside" with 2 lights (garden, front door)

Subscribe to: /tradfri/groups/outside 
An update gives:
{
   brightness  : 0, // [0..254 ID 5851]
   state: 0 // [0/1, ID 5850]
}
Publish to: /tradfri/groups/outside
Payload:
{
   brightness  : 200,
   state: 1
}
Subscribe to: /tradfri/lights/garden 
An update gives:
{
   brightness  : 0, // [0..254 ID 5851]
   state: 0 // [0/1, ID 5850]
}
etc...

I found a list of attributes here
Mqtt 3.1. can handle UTF-8 characters so using names in the topic should be a problem.
One issue could be that the group or light is not unique in that case both groups or light should be triggered.

Authentication rejected: The DTLS handshake timed out since latest update of Gateway

Hi,

I am running into this issue now since the latest update of Tradfri Gateway:

Authentication rejected Error: The DTLS handshake timed out at normalizeReason (/usr/local/lib/node_modules/tradfri-mqtt/node_modules/node-coap-client/build/lib/DeferredPromise.js:6:16) at Promise.rej [as reject] (/usr/local/lib/node_modules/tradfri-mqtt/node_modules/node-coap-client/build/lib/DeferredPromise.js:14:34) at Socket.onError (/usr/local/lib/node_modules/tradfri-mqtt/node_modules/node-coap-client/build/CoapClient.js:1003:33) at Object.onceWrapper (events.js:422:26) at Socket.emit (events.js:315:20) at Socket.killConnection (/usr/local/lib/node_modules/tradfri-mqtt/node_modules/node-dtls-client/build/dtls.js:221:22) at Socket.expectHandshake (/usr/local/lib/node_modules/tradfri-mqtt/node_modules/node-dtls-client/build/dtls.js:138:22) at Timeout.<anonymous> (/usr/local/lib/node_modules/tradfri-mqtt/node_modules/node-dtls-client/build/dtls.js:96:61) at listOnTimeout (internal/timers.js:554:17) at processTimers (internal/timers.js:497:7)

I am not sure if it is related with the firmware or just a coincidence. But it worked for quite a few weeks and today I cannot control tradfri via MQTT anymore. IKEA app access works fine.

Unable to control a device.

I have tradfri-mqtt installed and can see messages related to my Ikea devices in an MQTT Explorer as well as a HomeSeer software plugin. I am using paho MQTT broker.
I want to send a simple On or Off command to an Ikea Control socket.
It appears as; tradfri-raw/15001/65541:3312:01:5850. 5850 changes between 1 and 0 when I control the device via the Ikea app.
The command I have tried is; tradfri-cmd={ "method": "put", "url": "15001/65541", "replyTopic": "tradfri-reply/15001/65541", "payload": { "5850": 1} }
I have also tried a number of variations to this. I see a reaction in my MQTT Explorer but the socket does not turn on or off.
Any suggestions as to the format of the command would be gratefully accepted.
Cheers
Ian

Add Arm support

Would it possible to add an arm image to the docker hub so we can run it on for example a Raspberry Pi?

Cannot pull the tradfri-mqtt image into docker

When I try to pull the tradfri-mqtt image in to my docker instance I get an error. I use the following command:

docker pull ghcr.io/hemtjanst/tradfri-mqtt

Next I get the following output:

Using default tag: latest
Error response from daemon: manifest unknown

It doesn't make any difference when I define a tag as v0.1.4 for example. I then also the get: manifest unknown. What am I doing?wrong?

arm Cannot find module 'node-aead-crypto'

docker run -d --name tradfri-mqtt --volume /srv/tradfri/:/data/ --env TRADFRI_GATEWAY=192.168.1.100 --env TRADFRI_PSK=secret --env MQTT_ADDRESS=tcp://mosquitto:1883 hemtjanst/tradfri-mqtt:arm7

module.js:557
    throw err;
    ^

Error: Cannot find module 'node-aead-crypto'
    at Function.Module._resolveFilename (module.js:555:15)
    at Function.Module._load (module.js:482:25)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/app/node_modules/node-dtls-client/build/lib/AEADCrypto.js:54:47)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)

Add topic to ENV

Thank you for this project.
I would like to change the topic (currently it's tradfri-raw)
Would it possible to add a variable to set the topic where to publish to?
For example
MQTT_ADDRESS=tradfri

How to control curtain?

I have tried to control a curtain in a group the same way as a dimmers in a group would be controlled. But havent succeded. Is it possible?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.