Ejemplo n.º 1
0
func journalTailer() {
	cmd := exec.Command("journalctl", "--user-unit=gohome@*", "-f", "-n0", "-q", "--output=json")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Fatal(err)
	}
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}
	scanner := bufio.NewScanner(stdout)
	for scanner.Scan() {
		var data map[string]interface{}
		err := json.Unmarshal([]byte(scanner.Text()), &data)
		if err != nil {
			log.Println("Error decoding json:", err)
			continue
		}

		if message, ok := data["MESSAGE"].(string); ok {
			var source string
			if user_unit, ok := data["_SYSTEMD_USER_UNIT"].(string); ok {
				source = stripUnitName(user_unit)
			} else {
				source = "systemd"
			}
			fields := map[string]interface{}{
				"message": message,
				"source":  source,
			}
			ev := pubsub.NewEvent("log", fields)
			services.Publisher.Emit(ev)
		}
	}
}
Ejemplo n.º 2
0
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)
}
Ejemplo n.º 3
0
func ExampleLookupDeviceNameMissing() {
	config, _ := OpenRaw([]byte(yml))
	fields := pubsub.Fields{"source": "a02"}
	ev := pubsub.NewEvent("x10", fields)
	fmt.Println(config.LookupDeviceName(ev))
	// Output:
	// x10.a02
}
Ejemplo n.º 4
0
func (self *Thermostat) Heartbeat(now time.Time) {
	self.Check(now)
	// emit event for datalogging
	ev := pubsub.NewEvent("heating", pubsub.Fields{"source": "ch", "heating": self.State})
	self.Publisher.Emit(ev)
	// repeat current state
	self.Command()
	//log.Println(self.ShortStatus(now))
}
Ejemplo n.º 5
0
func emit(code string) {
	log.Println("Publishing:", code)
	fields := map[string]interface{}{
		"origin":  "rfid",
		"command": "tag",
		"source":  code,
	}
	event := pubsub.NewEvent("rfid", fields)
	services.Publisher.Emit(event)
}
Ejemplo n.º 6
0
func SendQuery(query, source, remote, reply_to string) {
	fields := pubsub.Fields{
		"source":   source,
		"query":    query,
		"remote":   remote,
		"reply_to": reply_to,
	}
	ev := pubsub.NewEvent("query", fields)
	Publisher.Emit(ev)
}
Ejemplo n.º 7
0
func (self EventAction) Video(device string, preset int64, secs float64, ir bool) {
	log.Printf("Video: %s at %d for %.1fs (ir: %v)", device, preset, secs, ir)
	fields := pubsub.Fields{
		"device":  device,
		"command": "video",
		"timeout": secs,
		"preset":  preset,
		"ir":      ir,
	}
	ev := pubsub.NewEvent("command", fields)
	services.Publisher.Emit(ev)
}
Ejemplo n.º 8
0
func SendAlert(message string, target string, subtopic string, interval int64) {
	fields := pubsub.Fields{
		"message": message,
		"target":  target,
	}
	if subtopic != "" {
		fields["subtopic"] = subtopic
		fields["interval"] = interval
	}
	ev := pubsub.NewEvent("alert", fields)
	Publisher.Emit(ev)
}
Ejemplo n.º 9
0
// Run the service
func (self *Service) Run() error {
	loc := Location{
		Latitude:  services.Config.Earth.Latitude,
		Longitude: services.Config.Earth.Longitude,
	}
	for tev := range eventChannel(loc) {
		ev := pubsub.NewEvent("earth",
			pubsub.Fields{"command": tev.Event, "source": "home"})
		services.Publisher.Emit(ev)
	}
	return nil
}
Ejemplo n.º 10
0
func (self *Service) queryTag(q services.Question) string {
	tagName := strings.ToLower(q.Args)
	if _, ok := services.Config.Devices["rfid."+tagName]; !ok {
		return fmt.Sprintf("Tag %s not found", tagName)
	}
	fields := map[string]interface{}{
		"source":  tagName,
		"command": "tag",
	}
	ev := pubsub.NewEvent("person", fields)
	services.Publisher.Emit(ev)
	return fmt.Sprintf("Emitted tag for %s", tagName)
}
Ejemplo n.º 11
0
func (self EventAction) StartTimer(name string, d int64) {
	// log.Printf("Starting timer: %s for %ds", name, d)
	duration := time.Duration(d) * time.Second
	if timer, ok := self.service.timers[name]; ok {
		// cancel any existing
		timer.Stop()
	}

	timer := time.AfterFunc(duration, func() {
		// emit timer event
		fields := map[string]interface{}{
			"source":  name,
			"command": "on",
		}
		ev := pubsub.NewEvent("timer", fields)
		services.Publisher.Emit(ev)
	})
	self.service.timers[name] = timer
}
Ejemplo n.º 12
0
func Heartbeat(id string) {
	started := time.Now()
	fields := pubsub.Fields{
		"pid":     os.Getpid(),
		"started": started.Format(time.RFC3339),
		"source":  id,
	}

	// wait 5 seconds before heartbeating - if the process dies very soon
	time.Sleep(time.Second * 5)

	for {
		uptime := int(time.Now().Sub(started).Seconds())
		fields["uptime"] = uptime
		ev := pubsub.NewEvent("heartbeat", fields)
		Publisher.Emit(ev)
		time.Sleep(time.Second * 60)
	}
}
Ejemplo n.º 13
0
func ExampleQuerySubscriber() {
	fields := pubsub.Fields{"query": "help"}
	query := pubsub.NewEvent("query", fields)
	li := dummy.Subscriber{
		Events: []*pubsub.Event{query},
	}
	Subscriber = &li
	em := dummy.Publisher{}
	Publisher = &em
	mock := MockService{
		queryHandlers: map[string]QueryHandler{"help": StaticHandler("squiggle")},
	}
	enabled = []Service{&mock}
	QuerySubscriber()
	fmt.Println(len(em.Events))
	fmt.Println(em.Events[0].StringField("message"))
	// Output:
	// 1
	// squiggle
}
Ejemplo n.º 14
0
func apiConfig(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query()
	path := q.Get("path")
	if path == "" {
		err := errors.New("path parameter required")
		errorResponse(w, err)
		return
	}

	// retrieve key from store
	value, err := services.Stor.Get(q.Get("path"))
	if err != nil {
		errorResponse(w, err)
		return
	}

	if r.Method == "GET" {
		w.Header().Add("Content-Type", "application/yaml; charset=utf-8")
		w.Write([]byte(value))
	} else if r.Method == "POST" {
		data, err := ioutil.ReadAll(r.Body)
		if err != nil {
			errorResponse(w, err)
			return
		}

		sout := string(data)
		if sout != value {
			// set store
			services.Stor.Set(path, sout)
			// emit event
			fields := pubsub.Fields{
				"path": path,
			}
			ev := pubsub.NewEvent("config", fields)
			services.Publisher.Emit(ev)
			log.Printf("%s changed, emitted config event", path)
		}
	}
}
Ejemplo n.º 15
0
// Run the service
func (service *Service) Run() error {
	addr, err := net.ResolveUDPAddr("udp", ":3865")
	if err != nil {
		return err
	}
	sock, err := net.ListenUDP("udp", addr)
	if err != nil {
		return err
	}
	var buf [1024]byte
	for {
		rlen, _, err := sock.ReadFromUDP(buf[0:])
		if err != nil {
			log.Fatal(err)
			continue
		}
		data := string(buf[:rlen])
		//log.Println("Received:", data)
		source, power := Process(data)
		if source != "" && power != "" {
			var command string
			switch power {
			case "1":
				command = "on"
			case "0":
				command = "off"
			}
			fields := map[string]interface{}{
				"origin":  "xpl",
				"command": command,
				"source":  source,
			}
			event := pubsub.NewEvent("xpl", fields)
			services.Publisher.Emit(event)
		}
	}
}
Ejemplo n.º 16
0
func translatePacket(packet gorfxtrx.Packet) *pubsub.Event {
	var ev *pubsub.Event
	switch p := packet.(type) {
	case *gorfxtrx.Status:
		// no event emitted
		protocols := strings.Join(p.Protocols(), ", ")
		log.Printf("Status: type: %s transceiver: %d firmware: %d protocols: %s", p.TypeString(), p.TransceiverType, p.FirmwareVersion, protocols)
	case *gorfxtrx.LightingX10:
		fields := map[string]interface{}{
			"origin":  Origin,
			"source":  p.Id(),
			"group":   p.Id()[:1],
			"command": p.Command(),
		}
		ev = pubsub.NewEvent("x10", fields)

	case *gorfxtrx.LightingHE:
		id := fmt.Sprintf("%07X%1X", p.HouseCode, p.UnitCode)
		fields := map[string]interface{}{
			"origin":  Origin,
			"source":  id,
			"command": p.Command(),
		}
		ev = pubsub.NewEvent("homeeasy", fields)

	case *gorfxtrx.Temp:
		source := fmt.Sprintf("thn132n.%s", p.Id()[0:2])
		fields := map[string]interface{}{
			"origin":  Origin,
			"source":  source,
			"temp":    p.Temp,
			"battery": p.Battery,
		}
		ev = pubsub.NewEvent("temp", fields)

	case *gorfxtrx.TempHumid:
		major := strings.ToLower(strings.Split(p.Type(), ",")[0])
		source := fmt.Sprintf("%s.%s", major, p.Id()[0:2])
		fields := map[string]interface{}{
			"origin":   Origin,
			"source":   source,
			"temp":     p.Temp,
			"humidity": p.Humidity,
			"battery":  p.Battery,
		}
		ev = pubsub.NewEvent("temp", fields)

	case *gorfxtrx.Wind:
		source := strings.ToLower(p.Type())
		fields := map[string]interface{}{
			"origin":   Origin,
			"source":   source,
			"speed":    p.Gust,
			"avgspeed": p.AverageSpeed,
			"dir":      p.Direction,
			"battery":  p.Battery,
		}
		ev = pubsub.NewEvent("wind", fields)

	case *gorfxtrx.Rain:
		device := strings.ToLower(p.Type())
		source := fmt.Sprintf("%s.%s", device, p.Id())
		fields := map[string]interface{}{
			"origin":    Origin,
			"source":    source,
			"rate":      p.RainRate,
			"all_total": p.RainTotal,
			"battery":   p.Battery,
		}
		ev = pubsub.NewEvent("rain", fields)

	case *gorfxtrx.Chime:
		device := deviceName(p.Type())
		source := fmt.Sprintf("%s.%s", device, strings.Replace(p.Id(), ":", "", 1))
		fields := map[string]interface{}{
			"origin":  Origin,
			"source":  source,
			"chime":   p.Chime,
			"battery": p.Battery,
			"command": "on",
		}
		ev = pubsub.NewEvent("chime", fields)

	default:
		log.Printf("Ignored unhandled packet: %#v\n", packet)
	}

	return ev
}
Ejemplo n.º 17
0
// Run the service
func (self *Service) Run() error {
	self.log = openLogFile()
	self.timers = map[string]*time.Timer{}
	self.configUpdated = make(chan bool, 2)
	// load templated automata
	var err error
	self.automata, err = loadAutomata()
	if err != nil {
		return err
	}

	// persistance can take a while and delay the workflow, so run in background
	chanPersist := make(chan string, 32)
	go func() {
		for automaton := range chanPersist {
			self.PersistStore(self.automata, automaton)
		}
	}()

	self.RestoreStore(self.automata)
	log.Printf("Initial states: %s", self.automata)

	ch := services.Subscriber.Channel()
	defer services.Subscriber.Close(ch)
	for {
		select {
		case ev := <-ch:
			if ev.Topic == "alert" || ev.Topic == "heating" || strings.HasPrefix(ev.Topic, "_") {
				continue
			}
			if ev.Command() == "" && ev.State() == "" {
				continue
			}

			// send relevant events to the automata
			event := EventWrapper{ev}
			self.automata.Process(event)

		case change := <-self.automata.Changes:
			trigger := change.Trigger.(EventWrapper)
			s := fmt.Sprintf("%-17s %s->%s", "["+change.Automaton+"]", change.Old, change.New)
			log.Printf("%-40s (event: %s)", s, trigger)
			chanPersist <- change.Automaton
			// emit event
			fields := pubsub.Fields{
				"device":  change.Automaton,
				"state":   change.New,
				"trigger": trigger.String(),
			}
			ev := pubsub.NewEvent("state", fields)
			services.Publisher.Emit(ev)

		case action := <-self.automata.Actions:
			wrapper := action.Trigger.(EventWrapper)
			ea := EventAction{self, wrapper.event, action.Change}
			err := DynamicCall(ea, action.Name)
			if err != nil {
				log.Println("Error:", err)
			}
		case <-self.configUpdated:
			// live reload the automata!
			log.Println("Automata config updated, reloading")
			updated, err := loadAutomata()
			if err != nil {
				log.Println("Failed to reload automata:", err)
				continue
			}
			self.RestoreStore(updated)
			self.automata = updated
			log.Println("Automata reloaded successfully")
		}
	}
	return nil
}