APC UPS new plugin

Started by Droid999, February 13, 2021, 05:04:01 AM

Previous topic - Next topic
Thank you!  I didn't know or dare that we can just install packages with pkg and didn't know that we're supposed to install apcupsd when installing the plugin.

Now with apcupsd installed, the status info is there and it kinda seems to work out of the box :)  This is awesome :)


Any way in the next version we can get an alarm time delay field, or in my case all I want is a checkbox to disable the alarm, I  dont need/want it beeping.

Quote from: danderson on July 18, 2022, 07:28:29 PM

Any way in the next version we can get an alarm time delay field, or in my case all I want is a checkbox to disable the alarm, I  dont need/want it beeping.

I think you have to use the `apctest` command line tool for that, you'll need to stop the apcupsd service first.

If the UPS model is supported, it should show a menu with this option "View/Change alarm behavior"

hi there. just updated to the latest opnsense firmware and install apcupsd plugin.

opnsense connect to apc ups server on another device
seems to be working fine.

though not sure if this is normal or not, i did a test to auto shutdown.
it went through the shut down process then it stopped for me to manually reboot or shutdown

the operating system has halted
please press any key to reboot

is there anything i can do to fully shutdown the device?
thanks

Quote from: i1mran92 on August 06, 2022, 01:35:42 PM
though not sure if this is normal or not, i did a test to auto shutdown.
it went through the shut down process then it stopped for me to manually reboot or shutdown

the operating system has halted
please press any key to reboot

is there anything i can do to fully shutdown the device?
thanks

apcupsd actions (not the plugin) are controlled via the /usr/local/etc/apcupsd/apccontrol script.

Weirdly the FreeBSD version uses "shutdown -h now" instead of "shutdown -p now". I cannot change that in the plugin.

As a workaround, the apccontrol scripts permits overriding the default actions by creating another script named after the action (in this case "doshutdown") inside the /usr/local/etc/apcupsd/ directory.

For example you can create the script /usr/local/etc/apcupsd/doshutdown and make it executable otherwise it wont be executed by apccontrol.


#!/usr/bin/env sh

set -e

printf "Beginning Shutdown Sequence" | wall
/sbin/shutdown -p now "apcupsd initiated shutdown"

# 99 prevents apccontrol from executing the default doshutdown action
exit 99


Quote from: xbb on August 06, 2022, 03:35:27 PM
Quote from: i1mran92 on August 06, 2022, 01:35:42 PM
though not sure if this is normal or not, i did a test to auto shutdown.
it went through the shut down process then it stopped for me to manually reboot or shutdown

the operating system has halted
please press any key to reboot

is there anything i can do to fully shutdown the device?
thanks

apcupsd actions (not the plugin) are controlled via the /usr/local/etc/apcupsd/apccontrol script.

Weirdly the FreeBSD version uses "shutdown -h now" instead of "shutdown -p now". I cannot change that in the plugin.

As a workaround, the apccontrol scripts permits overriding the default actions by creating another script named after the action (in this case "doshutdown") inside the /usr/local/etc/apcupsd/ directory.

For example you can create the script /usr/local/etc/apcupsd/doshutdown and make it executable otherwise it wont be executed by apccontrol.


#!/usr/bin/env sh

set -e

printf "Beginning Shutdown Sequence" | wall
/sbin/shutdown -p now "apcupsd initiated shutdown"

# 99 prevents apccontrol from executing the default doshutdown action
exit 99



thank you. was able to make it shutdown fully with the script.
though i dont actually see "begining Shutdown Sequest" and "apcupsd initiated shutdown" when the shutdown procees was happening. not sure why?
but atleast it is fully shutting down now.


Quote from: i1mran92 on August 11, 2022, 11:36:25 AM
thank you. was able to make it shutdown fully with the script.
though i dont actually see "begining Shutdown Sequest" and "apcupsd initiated shutdown" when the shutdown procees was happening. not sure why?
but atleast it is fully shutting down now.

I think only logged in users can see the broadcast messages and I'm not sure if they are logged somewhere.

You can use the logger command if you want see a message in the system log.

For example:


logger -t apcupsd "some message"


man logger, for more details

Here is my experience with this plugin. Trying to connect a APC SRT1000RMXLA-NC

1: Direct connection via USB works.
2: Connecting via USB and setting up a master/slave setup did not seem to work at least not with the truenas-core APCUPSD-UPS client.
3: Connecting via smart card with ethernet also failed to function.

After trying every combination multiple times I gave up after 6 to 8 hours.

For me it works fine with NMC via SNMP. Also had no issues with setup...
i am not an expert... just trying to help...

This plugin was working fine for me. But today we lost power for some minutes, I came to check the status, and I find out that the plugin was not working (i didnt setup a monit alert, my fault)


2023-07-28T10:06:42   Error   apcupsd   apcupsd error shutdown completed   
2023-07-28T10:06:42   Error   apcupsd   Lock file data error:   
           please stop it and run this program again.   
           If apcupsd or apctest is already running,   
           Unable to create UPS lock file.   
2023-07-28T10:06:42   Error   apcupsd   apcupsd FATAL ERROR in apcupsd.c at line 221   
2023-07-28T10:06:42   Error   apcupsd   Lock file data error: �

The service is not running.

Also, I ran apctest as root, with the same result


2023-07-28 10:07:15 apctest 3.14.14 (31 May 2016) freebsd
Checking configuration ...
sharenet.type = ShareUPS
cable.type = USB Cable
mode.type = USB UPS Driver
apctest FATAL ERROR in apctest.c at line 313
Unable to create UPS lock file.
  If apcupsd or apctest is already running,
  please stop it and run this program again.
apctest error termination completed

root@incheon:~ # ps ax | grep apc
35558  0  S+    0:00.00 grep apc
root@incheon:~ #

mmn, maybe the path/permissions for the lock file changed or something?

Just installed an RJ45 --> USB cable between my APC CS 500 and my OPNSense. What am I supposed to choose in the settings for (current choice):

UPS cable type (Smart)
UPS type (apcsmart)

OPNsense 24.7.7-amd64 on APU2E4 using ZFS

Could anyone say something on the new widgets support (>24.7)?
I updated my instance a few days ago and the widget is gone. Turns out you need a new kind of widget now.
Does this plugin even get support still? The latest commit was 2 years ago.
Could we maybe all contribute a little?
I'm a web dev, I could make the UI work, though I have no idea of how to develop opnsense plugins.

Quote from: beneix on April 12, 2024, 06:21:29 PM
Just installed an RJ45 --> USB cable between my APC CS 500 and my OPNSense. What am I supposed to choose in the settings for (current choice):

UPS cable type (Smart)
UPS type (apcsmart)

I've got my Back-UPS ES 850G2, which also uses the RJ45 --> USB cable, set up with these settings:
UPS Cable Type = USB
UPS Type = usb

August 03, 2024, 01:50:26 AM #58 Last Edit: August 03, 2024, 10:01:47 AM by Droid999
Quote from: mickgotwings on August 02, 2024, 03:43:05 PM
Could anyone say something on the new widgets support (>24.7)?
I updated my instance a few days ago and the widget is gone. Turns out you need a new kind of widget now.
Does this plugin even get support still? The latest commit was 2 years ago.
Could we maybe all contribute a little?
I'm a web dev, I could make the UI work, though I have no idea of how to develop opnsense plugins.

I also just updated the other day.  I'll need to find out how to create a widget using the new UI, and then see if I can get it working.  No ETA :)

EDIT:

This is all thanks to Monviech - https://forum.opnsense.org/index.php?action=profile;u=26898

Ok - Initial version - no error checking or anything yet.  But - what fields do people want to see:



You can have any field that is normally output from apcaccess:

DATE   
HOSTNAME   
VERSION   
UPSNAME   
CABLE   
DRIVER   
UPSMODE   
STARTTIME   
MASTERUPD   
MASTER   
MODEL   
STATUS   
LINEV   
LOADPCT   
BCHARGE   
TIMELEFT   
MBATTCHG   
MINTIMEL   
MAXTIME   
OUTPUTV   
SENSE   
LOTRANS   
HITRANS   
RETPCT   
ITEMP   
BATTV   
LINEFREQ   
LASTXFER   
NUMXFERS   
TONBATT   
CUMONBATT   
XOFFBATT   
SELFTEST   
STATFLAG   
SERIALNO   
BATTDATE   
NOMOUTV   
NOMBATTV   
FIRMWARE   

August 04, 2024, 05:58:18 AM #59 Last Edit: August 05, 2024, 02:44:08 AM by Droid999
Here is a working widget for the APC UPS plugin.

Shows when the apc service is offline:


And when the service is working and talking to the UPS


You can try it out by creating a new file called Apcupsd.js on your Opnsense box at

/usr/local/opnsense/www/js/widgets

Paste this code into that new file

/*
* Copyright (C) 2024 David Berry.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

import BaseTableWidget from "./BaseTableWidget.js";

export default class Apcupsd extends BaseTableWidget {
    constructor() {
        super();
        this.dataError = false;
        this.data = null;
        this.statusColor = this.translations['t_statusColorWarning'];
        this.statusText = this.translations['t_statusTextWaiting'];
        this.statusName = this.translations['t_statusNameOffline'];
    }

    getGridOptions() {
        return {
            // trigger overflow-y:scroll after 650px height
            sizeToContent: 650,
        }
    }
   
    getMarkup() {
        let $container = $('<div></div>');
        let $apcupsdTable = this.createTable('apcupsd-table', {
            headerPosition: 'left',
        });
        $container.append($apcupsdTable);
       
        return $container;
    }

    async onWidgetTick() {

        this.dataError = false;
        this.statusColor = this.translations['t_statusColorSuccess'];
        this.statusText = this.translations['t_statusNameOnline'];
        this.statusName = this.translations['t_statusNameOnline'];

        this.data = await this.ajaxCall('/api/apcupsd/service/getUpsStatus');
        if (!this.data) {
            $(`.${this.id}-chart-container`).html(`
                <a href="/system_advanced_misc.php">${this.translations.t_unconfigured}</a>
            `).css('margin', '2em auto')
            this.dataError = true;
            this.statusColor = this.translations['t_statusColorDanger'];
            this.statusText = this.translations['t_statusTextError'];
            this.statusName = this.translations['t_statusNameOffline'];
        }

        if (this.data.status === null) {
            this.dataError = true;   
            this.statusColor = this.translations['t_statusColorDanger'];
            this.statusText = this.translations['t_statusTextOffline'];
            this.statusName = this.translations['t_statusNameOffline'];
        }
        else
        {
            this.statusName = this.data['status']['MODEL']['value'];
        }

        let rows = [];
       
        let upsStatusLight = `<div>
        <i class="fa fa-circle text-muted ${this.statusColor} ups-status-icon" style="font-size: 11px; cursor: pointer;"
            data-toggle="tooltip" title=${this.statusText}>
        </i>
            &nbsp;
        ${this.statusName}
        &nbsp;
        </div>`
       
        rows.push([upsStatusLight, '']);

        if (this.dataError) {
            rows.push([this.translations['t_unable_to_connect'], this.data['error']]);
         }
        else {
            rows.push([this.translations['t_mode'], this.data['status']['UPSMODE']['value']]);
            rows.push([this.translations['t_status'], this.data['status']['STATUS']['value']]);
            rows.push([this.translations['t_battery_runtime'], this.data['status']['TIMELEFT']['value']]);
            rows.push([this.translations['t_load'], this.data['status']['LOADPCT']['value']]);
            rows.push([this.translations['t_int_temp'], this.data['status']['ITEMP']['value']]);
        }
        super.updateTable('apcupsd-table', rows);
    }
}


You will also need to include the below XML block into a new file

/usr/local/opnsense/www/js/widgets/Metadata/Apcupsd.xml

Add this code to that file

   
<metadata>
   <Apcupsd>
        <filename>Apcupsd.js</filename>
        <endpoints>
            <endpoint>/api/Apcupsd/getUpsStatus</endpoint>
        </endpoints>
        <translations>
            <title>APC UPS Status</title>
            <t_unconfigured>APC UPS is not available or not configured.</t_unconfigured>
            <t_statusColorSuccess>text-success</t_statusColorSuccess>
            <t_statusColorWarning>text-warning</t_statusColorWarning>
            <t_statusColorDanger>text-danger</t_statusColorDanger>
            <t_statusTextWaiting>Waiting</t_statusTextWaiting>
            <t_statusTextOffline>Offline</t_statusTextOffline>
            <t_statusTextError>Data fetch error</t_statusTextError>
            <t_statusNameOffline>Offline</t_statusNameOffline>
            <t_statusNameOnline>Online</t_statusNameOnline>
            <t_mode>Mode</t_mode>
            <t_status>Status</t_status>
            <t_battery_runtime>Battery Runtime</t_battery_runtime>
            <t_load>Load</t_load>
            <t_int_temp>Internal Temperature</t_int_temp>
            <t_unable_to_connect>Unable to connect</t_unable_to_connect>
        </translations>
    </Apcupsd>
</metadata>


Then reload the dashboard and add the widget