From 2456f45836b0054e756d44451f7644879ecfef76 Mon Sep 17 00:00:00 2001 From: Nicholas Thompson Date: Thu, 7 Mar 2019 19:04:15 +0200 Subject: [PATCH] Added golangci linting and improved what was required --- .golangci.yml | 29 +++++ Makefile | 6 +- cmd/guimock/main.go | 3 +- cmd/guimock/mock.go | 90 -------------- cmd/invertercli/invertercli.go | 8 +- cmd/invertergui/main.go | 2 +- frontend/binary.go | 12 +- mk2if/mk2.go | 211 +++++++++++++++------------------ mk2if/mk2interface.go | 1 - mk2if/mockmk2.go | 71 +++++++++++ webgui/munin.go | 9 +- webgui/webgui.go | 10 +- webgui/webgui_test.go | 34 +++--- websocket/client.go | 11 +- websocket/hub.go | 2 +- 15 files changed, 244 insertions(+), 255 deletions(-) create mode 100644 .golangci.yml delete mode 100644 cmd/guimock/mock.go create mode 100644 mk2if/mockmk2.go diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..aa9991d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,29 @@ +run: + deadline: 10m + +linters: + enable-all: false + enable: + # Enabled by default in golangci-lint v1.13.2 + - deadcode + - errcheck + - govet + - ineffassign + - typecheck + - varcheck + # Disabled by default in golangci-lint v1.13.2 + - dupl + - goconst + - gofmt + - golint + - unconvert + # The following result in high memory usage (>1GB) + # https://github.com/golangci/golangci-lint/issues/337 + - staticcheck + - structcheck + - gosimple + - unused + +issues: + max-per-linter: 0 + max-same-issues: 0 diff --git a/Makefile b/Makefile index e9107eb..3827a84 100644 --- a/Makefile +++ b/Makefile @@ -29,8 +29,7 @@ .PHONY: test install gofmt docker statik build: - go build ./cmd/invertergui/ - go build ./cmd/invertercli/ + go build ./cmd/... all: build gofmt test @@ -51,3 +50,6 @@ docker: statik: statik -p=frontend -src=./frontend/root + +lint: + golangci-lint run diff --git a/cmd/guimock/main.go b/cmd/guimock/main.go index 3441ce8..da02c08 100644 --- a/cmd/guimock/main.go +++ b/cmd/guimock/main.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/hpdvanwyk/invertergui/frontend" + "github.com/hpdvanwyk/invertergui/mk2if" "github.com/hpdvanwyk/invertergui/webgui" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -13,7 +14,7 @@ import ( func main() { addr := flag.String("addr", ":8080", "TCP address to listen on.") - mk2 := NewMk2Mock() + mk2 := mk2if.NewMk2Mock() gui := webgui.NewWebGui(mk2) http.Handle("/", frontend.NewStatic()) diff --git a/cmd/guimock/mock.go b/cmd/guimock/mock.go deleted file mode 100644 index cdeda43..0000000 --- a/cmd/guimock/mock.go +++ /dev/null @@ -1,90 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/hpdvanwyk/invertergui/mk2if" -) - -type mock struct { - c chan *mk2if.Mk2Info -} - -func NewMk2Mock() mk2if.Mk2If { - tmp := &mock{ - c: make(chan *mk2if.Mk2Info, 1), - } - go tmp.genMockValues() - return tmp -} - -func genBaseLeds(state mk2if.LEDstate) map[mk2if.Led]mk2if.LEDstate { - return map[mk2if.Led]mk2if.LEDstate{ - mk2if.LedMain: state, - mk2if.LedAbsorption: state, - mk2if.LedBulk: state, - mk2if.LedFloat: state, - mk2if.LedInverter: state, - mk2if.LedOverload: state, - mk2if.LedLowBattery: state, - mk2if.LedTemperature: state, - } -} - -func (m *mock) GetMk2Info() *mk2if.Mk2Info { - return &mk2if.Mk2Info{ - OutCurrent: 2.0, - InCurrent: 2.3, - OutVoltage: 230.0, - InVoltage: 230.1, - BatVoltage: 25, - BatCurrent: -10, - InFrequency: 50, - OutFrequency: 50, - ChargeState: 1, - Errors: nil, - Timestamp: time.Now(), - LEDs: genBaseLeds(mk2if.LedOff), - } -} - -func (m *mock) C() chan *mk2if.Mk2Info { - return m.c -} - -func (m *mock) Close() { - -} - -func (m *mock) genMockValues() { - mult := 1.0 - ledState := mk2if.LedOff - for { - input := &mk2if.Mk2Info{ - OutCurrent: 2.0 * mult, - InCurrent: 2.3 * mult, - OutVoltage: 230.0 * mult, - InVoltage: 230.1 * mult, - BatVoltage: 25 * mult, - BatCurrent: -10 * mult, - InFrequency: 50 * mult, - OutFrequency: 50 * mult, - ChargeState: 1 * mult, - Errors: nil, - Timestamp: time.Now(), - Valid: true, - LEDs: genBaseLeds(ledState), - } - - ledState = (ledState + 1) % 3 - - mult = mult - 0.1 - if mult < 0 { - mult = 1.0 - } - fmt.Printf("Sending\n") - m.c <- input - time.Sleep(1 * time.Second) - } -} diff --git a/cmd/invertercli/invertercli.go b/cmd/invertercli/invertercli.go index e1fe897..6cafb6d 100644 --- a/cmd/invertercli/invertercli.go +++ b/cmd/invertercli/invertercli.go @@ -3,14 +3,15 @@ package main import ( "flag" "fmt" - "github.com/hpdvanwyk/invertergui/mk2if" - "github.com/mikepb/go-serial" "io" "log" "net" "os" "os/signal" "syscall" + + "github.com/hpdvanwyk/invertergui/mk2if" + "github.com/mikepb/go-serial" ) // Basic CLI to serve as example lib usage @@ -46,10 +47,11 @@ func main() { } defer p.Close() mk2, err := mk2if.NewMk2Connection(p) - defer mk2.Close() if err != nil { panic(err) } + defer mk2.Close() + c := mk2.C() sigterm := make(chan os.Signal, 1) signal.Notify(sigterm, syscall.SIGTERM, os.Interrupt) diff --git a/cmd/invertergui/main.go b/cmd/invertergui/main.go index a1a4cb6..0ef9e0e 100644 --- a/cmd/invertergui/main.go +++ b/cmd/invertergui/main.go @@ -76,10 +76,10 @@ func main() { } defer p.Close() mk2, err := mk2if.NewMk2Connection(p) - defer mk2.Close() if err != nil { panic(err) } + defer mk2.Close() gui := webgui.NewWebGui(mk2) diff --git a/frontend/binary.go b/frontend/binary.go index 3935a59..a42ec02 100644 --- a/frontend/binary.go +++ b/frontend/binary.go @@ -7,20 +7,10 @@ import ( "net/http" ) -type static struct { - http.FileSystem -} - func NewStatic() http.Handler { statikFs, err := fs.New() if err != nil { log.Fatal(err) } - return &static{ - FileSystem: statikFs, - } -} - -func (s *static) ServeHTTP(w http.ResponseWriter, r *http.Request) { - http.FileServer(s).ServeHTTP(w, r) + return http.FileServer(statikFs) } diff --git a/mk2if/mk2.go b/mk2if/mk2.go index 8fb04a5..f597f90 100644 --- a/mk2if/mk2.go +++ b/mk2if/mk2.go @@ -16,70 +16,67 @@ type scaling struct { } type mk2Ser struct { - info *Mk2Info - report *Mk2Info - p io.ReadWriter - sc []scaling - scN int - run chan struct{} - locked bool - sync.RWMutex - infochan chan *Mk2Info - wg sync.WaitGroup + info *Mk2Info + p io.ReadWriter + scales []scaling + scaleCount int + run chan struct{} + frameLock bool + infochan chan *Mk2Info + wg sync.WaitGroup } func NewMk2Connection(dev io.ReadWriter) (Mk2If, error) { mk2 := &mk2Ser{} mk2.p = dev mk2.info = &Mk2Info{} - mk2.report = &Mk2Info{} - mk2.scN = 0 - mk2.locked = false - mk2.sc = make([]scaling, 0) + mk2.scaleCount = 0 + mk2.frameLock = false + mk2.scales = make([]scaling, 0, 14) mk2.setTarget() mk2.run = make(chan struct{}) mk2.infochan = make(chan *Mk2Info) mk2.wg.Add(1) - go mk2.frameLock() + go mk2.frameLocker() return mk2, nil } // Locks to incoming frame. -func (mk2 *mk2Ser) frameLock() { +func (m *mk2Ser) frameLocker() { frame := make([]byte, 256) var size byte for { select { - case <-mk2.run: - mk2.wg.Done() + case <-m.run: + m.wg.Done() return default: } - if mk2.locked { - size = mk2.readByte() - l, err := io.ReadFull(mk2.p, frame[0:int(size)+1]) + if m.frameLock { + size = m.readByte() + l, err := io.ReadFull(m.p, frame[0:int(size)+1]) if err != nil { - mk2.addError(fmt.Errorf("Read Error: %v", err)) - mk2.locked = false + m.addError(fmt.Errorf("Read Error: %v", err)) + m.frameLock = false } else if l != int(size)+1 { - mk2.addError(errors.New("Read Length Error")) - mk2.locked = false + m.addError(errors.New("Read Length Error")) + m.frameLock = false } else { - mk2.handleFrame(size, frame[0:int(size+1)]) + m.handleFrame(size, frame[0:int(size+1)]) } } else { - tmp := mk2.readByte() + tmp := m.readByte() if tmp == 0xff || tmp == 0x20 { - l, err := io.ReadFull(mk2.p, frame[0:int(size)]) + l, err := io.ReadFull(m.p, frame[0:int(size)]) if err != nil { - mk2.addError(fmt.Errorf("Read Error: %v", err)) + m.addError(fmt.Errorf("Read Error: %v", err)) time.Sleep(1 * time.Second) } else if l != int(size) { - mk2.addError(errors.New("Read Length Error")) + m.addError(errors.New("Read Length Error")) } else { if checkChecksum(size, tmp, frame[0:int(size)]) { - mk2.locked = true + m.frameLock = true log.Printf("Locked") } } @@ -90,109 +87,98 @@ func (mk2 *mk2Ser) frameLock() { } // Close Mk2 -func (mk2 *mk2Ser) Close() { - close(mk2.run) - mk2.wg.Wait() +func (m *mk2Ser) Close() { + close(m.run) + m.wg.Wait() } -// Returns last known state with all reported errors since previous poll. -// Mk2Info.Valid will be false if no polling has completed. -func (mk2 *mk2Ser) GetMk2Info() *Mk2Info { - mk2.RLock() - defer mk2.RUnlock() - return mk2.report +func (m *mk2Ser) C() chan *Mk2Info { + return m.infochan } -func (mk2 *mk2Ser) C() chan *Mk2Info { - return mk2.infochan -} - -func (mk2 *mk2Ser) readByte() byte { +func (m *mk2Ser) readByte() byte { buffer := make([]byte, 1) - _, err := io.ReadFull(mk2.p, buffer) + _, err := io.ReadFull(m.p, buffer) if err != nil { - mk2.addError(fmt.Errorf("Read error: %v", err)) + m.addError(fmt.Errorf("Read error: %v", err)) return 0 } return buffer[0] } // Adds error to error slice. -func (mk2 *mk2Ser) addError(err error) { - if mk2.info.Errors == nil { - mk2.info.Errors = make([]error, 0) +func (m *mk2Ser) addError(err error) { + if m.info.Errors == nil { + m.info.Errors = make([]error, 0) } - mk2.info.Errors = append(mk2.info.Errors, err) - mk2.info.Valid = false + m.info.Errors = append(m.info.Errors, err) + m.info.Valid = false } // Updates report. -func (mk2 *mk2Ser) updateReport() { - mk2.Lock() - defer mk2.Unlock() - mk2.info.Timestamp = time.Now() - mk2.report = mk2.info +func (m *mk2Ser) updateReport() { + m.info.Timestamp = time.Now() select { - case mk2.infochan <- mk2.info: + case m.infochan <- m.info: default: } - mk2.info = &Mk2Info{} + m.info = &Mk2Info{} } // Checks for valid frame and chooses decoding. -func (mk2 *mk2Ser) handleFrame(l byte, frame []byte) { +func (m *mk2Ser) handleFrame(l byte, frame []byte) { if checkChecksum(l, frame[0], frame[1:]) { switch frame[0] { case 0xff: switch frame[1] { case 0x56: // V - mk2.versionDecode(frame[2:]) + m.versionDecode(frame[2:]) case 0x57: switch frame[2] { case 0x8e: - mk2.scaleDecode(frame[2:]) + m.scaleDecode(frame[2:]) case 0x85: - mk2.stateDecode(frame[2:]) + m.stateDecode(frame[2:]) } case 0x4C: // L - mk2.ledDecode(frame[2:]) + m.ledDecode(frame[2:]) } case 0x20: switch frame[5] { case 0x0C: - mk2.dcDecode(frame[1:]) + m.dcDecode(frame[1:]) case 0x08: - mk2.acDecode(frame[1:]) + m.acDecode(frame[1:]) } } } else { - log.Printf("Failed") - mk2.locked = false + log.Printf("Invalid incoming frame checksum: %x", frame) + m.frameLock = false } } // Set the target VBus device. -func (mk *mk2Ser) setTarget() { +func (m *mk2Ser) setTarget() { cmd := make([]byte, 3) cmd[0] = 0x41 // A cmd[1] = 0x01 cmd[2] = 0x00 - mk.sendCommand(cmd) + m.sendCommand(cmd) } // Request the scaling factor for entry 'in'. -func (mk *mk2Ser) reqScaleFactor(in byte) { +func (m *mk2Ser) reqScaleFactor(in byte) { cmd := make([]byte, 4) cmd[0] = 0x57 // W cmd[1] = 0x36 cmd[2] = in - mk.sendCommand(cmd) + m.sendCommand(cmd) } // Decode the scale factor frame. -func (mk *mk2Ser) scaleDecode(frame []byte) { +func (m *mk2Ser) scaleDecode(frame []byte) { scl := uint16(frame[2])<<8 + uint16(frame[1]) ofs := int16(uint16(frame[5])<<8 + uint16(frame[4])) @@ -203,11 +189,11 @@ func (mk *mk2Ser) scaleDecode(frame []byte) { } else { tmp.scale = math.Abs(float64(scl)) } - mk.sc = append(mk.sc, tmp) + m.scales = append(m.scales, tmp) - mk.scN++ - if mk.scN < 14 { - mk.reqScaleFactor(byte(mk.scN)) + m.scaleCount++ + if m.scaleCount < 14 { + m.reqScaleFactor(byte(m.scaleCount)) } else { log.Print("Monitoring starting.") } @@ -215,28 +201,28 @@ func (mk *mk2Ser) scaleDecode(frame []byte) { } // Decode the version number -func (mk *mk2Ser) versionDecode(frame []byte) { - mk.info.Version = 0 - mk.info.Valid = true +func (m *mk2Ser) versionDecode(frame []byte) { + m.info.Version = 0 + m.info.Valid = true for i := 0; i < 4; i++ { - mk.info.Version += uint32(frame[i]) << uint(i) * 8 + m.info.Version += uint32(frame[i]) << uint(i) * 8 } - if mk.scN < 14 { + if m.scaleCount < 14 { log.Print("Get scaling factors.") - mk.reqScaleFactor(byte(mk.scN)) + m.reqScaleFactor(byte(m.scaleCount)) } else { // Send DC status request cmd := make([]byte, 2) cmd[0] = 0x46 //F cmd[1] = 0 - mk.sendCommand(cmd) + m.sendCommand(cmd) } } // Apply scaling to float -func (mk *mk2Ser) applyScale(value float64, scale int) float64 { - return mk.sc[scale].scale * (value + mk.sc[scale].offset) +func (m *mk2Ser) applyScale(value float64, scale int) float64 { + return m.scales[scale].scale * (value + m.scales[scale].offset) } // Convert bytes->int16->float @@ -250,57 +236,57 @@ func getUnsigned(data []byte) float64 { } // Decodes DC frame. -func (mk *mk2Ser) dcDecode(frame []byte) { - mk.info.BatVoltage = mk.applyScale(getSigned(frame[5:7]), 4) +func (m *mk2Ser) dcDecode(frame []byte) { + m.info.BatVoltage = m.applyScale(getSigned(frame[5:7]), 4) - usedC := mk.applyScale(getUnsigned(frame[7:10]), 5) - chargeC := mk.applyScale(getUnsigned(frame[10:13]), 5) - mk.info.BatCurrent = usedC - chargeC + usedC := m.applyScale(getUnsigned(frame[7:10]), 5) + chargeC := m.applyScale(getUnsigned(frame[10:13]), 5) + m.info.BatCurrent = usedC - chargeC - mk.info.OutFrequency = 10 / (mk.applyScale(float64(frame[13]), 7)) + m.info.OutFrequency = 10 / (m.applyScale(float64(frame[13]), 7)) // Send L1 status request cmd := make([]byte, 2) cmd[0] = 0x46 //F cmd[1] = 1 - mk.sendCommand(cmd) + m.sendCommand(cmd) } // Decodes AC frame. -func (mk *mk2Ser) acDecode(frame []byte) { - mk.info.InVoltage = mk.applyScale(getSigned(frame[5:7]), 0) - mk.info.InCurrent = mk.applyScale(getSigned(frame[7:9]), 1) - mk.info.OutVoltage = mk.applyScale(getSigned(frame[9:11]), 2) - mk.info.OutCurrent = mk.applyScale(getSigned(frame[11:13]), 3) +func (m *mk2Ser) acDecode(frame []byte) { + m.info.InVoltage = m.applyScale(getSigned(frame[5:7]), 0) + m.info.InCurrent = m.applyScale(getSigned(frame[7:9]), 1) + m.info.OutVoltage = m.applyScale(getSigned(frame[9:11]), 2) + m.info.OutCurrent = m.applyScale(getSigned(frame[11:13]), 3) if frame[13] == 0xff { - mk.info.InFrequency = 0 + m.info.InFrequency = 0 } else { - mk.info.InFrequency = 10 / (mk.applyScale(float64(frame[13]), 8)) + m.info.InFrequency = 10 / (m.applyScale(float64(frame[13]), 8)) } // Send status request cmd := make([]byte, 1) cmd[0] = 0x4C //F - mk.sendCommand(cmd) + m.sendCommand(cmd) } // Decode charge state of battery. -func (mk *mk2Ser) stateDecode(frame []byte) { - mk.info.ChargeState = mk.applyScale(getSigned(frame[1:3]), 13) - mk.updateReport() +func (m *mk2Ser) stateDecode(frame []byte) { + m.info.ChargeState = m.applyScale(getSigned(frame[1:3]), 13) + m.updateReport() } // Decode the LED state frame. -func (mk *mk2Ser) ledDecode(frame []byte) { +func (m *mk2Ser) ledDecode(frame []byte) { - mk.info.LEDs = getLEDs(frame[0], frame[1]) + m.info.LEDs = getLEDs(frame[0], frame[1]) // Send charge state request cmd := make([]byte, 4) cmd[0] = 0x57 //W cmd[1] = 0x30 cmd[2] = 13 - mk.sendCommand(cmd) + m.sendCommand(cmd) } // Adds active LEDs to list. @@ -322,7 +308,7 @@ func getLEDs(ledsOn, ledsBlink byte) map[Led]LEDstate { } // Adds header and trailing crc for frame to send. -func (mk2 *mk2Ser) sendCommand(data []byte) { +func (m *mk2Ser) sendCommand(data []byte) { l := len(data) dataOut := make([]byte, l+3) dataOut[0] = byte(l + 1) @@ -334,9 +320,9 @@ func (mk2 *mk2Ser) sendCommand(data []byte) { } dataOut[l+2] = cr - _, err := mk2.p.Write(dataOut) + _, err := m.p.Write(dataOut) if err != nil { - mk2.addError(fmt.Errorf("Write error: %v", err)) + m.addError(fmt.Errorf("Write error: %v", err)) } } @@ -346,8 +332,5 @@ func checkChecksum(l, t byte, d []byte) bool { for i := 0; i < len(d); i++ { cr = (cr + uint16(d[i])) % 256 } - if cr == 0 { - return true - } - return false + return cr == 0 } diff --git a/mk2if/mk2interface.go b/mk2if/mk2interface.go index 8e662c9..b620e26 100644 --- a/mk2if/mk2interface.go +++ b/mk2if/mk2interface.go @@ -73,7 +73,6 @@ type Mk2Info struct { } type Mk2If interface { - GetMk2Info() *Mk2Info C() chan *Mk2Info Close() } diff --git a/mk2if/mockmk2.go b/mk2if/mockmk2.go new file mode 100644 index 0000000..0c64b5d --- /dev/null +++ b/mk2if/mockmk2.go @@ -0,0 +1,71 @@ +package mk2if + +import ( + "fmt" + "time" +) + +type mock struct { + c chan *Mk2Info +} + +func NewMk2Mock() Mk2If { + tmp := &mock{ + c: make(chan *Mk2Info, 1), + } + go tmp.genMockValues() + return tmp +} + +func genBaseLeds(state LEDstate) map[Led]LEDstate { + return map[Led]LEDstate{ + LedMain: state, + LedAbsorption: state, + LedBulk: state, + LedFloat: state, + LedInverter: state, + LedOverload: state, + LedLowBattery: state, + LedTemperature: state, + } +} + +func (m *mock) C() chan *Mk2Info { + return m.c +} + +func (m *mock) Close() { + +} + +func (m *mock) genMockValues() { + mult := 1.0 + ledState := LedOff + for { + input := &Mk2Info{ + OutCurrent: 2.0 * mult, + InCurrent: 2.3 * mult, + OutVoltage: 230.0 * mult, + InVoltage: 230.1 * mult, + BatVoltage: 25 * mult, + BatCurrent: -10 * mult, + InFrequency: 50 * mult, + OutFrequency: 50 * mult, + ChargeState: 1 * mult, + Errors: nil, + Timestamp: time.Now(), + Valid: true, + LEDs: genBaseLeds(ledState), + } + + ledState = (ledState + 1) % 3 + + mult = mult - 0.1 + if mult < 0 { + mult = 1.0 + } + fmt.Printf("Sending\n") + m.c <- input + time.Sleep(1 * time.Second) + } +} diff --git a/webgui/munin.go b/webgui/munin.go index 161f09e..2e8c420 100644 --- a/webgui/munin.go +++ b/webgui/munin.go @@ -33,8 +33,9 @@ package webgui import ( "bytes" "fmt" - "github.com/hpdvanwyk/invertergui/mk2if" "net/http" + + "github.com/hpdvanwyk/invertergui/mk2if" ) type muninData struct { @@ -46,7 +47,7 @@ func (w *WebGui) ServeMuninHTTP(rw http.ResponseWriter, r *http.Request) { muninDat := <-w.muninRespChan if muninDat.timesUpdated == 0 { rw.WriteHeader(500) - rw.Write([]byte("No data to return.\n")) + _, _ = rw.Write([]byte("No data to return.\n")) return } calcMuninAverages(&muninDat) @@ -75,7 +76,7 @@ func (w *WebGui) ServeMuninHTTP(rw http.ResponseWriter, r *http.Request) { fmt.Fprintf(outputBuf, "freqin.value %s\n", tmpInput.InFreq) fmt.Fprintf(outputBuf, "freqout.value %s\n", tmpInput.OutFreq) - _, err := rw.Write([]byte(outputBuf.String())) + _, err := rw.Write(outputBuf.Bytes()) if err != nil { fmt.Printf("%v\n", err) } @@ -171,7 +172,7 @@ freqout.label Out frequency (Hz) //Munin only samples once every 5 minutes so averages have to be calculated for some values. func calcMuninValues(muninDat *muninData, newStatus *mk2if.Mk2Info) { - muninDat.timesUpdated += 1 + muninDat.timesUpdated++ muninVal := &muninDat.status muninVal.OutCurrent += newStatus.OutCurrent muninVal.InCurrent += newStatus.InCurrent diff --git a/webgui/webgui.go b/webgui/webgui.go index 3fea989..1c376a7 100644 --- a/webgui/webgui.go +++ b/webgui/webgui.go @@ -32,6 +32,7 @@ package webgui import ( "fmt" + "log" "net/http" "sync" "time" @@ -49,7 +50,6 @@ const ( ) type WebGui struct { - respChan chan *mk2if.Mk2Info stopChan chan struct{} muninRespChan chan muninData @@ -178,14 +178,16 @@ func (w *WebGui) Stop() { func (w *WebGui) dataPoll() { pollChan := w.poller.C() var muninValues muninData - s := &mk2if.Mk2Info{} for { select { - case s = <-pollChan: + case s := <-pollChan: if s.Valid { calcMuninValues(&muninValues, s) w.pu.updatePrometheus(s) - w.hub.Broadcast(buildTemplateInput(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) diff --git a/webgui/webgui_test.go b/webgui/webgui_test.go index dc7c019..17d16c8 100644 --- a/webgui/webgui_test.go +++ b/webgui/webgui_test.go @@ -32,10 +32,11 @@ package webgui import ( "fmt" - "github.com/hpdvanwyk/invertergui/mk2if" "reflect" "testing" "time" + + "github.com/hpdvanwyk/invertergui/mk2if" ) func TestWebGui(t *testing.T) { @@ -61,27 +62,28 @@ var templateInputTests = []templateTest{ InFrequency: 50, OutFrequency: 50, ChargeState: 1, - LedListOn: []int{mk2if.LED_MAIN, mk2if.LED_FLOAT}, + LEDs: map[mk2if.Led]mk2if.LEDstate{mk2if.LedMain: mk2if.LedOn}, Errors: nil, Timestamp: fakenow, }, output: &templateInput{ Error: nil, Date: fakenow.Format(time.RFC1123Z), - OutCurrent: "2.000", - OutVoltage: "230.000", - OutPower: "460.000", - InCurrent: "2.300", - InVoltage: "230.100", - InPower: "529.230", - InMinOut: "69.230", - BatVoltage: "25.000", - BatCurrent: "-10.000", - BatPower: "-250.000", - InFreq: "50.000", - OutFreq: "50.000", - BatCharge: "100.000", - Leds: []string{"Mains", "Float"}}, + OutCurrent: "2.00", + OutVoltage: "230.00", + OutPower: "460.00", + InCurrent: "2.30", + InVoltage: "230.10", + InPower: "529.23", + InMinOut: "69.23", + BatVoltage: "25.00", + BatCurrent: "-10.00", + BatPower: "-250.00", + InFreq: "50.00", + OutFreq: "50.00", + BatCharge: "100.00", + LedMap: map[string]string{"led_mains": "dot-green"}, + }, }, } diff --git a/websocket/client.go b/websocket/client.go index d6f19a4..03d4af4 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -17,9 +17,6 @@ const ( // Send pings to peer with this period. Must be less than pongWait. pingPeriod = (pongWait * 9) / 10 - - // Maximum message size allowed from peer. - maxMessageSize = 512 ) var upgrader = websocket.Upgrader{ @@ -52,10 +49,10 @@ func (c *Client) writePump() { for { select { case message, ok := <-c.send: - c.conn.SetWriteDeadline(time.Now().Add(writeWait)) + _ = c.conn.SetWriteDeadline(time.Now().Add(writeWait)) if !ok { // The hub closed the channel. - c.conn.WriteMessage(websocket.CloseMessage, []byte{}) + _ = c.conn.WriteMessage(websocket.CloseMessage, []byte{}) return } @@ -63,13 +60,13 @@ func (c *Client) writePump() { if err != nil { return } - w.Write(message) + _, _ = w.Write(message) if err := w.Close(); err != nil { return } case <-ticker.C: - c.conn.SetWriteDeadline(time.Now().Add(writeWait)) + _ = c.conn.SetWriteDeadline(time.Now().Add(writeWait)) if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil { return } diff --git a/websocket/hub.go b/websocket/hub.go index fff0e27..f73a165 100644 --- a/websocket/hub.go +++ b/websocket/hub.go @@ -36,7 +36,7 @@ func (h *Hub) Broadcast(message interface{}) error { if err != nil { return err } - h.broadcast <- []byte(payload) + h.broadcast <- payload return nil }