233 lines
4.6 KiB
Go
233 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
type Channel struct {
|
|
ID string
|
|
Num uint
|
|
Name string
|
|
MQTTTopic string
|
|
Value bool
|
|
Inverted bool // low level only
|
|
OnBoot string
|
|
Parent *Board
|
|
}
|
|
|
|
type Board struct {
|
|
ID string
|
|
Name string
|
|
ChannelCount uint
|
|
Inverted bool // low level only
|
|
Channels []*Channel
|
|
}
|
|
|
|
type Outlet struct {
|
|
ID string
|
|
Num uint
|
|
Description string
|
|
Board *Board
|
|
Channel *Channel
|
|
}
|
|
|
|
func (c *Channel) Toggle() (bool, error) {
|
|
c.Value = !c.Value
|
|
c.OnChange()
|
|
return c.Value, nil
|
|
}
|
|
|
|
func (c *Channel) On() error {
|
|
c.Value = true
|
|
c.OnChange()
|
|
return nil
|
|
}
|
|
|
|
func (c *Channel) Off() error {
|
|
c.Value = true
|
|
c.OnChange()
|
|
return nil
|
|
}
|
|
|
|
func (c *Channel) ToString() string {
|
|
if !c.Value {
|
|
return "off"
|
|
}
|
|
return "on"
|
|
}
|
|
|
|
func (c *Channel) UpdateMQTT() {
|
|
MQTTpublish(c.MQTTTopic, c.ToString())
|
|
}
|
|
|
|
func (c *Channel) OnChange() {
|
|
if c.OnBoot == "last" {
|
|
s := fmt.Sprintf("boards.%s.channels.%s.lastvalue", c.Parent.ID, c.ID)
|
|
viper.Set(s, c.Value)
|
|
viper.WriteConfig()
|
|
}
|
|
c.UpdateMQTT()
|
|
}
|
|
|
|
func (c *Channel) Status() bool {
|
|
return c.Value
|
|
}
|
|
|
|
var boards []*Board
|
|
var allChannels map[string]*Channel
|
|
var outlets []*Outlet
|
|
|
|
func newDummyChannel(v *viper.Viper, channelID string) Channel {
|
|
v.SetDefault("name", "unknown")
|
|
v.SetDefault("lastValue", false)
|
|
v.SetDefault("inverted", false)
|
|
v.SetDefault("onboot", "off")
|
|
v.SetDefault("mqtttopic", 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 Channel{
|
|
ID: channelID,
|
|
Num: v.GetUint("num"),
|
|
Name: v.GetString("name"),
|
|
MQTTTopic: v.GetString("mqtttopic"),
|
|
Value: value,
|
|
Inverted: v.GetBool("inverted"),
|
|
OnBoot: v.GetString("onboot"),
|
|
}
|
|
}
|
|
|
|
func newDummyBoard(v *viper.Viper, id string) Board {
|
|
var b Board
|
|
|
|
v.SetDefault("name", "board "+id)
|
|
v.SetDefault("inverted", false)
|
|
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 = Board{
|
|
ID: id,
|
|
Name: v.GetString("name"),
|
|
ChannelCount: v.GetUint("channelCount"),
|
|
Inverted: v.GetBool("inverted"),
|
|
}
|
|
|
|
channels := make([]*Channel, 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
|
|
|
|
return b
|
|
}
|
|
|
|
func parseBoardsConfig() {
|
|
// TODO: init boards array?
|
|
|
|
allChannels = make(map[string]*Channel)
|
|
|
|
boardsConfig := viper.Sub("boards")
|
|
if boardsConfig == nil {
|
|
logWarning("No board configured")
|
|
return
|
|
}
|
|
|
|
for key := range boardsConfig.AllSettings() {
|
|
boardConfig := boardsConfig.Sub(key)
|
|
|
|
boardType := boardConfig.GetString("type")
|
|
switch boardType {
|
|
case "gpio":
|
|
default:
|
|
b := newDummyBoard(boardConfig, key)
|
|
boards = append(boards, &b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
outlets = make([]*Outlet, len(allChannels))
|
|
|
|
outletsConfig := viper.Sub("outlets")
|
|
if outletsConfig == nil {
|
|
logWarning("No outlet configured")
|
|
return
|
|
}
|
|
|
|
for key := range outletsConfig.AllSettings() {
|
|
outletConfig := outletsConfig.Sub(key)
|
|
num := outletConfig.GetUint("num")
|
|
outletConfig.SetDefault("description", "no description")
|
|
description := outletConfig.GetString("description")
|
|
channelID := strings.ToLower(outletConfig.GetString("channelID"))
|
|
channel := allChannels[channelID]
|
|
// TODO: channel non esistente
|
|
o := Outlet{
|
|
ID: key,
|
|
Num: num,
|
|
Description: description,
|
|
Board: channel.Parent,
|
|
Channel: channel,
|
|
}
|
|
|
|
outlets[num] = &o
|
|
}
|
|
|
|
// dumpa tutto
|
|
for b := range boards {
|
|
boards[b].Dump()
|
|
}
|
|
|
|
// dumpa tutto
|
|
for o := range outlets {
|
|
outlets[o].Dump()
|
|
}
|
|
|
|
}
|
|
|
|
func (c *Channel) Dump() {
|
|
log.Printf(" Channel %d (on boot: %s): %s \n", c.Num, c.OnBoot, c.Name)
|
|
}
|
|
|
|
func (b *Board) 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 (o *Outlet) Dump() {
|
|
log.Printf("Outlet %v: channel name: %v\n", o.Num, o.Channel.Name)
|
|
}
|