Update board.go, board_dummy.go, and 4 more files...

This commit is contained in:
Paolo Asperti 2021-01-05 14:50:11 +01:00
parent 44de3e8694
commit 54b24620ba
6 changed files with 395 additions and 159 deletions

View File

@ -1,161 +1,49 @@
package main package main
import ( import (
"fmt"
"log" "log"
"strings" "strings"
"github.com/spf13/viper" "github.com/spf13/viper"
) )
type Channel struct { type Channel interface {
ID string Toggle() (bool, error)
Num uint On() error
Name string Off() error
MQTTTopic string ToString() string
Value bool UpdateMQTT()
Inverted bool // low level only OnChange()
OnBoot string Status() bool
Parent *Board Parent() Board
Dump()
Name() string
OnBoot() string
SetOnBoot(string)
SetMQTTTopic(string)
} }
type Board struct { type Board interface {
ID string Init()
Name string Dump()
ChannelCount uint Channel(uint64) Channel
Inverted bool // low level only
Channels []*Channel
} }
type Outlet struct { type Outlet struct {
ID string ID string
Num uint Num uint
Description string Description string
Board *Board Channel Channel
Channel *Channel
} }
func (c *Channel) Toggle() (bool, error) { var boards []Board
c.Value = !c.Value var allChannels map[string]Channel
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 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() { func parseBoardsConfig() {
// TODO: init boards array? // TODO: init boards array?
allChannels = make(map[string]*Channel) allChannels = make(map[string]Channel)
boardsConfig := viper.Sub("boards") boardsConfig := viper.Sub("boards")
if boardsConfig == nil { if boardsConfig == nil {
@ -168,10 +56,13 @@ func parseBoardsConfig() {
boardType := boardConfig.GetString("type") boardType := boardConfig.GetString("type")
switch boardType { switch boardType {
case "mqtt":
b := newMQTTBoard(boardConfig, key)
boards = append(boards, b)
case "gpio": case "gpio":
default: default:
b := newDummyBoard(boardConfig, key) b := newDummyBoard(boardConfig, key)
boards = append(boards, &b) boards = append(boards, b)
} }
@ -197,7 +88,6 @@ func parseBoardsConfig() {
ID: key, ID: key,
Num: num, Num: num,
Description: description, Description: description,
Board: channel.Parent,
Channel: channel, Channel: channel,
} }
@ -216,17 +106,6 @@ func parseBoardsConfig() {
} }
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() { func (o *Outlet) Dump() {
log.Printf("Outlet %v: channel name: %v\n", o.Num, o.Channel.Name) log.Printf("Outlet %v: channel name: %v\n", o.Num, o.Channel.Name())
} }

178
src/board_dummy.go Normal file
View File

@ -0,0 +1,178 @@
package main
import (
"fmt"
"log"
"strings"
"github.com/spf13/viper"
)
type DummyChannel struct {
ID string
Num uint
name string
MQTTTopic string
Value bool
onboot string
parent *DummyBoard
}
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("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 DummyChannel{
ID: channelID,
Num: v.GetUint("num"),
name: v.GetString("name"),
MQTTTopic: v.GetString("mqtttopic"),
Value: value,
onboot: v.GetString("onboot"),
}
}
func newDummyBoard(v *viper.Viper, id string) *DummyBoard {
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
return &b
}
func (c *DummyChannel) Toggle() (bool, error) {
c.Value = !c.Value
c.OnChange()
return c.Value, nil
}
func (c *DummyChannel) On() error {
c.Value = true
c.OnChange()
return nil
}
func (c *DummyChannel) Off() error {
c.Value = true
c.OnChange()
return nil
}
func (c *DummyChannel) ToString() string {
if !c.Value {
return "off"
}
return "on"
}
func (c *DummyChannel) UpdateMQTT() {
MQTTpublish(c.MQTTTopic, c.ToString())
}
func (c *DummyChannel) 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 *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) Init() {
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) SetMQTTTopic(str string) {
c.MQTTTopic = str
s := fmt.Sprintf("boards.%s.channels.%s.mqtttopic", c.parent.ID, c.ID)
viper.Set(s, str)
}

183
src/board_mqtt.go Normal file
View File

@ -0,0 +1,183 @@
package main
import (
"fmt"
"log"
"strings"
"github.com/spf13/viper"
)
type MQTTChannel struct {
ID string
Num uint
name string
MQTTTopic string
Value bool
onboot string
parent *MQTTBoard
MQTTRemoteTopic string
}
type MQTTBoard struct {
ID string
Name string
ChannelCount uint
Channels []*MQTTChannel
MQTTRemoteHost string
MQTTRemotePort string
MQTTRemoteUsername string
MQTTRemotePassword string
}
func newMQTTChannel(v *viper.Viper, channelID string) MQTTChannel {
v.SetDefault("name", "unknown")
v.SetDefault("lastValue", 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 MQTTChannel{
ID: channelID,
Num: v.GetUint("num"),
name: v.GetString("name"),
MQTTTopic: v.GetString("mqtttopic"),
Value: value,
onboot: v.GetString("onboot"),
}
}
func newMQTTBoard(v *viper.Viper, id string) *MQTTBoard {
var b MQTTBoard
v.SetDefault("name", "board "+id)
v.SetDefault("type", "mqtt")
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 = MQTTBoard{
ID: id,
Name: v.GetString("name"),
ChannelCount: v.GetUint("channelCount"),
}
channels := make([]*MQTTChannel, 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 := newMQTTChannel(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 (c *MQTTChannel) Toggle() (bool, error) {
c.Value = !c.Value
c.OnChange()
return c.Value, nil
}
func (c *MQTTChannel) On() error {
c.Value = true
c.OnChange()
return nil
}
func (c *MQTTChannel) Off() error {
c.Value = true
c.OnChange()
return nil
}
func (c *MQTTChannel) ToString() string {
if !c.Value {
return "off"
}
return "on"
}
func (c *MQTTChannel) UpdateMQTT() {
MQTTpublish(c.MQTTTopic, c.ToString())
}
func (c *MQTTChannel) 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 *MQTTChannel) Status() bool {
return c.Value
}
func (c *MQTTChannel) Parent() Board {
return c.parent
}
func (c *MQTTChannel) Dump() {
log.Printf(" Channel %d (on boot: %s): %s \n", c.Num, c.onboot, c.Name)
}
func (b *MQTTBoard) 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 *MQTTBoard) Init() {
return
}
func (b *MQTTBoard) Channel(num uint64) Channel {
return b.Channels[num]
}
func (c *MQTTChannel) Name() string {
return c.name
}
func (c *MQTTChannel) OnBoot() string {
return c.onboot
}
func (c *MQTTChannel) 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 *MQTTChannel) SetMQTTTopic(str string) {
c.MQTTTopic = str
s := fmt.Sprintf("boards.%s.channels.%s.mqtttopic", c.parent.ID, c.ID)
viper.Set(s, str)
}

View File

@ -68,10 +68,7 @@ func outletEditPost(ctx *macaron.Context, f OutletPostForm) {
outletsPage(ctx) outletsPage(ctx)
return return
} }
outlets[num].Channel.SetOnBoot(onboot)
outlets[num].Channel.OnBoot = onboot
s1 := fmt.Sprintf("boards.%s.channels.%s.onboot", outlets[num].Board.ID, outlets[num].Channel.ID)
viper.Set(s1, onboot)
outlets[num].Description = strings.TrimSpace(f.Description) outlets[num].Description = strings.TrimSpace(f.Description)
s2 := fmt.Sprintf("outlets.%s.description", outlets[num].ID) s2 := fmt.Sprintf("outlets.%s.description", outlets[num].ID)
@ -79,11 +76,10 @@ func outletEditPost(ctx *macaron.Context, f OutletPostForm) {
mqtt := strings.TrimSpace(f.MQTTTopic) mqtt := strings.TrimSpace(f.MQTTTopic)
if mqtt == "" { if mqtt == "" {
mqtt = outlets[num].Channel.Name mqtt = outlets[num].Channel.Name()
} }
outlets[num].Channel.MQTTTopic = mqtt
s3 := fmt.Sprintf("boards.%s.channels.%s.mqtttopic", outlets[num].Board.ID, outlets[num].Channel.ID) outlets[num].Channel.SetMQTTTopic(mqtt)
viper.Set(s3, mqtt)
viper.WriteConfig() viper.WriteConfig()

View File

@ -22,7 +22,7 @@ func jsonStatus(ctx *macaron.Context) {
data = append(data, Dictionary{ data = append(data, Dictionary{
"Num": o.Num, "Num": o.Num,
"Description": o.Description, "Description": o.Description,
"Status": o.Channel.Value, "Status": o.Channel.Status(),
}) })
} }

View File

@ -72,14 +72,14 @@
<div class="form-group"> <div class="form-group">
<label for="board" class="col-sm-2 control-label">Board</label> <label for="board" class="col-sm-2 control-label">Board</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" class="form-control" id="board" disabled="" value="{{ outlet.Board.Name }}"> <input type="text" class="form-control" id="board" disabled="" value="{{ outlet.Channel.Parent().Name }}">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="channel" class="col-sm-2 control-label">Board port</label> <label for="channel" class="col-sm-2 control-label">Board port</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" class="form-control" id="channel" disabled="" value="{{ outlet.Channel.Name }}"> <input type="text" class="form-control" id="channel" disabled="" value="{{ outlet.Channel.Name() }}">
</div> </div>
</div> </div>