@@ -3,10 +3,12 @@ package main
33import (
44 "bufio"
55 "errors"
6+ "fmt"
67 "log"
78 "net/http"
89 "strconv"
910 "strings"
11+ "time"
1012
1113 "github.com/alecthomas/kingpin/v2"
1214 "github.com/prometheus/client_golang/prometheus"
@@ -25,20 +27,28 @@ type Status struct {
2527var logger = log .Default ()
2628var ErrInvalidFormat = errors .New ("invalid format" )
2729
30+ const (
31+ expectedDataFields = 3
32+ keyValueLength = 2
33+ defaultBaudRate = 115200
34+ defaultDataBits = 8
35+ readHeaderTimeout = 5 * time .Second
36+ )
37+
2838func parser (data string ) (Status , error ) {
2939 data = strings .TrimSuffix (data , "\r \n " )
3040 splits := strings .Split (data , "," )
3141 result := Status {}
3242
33- if len (splits ) != 3 {
43+ if len (splits ) != expectedDataFields {
3444 logger .Println ("invalid format" , data )
3545 return Status {}, ErrInvalidFormat
3646 }
3747
3848 for _ , split := range splits {
3949 var err error
4050 keyValue := strings .Split (split , "=" )
41- if len (keyValue ) != 2 {
51+ if len (keyValue ) != keyValueLength {
4252 continue
4353 }
4454
@@ -62,20 +72,19 @@ func parser(data string) (Status, error) {
6272func recordMetrics () error {
6373 port , err := serial .Open (* deviceName , & serial.Mode {})
6474 if err != nil {
65- return err
75+ return fmt . Errorf ( "open serial port: %w" , err )
6676 }
6777 mode := & serial.Mode {
68- BaudRate : 115200 ,
78+ BaudRate : defaultBaudRate ,
6979 Parity : serial .NoParity ,
70- DataBits : 8 ,
80+ DataBits : defaultDataBits ,
7181 StopBits : serial .OneStopBit ,
7282 }
7383 if err := port .SetMode (mode ); err != nil {
74- return err
84+ return fmt . Errorf ( "set mode: %w" , err )
7585 }
76- _ , err = port .Write ([]byte ("STA\r \n " ))
77- if err != nil {
78- return err
86+ if _ , err := port .Write ([]byte ("STA\r \n " )); err != nil {
87+ return fmt .Errorf ("write start command: %w" , err )
7988 }
8089
8190 defer func () {
@@ -104,7 +113,10 @@ func recordMetrics() error {
104113 humidity .Set (stat .hum )
105114 }
106115
107- return err
116+ if err := scanner .Err (); err != nil {
117+ return fmt .Errorf ("scan: %w" , err )
118+ }
119+ return nil
108120}
109121
110122var (
@@ -130,21 +142,38 @@ func run() error {
130142 http .HandleFunc ("/" , func (w http.ResponseWriter , request * http.Request ) {
131143 w .Header ().Set ("Content-Type" , "text/html" )
132144 // language=HTML
133- _ , err := w .Write ([]byte (`<html><head><title>UD-CO2S Exporter</title></head><body><a href="/metrics">metrics</a></body></html>` ))
145+ _ , err := w .Write ([]byte (`<html><head><title>UD-CO2S Exporter</title></head><body>` +
146+ `<a href="/metrics">metrics</a></body></html>` ))
134147 if err != nil {
135148 return
136149 }
137150 })
138151 e .Go (func () error {
139- return http .ListenAndServe (* addr , nil )
152+ server := & http.Server {
153+ Addr : * addr ,
154+ ReadHeaderTimeout : readHeaderTimeout ,
155+ }
156+ if err := server .ListenAndServe (); err != nil {
157+ return fmt .Errorf ("listen and serve: %w" , err )
158+ }
159+ return nil
140160 })
141161
142- return e .Wait ()
162+ if err := e .Wait (); err != nil {
163+ return fmt .Errorf ("run error: %w" , err )
164+ }
165+ return nil
143166}
144167
145168var (
146- deviceName = kingpin .Flag ("device.name" , "Specify the UD-CO2S device path.(default /dev/ttyACM0)" ).Default ("/dev/ttyACM0" ).String ()
147- addr = kingpin .Flag ("exporter.addr" , "Specifies the address on which the exporter listens (default :9233)" ).Default (":9233" ).String ()
169+ deviceName = kingpin .
170+ Flag ("device.name" , "Specify the UD-CO2S device path.(default /dev/ttyACM0)" ).
171+ Default ("/dev/ttyACM0" ).
172+ String ()
173+ addr = kingpin .
174+ Flag ("exporter.addr" , "Specifies the address on which the exporter listens (default :9233)" ).
175+ Default (":9233" ).
176+ String ()
148177)
149178
150179func main () {
0 commit comments