2023-11-28 04:40:32 +00:00
|
|
|
package nats
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
ha "code.jhot.me/jhot/hats/pkg/homeassistant"
|
2024-06-17 15:12:21 +00:00
|
|
|
"github.com/nats-io/nats.go"
|
2023-11-28 04:40:32 +00:00
|
|
|
)
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
type TopicType string
|
|
|
|
|
|
|
|
const StateTopicType TopicType = "states"
|
|
|
|
const TimerTopicType TopicType = "timers"
|
|
|
|
const ScheduleTopicType TopicType = "schedules"
|
|
|
|
const CommandTopicType TopicType = "command"
|
|
|
|
const NfcTopicType TopicType = "nfc"
|
|
|
|
const ZhaTopicType TopicType = "zha"
|
|
|
|
const ZwaveTopicType TopicType = "zwave"
|
|
|
|
const ZwaveSceneTopicType TopicType = "zwave-scene"
|
|
|
|
|
|
|
|
func (t TopicType) GetTopic(id string) string {
|
|
|
|
switch t {
|
|
|
|
case StateTopicType:
|
|
|
|
return fmt.Sprintf("homeassistant.%s.%s.>", t, id)
|
|
|
|
case TimerTopicType:
|
|
|
|
return fmt.Sprintf("homeassistant.%s.%s.finished", t, id)
|
|
|
|
case ScheduleTopicType, CommandTopicType:
|
|
|
|
return fmt.Sprintf("%s.%s", t, id)
|
|
|
|
case NfcTopicType, ZhaTopicType, ZwaveTopicType, ZwaveSceneTopicType:
|
|
|
|
return fmt.Sprintf("homeassistant.%s.%s", t, id)
|
|
|
|
}
|
|
|
|
return ""
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
func (n *NatsConnection) addSub(topic string, cb nats.MsgHandler) (*nats.Subscription, error) {
|
|
|
|
return n.Conn.Subscribe(topic, cb)
|
2023-11-28 16:47:11 +00:00
|
|
|
}
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
func parseEvent(msg *nats.Msg, sendResponse bool) (ha.EventData, error) {
|
|
|
|
if sendResponse {
|
2023-12-07 19:39:48 +00:00
|
|
|
go msg.Respond([]byte("got it"))
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
2024-06-17 15:12:21 +00:00
|
|
|
var data ha.EventData
|
|
|
|
err := json.Unmarshal(msg.Data, &data)
|
|
|
|
return data, err
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
func (n *NatsConnection) AddEventSub(t TopicType, entityId string, handler func(ha.EventData) error) (*nats.Subscription, error) {
|
|
|
|
if t == "" || entityId == "" {
|
|
|
|
panic("TopicType and entityId cannot be empty")
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
topic := t.GetTopic(entityId)
|
|
|
|
l := n.logger.With("topic", topic, "entity_id", entityId)
|
2023-11-28 04:40:32 +00:00
|
|
|
l.Debug("Subscribing to topic")
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
return n.addSub(topic, func(msg *nats.Msg) {
|
|
|
|
data, err := parseEvent(msg, true)
|
2023-11-28 04:40:32 +00:00
|
|
|
if err != nil {
|
|
|
|
l.Error("Error parsing message", "error", err)
|
2024-06-17 15:12:21 +00:00
|
|
|
return
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
2024-06-17 15:12:21 +00:00
|
|
|
l.Debug(fmt.Sprintf("%s data event fired", t))
|
2023-11-28 04:40:32 +00:00
|
|
|
err = handler(data)
|
|
|
|
if err != nil {
|
2024-06-17 15:12:21 +00:00
|
|
|
l.Error(fmt.Sprintf("Error handling %s event", t), "error", err)
|
|
|
|
return
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
2024-06-17 15:12:21 +00:00
|
|
|
})
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
func (n *NatsConnection) AddStateSub(t TopicType, entityId string, handler func(ha.StateData) error) (*nats.Subscription, error) {
|
|
|
|
if t == "" || entityId == "" {
|
|
|
|
panic("TopicType and entityId cannot be empty")
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
topic := t.GetTopic(entityId)
|
|
|
|
l := n.logger.With("topic", topic, "entity_id", entityId)
|
|
|
|
l.Debug("Subscribing to topic")
|
2023-11-28 04:40:32 +00:00
|
|
|
|
2024-06-17 15:12:21 +00:00
|
|
|
return n.addSub(topic, func(msg *nats.Msg) {
|
|
|
|
data, err := parseEvent(msg, true)
|
2023-11-28 04:40:32 +00:00
|
|
|
if err != nil {
|
2024-06-17 15:12:21 +00:00
|
|
|
l.Error("Error parsing message", "error", err, "message", string(msg.Data))
|
|
|
|
return
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
2024-06-17 15:12:21 +00:00
|
|
|
l.Debug(fmt.Sprintf("%s state event fired", t), "newState", data.NewState.State)
|
|
|
|
err = handler(data.NewState)
|
2023-11-28 04:40:32 +00:00
|
|
|
if err != nil {
|
2024-06-17 15:12:21 +00:00
|
|
|
l.Error(fmt.Sprintf("Error handling %s event", t), "error", err)
|
|
|
|
return
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|
2024-06-17 15:12:21 +00:00
|
|
|
})
|
2023-11-28 04:40:32 +00:00
|
|
|
}
|