-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmain.go
96 lines (81 loc) · 2.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package main
import (
"container/ring"
"encoding/json"
"flag"
"fmt"
"net/http"
"os"
"sync"
teleinfo "github.com/j-vizcaino/goteleinfo"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func readFrames(reader teleinfo.Reader, framesChan chan<- teleinfo.Frame) {
for {
frame, err := reader.ReadFrame()
if err != nil {
fmt.Printf("Error reading Teleinfo frame: %s\n", err)
continue
}
framesChan <- frame
}
}
func main() {
var serialDevice string
var mode string
var listenAddress string
var framesCount int
flag.StringVar(&serialDevice, "device", "/dev/ttyUSB0", "Serial port to read frames from")
flag.StringVar(&mode, "mode", "historic", "Teleinfo mode standard or historic")
flag.StringVar(&listenAddress, "listen-address", "localhost:9000", "HTTP service listen address")
flag.IntVar(&framesCount, "frames-count", 20, "Number of Teleinfo frames to serve under /frames")
flag.Parse()
if mode != "historic" && mode != "standard" {
flag.PrintDefaults()
os.Exit(1)
}
port, err := teleinfo.OpenPort(serialDevice, mode)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer port.Close()
framesChan := make(chan teleinfo.Frame, 10)
framesBuffer := ring.New(framesCount)
mutex := &sync.Mutex{}
// Read Teleinfo frames and send them into framesChan
go readFrames(teleinfo.NewReader(port, &mode), framesChan)
// Enqueue teleinfo.Frame into a fixed-length ring buffer
go func() {
for frame := range framesChan {
mutex.Lock()
framesBuffer.Value = frame
framesBuffer = framesBuffer.Next()
mutex.Unlock()
}
}()
http.HandleFunc("/frames", func(w http.ResponseWriter, req *http.Request) {
// Convert ring into a slice of teleinfo.Frame for JSON marshalling
mutex.Lock()
frames := make([]teleinfo.Frame, 0, framesCount)
framesBuffer.Do(func(v interface{}) {
if v == nil {
return
}
f := v.(teleinfo.Frame)
frames = append(frames, f)
})
mutex.Unlock()
// Render JSON
doc, _ := json.Marshal(frames)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(doc)
})
http.Handle("/metrics", promhttp.Handler())
fmt.Printf("Starting HTTP service on %s, handling /frames and /metrics\n", listenAddress)
if err := http.ListenAndServe(listenAddress, nil); err != nil {
fmt.Printf("Unable to start HTTP server: %s", err)
os.Exit(1)
}
}