2018-10-27 14:29:11 +00:00
package main
import (
"errors"
2020-06-21 13:39:24 +00:00
"fmt"
2020-06-21 13:50:29 +00:00
"time"
2018-10-27 14:29:11 +00:00
netatmo "github.com/exzz/netatmo-api-go"
2020-06-21 13:39:24 +00:00
"github.com/sirupsen/logrus"
2018-10-27 14:29:11 +00:00
"github.com/spf13/pflag"
)
const (
envVarListenAddress = "NETATMO_EXPORTER_ADDR"
2020-06-21 13:39:24 +00:00
envVarLogLevel = "NETATMO_LOG_LEVEL"
2020-06-26 12:10:13 +00:00
envVarRefreshInterval = "NETATMO_REFRESH_INTERVAL"
2020-06-21 13:50:29 +00:00
envVarStaleDuration = "NETATMO_AGE_STALE"
2018-10-27 14:29:11 +00:00
envVarNetatmoClientID = "NETATMO_CLIENT_ID"
envVarNetatmoClientSecret = "NETATMO_CLIENT_SECRET"
envVarNetatmoUsername = "NETATMO_CLIENT_USERNAME"
envVarNetatmoPassword = "NETATMO_CLIENT_PASSWORD"
flagListenAddress = "addr"
2020-06-21 13:39:24 +00:00
flagLogLevel = "log-level"
2020-06-26 12:10:13 +00:00
flagRefreshInterval = "refresh-interval"
2020-06-21 13:50:29 +00:00
flagStaleDuration = "age-stale"
2018-10-27 14:29:11 +00:00
flagNetatmoClientID = "client-id"
flagNetatmoClientSecret = "client-secret"
flagNetatmoUsername = "username"
flagNetatmoPassword = "password"
2020-06-21 13:50:29 +00:00
2020-06-26 12:10:13 +00:00
defaultRefreshInterval = 8 * time . Minute
defaultStaleDuration = 30 * time . Minute
2018-10-27 14:29:11 +00:00
)
var (
defaultConfig = config {
2020-06-26 12:10:13 +00:00
Addr : ":9210" ,
LogLevel : logLevel ( logrus . InfoLevel ) ,
RefreshInterval : defaultRefreshInterval ,
StaleDuration : defaultStaleDuration ,
2018-10-27 14:29:11 +00:00
}
errNoBinaryName = errors . New ( "need the binary name as first argument" )
errNoListenAddress = errors . New ( "no listen address" )
errNoNetatmoClientID = errors . New ( "need a NetAtmo client ID" )
errNoNetatmoClientSecret = errors . New ( "need a NetAtmo client secret" )
errNoNetatmoUsername = errors . New ( "username can not be blank" )
errNoNetatmoPassword = errors . New ( "password can not be blank" )
)
2020-06-21 13:39:24 +00:00
type logLevel logrus . Level
func ( l * logLevel ) Type ( ) string {
return "level"
}
func ( l * logLevel ) String ( ) string {
return fmt . Sprintf ( "%s" , logrus . Level ( * l ) )
}
func ( l * logLevel ) Set ( value string ) error {
level , err := logrus . ParseLevel ( value )
if err != nil {
return err
}
* l = logLevel ( level )
return nil
}
2018-10-27 14:29:11 +00:00
type config struct {
2020-06-26 12:10:13 +00:00
Addr string
LogLevel logLevel
RefreshInterval time . Duration
StaleDuration time . Duration
Netatmo netatmo . Config
2018-10-27 14:29:11 +00:00
}
func parseConfig ( args [ ] string , getenv func ( string ) string ) ( config , error ) {
cfg := defaultConfig
if len ( args ) < 1 {
return cfg , errNoBinaryName
}
flagSet := pflag . NewFlagSet ( args [ 0 ] , pflag . ExitOnError )
2020-06-21 13:42:56 +00:00
flagSet . StringVarP ( & cfg . Addr , flagListenAddress , "a" , cfg . Addr , "Address to listen on." )
2020-06-21 13:39:24 +00:00
flagSet . Var ( & cfg . LogLevel , flagLogLevel , "Sets the minimum level output through logging." )
2020-06-26 12:10:13 +00:00
flagSet . DurationVar ( & cfg . RefreshInterval , flagRefreshInterval , cfg . RefreshInterval , "Time interval used for internal caching of NetAtmo sensor data." )
2020-06-21 13:50:29 +00:00
flagSet . DurationVar ( & cfg . StaleDuration , flagStaleDuration , cfg . StaleDuration , "Data age to consider as stale. Stale data does not create metrics anymore." )
2020-06-21 13:42:56 +00:00
flagSet . StringVarP ( & cfg . Netatmo . ClientID , flagNetatmoClientID , "i" , cfg . Netatmo . ClientID , "Client ID for NetAtmo app." )
flagSet . StringVarP ( & cfg . Netatmo . ClientSecret , flagNetatmoClientSecret , "s" , cfg . Netatmo . ClientSecret , "Client secret for NetAtmo app." )
flagSet . StringVarP ( & cfg . Netatmo . Username , flagNetatmoUsername , "u" , cfg . Netatmo . Username , "Username of NetAtmo account." )
flagSet . StringVarP ( & cfg . Netatmo . Password , flagNetatmoPassword , "p" , cfg . Netatmo . Password , "Password of NetAtmo account." )
2018-10-27 14:29:11 +00:00
flagSet . Parse ( args [ 1 : ] )
2020-06-21 13:39:24 +00:00
if err := applyEnvironment ( & cfg , getenv ) ; err != nil {
return config { } , fmt . Errorf ( "error in environment: %s" , err )
}
2018-10-27 14:29:11 +00:00
if len ( cfg . Addr ) == 0 {
2020-06-21 13:39:24 +00:00
return config { } , errNoListenAddress
2018-10-27 14:29:11 +00:00
}
if len ( cfg . Netatmo . ClientID ) == 0 {
2020-06-21 13:39:24 +00:00
return config { } , errNoNetatmoClientID
2018-10-27 14:29:11 +00:00
}
if len ( cfg . Netatmo . ClientSecret ) == 0 {
2020-06-21 13:39:24 +00:00
return config { } , errNoNetatmoClientSecret
2018-10-27 14:29:11 +00:00
}
if len ( cfg . Netatmo . Username ) == 0 {
2020-06-21 13:39:24 +00:00
return config { } , errNoNetatmoUsername
2018-10-27 14:29:11 +00:00
}
if len ( cfg . Netatmo . Password ) == 0 {
2020-06-21 13:39:24 +00:00
return config { } , errNoNetatmoPassword
2018-10-27 14:29:11 +00:00
}
2020-06-26 12:10:13 +00:00
if cfg . StaleDuration < cfg . RefreshInterval {
return config { } , fmt . Errorf ( "stale duration smaller than refresh interval: %s < %s" , cfg . StaleDuration , cfg . RefreshInterval )
}
2018-10-27 14:29:11 +00:00
return cfg , nil
}
2020-06-21 13:39:24 +00:00
func applyEnvironment ( cfg * config , getenv func ( string ) string ) error {
2018-10-27 14:29:11 +00:00
if envAddr := getenv ( envVarListenAddress ) ; envAddr != "" {
cfg . Addr = envAddr
}
2020-06-21 13:39:24 +00:00
if envLogLevel := getenv ( envVarLogLevel ) ; envLogLevel != "" {
if err := cfg . LogLevel . Set ( envLogLevel ) ; err != nil {
return err
}
}
2020-06-26 12:10:13 +00:00
if envRefreshInterval := getenv ( envVarRefreshInterval ) ; envRefreshInterval != "" {
duration , err := time . ParseDuration ( envRefreshInterval )
if err != nil {
return err
}
cfg . RefreshInterval = duration
}
2020-06-21 13:50:29 +00:00
if envStaleDuration := getenv ( envVarStaleDuration ) ; envStaleDuration != "" {
duration , err := time . ParseDuration ( envStaleDuration )
if err != nil {
return err
}
cfg . StaleDuration = duration
}
2018-10-27 14:29:11 +00:00
if envClientID := getenv ( envVarNetatmoClientID ) ; envClientID != "" {
cfg . Netatmo . ClientID = envClientID
}
if envClientSecret := getenv ( envVarNetatmoClientSecret ) ; envClientSecret != "" {
cfg . Netatmo . ClientSecret = envClientSecret
}
if envUsername := getenv ( envVarNetatmoUsername ) ; envUsername != "" {
cfg . Netatmo . Username = envUsername
}
if envPassword := getenv ( envVarNetatmoPassword ) ; envPassword != "" {
cfg . Netatmo . Password = envPassword
}
2020-06-21 13:39:24 +00:00
return nil
2018-10-27 14:29:11 +00:00
}