Add configuration

Add yaml configuration file handling
This commit is contained in:
Felix Niederwanger 2023-05-31 19:30:27 +02:00
parent cd8b6da112
commit aea0620747
Signed by: phoenix
GPG key ID: 6E77A590E3F6D71C
9 changed files with 135 additions and 35 deletions

4
.gitignore vendored
View file

@ -1 +1,5 @@
# Binaries
/smartbridge
# Config files
/*.yml

View file

@ -1,13 +1,47 @@
package main
import (
"io/ioutil"
"gopkg.in/yaml.v2"
)
type Config struct {
Remote string // Remote IP address of the Smartbridge
Mqtt string // mqtt server
Remote string `yaml:"remote"` // Remote IP address of the Smartbridge
Mqtt MqttConfig `yaml:"mqtt"` // mqtt configuration
Delay int `yaml:"delay"`
Verbose bool `yaml:"verbose"`
}
type MqttConfig struct {
Remote string `yaml:"remote"`
Port int `yaml:"port"`
ClientID string `yaml:"clientid"`
topic string `yaml:"topic"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}
var cf Config
func (cf *Config) SetDefaults() {
cf.Remote = "192.168.242.199"
cf.Mqtt = "192.168.0.42"
cf.Remote = "127.0.0.1"
cf.Delay = 5
cf.Mqtt.Remote = "127.0.0.1"
cf.Mqtt.Port = 1883
cf.Mqtt.ClientID = "smartbridge"
cf.Mqtt.topic = "home/power"
cf.Mqtt.Username = ""
cf.Mqtt.Password = ""
}
func (cf *Config) LoadYAML(filename string) error {
content, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
if err := yaml.Unmarshal(content, cf); err != nil {
return err
}
return nil
}

View file

@ -10,25 +10,9 @@ import (
var mqtt_c Mqtt
func establishMqtt() error {
var err error
n := 5 // Reconnection attempts
for i := 0; i < n; i++ {
mqtt_c, err = ConnectMqtt(cf.Mqtt, 1883)
if err == nil {
return nil
}
fmt.Fprintf(os.Stderr, "mqtt error: %s (attempt %d/%d)\n", err, i+1, n)
time.Sleep(time.Second * time.Duration(i))
}
return fmt.Errorf("connection failed")
}
// awaits SIGINT or SIGTERM and quit program
func awaitTerminationSignal() {
func registerTerminationSignal() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGABRT)
go func() {
sig := <-sigs
fmt.Println(sig)
@ -36,15 +20,39 @@ func awaitTerminationSignal() {
}()
}
func main() {
cf.SetDefaults()
if err := establishMqtt(); err != nil {
fmt.Fprintf(os.Stderr, "mqtt: %s\n", err)
func loadConfig(filename string) {
if !fileExists(filename) {
return
}
if err := cf.LoadYAML(filename); err != nil {
fmt.Fprintf(os.Stderr, "error loading configuration '%s': %s\n", filename, err)
os.Exit(1)
}
}
awaitTerminationSignal()
func main() {
var err error
cf.SetDefaults()
// Try to load default locations
loadConfig("/etc/smartbridge.yml")
loadConfig("./smartbridge.yml")
// Program arguments are configuration files
for i := 1; i < len(os.Args); i++ {
arg := os.Args[i]
if err := cf.LoadYAML(arg); err != nil {
fmt.Fprintf(os.Stderr, "error loading configuration '%s': %s\n", arg, err)
os.Exit(1)
}
}
mqtt_c, err = ConnectMqtt(cf.Mqtt)
if err != nil {
fmt.Fprintf(os.Stderr, "mqtt error: %s\n", err)
os.Exit(101)
}
registerTerminationSignal()
fmt.Println("smartbridge SBWF3102 reader")
for true {
reading, err := ReadSmartbridge(cf.Remote)
@ -54,7 +62,12 @@ func main() {
if reading.Status != "ok" {
fmt.Fprintf(os.Stderr, "status: %s\n", reading.Status)
} else {
data := fmt.Sprintf("{\"power\":%d,\"unit\":\"W\",\"timestamp\":%d}", reading.Electricity.Power.Current.Value, time.Now().Unix())
data := fmt.Sprintf("{\"power\":%d,\"unit\":\"W\",\"min\":%d,\"max\":%d,\"timestamp\":%d}", reading.Electricity.Power.Current.Value, reading.Electricity.Power.Minimun.Value, reading.Electricity.Power.Maximum.Value, time.Now().Unix())
if cf.Verbose {
fmt.Print(cf.Mqtt.topic)
fmt.Print(" ")
fmt.Println(data)
}
mqtt_c.Publish("home/power", data)
}
time.Sleep(5 * time.Second)

View file

@ -10,13 +10,19 @@ type Mqtt struct {
client mqtt.Client
}
func ConnectMqtt(broker string, port int) (Mqtt, error) {
func ConnectMqtt(cf MqttConfig) (Mqtt, error) {
var ret Mqtt
opts := mqtt.NewClientOptions()
opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port))
opts.SetClientID("smartbridge")
//opts.SetUsername("emqx")
//opts.SetPassword("public")
opts.AddBroker(fmt.Sprintf("tcp://%s:%d", cf.Remote, cf.Port))
if cf.ClientID != "" {
opts.SetClientID(cf.ClientID)
}
if cf.Username != "" {
opts.SetUsername(cf.Username)
}
if cf.Password != "" {
opts.SetPassword(cf.Password)
}
//opts.SetDefaultPublishHandler(messagePubHandler)
//opts.OnConnect = connectHandler
//opts.OnConnectionLost = connectLostHandler

11
cmd/smartbridge/utils.go Normal file
View file

@ -0,0 +1,11 @@
package main
import "os"
func fileExists(filename string) bool {
info, err := os.Stat(filename)
if os.IsNotExist(err) {
return false
}
return !info.IsDir()
}

5
go.mod
View file

@ -2,7 +2,10 @@ module feldspaten.org/smartbridge/v2
go 1.20
require github.com/eclipse/paho.mqtt.golang v1.4.2
require (
github.com/eclipse/paho.mqtt.golang v1.4.2
gopkg.in/yaml.v2 v2.4.0
)
require (
github.com/gorilla/websocket v1.4.2 // indirect

4
go.sum
View file

@ -10,3 +10,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

11
smartbridge.service Normal file
View file

@ -0,0 +1,11 @@
[Unit]
Description=smartbridge reader service
After=network.target
[Service]
Type=simple
User=nobody
#WorkingDirectory=/var/empty
ExecStart=/usr/bin/smartbridge
Restart=always
RestartSec=30

14
smartbridge.yml.example Normal file
View file

@ -0,0 +1,14 @@
---
# smartbridge configuration
remote: "192.168.0.1" # Smartbridge IP address
delay: 5 # Seconds between polls
verbose: False
mqtt:
remote: "192.168.0.1"
port: 1883
clientid: "smartbridge"
topic: "home/power"
username: ""
password: ""