func (self *Thermostat) Event(ev *pubsub.Event) { now := ev.Timestamp.Local() // must use Local time, as schedule is in local switch ev.Topic { case "temp": // temperature device update device := services.Config.LookupDeviceName(ev) if dev, ok := self.Devices[device]; ok { temp, _ := ev.Fields["temp"].(float64) dev.Update(temp, now) self.Check(now) } case "house": // house state update state := ev.Fields["state"] self.Occupied = (state != "Empty") self.Check(now) case "command": if ev.Target() == "ch" { value, ok := ev.Fields["value"].(string) if ok { err := self.setParty(value, ev.Timestamp) if err == nil { self.Check(now) // TODO - response } else { // TODO - error response } } } } }
func sendAnswer(request *pubsub.Event, source string, answer Answer) { fields := pubsub.Fields{ "source": source, "target": request.StringField("source"), } if answer.Text != "" { fields["message"] = answer.Text } if answer.Json != nil { fields["json"] = answer.Json } remote := request.StringField("remote") if remote != "" { fields["remote"] = remote } topic := "alert" reply_to := request.StringField("reply_to") if reply_to != "" { topic = reply_to } response := pubsub.NewEvent(topic, fields) Publisher.Emit(response) }
// Translate command messages into rfxtrx packets func translateCommands(ev *pubsub.Event) (gorfxtrx.OutPacket, error) { device := ev.Device() command := ev.Command() if command != "off" && command != "on" { log.Println("Command not recognised:", command) return nil, nil } pids := services.Config.LookupDeviceProtocol(device) if len(pids) == 0 { log.Println("Device not found for:", device) return nil, nil } switch { case pids["homeeasy"] != "": return gorfxtrx.NewLightingHE(0x00, pids["homeeasy"], command) case pids["x10"] != "": return gorfxtrx.NewLightingX10(0x01, pids["x10"], command) } return nil, nil }
func writeToLogFile(ev *pubsub.Event) { name := ev.Topic device := services.Config.LookupDeviceName(ev) if device != "" { ev.Fields["device"] = device } p := path.Join(logDir, name) ensureDirectory(p) p = path.Join(p, "data.log") // reopen the log file each time, so that log rotation can happen in the // background. // TODO: could this be done more smartly by checking inode and only // reopening when it changes? fio, err := os.OpenFile(p, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660) defer fio.Close() if err != nil { log.Println("Couldn't write file:", err) return } fio.Write(ev.Bytes()) fio.WriteString("\n") }
// Find the device name func (self *Config) LookupDeviceName(ev *pubsub.Event) string { // silly question: is device set on the event if ev.Device() != "" { return ev.Device() } topic := ev.Topic source := ev.Source() // try: protocol.id if device, ok := self.Protocols[topic][source]; ok { return device } // fallback: topic.source // ignore dynamic topics (prefix _) if topic != "" && source != "" && !strings.HasPrefix(topic, "_") { return topic + "." + source } return "" }
// Emit an event func (pub *Publisher) Emit(ev *pubsub.Event) { // put all topics under gohome/ topic := "gohome/" + ev.Topic r := pub.client.Publish(MQTT.QOS_ONE, topic, ev.Bytes()) <-r }
func eventCommand(ev *pubsub.Event) { cam, ok := cameras[ev.Device()] if !ok { return } p, _ := ev.Fields["preset"].(float64) preset := int(p) switch ev.Fields["command"] { case "position": log.Printf("%s going to preset %d", ev.Device(), preset) cam.GotoPreset(preset) case "snapshot": log.Printf("%s taking snapshot", ev.Device()) go func() { if preset != 0 { log.Printf("Going to preset: %d", preset) cam.GotoPreset(preset) time.Sleep(GotoDelay) } filename, err := cam.Snapshot() if err != nil { log.Println("Error taking snapshot:", err) } else { log.Println("Snapshot:", filename) } }() case "video": timeout, ok := ev.Fields["timeout"].(float64) if !ok { timeout = 15 } duration := time.Duration(timeout) * time.Second log.Printf("%s recording video for %s", ev.Device(), duration) go func() { if preset != 0 { log.Printf("Going to preset: %d", preset) cam.GotoPreset(preset) time.Sleep(GotoDelay) } if ir, ok := ev.Fields["ir"].(bool); ok { err := cam.Ir(ir) if err != nil { log.Println("Error setting ir:", err) } } filename, err := cam.Video(duration) if err != nil { log.Println("Error taking video:", err) } else { log.Println("Video:", filename) } }() case "ir": on, _ := ev.Fields["on"].(bool) log.Printf("%s infra-red turned %s", ev.Device(), on) cam.Ir(on) case "detection": on, _ := ev.Fields["on"].(bool) log.Printf("%s detection %s", ev.Device(), on) cam.Detect(on) } }