2
0
mirror of https://github.com/xcat2/confluent.git synced 2025-04-15 09:39:37 +00:00

Begin adding sensors to Geist PDUs

This commit is contained in:
Jarrod Johnson 2023-03-17 14:37:03 -04:00
parent ff025989c6
commit 48696ef63d

View File

@ -16,7 +16,14 @@ import pyghmi.util.webclient as wc
import confluent.util as util
import confluent.messages as msg
import confluent.exceptions as exc
import eventlet.green.time as time
import eventlet.greenpool as greenpool
def simplify_name(name):
return name.lower().replace(' ', '_').replace('/', '-').replace(
'_-_', '-')
pdupool = greenpool.GreenPool(128)
class GeistClient(object):
def __init__(self, pdu, configmanager):
@ -102,17 +109,160 @@ class GeistClient(object):
{'cmd': 'control', 'token': self.token,
'data': {'action': state, 'delay': False}})
_sensors_by_node = {}
def read_sensors(element, node, configmanager):
category, name = element[-2:]
justnames = False
if len(element) == 3:
# just get names
category = name
justnames = True
if category in ('leds, fans', 'temperature'):
return
sn = _sensors_by_node.get(node, None)
if not sn or sn[1] < time.time():
gc = GeistClient(node, configmanager)
adev = gc.wc.grab_json_response('/api/dev')
_sensors_by_node[node] = (adev, time.time() + 1)
sn = _sensors_by_node.get(node, None)
if len(sn[0]['data']) != 1:
raise Exception('Unable to support multiple pdus at an ip')
print(repr(element))
readings = []
totalenergy = 0.0
totalrealpower = 0.0
totalapparentpower = 0.0
for pduid in sn[0]['data']:
datum = sn[0]['data'][pduid]
for ent in util.natural_sort(list(datum['entity'])):
outsensors = datum['entity'][ent]['measurement']
if ent.startswith('breaker'):
continue
if ent == 'total0':
continue
for outlet in util.natural_sort(list(datum['outlet'])):
outsensors = datum['outlet'][outlet]['measurement']
for measure in outsensors:
measurement = outsensors[measure]
if measurement['type'] == 'energy' and category != 'power':
myname = 'Outlet {0} Energy'.format(int(outlet) + 1)
if justnames:
yield msg.ChildCollection(simplify_name(myname))
continue
totalenergy += float(measurement['value'])
if name != 'all' and simplify_name(myname) != name:
continue
reading = {
'name': myname,
'value': float(measurement['value']),
'units': measurement['units'],
'type': 'Energy'
}
readings.append(reading)
if measurement['type'] == 'realPower' and category != 'energy':
myname = 'Outlet {0} Real Power'.format(int(outlet) + 1)
if justnames:
yield msg.ChildCollection(simplify_name(myname))
continue
totalrealpower += float(measurement['value'])
if name != 'all' and simplify_name(myname) != name:
continue
reading = {
'name': myname,
'value': float(measurement['value']),
'units': measurement['units'],
'type': 'Current'
}
readings.append(reading)
if measurement['type'] == 'voltage' and category == 'all':
myname = 'Outlet {0} Voltage'.format(int(outlet) + 1)
if justnames:
yield msg.ChildCollection(simplify_name(myname))
continue
if name != 'all' and simplify_name(myname) != name:
continue
reading = {
'name': myname,
'value': float(measurement['value']),
'units': measurement['units'],
'type': 'Voltage'
}
readings.append(reading)
if measurement['type'] == 'apparentPower' and category != 'energy':
myname = 'Outlet {0} Apparent Power'.format(int(outlet) + 1)
if justnames:
yield msg.ChildCollection(simplify_name(myname))
continue
totalapparentpower += float(measurement['value'])
if name != 'all' and simplify_name(myname) != name:
continue
reading = {
'name': myname,
'value': float(measurement['value']),
'units': measurement['units'],
'type': 'Current'
}
readings.append(reading)
myname = 'Overall Energy'
if justnames and category != 'power':
yield msg.ChildCollection(simplify_name(myname))
elif (name == 'all' or simplify_name(myname) == name) and category != 'power':
readings.append({
'name': 'Overall Energy',
'value': totalenergy,
'units': 'kWh',
'type': 'Energy',
})
myname = 'Overall Real Power'
if justnames and category != 'energy':
yield msg.ChildCollection(simplify_name(myname))
elif (name == 'all' or simplify_name(myname) == name) and category != 'energy':
readings.append({
'name': 'Overall Real Power',
'value': totalrealpower,
'units': 'W',
'type': 'Current',
})
myname = 'Overall Apparent Power'
if justnames and category != 'energy':
yield msg.ChildCollection(simplify_name(myname))
elif (name == 'all' or simplify_name(myname) == name) and category != 'energy':
readings.append({
'name': 'Overall Apparent Power',
'value': totalapparentpower,
'units': 'VA',
'type': 'Current',
})
if readings:
yield msg.SensorReadings(readings, name=node)
def get_outlet(node, configmanager):
gc = GeistClient(node, configmanager)
state = gc.get_outlet(element[-1])
return msg.PowerState(node=node, state=state)
def retrieve(nodes, element, configmanager, inputdata):
if 'outlets' not in element:
if 'outlets' in element:
gp = greenpool.GreenPile(pdupool)
for node in nodes:
gp.spawn(get_outlet, node, configmanager)
for res in gp:
yield res
return
elif element[0] == 'sensors':
gp = greenpool.GreenPile(pdupool)
for node in nodes:
gp.spawn(read_sensors, element, node, configmanager)
for rsp in gp:
for datum in rsp:
yield datum
return
else:
for node in nodes:
yield msg.ConfluentResourceUnavailable(node, 'Not implemented')
return
for node in nodes:
gc = GeistClient(node, configmanager)
state = gc.get_outlet(element[-1])
yield msg.PowerState(node=node, state=state)
def update(nodes, element, configmanager, inputdata):
if 'outlets' not in element:
yield msg.ConfluentResourceUnavailable(node, 'Not implemented')