mirror of
https://github.com/opnsense/plugins.git
synced 2026-05-28 04:34:15 -04:00
sysutils/apcupsd: new plugin (#2799)
This is a plugin to configure the apcupsd service, it includes a widget for the dashboard Originally started by @Gibbon99 and @mrzaz (please mention their contribution too), repo here: https://github.com/Gibbon99/apcupsd and my fork: https://github.com/xbb/apcupsd where you can see the full changelog/commit list Forum thread: https://forum.opnsense.org/index.php?topic=21487.0
This commit is contained in:
parent
4723896915
commit
3bcbadaf1c
20 changed files with 1540 additions and 0 deletions
8
sysutils/apcupsd/Makefile
Normal file
8
sysutils/apcupsd/Makefile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
PLUGIN_NAME= apcupsd
|
||||
PLUGIN_DEVEL= yes
|
||||
PLUGIN_VERSION= 0.1
|
||||
PLUGIN_DEPENDS= apcupsd
|
||||
PLUGIN_COMMENT= APCUPSD - APC UPS daemon
|
||||
PLUGIN_MAINTAINER= xbb@xbblabs.com
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
||||
21
sysutils/apcupsd/pkg-descr
Normal file
21
sysutils/apcupsd/pkg-descr
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Apcupsd, short for APC UPS daemon, can be used for controlling all APC UPS models.
|
||||
It can monitor and log the current power and battery status, perform automatic
|
||||
shutdown, and can run in network mode in order to power down other hosts on a LAN.
|
||||
|
||||
This plugin allows you to configure an APC UPS for use with OPNsense using the
|
||||
Apcupsd project. The setup page allows you to set the most common options for
|
||||
connecting your UPS to your OPNsense router and a status page for the UPS
|
||||
status. It also includes support to act as an APC Netserver.
|
||||
|
||||
WWW: http://www.apcupsd.org/
|
||||
|
||||
Plugin Changelog
|
||||
================
|
||||
|
||||
1.0
|
||||
|
||||
Initial release
|
||||
|
||||
* Apcupsd service control and configuration
|
||||
* UPS status page
|
||||
* Dashboard widget
|
||||
77
sysutils/apcupsd/src/etc/inc/plugins.inc.d/apcupsd.inc
Normal file
77
sysutils/apcupsd/src/etc/inc/plugins.inc.d/apcupsd.inc
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2021 Dan Lundqvist
|
||||
* Copyright (C) 2021 David Berry
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* register service
|
||||
* @return array
|
||||
*/
|
||||
function apcupsd_services()
|
||||
{
|
||||
global $config;
|
||||
|
||||
$services = array();
|
||||
|
||||
if (
|
||||
isset($config['OPNsense']['apcupsd']['general']['Enabled']) &&
|
||||
$config['OPNsense']['apcupsd']['general']['Enabled'] == 1
|
||||
) {
|
||||
$services[] = array(
|
||||
'description' => gettext('APC UPS Daemon'),
|
||||
'configd' => array(
|
||||
'restart' => array('apcupsd restart'),
|
||||
'start' => array('apcupsd start'),
|
||||
'stop' => array('apcupsd stop'),
|
||||
),
|
||||
'name' => 'apcupsd',
|
||||
'pidfile' => '/var/run/apcupsd.pid'
|
||||
);
|
||||
}
|
||||
return $services;
|
||||
}
|
||||
|
||||
/**
|
||||
* sync configuration via xmlrpc
|
||||
* @return array
|
||||
*/
|
||||
function apcupsd_xmlrpc_sync()
|
||||
{
|
||||
$result = array();
|
||||
|
||||
$result[] = array(
|
||||
'description' => gettext('APC UPS Daemon'),
|
||||
'section' => 'OPNsense.apcupsd',
|
||||
'id' => 'apcupsd',
|
||||
'services' => ["apcupsd"],
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2021 Dan Lundqvist
|
||||
* Copyright (C) 2021 David Berry
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Apcupsd\Api;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Base\ApiMutableServiceControllerBase;
|
||||
|
||||
class ServiceController extends ApiMutableServiceControllerBase
|
||||
{
|
||||
protected static $internalServiceClass = '\OPNsense\Apcupsd\Apcupsd';
|
||||
protected static $internalServiceTemplate = 'OPNsense/Apcupsd';
|
||||
protected static $internalServiceEnabled = 'general.Enabled';
|
||||
protected static $internalServiceName = 'apcupsd';
|
||||
|
||||
private static $dateTimeFields = [
|
||||
'DATE',
|
||||
'STARTTIME',
|
||||
'MASTERUPD',
|
||||
'END APC',
|
||||
'XONBATT',
|
||||
'XOFFBATT',
|
||||
];
|
||||
|
||||
private static $dateFields = [
|
||||
'MANDATE',
|
||||
'BATDATE'
|
||||
];
|
||||
|
||||
public function getUpsStatusAction()
|
||||
{
|
||||
$result = $this->getUpsStatusOutput();
|
||||
$result['status'] = null;
|
||||
if (!$result['error']) {
|
||||
$result['status'] = $this->parseUpsStatus($result['output']);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function parseUpsStatus($statusOutput)
|
||||
{
|
||||
$status = array();
|
||||
foreach (explode("\n", $statusOutput) as $line) {
|
||||
$kv = array_map('trim', explode(':', $line, 2));
|
||||
$key = $kv[0];
|
||||
$value = isset($kv[1]) ? $kv[1] : null;
|
||||
$norm = $value;
|
||||
if (empty($key)) {
|
||||
continue;
|
||||
}
|
||||
if ($value === 'N/A') {
|
||||
$norm = null;
|
||||
} elseif (in_array($key, self::$dateTimeFields, true)) {
|
||||
$norm = $this->tryParseDateTime($value);
|
||||
} elseif (in_array($key, self::$dateFields, true)) {
|
||||
$norm = $this->tryParseDate($value);
|
||||
} elseif (preg_match('/^((?:[0-9]*[.])?[0-9]+)(?:\s+\w+)?$/i', $value, $matches)) {
|
||||
$norm = floatval($matches[1]);
|
||||
}
|
||||
$status[$key] = array(
|
||||
'value' => $value,
|
||||
'norm' => $norm
|
||||
);
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
private function tryParseDateTime($dateTimeString) {
|
||||
$formats = [
|
||||
'Y-m-d H:i:s P', // 2021-12-27 17:51:42 +0100
|
||||
'D M d H:i:s T Y' // Sat Sep 16 17:13:00 CEST 2000
|
||||
];
|
||||
foreach ($formats as $format) {
|
||||
$dt = DateTime::createFromFormat($format, $dateTimeString);
|
||||
if ($dt) {
|
||||
return $dt->format(DateTimeInterface::RFC3339);
|
||||
}
|
||||
}
|
||||
return $dateTimeString;
|
||||
}
|
||||
|
||||
private function tryParseDate($dateString) {
|
||||
$formats = [
|
||||
'Y-m-d', // 2021-12-27
|
||||
'm/d/y', // 12/27/21
|
||||
];
|
||||
foreach ($formats as $format) {
|
||||
$dt = DateTime::createFromFormat($format, $dateString);
|
||||
if ($dt) {
|
||||
return $dt->format('Y-m-d');
|
||||
}
|
||||
}
|
||||
return $dateString;
|
||||
}
|
||||
|
||||
private function getUpsStatusOutput()
|
||||
{
|
||||
$output = $error = null;
|
||||
|
||||
if ($this->isEnabled()) {
|
||||
$backend = new Backend();
|
||||
$output = trim($backend->configdRun('apcupsd upsstatus'));
|
||||
if (empty($output)) {
|
||||
$error = 'Error: empty output from apcaccess';
|
||||
}
|
||||
} else {
|
||||
$error = 'Error: apcupsd is disabled';
|
||||
}
|
||||
|
||||
return array(
|
||||
'error' => $error,
|
||||
'output' => $output
|
||||
);
|
||||
}
|
||||
|
||||
private function isEnabled()
|
||||
{
|
||||
return $this->getModel()->general->Enabled == '1';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2021 Dan Lundqvist
|
||||
* Copyright (C) 2021 David Berry
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Apcupsd\Api;
|
||||
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
|
||||
class SettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelClass = '\OPNsense\Apcupsd\Apcupsd';
|
||||
protected static $internalModelName = 'apcupsd';
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2021 Dan Lundqvist
|
||||
* Copyright (C) 2021 David Berry
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Apcupsd;
|
||||
|
||||
/**
|
||||
* Class IndexController
|
||||
* @package OPNsense\Apcupsd
|
||||
*/
|
||||
|
||||
class IndexController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
// pick the template to serve to our users.
|
||||
$this->view->pick('OPNsense/Apcupsd/index');
|
||||
$this->view->generalForm = $this->getForm("general");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2021 Dan Lundqvist
|
||||
* Copyright (C) 2021 David Berry
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Apcupsd;
|
||||
|
||||
/**
|
||||
* Class StatusController
|
||||
* @package OPNsense\Apcupsd
|
||||
*/
|
||||
|
||||
class StatusController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
// pick the template to serve to our use
|
||||
$this->view->pick('OPNsense/Apcupsd/status');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
<form>
|
||||
<field>
|
||||
<id>apcupsd.general.Enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable the APC UPS service.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.UPSName</id>
|
||||
<label>UPS Name</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
Specify a name for the UPS for log files, status reports etc.,
|
||||
between 1 and 99 characters in length.
|
||||
</help>
|
||||
<hint>Name of the UPS for log files, status reports etc.</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.UPSCable</id>
|
||||
<label>UPS Cable Type</label>
|
||||
<type>dropdown</type>
|
||||
<help>Select the type of cable connecting the UPS to the server.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.UPSType</id>
|
||||
<label>UPS Type</label>
|
||||
<type>dropdown</type>
|
||||
<help>Select the type of UPS in use. You may also need to specify the UPS device below.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.Device</id>
|
||||
<label>UPS Device</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
<![CDATA[
|
||||
Specify the device path for the selected type of UPS:<br>
|
||||
usb: leave blank for auto-detection<br>
|
||||
apcsmart or dumb: /dev/tty** (serial connection)<br>
|
||||
net: host:port (remote apcupsd network information server)<br>
|
||||
snmp: host:port:vendor:community<br>
|
||||
pcnet: ipaddr:username:passphrase (SmartSlot card)
|
||||
]]>
|
||||
</help>
|
||||
<hint>Path or address, leave blank for USB</hint>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.Polltime</id>
|
||||
<label>Polltime</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
<![CDATA[
|
||||
The rate in seconds that the daemon polls the UPS for status.
|
||||
This rate is automatically set to 1 second when the UPS goes on battery and reset to the specified value
|
||||
when the utility power returns.<br>
|
||||
A low setting will improve the daemon's responsiveness to certain events at the cost of higher CPU
|
||||
utilisation.<br>
|
||||
The default of 60 is appropriate for most situations.
|
||||
]]>
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.BatteryLevel</id>
|
||||
<label>Battery Level Shutdown (%)</label>
|
||||
<type>text</type>
|
||||
<help>Apcupsd will shutdown the system during a power failure when the remaining battery charge falls below the
|
||||
specified percentage. (Default is 5).</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.Minutes</id>
|
||||
<label>Battery Minutes Shutdown</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
Apcupsd will shutdown the system during a power failure when the remaining runtime on batteries as
|
||||
internally calculated by the UPS falls below the specified minutes. (Default is 3)
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.Timeout</id>
|
||||
<label>Battery Timeout Shutdown</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
<![CDATA[
|
||||
After a power failure occurs, apcupsd will shutdown the system after the specified number of seconds
|
||||
have expired.<br>
|
||||
For a Smart-UPS, this should normally be set to zero so that the shutdown time will be determined by the
|
||||
battery level or remaining runtime.<br>
|
||||
It is also useful for testing apcupsd because you can force a rapid shutdown by setting a small value
|
||||
(eg. 60) and turning off the power to the UPS.
|
||||
]]>
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.OnBatteryDelay</id>
|
||||
<label>OnBattery Event Delay</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
The number of seconds from when a power failure is detected until apcupsd reacts with an onbattery event.
|
||||
(Default is 6).
|
||||
</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.Annoy</id>
|
||||
<label>Annoy Time</label>
|
||||
<type>text</type>
|
||||
<help>Time in seconds between annoying users to signoff prior to system shutdown. 0 disables.</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.AnnoyDelay</id>
|
||||
<label>Annoy Delay</label>
|
||||
<type>text</type>
|
||||
<help>Initial delay after power failure before warning users to get off the system.</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.KillDelay</id>
|
||||
<label>Kill Delay</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
<![CDATA[
|
||||
Specifies the number of seconds for which apcupsd will continue running after a shutdown has been
|
||||
requested.<br>
|
||||
After the specified time, apcupsd will attempt to put the UPS into hibernate mode and kill the power to
|
||||
the computer.<br>
|
||||
This is for use on operating systems where apcupsd cannot regain control after a shutdown (eg. FreeBSD)
|
||||
to issue an apcupsd --killpower command.<br>
|
||||
Setting the delay to 0 disables it.
|
||||
]]>
|
||||
</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.Netserver</id>
|
||||
<label>Netserver</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enables the network information server which is required to obtain the current status information
|
||||
from the local or remote UPS.</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.NetserverAddress</id>
|
||||
<label>Netserver IP Address</label>
|
||||
<type>text</type>
|
||||
<hint>127.0.0.1 is the default</hint>
|
||||
<help>
|
||||
<![CDATA[
|
||||
IP address on which the net information server will listen for incoming connections.<br>
|
||||
Default address is 127.0.0.1 which means only local machine connections are accepted.
|
||||
]]>
|
||||
</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.NetserverPort</id>
|
||||
<label>Netserver Port</label>
|
||||
<type>text</type>
|
||||
<help>Network port used to send status and event data over the network.</help>
|
||||
<hint>Port 3551 is the default as registered with the IANA.</hint>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.UPSClass</id>
|
||||
<label>UPS Class</label>
|
||||
<type>dropdown</type>
|
||||
<help>Normally standalone unless you share an UPS using an APC ShareUPS card.</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.UPSMode</id>
|
||||
<label>UPS Mode</label>
|
||||
<type>dropdown</type>
|
||||
<help>Normally disable unless you share an UPS using an APC ShareUPS card.</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>apcupsd.general.NoLogon</id>
|
||||
<label>Nologon Mode</label>
|
||||
<type>dropdown</type>
|
||||
<help>The condition which determines when users are prevented from logging in during a power failure.</help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
</form>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<acl>
|
||||
<page-services-apcupsd>
|
||||
<name>Services: Apcupsd System Monitoring page</name>
|
||||
<patterns>
|
||||
<pattern>ui/apcupsd/*</pattern>
|
||||
<pattern>api/apcupsd/*</pattern>
|
||||
</patterns>
|
||||
</page-services-apcupsd>
|
||||
</acl>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2021 Dan Lundqvist
|
||||
* Copyright (C) 2021 David Berry
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\Apcupsd;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class Apcupsd extends BaseModel
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
<model>
|
||||
<mount>//OPNsense/apcupsd</mount>
|
||||
<version>0.0.2</version>
|
||||
<description>APC UPS configuration</description>
|
||||
<items>
|
||||
<general>
|
||||
<Enabled type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
</Enabled>
|
||||
<UPSName type="TextField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([0-9a-zA-Z._\- ]){1,99}$/</mask>
|
||||
<ValidationMessage>
|
||||
The name should be 1 to 99 characters and contain only alphanumeric characters,
|
||||
dashes, underscores, dot or space.
|
||||
</ValidationMessage>
|
||||
</UPSName>
|
||||
<UPSCable type="OptionField">
|
||||
<default>smart</default>
|
||||
<Required>Y</Required>
|
||||
<OptionValues>
|
||||
<option value="simple">Simple</option>
|
||||
<option value="smart">Smart</option>
|
||||
<option value="ether">Ether</option>
|
||||
<option value="usb">USB</option>
|
||||
<option value="940-0020B">940-0020B</option>
|
||||
<option value="940-0020C">940-0020C</option>
|
||||
<option value="940-0023A">940-0023A</option>
|
||||
<option value="940-0024B">940-0024B</option>
|
||||
<option value="940-0024C">940-0024C</option>
|
||||
<option value="940-0024G">940-0024G</option>
|
||||
<option value="940-0095A">940-0095A</option>
|
||||
<option value="940-0095B">940-0095B</option>
|
||||
<option value="940-0095C">940-0095C</option>
|
||||
<option value="940-0119A">940-0119A</option>
|
||||
<option value="940-0127A">940-0127A</option>
|
||||
<option value="940-0128A">940-0128A</option>
|
||||
<option value="940-0625A">940-0625A</option>
|
||||
<option value="940-1524C">940-1524C</option>
|
||||
<option value="MAM-04-02-2000">MAM-04-02-2000</option>
|
||||
</OptionValues>
|
||||
</UPSCable>
|
||||
<UPSType type="OptionField">
|
||||
<default>apcsmart</default>
|
||||
<Required>Y</Required>
|
||||
<OptionValues>
|
||||
<apcsmart>apcsmart</apcsmart>
|
||||
<usb>usb</usb>
|
||||
<net>net</net>
|
||||
<snmp>snmp</snmp>
|
||||
<netsnmp>netsnmp</netsnmp>
|
||||
<dumb>dumb</dumb>
|
||||
<pcnet>pcnet</pcnet>
|
||||
<modbus>modbus</modbus>
|
||||
</OptionValues>
|
||||
</UPSType>
|
||||
<Device type="TextField">
|
||||
<Required>N</Required>
|
||||
</Device>
|
||||
<Polltime type="IntegerField">
|
||||
<Required>Y</Required>
|
||||
<default>60</default>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>86400</MaximumValue>
|
||||
<ValidationMessage>Polltime must be between 1 and 86400.</ValidationMessage>
|
||||
</Polltime>
|
||||
<Netserver type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</Netserver>
|
||||
<NetserverAddress type="NetworkField">
|
||||
<default>127.0.0.1</default>
|
||||
<Required>Y</Required>
|
||||
</NetserverAddress>
|
||||
<NetserverPort type="PortField">
|
||||
<default>3551</default>
|
||||
<Required>Y</Required>
|
||||
</NetserverPort>
|
||||
<OnBatteryDelay type="IntegerField">
|
||||
<default>6</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>60</MaximumValue>
|
||||
<ValidationMessage>On battery delay must be between 1 and 60.</ValidationMessage>
|
||||
</OnBatteryDelay>
|
||||
<BatteryLevel type="IntegerField">
|
||||
<default>5</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>99</MaximumValue>
|
||||
<ValidationMessage>Battery level must be between 1 and 99 percent.</ValidationMessage>
|
||||
</BatteryLevel>
|
||||
<Minutes type="IntegerField">
|
||||
<default>3</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>1</MinimumValue>
|
||||
<MaximumValue>60</MaximumValue>
|
||||
<ValidationMessage>Remaining battery minutes must be between 1 and 60 minutes.</ValidationMessage>
|
||||
</Minutes>
|
||||
<Timeout type="IntegerField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>360</MaximumValue>
|
||||
<ValidationMessage>Timeout must be between 1 and 360 seconds.</ValidationMessage>
|
||||
</Timeout>
|
||||
<Annoy type="IntegerField">
|
||||
<default>300</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>10</MinimumValue>
|
||||
<MaximumValue>360</MaximumValue>
|
||||
<ValidationMessage>Annoy time must be between 10 and 360 seconds.</ValidationMessage>
|
||||
</Annoy>
|
||||
<AnnoyDelay type="IntegerField">
|
||||
<default>60</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>10</MinimumValue>
|
||||
<MaximumValue>360</MaximumValue>
|
||||
<ValidationMessage>Annoy delay time must be between 10 and 360 seconds.</ValidationMessage>
|
||||
</AnnoyDelay>
|
||||
<KillDelay type="IntegerField">
|
||||
<default>0</default>
|
||||
<Required>Y</Required>
|
||||
<MinimumValue>0</MinimumValue>
|
||||
<MaximumValue>360</MaximumValue>
|
||||
<ValidationMessage>Kill delay time must be between 0 and 360 seconds.</ValidationMessage>
|
||||
</KillDelay>
|
||||
<UPSClass type="OptionField">
|
||||
<default>standalone</default>
|
||||
<Required>Y</Required>
|
||||
<OptionValues>
|
||||
<standalone>standalone</standalone>
|
||||
<shareslave>shareslave</shareslave>
|
||||
<sharemaster>sharemaster</sharemaster>
|
||||
</OptionValues>
|
||||
</UPSClass>
|
||||
<UPSMode type="OptionField">
|
||||
<default>disable</default>
|
||||
<Required>Y</Required>
|
||||
<OptionValues>
|
||||
<disable>disable</disable>
|
||||
<share>share</share>
|
||||
</OptionValues>
|
||||
</UPSMode>
|
||||
<NoLogon type="OptionField">
|
||||
<default>disable</default>
|
||||
<Required>Y</Required>
|
||||
<OptionValues>
|
||||
<disable>disable</disable>
|
||||
<timeout>timeout</timeout>
|
||||
<percent>percent</percent>
|
||||
<minutes>minutes</minutes>
|
||||
<always>always</always>
|
||||
</OptionValues>
|
||||
</NoLogon>
|
||||
</general>
|
||||
</items>
|
||||
</model>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<menu>
|
||||
<Services>
|
||||
<Apcupsd cssClass="fa fa-battery-full fa-fw">
|
||||
<Settings url="/ui/apcupsd" />
|
||||
<Status url="/ui/apcupsd/status" />
|
||||
</Apcupsd>
|
||||
</Services>
|
||||
</menu>
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
{#
|
||||
# Copyright (C) 2021 Dan Lundqvist
|
||||
# Copyright (C) 2021 David Berry
|
||||
# Copyright (C) 2021 Nicola Pellegrini
|
||||
#
|
||||
# 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.
|
||||
#}
|
||||
<div class="col-md-12">
|
||||
{{ partial('layout_partials/base_form',['fields':generalForm,'id':'frm_GeneralSettings','apply_btn_id':'saveAct'])}}
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
var data_get_map = { 'frm_GeneralSettings': '/api/apcupsd/settings/get' };
|
||||
|
||||
mapDataToFormUI(data_get_map).done(function(data) {
|
||||
// place actions to run after load, for example update form styles.
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
|
||||
// Adds or updates the service control
|
||||
updateServiceControlUI('apcupsd');
|
||||
|
||||
var waitEnabled = function(callback, ntry) {
|
||||
ntry = ntry || 0;
|
||||
ajaxCall('/api/apcupsd/service/status', {}, function(data) {
|
||||
if ((data && data['status'] === 'running') || ntry > 5) {
|
||||
callback.call(null);
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
waitEnabled(callback, ntry++);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// link save button to API set action
|
||||
$('#saveAct').click(function(){
|
||||
saveFormToEndpoint('/api/apcupsd/settings/set', 'frm_GeneralSettings', function() {
|
||||
$('#frm_GeneralSettings_progress').addClass('fa fa-spinner fa-pulse');
|
||||
// action to run after successful save, for example reconfigure service.
|
||||
ajaxCall('/api/apcupsd/service/reconfigure', {}, function(data, status) {
|
||||
// action to run after reload
|
||||
$('#frm_GeneralSettings_progress').removeClass('fa fa-spinner fa-pulse');
|
||||
updateServiceControlUI('apcupsd');
|
||||
waitEnabled(function() {
|
||||
updateServiceControlUI('apcupsd');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
{#
|
||||
# Copyright (C) 2021 Dan Lundqvist
|
||||
# Copyright (C) 2021 David Berry
|
||||
# Copyright (C) 2021 Nicola Pellegrini
|
||||
#
|
||||
# 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.
|
||||
#}
|
||||
<pre id="apcupsd-status">No status</pre>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var refreshStatus = function() {
|
||||
ajaxCall('/api/apcupsd/service/getUpsStatus', {}, function(data, status) {
|
||||
if (status === 'success') {
|
||||
$('#apcupsd-status').text(data.error || data.output);
|
||||
setTimeout(refreshStatus, 5000);
|
||||
}
|
||||
});
|
||||
};
|
||||
refreshStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
[start]
|
||||
command:/usr/local/etc/rc.d/apcupsd start
|
||||
parameters:
|
||||
type:script
|
||||
message:starting apcupsd
|
||||
|
||||
[stop]
|
||||
command:/usr/local/etc/rc.d/apcupsd stop
|
||||
parameters:
|
||||
type:script
|
||||
message:stopping apcupsd
|
||||
|
||||
[restart]
|
||||
command:/usr/local/etc/rc.d/apcupsd restart
|
||||
parameters:
|
||||
type:script
|
||||
message:restarting apcupsd
|
||||
|
||||
[status]
|
||||
command:/usr/local/etc/rc.d/apcupsd status;exit 0
|
||||
parameters:
|
||||
type:script_output
|
||||
message:requesting apcupsd status
|
||||
|
||||
[upsstatus]
|
||||
command:/usr/local/sbin/apcaccess
|
||||
parameters:
|
||||
type:script_output
|
||||
message:requesting UPS Status
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
apcupsd:/etc/rc.conf.d/apcupsd
|
||||
apcupsd.conf:/usr/local/etc/apcupsd/apcupsd.conf
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{% if helpers.exists('OPNsense.apcupsd.general.Enabled') and OPNsense.apcupsd.general.Enabled == "1" %}
|
||||
apcupsd_enable="YES"
|
||||
{% else %}
|
||||
apcupsd_enable="NO"
|
||||
{% endif %}
|
||||
|
||||
# Hook to post start/restart commands waiting for the pid file for max 3 seconds
|
||||
# this prevents the status command to erroneously report the service as stopped
|
||||
# since apcupsd detaches before the pid file creation
|
||||
|
||||
start_postcmd="${name}_post_start_restart"
|
||||
restart_postcmd="${name}_post_start_restart"
|
||||
|
||||
apcupsd_post_start_restart()
|
||||
{
|
||||
if [ -n "$pidfile" ]; then
|
||||
i=0
|
||||
while [ ! -f "$pidfile" ] && [ "$i" -le 5 ]; do
|
||||
i=$(( i + 1 ))
|
||||
sleep 0.5
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
## apcupsd.conf v1.1 ##
|
||||
#
|
||||
# for apcupsd release 3.14.14 (31 May 2016) - freebsd
|
||||
|
||||
##############################################################
|
||||
#
|
||||
# This file is auto-generated - any changes made will be lost
|
||||
#
|
||||
#############################################################
|
||||
|
||||
# "apcupsd" POSIX config file
|
||||
|
||||
#
|
||||
# Note that the apcupsd daemon must be restarted in order for changes to
|
||||
# this configuration file to become active.
|
||||
#
|
||||
|
||||
#
|
||||
# ========= General configuration parameters ============
|
||||
#
|
||||
|
||||
# UPSNAME xxx
|
||||
# Use this to give your UPS a name in log files and such. This
|
||||
# is particulary useful if you have multiple UPSes. This does not
|
||||
# set the EEPROM. It should be 8 characters or less.
|
||||
{% if not helpers.empty('OPNsense.apcupsd.general.UPSName') %}
|
||||
UPSNAME {{ OPNsense.apcupsd.general.UPSName }}
|
||||
{% endif %}
|
||||
|
||||
# UPSCABLE <cable>
|
||||
# Defines the type of cable connecting the UPS to your computer.
|
||||
#
|
||||
# Possible generic choices for <cable> are:
|
||||
# simple, smart, ether, usb
|
||||
#
|
||||
# Or a specific cable model number may be used:
|
||||
# 940-0119A, 940-0127A, 940-0128A, 940-0020B,
|
||||
# 940-0020C, 940-0023A, 940-0024B, 940-0024C,
|
||||
# 940-1524C, 940-0024G, 940-0095A, 940-0095B,
|
||||
# 940-0095C, 940-0625A, M-04-02-2000
|
||||
#
|
||||
UPSCABLE {{ OPNsense.apcupsd.general.UPSCable }}
|
||||
|
||||
# To get apcupsd to work, in addition to defining the cable
|
||||
# above, you must also define a UPSTYPE, which corresponds to
|
||||
# the type of UPS you have (see the Description for more details).
|
||||
# You must also specify a DEVICE, sometimes referred to as a port.
|
||||
# For USB UPSes, please leave the DEVICE directive blank. For
|
||||
# other UPS types, you must specify an appropriate port or address.
|
||||
#
|
||||
# UPSTYPE DEVICE Description
|
||||
# apcsmart /dev/tty** Newer serial character device, appropriate for
|
||||
# SmartUPS models using a serial cable (not USB).
|
||||
#
|
||||
# usb <BLANK> Most new UPSes are USB. A blank DEVICE
|
||||
# setting enables autodetection, which is
|
||||
# the best choice for most installations.
|
||||
#
|
||||
# net hostname:port Network link to a master apcupsd through apcupsd's
|
||||
# Network Information Server. This is used if the
|
||||
# UPS powering your computer is connected to a
|
||||
# different computer for monitoring.
|
||||
#
|
||||
# snmp hostname:port:vendor:community
|
||||
# SNMP network link to an SNMP-enabled UPS device.
|
||||
# Hostname is the ip address or hostname of the UPS
|
||||
# on the network. Vendor can be can be "APC" or
|
||||
# "APC_NOTRAP". "APC_NOTRAP" will disable SNMP trap
|
||||
# catching; you usually want "APC". Port is usually
|
||||
# 161. Community is usually "private".
|
||||
#
|
||||
# netsnmp hostname:port:vendor:community
|
||||
# OBSOLETE
|
||||
# Same as SNMP above but requires use of the
|
||||
# net-snmp library. Unless you have a specific need
|
||||
# for this old driver, you should use 'snmp' instead.
|
||||
#
|
||||
# dumb /dev/tty** Old serial character device for use with
|
||||
# simple-signaling UPSes.
|
||||
#
|
||||
# pcnet ipaddr:username:passphrase:port
|
||||
# PowerChute Network Shutdown protocol which can be
|
||||
# used as an alternative to SNMP with the AP9617
|
||||
# family of smart slot cards. ipaddr is the IP
|
||||
# address of the UPS management card. username and
|
||||
# passphrase are the credentials for which the card
|
||||
# has been configured. port is the port number on
|
||||
# which to listen for messages from the UPS, normally
|
||||
# 3052. If this parameter is empty or missing, the
|
||||
# default of 3052 will be used.
|
||||
#
|
||||
# modbus /dev/tty** Serial device for use with newest SmartUPS models
|
||||
# supporting the MODBUS protocol.
|
||||
# modbus <BLANK> Leave the DEVICE setting blank for MODBUS over USB
|
||||
# or set to the serial number of the UPS to ensure
|
||||
# that apcupsd binds to that particular unit
|
||||
# (helpful if you have more than one USB UPS).
|
||||
#
|
||||
UPSTYPE {{ OPNsense.apcupsd.general.UPSType|default("apcsmart") }}
|
||||
DEVICE {{ OPNsense.apcupsd.general.Device }}
|
||||
|
||||
# POLLTIME <int>
|
||||
# Interval (in seconds) at which apcupsd polls the UPS for status. This
|
||||
# setting applies both to directly-attached UPSes (UPSTYPE apcsmart, usb,
|
||||
# dumb) and networked UPSes (UPSTYPE net, snmp). Lowering this setting
|
||||
# will improve apcupsd's responsiveness to certain events at the cost of
|
||||
# higher CPU utilization. The default of 60 is appropriate for most
|
||||
# situations.
|
||||
POLLTIME {{ OPNsense.apcupsd.general.Polltime|default("60") }}
|
||||
|
||||
# LOCKFILE <path to lockfile>
|
||||
# Path for device lock file. This is the directory into which the lock file
|
||||
# will be written. The directory must already exist; apcupsd will not create
|
||||
# it. The actual name of the lock file is computed from DEVICE.
|
||||
# Not used on Win32.
|
||||
LOCKFILE /var/spool/lock
|
||||
|
||||
# SCRIPTDIR <path to script directory>
|
||||
# Directory in which apccontrol and event scripts are located.
|
||||
SCRIPTDIR /usr/local/etc/apcupsd
|
||||
|
||||
# PWRFAILDIR <path to powerfail directory>
|
||||
# Directory in which to write the powerfail flag file. This file
|
||||
# is created when apcupsd initiates a system shutdown and is
|
||||
# checked in the OS halt scripts to determine if a killpower
|
||||
# (turning off UPS output power) is required.
|
||||
PWRFAILDIR /var/run
|
||||
|
||||
# NOLOGINDIR <path to nologin directory>
|
||||
# Directory in which to write the nologin file. The existence
|
||||
# of this flag file tells the OS to disallow new logins.
|
||||
NOLOGINDIR /var/run
|
||||
|
||||
|
||||
#
|
||||
# ======== Configuration parameters used during power failures ==========
|
||||
#
|
||||
|
||||
# The ONBATTERYDELAY is the time in seconds from when a power failure
|
||||
# is detected until we react to it with an onbattery event.
|
||||
#
|
||||
# This means that, apccontrol will be called with the powerout argument
|
||||
# immediately when a power failure is detected. However, the
|
||||
# onbattery argument is passed to apccontrol only after the
|
||||
# ONBATTERYDELAY time. If you don't want to be annoyed by short
|
||||
# powerfailures, make sure that apccontrol powerout does nothing
|
||||
# i.e. comment out the wall.
|
||||
ONBATTERYDELAY {{ OPNsense.apcupsd.general.OnBatteryDelay|default("6") }}
|
||||
|
||||
#
|
||||
# Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so
|
||||
# the first that occurs will cause the initation of a shutdown.
|
||||
#
|
||||
|
||||
# If during a power failure, the remaining battery percentage
|
||||
# (as reported by the UPS) is below or equal to BATTERYLEVEL,
|
||||
# apcupsd will initiate a system shutdown.
|
||||
BATTERYLEVEL {{ OPNsense.apcupsd.general.BatteryLevel|default("5") }}
|
||||
|
||||
# If during a power failure, the remaining runtime in minutes
|
||||
# (as calculated internally by the UPS) is below or equal to MINUTES,
|
||||
# apcupsd, will initiate a system shutdown.
|
||||
MINUTES {{ OPNsense.apcupsd.general.Minutes|default("3") }}
|
||||
|
||||
# If during a power failure, the UPS has run on batteries for TIMEOUT
|
||||
# many seconds or longer, apcupsd will initiate a system shutdown.
|
||||
# A value of 0 disables this timer.
|
||||
#
|
||||
# Note, if you have a Smart UPS, you will most likely want to disable
|
||||
# this timer by setting it to zero. That way, you UPS will continue
|
||||
# on batteries until either the % charge remaing drops to or below BATTERYLEVEL,
|
||||
# or the remaining battery runtime drops to or below MINUTES. Of course,
|
||||
# if you are testing, setting this to 60 causes a quick system shutdown
|
||||
# if you pull the power plug.
|
||||
# If you have an older dumb UPS, you will want to set this to less than
|
||||
# the time you know you can run on batteries.
|
||||
TIMEOUT {{ OPNsense.apcupsd.general.Timeout|default("0") }}
|
||||
|
||||
# Time in seconds between annoying users to signoff prior to
|
||||
# system shutdown. 0 disables.
|
||||
ANNOY {{ OPNsense.apcupsd.general.Annoy|default("300") }}
|
||||
|
||||
# Initial delay after power failure before warning users to get
|
||||
# off the system.
|
||||
ANNOYDELAY {{ OPNsense.apcupsd.general.AnnoyDelay|default("60") }}
|
||||
|
||||
# The condition which determines when users are prevented from
|
||||
# logging in during a power failure.
|
||||
# NOLOGON <string> [ disable | timeout | percent | minutes | always ]
|
||||
NOLOGON {{ OPNsense.apcupsd.general.NoLogon|default("disable") }}
|
||||
|
||||
# If KILLDELAY is non-zero, apcupsd will continue running after a
|
||||
# shutdown has been requested, and after the specified time in
|
||||
# seconds attempt to kill the power. This is for use on systems
|
||||
# where apcupsd cannot regain control after a shutdown.
|
||||
# KILLDELAY <seconds> 0 disables
|
||||
KILLDELAY {{ OPNsense.apcupsd.general.KillDelay|default("0") }}
|
||||
|
||||
#
|
||||
# ==== Configuration statements for Network Information Server ====
|
||||
#
|
||||
|
||||
# NETSERVER [ on | off ] on enables, off disables the network
|
||||
# information server. If netstatus is on, a network information
|
||||
# server process will be started for serving the STATUS and
|
||||
# EVENT data over the network (used by CGI programs).
|
||||
{% if helpers.exists('OPNsense.apcupsd.general.Netserver') and OPNsense.apcupsd.general.Netserver == "1" %}
|
||||
NETSERVER on
|
||||
{% else %}
|
||||
NETSERVER off
|
||||
{% endif %}
|
||||
|
||||
# NISIP <dotted notation ip address>
|
||||
# IP address on which NIS server will listen for incoming connections.
|
||||
# This is useful if your server is multi-homed (has more than one
|
||||
# network interface and IP address). Default value is 0.0.0.0 which
|
||||
# means any incoming request will be serviced. Alternatively, you can
|
||||
# configure this setting to any specific IP address of your server and
|
||||
# NIS will listen for connections only on that interface. Use the
|
||||
# loopback address (127.0.0.1) to accept connections only from the
|
||||
# local machine.
|
||||
NISIP {{ OPNsense.apcupsd.general.NetserverAddress|default("127.0.0.1") }}
|
||||
|
||||
# NISPORT <port> default is 3551 as registered with the IANA
|
||||
# port to use for sending STATUS and EVENTS data over the network.
|
||||
# It is not used unless NETSERVER is on. If you change this port,
|
||||
# you will need to change the corresponding value in the cgi directory
|
||||
# and rebuild the cgi programs.
|
||||
NISPORT {{ OPNsense.apcupsd.general.NetserverPort|default("3551") }}
|
||||
|
||||
# If you want the last few EVENTS to be available over the network
|
||||
# by the network information server, you must define an EVENTSFILE.
|
||||
EVENTSFILE /var/log/apcupsd.events
|
||||
|
||||
# EVENTSFILEMAX <kilobytes>
|
||||
# By default, the size of the EVENTSFILE will be not be allowed to exceed
|
||||
# 10 kilobytes. When the file grows beyond this limit, older EVENTS will
|
||||
# be removed from the beginning of the file (first in first out). The
|
||||
# parameter EVENTSFILEMAX can be set to a different kilobyte value, or set
|
||||
# to zero to allow the EVENTSFILE to grow without limit.
|
||||
EVENTSFILEMAX 10
|
||||
|
||||
#
|
||||
# ========== Configuration statements used if sharing =============
|
||||
# a UPS with more than one machine
|
||||
|
||||
#
|
||||
# Remaining items are for ShareUPS (APC expansion card) ONLY
|
||||
#
|
||||
|
||||
# UPSCLASS [ standalone | shareslave | sharemaster ]
|
||||
# Normally standalone unless you share an UPS using an APC ShareUPS
|
||||
# card.
|
||||
UPSCLASS {{ OPNsense.apcupsd.general.UPSClass|default("standalone") }}
|
||||
|
||||
# UPSMODE [ disable | share ]
|
||||
# Normally disable unless you share an UPS using an APC ShareUPS card.
|
||||
UPSMODE {{ OPNsense.apcupsd.general.UPSMode|default("disable") }}
|
||||
|
||||
#
|
||||
# ===== Configuration statements to control apcupsd system logging ========
|
||||
#
|
||||
|
||||
# Time interval in seconds between writing the STATUS file; 0 disables
|
||||
STATTIME 0
|
||||
|
||||
# Location of STATUS file (written to only if STATTIME is non-zero)
|
||||
STATFILE /var/log/apcupsd.status
|
||||
|
||||
# LOGSTATS [ on | off ] on enables, off disables
|
||||
# Note! This generates a lot of output, so if
|
||||
# you turn this on, be sure that the
|
||||
# file defined in syslog.conf for LOG_NOTICE is a named pipe.
|
||||
# You probably do not want this on.
|
||||
LOGSTATS off
|
||||
|
||||
# Time interval in seconds between writing the DATA records to
|
||||
# the log file. 0 disables.
|
||||
DATATIME 0
|
||||
|
||||
# FACILITY defines the logging facility (class) for logging to syslog.
|
||||
# If not specified, it defaults to "daemon". This is useful
|
||||
# if you want to separate the data logged by apcupsd from other
|
||||
# programs.
|
||||
#FACILITY DAEMON
|
||||
|
||||
#
|
||||
# ========== Configuration statements used in updating the UPS EPROM =========
|
||||
#
|
||||
|
||||
#
|
||||
# These statements are used only by apctest when choosing "Set EEPROM with conf
|
||||
# file values" from the EEPROM menu. THESE STATEMENTS HAVE NO EFFECT ON APCUPSD.
|
||||
#
|
||||
|
||||
# UPS name, max 8 characters
|
||||
#UPSNAME UPS_IDEN
|
||||
|
||||
# Battery date - 8 characters
|
||||
#BATTDATE mm/dd/yy
|
||||
|
||||
# Sensitivity to line voltage quality (H cause faster transfer to batteries)
|
||||
# SENSITIVITY H M L (default = H)
|
||||
#SENSITIVITY H
|
||||
|
||||
# UPS delay after power return (seconds)
|
||||
# WAKEUP 000 060 180 300 (default = 0)
|
||||
#WAKEUP 60
|
||||
|
||||
# UPS Grace period after request to power off (seconds)
|
||||
# SLEEP 020 180 300 600 (default = 20)
|
||||
#SLEEP 180
|
||||
|
||||
# Low line voltage causing transfer to batteries
|
||||
# The permitted values depend on your model as defined by last letter
|
||||
# of FIRMWARE or APCMODEL. Some representative values are:
|
||||
# D 106 103 100 097
|
||||
# M 177 172 168 182
|
||||
# A 092 090 088 086
|
||||
# I 208 204 200 196 (default = 0 => not valid)
|
||||
#LOTRANSFER 208
|
||||
|
||||
# High line voltage causing transfer to batteries
|
||||
# The permitted values depend on your model as defined by last letter
|
||||
# of FIRMWARE or APCMODEL. Some representative values are:
|
||||
# D 127 130 133 136
|
||||
# M 229 234 239 224
|
||||
# A 108 110 112 114
|
||||
# I 253 257 261 265 (default = 0 => not valid)
|
||||
#HITRANSFER 253
|
||||
|
||||
# Battery charge needed to restore power
|
||||
# RETURNCHARGE 00 15 50 90 (default = 15)
|
||||
#RETURNCHARGE 15
|
||||
|
||||
# Alarm delay
|
||||
# 0 = zero delay after pwr fail, T = power fail + 30 sec, L = low battery, N = never
|
||||
# BEEPSTATE 0 T L N (default = 0)
|
||||
#BEEPSTATE T
|
||||
|
||||
# Low battery warning delay in minutes
|
||||
# LOWBATT 02 05 07 10 (default = 02)
|
||||
#LOWBATT 2
|
||||
|
||||
# UPS Output voltage when running on batteries
|
||||
# The permitted values depend on your model as defined by last letter
|
||||
# of FIRMWARE or APCMODEL. Some representative values are:
|
||||
# D 115
|
||||
# M 208
|
||||
# A 100
|
||||
# I 230 240 220 225 (default = 0 => not valid)
|
||||
#OUTPUTVOLTS 230
|
||||
|
||||
# Self test interval in hours 336=2 weeks, 168=1 week, ON=at power on
|
||||
# SELFTEST 336 168 ON OFF (default = 336)
|
||||
#SELFTEST 336
|
||||
4
sysutils/apcupsd/src/www/widgets/include/apcupsd.inc
Normal file
4
sysutils/apcupsd/src/www/widgets/include/apcupsd.inc
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
$apcupsd_title = gettext('Apcupsd');
|
||||
$apcupsd_title_link = 'ui/apcupsd';
|
||||
219
sysutils/apcupsd/src/www/widgets/widgets/apcupsd.widget.php
Normal file
219
sysutils/apcupsd/src/www/widgets/widgets/apcupsd.widget.php
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2021 Nicola Pellegrini
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
require_once("guiconfig.inc");
|
||||
require_once("widgets/include/apcupsd.inc");
|
||||
|
||||
?>
|
||||
<table id="apcupsd-widget" class="table table-striped table-condensed">
|
||||
<colgroup>
|
||||
<col class="apcupsd-widget-label" />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody id="apcupsd-widget-tbody"></tbody>
|
||||
</table>
|
||||
<style>
|
||||
.apcupsd-widget-label {
|
||||
max-width: 20em;
|
||||
width: 30%;
|
||||
min-width: 10em;
|
||||
}
|
||||
|
||||
.apcupsd-widget-highlight {
|
||||
font-weight: bold
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$(document).ready(() => {
|
||||
const withMomentJs = moment && moment.version && typeof moment === 'function';
|
||||
|
||||
const $newCell = (content) => $('<td></td>').html(content);
|
||||
|
||||
const $newLabel = (text) => {
|
||||
return $('<td></td>').text(text);
|
||||
};
|
||||
|
||||
const $newRow = (content, label) => {
|
||||
return $('<tr></tr>').append(
|
||||
typeof label === 'string' ? $newLabel(label) : label,
|
||||
content
|
||||
);
|
||||
};
|
||||
|
||||
const $newProgressBar = (width, text) => {
|
||||
const $text = $('<span class="text-center"></span>').text(text).css({
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0
|
||||
});
|
||||
const $bar = $('<div class="progress-bar"></div>').css({
|
||||
width: width,
|
||||
zIndex: 0
|
||||
});
|
||||
return $('<div class="progress"></div>').append($bar, $text);
|
||||
};
|
||||
|
||||
const renderText = (data, label) => {
|
||||
const text = typeof data === 'string' ? data : data.value;
|
||||
return $newRow($('<td></td>').text(text), label);
|
||||
};
|
||||
|
||||
const renderDateString = (data, label, format, parseFormat) => {
|
||||
let value = typeof data === 'string' ? data : (data.norm || data.value);
|
||||
let text;
|
||||
if (withMomentJs) {
|
||||
const m = moment(value, parseFormat);
|
||||
if (m.isValid()) {
|
||||
m.locale(window.navigator.language);
|
||||
text = m.format(format);
|
||||
}
|
||||
}
|
||||
return renderText(text || value, label);
|
||||
};
|
||||
|
||||
const renderProgress = (data, label, progressText) => {
|
||||
const width = data.norm + '%';
|
||||
progressText = progressText || data.norm.toFixed(1) + ' %';
|
||||
const pb = $newProgressBar(width, progressText);
|
||||
return $newRow($newCell(pb), label);
|
||||
};
|
||||
|
||||
const renderLoad = (loadpct, nompower) => {
|
||||
let text = loadpct.norm.toFixed(1) + ' %';
|
||||
if (nompower) {
|
||||
text += ' ( ~ ' + Math.round(loadpct.norm * nompower.norm / 100) + ' W )';
|
||||
}
|
||||
return renderProgress(loadpct, 'Load', text);
|
||||
};
|
||||
|
||||
const renderHighlight = (text, label, okRegexp, errRegexp) => {
|
||||
const textEl = $('<span class="apcupsd-widget-highlight"></span>').text(text);
|
||||
if (okRegexp && okRegexp.exec(text)) {
|
||||
textEl.addClass('text-success');
|
||||
} else if (errRegexp && errRegexp.exec(text)) {
|
||||
textEl.addClass('text-danger');
|
||||
} else {
|
||||
textEl.addClass('text-warning');
|
||||
}
|
||||
return $newRow($('<td></td>').append(textEl), label);
|
||||
};
|
||||
|
||||
const selfTestText = {
|
||||
BT: 'Failed due to battery capacity (BT)',
|
||||
NG: 'Failed due to overload (NG)',
|
||||
NO: 'No results',
|
||||
};
|
||||
|
||||
const updateUi = (status) => {
|
||||
const rows = [];
|
||||
|
||||
if (status.MODEL) {
|
||||
rows.push(renderText(status.MODEL, 'Model'));
|
||||
}
|
||||
|
||||
if (status.STATUS) {
|
||||
rows.push(
|
||||
renderHighlight(
|
||||
status.STATUS.value,
|
||||
'Status',
|
||||
/ONLINE/,
|
||||
/ONBATT|LOWBATT|REPLACEBATT|NOBATT|SLAVEDOWN|COMMLOST/
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (status.SELFTEST) {
|
||||
const value = status.SELFTEST.value;
|
||||
const text = selfTestText[value] || value;
|
||||
if (value === 'NO') {
|
||||
rows.push(renderText(text, 'Self test'));
|
||||
} else {
|
||||
rows.push(renderHighlight(
|
||||
text,
|
||||
'Self test',
|
||||
/OK/,
|
||||
/BT|NG/
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (status.LINEV) {
|
||||
rows.push(renderText(status.LINEV, 'Line voltage'));
|
||||
}
|
||||
|
||||
if (status.LOADPCT) {
|
||||
rows.push(renderLoad(status.LOADPCT, status.NOMPOWER))
|
||||
}
|
||||
|
||||
if (status.BCHARGE) {
|
||||
rows.push(renderProgress(status.BCHARGE, 'Battery level'));
|
||||
}
|
||||
|
||||
if (status.TIMELEFT) {
|
||||
rows.push(renderText(status.TIMELEFT, 'Battery runtime'));
|
||||
}
|
||||
|
||||
if (status.BATTV) {
|
||||
rows.push(renderText(status.BATTV, 'Battery voltage'));
|
||||
}
|
||||
|
||||
if (status.BATTDATE) {
|
||||
rows.push(renderDateString(status.BATTDATE, 'Battery date', 'll', 'YYYY-MM-DD'));
|
||||
}
|
||||
|
||||
if (status.ITEMP) {
|
||||
rows.push(renderText(status.ITEMP, 'Temperature'));
|
||||
}
|
||||
|
||||
if (status.DATE) {
|
||||
rows.push(renderDateString(status.DATE, 'Status update', 'll LTS'));
|
||||
}
|
||||
|
||||
$('#apcupsd-widget-tbody').html(rows);
|
||||
};
|
||||
|
||||
const displayError = (message) => {
|
||||
const el = $('<tr></tr>').append($('<td class="text-center text-danger" colspan="2"></td>').text(message));
|
||||
$('#apcupsd-widget-tbody').html(el);
|
||||
};
|
||||
|
||||
const refreshStatus = () => {
|
||||
ajaxCall('/api/apcupsd/service/getUpsStatus', {}, function(data, status) {
|
||||
if (status === 'success' && !data.error) {
|
||||
updateUi(data.status);
|
||||
} else {
|
||||
displayError(data ? (data.message || data.error) : 'request error');
|
||||
}
|
||||
setTimeout(refreshStatus, 5000);
|
||||
});
|
||||
};
|
||||
|
||||
refreshStatus();
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in a new issue