This repository has been archived on 2023-08-29. You can view files and clone it, but cannot push or open issues or pull requests.
automation/main.go
Dreaded_X 01b2d492ba
All checks were successful
continuous-integration/drone/push Build is passing
All devices are now stored in a central map, part of large refactor
2022-11-18 21:12:09 +01:00

186 lines
4.4 KiB
Go

package main
import (
"automation/device"
"automation/integration/hue"
"automation/integration/kasa"
"automation/integration/mqtt"
"automation/integration/ntfy"
"automation/presence"
"encoding/json"
"log"
"net/http"
"os"
"github.com/gorilla/mux"
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"gopkg.in/yaml.v3"
paho "github.com/eclipse/paho.mqtt.golang"
)
type config struct {
Hue struct {
Token string `yaml:"token" envconfig:"HUE_TOKEN"`
IP string `yaml:"ip" envconfig:"HUE_IP"`
} `yaml:"hue"`
NTFY struct {
topic string `yaml:"topic" envconfig:"NTFY_TOPIC"`
} `yaml:"ntfy"`
MQTT struct {
Host string `yaml:"host" envconfig:"MQTT_HOST"`
Port int `yaml:"port" envconfig:"MQTT_PORT"`
Username string `yaml:"username" envconfig:"MQTT_USERNAME"`
Password string `yaml:"password" envconfig:"MQTT_PASSWORD"`
ClientID string `yaml:"client_id" envconfig:"MQTT_CLIENT_ID"`
} `yaml:"mqtt"`
Kasa struct {
Outlets map[string]string `yaml:"outlets"`
} `yaml:"kasa"`
Computer map[string]struct {
MACAddress string `yaml:"mac"`
Room string `yaml:"room"`
Url string `yaml:"url"`
} `yaml:"computers"`
Google device.Config `yaml:"google"`
}
func GetConfig() config {
// First load the config from the yaml file
f, err := os.Open("config.yml")
if err != nil {
log.Fatalln("Failed to open config file", err)
}
defer f.Close()
var cfg config
decoder := yaml.NewDecoder(f)
err = decoder.Decode(&cfg)
if err != nil {
log.Fatalln("Failed to parse config file", err)
}
// Then load values from environment
// This can be used to either override the config or pass in secrets
err = envconfig.Process("", &cfg)
if err != nil {
log.Fatalln("Failed to parse environmet config", err)
}
return cfg
}
// // @TODO Implement this for the other devices as well
// func GetDeviceKasa(name string) (*kasa.Kasa, error) {
// deviceGeneric, ok := devices[name]
// if !ok {
// return nil, fmt.Errorf("Device does not exist")
// }
// device, ok := deviceGeneric.(kasa.Kasa)
// if !ok {
// return nil, fmt.Errorf("Device is not a Kasa device")
// }
// return &device, nil
// }
func SetupBindings(client paho.Client, p *device.Provider) {
var handler paho.MessageHandler = func(client paho.Client, msg paho.Message) {
mixer, err := p.Devices.GetKasaDevice("living_room/mixer")
if err != nil {
log.Println(err)
return
}
speakers, err := p.Devices.GetKasaDevice("living_room/speakers")
if err != nil {
log.Println(err)
return
}
var message struct {
Action string `json:"action"`
}
err = json.Unmarshal(msg.Payload(), &message)
if err != nil {
log.Println(err)
return
}
if message.Action == "on" {
if mixer.GetState() {
mixer.SetState(false)
speakers.SetState(false)
} else {
mixer.SetState(true)
}
} else if message.Action == "brightness_move_up" {
if speakers.GetState() {
speakers.SetState(false)
} else {
speakers.SetState(true)
mixer.SetState(true)
}
}
}
if token := client.Subscribe("test/remote", 1, handler); token.Wait() && token.Error() != nil {
log.Println(token.Error())
}
}
func main() {
_ = godotenv.Load()
config := GetConfig()
// Setup all the connections to other services
client := mqtt.New(config.MQTT.Host, config.MQTT.Port, config.MQTT.ClientID, config.MQTT.Username, config.MQTT.Password)
defer client.Disconnect(250)
notify := ntfy.New(config.NTFY.topic)
hue := hue.New(config.Hue.IP, config.Hue.Token)
// Devices that we control and expose to google home
provider := device.NewProvider(config.Google, client)
// Setup presence system
p := presence.New(client, hue, notify, provider)
defer p.Delete()
r := mux.NewRouter()
r.HandleFunc("/assistant", provider.Service.FullfillmentHandler)
// Register computers
for name, info := range config.Computer {
provider.AddDevice(device.NewComputer(info.MACAddress, name, info.Room, info.Url))
}
// Register all kasa devies
for name, ip := range config.Kasa.Outlets {
provider.AddDevice(kasa.New(name, ip))
}
SetupBindings(client, provider)
// time.Sleep(time.Second)
// pretty.Println(provider.Devices)
// pretty.Println(provider.Devices.GetGoogleDevices())
// pretty.Println(provider.Devices.GetKasaDevices())
// pretty.Println(provider.Devices.GetZigbeeDevices())
addr := ":8090"
srv := http.Server{
Addr: addr,
Handler: r,
}
log.Printf("Starting server on %s (PID: %d)\n", addr, os.Getpid())
srv.ListenAndServe()
}