Add configuration
Add yaml configuration file handling
This commit is contained in:
parent
cd8b6da112
commit
aea0620747
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1 +1,5 @@
|
|||
# Binaries
|
||||
/smartbridge
|
||||
|
||||
# Config files
|
||||
/*.yml
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
11
cmd/smartbridge/utils.go
Normal 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
5
go.mod
|
@ -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
4
go.sum
|
@ -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
11
smartbridge.service
Normal 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
14
smartbridge.yml.example
Normal 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: ""
|
Loading…
Reference in a new issue