gohmekit package

import "code.pfad.fr/gohmekit"

package gohmekit implements the HomeKit Accessory Protocol (hap).

See the Example to get started.

This library wouldn't have been possible without the amazing open-source work of Matthias Hochgatterer:

https://github.com/brutella/hc

https://github.com/brutella/hap

Example

package main

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"strconv"
	"time"

	"code.pfad.fr/gohmekit/contrib/shelly"
	"code.pfad.fr/gohmekit/discovery"
	"code.pfad.fr/gohmekit/hapip"
	"code.pfad.fr/gohmekit/hapip/characteristic/service/accessory"
	"code.pfad.fr/gohmekit/pairing"
	"code.pfad.fr/gohmekit/storage"
)

func main() {
	// store the state in a json file (secret key, pin, paired devices...)
	jsonFile, err := storage.NewJSONFile("db.json")
	if err != nil {
		fmt.Printf("could not get json file storage: %v\n", err)
		return
	}

	shellyPlug, _ := shelly.NewPlug("http://localhost/")

	// create an accessory handler.
	port := 51821 // same port used by homebridge (can be changed)
	accessoryServer := hapip.PrepareServer(
		&http.Server{Addr: ":" + strconv.Itoa(port)},
		map[uint16]hapip.Accessory{
			// If multiple accessories are provided, the number 1 must be a bridge
			// (which is required per the spec to have the service.AccessoryInformation).
			1: accessory.Basic{
				Name: "Gohmebridge",
				Identify: func(bool) error {
					fmt.Println("TODO: blink a led or make a tone (not paired yet)")
					return errors.New("identify is not implemented")
				},

				HAPProtocolVersion: "1.1.0",
			},
			// bridged devices
			2: shellyPlug,
		},
	)

	// pairing server will manage connection encryption
	// and handle the decrypted requests to the given accessory server.
	pairingServer := pairing.NewServer(accessoryServer, jsonFile, jsonFile,
		pairing.WithIdentify(func() {
			fmt.Println("TODO: blink a led or make a tone (accessory is paired)")
		}),
	)

	// announce the accessory as a bridge via bonjour (zeroconf)
	stopDiscovery, err := jsonFile.DiscoveryService(
		"gohmebridge",
		port,
		discovery.Bridge,
	).Announce(context.Background())
	if err != nil {
		fmt.Printf("could not start announcing: %v\n", err)
		return
	}
	defer stopDiscovery()

	// start serving
	go pairingServer.ListenAndServe() //nolint:errcheck

	time.Sleep(10 * time.Millisecond)

}

Files

doc.go

Directories

cmd/generate

contrib/camera

contrib/fake

contrib/fritzbox

contrib/shelly

discovery

hapip

pairing

storage

tlv8

Forge

https://codeberg.org/pfad.fr/gohmekit

git clone

https://codeberg.org/pfad.fr/gohmekit
git@codeberg.org:pfad.fr/gohmekit