package board import ( "fmt" "log" "strings" PahoMQTT "github.com/eclipse/paho.mqtt.golang" "github.com/spf13/viper" ) type DummyChannel struct { ID string Num uint name string mqttStateTopic string mqttCommandTopic string value bool onboot string parent *DummyBoard onChannelUpdateFunctions map[string]onChannelUpdateFunction } type DummyBoard struct { ID string Name string ChannelCount uint channels []*DummyChannel } func newDummyChannel(v *viper.Viper, channelID string) DummyChannel { v.SetDefault("name", "unknown") v.SetDefault("lastValue", false) v.SetDefault("onboot", "off") v.SetDefault("mqtt.statetopic", v.GetString("name")) value := false switch v.GetString("onboot") { case "on": value = true case "last": value = v.GetBool("lastValue") } // newUUID := UUID.New().String() // v.SetDefault("id", newUUID) return DummyChannel{ ID: channelID, Num: v.GetUint("num"), name: v.GetString("name"), mqttStateTopic: v.GetString("mqtt.statetopic"), mqttCommandTopic: v.GetString("mqtt.commandtopic"), value: value, onboot: v.GetString("onboot"), } } func newDummyBoard(v *viper.Viper, id string) *Board { var b *DummyBoard v.SetDefault("name", "board "+id) v.SetDefault("type", "dummy") v.SetDefault("channelCount", 0) v.SetDefault("channels", "") if v.GetInt("channelCount") > 0 { for i := 0; i < v.GetInt("channelCount"); i++ { v.SetDefault("channels."+fmt.Sprint(i)+".num", i) } } b = &DummyBoard{ ID: id, Name: v.GetString("name"), ChannelCount: v.GetUint("channelCount"), } channels := make([]*DummyChannel, v.GetInt("channelCount")) if v.GetInt("channelCount") > 0 { channelsConfig := v.Sub("channels") if channelsConfig != nil { for channelid1 := range channelsConfig.AllSettings() { channelid := strings.ToLower(channelid1) channelConfig := channelsConfig.Sub(channelid) c := newDummyChannel(channelConfig, channelid) c.parent = b if c.Num >= v.GetUint("channelCount") { continue } channels[c.Num] = &c AllChannels[c.ID] = &c } } } b.channels = channels var b1 Board = b return &b1 } func (c *DummyChannel) Toggle() (bool, error) { c.value = !c.value c.SaveLastState() for f := range c.onChannelUpdateFunctions { c.onChannelUpdateFunctions[f](!c.value, c) } return c.value, nil } func (c *DummyChannel) On() error { oldval := c.value c.value = true c.SaveLastState() for f := range c.onChannelUpdateFunctions { c.onChannelUpdateFunctions[f](oldval, c) } return nil } func (c *DummyChannel) Off() error { oldval := c.value c.value = true c.SaveLastState() for f := range c.onChannelUpdateFunctions { c.onChannelUpdateFunctions[f](oldval, c) } return nil } func (c *DummyChannel) ToString() string { if !c.value { return "off" } return "on" } func (c *DummyChannel) SaveLastState() { if c.onboot == "last" { s := fmt.Sprintf("boards.%s.channels.%s.lastvalue", c.parent.ID, c.ID) viper.Set(s, c.value) viper.WriteConfig() } } func (c *DummyChannel) Status() bool { return c.value } func (c *DummyChannel) Parent() Board { return c.parent } func (c *DummyChannel) Dump() { log.Printf(" Channel %d (on boot: %s): %s \n", c.Num, c.onboot, c.name) } func (b DummyBoard) Dump() { log.Printf("Board '%s' (id: %s): %d channels\n", b.Name, b.ID, b.ChannelCount) for c := range b.channels { b.channels[c].Dump() } } func (b *DummyBoard) Initialize() { return } func (b *DummyBoard) Channel(num uint64) Channel { return b.channels[num] } func (c *DummyChannel) Name() string { return c.name } func (c *DummyChannel) OnBoot() string { return c.onboot } func (c *DummyChannel) SetOnBoot(str string) { c.onboot = str s := fmt.Sprintf("boards.%s.channels.%s.onboot", c.parent.ID, c.ID) viper.Set(s, str) } func (c *DummyChannel) SetMQTTStateTopic(str string) { c.mqttStateTopic = str s := fmt.Sprintf("boards.%s.channels.%s.mqtt.statetopic", c.parent.ID, c.ID) viper.Set(s, str) } func (c *DummyChannel) SetMQTTCommandTopic(str string) { c.mqttCommandTopic = str s := fmt.Sprintf("boards.%s.channels.%s.mqtt.commandtopic", c.parent.ID, c.ID) viper.Set(s, str) } func (c *DummyChannel) MQTTHandler(client PahoMQTT.Client, msg PahoMQTT.Message) { switch string(msg.Payload()) { case "on": if !c.value { c.value = true c.SaveLastState() } case "off": if c.value { c.value = false c.SaveLastState() } } } func (c *DummyChannel) MQTTStateTopic() string { return c.mqttStateTopic } func (c *DummyChannel) MQTTCommandTopic() string { return c.mqttCommandTopic } func init() { RegisterBoardType("dummy", newDummyBoard) } func (c *DummyChannel) AddOnChannelUpdateFunction(name string, f onChannelUpdateFunction) { if c.onChannelUpdateFunctions == nil { c.onChannelUpdateFunctions = make(map[string]onChannelUpdateFunction) } c.onChannelUpdateFunctions[name] = f }