Add Fireboard Input Plugin (#6052)
This commit is contained in:
committed by
Daniel Nelson
parent
109d1e1e15
commit
e098758d78
157
plugins/inputs/fireboard/fireboard.go
Normal file
157
plugins/inputs/fireboard/fireboard.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package fireboard
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
// Fireboard gathers statistics from the fireboard.io servers
|
||||
type Fireboard struct {
|
||||
AuthToken string `toml:"auth_token"`
|
||||
URL string `toml:"url"`
|
||||
HTTPTimeout internal.Duration `toml:"http_timeout"`
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
// NewFireboard return a new instance of Fireboard with a default http client
|
||||
func NewFireboard() *Fireboard {
|
||||
tr := &http.Transport{ResponseHeaderTimeout: time.Duration(3 * time.Second)}
|
||||
client := &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: time.Duration(4 * time.Second),
|
||||
}
|
||||
return &Fireboard{client: client}
|
||||
}
|
||||
|
||||
// RTT fireboardStats represents the data that is received from Fireboard
|
||||
type RTT struct {
|
||||
Temp float64 `json:"temp"`
|
||||
Channel int64 `json:"channel"`
|
||||
Degreetype int `json:"degreetype"`
|
||||
Created string `json:"created"`
|
||||
}
|
||||
|
||||
type fireboardStats struct {
|
||||
Title string `json:"title"`
|
||||
UUID string `json:"uuid"`
|
||||
Latesttemps []RTT `json:"latest_temps"`
|
||||
}
|
||||
|
||||
// A sample configuration to only gather stats from localhost, default port.
|
||||
const sampleConfig = `
|
||||
## Specify auth token for your account
|
||||
auth_token = "invalidAuthToken"
|
||||
## You can override the fireboard server URL if necessary
|
||||
# url = https://fireboard.io/api/v1/devices.json
|
||||
## You can set a different http_timeout if you need to
|
||||
## You should set a string using an number and time indicator
|
||||
## for example "12s" for 12 seconds.
|
||||
# http_timeout = "4s"
|
||||
`
|
||||
|
||||
// SampleConfig Returns a sample configuration for the plugin
|
||||
func (r *Fireboard) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// Description Returns a description of the plugin
|
||||
func (r *Fireboard) Description() string {
|
||||
return "Read real time temps from fireboard.io servers"
|
||||
}
|
||||
|
||||
// Init the things
|
||||
func (r *Fireboard) Init() error {
|
||||
|
||||
if len(r.AuthToken) == 0 {
|
||||
return fmt.Errorf("You must specify an authToken")
|
||||
}
|
||||
if len(r.URL) == 0 {
|
||||
r.URL = "https://fireboard.io/api/v1/devices.json"
|
||||
}
|
||||
// Have a default timeout of 4s
|
||||
if r.HTTPTimeout.Duration == 0 {
|
||||
r.HTTPTimeout.Duration = time.Second * 4
|
||||
}
|
||||
|
||||
r.client.Timeout = r.HTTPTimeout.Duration
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Gather Reads stats from all configured servers.
|
||||
func (r *Fireboard) Gather(acc telegraf.Accumulator) error {
|
||||
|
||||
// Perform the GET request to the fireboard servers
|
||||
req, err := http.NewRequest("GET", r.URL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("Authorization", "Token "+r.AuthToken)
|
||||
resp, err := r.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Successful responses will always return status code 200
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode == http.StatusForbidden {
|
||||
return fmt.Errorf("fireboard server responded with %d [Forbidden], verify your authToken", resp.StatusCode)
|
||||
}
|
||||
return fmt.Errorf("fireboard responded with unexepcted status code %d", resp.StatusCode)
|
||||
}
|
||||
// Decode the response JSON into a new stats struct
|
||||
var stats []fireboardStats
|
||||
if err := json.NewDecoder(resp.Body).Decode(&stats); err != nil {
|
||||
return fmt.Errorf("unable to decode fireboard response: %s", err)
|
||||
}
|
||||
// Range over all devices, gathering stats. Returns early in case of any error.
|
||||
for _, s := range stats {
|
||||
r.gatherTemps(s, acc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return text description of degree type (scale)
|
||||
func scale(n int) string {
|
||||
switch n {
|
||||
case 1:
|
||||
return "Celcius"
|
||||
case 2:
|
||||
return "Fahrenheit"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Gathers stats from a single device, adding them to the accumulator
|
||||
func (r *Fireboard) gatherTemps(s fireboardStats, acc telegraf.Accumulator) {
|
||||
// Construct lookup for scale values
|
||||
|
||||
for _, t := range s.Latesttemps {
|
||||
tags := map[string]string{
|
||||
"title": s.Title,
|
||||
"uuid": s.UUID,
|
||||
"channel": strconv.FormatInt(t.Channel, 10),
|
||||
"scale": scale(t.Degreetype),
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
"temperature": t.Temp,
|
||||
}
|
||||
acc.AddFields("fireboard", fields, tags)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("fireboard", func() telegraf.Input {
|
||||
return NewFireboard()
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user