diff --git a/poc/homeassistant_autodiscover.txt b/poc/homeassistant_autodiscover.txt new file mode 100644 index 0000000..7a6b4ac --- /dev/null +++ b/poc/homeassistant_autodiscover.txt @@ -0,0 +1,18 @@ +sonoff10/tele/LWT Online +sonoff10/cmnd/POWER (null) +sonoff10/tele/INFO1 {"Module":"Sonoff Basic","Version":"6.6.0(release-sonoff)","FallbackTopic":"cmnd/DVES_E4A1F5_fb/","GroupTopic":"sonoffs"} +sonoff10/tele/INFO2 {"WebServerMode":"Admin","Hostname":"sonoff10-0501","IPAddress":"192.168.107.105"} +sonoff10/tele/INFO3 {"RestartReason":"Software/System restart"} +sonoff10/stat/RESULT {"POWER":"ON"} +sonoff10/stat/POWER ON + +homeassistant/switch/E4A1F5_RL_1/config {"name":"sonoff10","cmd_t":"~cmnd/POWER","stat_t":"~tele/STATE","val_tpl":"{{value_json.POWER}}","pl_off":"OFF","pl_on":"ON","avty_t":"~tele/LWT","pl_avail":"Online","pl_not_avail":"Offline","uniq_id":"E4A1F5_RL_1","device":{"identifiers":["E4A1F5"]},"~":"sonoff10/"} +homeassistant/sensor/E4A1F5_status/config {"name":"sonoff10 status","stat_t":"~HASS_STATE","avty_t":"~LWT","pl_avail":"Online","pl_not_avail":"Offline","json_attributes_topic":"~HASS_STATE","unit_of_meas":" ","val_tpl":"{{value_json['RSSI']}}","uniq_id":"E4A1F5_status","device":{"identifiers":["E4A1F5"],"name":"sonoff10","model":"Sonoff Basic","sw_version":"6.6.0(release-sonoff)","manufacturer":"Tasmota"},"~":"sonoff10/tele/"} + +sonoff10/tele/STATE {"Time":"1970-01-01T00:00:10","Uptime":"0T00:00:10","Heap":15,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":23,"POWER":"ON","Wifi":{"AP":1,"SSId":"iot","BSSId":"02:9F:C2:F7:CD:A9","Channel":5,"RSSI":100,"LinkCount":1,"Downtime":"0T00:00:06"}} +sonoff10/stat/RESULT {"POWER":"ON"} +sonoff10/stat/POWER ON +sonoff10/tele/STATE {"Time":"2019-09-21T12:10:18","Uptime":"0T00:00:16","Heap":15,"SleepMode":"Dynamic","Sleep":50,"LoadAvg":19,"POWER":"ON","Wifi":{"AP":1,"SSId":"iot","BSSId":"02:9F:C2:F7:CD:A9","Channel":5,"RSSI":100,"LinkCount":1,"Downtime":"0T00:00:06"}} + + + diff --git a/poc/info.txt b/poc/info.txt new file mode 100644 index 0000000..661ba78 --- /dev/null +++ b/poc/info.txt @@ -0,0 +1,3 @@ +docker run --rm -ti -p 1883:1883 alpine:latest sh -c "apk -U add mosquitto && mosquitto" + + diff --git a/t/t.go b/t/t.go new file mode 100644 index 0000000..eab87c2 --- /dev/null +++ b/t/t.go @@ -0,0 +1,270 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" +) + +// Board def +type Board struct { + ChannelCount uint `json:"channelcount"` + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Bus uint `json:"bus"` + Address uint `json:"address"` +} + +// ChannelName - return the name of a channel, useful for onboard GPIO +func (b Board) ChannelName(num uint) string { + return string(num) +} + +// PowerON def +func (b Board) PowerON(num uint) error { + return nil +} + +// PowerOFF def +func (b Board) PowerOFF(num uint) error { + return nil +} + +// PowerToggle def +func (b Board) PowerToggle(num uint) error { + return nil +} + +// Boardlink def +type Boardlink struct { + BoardID string `json:"boardid"` + Channel uint `json:"channel"` + board Board +} + +// Board def +func (bl Boardlink) Board() Board { + fmt.Printf("\n boardlink: \n\n") + if bl.board.ID == "" { + fmt.Printf("\n board nil: \n\n") + for i := range TheConfig.Boards { + if TheConfig.Boards[i].ID == bl.BoardID { + bl.board = TheConfig.Boards[i] + break + } + } + } + return bl.board +} + +// PowerON def +func (bl Boardlink) PowerON() error { + return bl.Board().PowerON(bl.Channel) +} + +// PowerOFF def +func (bl Boardlink) PowerOFF() error { + return bl.Board().PowerOFF(bl.Channel) +} + +// PowerToggle def +func (bl Boardlink) PowerToggle() error { + return bl.Board().PowerToggle(bl.Channel) +} + +// Outlet def +type Outlet struct { + Name string `json:"name"` + Location string `json:"location"` + HasPowerMeter bool `json:"haspowermeter"` + Command Boardlink `json:"command"` + PowerMeter Boardlink `json:"powermeter"` +} + +// PowerON def +func (o Outlet) PowerON() error { + return o.Command.PowerON() +} + +// PowerOFF def +func (o Outlet) PowerOFF() error { + return o.Command.PowerOFF() +} + +// PowerToggle def +func (o Outlet) PowerToggle() error { + return o.Command.PowerToggle() +} + +// MQTTConfig def +type MQTTConfig struct { + BrokerIP string `json:"ip"` + BrokerPort string `json:"port"` + ClientID string `json:"clientid"` + Username string `json:"username"` + Password string `json:"password"` + CleanSession bool `json:"cleansession"` + Topic string `json:"topic"` + HomeAssistant bool `json:"homeassistant"` +} + +// Configuration def +type Configuration struct { + Hostname string `json:"hostname"` + Outlets map[(uint)]Outlet `json:"outlets"` + Boards []Board `json:"boards"` + MQTT MQTTConfig `json:"mqtt"` +} + +func loadConfig(filename string) (Configuration, error) { + bytes, err := ioutil.ReadFile(filename) + if err != nil { + return Configuration{}, err + } + + var c Configuration + err = json.Unmarshal(bytes, &c) + if err != nil { + return Configuration{}, err + } + + return c, nil +} + +func saveConfig(c Configuration, filename string) error { + bytes, err := json.MarshalIndent(c, "", " ") + if err != nil { + return err + } + + return ioutil.WriteFile(filename, bytes, 0644) +} + +// TheConfig def +var TheConfig Configuration + +func main() { + var err error + + var c1 Configuration + + c1 = createMockConfig() + for n, br := range c1.Boards { + fmt.Printf("A - Board %v (%v)\n", n, br.Type) + } + + err = saveConfig(c1, "t.json") + if err != nil { + panic(err) + } + + TheConfig, err = loadConfig("t.json") + if err != nil { + panic(err) + } + + err = saveConfig(TheConfig, "t1.json") + if err != nil { + panic(err) + } + + fmt.Printf("\n\nmqtt: %v\n\n", TheConfig.MQTT) + + TheConfig.Outlets[0].PowerON() +} + +func createMockConfig() Configuration { + return Configuration{ + Hostname: "maramao", + MQTT: MQTTConfig{ + BrokerIP: "192.168.2.190", + BrokerPort: "1883", + ClientID: "openpdu-123", + Username: "DVES_USER", + Password: "DVES_PASS", + CleanSession: false, + Topic: "openpdu/ok", + HomeAssistant: true, + }, + Boards: []Board{ + Board{ + ID: "6561df75-bf93-43f5-82ac-9b3dda081961", + Name: "Internal GPIO", + Type: "GPIO", + ChannelCount: 40, + }, + Board{ + Bus: 1, + Address: 0x29, + ID: "79690164-214f-41b0-93f9-e910dd54f323", + Name: "bordo1", + Type: "I2C-GPIO", + ChannelCount: 8, + }, + Board{ + Bus: 1, + Address: 0x27, + ID: "93f446d8-59e4-4abd-8bf7-e31cd80bc713", + Name: "bordo2", + Type: "I2C-ADC", + ChannelCount: 4, + }, + }, + Outlets: map[(uint)]Outlet{ + 0: Outlet{ + Name: "uscita 0", + Location: "port 1 dx", + HasPowerMeter: true, + Command: Boardlink{ + BoardID: "79690164-214f-41b0-93f9-e910dd54f323", + Channel: 0, + }, + PowerMeter: Boardlink{ + BoardID: "93f446d8-59e4-4abd-8bf7-e31cd80bc713", + Channel: 0, + }, + }, + 1: Outlet{ + Name: "uscita 1", + Location: "port 1 sx", + HasPowerMeter: true, + Command: Boardlink{ + BoardID: "79690164-214f-41b0-93f9-e910dd54f323", + Channel: 1, + }, + PowerMeter: Boardlink{ + BoardID: "93f446d8-59e4-4abd-8bf7-e31cd80bc713", + Channel: 1, + }, + }, + 2: Outlet{ + Name: "uscita 2", + Location: "port 2 dx", + HasPowerMeter: false, + Command: Boardlink{ + BoardID: "79690164-214f-41b0-93f9-e910dd54f323", + Channel: 2, + }, + }, + 3: Outlet{ + Name: "uscita 5v 1", + Location: "usb avanti 1", + HasPowerMeter: false, + Command: Boardlink{ + BoardID: "6561df75-bf93-43f5-82ac-9b3dda081961", + Channel: 21, + }, + }, + 4: Outlet{ + Name: "uscita 5v 2", + Location: "usb avanti 2", + HasPowerMeter: false, + Command: Boardlink{ + BoardID: "6561df75-bf93-43f5-82ac-9b3dda081961", + Channel: 22, + }, + }, + }, + } +} diff --git a/v.go b/v.go new file mode 100644 index 0000000..56d8695 --- /dev/null +++ b/v.go @@ -0,0 +1,42 @@ +package main + +import "github.com/spf13/viper" + +// Board def +type Board struct { + ChannelCount uint `json:"channelcount"` + ID string `json:"id"` + Name string `json:"name"` + Type string `json:"type"` +} + +// Configuration def +type Configuration struct { + Hostname string `json:"hostname"` + // Outlets map[(uint)]Outlet `json:"outlets"` + Boards []Board `json:"boards"` + // MQTT MQTTConfig `json:"mqtt"` +} + +// Boards definition +var Boards []Board + +func main() { + var err error + viper.SetConfigName("v") + viper.SetConfigType("yaml") + viper.AddConfigPath(".") + + mock() + +} + +func mock() { + b := Board{ + ID: "6561df75-bf93-43f5-82ac-9b3dda081961", + Name: "Internal GPIO", + Type: "GPIORelayBoard", + ChannelCount: 40, + } + Boards = append(Boards, b) +}