Giter VIP home page Giter VIP logo

hemtjanst'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"
}

hemtjanst's People

Contributors

benochsson avatar bonan avatar daenney avatar dependabot[bot] avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

bonan beho1der

hemtjanst's Issues

light Switches and bulbs

great project

i am working on adding touch light switches that can also be controlled over mqtt.
This allows humans to use them but also the house automation.
They work over wifi, but also mqtt.

Sonoff hardware light switches
Mqtt tasmoto code: https://github.com/arendst/Sonoff-Tasmota

Upload firmware: https://github.com/arendst/Sonoff-Tasmota/wiki/Upload
No hardware soldering needed !

https://github.com/stefanwichmann/kelvin
Adjust diurnal ligths

LED bulbs
http://sonoff.itead.cc/en/products/residential/sonoff-b1
15 euro :)

Use CBOR instead of JSON

The Concise Binary Objet Representation is an IETF standard unofficially part of the CoRE set and is meant to handle object encoding in constrained environments (think IoT). This seems like an ideal candidate to replace our current JSON usage with. Libraries exist for all languages we currently have code in.

The go-codec library supports CBOR out of the box so it would mostly changing the json:"" struct tags to codec:"" ones and giving it a cbor encoder and decoder. Using CDDL we could also write a spec for what the data should look like and validate against it, which could be rather helpful.

Resubscribe after a reconnect to the broker

When we reconnect to the broker due to network weather we don't resubscribe to all the devices' get and set topics which causes any commands to essentially get lost.

The current workaround is to simply restart.

Integrate with Google Home

There's apparently documentation on how to create a "Smart Home App" so that it's possible to integrate with Google Home (essentially allowing to remote control things like lights etc.).

It's a bit more complicated than HomeKit since we have to deal with Oauth2, exposing the service to the internet etc. but it looks doable.

The docs are here: https://developers.google.com/actions/smarthome/. The docs are a bit of a mess, for example the light schema also includes the outlet and switch device types but no traits are specified for the switch or the outlet. It's not clear that they're actively working on improving the docs and expanding device support, but here's a mapping of the current state of affairs:

HomeKit service Google Home action/device type
Lightbulb action.devices.types.LIGHT
Switch action.devices.types.SWITCH
Outlet action.devices.types.OUTLET
HomeKit Characteristic Google Home action/trait
On action.devices.traits.OnOff
Brightness action.devices.traits.Brightness
Hue action.devices.traits.ColorSpectrum
Saturation ???
Color Temperature action.devices.traits.ColorTemperature
Outlet in use ???

Unfortunately it seems that once we have built this "app" it needs to be submitted for review to Google and so on. It seems unlikely they would accept it as it seems mostly geared towards partner integrations and expects to be going through the partner "cloud", not to talk directly to tinkerer's home setups. I suppose it's possible for everyone to deploy this app as a developer but it basically means everyone that wants to use this needs to be a developer with Google, deploy the code etc. It's clearly not designed to just toy around with and contrary to HomeKit requires to go through Google's cloud.

Install fails?

Found some instructions and got further with the install, however now I get this:

github.com/hemtjanst/hemtjanst/homekit/util
../src/github.com/hemtjanst/hemtjanst/homekit/util/accessory.go:71:10: undefined: accessory.TypeHumidifer
github.com/hemtjanst/hemtjanst/messaging/flagmqtt
../src/github.com/hemtjanst/hemtjanst/messaging/flagmqtt/setup.go:108:19: multiple-value uuid.NewV4() in single-value context

Is anyone still paying attention to this project?

Change MQTT discover/announce flow

Current behavior

  1. Bridge sends a persistent message to discover on startup
  2. Clients subscribe to discover on startup
  3. Clients publish their meta to <baseTopic>/meta on startup
  4. Clients sends their own base topic name to announce every time a discover message is received
  5. Bridge is subscribed to announce, when receiving a message, <payload>/meta is subscribed to

Suggestion

  1. Does not change
  2. Does not change
  3. On receiving a message from discover, clients publish their meta with persistence to announce/<baseTopic>
  4. Bridge is subscribed to announce/#, any messages received are parsed as device metadata

Benefits

  • The bridge will get information about all previous devices upon startup, even if they're not currently available. MQTT server acts as a database, instead of the bridge having to store all seen devices
  • Any devices discovered before discover is sent can be marked as offline until receiving a new update
  • One less subscription for the bridge per device
  • A client can be permanently removed by publishing an empty payload with persistence to its announce-topic

Drawbacks

  • Breaks all current implementations
  • Clients have to compile and send meta for every discovery, potentially requiring more resources and bandwidth.
  • If multiple bridges are running, all of them have to parse and compare received meta for all devices every time another bridge makes a discover request.

Add RGB color support

To simplify implementations, we should add the feature rgb (which will be converted internally to the features brightness, saturation and hue) for the lightbulb device type.

RGB lightbulbs could be published with the meta:

{
  "name": "<name>",
  "type": "lightbulb",
  "feature": {
    "on": {},
    "rgb": {}
  }
}

The rgb feature would be mutually exclusive with brightness, hue and saturation

The value could either be r,g,b in decimal (0-255) or rrggbb in hex (00-FF), needs some discussion

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.