Yes, APC includes some software with their UPS units. However, if you have more than one UPS, or just want better network-based monitoring, apcupsd-admin-plus is the answer. All of the components use Docker containers for ease of deployment and updates.
I’d also recommend, and this guide will use, the excellent WebUI for Docker — Portainer. Cockpit (with the Navigator plugin), and Organizr are also part of my everyday suite of applications I install on every device that I use as any kind of a server. So you’ll be seeing them here too — they’re not required, but will make your life easier.
With Docker, Portainer and Cockpit installed, you’ll have exactly zero-else to do from the command line to get this up-and-running. In the great spirit of dessert-first, here’s where we’re headed with this project:
Here’s the classic apcupsd-cgi showing my 6 UPS units in an Organizr window. All are online and 100% charged (Note that some APC models offer slightly less information than others). Drilling down on any unit gives additional info:
Note that in this same single browser tab we can also jump to Portainer, Cockpit and apcupsd-cgi. The other bit of wizardry I’d like to accomplish with this is to get some nice dashboard-style output from Grafana:
So, thanks to me spending a bunch of time on this, you shouldn’t have to. 🙂 Here are the steps:
Install apcupsd on each of the PCs, RaspberryPis or servers you have connected to the UPS units you plan to monitor. Here’s the docker-compose you can plug into Portainer-Stacks to get that going:
version: '3.7'
services:
apcupsd:
image: bnhf/apcupsd:latest
container_name: apcupsd
devices:
- /dev/usb/hiddev0
ports:
- 3551:3551
environment: # Delete or comment out any environment variables you don't wish to change
- UPSNAME=${UPSNAME} # This value will display in apcupsd-cgi details.
- UPSCABLE=${UPSCABLE} # Default value is usb
- UPSTYPE=${UPSTYPE} # Default value is usb
- DEVICE=${DEVICE} # Default value is <blank>
- NETSERVER=${NETSERVER} # Default value is on
- NISIP=${NISIP} # Default value is 0.0.0.0
- TZ=${TZ} # Default value is Europe/London
volumes:
- /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket
- /data/apcupsd:/etc/apcupsd
restart: unless-stopped
Your USB device name may be different than the /dev/usb/hiddev0 used above, but it should be an hid device — so have look in the /dev/usb directory to see what other options you might have. At minimum, you’ll want to add the following environment variables to the bottom of your Portainer-Stack:
UPSNAME (Used in apcupsd-cgi and system tray icons. Should be 8 characters or less)
TZ (The timezone you'd like apcupsd-cgi to use)
Your ready to deploy stack should look something like this:
By the way, apcupsd is also available for Windows, so if any of the PCs you’re connecting to are Windows-based you’ll want to download the Windows installer from:
The Windows installer includes a system tray icon, which you can use for each UPS. I’m monitoring 4 here:
You can get status information from each UPS you monitor from your Windows machine, and the icons change to show if you’re fully charged, charging, or on battery:
There’s also a very nice Android app available, and just like the above Windows-based monitoring, only needs the apcupsd daemon running for data. It’s called APCUPSD Monitor and is available via Google Play:
Once you have apcupsd running for each of your UPS units, deploying the WebUI apcupsd-cgi is the next move. Here’s the stack for that:
version: '3.7'
services:
apcupsd-cgi:
image: bnhf/apcupsd-cgi:latest
container_name: apcupsd-cgi
ports:
- 3552:80
environment:
- UPSHOSTS=${UPSHOSTS} # Ordered list of hostnames or IP addresses of UPS connected computers (space separated, no quotes)
- UPSNAMES=${UPSNAMES} # Matching ordered list of location names to display on status page (space separated, no quotes)
- TZ=${TZ} # Timezone to use for status page -- UTC is the default
restart: unless-stopped
Your minimum environment variables for this stack are:
UPSHOSTS (List of hostnames or IP addresses for computers with connected APC UPSs. Space separated without quotes.)
UPSNAMES (List of names you'd like used in the WebUI. Order must match UPSHOSTS. Space separated without quotes.)
TZ (Timezone for apcupsd-cgi to use when displaying information about individual UPS units)
Your stack should look like this in Portainer:
There are a couple of images of what information you can get from the WebUI (apcupsd-cgi) earlier in this post. After the container deploys successfully, you should be able reach apcupsd-cgi at http://<hostname>:3552
The final whiz-bang add-on to our project is a Grafana Dashboard to display more detail about each of our UPS units over time, as opposed to the more instantaneous data we can see using the above tools. We’re going to create a telegraf-influxdb-grafana (TIG) stack, and provision it with dashboard designed just for this process.
Doing this from scratch can be something of a mission, but thanks to Docker and Cockpit, I think you’ll find it relatively straighforward.
First, using Cockpit, we’ll create a few directories and upload a few configuration files. I use a /data directory for all of the Docker data I’d like to be persistent and the use volume bindings to attach /data subdirectories as needed for each Docker container. If you prefer to do it a different way, adjust accordingly. We’re going to create:
/data/telegraf
/data/grafana/provisioning/datasources
/data/grafana/provisioning/dashboards
Obviously, you need to create each parent directory, and then the child directories as you drill down. It should look like this in Cockpit (with the Navigator plugin). Use the usual right-click in the folders window to create a new directory, and double-click to open that directory folder:
In this example, you can see I’ve created all of my needed directories for /data/grafana. Same process for /data/telegraf.
Next we’ll need to upload the following configuration files:
telegraf.conf to /data/telegraf
datasource.yml to /data/grafana/provisioning/datasources
dashboard.yml to /data/grafana/provisioning/dashboards
APC UPS Detailed Summary.json to /data/grafana/provisioning/dashboards
And again Cockpit – Navigator makes this easy with its convenient upload button:
Here are each of the four files, for you to inspect, and then links to download. Alternatively, you can create an empty file with Cockpit-Navigator and then copy-and-paste the contents. As you can see environment variables have been used, so you don’t need to modify the configuration files. You’ll be specifying the values to assign to these variables in your Portainer-Stack:
telegraf.conf:
[[outputs.influxdb_v2]]
urls = ["http://influxdb2:8086"]
token = "$DOCKER_INFLUXDB_INIT_ADMIN_TOKEN"
organization = "$DOCKER_INFLUXDB_INIT_ORG"
bucket = "$DOCKER_INFLUXDB_INIT_BUCKET"
[[inputs.apcupsd]]
servers = ["tcp://$UPS1", "tcp://$UPS2", "tcp://$UPS3", "tcp://$UPS4", "tcp://$UPS5", "tcp://$UPS6", "tcp://$UPS7", "tcp://$UPS8"]
timeout = "5s"
datasource.yml:
apiVersion: 1
datasources:
- name: InfluxDB2
type: influxdb
access: proxy
url: http://influxdb2:8086
basicAuth: true
isDefault: true
basicAuthUser: $GF_SECURITY_ADMIN_USER
jsonData:
version: Flux
organization: $DOCKER_INFLUXDB_INIT_ORG
defaultBucket: $DOCKER_INFLUXDB_INIT_BUCKET
secureJsonData:
token: $DOCKER_INFLUXDB_INIT_ADMIN_TOKEN
basicAuthPassword: $GF_SECURITY_ADMIN_PASSWORD
dashboard.yml:
apiVersion: 1
providers:
# <string> an unique provider name
- name: 'default'
# <int> org id. will default to orgId 1 if not specified
orgId: 1
# <string, required> name of the dashboard folder. Required
folder: ''
# <string> folder UID. will be automatically generated if not specified
folderUid: ''
# <string, required> provider type. Required
type: file
# <bool> disable dashboard deletion
disableDeletion: false
# <bool> enable dashboard editing
editable: true
# <int> how often Grafana will scan for changed dashboards
updateIntervalSeconds: 10
options:
# <string, required> path to dashboard files on disk. Required
path: /etc/grafana/provisioning/dashboards
APC UPS Detailed Summary.json (this one is too big to display here):
{
"__inputs": [
{
"name": "DS_INFLUXDB2",
"label": "InfluxDB2",
"description": "",
"type": "datasource",
"pluginId": "influxdb",
"pluginName": "InfluxDB"
}
],
"__elements": {},
"__requires": [
{
"type": "panel",
"id": "gauge",
"name": "Gauge",
"version": ""
},
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "9.3.2"
},
{
"type": "datasource",
"id": "influxdb",
"name": "InfluxDB",
"version": "1.0.0"
},
{
"type": "panel",
"id": "stat",
"name": "Stat",
"version": ""
},
{
"type": "panel",
"id": "timeseries",
"name": "Time series",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "InfluxDB2",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"description": "A Flux-based modification of the InfluxQL-based dashboard from https://grafana.com/grafana/dashboards/12625 - thank you, jenniferhatches. Modifications pertain to layout (less emphasis on power consumption costs), colour thresholds for UPS Runtime, and the addition of power factor calculated based on maximum load/real power (watts) and maximum apparent power (volt-amps) supported by the UPS, as well as correct representation of the calculated load and total UPS consumption as a function of load percentage. You will need to manually alter the load power figures for the \"maxwatt\" variable, in accordance with APC's official specifications for your UPS unit(s). \"maxvoltamp\" variable will continue to automatically extract its value from the model name, as per the previous author's design.\n\nNotes for Revision 2: Completely revamped the calculation for kWh graphs, which were so far away from accuracy I'm embarrassed I overlooked them when interpreting the code from InfluxQL to Flux. Correctly using integral function for gathering kWh consumption in both 24hr and 1M periods.",
"editable": true,
"fiscalYearStartMonth": 0,
"gnetId": 15010,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"decimals": 1,
"mappings": [
{
"options": {
"BOOST ONLINE": {
"color": "light-yellow",
"index": 2,
"text": "BOOST"
},
"COMMLOST": {
"color": "light-purple",
"index": 4,
"text": "NO COMMS"
},
"ONBATT": {
"color": "semi-dark-red",
"index": 3,
"text": "ON BATTERY"
},
"ONLINE": {
"color": "semi-dark-green",
"index": 1,
"text": "ONLINE"
},
"ONLINE LOWBATT": {
"color": "semi-dark-red",
"index": 5,
"text": "ONLINE (Check batteries)"
}
},
"type": "value"
},
{
"options": {
"match": "null",
"result": {
"index": 0,
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
}
]
},
"unit": "string"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "_value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
}
]
},
"gridPos": {
"h": 6,
"w": 5,
"x": 0,
"y": 0
},
"hideTimeOverride": true,
"id": 42,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "/.*/",
"values": true
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Volts",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> keep(columns: [\"status\"])\r\n |> group()\r\n |> distinct(column: \"status\")\r\n |> last()\r\n ",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_voltage"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "now-1m",
"title": "Status",
"transformations": [],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"max": 100,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "semi-dark-green",
"value": null
},
{
"color": "light-yellow",
"value": 25
},
{
"color": "semi-dark-orange",
"value": 50
},
{
"color": "dark-red",
"value": 75
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 4,
"x": 5,
"y": 0
},
"hideTimeOverride": true,
"id": 55,
"links": [],
"maxDataPoints": 100,
"options": {
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showThresholdLabels": true,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Percent",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"load_percent\")\r\n |> group()\r\n |> yield(name: \"last\")\r\n",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"slimit": "",
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1h",
"title": "Load Power",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "gauge"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"max": 100,
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#d44a3a",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 20
},
{
"color": "#299c46",
"value": 50
}
]
},
"unit": "percent"
},
"overrides": []
},
"gridPos": {
"h": 6,
"w": 4,
"x": 9,
"y": 0
},
"hideTimeOverride": true,
"id": 4,
"links": [],
"maxDataPoints": 100,
"options": {
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"showThresholdLabels": true,
"showThresholdMarkers": true,
"text": {}
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Percent",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"battery_charge_percent\")\r\n |> group()\r\n |> yield(name: \"last\")\r\n",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"slimit": "",
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1h",
"title": "Battery Charge",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "gauge"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "#d44a3a",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 2700000000000
},
{
"color": "#299c46",
"value": 3600000000000
}
]
},
"unit": "ns"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "time_left_ns"
},
"properties": [
{
"id": "displayName",
"value": "${__field.labels.ups_name}"
}
]
}
]
},
"gridPos": {
"h": 6,
"w": 4,
"x": 13,
"y": 0
},
"hideTimeOverride": true,
"id": 6,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": [
"mean"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"time_left_ns\")\r\n |> last()\r\n |> yield(name: \"last\")\r\n",
"refId": "A",
"resultFormat": "table",
"select": [
[
{
"params": [
"time_left_ns"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1m",
"title": "Runtime Remaining",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"0": {
"index": 1,
"text": "Not on battery"
}
},
"type": "value"
},
{
"options": {
"match": "null",
"result": {
"index": 0,
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "dark-blue",
"value": null
},
{
"color": "rgba(237, 129, 40, 0.89)",
"value": 2700000000000
},
{
"color": "semi-dark-red",
"value": 3600000000000
}
]
},
"unit": "ns"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "time_left_ns"
},
"properties": [
{
"id": "displayName",
"value": "${__field.labels.ups_name}"
}
]
}
]
},
"gridPos": {
"h": 6,
"w": 4,
"x": 17,
"y": 0
},
"hideTimeOverride": true,
"id": 56,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "background",
"fieldOptions": {
"calcs": [
"mean"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"last"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"time_on_battery_ns\")\r\n |> last()\r\n |> yield(name: \"last\")\r\n",
"refId": "A",
"resultFormat": "table",
"select": [
[
{
"params": [
"time_left_ns"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1m",
"title": "Time on Battery",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "yellow",
"value": 12
},
{
"color": "green",
"value": 13
}
]
},
"unit": "volt"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 3,
"x": 21,
"y": 0
},
"hideTimeOverride": true,
"id": 54,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Volts",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"battery_voltage\")\r\n |> last()\r\n |> yield(name: \"last\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_voltage"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "now-1m",
"title": "Battery Voltage",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " ",
"battery_voltage {host=\"ubuntu-magnum-20\", model=\"Smart-UPS 1000 XL\", serial=\"AS0539232598\", status=\"ONLINE\", ups_name=\"UPSTower\"}": " ",
"battery_voltage {host=\"ubuntu-magnum-20\", model=\"Smart-UPS 1500 RM\", serial=\"AS0633131078\", status=\"ONLINE\", ups_name=\"UPS Rack\"}": " "
}
}
}
],
"type": "stat"
},
{
"datasource": "InfluxDB2",
"description": "",
"fieldConfig": {
"defaults": {
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 375
}
]
},
"unit": "none"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "_value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
},
{
"matcher": {
"id": "byFrameRefID",
"options": "Real"
},
"properties": [
{
"id": "unit",
"value": "watt"
},
{
"id": "displayName",
"value": "Real"
}
]
},
{
"matcher": {
"id": "byFrameRefID",
"options": "Apparent"
},
"properties": [
{
"id": "unit",
"value": "voltamp"
},
{
"id": "displayName",
"value": "Apparent"
}
]
}
]
},
"gridPos": {
"h": 3,
"w": 3,
"x": 21,
"y": 3
},
"hideTimeOverride": true,
"id": 10,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {
"valueSize": 32
},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Watts",
"datasource": "InfluxDB2",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"load_percent\")\r\n |> keep(columns: [\"_time\",\"_value\"])\r\n |> map(fn: (r) => ({ r with _value: (r._value / 100.0) * float(v: ${maxwatt})}))\r\n |> yield(name: \"last\")\r\n",
"rawQuery": false,
"refId": "Real",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"load_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
},
{
"params": [
" / 100*$maxwatt"
],
"type": "math"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
},
{
"datasource": "InfluxDB2",
"hide": false,
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"load_percent\")\r\n |> keep(columns: [\"_time\",\"_value\"])\r\n |> map(fn: (r) => ({ r with _value: (r._value / 100.0) * float(v: ${maxvoltamp})}))\r\n |> keep(columns: [\"_value\"])\r\n |> yield(name: \"last\")\r\n",
"refId": "Apparent"
}
],
"timeFrom": "now-1m",
"title": "Current UPS Load",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " ",
"load_percent {host=\"ubuntu-magnum-20\", model=\"Smart-UPS 1000 XL\", serial=\"AS0539232598\", status=\"ONLINE\", ups_name=\"UPSTower\"}": " ",
"load_percent {host=\"ubuntu-magnum-20\", model=\"Smart-UPS 1500 RM\", serial=\"AS0633131078\", status=\"ONLINE\", ups_name=\"UPS Rack\"}": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "ns"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
},
{
"matcher": {
"id": "byName",
"options": "APC.mean"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "rgb(0, 218, 255)",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "UPS Load"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "#70dbed",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "Minutes"
},
"properties": [
{
"id": "unit",
"value": "watt"
},
{
"id": "custom.axisPlacement",
"value": "hidden"
},
{
"id": "custom.axisLabel",
"value": "Watts"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 11,
"x": 0,
"y": 6
},
"hideTimeOverride": false,
"id": 49,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Runtime Remaining",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"time_left_ns\")\r\n |> keep(columns: [\"_time\",\"_value\",\"battery_charge_percent\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"time_left_ns"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Runtime Remaining",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds",
"seriesBy": "last"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "semi-dark-red",
"value": null
},
{
"color": "#EAB839",
"value": 200
},
{
"color": "green",
"value": 220
}
]
},
"unit": "volt"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 10,
"x": 11,
"y": 6
},
"id": 50,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Battery Charge",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"input_voltage\")\r\n |> keep(columns: [\"_time\",\"_value\",\"input_voltage\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Input Voltage",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "yellow",
"value": 12
},
{
"color": "green",
"value": 13
}
]
},
"unit": "hertz"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "input_frequency"
},
"properties": [
{
"id": "displayName",
"value": "${__field.labels.ups_name}"
}
]
}
]
},
"gridPos": {
"h": 3,
"w": 3,
"x": 21,
"y": 6
},
"hideTimeOverride": true,
"id": 44,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Hz",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"input_frequency\")\r\n |> last()\r\n |> yield(name: \"last\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"input_frequency"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "now-1m",
"title": "Input Frequency",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "yellow",
"value": 200
},
{
"color": "green",
"value": 220
}
]
},
"unit": "volt"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "input_voltage"
},
"properties": [
{
"id": "displayName",
"value": "${__field.labels.ups_name}"
}
]
}
]
},
"gridPos": {
"h": 4,
"w": 3,
"x": 21,
"y": 9
},
"hideTimeOverride": true,
"id": 43,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Volts",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"input_voltage\")\r\n |> last()\r\n |> yield(name: \"last\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"input_voltage"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "now-1m",
"title": "Input Voltage",
"transformations": [],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"max": 100,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
},
{
"matcher": {
"id": "byName",
"options": "APC.mean"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "rgb(0, 218, 255)",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "UPS Load"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "#70dbed",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "Watts"
},
"properties": [
{
"id": "unit",
"value": "watt"
},
{
"id": "custom.axisPlacement",
"value": "hidden"
},
{
"id": "custom.axisLabel",
"value": "Watts"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 11,
"x": 0,
"y": 13
},
"id": 48,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Battery Charge",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"battery_charge_percent\")\r\n |> keep(columns: [\"_time\",\"_value\",\"battery_charge_percent\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Battery Charge %",
"transformations": [],
"type": "timeseries"
},
{
"datasource": "InfluxDB2",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "percent"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
},
{
"matcher": {
"id": "byName",
"options": "APC.mean"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "rgb(0, 218, 255)",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "UPS Load"
},
"properties": [
{
"id": "color",
"value": {
"fixedColor": "#70dbed",
"mode": "fixed"
}
}
]
},
{
"matcher": {
"id": "byName",
"options": "Watts"
},
"properties": [
{
"id": "unit",
"value": "watt"
},
{
"id": "custom.axisPlacement",
"value": "hidden"
},
{
"id": "custom.axisLabel",
"value": "Watts"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 10,
"x": 11,
"y": 13
},
"id": 2,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "UPS Load",
"datasource": "InfluxDB2",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"load_percent\")\r\n |> keep(columns: [\"_time\",\"_value\",\"battery_charge_percent\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"load_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "UPS Load %",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "red",
"value": null
},
{
"color": "yellow",
"value": 200
},
{
"color": "green",
"value": 220
}
]
},
"unit": "volt"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "output_voltage"
},
"properties": [
{
"id": "displayName",
"value": "${__field.labels.ups_name}"
}
]
}
]
},
"gridPos": {
"h": 4,
"w": 3,
"x": 21,
"y": 13
},
"hideTimeOverride": true,
"id": 45,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Volts",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"output_voltage\")\r\n |> last()\r\n |> yield(name: \"last\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"output_voltage"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "now-1m",
"title": "Output Voltage",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 1,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "yellow",
"value": 35
},
{
"color": "semi-dark-red",
"value": 45
}
]
},
"unit": "celsius"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "internal_temp"
},
"properties": [
{
"id": "displayName",
"value": "${__field.labels.ups_name}"
}
]
}
]
},
"gridPos": {
"h": 3,
"w": 3,
"x": 21,
"y": 17
},
"hideTimeOverride": true,
"id": 46,
"links": [],
"maxDataPoints": 100,
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"lastNotNull"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"mean"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "C",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"internal_temp\")\r\n |> last()\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"internal_temp"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "now-1m",
"title": "Internal Temp",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 22
},
{
"color": "#EAB839",
"value": 23
},
{
"color": "light-green",
"value": 24
}
]
},
"unit": "volt"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 11,
"x": 0,
"y": 20
},
"id": 52,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Battery Charge",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"battery_voltage\")\r\n |> keep(columns: [\"_time\",\"_value\",\"battery_voltage\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Battery Voltage",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"max": 60,
"min": 40,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 190
},
{
"color": "#EAB839",
"value": 219
},
{
"color": "light-green",
"value": 220
}
]
},
"unit": "hertz"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 10,
"x": 11,
"y": 20
},
"id": 57,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Battery Charge",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"input_frequency\")\r\n |> keep(columns: [\"_time\",\"_value\",\"input_frequency\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Input Frequency",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 2,
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": "N/A"
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
},
"unit": "kwatth"
},
"overrides": []
},
"gridPos": {
"h": 4,
"w": 3,
"x": 21,
"y": 20
},
"hideTimeOverride": true,
"id": 41,
"interval": "1h",
"links": [],
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"sum"
]
},
"graphMode": "none",
"justifyMode": "auto",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"sum"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"load_percent\")\r\n |> keep(columns: [\"_time\",\"_value\",\"load_percent\"])\r\n |> map(fn: (r) => ({ r with _value: ((r._value / 100.0) * float(v: ${maxvoltamp}) / 1000.0)}))\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"load_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
},
{
"params": [
"/100*$maxwatt/1000"
],
"type": "math"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1d",
"title": "Past Day's Usage",
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": " "
}
}
}
],
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"decimals": 2,
"displayName": "$currency",
"mappings": [
{
"options": {
"match": "null",
"result": {
"text": ""
}
},
"type": "special"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 80
}
]
},
"unit": "none"
},
"overrides": []
},
"gridPos": {
"h": 3,
"w": 3,
"x": 21,
"y": 24
},
"hideTimeOverride": true,
"id": 22,
"interval": "1h",
"links": [],
"options": {
"colorMode": "value",
"fieldOptions": {
"calcs": [
"sum"
]
},
"graphMode": "none",
"justifyMode": "center",
"orientation": "horizontal",
"reduceOptions": {
"calcs": [
"sum"
],
"fields": "",
"values": false
},
"text": {},
"textMode": "auto"
},
"pluginVersion": "9.3.2",
"targets": [
{
"alias": "Costs",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"load_percent\")\r\n |> keep(columns: [\"_time\",\"_value\"])\r\n |> map(fn: (r) => ({ r with _value: ((r._value / 100.0) * float(v: ${maxvoltamp}) / 1000.0) * ${kwhprice}}))\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"load_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
},
{
"params": [
"/100*$maxwatt/1000*$kwhprice"
],
"type": "math"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1d",
"title": "Past Day's Cost",
"type": "stat"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [
{
"options": {
"0": {
"index": 0,
"text": "Not on battery"
}
},
"type": "value"
}
],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
},
{
"color": "red",
"value": 22
},
{
"color": "#EAB839",
"value": 23
},
{
"color": "light-green",
"value": 24
}
]
},
"unit": "ns"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 11,
"x": 0,
"y": 27
},
"id": 53,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Battery Charge",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"time_on_battery_ns\")\r\n |> keep(columns: [\"_time\",\"_value\",\"time_on_battery_ns\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Time on Battery",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 40,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"links": [],
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "semi-dark-red"
},
{
"color": "#EAB839",
"value": 200
},
{
"color": "green",
"value": 220
}
]
},
"unit": "volt"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 10,
"x": 11,
"y": 27
},
"id": 51,
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"max",
"min"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": false
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.3",
"targets": [
{
"alias": "Battery Charge",
"datasource": {
"uid": "$upsdatasource"
},
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"none"
],
"type": "fill"
}
],
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> filter(fn: (r) => r._field == \"output_voltage\")\r\n |> keep(columns: [\"_time\",\"_value\",\"output_voltage\",\"upsname\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n |> yield(name: \"mean\")\r\n",
"rawQuery": false,
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"battery_charge_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"title": "Output Voltage",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "bars",
"fillOpacity": 100,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 1,
"links": [],
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
}
]
},
"unit": "kwatth"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
},
{
"id": "color",
"value": {
"fixedColor": "semi-dark-yellow",
"mode": "fixed"
}
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 11,
"x": 0,
"y": 34
},
"hideTimeOverride": false,
"id": 34,
"interval": "1M",
"links": [],
"options": {
"legend": {
"calcs": [
"mean",
"lastNotNull",
"max",
"sum"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.2",
"targets": [
{
"alias": "kWh",
"datasource": {
"uid": "$upsdatasource"
},
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"load_percent\")\r\n |> aggregateWindow(\r\n every: 1h,\r\n fn: (tables=<-, column) =>\r\n tables\r\n |> integral(unit: 1h)\r\n |> map(fn: (r) => ({ r with _value: ((r._value / 100.0) * float(v: ${maxvoltamp}) / 1000.0)})))\r\n |> keep(columns: [\"_time\",\"_value\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: false)",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"load_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
},
{
"params": [
"/100*$maxwatt/1000*24"
],
"type": "math"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1y",
"title": "Power Consumption",
"transformations": [],
"type": "timeseries"
},
{
"datasource": {
"uid": "$upsdatasource"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "left",
"barAlignment": 1,
"drawStyle": "bars",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 5,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"decimals": 1,
"links": [],
"mappings": [],
"min": 0,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green"
}
]
},
"unit": "kwatth"
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Value"
},
"properties": [
{
"id": "displayName",
"value": "${upsname}"
},
{
"id": "color",
"value": {
"fixedColor": "semi-dark-yellow",
"mode": "fixed"
}
}
]
}
]
},
"gridPos": {
"h": 7,
"w": 10,
"x": 11,
"y": 34
},
"hideTimeOverride": false,
"id": 33,
"interval": "1d",
"links": [],
"options": {
"legend": {
"calcs": [
"min",
"mean",
"max"
],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"pluginVersion": "8.1.2",
"targets": [
{
"alias": "kWh",
"datasource": {
"uid": "$upsdatasource"
},
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$__interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"hide": false,
"measurement": "apcupsd",
"orderByTime": "ASC",
"policy": "default",
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"load_percent\")\r\n |> aggregateWindow(\r\n every: 1h,\r\n fn: (tables=<-, column) =>\r\n tables\r\n |> integral(unit: 1h)\r\n |> map(fn: (r) => ({ r with _value: ((r._value / 100.0) * float(v: ${maxvoltamp}) / 1000.0)})))\r\n |> keep(columns: [\"_time\",\"_value\"])\r\n |> aggregateWindow(every: v.windowPeriod, fn: sum, createEmpty: false)\r\n// |> keep(columns: [\"_time\",\"_value\",\"upsname\"])\r\n// |> map(fn: (r) => ({ r with _value: ((r._value / 100.0) * float(v: ${maxvoltamp}) / 1000.0 * 24.0)}))\r\n// |> keep(columns: [\"_time\",\"_value\"])\r\n// |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\r\n// |> yield(name: \"mean\")\r\n",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"load_percent"
],
"type": "field"
},
{
"params": [],
"type": "mean"
},
{
"params": [
"/100*$maxwatt/1000*24"
],
"type": "math"
}
]
],
"tags": [
{
"key": "ups_name",
"operator": "=~",
"value": "/^$upsname$/"
}
]
}
],
"timeFrom": "1M",
"title": "Power Consumption",
"transformations": [],
"type": "timeseries"
}
],
"refresh": "30s",
"schemaVersion": 37,
"style": "dark",
"tags": [
"apcupsd"
],
"templating": {
"list": [
{
"current": {
"selected": false,
"text": "InfluxDB2",
"value": "InfluxDB2"
},
"hide": 0,
"includeAll": false,
"label": "UPS Datasource",
"multi": false,
"name": "upsdatasource",
"options": [],
"query": "influxdb",
"queryValue": "",
"refresh": 1,
"regex": "/^InfluxDB2/",
"skipUrlSync": false,
"type": "datasource"
},
{
"current": {},
"datasource": "InfluxDB2",
"definition": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\")\r\n |> keep(columns: [\"ups_name\"])\r\n |> group()\r\n |> distinct(column: \"ups_name\")\r\n\r\n ",
"hide": 0,
"includeAll": false,
"label": "UPS Name",
"multi": false,
"name": "upsname",
"options": [],
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\")\r\n |> keep(columns: [\"ups_name\"])\r\n |> group()\r\n |> distinct(column: \"ups_name\")\r\n\r\n ",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {},
"datasource": "InfluxDB2",
"definition": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> keep(columns: [\"model\"])\r\n |> group()\r\n |> distinct(column: \"model\")\r\n\r\n",
"hide": 0,
"includeAll": false,
"label": "UPS Max Output Power Capacity (VA)",
"multi": false,
"name": "maxvoltamp",
"options": [],
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> keep(columns: [\"model\"])\r\n |> group()\r\n |> distinct(column: \"model\")\r\n\r\n",
"refresh": 1,
"regex": "/.*(\\d{4,4})/",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"current": {},
"datasource": "InfluxDB2",
"definition": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"nominal_power\")\r\n |> keep(columns: [\"_time\",\"ups_name\"])\r\n |> map(fn: (r) => ({ r with _value: if \"${upsname}\" == \"UPSTower\" then 800 else 980}))\r\n |> yield(name: \"last\")\r\n",
"hide": 0,
"includeAll": false,
"label": "UPS Max Output Power Capacity (W)",
"multi": false,
"name": "maxwatt",
"options": [],
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\" and r._field == \"nominal_power\")\r\n |> keep(columns: [\"_time\",\"ups_name\"])\r\n |> map(fn: (r) => ({ r with _value: if \"${upsname}\" == \"UPSTower\" then 800 else 980}))\r\n |> yield(name: \"last\")\r\n",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {},
"datasource": "InfluxDB2",
"definition": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> keep(columns: [\"_time\",\"ups_name\"])\r\n |> map(fn: (r) => ({ r with _value: if \"${upsname}\" == \"UPSTower\" then float(v: ${maxwatt})/float(v: ${maxvoltamp}) else float(v: ${maxwatt})/float(v: ${maxvoltamp})}))\r\n |> yield(name: \"last\")\r\n",
"hide": 0,
"includeAll": false,
"label": "Power Factor",
"multi": false,
"name": "powerfactor",
"options": [],
"query": "from(bucket: \"telegraf\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r._measurement == \"apcupsd\" and r.ups_name == \"${upsname}\")\r\n |> keep(columns: [\"_time\",\"ups_name\"])\r\n |> map(fn: (r) => ({ r with _value: if \"${upsname}\" == \"UPSTower\" then float(v: ${maxwatt})/float(v: ${maxvoltamp}) else float(v: ${maxwatt})/float(v: ${maxvoltamp})}))\r\n |> yield(name: \"last\")\r\n",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"type": "query"
},
{
"current": {
"selected": true,
"text": ".15",
"value": ".15"
},
"hide": 0,
"label": "kWh Price",
"name": "kwhprice",
"options": [
{
"selected": true,
"text": ".15",
"value": ".15"
}
],
"query": ".15",
"skipUrlSync": false,
"type": "textbox"
},
{
"current": {
"selected": false,
"text": "$",
"value": "$"
},
"hide": 0,
"includeAll": false,
"label": "Currency",
"multi": false,
"name": "currency",
"options": [
{
"selected": true,
"text": "$",
"value": "$"
},
{
"selected": false,
"text": "€",
"value": "€"
},
{
"selected": false,
"text": "£",
"value": "£"
},
{
"selected": false,
"text": "C$",
"value": "C$"
},
{
"selected": false,
"text": "kr",
"value": "kr"
},
{
"selected": false,
"text": "₽",
"value": "₽"
},
{
"selected": false,
"text": "Â¥",
"value": "Â¥"
},
{
"selected": false,
"text": "R",
"value": "R"
}
],
"query": "$,€,£,C$,kr,₽,¥,R",
"queryValue": "",
"skipUrlSync": false,
"type": "custom"
}
]
},
"time": {
"from": "now-3h",
"to": "now"
},
"timepicker": {
"hidden": false,
"refresh_intervals": [
"30s",
"1m",
"15m",
"30m",
"1h"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "",
"title": "APC UPS Detailed Summary",
"uid": "RwSBnsS7z",
"version": 5,
"weekStart": ""
}
OK, so we created our directories and placed out config files. Now we can create our Portainer-Stack, including a few environment variables, which will be used to provision our containers and also for the 4 configuration files we just uploaded:
version: '3.7'
services:
influxdb2:
image: influxdb:latest
container_name: influxdb2
ports:
- 8086:8086
volumes:
- /data/influxdb2/data:/var/lib/influxdb2
- /data/influxdb2/config:/etc/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=${MODE} # Required, usually <setup>
- DOCKER_INFLUXDB_INIT_USERNAME=${USERNAME} # Usually <admin> and this will be the username for Grafana as well
- DOCKER_INFLUXDB_INIT_PASSWORD=${PASSWORD} # Whatever you want for a password for InfluxDB and Grafana
- DOCKER_INFLUXDB_INIT_ORG=${ORG} # Required, make something up if you're not part of an organization
- DOCKER_INFLUXDB_INIT_BUCKET=${BUCKET} # Required, usually <telegraf>
- DOCKER_INFLUXDB_INIT_RETENTION=${RETENTION} # Required, usually <1w>
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${ADMIN_TOKEN} # Required, make up a token or use https://randomkeygen.com CodeIgniter Encryption Keys
restart: unless-stopped
telegraf:
image: telegraf:latest
container_name: telegraf
pid: 'host'
ports:
- 8092:8092
- 8094:8094
- 8125:8125
environment:
- HOST_PROC=/host/proc
- HOST_SYS=/host/sys
- HOST_ETC=/host/etc
- DOCKER_INFLUXDB_INIT_ORG=${ORG}
- DOCKER_INFLUXDB_INIT_BUCKET=${BUCKET}
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${ADMIN_TOKEN}
- UPS1=${UPS1}
- UPS2=${UPS2} # Optional if you have more than one UPS
- UPS3=${UPS3} # Optional if you have more than one UPS
- UPS4=${UPS4} # Optional if you have more than one UPS
- UPS5=${UPS5} # Optional if you have more than one UPS
- UPS6=${UPS6} # Optional if you have more than one UPS
- UPS7=${UPS7} # Optional if you have more than one UPS
- UPS8=${UPS8} # Optional if you have more than one UPS
volumes:
- /data/telegraf/telegraf.conf:/etc/telegraf/telegraf.conf:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- /sys:/host/sys:ro
- /proc:/host/proc:ro
- /etc:/host/etc:ro
restart: unless-stopped
grafana8:
image: grafana/grafana:latest
container_name: grafana8
ports:
- 3000:3000
user: '0:0'
environment:
- GF_SECURITY_ADMIN_USER=${USERNAME}
- GF_SECURITY_ADMIN_PASSWORD=${PASSWORD}
- GF_SECURITY_ALLOW_EMBEDDING=true # Allows iFrame embedding in Organizr for example
- DOCKER_INFLUXDB_INIT_ORG=${ORG}
- DOCKER_INFLUXDB_INIT_BUCKET=${BUCKET}
- DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${ADMIN_TOKEN}
volumes:
- /data/grafana:/var/lib/grafana
- /data/grafana/provisioning:/etc/grafana/provisioning
restart: unless-stopped
And, don’t forget to add your environment variables:
MODE=setup
USERNAME=admin
PASSWORD=
ORG=
BUCKET=telegraf
RETENTION=1w
ADMIN_TOKEN=
UPS1=<hostname or IP>:3551
UPS2=<hostname or IP>:3551
UPS3=<hostname or IP>:3551
UPS4=<hostname or IP>:3551
UPS5=<hostname or IP>:3551
UPS6=<hostname or IP>:3551
I’ve left values where you should keep the “default” unless you know what you’re doing. Delete any unneeded UPS variables. You can use the “Advanced” mode in Environment section of Portainer to paste the above, and then switch to “Simple” to adjust values and delete unneeded UPSx values. You ready-to-deploy Portainer-Stack should look like this:
Once your provisioned TIG stack has deployed, you should be able reach the Grafana WebUI at http://<hostname>:3000. You’ll login with username and password you specified in your stack:
Once logged in, navigate to Dashboards-Browse and you should see APC UPS Detailed Summary. Click on that, and the Dashboard should launch with data from one of your UPS units. The others can be accessed using the “UPS Name” dropdown. From here forward, as long as your stack continues to run, it’ll be gathering data from your UPS units:
Not too bad eh? If you’ve successfully followed along, you should have docker-based daemons monitoring each of your UPS units. And, more importantly, multiple ways to make use of that data — whether by WebUI, Grafana dashboard, Windows system tray, Android phone or all of the above. All with little or no time at the command line. 😉 Enjoy!
Hi! I’m getting an error when trying to run the apcupsd-cgi container on a Raspberry Pi 3B+ with Debian Bullseye OS Lite (32-bit):
exec format error
Can you help?
I had a little snafu yesterday trying to build with Debian:bookworm, which I thought I fixed — but apparently not for ARMv7. Fixed now I believe, so give it another try.
Worked nicely now. Thanks a lot!
Raspberry Pi OS
Debian version: 11 (bullseye)
On a raspberry Pi 3
I have the apcupsd and apcupsd-cgi working with docker, portainer and cockpit.
Try to get the Grafana Dashboard but i get the following issue deploying.
I get the following Deployment error:
failed to deploy a stack: grafana8 Pulling telegraf Pulling influxdb2 Pulling no matching manifest for linux/arm/v7 in the manifest list entries
Looks like InfluxDB2 isn’t available for the 32bit version of the RaspberryPi OS — which is too bad since Grafana and Telegraf are. You can run the 64bit OS on the Raspberry Pi 3B, so that’s one option, or you could put the apcupsd-cgi and TIG projects on a different 64bit system.
I am trying to use apcupsd and apcupsd-cgi in portainer / Docker on Debian bookworm.
This is with only a master APC UPS no slaves. And on the same machine.
portainer will not deploy the apcusbd container. It throws up the following error
failed to deploy a stack: Network apcupsd_default Creating Network apcupsd_default Created Container apcupsd Creating Container apcupsd Created Container apcupsd Starting Error response from daemon: driver failed programming external connectivity on endpoint apcupsd (923b0f6916f425b75bf25e2f4a6e7f0075ba33adcb6e19f304823057fd1c4ce2): Error starting userland proxy: listen tcp4 0.0.0.0:3551: bind: address already in use
I am wondering if this is due to not being able to set the device correctly in apcupsd
devices:
– /dev/usb/hiddev0 # This device needs to match what the APC UPS on your APCUPSD_MASTER system uses — Comment out this section on APCUPSD_SLAVES
sudo ls -al /dev/usb/ Gives the following result.
dell@Debian-x79:/# sudo ls -al /dev/usb/
total 0 drwxr-xr-x 2 root root 60 Mar 6 20:39 .
drwxr-xr-x 20 root root 3800 Mar 6 20:39 ..
crw——- 1 root root 180, 0 Mar 6 20:39 hiddev0
And the slush command gives the following result
dell@Debian-x79:/# lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 413c:301a Dell Computer Corp. Dell MS116 Optical Mouse
Bus 001 Device 002: ID 051d:0002 American Power Conversion Uninterruptible Power Supply
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
And ideas what’s going wrong ?.
Thanks.
Looks like port 3551 is in use. Is apcupsd already installed at the OS level?
pi@raspberrypi10:~ $ sudo lsof -i -P -n | grep '3551 (LISTEN)'
docker-pr 2093 root 4u IPv4 19786 0t0 TCP *:3551 (LISTEN)
docker-pr 2140 root 4u IPv6 19794 0t0 TCP *:3551 (LISTEN)
pi@raspberrypi10:~ $
apcupsd is already installed at the OS level – yes.
dell@Debian-x79:~# sudo lsof -i -P -n | grep ‘3551 (LISTEN)’
docker-pr 2093 root 4u IPv4 19786 0t0 TCP *:3551 (LISTEN)
docker-pr 2140 root 4u IPv6 19794 0t0 TCP *:3551 (LISTEN)
apcupsd 2211541 root 5u IPv4 3466610 0t0 TCP 127.0.0.1:3551 (LISTEN)
-bash: syntax error near unexpected token `(‘
-bash: syntax error near unexpected token `(‘
So, you’d need to uninstall it at the OS level, if you want to run this containerized version of apcupsd. You can’t have two versions of it running both trying to grab the same resources.
apcupsd now uninstalled at OS level, I had forgotten that it was there.
apcupsd stack now deploys. But it seems to constantly connect – disconnect.
I tried with apcupsd at OS level, to eliminate if driver / HW issue, and it stays connected.