Skip to content

Commit

Permalink
Merge pull request #15 from diebietse/mqtt-plugin
Browse files Browse the repository at this point in the history
Add n MQTT plugin to invertergui
  • Loading branch information
ncthompson authored Jun 15, 2020
2 parents 4a72d24 + 4f428d6 commit 3f783fa
Show file tree
Hide file tree
Showing 561 changed files with 270,058 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ env:
- GO111MODULE=on

go:
- 1.12.x
- 1.14.x

git:
depth: 1
Expand All @@ -17,7 +17,7 @@ notifications:
email: false

before_script:
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.15.0
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.26.0
- go mod vendor

script:
Expand Down
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

.PHONY: test test-race vet install gofmt docker statik lint clean invertergui
.PHONY: test test-race vet install gofmt docker statik lint clean invertergui vendor

.DEFAULT_GOAL = invertergui

Expand All @@ -51,7 +51,14 @@ statik:
statik -f -p=frontend -src=./frontend/root

lint:
golangci-lint run
docker run --rm -it \
-w /src -v $(shell pwd):/src \
golangci/golangci-lint:v1.26 golangci-lint run \
-v -c .golangci.yml

clean:
rm ./invertergui
rm ./invertergui

vendor:
go mod tidy
go mod vendor
48 changes: 39 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,26 @@ This project makes use of [Go Modules](https://github.com/golang/go/wiki/Modules
## Getting started

```bash
Usage of ./invertergui:
-addr string
TCP address to listen on. (default ":8080")
-dev string
TTY device to use. (default "/dev/ttyUSB0")
-ip string
IP to connect when using tcp connection. (default "localhost:8139")
-tcp
Use TCP instead of TTY
Usage:
invertergui [OPTIONS]

Application Options:
--address= The IP/DNS and port of the machine that the application is running on. (default: :8080)
[$ADDRESS]
--data.source= Set the source of data for the inverter gui. "serial", "tcp" or "mock" (default: serial)
[$DATA_SOURCE]
--data.host= Host to connect when source is set to tcp. (default: localhost:8139) [$DATA_HOST]
--data.device= TTY device to use when source is set to serial. (default: /dev/ttyUSB0) [$DATA_DEVICE]
--cli.enabled Enable CLI output. [$CLI_ENABLED]
--mqtt.enabled Enable MQTT publishing. [$MQTT_ENABLED]
--mqtt.broker= Set the host port and scheme of the MQTT broker. (default: tcp://localhost:1883) [$MQTT_BROKER]
--mqtt.client_id= Set the client ID for the MQTT connection. (default: interter-gui) [$MQTT_CLIENT_ID]
--mqtt.topic= Set the MQTT topic updates published to. (default: invertergui/updates) [$MQTT_TOPIC]
--mqtt.username= Set the MQTT username [$MQTT_USERNAME]
--mqtt.password= Set the MQTT password [$MQTT_PASSWORD]

Help Options:
-h, --help Show this help message
```

## Port 8080
Expand Down Expand Up @@ -259,6 +270,25 @@ process_start_time_seconds 1.54506833485e+09
process_virtual_memory_bytes 1.15101696e+08
```

### MQTT

The MQTT client will publish updates to the given broker at the set topic.

#### MQTT Configuration Options

```bash
--mqtt.enabled Enable MQTT publishing. [$MQTT_ENABLED]
--mqtt.broker= Set the host port and scheme of the MQTT broker. (default: tcp://localhost:1883) [$MQTT_BROKER]
--mqtt.client_id= Set the client ID for the MQTT connection. (default: interter-gui) [$MQTT_CLIENT_ID]
--mqtt.topic= Set the MQTT topic updates published to. (default: invertergui/updates) [$MQTT_TOPIC]
--mqtt.username= Set the MQTT username [$MQTT_USERNAME]
--mqtt.password= Set the MQTT password [$MQTT_PASSWORD]
```

The MQTT client can be enabled by setting the environment variable `MQTT_ENABLED=true` or flag `--mqtt.enabled`.
All MQTT configuration can be done via flags or as environment variables.
The URI for the broker can be configured format should be `scheme://host:port`, where "scheme" is one of "tcp", "ssl", or "ws".

## TTY Device

The intertergui application makes use of a serial tty device to monitor the Multiplus.
Expand Down
34 changes: 34 additions & 0 deletions cmd/invertergui/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package main

import (
"github.com/jessevdk/go-flags"
)

type config struct {
Address string `long:"address" env:"ADDRESS" default:":8080" description:"The IP/DNS and port of the machine that the application is running on."`
Data struct {
Source string `long:"data.source" env:"DATA_SOURCE" default:"serial" description:"Set the source of data for the inverter gui. \"serial\", \"tcp\" or \"mock\""`
Host string `long:"data.host" env:"DATA_HOST" default:"localhost:8139" description:"Host to connect when source is set to tcp."`
Device string `long:"data.device" env:"DATA_DEVICE" default:"/dev/ttyUSB0" description:"TTY device to use when source is set to serial."`
}
Cli struct {
Enabled bool `long:"cli.enabled" env:"CLI_ENABLED" description:"Enable CLI output."`
}
MQTT struct {
Enabled bool `long:"mqtt.enabled" env:"MQTT_ENABLED" description:"Enable MQTT publishing."`
Broker string `long:"mqtt.broker" env:"MQTT_BROKER" default:"tcp://localhost:1883" description:"Set the host port and scheme of the MQTT broker."`
ClientID string `long:"mqtt.client_id" env:"MQTT_CLIENT_ID" default:"interter-gui" description:"Set the client ID for the MQTT connection."`
Topic string `long:"mqtt.topic" env:"MQTT_TOPIC" default:"invertergui/updates" description:"Set the MQTT topic updates published to."`
Username string `long:"mqtt.username" env:"MQTT_USERNAME" default:"" description:"Set the MQTT username"`
Password string `long:"mqtt.password" env:"MQTT_PASSWORD" default:"" description:"Set the MQTT password"`
}
}

func parseConfig() (*config, error) {
conf := &config{}
parser := flags.NewParser(conf, flags.Default)
if _, err := parser.Parse(); err != nil {
return nil, err
}
return conf, nil
}
63 changes: 42 additions & 21 deletions cmd/invertergui/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,38 +31,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package main

import (
"flag"
"fmt"
"io"
"log"
"net"
"net/http"
"os"

"github.com/diebietse/invertergui/mk2core"
"github.com/diebietse/invertergui/mk2driver"
"github.com/diebietse/invertergui/plugins/cli"
"github.com/diebietse/invertergui/plugins/mqttclient"
"github.com/diebietse/invertergui/plugins/munin"
"github.com/diebietse/invertergui/plugins/prometheus"
"github.com/diebietse/invertergui/plugins/webui"
"github.com/diebietse/invertergui/plugins/webui/static"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
"github.com/tarm/serial"
)

var log = logrus.WithField("ctx", "inverter-gui")

func main() {
source := flag.String("source", "serial", "Set the source of data for the inverter gui. \"serial\", \"tcp\" or \"mock\"")
addr := flag.String("addr", ":8080", "TCP address to listen on.")
ip := flag.String("ip", "localhost:8139", "IP to connect when using tcp connection.")
dev := flag.String("dev", "/dev/ttyUSB0", "TTY device to use.")
cliEnable := flag.Bool("cli", false, "Enable CLI output")
flag.Parse()

mk2 := getMk2Device(*source, *ip, *dev)
conf, err := parseConfig()
if err != nil {
os.Exit(1)
}
log.Info("Starting invertergui")

mk2, err := getMk2Device(conf.Data.Source, conf.Data.Host, conf.Data.Device)
if err != nil {
log.Fatalf("Could not open data source: %v", err)
}
defer mk2.Close()

core := mk2core.NewCore(mk2)

if *cliEnable {
if conf.Cli.Enabled {
cli.NewCli(core.NewSubscription())
}

Expand All @@ -80,10 +85,27 @@ func main() {
prometheus.NewPrometheus(core.NewSubscription())
http.Handle("/metrics", promhttp.Handler())

log.Fatal(http.ListenAndServe(*addr, nil))
// MQTT
if conf.MQTT.Enabled {
mqttConf := mqttclient.Config{
Broker: conf.MQTT.Broker,
Topic: conf.MQTT.Topic,
ClientID: conf.MQTT.ClientID,
Username: conf.MQTT.Username,
Password: conf.MQTT.Password,
}
if err := mqttclient.New(core.NewSubscription(), mqttConf); err != nil {
log.Fatalf("Could not setup MQTT client: %v", err)
}
}
log.Infof("Invertergui web server starting on: %v", conf.Address)

if err := http.ListenAndServe(conf.Address, nil); err != nil {
log.Fatal(err)
}
}

func getMk2Device(source, ip, dev string) mk2driver.Mk2 {
func getMk2Device(source, ip, dev string) (mk2driver.Mk2, error) {
var p io.ReadWriteCloser
var err error
var tcpAddr *net.TCPAddr
Expand All @@ -93,28 +115,27 @@ func getMk2Device(source, ip, dev string) mk2driver.Mk2 {
serialConfig := &serial.Config{Name: dev, Baud: 2400}
p, err = serial.OpenPort(serialConfig)
if err != nil {
panic(err)
return nil, err
}
case "tcp":
tcpAddr, err = net.ResolveTCPAddr("tcp", ip)
if err != nil {
panic(err)
return nil, err
}
p, err = net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
panic(err)
return nil, err
}
case "mock":
return mk2driver.NewMk2Mock()
return mk2driver.NewMk2Mock(), nil
default:
log.Printf("Invalid source selection: %v\nUse \"serial\", \"tcp\" or \"mock\"", source)
os.Exit(1)
return nil, fmt.Errorf("Invalid source selection: %v\nUse \"serial\", \"tcp\" or \"mock\"", source)
}

mk2, err := mk2driver.NewMk2Connection(p)
if err != nil {
panic(err)
return nil, err
}

return mk2
return mk2, nil
}
4 changes: 4 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
coverage:
precision: 2
round: down
range: "65...100"
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
module github.com/diebietse/invertergui

require (
github.com/eclipse/paho.mqtt.golang v1.2.0
github.com/gorilla/websocket v1.4.0
github.com/jessevdk/go-flags v1.4.0
github.com/prometheus/client_golang v0.9.2
github.com/rakyll/statik v0.1.5
github.com/sirupsen/logrus v1.6.0
github.com/stretchr/testify v1.3.0
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07
golang.org/x/sys v0.0.0-20190312061237-fead79001313 // indirect
)

go 1.14
16 changes: 14 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLM
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/eclipse/paho.mqtt.golang v1.2.0 h1:1F8mhG9+aO5/xpdtFkW4SxOJB67ukuDC3t2y2qayIX0=
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -20,13 +28,17 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nL
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rakyll/statik v0.1.5 h1:Ly2UjURzxnsSYS0zI50fZ+srA+Fu7EbpV5hglvJvJG0=
github.com/rakyll/statik v0.1.5/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
32 changes: 16 additions & 16 deletions plugins/cli/cli.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package cli

import (
"fmt"
"log"

"github.com/diebietse/invertergui/mk2driver"
"github.com/sirupsen/logrus"
)

var log = logrus.WithField("ctx", "inverter-gui-cli")

type Cli struct {
mk2driver.Mk2
}
Expand All @@ -27,21 +27,21 @@ func (c *Cli) run() {
}

func printInfo(info *mk2driver.Mk2Info) {
out := fmt.Sprintf("Version: %v\n", info.Version)
out += fmt.Sprintf("Bat Volt: %.2fV Bat Cur: %.2fA \n", info.BatVoltage, info.BatCurrent)
out += fmt.Sprintf("In Volt: %.2fV In Cur: %.2fA In Freq %.2fHz\n", info.InVoltage, info.InCurrent, info.InFrequency)
out += fmt.Sprintf("Out Volt: %.2fV Out Cur: %.2fA Out Freq %.2fHz\n", info.OutVoltage, info.OutCurrent, info.OutFrequency)
out += fmt.Sprintf("In Power %.2fW Out Power %.2fW\n", info.InVoltage*info.InCurrent, info.OutVoltage*info.OutCurrent)
out += fmt.Sprintf("Charge State: %.2f%%\n", info.ChargeState*100)
out += "LEDs state:"
log.Infof("Version: %v", info.Version)
log.Infof("Bat Volt: %.2fV Bat Cur: %.2fA", info.BatVoltage, info.BatCurrent)
log.Infof("In Volt: %.2fV In Cur: %.2fA In Freq %.2fHz", info.InVoltage, info.InCurrent, info.InFrequency)
log.Infof("Out Volt: %.2fV Out Cur: %.2fA Out Freq %.2fHz", info.OutVoltage, info.OutCurrent, info.OutFrequency)
log.Infof("In Power %.2fW Out Power %.2fW", info.InVoltage*info.InCurrent, info.OutVoltage*info.OutCurrent)
log.Infof("Charge State: %.2f%%", info.ChargeState*100)
log.Info("LEDs state:")
for k, v := range info.LEDs {
out += fmt.Sprintf(" %s %s", mk2driver.LedNames[k], mk2driver.StateNames[v])
log.Infof(" %s %s", mk2driver.LedNames[k], mk2driver.StateNames[v])
}

out += "\nErrors:"
for _, v := range info.Errors {
out += " " + v.Error()
if len(info.Errors) != 0 {
log.Info("Errors:")
for _, err := range info.Errors {
log.Error(err)
}
}
out += "\n"
log.Printf("System Info: \n%v", out)
}
Loading

0 comments on commit 3f783fa

Please sign in to comment.