src/go/plugin/go.d/modules/apcupsd/collect.go
// SPDX-License-Identifier: GPL-3.0-or-later
package apcupsd
import (
"errors"
"fmt"
"strings"
"time"
)
const precision = 100
func (a *Apcupsd) collect() (map[string]int64, error) {
if a.conn == nil {
conn, err := a.establishConnection()
if err != nil {
return nil, err
}
a.conn = conn
}
resp, err := a.conn.status()
if err != nil {
a.Cleanup()
return nil, err
}
mx := make(map[string]int64)
if err := a.collectStatus(mx, resp); err != nil {
return nil, err
}
return mx, nil
}
func (a *Apcupsd) collectStatus(mx map[string]int64, resp []byte) error {
st, err := parseStatus(resp)
if err != nil {
return fmt.Errorf("failed to parse status: %v", err)
}
if st.status == "" {
return errors.New("unexpected response: status is empty")
}
for _, v := range upsStatuses {
mx["status_"+v] = 0
}
for _, v := range strings.Fields(st.status) {
mx["status_"+v] = 1
}
switch st.status {
case "COMMLOST", "SHUTTING_DOWN":
return nil
}
if st.selftest != "" {
for _, v := range upsSelftestStatuses {
mx["selftest_"+v] = 0
}
mx["selftest_"+st.selftest] = 1
}
if st.bcharge != nil {
mx["battery_charge"] = int64(*st.bcharge * precision)
}
if st.battv != nil {
mx["battery_voltage"] = int64(*st.battv * precision)
}
if st.nombattv != nil {
mx["battery_voltage_nominal"] = int64(*st.nombattv * precision)
}
if st.linev != nil {
mx["input_voltage"] = int64(*st.linev * precision)
}
if st.minlinev != nil {
mx["input_voltage_min"] = int64(*st.minlinev * precision)
}
if st.maxlinev != nil {
mx["input_voltage_max"] = int64(*st.maxlinev * precision)
}
if st.linefreq != nil {
mx["input_frequency"] = int64(*st.linefreq * precision)
}
if st.outputv != nil {
mx["output_voltage"] = int64(*st.outputv * precision)
}
if st.nomoutv != nil {
mx["output_voltage_nominal"] = int64(*st.nomoutv * precision)
}
if st.loadpct != nil {
mx["load_percent"] = int64(*st.loadpct * precision)
}
if st.itemp != nil {
mx["itemp"] = int64(*st.itemp * precision)
}
if st.timeleft != nil {
mx["timeleft"] = int64(*st.timeleft * 60 * precision) // to seconds
}
if st.nompower != nil && st.loadpct != nil {
mx["load"] = int64(*st.nompower * *st.loadpct / 100)
}
if st.battdate != "" {
if v, err := battdateSecondsAgo(st.battdate); err != nil {
a.Debugf("failed to calculate time since battery replacement for date '%s': %v", st.battdate, err)
} else {
mx["battery_seconds_since_replacement"] = v
}
}
return nil
}
func battdateSecondsAgo(battdate string) (int64, error) {
var layout string
if strings.ContainsRune(battdate, '-') {
layout = "2006-01-02"
} else {
layout = "01/02/06"
}
date, err := time.Parse(layout, battdate)
if err != nil {
return 0, err
}
secsAgo := int64(time.Now().Sub(date).Seconds())
return secsAgo, nil
}
func (a *Apcupsd) establishConnection() (apcupsdConn, error) {
conn := a.newConn(a.Config)
if err := conn.connect(); err != nil {
return nil, err
}
return conn, nil
}