Skip to content

puckawayjeff/poe-nut

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

POE-NUT: ESP32-P4 PoE NUT Server for APC UPS

A dedicated Network UPS Tools (NUT) server running on a Waveshare ESP32-P4-ETH with PoE, communicating with APC Back-UPS devices via USB HID over Ethernet on port 3493.

Overview

POE-NUT turns a $30 ESP32-P4 board into a standalone NUT server. It connects to an APC UPS via USB HID, reads real battery/power data, and serves it over Ethernet using the standard NUT protocol. Powered entirely by PoE — one Ethernet cable does everything.

Key Features

  • Real USB HID data from APC Back-UPS devices (not mock/simulated)
  • PoE powered — single Ethernet cable for power and network
  • Standard NUT protocol — works with upsc, upsmon, PeaNUT, Home Assistant, etc.
  • Multi-client support — concurrent TCP connections via task-per-connection model
  • DHCP networking — plug and play on any network
  • ESP-IDF v5.4.3 on ESP32-P4 (RISC-V, 360MHz)

Hardware

Component Description
Waveshare ESP32-P4-ETH ESP32-P4 dev board with Ethernet PHY (IP101)
Waveshare PoE Module (B) IEEE 802.3af/at PoE power module
USB 2.0 female Type-A screw-terminal breakout For wiring USB signals to GPIO pins
APC Back-UPS XS/RS 1500G APC UPS with RJ50 USB port
PoE switch or injector To provide power over Ethernet

Quick Start

1. Wire the Hardware

Connect the USB breakout to ESP32-P4 USB Port 1 pins:

USB Breakout       ESP32-P4-ETH
────────────       ────────────
Pin 2 (D-)    →    GPIO 26
Pin 3 (D+)    →    GPIO 27
Pin 4 (GND)   →    GND

The APC UPS connects via its RJ50 USB cable to the screw-terminal breakout. VCC is not needed — the UPS provides its own power. See docs/WIRING.md for details.

2. Build and Flash

Requires ESP-IDF v5.4 or later. See docs/SETUP.md for full setup.

cd esp-idf
source ~/esp/esp-idf/export.sh
idf.py set-target esp32p4
idf.py build
idf.py -p /dev/ttyACM0 flash monitor

3. Test

The device gets an IP via DHCP. Check serial output for the assigned address.

# List all variables
echo "LIST VAR apc" | nc -w 5 <DEVICE_IP> 3493

# Or use upsc
upsc apc@<DEVICE_IP>

Supported NUT Variables

Variable Description Example
battery.charge Battery charge percentage 100
battery.runtime Estimated runtime (seconds) 1755
input.voltage Input AC voltage 121.0
input.frequency Input frequency (Hz) 60.0
ups.load Load percentage 22
ups.status UPS status OL
ups.model UPS model name Back-UPS RS 1500G
ups.serial UPS serial number (from device)
battery.voltage Battery voltage 0.0 *
output.voltage Output voltage 0.0 *
ups.firmware Firmware version Unknown *

* Not available in APC Back-UPS HID descriptor for these collections. See roadmap below.

NUT Protocol Commands

Command Description
VER Server version
NETVER Protocol version
LIST UPS List available UPS devices
LIST VAR <ups> List all variables for a UPS
GET VAR <ups> <var> Get a specific variable
LOGIN <ups> Login to UPS for monitoring
LOGOUT End session

Integration Examples

PeaNUT Web Dashboard

Add the device in PeaNUT's settings.yml:

- host: <DEVICE_IP>
  port: 3493
  device: apc

upsmon (Automatic Shutdown)

Add to /etc/nut/upsmon.conf:

MONITOR apc@<DEVICE_IP> 1 upsmon pass master
MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"

Home Assistant

Add to configuration.yaml:

sensor:
  - platform: nut
    host: <DEVICE_IP>
    port: 3493
    resources:
      - battery.charge
      - battery.runtime
      - ups.load
      - ups.status

Project Structure

poe-nut/
├── esp-idf/                      # ESP-IDF project
│   ├── CMakeLists.txt
│   ├── sdkconfig.defaults
│   ├── partitions.csv
│   ├── main/
│   │   ├── main.c               # Application entry point
│   │   ├── config.c             # Configuration (NVS)
│   │   └── config.h
│   └── components/
│       ├── apc_ups/             # APC UPS USB HID driver + HID parser
│       ├── nut_server/          # NUT protocol TCP server (multi-client)
│       └── ethernet_manager/    # Ethernet PHY (IP101) management
├── docs/
│   ├── SETUP.md                 # Development environment setup
│   └── WIRING.md                # Hardware wiring guide
├── agent-instructions.md        # AI assistant development context
└── LICENSE.md                   # CC BY-NC 4.0

Roadmap

Additional APC UPS values that can be added (present in the HID descriptor):

  • Battery voltage (BATTV) — requires collection-aware HID lookup fix
  • Transfer voltage thresholds (LOTRANS, HITRANS)
  • Sensitivity setting (SENSE)
  • Nominal input voltage (NOMINV)
  • Self-test status (SELFTEST)
  • Nominal power (NOMPOWER)
  • Battery date (BATTDATE)
  • Last transfer reason (LASTXFER)
  • Firmware version — from USB string descriptor
  • Time on battery / cumulative (TONBATT, CUMONBATT) — derived, needs NVS

Other planned improvements:

  • Authentication support
  • NVS-based configuration via serial console
  • OTA firmware updates

Security Notice

This server does not implement authentication — it accepts any username/password. Deploy only on trusted networks. Use firewall rules to restrict access to port 3493.

License

CC BY-NC 4.0 — free for non-commercial use with attribution.

Acknowledgments

About

ESP32 PoE NUT server for USB APC UPS

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors