package devices import ( "fmt" "log" "strconv" "strings" "sync" "time" "git.k7n.net/mats/go-telldus/pkg/datastore" "git.k7n.net/mats/go-telldus/pkg/mqtt" "git.k7n.net/mats/go-telldus/pkg/telldus" ) // 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) }