Development informations¶
How it UPS status found ?¶
The plugin just use the NUT server functions.
xPL messages¶
No xPL message handle, use only 0MQ
NUT driver compatibility¶
Plugin need driver device class for working with specific UPS.
Existing drivers device.¶
- Basic:
Must work with any NUT driver but handle only status and events
onmains
,onbattery
,batterylow
,comm_ok
andcomm_lost
If NUT server returnbattery.charge
driver can handle it.
- Blazer_USB:
Handle all basic and if available by NUT server:
battery.charge
calculat, input-output voltage status , input frequence status, output current status and temperature status
Add developement NUT driver compatibility¶
Plugin offer simple way to add new driver device.
File lib/nutdevices.py
contains a DeciveBase
python class who handle basic methodes.
You create a new class inherit this base class and overwriting some methodes to get NUT driver compatibility.
You just have to add new driver device class reference in createDevice
methode.
def createDevice(data):
""" Create a device depending of 'driver.name' given by data dict.
- Developer : add your python class derived from DeviceBase class."""
if data.has_key('driver.name') :
if data['driver.name'] == 'blazer_usb' : return Blazer_USB(data)
# Just add next line
elif data['driver.name'] == 'My_new_driver' : return My_New_Device(data)
else : return DeviceBase(data)
else : return DeviceBase(data)
Have a look to Network UPS Tools and get details informations on Driver section of User manual pages
Getting UPS variables available¶
- Use clients commands upsc of Network UPS Tools to get all variables available :
Example :
$ /bin/upsc MyUPS@localhost battery.voltage.nominal: 12.0 battery.voltage: 13.60 beeper.status: enabled device.type: ups driver.version.internal: 0.04 driver.name: blazer_usb driver.version: 2.6.3 driver.parameter.pollinterval: 2 driver.parameter.port: /dev/upsZ3 driver.parameter.productid: 5161 driver.parameter.vendorid: 0665 input.voltage.nominal: 230 input.voltage.fault: 240.2 input.voltage: 240.2 input.current.nominal: 2.0 input.frequency.nominal: 50 input.frequency: 49.9 output.voltage: 240.2 ups.type: offline ups.vendorid: 0665 ups.delay.shutdown: 30 ups.productid: 5161 ups.delay.start: 180 ups.status: OL
- Or using plugin tools
lib/nutsockclient.py
: Simple set your own parameters on __main__ section of
lib/nutsockclient.py
file.if __name__ == "__main__": # Set upsaddr, upsport and upsname depending on your config upsaddr = <UPS server IP > upsport = <UPS server port (generaly= 3493)> upsname = <UPS name>
Run python file ``lib/nutsockclient.py` and you get appropriate informations.
$ python nutsockclient.py +++ Internal NUTSocketClient created +++ Client connected to Z3_SERVER *** getNUTVersion {'cmd': 'VER', 'data': '2.6.3', 'error': ''} *** getNUTNetworkVersion {'cmd': 'NETVER', 'error': 'NUT version to old (2.6.3), NETVER function not handle, Update NUT lib >= 2.6.4'} *** getNUTHelp Commands: HELP VER GET LIST SET INSTCMD LOGIN LOGOUT USERNAME PASSWORD STARTTLS {} *** getUPSList {'cmd': 'LIST UPS', 'data': {'Z3_SERVER': 'Server Linux Internet'}, 'error': ''} *** getUPSVars {'cmd': 'LIST VAR', 'data': { 'input.voltage.nominal': '230', 'beeper.status': 'enabled', 'input.voltage.fault': '238.4', 'device.type': 'ups', 'driver.version.internal': '0.04', 'input.voltage': '238.4', 'ups.type': 'offline', 'input.current.nominal': '2.0', 'ups.vendorid': '0665', 'driver.name': 'blazer_usb', 'ups.delay.shutdown': '30', 'output.voltage': '238.4', 'ups.productid': '5161', 'ups.delay.start': '180', 'driver.version': '2.6.3', 'input.frequency.nominal': '50', 'battery.voltage.nominal': '12.0', 'driver.parameter.pollinterval': '2', 'driver.parameter.port': '/dev/upsZ3', 'battery.voltage': '13.60', 'driver.parameter.productid': '5161', 'ups.status': 'OL', 'input.frequency': '49.9', 'driver.parameter.vendorid': '0665' }, 'ups': 'Z3_SERVER', 'error': ''} *** getUPSRWVars {'cmd': 'LIST RW', 'data': {}, 'ups': 'Z3_SERVER', 'error': ''} *** getUPSCommands {'cmd': 'LIST CMD', 'data': [ 'beeper.toggle', 'load.off', 'load.on', 'shutdown.return', 'shutdown.stayoff', 'shutdown.stop', 'test.battery.start', 'test.battery.start.deep', 'test.battery.start.quick', 'test.battery.stop' ], 'ups': 'Z3_SERVER', 'error': ''} *** getUPSListClients {'cmd': 'LIST CLIENT', 'error': 'NUT version to old (2.6.3), LIST CLIENT function not handle, Update NUT lib >= 2.6.4'} *** getUPSVar {'var': 'ups.status', 'cmd': 'GET VAR', 'ups': 'Z3_SERVER', 'value': 'OL', 'error': ''} *** getUPSNumLogin {'cmd': 'NUMLOGINS', 'data': '2', 'error': ''} Terminated --- Internal NUTSocketClient deleted ---
- Or using plugin tools
Creating new Driver device class¶
- File lib/nutdevices.py contains a DeviceBase python class who handle basic methodes. You create a new class inherit this base class and overwriting some methodes to get acces of this new service or hardware.
You can insert your new class in the file or create a new with import DeviceBase :
class My_New_Device(DeviceBase): # simply new class declaration
def checkInputVoltage(self): # overwrite methodes class
......
Data format who must be return by methods¶
By calling source class method self.checkStatus()
you get DATA_TYPE_RETURN value.
DATA_TYPE_RETURN is a dict type with keys.
DATA_TYPE_RETURN :
{
'Modify' : True/False, # if the value change you must set to True.
'sensorsData' : { # Here all value who must transmit to domogik.
'status' : <'mains' or 'battery', or 'unknown'>
'event' : <All event define in UPS_Events>
}
}
- Use
self.handleUPS_Events
to set UPS_Events status at True/False. - This method :
Return a tuple with a boolean and a string for event key of DATA_TYPE_RETURN.
Manage an UPS_Event retention for some UPS Events values.
Ret others depending UPS_Events status of new event, Ex:
if input_voltage_low’ set to True
‘input_voltage_high’ must set to False
‘input_voltage_ok’ must set to False
How to use it :
.... retval = self.checkStatus() retVal['modify'], retVal['sensorsData']['event'] = self.handleUPS_Events(< an UPS_Events>, True/False)
Dependency UPS_Events status¶
UPS_Events are groups in dependencies status, if an item change others items must change.
Developer has no need to handle dependencies, self.handleUPS_Events
method handle them.
It’s just for information.
- On line status:
‘onmains’ => The UPS has begun operating on mains power
‘onbattery’ => The UPS has begun operating on battery power
- Battery status:
‘battlow’ => The UPS battery is low
‘battfull’ => The UPS battery is fully charged
- Battery test status:
‘bti’ => Battery test initiated
‘btp’ => Battery Test Passed
‘btf’ => Battery Test Failed
- UPS server communucation status:
‘comms_lost’ => The host has lost communication with the UPS
‘comms_ok’ => Communication with the UPS has been restored
- Input frequency status:
‘input_freq_error’ => The input frequency is out of range
‘input_freq_ok’ => The input frequency has returned from an error condition
- Input voltage status:
‘input_voltage_high’ => The input voltage is too high
‘input_voltage_low’ => The input voltage is too low
‘input_voltage_ok’ => The input voltage is OK following a previously “too low” or “too high” state
- Output voltage status:
‘output_voltage_high’ => The UPS output voltage is too high
‘output_voltage_low’ => THe UPS output voltage is too low
‘output_voltage_ok’ => The UPS output voltage has returned to normal following a “too high” or “too low” condition.
- Output status:
‘output_overload’ => The UPS output is in overload
‘output_ok’ => The UPS output has returned from overload
- Temperature status:
‘temp_high’ => The UPS temperature is too high
‘temp_ok’ => The UPS temperature has returned from an over-temperature condition
Overwrited methods¶
- getBatteryCharge:
You can overwrite this method but it is essential to call source method at first, Because if NUT server has is own level it’s probably the better.
Overwriting structure:
def getBatteryCharge(self): charge = DeviceBase.getBatteryCharge(self) if charge: return charge #.... Your new code in case of none 'battery.charge' handle by NUT server .... return charge # type float
- checkAll:
Check All UPS stuff and return they values in DATA_TYPE_RETURN list.
This method work with DeviceBase class, overwrite it only if new check method is necessary.
You can overwrite this method but it is essential to call source method at first.
Overwriting structure:
def checkAll(self): data = DeviceBase.checkAll(self) data = data.append(self.Your_New_Check()) ..... return data
- checkInputVoltage:
Source method do nothing and return None. You must overwrite it with status calculate to return event
input_voltage_low
,input_voltage_high
,input_voltage_ok
in format DATA_TYPE_RETURNOverwriting example:
def checkInputVoltage(self): # Check if key exist in UPS vars if self._vars.has_key('input.voltage.nominal') : # Calculat range voltage status high = self._vars['input.voltage.nominal'] * 1.06 low = self._vars['input.voltage.nominal'] * 0.94 else : # Return None to report not handling UPS event return None # Check if key exist in UPS vars if self._vars.has_key('input.voltage') : # Get UPS status in DATA_TYPE_RETURN format retVal = self.checkStatus() # Test voltage status if self._vars['input.voltage'] >= high : # Set 'Modify' and UPS_Events DATA_TYPE_RETURN format retVal['modify'], retVal['sensorsData']['event'] = self.handleUPS_Events('input_voltage_high', True) elif self._vars['input.voltage'] <= low : # Set 'Modify' and UPS_Events DATA_TYPE_RETURN format retVal['modify'], retVal['sensorsData']['event'] = self.handleUPS_Events('input_voltage_low', True) else : # Set 'Modify' and UPS_Events DATA_TYPE_RETURN format retVal['modify'], retVal['sensorsData']['event'] = self.handleUPS_Events('input_voltage_ok', True) return retVal # Return DATA_TYPE_RETURN format return None # Return None to report not handling UPS event
- checkInputFreq:
Source method do nothing and return None. You must overwrite it with status calculate to return event
input_freq_error
,input_freq_ok
in format DATA_TYPE_RETURNOverwriting structure : same principle than checkInputVoltage
- checkOutputVoltage:
Source method do nothing and return None. You must overwrite it with status calculate to return event
ouput_voltage_low
,output_voltage_high
,output_voltage_ok
in format DATA_TYPE_RETURNOverwriting structure : same principle than checkInputVoltage
- checkOutput:
Source method do nothing and return None. You must overwrite it with status calculate to return event
output_overload
,output_ok
in format DATA_TYPE_RETURNOverwriting structure : same principle than checkInputVoltage
- checkTemperature:
Source method do nothing and return None. You must overwrite it with status calculate to return event
temp_high
,temp_ok
in format DATA_TYPE_RETURNOverwriting structure : same principle than checkInputVoltage