1
0
Fork 0
hats/README.md

86 lines
3.1 KiB
Markdown
Raw Permalink Normal View History

2023-10-12 17:23:35 +00:00
# HATS
2023-11-17 18:24:12 +00:00
[Home Assistant](https://www.home-assistant.io/) + [NATS](https://nats.io/) = HATS
## Features
- Push Home Assistant websocket events to a NATS message queue
- Caching proxy for Home Assistant API
2023-11-30 20:53:23 +00:00
- Generic implementations for subscribing to NATS topics
2023-11-17 18:24:12 +00:00
- Clients for some application APIs (limited functionality)
- [Gokapi](https://github.com/Forceu/Gokapi)
- [ntfy](https://github.com/binwiederhier/ntfy)
- [qBittorrent](https://github.com/qbittorrent/qBittorrent)
- [Syncthing](https://github.com/syncthing/syncthing)
- [National Weather Service](https://www.weather.gov/)
2023-12-20 18:29:23 +00:00
- [Amcrest Cameras](https://amcrest.com/)
- [Infisical](https://infisical.com/)
2023-11-17 18:24:12 +00:00
## NATS Topics
- `homeassistant.states.{domain}.{entity}.{state}` - Home Assistant device state changes: [payload](https://www.home-assistant.io/docs/configuration/state_object/)
2023-11-20 23:59:37 +00:00
- `homeassistant.attributes.{domain}.{entity}.{state}` - When a device's attributes change but the state hasn't changed: [payload](https://www.home-assistant.io/docs/configuration/state_object/)
- `homeassistant.zha.{device IEEE}` - ZHA events: [payload](https://www.home-assistant.io/docs/configuration/state_object/)
2023-11-27 22:59:35 +00:00
- `homeassistant.zwave-scene.{device ID}` - ZwaveJS scene events: [payload](https://www.home-assistant.io/integrations/zwave_js/#scene-events-value-notification)
- `homeassistant.nfc.{tag ID}` - Home Assistant NFC tag scanned: [payload](https://www.home-assistant.io/docs/configuration/state_object/)
- `homeassistant.timer.{timer name}.finished` - Home Assistant timer finished: payload is simply `"finished"`
- `schedules.{schedule name}` - HATS schedule finished: payload is simply `"finished"`
- `command.{command name}` - Command called via HATS API: payload is a byte array of the HTTP Post body
2023-11-17 18:24:12 +00:00
## Example Client
```golang
package main
import (
"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"
2023-11-30 20:53:23 +00:00
"code.jhot.me/jhot/hats/pkg/nats"
n "github.com/nats-io/nats.go"
2023-11-17 18:24:12 +00:00
)
var (
logger *slog.Logger
hatsClient *client.HatsClient
2023-11-30 20:53:23 +00:00
natsClient *nats.NatsConnection
2023-11-17 18:24:12 +00:00
)
func main() {
cfg := config.FromEnvironment()
logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: cfg.GetLogLevel(),
}))
hatsClient = client.NewHatsClient(cfg.GetHatsBaseUrl(), cfg.HatsToken)
2023-11-30 20:53:23 +00:00
natsClient = nats.DefaultNatsConnection().WithJetstream(false).WithHostName(cfg.NatsHost).
WithPort(cfg.NatsPort).WithConnectionOption(n.Name(cfg.NatsClientName))
err := natsClient.Connect()
if err != nil {
panic(err)
}
2023-11-17 18:24:12 +00:00
defer natsClient.Close()
2023-11-30 20:53:23 +00:00
go natsClient.GenericStateSubscriber(logger, "sun.sun", SunHandler)
2023-11-17 18:24:12 +00:00
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 {
2023-11-30 20:53:23 +00:00
var service string
if up := ha.StateToBool(state.State); up {
service = ha.Services.TurnOff
} else {
service = ha.Services.TurnOn
2023-11-17 18:24:12 +00:00
}
2023-11-30 20:53:23 +00:00
return hatsClient.CallService("light.some_light", service)
2023-11-17 18:24:12 +00:00
}
```