170 lines
4.6 KiB
Go
170 lines
4.6 KiB
Go
package devices
|
|
|
|
import (
|
|
"app/datastore"
|
|
"app/mqtt"
|
|
"app/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)
|
|
}
|