1
0
Fork 0
Home Assistant + NATS = HATS
 
 
Go to file
Jordan Hotmann ffd1ff689b
get state logging
2023-11-17 12:15:15 -07:00
internal get state logging 2023-11-17 12:15:15 -07:00
pkg API token auth, readme updates 2023-11-17 11:24:12 -07:00
.gitignore Initial commit 2023-10-12 11:23:35 -06:00
Dockerfile Initial commit 2023-10-12 11:23:35 -06:00
README.md API token auth, readme updates 2023-11-17 11:24:12 -07:00
go.mod HATS home and status pages 2023-11-17 11:43:50 -07:00
go.sum HATS home and status pages 2023-11-17 11:43:50 -07:00
main.go HATS home and status pages 2023-11-17 11:43:50 -07:00

README.md

HATS

Home Assistant + NATS = HATS

Features

Example Client

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"
	"os"
	"os/signal"
	"syscall"

	"code.jhot.me/jhot/hats/pkg/client"
	"code.jhot.me/jhot/hats/pkg/config"
	ha "code.jhot.me/jhot/hats/pkg/homeassistant"
	n "code.jhot.me/jhot/hats/pkg/nats"
	"github.com/nats-io/nats.go"
)

var (
	logger     *slog.Logger
	hatsClient *client.HatsClient
	natsClient *n.NatsConnection
)

func main() {
	cfg := config.FromEnvironment()
	logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
		Level: cfg.GetLogLevel(),
	}))

	hatsClient = client.NewHatsClient(cfg.GetHatsBaseUrl(), cfg.HatsToken)
	natsClient = n.DefaultNatsConnection().WithJetstream(false).WithHostName(cfg.NatsHost).WithPort(cfg.NatsPort).WithConnectionOption(nats.Name(cfg.NatsClientName))
	defer natsClient.Close()

	go GenericStateListener("sun.sun", SunHandler)

	sigch := make(chan os.Signal, 1)
	signal.Notify(sigch, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
	<-sigch
	logger.Info("SIGTERM received")
}

func SunHandler(state ha.StateData) error {
	return hatsClient.CallService("light.some_light", ha.Services.TurnOn)
}

func GenericStateListener(entityId string, handler func(ha.StateData) error) {
	topic := fmt.Sprintf("homeassistant.states.%s.*", entityId)
	l := logger.With("topic", topic, "entity_id", entityId)
	l.Debug("Subscribing to topic")
	sub, ch, err := natsClient.Subscribe(topic)
	if err != nil {
		l.Error("Error subscribing to topic", "error", err)
		return
	}

	defer sub.Unsubscribe()

	for msg := range ch {
		msg.Ack()
		var data ha.EventData
		err = json.Unmarshal(msg.Data, &data)
		if err != nil {
			l.Error("Error parsing message", "error", err)
			continue
		}
		l.Debug("Event state " + data.NewState.State)
		err = handler(data.NewState)
		if err != nil {
			l.Error("Error handling state event", "error", err)
			continue
		}
	}
}