This commit is contained in:
Mats Tornberg
2025-11-22 17:35:24 +01:00
parent 0596fe60fa
commit 87660c7d1d
12 changed files with 34 additions and 39 deletions

169
pkg/devices/manager.go Normal file
View File

@@ -0,0 +1,169 @@
package devices
import (
"app/pkg/datastore"
"app/pkg/mqtt"
"app/pkg/telldus"
"fmt"
"log"
"strconv"
"strings"
"sync"
"time"
)
// EventManager handles telldus events and callbacks
type EventManager struct {
store *datastore.DataStore
mqttClient *mqtt.Client
rawEvents []datastore.RawEvent
sensorEvents []datastore.SensorEvent
mu sync.Mutex
maxEvents int
}
// NewEventManager creates a new event manager
func NewEventManager(store *datastore.DataStore, mqttClient *mqtt.Client, maxEvents int) *EventManager {
return &EventManager{
store: store,
mqttClient: mqttClient,
maxEvents: maxEvents,
}
}
// GetRawEvents returns a copy of raw events
func (em *EventManager) GetRawEvents() []datastore.RawEvent {
em.mu.Lock()
defer em.mu.Unlock()
events := make([]datastore.RawEvent, len(em.rawEvents))
copy(events, em.rawEvents)
return events
}
// GetSensorEvents returns a copy of sensor events
func (em *EventManager) GetSensorEvents() []datastore.SensorEvent {
em.mu.Lock()
defer em.mu.Unlock()
events := make([]datastore.SensorEvent, len(em.sensorEvents))
copy(events, em.sensorEvents)
return events
}
// HandleDeviceEvent handles device state change events
func (em *EventManager) HandleDeviceEvent(deviceID, method int, data string, callbackID int) {
fmt.Printf("Device event: ID=%d, Method=%d, Data=%s\n", deviceID, method, data)
var state string
switch method {
case telldus.MethodTurnOn:
state = "ON"
case telldus.MethodTurnOff:
state = "OFF"
}
if state != "" {
em.mqttClient.PublishDeviceState(deviceID, state)
}
}
// HandleSensorEvent handles sensor data events
func (em *EventManager) HandleSensorEvent(protocol, model string, id, dataType int, value string, timestamp, callbackID int) {
fmt.Printf("Sensor event: Protocol=%s, Model=%s, ID=%d, Type=%d, Value=%s, Timestamp=%d\n",
protocol, model, id, dataType, value, timestamp)
// Publish to MQTT
em.mqttClient.PublishSensorValue(protocol, model, id, dataType, value)
// Store in history
em.mu.Lock()
em.sensorEvents = append(em.sensorEvents, datastore.SensorEvent{
Timestamp: time.Now(),
Protocol: protocol,
Model: model,
ID: id,
DataType: dataType,
Value: value,
})
if len(em.sensorEvents) > em.maxEvents {
em.sensorEvents = em.sensorEvents[1:]
}
em.mu.Unlock()
// Update last value in DB
if err := em.store.UpdateSensorValue(protocol, model, id, dataType, value); err != nil {
log.Printf("Error updating sensor %s %s %d: %v", protocol, model, id, err)
}
}
// HandleRawDeviceEvent handles raw device detection events
func (em *EventManager) HandleRawDeviceEvent(data string, controllerID, callbackID int) {
fmt.Printf("Raw device event: ControllerID=%d, Data=%s\n", controllerID, data)
// Parse data
fields := strings.Split(data, ";")
var class, protocol, model, deviceID string
for _, field := range fields {
kv := strings.SplitN(field, ":", 2)
if len(kv) == 2 {
key, val := kv[0], kv[1]
switch key {
case "class":
class = val
case "protocol":
protocol = val
case "model":
model = val
case "id":
deviceID = val
}
}
}
// Store in potential_devices
potentialDev := &datastore.PotentialDevice{
Class: class,
Protocol: protocol,
Model: model,
DeviceID: deviceID,
LastData: data,
LastSeen: time.Now().Unix(),
}
if err := em.store.UpsertPotentialDevice(potentialDev); err != nil {
log.Printf("Error storing potential device: %v", err)
}
// If sensor, ensure in sensors table
if class == "sensor" {
idInt, _ := strconv.Atoi(deviceID)
sensor := &datastore.Sensor{
Protocol: protocol,
Model: model,
ID: idInt,
Name: fmt.Sprintf("%s %s %s", protocol, model, deviceID),
TemperatureUniqueID: fmt.Sprintf("telldus_sensor_%s_%s_%s_temperature", protocol, model, deviceID),
HumidityUniqueID: fmt.Sprintf("telldus_sensor_%s_%s_%s_humidity", protocol, model, deviceID),
}
if err := em.store.UpsertSensor(sensor); err != nil {
log.Printf("Error inserting sensor from raw: %v", err)
}
}
// Log the raw event data
em.mu.Lock()
em.rawEvents = append(em.rawEvents, datastore.RawEvent{
Timestamp: time.Now(),
ControllerID: controllerID,
Data: data,
})
if len(em.rawEvents) > em.maxEvents {
em.rawEvents = em.rawEvents[1:]
}
em.mu.Unlock()
}
// RegisterCallbacks registers all event callbacks with telldus
func (em *EventManager) RegisterCallbacks() {
telldus.RegisterDeviceEvent(em.HandleDeviceEvent)
telldus.RegisterSensorEvent(em.HandleSensorEvent)
telldus.RegisterRawDeviceEvent(em.HandleRawDeviceEvent)
}