feat: add goreport notation

This commit is contained in:
Adrien Waksberg 2019-08-22 22:44:50 +02:00
parent 4bf2f1e02f
commit 0ad5151d98
5 changed files with 186 additions and 181 deletions

View file

@ -7,6 +7,10 @@ Which is based on [Keep A Changelog](http://keepachangelog.com/)
## Unreleased
### Added
- goreport notation
### Fixed
- too many open files close with influxdb connection

View file

@ -1,6 +1,7 @@
# Weather
[![Version](https://img.shields.io/badge/latest_version-1.0.0-green.svg)](https://git.yaegashi.fr/nishiki/weather/releases)
[![GoReport](https://goreportcard.com/badge/git.yaegashi.fr/nishiki/weather)](https://goreportcard.com/report/git.yaegashi.fr/nishiki/weather)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://git.yaegashi.fr/nishiki/weather/src/branch/master/LICENSE)
weather is a small program that fetch weather informations, and store them to influxdb

View file

@ -17,78 +17,78 @@
package main
import (
"fmt"
"io/ioutil"
"fmt"
"io/ioutil"
yaml "gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v2"
)
// Config struct contains all options
type Config struct {
InfluxDB struct {
URL string `yaml:"url"`
Database string `yaml:"database"`
Measurement string `yaml:"measurement"`
Username string `yaml:"username"`
Password string `yaml:"password"`
} `yaml:"influxdb"`
OpenWeatherMap struct {
APIKey string `yaml:"api_key"`
Units string `yaml:"units"`
} `yaml:"openweathermap"`
Cities []string `yaml:"cities"`
Interval int64 `yaml:"interval"`
InfluxDB struct {
URL string `yaml:"url"`
Database string `yaml:"database"`
Measurement string `yaml:"measurement"`
Username string `yaml:"username"`
Password string `yaml:"password"`
} `yaml:"influxdb"`
OpenWeatherMap struct {
APIKey string `yaml:"api_key"`
Units string `yaml:"units"`
} `yaml:"openweathermap"`
Cities []string `yaml:"cities"`
Interval int64 `yaml:"interval"`
}
// Load the config from a file
func (c *Config) Load(path string) error {
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
data, err := ioutil.ReadFile(path)
if err != nil {
return err
}
err = yaml.Unmarshal(data, &c)
if err != nil {
return err
}
err = yaml.Unmarshal(data, &c)
if err != nil {
return err
}
c.Defaults()
err = c.Check()
if err != nil {
return err
}
c.Defaults()
err = c.Check()
if err != nil {
return err
}
return nil
return nil
}
// Defaults set options with default value
func (c *Config) Defaults() {
if c.OpenWeatherMap.Units == "" {
c.OpenWeatherMap.Units = "metric"
}
if c.OpenWeatherMap.Units == "" {
c.OpenWeatherMap.Units = "metric"
}
if c.Interval == 0 {
c.Interval = 600
}
if c.Interval == 0 {
c.Interval = 600
}
if c.InfluxDB.URL == "" {
c.InfluxDB.URL = "http://127.0.0.1:8086"
}
if c.InfluxDB.URL == "" {
c.InfluxDB.URL = "http://127.0.0.1:8086"
}
if c.InfluxDB.Measurement == "" {
c.InfluxDB.Measurement = "weather"
}
if c.InfluxDB.Measurement == "" {
c.InfluxDB.Measurement = "weather"
}
}
// Check if the options are good
func (c *Config) Check() error {
if c.InfluxDB.Database == "" {
return fmt.Errorf("you must specify influxdb.database in config file")
}
if c.InfluxDB.Database == "" {
return fmt.Errorf("you must specify influxdb.database in config file")
}
if c.OpenWeatherMap.APIKey == "" {
return fmt.Errorf("you must specify api_key in config file")
}
if c.OpenWeatherMap.APIKey == "" {
return fmt.Errorf("you must specify api_key in config file")
}
return nil
return nil
}

84
main.go
View file

@ -17,63 +17,63 @@
package main
import (
"fmt"
"flag"
"os"
"time"
"flag"
"fmt"
"os"
"time"
)
// Options and OpenWeatherMap URI
var (
URI = "https://api.openweathermap.org/data/2.5"
CONFIG = flag.String("config", "", "config file path")
DAEMON = flag.Bool("daemon", false, "run in daemon mode")
HELP = flag.Bool("help", false, "print this help message")
URI = "https://api.openweathermap.org/data/2.5"
CONFIG = flag.String("config", "", "config file path")
DAEMON = flag.Bool("daemon", false, "run in daemon mode")
HELP = flag.Bool("help", false, "print this help message")
)
func init() {
flag.Parse()
flag.Parse()
}
func main() {
var w Weather
var w Weather
if *HELP {
flag.PrintDefaults()
os.Exit(1)
}
if *HELP {
flag.PrintDefaults()
os.Exit(1)
}
if *CONFIG == "" {
fmt.Println("you must specify a config file with -config option")
os.Exit(1)
}
if *CONFIG == "" {
fmt.Println("you must specify a config file with -config option")
os.Exit(1)
}
err := w.Config.Load(*CONFIG)
if err != nil {
fmt.Printf("%s\n", err)
os.Exit(2)
}
err := w.Config.Load(*CONFIG)
if err != nil {
fmt.Printf("%s\n", err)
os.Exit(2)
}
for {
startTime := time.Now().Unix()
for {
startTime := time.Now().Unix()
w.FetchData()
err = w.SendToInfluxDB()
if err != nil {
fmt.Printf("%s\n", err)
}
w.FetchData()
err = w.SendToInfluxDB()
if err != nil {
fmt.Printf("%s\n", err)
}
if *DAEMON == false {
if err == nil {
os.Exit(0)
} else {
os.Exit(2)
}
}
if *DAEMON == false {
if err == nil {
os.Exit(0)
} else {
os.Exit(2)
}
}
sleepTime := time.Now().Unix() - startTime + w.Config.Interval
if sleepTime > 0 {
time.Sleep(time.Duration(sleepTime) * time.Second)
}
}
sleepTime := time.Now().Unix() - startTime + w.Config.Interval
if sleepTime > 0 {
time.Sleep(time.Duration(sleepTime) * time.Second)
}
}
}

View file

@ -17,118 +17,118 @@
package main
import (
"fmt"
"net/http"
"encoding/json"
"io/ioutil"
"time"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
influx "github.com/influxdata/influxdb1-client/v2"
influx "github.com/influxdata/influxdb1-client/v2"
)
// Weather is the main struct
type Weather struct {
Config Config
WeatherDatas []WeatherData
Config Config
WeatherDatas []WeatherData
}
// WeatherData contains weather data from openweathermap
type WeatherData struct {
City string `json:"name"`
Main struct {
Humidity int `json:"humidity"`
Pressure int `json:"pressure"`
Temperature float32 `json:"temp"`
} `json:"main"`
Clouds struct {
All int `json:"all"`
} `json:"clouds"`
Rain struct {
OneHour float32 `json:"1h"`
TreeHours float32 `json:"3h"`
} `json:"rain"`
Snow struct {
OneHour float32 `json:"1h"`
TreeHours float32 `json:"3h"`
} `json:"snow"`
Wind struct {
Speed float32 `json:"speed"`
Direction int `json:"deg"`
} `json:"Wind"`
Sys struct {
Country string `json:"country"`
} `json:"sys"`
City string `json:"name"`
Main struct {
Humidity int `json:"humidity"`
Pressure int `json:"pressure"`
Temperature float32 `json:"temp"`
} `json:"main"`
Clouds struct {
All int `json:"all"`
} `json:"clouds"`
Rain struct {
OneHour float32 `json:"1h"`
TreeHours float32 `json:"3h"`
} `json:"rain"`
Snow struct {
OneHour float32 `json:"1h"`
TreeHours float32 `json:"3h"`
} `json:"snow"`
Wind struct {
Speed float32 `json:"speed"`
Direction int `json:"deg"`
} `json:"Wind"`
Sys struct {
Country string `json:"country"`
} `json:"sys"`
}
// FetchData from OpenWeatherMap API
func (w *Weather) FetchData() {
for _, city := range w.Config.Cities {
resp, err := http.Get(
fmt.Sprintf(
"%s/weather?q=%s&appid=%s&units=%s",
URI,
city,
w.Config.OpenWeatherMap.APIKey,
w.Config.OpenWeatherMap.Units,
),
)
if err != nil {
fmt.Printf("%s", err)
}
defer resp.Body.Close()
for _, city := range w.Config.Cities {
resp, err := http.Get(
fmt.Sprintf(
"%s/weather?q=%s&appid=%s&units=%s",
URI,
city,
w.Config.OpenWeatherMap.APIKey,
w.Config.OpenWeatherMap.Units,
),
)
if err != nil {
fmt.Printf("%s", err)
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("%s", err)
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("%s", err)
}
weatherData := WeatherData{}
json.Unmarshal(data, &weatherData)
w.WeatherDatas = append(w.WeatherDatas, weatherData)
weatherData := WeatherData{}
json.Unmarshal(data, &weatherData)
w.WeatherDatas = append(w.WeatherDatas, weatherData)
time.Sleep(500 * time.Millisecond)
}
time.Sleep(500 * time.Millisecond)
}
}
// SendToInfluxDB send data in influxdb
func (w *Weather) SendToInfluxDB() error {
conn, err := influx.NewHTTPClient(influx.HTTPConfig{
Addr: w.Config.InfluxDB.URL,
Username: w.Config.InfluxDB.Username,
Password: w.Config.InfluxDB.Password,
})
if err != nil {
return err
}
defer conn.Close()
conn, err := influx.NewHTTPClient(influx.HTTPConfig{
Addr: w.Config.InfluxDB.URL,
Username: w.Config.InfluxDB.Username,
Password: w.Config.InfluxDB.Password,
})
if err != nil {
return err
}
defer conn.Close()
bps, _ := influx.NewBatchPoints(
influx.BatchPointsConfig{
Database: w.Config.InfluxDB.Database,
})
bps, _ := influx.NewBatchPoints(
influx.BatchPointsConfig{
Database: w.Config.InfluxDB.Database,
})
for _, weather := range w.WeatherDatas {
tags := map[string]string{ "city": weather.City, "country": weather.Sys.Country }
fields := map[string]interface{}{
"temperature": weather.Main.Temperature,
"humidity": weather.Main.Humidity,
"pressure": weather.Main.Pressure,
"clouds": weather.Clouds.All,
"wind_speed": weather.Wind.Speed,
"wind_direction": weather.Wind.Direction,
"rain_1h": weather.Rain.OneHour,
"rain_3h": weather.Rain.TreeHours,
"snow_1h": weather.Snow.OneHour,
"snow_3h": weather.Snow.TreeHours,
}
point, _ := influx.NewPoint(w.Config.InfluxDB.Measurement, tags, fields, time.Now())
bps.AddPoint(point)
}
for _, weather := range w.WeatherDatas {
tags := map[string]string{"city": weather.City, "country": weather.Sys.Country}
fields := map[string]interface{}{
"temperature": weather.Main.Temperature,
"humidity": weather.Main.Humidity,
"pressure": weather.Main.Pressure,
"clouds": weather.Clouds.All,
"wind_speed": weather.Wind.Speed,
"wind_direction": weather.Wind.Direction,
"rain_1h": weather.Rain.OneHour,
"rain_3h": weather.Rain.TreeHours,
"snow_1h": weather.Snow.OneHour,
"snow_3h": weather.Snow.TreeHours,
}
point, _ := influx.NewPoint(w.Config.InfluxDB.Measurement, tags, fields, time.Now())
bps.AddPoint(point)
}
err = conn.Write(bps)
if err != nil {
return err
}
err = conn.Write(bps)
if err != nil {
return err
}
return nil
return nil
}