Concept plugin layout

This commit is contained in:
Nicholas Thompson
2019-03-10 21:36:34 +02:00
committed by ncthompson
parent d02de285d9
commit 47e73a4eff
12 changed files with 363 additions and 287 deletions

View File

@@ -26,21 +26,13 @@
#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 guimock invertergui invertercli build
.PHONY: test test-race vet install gofmt docker statik lint clean invertergui
.DEFAULT_GOAL = build
guimock:
go build ./cmd/guimock/
.DEFAULT_GOAL = invertergui
invertergui:
go build ./cmd/invertergui/
invertercli:
go build ./cmd/invertercli/
build: guimock invertergui invertercli
all: build gofmt test
gofmt:
@@ -62,4 +54,4 @@ lint:
golangci-lint run
clean:
rm ./guimock ./invertercli ./invertergui
rm ./invertergui

View File

@@ -1,29 +0,0 @@
package main
import (
"flag"
"log"
"net/http"
"github.com/diebietse/invertergui/frontend"
"github.com/diebietse/invertergui/mk2driver"
"github.com/diebietse/invertergui/webgui"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
addr := flag.String("addr", ":8080", "TCP address to listen on.")
flag.Parse()
mk2 := mk2driver.NewMk2Mock()
gui := webgui.NewWebGui(mk2)
http.Handle("/", frontend.NewStatic())
http.Handle("/ws", http.HandlerFunc(gui.ServeHub))
http.Handle("/munin", http.HandlerFunc(gui.ServeMuninHTTP))
http.Handle("/muninconfig", http.HandlerFunc(gui.ServeMuninConfigHTTP))
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(*addr, nil))
}

View File

@@ -1,90 +0,0 @@
package main
import (
"flag"
"fmt"
"io"
"log"
"net"
"os"
"os/signal"
"syscall"
"github.com/diebietse/invertergui/mk2if"
"github.com/tarm/serial"
"github.com/diebietse/invertergui/mk2driver"
"github.com/mikepb/go-serial"
)
// Basic CLI to serve as example lib usage
func main() {
//Info = log.New()
tcp := flag.Bool("tcp", false, "Use TCP instead of TTY")
ip := flag.String("ip", "localhost:8139", "IP to connect when using tcp connection.")
dev := flag.String("dev", "/dev/ttyUSB0", "TTY device to use.")
flag.Parse()
var p io.ReadWriteCloser
var err error
var tcpAddr *net.TCPAddr
if *tcp {
tcpAddr, err = net.ResolveTCPAddr("tcp", *ip)
if err != nil {
panic(err)
}
p, err = net.DialTCP("tcp", nil, tcpAddr)
if err != nil {
panic(err)
}
} else {
serialConfig := &serial.Config{Name: *dev, Baud: 2400}
p, err = serial.OpenPort(serialConfig)
if err != nil {
panic(err)
}
}
defer p.Close()
mk2, err := mk2driver.NewMk2Connection(p)
if err != nil {
panic(err)
}
defer mk2.Close()
c := mk2.C()
sigterm := make(chan os.Signal, 1)
signal.Notify(sigterm, syscall.SIGTERM, os.Interrupt)
mainloop:
for {
select {
case tmp := <-c:
if tmp.Valid {
PrintInfo(tmp)
}
case <-sigterm:
break mainloop
}
}
log.Printf("Closing connection")
}
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:"
for k, v := range info.LEDs {
out += fmt.Sprintf(" %s %s", mk2driver.LedNames[k], mk2driver.StateNames[v])
}
out += "\nErrors:"
for _, v := range info.Errors {
out += " " + v.Error()
}
out += "\n"
log.Printf("System Info: \n%v", out)
}

View File

@@ -38,8 +38,12 @@ import (
"net/http"
"github.com/diebietse/invertergui/frontend"
"github.com/diebietse/invertergui/mk2core"
"github.com/diebietse/invertergui/mk2driver"
"github.com/diebietse/invertergui/webgui"
"github.com/diebietse/invertergui/plugins/cli"
"github.com/diebietse/invertergui/plugins/munin"
"github.com/diebietse/invertergui/plugins/prometheus"
"github.com/diebietse/invertergui/plugins/webui"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/tarm/serial"
)
@@ -50,14 +54,44 @@ func main() {
tcp := flag.Bool("tcp", false, "Use TCP instead of TTY")
ip := flag.String("ip", "localhost:8139", "IP to connect when using tcp connection.")
dev := flag.String("dev", "/dev/ttyUSB0", "TTY device to use.")
mock := flag.Bool("mock", false, "Creates a mock device for test puposes")
cliEnable := flag.Bool("cli", false, "Enable CLI output")
flag.Parse()
var mk2 mk2driver.Mk2
if *mock {
mk2 = mk2driver.NewMk2Mock()
} else {
mk2 = getMk2Device(*tcp, *ip, *dev)
}
defer mk2.Close()
core := mk2core.NewCore(mk2)
if *cliEnable {
cli.NewCli(core.NewSubscription())
}
gui := webui.NewWebGui(core.NewSubscription())
mu := munin.NewMunin(core.NewSubscription())
prometheus.NewPrometheus(core.NewSubscription())
http.Handle("/", frontend.NewStatic())
http.Handle("/ws", http.HandlerFunc(gui.ServeHub))
http.Handle("/munin", http.HandlerFunc(mu.ServeMuninHTTP))
http.Handle("/muninconfig", http.HandlerFunc(mu.ServeMuninConfigHTTP))
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(*addr, nil))
}
func getMk2Device(tcp bool, ip, dev string) mk2driver.Mk2 {
var p io.ReadWriteCloser
var err error
var tcpAddr *net.TCPAddr
if *tcp {
tcpAddr, err = net.ResolveTCPAddr("tcp", *ip)
if tcp {
tcpAddr, err = net.ResolveTCPAddr("tcp", ip)
if err != nil {
panic(err)
}
@@ -66,25 +100,16 @@ func main() {
panic(err)
}
} else {
serialConfig := &serial.Config{Name: *dev, Baud: 2400}
serialConfig := &serial.Config{Name: dev, Baud: 2400}
p, err = serial.OpenPort(serialConfig)
if err != nil {
panic(err)
}
}
defer p.Close()
mk2, err := mk2driver.NewMk2Connection(p)
if err != nil {
panic(err)
}
defer mk2.Close()
gui := webgui.NewWebGui(mk2)
http.Handle("/", frontend.NewStatic())
http.Handle("/ws", http.HandlerFunc(gui.ServeHub))
http.Handle("/munin", http.HandlerFunc(gui.ServeMuninHTTP))
http.Handle("/muninconfig", http.HandlerFunc(gui.ServeMuninConfigHTTP))
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(*addr, nil))
return mk2
}

57
mk2core/core.go Normal file
View File

@@ -0,0 +1,57 @@
package mk2core
import (
"github.com/diebietse/invertergui/mk2driver"
)
type Core struct {
mk2driver.Mk2
plugins map[*subscription]bool
register chan *subscription
}
func NewCore(m mk2driver.Mk2) *Core {
core := &Core{
Mk2: m,
register: make(chan *subscription, 255),
plugins: map[*subscription]bool{},
}
go core.run()
return core
}
func (c *Core) NewSubscription() mk2driver.Mk2 {
sub := &subscription{
send: make(chan *mk2driver.Mk2Info),
}
c.register <- sub
return sub
}
func (c *Core) run() {
for {
select {
case r := <-c.register:
c.plugins[r] = true
case e := <-c.C():
for plugin := range c.plugins {
select {
case plugin.send <- e:
default:
}
}
}
}
}
type subscription struct {
send chan *mk2driver.Mk2Info
}
func (s *subscription) C() chan *mk2driver.Mk2Info {
return s.send
}
func (s *subscription) Close() {
close(s.send)
}

View File

@@ -1,7 +1,6 @@
package mk2driver
import (
"fmt"
"time"
)
@@ -64,7 +63,6 @@ func (m *mock) genMockValues() {
if mult < 0 {
mult = 1.0
}
fmt.Printf("Sending\n")
m.c <- input
time.Sleep(1 * time.Second)
}

47
plugins/cli/cli.go Normal file
View File

@@ -0,0 +1,47 @@
package cli
import (
"fmt"
"log"
"github.com/diebietse/invertergui/mk2driver"
)
type Cli struct {
mk2driver.Mk2
}
func NewCli(mk2 mk2driver.Mk2) {
newCli := &Cli{
Mk2: mk2,
}
go newCli.run()
}
func (c *Cli) run() {
for e := range c.C() {
if e.Valid {
printInfo(e)
}
}
}
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:"
for k, v := range info.LEDs {
out += fmt.Sprintf(" %s %s", mk2driver.LedNames[k], mk2driver.StateNames[v])
}
out += "\nErrors:"
for _, v := range info.Errors {
out += " " + v.Error()
}
out += "\n"
log.Printf("System Info: \n%v", out)
}

View File

@@ -28,32 +28,49 @@ 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.
*/
package webgui
package munin
import (
"bytes"
"fmt"
"net/http"
"time"
"github.com/diebietse/invertergui/mk2driver"
)
type Munin struct {
mk2driver.Mk2
muninResponse chan *muninData
}
type muninData struct {
status mk2driver.Mk2Info
status *mk2driver.Mk2Info
timesUpdated int
}
func (w *WebGui) ServeMuninHTTP(rw http.ResponseWriter, r *http.Request) {
muninDat := <-w.muninRespChan
func NewMunin(mk2 mk2driver.Mk2) *Munin {
m := &Munin{
Mk2: mk2,
muninResponse: make(chan *muninData),
}
go m.run()
return m
}
func (m *Munin) ServeMuninHTTP(rw http.ResponseWriter, r *http.Request) {
muninDat := <-m.muninResponse
if muninDat.timesUpdated == 0 {
rw.WriteHeader(500)
_, _ = rw.Write([]byte("No data to return.\n"))
return
}
calcMuninAverages(&muninDat)
calcMuninAverages(muninDat)
status := muninDat.status
tmpInput := buildTemplateInput(&status)
tmpInput := buildTemplateInput(status)
outputBuf := &bytes.Buffer{}
fmt.Fprintf(outputBuf, "multigraph in_batvolt\n")
fmt.Fprintf(outputBuf, "volt.value %s\n", tmpInput.BatVoltage)
@@ -82,98 +99,35 @@ func (w *WebGui) ServeMuninHTTP(rw http.ResponseWriter, r *http.Request) {
}
}
func (w *WebGui) ServeMuninConfigHTTP(rw http.ResponseWriter, r *http.Request) {
output := `multigraph in_batvolt
graph_title Battery Voltage
graph_vlabel Voltage (V)
graph_category inverter
graph_info Battery voltage
volt.info Voltage of battery
volt.label Voltage of battery (V)
multigraph in_batcharge
graph_title Battery Charge
graph_vlabel Charge (%)
graph_category inverter
graph_info Battery charge
charge.info Estimated charge of battery
charge.label Battery charge (%)
multigraph in_batcurrent
graph_title Battery Current
graph_vlabel Current (A)
graph_category inverter
graph_info Battery current
current.info Battery current
current.label Battery current (A)
multigraph in_batpower
graph_title Battery Power
graph_vlabel Power (W)
graph_category inverter
graph_info Battery power
power.info Battery power
power.label Battery power (W)
multigraph in_mainscurrent
graph_title Mains Current
graph_vlabel Current (A)
graph_category inverter
graph_info Mains current
currentin.info Input current
currentin.label Input current (A)
currentout.info Output current
currentout.label Output current (A)
multigraph in_mainsvoltage
graph_title Mains Voltage
graph_vlabel Voltage (V)
graph_category inverter
graph_info Mains voltage
voltagein.info Input voltage
voltagein.label Input voltage (V)
voltageout.info Output voltage
voltageout.label Output voltage (V)
multigraph in_mainspower
graph_title Mains Power
graph_vlabel Power (VA)
graph_category inverter
graph_info Mains power
powerin.info Input power
powerin.label Input power (VA)
powerout.info Output power
powerout.label Output power (VA)
multigraph in_mainsfreq
graph_title Mains frequency
graph_vlabel Frequency (Hz)
graph_category inverter
graph_info Mains frequency
freqin.info In frequency
freqin.label In frequency (Hz)
freqout.info Out frequency
freqout.label Out frequency (Hz)
`
func (m *Munin) ServeMuninConfigHTTP(rw http.ResponseWriter, r *http.Request) {
output := muninConfig
_, err := rw.Write([]byte(output))
if err != nil {
fmt.Printf("%v\n", err)
}
}
func (m *Munin) run() {
muninValues := &muninData{
status: &mk2driver.Mk2Info{},
}
for {
select {
case e := <-m.C():
if e.Valid {
calcMuninValues(muninValues, e)
}
case m.muninResponse <- muninValues:
zeroMuninValues(muninValues)
}
}
}
//Munin only samples once every 5 minutes so averages have to be calculated for some values.
func calcMuninValues(muninDat *muninData, newStatus *mk2driver.Mk2Info) {
muninDat.timesUpdated++
muninVal := &muninDat.status
muninVal := muninDat.status
muninVal.OutCurrent += newStatus.OutCurrent
muninVal.InCurrent += newStatus.InCurrent
muninVal.BatCurrent += newStatus.BatCurrent
@@ -189,7 +143,7 @@ func calcMuninValues(muninDat *muninData, newStatus *mk2driver.Mk2Info) {
}
func calcMuninAverages(muninDat *muninData) {
muninVal := &muninDat.status
muninVal := muninDat.status
muninVal.OutCurrent /= float64(muninDat.timesUpdated)
muninVal.InCurrent /= float64(muninDat.timesUpdated)
muninVal.BatCurrent /= float64(muninDat.timesUpdated)
@@ -201,7 +155,7 @@ func calcMuninAverages(muninDat *muninData) {
func zeroMuninValues(muninDat *muninData) {
muninDat.timesUpdated = 0
muninVal := &muninDat.status
muninVal := muninDat.status
muninVal.OutCurrent = 0
muninVal.InCurrent = 0
muninVal.BatCurrent = 0
@@ -215,3 +169,50 @@ func zeroMuninValues(muninDat *muninData) {
muninVal.ChargeState = 0
}
type templateInput struct {
Date string `json:"date"`
OutCurrent string `json:"output_current"`
OutVoltage string `json:"output_voltage"`
OutPower string `json:"output_power"`
InCurrent string `json:"input_current"`
InVoltage string `json:"input_voltage"`
InPower string `json:"input_power"`
InMinOut string
BatVoltage string `json:"battery_voltage"`
BatCurrent string `json:"battery_current"`
BatPower string `json:"battery_power"`
BatCharge string `json:"battery_charge"`
InFreq string `json:"input_frequency"`
OutFreq string `json:"output_frequency"`
}
func buildTemplateInput(status *mk2driver.Mk2Info) *templateInput {
outPower := status.OutVoltage * status.OutCurrent
inPower := status.InCurrent * status.InVoltage
newInput := &templateInput{
Date: status.Timestamp.Format(time.RFC1123Z),
OutCurrent: fmt.Sprintf("%.2f", status.OutCurrent),
OutVoltage: fmt.Sprintf("%.2f", status.OutVoltage),
OutPower: fmt.Sprintf("%.2f", outPower),
InCurrent: fmt.Sprintf("%.2f", status.InCurrent),
InVoltage: fmt.Sprintf("%.2f", status.InVoltage),
InFreq: fmt.Sprintf("%.2f", status.InFrequency),
OutFreq: fmt.Sprintf("%.2f", status.OutFrequency),
InPower: fmt.Sprintf("%.2f", inPower),
InMinOut: fmt.Sprintf("%.2f", inPower-outPower),
BatCurrent: fmt.Sprintf("%.2f", status.BatCurrent),
BatVoltage: fmt.Sprintf("%.2f", status.BatVoltage),
BatPower: fmt.Sprintf("%.2f", status.BatVoltage*status.BatCurrent),
BatCharge: fmt.Sprintf("%.2f", status.ChargeState*100),
}
return newInput
}

View File

@@ -0,0 +1,82 @@
package munin
const muninConfig = `multigraph in_batvolt
graph_title Battery Voltage
graph_vlabel Voltage (V)
graph_category inverter
graph_info Battery voltage
volt.info Voltage of battery
volt.label Voltage of battery (V)
multigraph in_batcharge
graph_title Battery Charge
graph_vlabel Charge (%)
graph_category inverter
graph_info Battery charge
charge.info Estimated charge of battery
charge.label Battery charge (%)
multigraph in_batcurrent
graph_title Battery Current
graph_vlabel Current (A)
graph_category inverter
graph_info Battery current
current.info Battery current
current.label Battery current (A)
multigraph in_batpower
graph_title Battery Power
graph_vlabel Power (W)
graph_category inverter
graph_info Battery power
power.info Battery power
power.label Battery power (W)
multigraph in_mainscurrent
graph_title Mains Current
graph_vlabel Current (A)
graph_category inverter
graph_info Mains current
currentin.info Input current
currentin.label Input current (A)
currentout.info Output current
currentout.label Output current (A)
multigraph in_mainsvoltage
graph_title Mains Voltage
graph_vlabel Voltage (V)
graph_category inverter
graph_info Mains voltage
voltagein.info Input voltage
voltagein.label Input voltage (V)
voltageout.info Output voltage
voltageout.label Output voltage (V)
multigraph in_mainspower
graph_title Mains Power
graph_vlabel Power (VA)
graph_category inverter
graph_info Mains power
powerin.info Input power
powerin.label Input power (VA)
powerout.info Output power
powerout.label Output power (VA)
multigraph in_mainsfreq
graph_title Mains frequency
graph_vlabel Frequency (Hz)
graph_category inverter
graph_info Mains frequency
freqin.info In frequency
freqin.label In frequency (Hz)
freqout.info Out frequency
freqout.label Out frequency (Hz)
`

View File

@@ -28,14 +28,15 @@ 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.
*/
package webgui
package prometheus
import (
"github.com/diebietse/invertergui/mk2driver"
"github.com/prometheus/client_golang/prometheus"
)
type prometheusUpdater struct {
type Prometheus struct {
mk2driver.Mk2
batteryVoltage prometheus.Gauge
batteryCharge prometheus.Gauge
batteryCurrent prometheus.Gauge
@@ -50,8 +51,9 @@ type prometheusUpdater struct {
mainsFreqOut prometheus.Gauge
}
func newPrometheusUpdater() *prometheusUpdater {
tmp := &prometheusUpdater{
func NewPrometheus(mk2 mk2driver.Mk2) {
tmp := &Prometheus{
Mk2: mk2,
batteryVoltage: prometheus.NewGauge(prometheus.GaugeOpts{
Name: "battery_voltage_v",
Help: "Voltage of the battery.",
@@ -101,7 +103,8 @@ func newPrometheusUpdater() *prometheusUpdater {
Help: "Mains frequency at inverter output",
}),
}
prometheus.MustRegister(tmp.batteryVoltage,
prometheus.MustRegister(
tmp.batteryVoltage,
tmp.batteryCharge,
tmp.batteryCurrent,
tmp.batteryPower,
@@ -114,21 +117,30 @@ func newPrometheusUpdater() *prometheusUpdater {
tmp.mainsFreqIn,
tmp.mainsFreqOut,
)
return tmp
go tmp.run()
}
func (pu *prometheusUpdater) updatePrometheus(newStatus *mk2driver.Mk2Info) {
s := newStatus
pu.batteryVoltage.Set(s.BatVoltage)
pu.batteryCharge.Set(newStatus.ChargeState * 100)
pu.batteryCurrent.Set(s.BatCurrent)
pu.batteryPower.Set(s.BatVoltage * s.BatCurrent)
pu.mainsCurrentIn.Set(s.InCurrent)
pu.mainsCurrentOut.Set(s.OutCurrent)
pu.mainsVoltageIn.Set(s.InVoltage)
pu.mainsVoltageOut.Set(s.OutVoltage)
pu.mainsPowerIn.Set(s.InVoltage * s.InCurrent)
pu.mainsPowerOut.Set(s.OutVoltage * s.OutCurrent)
pu.mainsFreqIn.Set(s.InFrequency)
pu.mainsFreqOut.Set(s.OutFrequency)
func (p *Prometheus) run() {
for e := range p.C() {
if e.Valid {
p.updatePrometheus(e)
}
}
}
func (p *Prometheus) updatePrometheus(newStatus *mk2driver.Mk2Info) {
s := newStatus
p.batteryVoltage.Set(s.BatVoltage)
p.batteryCharge.Set(newStatus.ChargeState * 100)
p.batteryCurrent.Set(s.BatCurrent)
p.batteryPower.Set(s.BatVoltage * s.BatCurrent)
p.mainsCurrentIn.Set(s.InCurrent)
p.mainsCurrentOut.Set(s.OutCurrent)
p.mainsVoltageIn.Set(s.InVoltage)
p.mainsVoltageOut.Set(s.OutVoltage)
p.mainsPowerIn.Set(s.InVoltage * s.InCurrent)
p.mainsPowerOut.Set(s.OutVoltage * s.OutCurrent)
p.mainsFreqIn.Set(s.InFrequency)
p.mainsFreqOut.Set(s.OutFrequency)
}

View File

@@ -28,7 +28,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.
*/
package webgui
package webui
import (
"fmt"
@@ -50,24 +50,19 @@ const (
)
type WebGui struct {
mk2driver.Mk2
stopChan chan struct{}
muninRespChan chan muninData
poller mk2driver.Mk2
wg sync.WaitGroup
hub *websocket.Hub
pu *prometheusUpdater
wg sync.WaitGroup
hub *websocket.Hub
}
func NewWebGui(source mk2driver.Mk2) *WebGui {
w := new(WebGui)
w.muninRespChan = make(chan muninData)
w.stopChan = make(chan struct{})
w.poller = source
w.pu = newPrometheusUpdater()
w.hub = websocket.NewHub()
w := &WebGui{
stopChan: make(chan struct{}),
Mk2: source,
hub: websocket.NewHub(),
}
w.wg.Add(1)
go w.dataPoll()
return w
@@ -99,14 +94,6 @@ type templateInput struct {
LedMap map[string]string `json:"led_map"`
}
func (w *WebGui) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
http.ServeFile(rw, r, "./frontend/index.html")
}
func (w *WebGui) ServeJS(rw http.ResponseWriter, r *http.Request) {
http.ServeFile(rw, r, "./frontend/js/controller.js")
}
func (w *WebGui) ServeHub(rw http.ResponseWriter, r *http.Request) {
w.hub.ServeHTTP(rw, r)
}
@@ -176,21 +163,15 @@ func (w *WebGui) Stop() {
// dataPoll waits for data from the w.poller channel. It will send its currently stored status
// to respChan if anything reads from it.
func (w *WebGui) dataPoll() {
pollChan := w.poller.C()
var muninValues muninData
for {
select {
case s := <-pollChan:
case s := <-w.C():
if s.Valid {
calcMuninValues(&muninValues, s)
w.pu.updatePrometheus(s)
err := w.hub.Broadcast(buildTemplateInput(s))
if err != nil {
log.Printf("Could not send update to clients: %v", err)
}
}
case w.muninRespChan <- muninValues:
zeroMuninValues(&muninValues)
case <-w.stopChan:
w.wg.Done()
return

View File

@@ -28,7 +28,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.
*/
package webgui
package webui
import (
"fmt"