feat: add goreport notation
This commit is contained in:
parent
4bf2f1e02f
commit
0ad5151d98
5 changed files with 186 additions and 181 deletions
|
@ -7,6 +7,10 @@ Which is based on [Keep A Changelog](http://keepachangelog.com/)
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- goreport notation
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- too many open files close with influxdb connection
|
- too many open files close with influxdb connection
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Weather
|
# Weather
|
||||||
|
|
||||||
[![Version](https://img.shields.io/badge/latest_version-1.0.0-green.svg)](https://git.yaegashi.fr/nishiki/weather/releases)
|
[![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)
|
[![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
|
weather is a small program that fetch weather informations, and store them to influxdb
|
||||||
|
|
98
config.go
98
config.go
|
@ -17,78 +17,78 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct contains all options
|
// Config struct contains all options
|
||||||
type Config struct {
|
type Config struct {
|
||||||
InfluxDB struct {
|
InfluxDB struct {
|
||||||
URL string `yaml:"url"`
|
URL string `yaml:"url"`
|
||||||
Database string `yaml:"database"`
|
Database string `yaml:"database"`
|
||||||
Measurement string `yaml:"measurement"`
|
Measurement string `yaml:"measurement"`
|
||||||
Username string `yaml:"username"`
|
Username string `yaml:"username"`
|
||||||
Password string `yaml:"password"`
|
Password string `yaml:"password"`
|
||||||
} `yaml:"influxdb"`
|
} `yaml:"influxdb"`
|
||||||
OpenWeatherMap struct {
|
OpenWeatherMap struct {
|
||||||
APIKey string `yaml:"api_key"`
|
APIKey string `yaml:"api_key"`
|
||||||
Units string `yaml:"units"`
|
Units string `yaml:"units"`
|
||||||
} `yaml:"openweathermap"`
|
} `yaml:"openweathermap"`
|
||||||
Cities []string `yaml:"cities"`
|
Cities []string `yaml:"cities"`
|
||||||
Interval int64 `yaml:"interval"`
|
Interval int64 `yaml:"interval"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the config from a file
|
// Load the config from a file
|
||||||
func (c *Config) Load(path string) error {
|
func (c *Config) Load(path string) error {
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = yaml.Unmarshal(data, &c)
|
err = yaml.Unmarshal(data, &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Defaults()
|
c.Defaults()
|
||||||
err = c.Check()
|
err = c.Check()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defaults set options with default value
|
// Defaults set options with default value
|
||||||
func (c *Config) Defaults() {
|
func (c *Config) Defaults() {
|
||||||
if c.OpenWeatherMap.Units == "" {
|
if c.OpenWeatherMap.Units == "" {
|
||||||
c.OpenWeatherMap.Units = "metric"
|
c.OpenWeatherMap.Units = "metric"
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Interval == 0 {
|
if c.Interval == 0 {
|
||||||
c.Interval = 600
|
c.Interval = 600
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.InfluxDB.URL == "" {
|
if c.InfluxDB.URL == "" {
|
||||||
c.InfluxDB.URL = "http://127.0.0.1:8086"
|
c.InfluxDB.URL = "http://127.0.0.1:8086"
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.InfluxDB.Measurement == "" {
|
if c.InfluxDB.Measurement == "" {
|
||||||
c.InfluxDB.Measurement = "weather"
|
c.InfluxDB.Measurement = "weather"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the options are good
|
// Check if the options are good
|
||||||
func (c *Config) Check() error {
|
func (c *Config) Check() error {
|
||||||
if c.InfluxDB.Database == "" {
|
if c.InfluxDB.Database == "" {
|
||||||
return fmt.Errorf("you must specify influxdb.database in config file")
|
return fmt.Errorf("you must specify influxdb.database in config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.OpenWeatherMap.APIKey == "" {
|
if c.OpenWeatherMap.APIKey == "" {
|
||||||
return fmt.Errorf("you must specify api_key in config file")
|
return fmt.Errorf("you must specify api_key in config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
84
main.go
84
main.go
|
@ -17,63 +17,63 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"flag"
|
||||||
"flag"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options and OpenWeatherMap URI
|
// Options and OpenWeatherMap URI
|
||||||
var (
|
var (
|
||||||
URI = "https://api.openweathermap.org/data/2.5"
|
URI = "https://api.openweathermap.org/data/2.5"
|
||||||
CONFIG = flag.String("config", "", "config file path")
|
CONFIG = flag.String("config", "", "config file path")
|
||||||
DAEMON = flag.Bool("daemon", false, "run in daemon mode")
|
DAEMON = flag.Bool("daemon", false, "run in daemon mode")
|
||||||
HELP = flag.Bool("help", false, "print this help message")
|
HELP = flag.Bool("help", false, "print this help message")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var w Weather
|
var w Weather
|
||||||
|
|
||||||
if *HELP {
|
if *HELP {
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *CONFIG == "" {
|
if *CONFIG == "" {
|
||||||
fmt.Println("you must specify a config file with -config option")
|
fmt.Println("you must specify a config file with -config option")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := w.Config.Load(*CONFIG)
|
err := w.Config.Load(*CONFIG)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%s\n", err)
|
fmt.Printf("%s\n", err)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
startTime := time.Now().Unix()
|
startTime := time.Now().Unix()
|
||||||
|
|
||||||
w.FetchData()
|
w.FetchData()
|
||||||
err = w.SendToInfluxDB()
|
err = w.SendToInfluxDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%s\n", err)
|
fmt.Printf("%s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *DAEMON == false {
|
if *DAEMON == false {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
} else {
|
} else {
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sleepTime := time.Now().Unix() - startTime + w.Config.Interval
|
sleepTime := time.Now().Unix() - startTime + w.Config.Interval
|
||||||
if sleepTime > 0 {
|
if sleepTime > 0 {
|
||||||
time.Sleep(time.Duration(sleepTime) * time.Second)
|
time.Sleep(time.Duration(sleepTime) * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
180
weather.go
180
weather.go
|
@ -17,118 +17,118 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"encoding/json"
|
||||||
"net/http"
|
"fmt"
|
||||||
"encoding/json"
|
"io/ioutil"
|
||||||
"io/ioutil"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
influx "github.com/influxdata/influxdb1-client/v2"
|
influx "github.com/influxdata/influxdb1-client/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Weather is the main struct
|
// Weather is the main struct
|
||||||
type Weather struct {
|
type Weather struct {
|
||||||
Config Config
|
Config Config
|
||||||
WeatherDatas []WeatherData
|
WeatherDatas []WeatherData
|
||||||
}
|
}
|
||||||
|
|
||||||
// WeatherData contains weather data from openweathermap
|
// WeatherData contains weather data from openweathermap
|
||||||
type WeatherData struct {
|
type WeatherData struct {
|
||||||
City string `json:"name"`
|
City string `json:"name"`
|
||||||
Main struct {
|
Main struct {
|
||||||
Humidity int `json:"humidity"`
|
Humidity int `json:"humidity"`
|
||||||
Pressure int `json:"pressure"`
|
Pressure int `json:"pressure"`
|
||||||
Temperature float32 `json:"temp"`
|
Temperature float32 `json:"temp"`
|
||||||
} `json:"main"`
|
} `json:"main"`
|
||||||
Clouds struct {
|
Clouds struct {
|
||||||
All int `json:"all"`
|
All int `json:"all"`
|
||||||
} `json:"clouds"`
|
} `json:"clouds"`
|
||||||
Rain struct {
|
Rain struct {
|
||||||
OneHour float32 `json:"1h"`
|
OneHour float32 `json:"1h"`
|
||||||
TreeHours float32 `json:"3h"`
|
TreeHours float32 `json:"3h"`
|
||||||
} `json:"rain"`
|
} `json:"rain"`
|
||||||
Snow struct {
|
Snow struct {
|
||||||
OneHour float32 `json:"1h"`
|
OneHour float32 `json:"1h"`
|
||||||
TreeHours float32 `json:"3h"`
|
TreeHours float32 `json:"3h"`
|
||||||
} `json:"snow"`
|
} `json:"snow"`
|
||||||
Wind struct {
|
Wind struct {
|
||||||
Speed float32 `json:"speed"`
|
Speed float32 `json:"speed"`
|
||||||
Direction int `json:"deg"`
|
Direction int `json:"deg"`
|
||||||
} `json:"Wind"`
|
} `json:"Wind"`
|
||||||
Sys struct {
|
Sys struct {
|
||||||
Country string `json:"country"`
|
Country string `json:"country"`
|
||||||
} `json:"sys"`
|
} `json:"sys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FetchData from OpenWeatherMap API
|
// FetchData from OpenWeatherMap API
|
||||||
func (w *Weather) FetchData() {
|
func (w *Weather) FetchData() {
|
||||||
for _, city := range w.Config.Cities {
|
for _, city := range w.Config.Cities {
|
||||||
resp, err := http.Get(
|
resp, err := http.Get(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"%s/weather?q=%s&appid=%s&units=%s",
|
"%s/weather?q=%s&appid=%s&units=%s",
|
||||||
URI,
|
URI,
|
||||||
city,
|
city,
|
||||||
w.Config.OpenWeatherMap.APIKey,
|
w.Config.OpenWeatherMap.APIKey,
|
||||||
w.Config.OpenWeatherMap.Units,
|
w.Config.OpenWeatherMap.Units,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%s", err)
|
fmt.Printf("%s", err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
data, err := ioutil.ReadAll(resp.Body)
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("%s", err)
|
fmt.Printf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
weatherData := WeatherData{}
|
weatherData := WeatherData{}
|
||||||
json.Unmarshal(data, &weatherData)
|
json.Unmarshal(data, &weatherData)
|
||||||
w.WeatherDatas = append(w.WeatherDatas, weatherData)
|
w.WeatherDatas = append(w.WeatherDatas, weatherData)
|
||||||
|
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendToInfluxDB send data in influxdb
|
// SendToInfluxDB send data in influxdb
|
||||||
func (w *Weather) SendToInfluxDB() error {
|
func (w *Weather) SendToInfluxDB() error {
|
||||||
conn, err := influx.NewHTTPClient(influx.HTTPConfig{
|
conn, err := influx.NewHTTPClient(influx.HTTPConfig{
|
||||||
Addr: w.Config.InfluxDB.URL,
|
Addr: w.Config.InfluxDB.URL,
|
||||||
Username: w.Config.InfluxDB.Username,
|
Username: w.Config.InfluxDB.Username,
|
||||||
Password: w.Config.InfluxDB.Password,
|
Password: w.Config.InfluxDB.Password,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
bps, _ := influx.NewBatchPoints(
|
bps, _ := influx.NewBatchPoints(
|
||||||
influx.BatchPointsConfig{
|
influx.BatchPointsConfig{
|
||||||
Database: w.Config.InfluxDB.Database,
|
Database: w.Config.InfluxDB.Database,
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, weather := range w.WeatherDatas {
|
for _, weather := range w.WeatherDatas {
|
||||||
tags := map[string]string{ "city": weather.City, "country": weather.Sys.Country }
|
tags := map[string]string{"city": weather.City, "country": weather.Sys.Country}
|
||||||
fields := map[string]interface{}{
|
fields := map[string]interface{}{
|
||||||
"temperature": weather.Main.Temperature,
|
"temperature": weather.Main.Temperature,
|
||||||
"humidity": weather.Main.Humidity,
|
"humidity": weather.Main.Humidity,
|
||||||
"pressure": weather.Main.Pressure,
|
"pressure": weather.Main.Pressure,
|
||||||
"clouds": weather.Clouds.All,
|
"clouds": weather.Clouds.All,
|
||||||
"wind_speed": weather.Wind.Speed,
|
"wind_speed": weather.Wind.Speed,
|
||||||
"wind_direction": weather.Wind.Direction,
|
"wind_direction": weather.Wind.Direction,
|
||||||
"rain_1h": weather.Rain.OneHour,
|
"rain_1h": weather.Rain.OneHour,
|
||||||
"rain_3h": weather.Rain.TreeHours,
|
"rain_3h": weather.Rain.TreeHours,
|
||||||
"snow_1h": weather.Snow.OneHour,
|
"snow_1h": weather.Snow.OneHour,
|
||||||
"snow_3h": weather.Snow.TreeHours,
|
"snow_3h": weather.Snow.TreeHours,
|
||||||
}
|
}
|
||||||
point, _ := influx.NewPoint(w.Config.InfluxDB.Measurement, tags, fields, time.Now())
|
point, _ := influx.NewPoint(w.Config.InfluxDB.Measurement, tags, fields, time.Now())
|
||||||
bps.AddPoint(point)
|
bps.AddPoint(point)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conn.Write(bps)
|
err = conn.Write(bps)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue