package main import ( "flag" "fmt" "log" "os" "strconv" "time" "github.com/hashicorp/logutils" ) func getEnvFloat64(env string, def float64) (val float64) { osVal := os.Getenv(env) if osVal == "" { return def } var err error if val, err = strconv.ParseFloat(osVal, 64); err != nil { log.Fatalf("[ERROR] Unable to parse floating point number from environment variable (%s): %v", env, err) } return } func getEnvInt(env string, def int) (ret int) { val := os.Getenv(env) if val == "" { return def } ret, err := strconv.Atoi(val) if err != nil { log.Fatalf("[ERROR] Environment variable is not of numeric type: %v\n", env) } return } func getEnvString(env, def string) (val string) { val = os.Getenv(env) if val == "" { return def } return } func getEnvBool(env string, def bool) (val bool) { osVal := os.Getenv(env) if osVal == "" { return def } var err error if val, err = strconv.ParseBool(osVal); err != nil { log.Fatalf("[ERROR] Environment variable is not of boolean type: %v\n", env) } return } func setLogLevel(l int) { switch { case l <= 20: config.Log.SetMinLevel(logutils.LogLevel("ERROR")) case l > 20 && l <= 40: config.Log.SetMinLevel(logutils.LogLevel("WARNING")) case l > 40 && l <= 60: config.Log.SetMinLevel(logutils.LogLevel("INFO")) case l > 60 && l <= 80: config.Log.SetMinLevel(logutils.LogLevel("DEBUG")) case l > 80: config.Log.SetMinLevel(logutils.LogLevel("TRACE")) } } func initialize() { var ( tz string dt string err error ) flag.IntVar(&config.LogLevel, "log", getEnvInt("LOG_LEVEL", 0), "(LOG_LEVEL) Set the log verbosity.", ) flag.Float64Var(&config.SunRiseSet.Latitude, "latitude", getEnvFloat64("LATITUDE", 38.749020), "(LATITUDE) Latitude for the sunset/sunrise calculation.", ) flag.Float64Var(&config.SunRiseSet.Longitude, "longitude", getEnvFloat64("LONGITUDE", -90.521360), "(LONGITUDE) Longitude for the sunrise/sunset calculation.", ) flag.StringVar(&tz, "timezone", getEnvString("TIMEZONE", "America/Chicago"), "(TIMEZONE) Timezone for the sunrise/sunset calculation.", ) flag.StringVar(&dt, "date", getEnvString("DATE", time.Now().Format(config.TimeFormat)), "(DATE) Date to use for sunrise/sunset calculation.", ) flag.BoolVar(&config.NextSunrise, "next-sunrise", getEnvBool("SUNRISE", false), "(NEXT) Return the number of seconds until the next sunrise.", ) flag.BoolVar(&config.NextSunset, "next-sunset", getEnvBool("SUNSET", false), "(NEXT) Return the number of seconds until the next sunrise.", ) flag.StringVar(&config.Host, "host", getEnvString("HOST", ""), "(HOST) Hostname or IP address of device.", ) flag.IntVar(&config.DeviceID, "device-id", getEnvInt("DEVICE_ID", 0), "(DEVICE_ID) For devices with multiple switchable elements, the\ndevice-id is used to identify the switch port.\nIDs start at 0.", ) flag.BoolVar(&config.GetState, "get-state", getEnvBool("GET_STATE", false), "(ON) Get the power state of the device.", ) flag.BoolVar(&config.On, "on", getEnvBool("ON", false), "(ON) Turn the device on.", ) flag.BoolVar(&config.Off, "off", getEnvBool("OFF", false), "(OFF) Turn the device off.", ) flag.Parse() setLogLevel(config.LogLevel) log.SetOutput(config.Log) // check to make sure options were formatted correctly and can be parsed config.CalculateDate, err = time.Parse(config.TimeFormat, dt) if err != nil { runError(fmt.Sprintf("Unable to parse time: %v\n", err)) } config.TimeZone, err = time.LoadLocation(tz) if err != nil { runError(fmt.Sprintf("Unable to parse time zone: %v\n", err)) } // check to see if the program was called correctly if config.On && config.Off { runError("Can not set '-on' and '-off' at the same time.") } if config.Host == "" && (config.On || config.Off || config.GetState) { runError("Must supply '-host' with '-on', '-off', '-get-state'.") } if config.NextSunrise && config.NextSunset { runError("Can not set '-next-sunrise' and '-next-sunset' at the same time.") } // Get timezone offset _, tzOffset := config.CalculateDate.In(config.TimeZone).Zone() config.SunRiseSet.UtcOffset = float64(tzOffset / 60 / 60) } func runError(errorMsg string) { flag.PrintDefaults() fmt.Printf("\n\n") fmt.Printf("[ERROR] %s\n", errorMsg) os.Exit(1) }