mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-21 18:41:03 +00:00
hue: plugin to monitor Philips Hue light status and temperature sensors
This commit is contained in:
parent
c633ff00ea
commit
4f22cec97c
1 changed files with 139 additions and 0 deletions
139
plugins/hue/hue
Executable file
139
plugins/hue/hue
Executable file
|
@ -0,0 +1,139 @@
|
||||||
|
#!/usr/bin/python3 -tt
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Munin plugin to read various data from Philips Hue.
|
||||||
|
|
||||||
|
Copyright 2019, Kim B. Heino, b@bbbs.net, Foobar Oy
|
||||||
|
License GPLv2+
|
||||||
|
|
||||||
|
Munin configuration:
|
||||||
|
|
||||||
|
[hue]
|
||||||
|
env.host hue-bridge-ip-or-hostname
|
||||||
|
env.auth auth-key
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unicodedata
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup(value):
|
||||||
|
"""Convert value to Munin key."""
|
||||||
|
ret = []
|
||||||
|
for char in value:
|
||||||
|
if 'a' <= char <= 'z' or '0' <= char <= '9':
|
||||||
|
ret.append(char)
|
||||||
|
elif 'A' <= char <= 'Z':
|
||||||
|
ret.append(char.lower())
|
||||||
|
else:
|
||||||
|
ret.append('_')
|
||||||
|
return ''.join(ret)
|
||||||
|
|
||||||
|
|
||||||
|
def sensor_name(data, sensor):
|
||||||
|
"""Find "parent" sensor for temperatue/light."""
|
||||||
|
uniqueid = sensor['uniqueid'][:27]
|
||||||
|
name = sensor['name']
|
||||||
|
for item in data['sensors'].values():
|
||||||
|
if item.get('uniqueid', '').startswith(uniqueid):
|
||||||
|
name = item['name']
|
||||||
|
break
|
||||||
|
|
||||||
|
# Convert ä to a and return it as utf8 string, py2/3 compatible way
|
||||||
|
name = unicodedata.normalize('NFKD', name)
|
||||||
|
return name.encode('ASCII', 'ignore').decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def print_temperatures(data, config, both):
|
||||||
|
"""Temperature sensors."""
|
||||||
|
if not any([sensor['type'] == 'ZLLTemperature'
|
||||||
|
for sensor in data['sensors'].values()]):
|
||||||
|
return
|
||||||
|
|
||||||
|
print('multigraph hue_temp')
|
||||||
|
if config:
|
||||||
|
print('graph_title Hue temperatures')
|
||||||
|
print('graph_vlabel Celsius')
|
||||||
|
print('graph_category sensors')
|
||||||
|
print('graph_args --base 1000')
|
||||||
|
print('graph_info Temperature sensor values.')
|
||||||
|
for sensor in data['sensors'].values():
|
||||||
|
if sensor['type'] != 'ZLLTemperature':
|
||||||
|
continue
|
||||||
|
label = cleanup(sensor['name'])
|
||||||
|
if config:
|
||||||
|
print('{}.label {}'.format(label, sensor_name(data, sensor)))
|
||||||
|
if not config or both:
|
||||||
|
value = sensor['state']['temperature'] / 100
|
||||||
|
print('{}.value {}'.format(label, value))
|
||||||
|
|
||||||
|
|
||||||
|
def print_light_levels(data, config, both):
|
||||||
|
"""Light level sensors."""
|
||||||
|
if not any([sensor['type'] == 'ZLLLightLevel'
|
||||||
|
for sensor in data['sensors'].values()]):
|
||||||
|
return
|
||||||
|
|
||||||
|
print('multigraph hue_light_level')
|
||||||
|
if config:
|
||||||
|
print('graph_title Hue light levels')
|
||||||
|
print('graph_vlabel Lux')
|
||||||
|
print('graph_category sensors')
|
||||||
|
print('graph_args --base 1000')
|
||||||
|
print('graph_scale no')
|
||||||
|
print('graph_info Light level sensor values.')
|
||||||
|
for sensor in data['sensors'].values():
|
||||||
|
if sensor['type'] != 'ZLLLightLevel':
|
||||||
|
continue
|
||||||
|
label = cleanup(sensor['name'])
|
||||||
|
if config:
|
||||||
|
print('{}.label {}'.format(label, sensor_name(data, sensor)))
|
||||||
|
if not config or both:
|
||||||
|
value = 10 ** ((sensor['state']['lightlevel'] - 1) / 10000)
|
||||||
|
print('{}.value {}'.format(label, value))
|
||||||
|
|
||||||
|
|
||||||
|
def print_lights(data, config, both):
|
||||||
|
"""Lights on/off."""
|
||||||
|
if not data['lights']:
|
||||||
|
return
|
||||||
|
|
||||||
|
print('multigraph hue_lights')
|
||||||
|
if config:
|
||||||
|
print('graph_title Hue lights on')
|
||||||
|
print('graph_vlabel Count')
|
||||||
|
print('graph_category sensors')
|
||||||
|
print('graph_args --base 1000 --lower-limit 0')
|
||||||
|
print('graph_info Number of turned on lights.')
|
||||||
|
count = 0
|
||||||
|
for light in data['lights'].values():
|
||||||
|
if light['state']['on']:
|
||||||
|
count += 1
|
||||||
|
if config:
|
||||||
|
print('lights.label Number of lights on')
|
||||||
|
if not config or both:
|
||||||
|
print('lights.value {}'.format(count))
|
||||||
|
|
||||||
|
|
||||||
|
def print_data(config):
|
||||||
|
"""Print config or values."""
|
||||||
|
# Get values
|
||||||
|
data = requests.get('http://{}/api/{}/'.format(
|
||||||
|
os.getenv('host'), os.getenv('auth')), timeout=50).json()
|
||||||
|
both = os.getenv('MUNIN_CAP_DIRTYCONFIG') == '1'
|
||||||
|
|
||||||
|
# Print config/values
|
||||||
|
print_temperatures(data, config, both)
|
||||||
|
print_light_levels(data, config, both)
|
||||||
|
print_lights(data, config, both)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == 'autoconf':
|
||||||
|
print('no')
|
||||||
|
elif len(sys.argv) > 1 and sys.argv[1] == 'config':
|
||||||
|
print_data(True)
|
||||||
|
else:
|
||||||
|
print_data(False)
|
Loading…
Add table
Add a link
Reference in a new issue