Installing and monitoring an UPS + local laptop battery with Jeedom

In this tutorial we will monitor an UPS (Eaton Ellipse 1200 PRO) locally connected via USB to the Jeedom’s controller. Due to the inclusion of the UPS in a home automation system AND because this Jeedom installation is also running on a laptop on which is plugged the UPS, there are some specificities ! In a next tutorial we will monitor more -remotes- UPS.

This tutorial is based on this one and this one. Also, this one is very interesting about the shutdown process.

1. Plug the UPS & Install NUT

Plug the UPS with an USB cord on your Jeedom controller while monitoring /var/log/messages.

jeedom@jeedom-stgreg2:~$ su -
Mot de passe :
root@jeedom-stgreg2:~# tail -f /var/log/messages
Aug 19 21:04:36 jeedom-stgreg2 kernel: [131160.232904] usb 2-3.4: new full-speed USB device number 7 using xhci_hcd
Aug 19 21:04:37 jeedom-stgreg2 kernel: [131161.016186] usb 2-3.4: New USB device found, idVendor=0463, idProduct=ffff, bcdDevice= 1.00
Aug 19 21:04:37 jeedom-stgreg2 kernel: [131161.016189] usb 2-3.4: New USB device strings: Mfr=1, Product=2, SerialNumber=4
Aug 19 21:04:37 jeedom-stgreg2 kernel: [131161.016190] usb 2-3.4: Product: Ellipse PRO
Aug 19 21:04:37 jeedom-stgreg2 kernel: [131161.016191] usb 2-3.4: Manufacturer: EATON
Aug 19 21:04:37 jeedom-stgreg2 kernel: [131161.016192] usb 2-3.4: SerialNumber: xxxxxxxxxxx
Aug 19 21:04:37 jeedom-stgreg2 mtp-probe: checking bus 2, device 7: "/sys/devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3.4"
Aug 19 21:04:37 jeedom-stgreg2 mtp-probe: bus: 2, device: 7 was not an MTP device
Aug 19 21:04:37 jeedom-stgreg2 kernel: [131161.035286] hidraw: raw HID events driver (C) Jiri Kosina
Aug 19 21:04:41 jeedom-stgreg2 kernel: [131164.860060] usbcore: registered new interface driver usbhid
Aug 19 21:04:41 jeedom-stgreg2 kernel: [131164.860063] usbhid: USB HID core driver
Aug 19 21:04:41 jeedom-stgreg2 mtp-probe: checking bus 2, device 7: "/sys/devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3.4"
Aug 19 21:04:41 jeedom-stgreg2 mtp-probe: bus: 2, device: 7 was not an MTP device
Aug 19 21:04:41 jeedom-stgreg2 kernel: [131164.874069] hid-generic 0003:0463:FFFF.0001: hiddev0,hidraw0: USB HID v1.10 Device [EATON Ellipse PRO] on usb-0000:00:14.0-3.4/input0

We install NUT.

root@jeedom-stgreg2:~# apt-get install nut

In the /etc/nut/ups.conf you need to configure the right drivers for the UPS. In my case the EATON is handled by the standard NUT driver. You can get a compatibility list from the NUT-Server on https://networkupstools.org/stable-hcl.html
We make a new section for the UPS, as in this example. As my UPS is connected via usb, the port configuration can be set to auto.

Nota: don’t use spaces in section’s name (the one in brackets [ ]).

[Eaton_Ellipse_1200_Pro]
    driver = usbhid-ups
    port = auto
    pollonly
    desc = "Eaton Ellipse 1200 Pro"

Now we should make sure that the NUT-Server detects the UPS.

root@jeedom-stgreg2:~# upsdrvctl start
Network UPS Tools - UPS driver controller 2.7.4
Network UPS Tools - Generic HID driver 0.41 (2.7.4)
USB communication driver 0.33
Using subdriver: MGE HID 1.39

We explain NUT we are working on a standlone mode in /etc/nut/nut.conf

MODE=standalone

Now, we need to configure /etc/nut/upsd.conf with the server ip-address so we can connect to the NUT-Server from other clients. The MAXAGE line could be necessary to avoid NUT to consider the data returned by your UPs as staled if it doesn’t change for a while.

MAXAGE 30
LISTEN 127.0.0.1 3493
LISTEN 0.0.0.0 3493
LISTEN ::1 3493

Note: you could see that listening 127.0.0.1 is redundant with listening 0.0.0.0 (especially because later when we will check the daemon status it will tell it is NOT listening on 127.0.0.1) BUT if I remove the LISTEN 127.0.0.1 line, the daemon will complain about the /var/run/nut/upsd.pid file … So i keep this line until I understand what is happening.

Now we need to make a new user in the upsd.user file, let’s call him ‘master’, he got all the rights (because he is always right (!)).

[admin]
        password = YourAdminPassword
        upsmon master
        actions = SET
        instcmds = ALL

We configure /etc/nut/upsmon.conf where we need to add a MONITOR master and configure the notifications.

MONITOR Eaton_Ellipse_1200_Pro@localhost 1 admin YourAdminPassword master
MINSUPPLIES 1
POWERDOWNFLAG /etc/nut/killpower
#SHUTDOWNCMD "/sbin/shutdown -P +0"

HOSTSYNC 15
FINALDELAY 30
DEADTIME 15

NOTIFYCMD /sbin/upssched

NOTIFYMSG ONLINE    "UPS %s on line power"
NOTIFYMSG ONBATT    "UPS %s on battery"
NOTIFYMSG LOWBATT   "UPS %s battery is low"
NOTIFYMSG FSD       "UPS %s: forced shutdown in progress"
NOTIFYMSG COMMOK    "Communications with UPS %s established"
NOTIFYMSG COMMBAD   "Communications with UPS %s lost"
NOTIFYMSG SHUTDOWN  "UPS %s is going offline - System will now run on its own batteries !"
NOTIFYMSG REPLBATT  "UPS %s battery needs to be replaced"
NOTIFYMSG NOCOMM    "UPS %s is unavailable"
NOTIFYMSG NOPARENT  "upsmon parent process died - shutdown impossible"

NOTIFYFLAG ONLINE   SYSLOG+WALL+EXEC
NOTIFYFLAG ONBATT   SYSLOG+WALL+EXEC
NOTIFYFLAG LOWBATT  SYSLOG+WALL
NOTIFYFLAG FSD      SYSLOG+WALL+EXEC
NOTIFYFLAG COMMOK   SYSLOG+WALL+EXEC
NOTIFYFLAG COMMBAD  SYSLOG+WALL+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+WALL+EXEC
NOTIFYFLAG REPLBATT SYSLOG+WALL
NOTIFYFLAG NOCOMM   SYSLOG+WALL+EXEC
NOTIFYFLAG NOPARENT SYSLOG+WALL

RBWARNTIME 43200

NOCOMMWARNTIME 600

FINALDELAY 5

Note that on the first line, we here use the UPS name defined in ups.conf above, AND the user/password defined in upsd.user above too.

Also note our first specificity due to the fact that we use a laptop that we don’t want to be shutdowned automatically when the upsmon daemon will detect that the UPS is on low battery. That is because our laptop also has its own battery, which can maintain the system running for-theoricalli- a few more hours. Therefore, we commented out the SHUTDOWNCMD line ! In a classical system, this line would launch the shutdown command on the host running upsmon when UPS is detected on discharge + low battery.

We check/fix the permissions on various configuration files …

root@jeedom-stgreg2:~# chown root:nut /etc/nut/*
root@jeedom-stgreg2:~# chmod 640 /etc/nut/*

We configure the automatic start of NUT …

root@jeedom-stgreg2:~# systemctl enable nut-server
Synchronizing state of nut-server.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable nut-server

We start the service …

root@jeedom-stgreg2:~# service nut-server start

We check if it was launched.

root@jeedom-stgreg2:~# service nut-server status
● nut-server.service - Network UPS Tools - power devices information server
   Loaded: loaded (/lib/systemd/system/nut-server.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2022-09-03 08:15:46 CEST; 3min 6s ago
  Process: 3200 ExecStart=/sbin/upsd (code=exited, status=0/SUCCESS)
 Main PID: 3201 (upsd)
    Tasks: 1 (limit: 4915)
   Memory: 876.0K
   CGroup: /system.slice/nut-server.service
           └─3201 /lib/nut/upsd

sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: listening on 0.0.0.0 port 3493
sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: not listening on 127.0.0.1 port 3493
sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: listening on ::1 port 3493
sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: listening on 0.0.0.0 port 3493
sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: not listening on 127.0.0.1 port 3493
sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: Connected to UPS [Eaton_Ellipse_1200_Pro]: usbhid-ups-Eaton_Ellipse_1200_Pro
sept. 03 08:15:46 jeedom-stgreg2 upsd[3200]: Connected to UPS [Eaton_Ellipse_1200_Pro]: usbhid-ups-Eaton_Ellipse_1200_Pro
sept. 03 08:15:46 jeedom-stgreg2 upsd[3201]: Startup successful
sept. 03 08:15:46 jeedom-stgreg2 systemd[1]: Started Network UPS Tools - power devices information server.
sept. 03 08:15:50 jeedom-stgreg2 upsd[3201]: User admin@::1 logged into UPS [Eaton_Ellipse_1200_Pro]

We check which UPS are known by the system …

root@jeedom-stgreg2:~# upsc -l
Init SSL without certificate database
Eaton_Ellipse_1200_Pro

We check the whole UPS state …

root@jeedom-stgreg2:~# upsc Eaton_Ellipse_1200_Pro@localhost
Init SSL without certificate database
battery.charge: 100
battery.charge.low: 20
battery.runtime: 2682
battery.type: PbAc
device.mfr: EATON
device.model: Ellipse PRO 1200
device.serial: xxxxxxxxxxxxxxxx
device.type: ups
driver.flag.pollonly: enabled
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
driver.version.data: MGE HID 1.39
driver.version.internal: 0.41
input.frequency: 50.0
input.transfer.high: 285
input.transfer.low: 165
input.voltage: 237.0
input.voltage.extended: no
outlet.1.desc: PowerShare Outlet 1
outlet.1.id: 2
outlet.1.status: on
outlet.1.switchable: no
outlet.2.desc: PowerShare Outlet 2
outlet.2.id: 3
outlet.2.status: on
outlet.2.switchable: no
outlet.desc: Main Outlet
outlet.id: 1
outlet.switchable: no
output.frequency: 50.0
output.frequency.nominal: 50
output.voltage: 242.0
output.voltage.nominal: 230
ups.beeper.status: enabled
ups.delay.shutdown: 20
ups.delay.start: 30
ups.firmware: 01.18.0022
ups.load: 11
ups.mfr: EATON
ups.model: Ellipse PRO 1200
ups.power: 139
ups.power.nominal: 1200
ups.productid: ffff
ups.realpower: 0
ups.serial: xxxxxxxxxxxxxxx
ups.status: OL
ups.timer.shutdown: 0
ups.timer.start: 0
ups.vendorid: 0463

2. Install the Nut_free plugin in Jeedom

Now let’s integrate the UPS in Jeedom, by using the Nut_Free plugin on Jeedom’s Market.

Equipment creation

A little comment about this equipment: it should be possible to use autodetection BUT I choosed to use another name for this equipment, than the UPS name configured in NUT. Therefore, I choosed to not enable Auto detection, AND to specifiy the UPS name defined in /etc/nut/upsc.conf.

Saving the equipment will make the plugin check the UPS through the same upsc command we used manually to check our UPS status, and create the right commands in the Jeedom’s equipment.

After a few tweaking inside which commands we want to display, here is the widget seen on Jeedom’s main dashboard:

The UPS widget on Jeedom’s main dashboard

3. Specific tweaking as I use a laptop as Jeedom’s host

On this jeedom controller setup, running on a HP laptop, I had to disable a few things:

  • The SHUTDOWNCMD line in /etc/nut/upsmon.conf as we saw earlier
  • Suspend & hibernation
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

We also need to explain logind to avoid Suspend, Hibernate & closing lid events, by adding those lines to /etc/systemd/logind.conf and then restart the service.

HandleSuspendKey=ignore
HandleHibernateKey=ignore
HandleLidSwitch=ignore
HandleLidSwitchExternalPower=ignore
HandleLidSwitchDocked=ignore
systemctl restart systemd-logind
  • USB sleeping mode

Edit the /etc/default/grub file and change the GRUB_CMDLINE_LINUX_DEFAULT line to add the usbcore.autosuspend=-1 option

GRUB_CMDLINE_LINUX_DEFAULT="quiet usbcore.autosuspend=-1"

Save the file, then update grub:

update-grub

Reboot, and check the change (command below should return -1; before the change on my system it returned 2):

cat /sys/module/usbcore/parameters/autosuspend

4. UPS Monitoring & notification

We have to create a scenario (actually, three :)) to be notified in case a change related to the UPS state occurs. A simple way to detect the UPS state is to use the Nut_free “UPS Mode” command from our UPS equipment. Basically, it can have 2 interesting states: OL (On Line) and OB (On Battery). If it switches on battery, we can then use other commands to decide if we should properly switch off Jeedom (or do other things) before a real power failure, in case the UPS battery goes below a value.

In this first scenario, notice the trigger, and the fact that JEedom displays a second scenario linked to this one, called “UPs – Notif charge”. This second scenario is activated and launched only when we need to receive recurrent notifications with battery level.

What we do here is quite simple:

  • First (red step 0), if we enter this scenario, it is because the UPS state changed, so we send an alert. For all my alerts or things I want to be sent over my phones, email, etc., I created a scenario called “sNotification” which allows several things, but let’s say it basically sends an email, a short message and a notification on the Jeedom mobile app, and this notifications explains what changed.
  • Then (red step 1) we test if the UPS is back online. If yes:
    • We set a tracking variable to 1 (may be used elsewhere, but not right now)
    • We check if the notification scenario (UPS – Notif Charge) is enabled and if yes, as the UPS is back OL, we stop and disable it (we could maintain it a few more minutes to monitor that he is actually charging).
  • If no, then we check the UPS is not in an error state. It means, on battery, but we can still monitor it.
    • If OK, we check if the “UPS – Notif Charge” is not already active. If not, we enable and start it so that now we willreceive periodic updates about the UPS state & battery level.
    • If not OK (it means maybe the UPS is on battery, but more important, there is an error somewhere and we can not monitor it anymore for any reason), then we stop & disable the “UPS – Notif Charge” scenario so that we are not flooded by recurrent notifications until we fix the monitoring problem.

Let’s have a look at the second scenario. It has no specific trigger (scenario mode: programmed), as we will activate/deactivate it from the “UPS – check status” scenario, but it is scheduled to run every 5 minutes, when it will be activated which is not the case right now on the screen capture (notice the “Active” checkbox, not checked).

What this second scenario does is quite simple: it just use my notification sub-system (sNotification scenario) to alert me with an email, a text message on phone, and a notification on Jeedom’s mobile app. The alert will contain the UPS charge level and the estimated remaining time before it will shut down.

Now, with those 2 scenarios, and the UPS setting described, we have a fully working UPS and alerting system in case of a failure. But, remember, we are on a laptop. It means that when the UPS will stop, the laptop will also change its state, from “Online” to “On battery” … So, we also need to monitor the laptop’s state & battery, before we nicely shutdown our home automation center in case both the UPS and the laptop are out of batteries. Those are the two next scenarios.

5. Laptop Monitoring & notification

Here again, we will have several scenarios, not two as previously, but … three … And a Virtual component (we need the “Virtual” plugin to be installed, it’s free in Jeedom’s market).

  • One virtual component to represent the laptop battery state and centralize different informations about it, through “info” commands we will be able to use in other Jeedoms scenarios.
  • One scenario “Laptop battery – get data” to use a system command to get information about laptop’s battery, and update the virtual component every 5mn
  • One scenario “Laptop battery – Check status” to monitor the laptop status (online or on battery)
  • One last scenario “Laptop battery – Notif charge” to be activated ondemand by “Laptop battery – Check status” and send periodic notifications, but also, this time, to properly shutdown jeedom in case we approach the full (UPS + laptop) battery failure.

This virtual component is just a nicely way to embed and to use information in Jeedom, as all of those commands will be usable by other components, scenarios, etc. But we need to gather the data from the OS, by using a system command, in a scenario.

As you can see, this scenario is not triggered by any event (Scenario mode: Programmed), and it will execute every 5 minutes.

It’s not so complicated as it looks like. Basically, it executes the OS upower command and filters the information we want, then it puts each row from the output result in our virtual component commands, and depending on the status (fully-charged or not) it uses different rows of the result to feed data in the Virtual componant.

The OS command is upower -i $(upower -e | grep “BAT”) | grep “native|power|updated|state|energy:|energy-full:|percentage|warning|time” … What does it do ? Let’s test it in the system administration menu of Jeedom, which allows us to send OS commands and check the output.

We can see here that the result is a text with 7 lines, but in case the battery is not fully-charged, an 8th row would appear.

Then we have a bunch of commands as this one cmd::byString(‘#[Bureau][Batterie Laptop][ID]#’)->event(trim(explode(“:”,$output[0],2)[1]));

  • With the explode() instruction, it extracts the information we need from the first (#0) row (“native-path: BAT0”), information which is the second one (#1) after the “:” caracter.
  • Then it removes every unwanted spaces around the “BAT0” text with the trim() instruction.
  • And then it puts this text in the Virtual componant “ID” command by using the cmd::byString()->event method

We do that for every row of the output. There is one more thing: we analyze the value of the “state” data, so that we can feed the “Time to empty” and “Percentage” info commands in the Virtual component, accurately.

Once this scenario is activated, then every 5mn we will have up-to-date data about laptop’s battery in the Virtual Component. Now we can use our monitoring & alerting scenario, almost the sames as for the UPS.

Notice that this scenario is “Provoked” and the trigger is one of our Virtual component information: “State”.

What it does is fairly simple and almost as the one for the UPS we saw earlier:

  • If battery state is fully charged or charging, then it stops & disables the alerting “Laptop battery – Notif charge” scenario.
  • Else, it enables periodic notifications by enabling and starting the “Laptop battery – Notif charge” alerting scenario.

Here again, this is the same as for the UPS: this scenario is not activated by default (“Activate” checkbox not checked), it is Programmed to execute every 30 minutes once it is activated and started.

The alerting scenario is quite simple: it sens a mail + SMS + mobile app notification. But this time, as laptop’s battery is discharging because the UPS went down, we also shutdown Jeedom “properly” if the battery level goes below 30%.

6. Conclusion

In this article, we have seen how to connect, supervise, and monitor a UPS plugged into the laptop that hosts our Jeedom-based home automation hub.

The system we have set up allows us to:

  • Monitor and be alerted in case of a change in the status of the UPS, and then of the laptop battery, which will take over once the UPS shuts down in the event of a major power outage.
  • Properly shut down our home automation hub if the power outage lasts long enough to drain both the UPS that powers the laptop and the laptop’s own battery.

Thank you for your attention.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.