fuelprices/functions.go

191 lines
4.2 KiB
Go

package main
import (
"archive/zip"
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strconv"
"time"
"github.com/antchfx/xmlquery"
_ "github.com/influxdata/influxdb1-client"
client "github.com/influxdata/influxdb1-client/v2"
"gopkg.in/ini.v1"
)
// ParseArgs is not yet implemented
func ParseArgs() error {
return nil
}
// GetConfig fetch config from ini file
func GetConfig(configfile string, fuelpricesconfig *FuelPricesConfig) error {
flag.Usage = Usage
config, err := ini.Load(configfile)
HandleFatalError(err)
var fpc FuelPricesConfig
fuelpricesSection := config.Section("fuelprices")
fpc.RemoteURL = fuelpricesSection.Key("remote_url").String()
fpc.RemoteFilename = fuelpricesSection.Key("remote_filename").String()
fpc.XPathBase = fuelpricesSection.Key("xpath_base").String()
fpc.Table = fuelpricesSection.Key("table").String()
influxdbSection := config.Section("influxdb")
fpc.InfluxHost = influxdbSection.Key("hostname").String()
fpc.InfluxPort, err = influxdbSection.Key("port").Int()
HandleError(err)
fpc.InfluxUser = influxdbSection.Key("username").String()
fpc.InfluxPass = influxdbSection.Key("password").String()
HandleError(err)
fpc.InfluxDB = influxdbSection.Key("database").String()
fpc.Pos = fuelpricesSection.Key("pos").Strings(",")
fpc.Types = fuelpricesSection.Key("types").Strings(",")
*fuelpricesconfig = fpc
return err
}
// DownloadFile fetch file from webserver
func DownloadFile(fpc *FuelPricesConfig, szip *Srcfile) error {
pollTo := 30 * time.Millisecond
c := &http.Client{Timeout: pollTo * time.Second, Transport: &http.Transport{
IdleConnTimeout: pollTo,
DisableCompression: false,
}}
//resp, err := http.Get(url)
resp, err := c.Get(fpc.RemoteURL)
HandleError(err)
defer resp.Body.Close()
szip.Content, err = ioutil.ReadAll(resp.Body)
HandleError(err)
time.Sleep(pollTo)
return err
}
// ExtractZip get the XML file to be processed
func ExtractZip(fpc *FuelPricesConfig, szip *Srcfile, output *[]byte) error {
zipfile, err := zip.NewReader(bytes.NewReader(szip.Content), int64(len(szip.Content)))
HandleFatalError(err)
for _, f := range zipfile.File {
if f.Name == fpc.RemoteFilename {
rc, err := f.Open()
if err != nil {
return err
}
*output, err = ioutil.ReadAll(rc)
rc.Close()
} else {
log.Fatal("File not found")
}
}
return err
}
// GetPrices parses the XML file and get values of prices
func GetPrices(prices **[]Price, fpc *FuelPricesConfig, output *[]byte) error {
var pr []Price
var xml *xmlquery.Node
f := bytes.NewReader(*output)
xml, err := xmlquery.Parse(f)
HandleError(err)
for _, station := range fpc.Pos {
for _, fuel := range fpc.Types {
query := fmt.Sprintf(fpc.XPathBase, station, fuel)
list := xmlquery.FindOne(xml, query)
if list != nil {
for _, i := range list.Attr {
if i.Name.Local == "valeur" {
var val float64
if s, err := strconv.ParseFloat(i.Value, 64); err == nil {
val = s
}
pr = append(pr, Price{ID: station, Fuel: fuel, Amount: val})
}
}
} else {
log.Println(fmt.Sprintf("Fuel type not found for point of sale, skipping. Query : %s", query))
}
}
}
*prices = &pr
return err
}
// SendToInflux sends time series data to influxdb
func SendToInflux(fpc *FuelPricesConfig, prices *[]Price) {
httpClient, err := client.NewHTTPClient(client.HTTPConfig{
Addr: fmt.Sprintf("http://%s:%d", fpc.InfluxHost, fpc.InfluxPort),
Username: fpc.InfluxUser,
Password: fpc.InfluxPass,
})
HandleFatalError(err)
bp, err := client.NewBatchPoints(client.BatchPointsConfig{
Database: fpc.InfluxDB,
})
HandleFatalError(err)
for _, p := range *prices {
tags := map[string]string{"pdv": p.ID, "fuel": p.Fuel}
fields := map[string]interface{}{"value": p.Amount}
point, _ := client.NewPoint(
fpc.Table,
tags,
fields,
time.Now(),
)
log.Println(point)
bp.AddPoint(point)
err = httpClient.Write(bp)
HandleError(err)
}
}
// HandleError handles errors to return err
func HandleError(err error) error {
if err != nil {
return err
}
return nil
}
// HandleFatalError fatal errors
func HandleFatalError(err error) {
if err != nil {
log.Fatal(err)
os.Exit(2)
}
}
// Usage displays possible arguments
func Usage() {
flag.PrintDefaults()
os.Exit(1)
}