Skip to content

Commit

Permalink
Merge pull request #2 from twrecked/alpha-02
Browse files Browse the repository at this point in the history
Alpha 02
  • Loading branch information
twrecked authored Nov 26, 2023
2 parents 2c3f525 + 3be99e2 commit 697f682
Show file tree
Hide file tree
Showing 11 changed files with 787 additions and 7 deletions.
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# hass-pwrstat

An integration to poll a _Cyberpower_ UPS through [pwrstat-api](https://github.com/sbruggeman/pwrstat-api).
An integration to poll a _Cyberpower_ UPS throught the
[pwrstat-api](https://github.com/sbruggeman/pwrstat-api) wrapper.


## Thanks
Expand All @@ -15,15 +16,30 @@ Many thanks to:
* @bruggeman for the `pwrstat-api` wrapper.


## Other Options

### Nut
You can use the [Network UPS Tools](https://www.home-assistant.io/integrations/nut/).

And I did for the longest time and it works well. I just found it a little too
powerful for my needs. I have 2 PCs each with a Cyberpower UPS on them and
it ended up being simpler to monitor them in _Home Assistant_ so a lot of
the extra functionality was moot. I also found it would infrequently lock up the
USB connection.


## Introduction

I wrote this to compliment the _pwrstat-api_ wrapper. I've been accessing the
wrapper using the [RESTful API](https://www.home-assistant.io/integrations/rest/)
integration and it was working great. But it was lacking full _Integration_
support and monitoring more than one UPS was a pain to change the config.
support and monitoring more than one UPS was a pain manage to config.

I decided to add proper _Integration_ support.

The integration needs a working `pwrstat-api` server. The integration does not
support any of the cloud feature of _Cyberpower_.


## Installation

Expand Down Expand Up @@ -96,3 +112,7 @@ similar to this:
method: left
```
### `extras/pwrstat`

This is my snapshot of the `pwrstat-api` docker set up. I modified it to mount
the local tools inside the docker so there was no need to include a `deb` file.
2 changes: 2 additions & 0 deletions changelog
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
0.1.0a2:
add example docker
0.1.0a1:
Initial commit.
2 changes: 1 addition & 1 deletion custom_components/pwrstat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .coordinator import PwrStatCoordinator


__version__ = "0.1.0a1"
__version__ = "0.1.0a2"

_LOGGER = logging.getLogger(__name__)

Expand Down
8 changes: 4 additions & 4 deletions custom_components/pwrstat/manifest.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"domain": "pwrstat",
"name": "Cyberpower/pwrstat-api UPS Support",
"name": "pwrstat (Cyberpower cli) Support",
"codeowners": [
"@twrecked"
],
"config_flow": true,
"dependencies": [
],
"documentation": "https://github.com/twrecked/hass-aarlo/blob/master/README.md",
"documentation": "https://github.com/twrecked/hass-pwrstat/blob/main/README.md",
"iot_class": "local_polling",
"issue_tracker": "https://github.com/twrecked/hass-aarlo/issues",
"issue_tracker": "https://github.com/twrecked/hass-pwrstat/issues",
"requirements": [
],
"version": "0.1.0a1"
"version": "0.1.0a2"
}
674 changes: 674 additions & 0 deletions extras/pwrstat/LICENSE

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions extras/pwrstat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# PowerPanel (pwrstat) API

This is a very simple REST API that wraps the PowerPanel pwrstat application for CyberPower battery backups. Only basic GET support for a single JSON object response for all parameters of the UPS are implemented.

# Usage

- Clone GitHub repo to local computer.
- Must have Linux PowerPanel application from CyberPower already downloaded (https://www.cyberpowersystems.com/product/software/powerpanel-for-linux/)
- Place powerpanel_ver_amd64.deb OR PPL-*-64bit.deb (newer) file downloaded from above address in the folder containing this README, on your local computer.
- Run Docker build, or use included Docker-Compose example.
- Note that you cannot use this GitHub repo as a Docker-Compose build context, due to needing to download a local copy of the CyberPower binary.
- Access JSON response at http://<docker host IP>:5002/pwrstat

23 changes: 23 additions & 0 deletions extras/pwrstat/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# The file I use.
# HOME_NAME comes from the command line or .env
# All the Cyberpower utilities are linked in from the outside.
version: '2.1'
services:
ups-status:
container_name: ${HOME_NAME}-ups-status
image: ups-status
network_mode: host
restart: always
volumes:
- /etc/localtime:/etc/localtime:ro
- /usr/sbin/pwrstat:/usr/sbin/pwrstat:ro
- /var/pwrstatd.ipc:/var/pwrstatd.ipc:ro
- /var/pwrstatd.dev:/var/pwrstatd.dev:ro
build:
context: .
dockerfile: dockerfile
logging:
options:
max-size: 5m
max-file: "3"

9 changes: 9 additions & 0 deletions extras/pwrstat/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3

VOLUME /src
COPY pwrstat-api.py requirements.txt init.sh /src/
WORKDIR /src
RUN chmod +x /src/init.sh
RUN chmod +x /src/pwrstat-api.py
RUN pip install --trusted-host pypi.python.org -r requirements.txt
ENTRYPOINT "/src/init.sh"
3 changes: 3 additions & 0 deletions extras/pwrstat/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

/src/pwrstat-api.py
33 changes: 33 additions & 0 deletions extras/pwrstat/pwrstat-api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env python3

from flask import Flask, request
from flask_restful import Resource, Api
from json import dumps
from flask_jsonpify import jsonify
import subprocess

app = Flask(__name__)
api = Api(app)

class pwrstat(Resource):
def get(self):
status = subprocess.Popen(['pwrstat', '-status'], stdout=subprocess.PIPE).communicate()[0].decode('utf-8')
statusArr=[]
statusDict={}

for line in status.splitlines():
line = line.lstrip()
line = line.replace(". ",";")
line = line.replace(".","")
line = line.split(";")
if len(line) > 1:
statusArr.append(line)

statusDict = {k[0]: k[1] for k in statusArr}

return jsonify(statusDict)

api.add_resource(pwrstat, '/pwrstat') # return all parameters

if __name__ == '__main__':
app.run(port=5002, host='0.0.0.0')
3 changes: 3 additions & 0 deletions extras/pwrstat/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
flask
flask_restful
flask-jsonpify

0 comments on commit 697f682

Please sign in to comment.