Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

NUT - Network UPS Tools Plug-in #6316

Closed
mcindea opened this issue Aug 27, 2019 · 22 comments · Fixed by #9890
Closed

NUT - Network UPS Tools Plug-in #6316

mcindea opened this issue Aug 27, 2019 · 22 comments · Fixed by #9890
Labels
external plugin Plugins that would be ideal external plugin and expedite being able to use plugin w/ Telegraf feature request Requests for new plugin and for new features to existing plugins

Comments

@mcindea
Copy link

mcindea commented Aug 27, 2019

Feature Request

Hello guys,

I'm just curious if you have any plans in creating a plugin for NUT ? Similar to what you did for #2877

Proposal:

I volunteer to create it myself, but I'm new to Go, so I would need your support reviewing the code and most possibly also share the procedures you have for this kind of situations? i.e. Best practices or some docs about writing plugins.
Thanks!

Current behavior:

Currently only a plugin for APCUPCd exists.

Desired behavior:

Would be nice if a plugin for NUT exists, which offers a broader compatibility with UPS hardware.

Use case:

Currently I use Telegraf for my UnRaid setup, which monitors everything, and built a custom Docker container script which gathers data and sends it to InfluxDB. Another solution is to use an Exec, but that also requires having NUT installed in the Alpine container where Telegraf is. Therefore I would like a plugin, which doesn't have any external dependencies.

@danielnelson danielnelson added the feature request Requests for new plugin and for new features to existing plugins label Aug 27, 2019
@danielnelson
Copy link
Contributor

This would be nice to have. I looked very briefly at the NUT documentation, do you think the plugin would operate similar to the upsc command?

@mcindea
Copy link
Author

mcindea commented Aug 28, 2019

Yes, as a matter of fact the python script I built uses the same uspc command.

@danielnelson
Copy link
Contributor

Would be nice to get an idea of how some actual data looks, could you show the output of your script?

I believe this is the documentation for connecting to upsd: https://networkupstools.org/docs/developer-guide.chunked/ar01s09.html

@mcindea
Copy link
Author

mcindea commented Aug 28, 2019

Sure, but it's it's not fully relevant since currently I just adapted a python script that was built for APCUPCd, so currently the fields match what APC would output:

[{'fields': {'STATUS': u'OL', 'WATTS': 90.0, 'TIMELEFT': 3570.0, 'BCHARGE': 100.0, 'LOADPCT': 10.0, 'BATTV': 24.0, 'OUTPUTV': 260.0, 'NOMPOWER': 900.0}, 'tags': {'ups_alias': 'ups', 'host': 'Tower', 'serial': u'CRMJP2000104'}, 'measurement': 'ups_status'}]

Just for reference, BCHARGE is actually battery.charge on UPS Cyberpower and similar BATTV is battery.voltage.
Since I can't test other UPS equipments, I would want to make it dynamic, just output the fields it gets. Of course, after proper filtering so we make sure nothing malicious gets stored in the DB.

Thinking about it I think it's better if I just show you the upsc output:

root@Tower:~# upsc ups@localhost
battery.charge: 100
battery.charge.low: 10
battery.charge.warning: 20
battery.mfr.date: CPS
battery.runtime: 3720
battery.runtime.low: 300
battery.type: PbAcid
battery.voltage: 24.0
battery.voltage.nominal: 24
device.mfr: CPS
device.model: CP1500EPFCLCD
device.serial: CRMJP2000104
device.type: ups
driver.name: usbhid-ups
driver.parameter.pollfreq: 30
driver.parameter.pollinterval: 2
driver.parameter.port: auto
driver.parameter.synchronous: no
driver.version: 2.7.4.1
driver.version.data: CyberPower HID 0.5
driver.version.internal: 0.53
driver.version.usb: libusb-1.0.22 (API: 0x1000106)
input.transfer.high: 260
input.transfer.low: 170
input.voltage: 225.0
input.voltage.nominal: 230
output.voltage: 260.0
ups.beeper.status: enabled
ups.delay.shutdown: 20
ups.delay.start: 30
ups.load: 10
ups.mfr: CPS
ups.model: CP1500EPFCLCD
ups.productid: 0501
ups.realpower.nominal: 900
ups.serial: CRMJP2000104
ups.status: OL
ups.test.result: No test initiated
ups.timer.shutdown: -60
ups.timer.start: -60
ups.vendorid: 0764
root@Tower:~# 

@danielnelson
Copy link
Contributor

I wonder how standardized these stats are, is there a list of possible stats? Likely we would want a plugin to connect to upsd and list all stats and then for each stat we would check a list of known stats to determine if the stat should be saved as a tag/field.

If a stat is unknown we could either ignore the stat or add it based on the observed type:

  • 2.0 -> float
  • 2 -> int
  • default: string

If we find the use of a decimal point is not consistent, we may want to always store as float. I would think that the memcached plugin is the closest in style to what we would want here.

@mcindea
Copy link
Author

mcindea commented Aug 29, 2019

That's a very good idea. I'll have to dig into this a bit more. I found upsrw, which does something like that, but only for config variables that can be changed by the user and not actual log data.

[battery.charge.low]
Remaining battery level when UPS switches to LB (percent)
Type: STRING
Maximum length: 10
Value: 10

[battery.runtime.low]
Remaining battery runtime when UPS switches to LB (seconds)
Type: STRING
Maximum length: 10
Value: 300

[input.transfer.high]
High voltage transfer point (V)
Type: STRING
Maximum length: 10
Value: 260

[input.transfer.low]
Low voltage transfer point (V)
Type: STRING
Maximum length: 10
Value: 170

[ups.delay.shutdown]
Interval to wait after shutdown with delay command (seconds)
Type: STRING
Maximum length: 10
Value: 20

[ups.delay.start]
Interval to wait before (re)starting the load (seconds)
Type: STRING
Maximum length: 10
Value: 30

root@Tower:~#

Also found something we could use to replace upsc which polls every 30 seconds by default, but unfortunately it doesn't say anything about types. The format appears to be universal, so I don't think it's tied to the vendor type. Especially if you look at the last 2 columns, ups.temperature and input.frequency. They're NA because I don't have those sensors.

root@Tower:~# upslog  -s ups@localhost -l - -f "%TIME @Y@m@d @H@M@S% %VAR battery.charge% %VAR battery.runtime% %VAR ups.realpower.nominal% %VAR battery.voltage% %VAR output.voltage% %VAR input.voltage% %VAR ups.load%  [%VAR ups.status%] %VAR ups.temperature% %VAR input.frequency%"
Network UPS Tools upslog 2.7.4.1
logging status of ups@localhost to - (30s intervals)
20190829 073621 100 3480 900 24.0 260.0 225.0 11  [OL] NA NA
20190829 073651 100 3330 900 24.0 260.0 224.0 11  [OL] NA NA

EDIT: I looked into it and they have quite complex documentation about this:
https://networkupstools.org/docs/developer-guide.chunked/apas01.html

To be honest there are more than I expected and I'm curious how much of them my UPS actually supports so I can actually test them.

Thanks for the tip about memcached, I''ll look into that.

@sjwang90
Copy link
Contributor

Hi @kiwimato, just checking if you have any update in looking into referencing thememcached plugin for the NUT plugin you're working on. Just looking into prioritizing plugins for future feature releases. Please respond if you have any questions!

@mcindea
Copy link
Author

mcindea commented Nov 12, 2019

Hello @sjwang90, unfortunately I didn't enough time to start work on it and my server where I had this setup crashed in the meantime, so I won't be able to work on it until I will fix it.
I did however write a python script which I planned to use as PoC before I planned to work on this. If you guys have more time than me or might find it useful you can find it here - it's fully tested and it works.
Please keep me updated. I find it really awesome that you are guys are interested in it!

@sjwang90 sjwang90 added the ready label Nov 12, 2019
@Styx13
Copy link

Styx13 commented Mar 6, 2020

Hello @kiwimato , do you still plan to create this nut plugin for telegraf ?

I too am using nut for my UPS management and monitoring, and I would love to be able to send the metrics to influxdb/grafana using telegraf.

@mcindea
Copy link
Author

mcindea commented Mar 6, 2020

Hey @Styx13, to be honest I didn't have time to yet and for my use case i created a workaround: https://github.com/kiwimato/nut-influxdb-exporter

I still plan to work on it at some point, but don't have an ETA at this point.

@lmondoux
Copy link

Just wanted to say it would be great if there was a NUT telegraf input!

@donmueang
Copy link

Is there any known update on this? Would like to have Telegram scraping data from the NUT instance running on another server. Not planning to switch over to apcupcd.

@cvandesande
Copy link

Is there any known update on this? Would like to have Telegram scraping data from the NUT instance running on another server. Not planning to switch over to apcupcd.

Yeah, you can always use "inputs_exec" and run upsc. It's what I'm currently doing and it works fine.

[[inputs.exec]]
  commands = ["sh -c 'upsc cyberpower@localhost ups.realpower.nominal'"]
  name_override = "ups_power"
  timeout = "5s"
  data_format = "value"
  data_type = "integer"
  [inputs.exec.tags]
    ups = "ups0"

[[inputs.exec]]
  commands = ["sh -c 'upsc cyberpower@localhost ups.load'"]
  name_override = "ups_load"
  timeout = "5s"
  data_format = "value"
  data_type = "integer"
  [inputs.exec.tags]
    ups = "ups0"

@samuelkadolph
Copy link

I came across the issue and whipped up a script. Figured I'd share it for others.

#!/bin/sh

if [ $# -lt 1 ]; then
  echo "usage: $0 field [...field]" >&2
  exit 1
fi

fields="$1"
shift

while [ $# -ne 0 ]; do
  fields="$fields|$1"
  shift
done

list=$(upsc -l 2>/dev/null)
safe_fields="$(echo "${fields}" | sed 's/\./\\\./g')"

for name in $list; do
  props=$(upsc "$name" 2>/dev/null | sed -nE "/^($safe_fields):/p" | sed -nE 's/([^0-9])\.([^0-9])/\1_\2/g;s/^(.*): ([0-9.]+)$/\1=\2/p' | tr '\n' ',')
  echo "ups,name=${name} ${props%,}"
done

In my case I have that script at /etc/telegraf/ups and added the following to my config:

[[inputs.exec]]
  commands = ["/etc/telegraf/ups battery.charge battery.runtime battery.voltage battery.voltage.nominal input.voltage output.voltage ups.load ups.realpower.nominal"]
  data_format = "influx"

@sjwang90
Copy link
Contributor

@kiwimato @samuelkadolph Would either of your scripts be able list as an external plugin. If you would you be willing to submit this plugin as an external plugin that can be used with execd to run seamlessly with Telegraf?

@sjwang90 sjwang90 added the external plugin Plugins that would be ideal external plugin and expedite being able to use plugin w/ Telegraf label Nov 23, 2020
@fabriziorizzo
Copy link

collecting the non-numeric ups.status value would also useful. Not entirely sure how to adapt the regexp so it becomes an accepted property for the script above. perhaps even transforming the abbreviated code for full-text status descriptions?

e.g.
'OL': 'Online',
'OB': 'On Battery',
'LB': 'Low Battery',
'HB': 'High Battery',
'RB': 'Battery Needs Replaced',
'CHRG': 'Battery Charging',
'DISCHRG': 'Battery Discharging',
'BYPASS': 'Bypass Active',
'CAL': 'Runtime Calibration',
'OFF': 'Offline',
'OVER': 'Overloaded',
'TRIM': 'Trimming Voltage',
'BOOST': 'Boosting Voltage',
'FSD': 'Forced Shutdown',
'ALARM': 'Alarm'

@arrmo
Copy link

arrmo commented Jun 24, 2021

Hi,

Sorry if this is a dumb question, but ... as there is an official plugin for apcupsd, why not align with that => meaning, save the same parameter set with NUT?

Thanks!

@midzelis
Copy link

I wrote this for myself, but then i found this comment, so I put it up on github/dockerhub -- maybe others will find it useful?

https://github.com/midzelis/nut-ups-logger

This will connect to NUT remotely, list all the UPS, and then send ALL the variables over a remote server. This can be telegraf running with the HTTP Listener plugin.

By default, I send all the variables I find. If there is something you don't want, looks like telegraf can filter things out: https://docs.influxdata.com/telegraf/v1.19/administration/configuration/#measurement-filtering

docker-compose.yml

version: "3"
services:
  nut-ups-logger:
    image: midzelis/nut-ups-logger
    environment:
      - NUT_HOST=${NUT_HOST}
      - NUT_PORT=${NUT_PORT}
      - LOGGING_URL=${LOGGING_URL}
    container_name: nut-ups-logger
    depends_on:
      - telegraf
    restart: always

telegraf.conf snippet

[[inputs.http_listener_v2]]
#   ## Address and port to host HTTP listener on
  service_address = ":10800"
#
#   ## Path to listen to.
    path = "/telegraf"

    data_format = "json"
    json_name_key = "UPS_NAME"

@Malinskiy
Copy link
Contributor

A very quick implementation of NUT client using github.com/robbiet480/go.nut can be found here - https://github.com/Malinskiy/telegraf/tree/feature/upsd/plugins/inputs/upsd

It produces an almost identical set of metrics as apcupsd input with a couple of exceptions. Dashboards that work for apcupsd work almost out of the box:
image

@grasshide
Copy link

A very quick implementation of NUT client using github.com/robbiet480/go.nut can be found here - https://github.com/Malinskiy/telegraf/tree/feature/upsd/plugins/inputs/upsd

This looks perfect. But how do I use this? I run telegraf as docker container.
Will this be adopted as a standard plugin? Right now it is not included.

@Malinskiy
Copy link
Contributor

A very quick implementation of NUT client using github.com/robbiet480/go.nut can be found here - https://github.com/Malinskiy/telegraf/tree/feature/upsd/plugins/inputs/upsd

This looks perfect. But how do I use this? I run telegraf as docker container.
Will this be adopted as a standard plugin? Right now it is not included.

I may work on submitting this as a PR to the main repo next month depending on my availability

@ostueker
Copy link

ostueker commented Jul 7, 2022

Looking forward to the upsd support in the next release.

Thank you @Malinskiy, @AdamLeyshon and @srebhan !

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
external plugin Plugins that would be ideal external plugin and expedite being able to use plugin w/ Telegraf feature request Requests for new plugin and for new features to existing plugins
Projects
None yet
Development

Successfully merging a pull request may close this issue.