270 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
import gi
 | 
						|
import tempfile
 | 
						|
import time
 | 
						|
import os
 | 
						|
import signal
 | 
						|
 | 
						|
import paho.mqtt.client as mqtt
 | 
						|
 | 
						|
gi.require_version('Gtk', '3.0')
 | 
						|
from gi.repository import Gtk, Gdk
 | 
						|
 | 
						|
gi.require_version('AppIndicator3', '0.1')
 | 
						|
from gi.repository import AppIndicator3 as AppIndicator
 | 
						|
 | 
						|
from PIL import Image, ImageDraw, ImageFont
 | 
						|
import yaml
 | 
						|
 | 
						|
oldtmpfile = ''
 | 
						|
oldalertcount = 0
 | 
						|
menu = Gtk.Menu()
 | 
						|
 | 
						|
fp = open("mqtt-systray.yaml")
 | 
						|
conf = yaml.safe_load(fp)
 | 
						|
fp.close()
 | 
						|
 | 
						|
mqttprefix = conf['config']['mqtt_prefix']
 | 
						|
mqtthost = conf['config']['mqtt_host']
 | 
						|
 | 
						|
appindicator = AppIndicator.Indicator.new(
 | 
						|
            'mqttalert',
 | 
						|
            '',
 | 
						|
            AppIndicator.IndicatorCategory.APPLICATION_STATUS)
 | 
						|
 | 
						|
def create_image(width, height, count, color_circle):
 | 
						|
    # Generate an image and draw a pattern
 | 
						|
    image = Image.new('RGB', (width, height), 'white')
 | 
						|
    dc = ImageDraw.Draw(image)
 | 
						|
    #dc.circle((width // 2, height // 2), height // 2, fill=color2)
 | 
						|
    radius = height // 2
 | 
						|
    ellipse_xy = (0, 0, radius*2, radius*2)
 | 
						|
    dc.ellipse(ellipse_xy, color_circle)
 | 
						|
 | 
						|
    if count > 0:
 | 
						|
      #font = ImageFont.truetype("OpenSans-Regular.ttf", int(width))
 | 
						|
      font = ImageFont.load_default(float(width))
 | 
						|
      dc.text((12, -12),str(count),(0,0,0),font=font)
 | 
						|
 | 
						|
    return image
 | 
						|
 | 
						|
def quit():
 | 
						|
    os.remove(oldtmpfile)
 | 
						|
    Gtk.main_quit()
 | 
						|
 | 
						|
def signal_handler(sig, frame):
 | 
						|
    #print('You pressed Ctrl+C!')
 | 
						|
    quit()
 | 
						|
 | 
						|
def gtkquit(source):
 | 
						|
    quit()
 | 
						|
 | 
						|
def gtkdashboard(source):
 | 
						|
    Gtk.show_uri_on_window(None, conf['config']['dashboard_url'],int(Gdk.CURRENT_TIME))
 | 
						|
 | 
						|
def get_alert_text_warning(devicea, sensora):
 | 
						|
    alert_text = ''
 | 
						|
    if 'value' in conf['devices'][devicea]['values'][sensora]:
 | 
						|
        if 'max_warning' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] > conf['devices'][devicea]['values'][sensora]['max_warning']:
 | 
						|
            alert_text = '!!high!! '
 | 
						|
        elif 'min_warning' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] < conf['devices'][devicea]['values'][sensora]['min_warning']:
 | 
						|
            alert_text = '!!low!! '
 | 
						|
    return alert_text
 | 
						|
 | 
						|
def get_alert_text_critical(devicea, sensora):
 | 
						|
    alert_text = ''
 | 
						|
    if 'value' in conf['devices'][devicea]['values'][sensora]:
 | 
						|
        if 'max_critical' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] > conf['devices'][devicea]['values'][sensora]['max_critical']:
 | 
						|
            alert_text = '!!HIGH!! '
 | 
						|
        elif 'min_critical' in conf['devices'][devicea]['values'][sensora] and conf['devices'][devicea]['values'][sensora]['value'] < conf['devices'][devicea]['values'][sensora]['min_critical']:
 | 
						|
            alert_text = '!!LOW!! '
 | 
						|
    return alert_text
 | 
						|
 | 
						|
def get_alert_text(devicea, sensora):
 | 
						|
    alert_text = ''
 | 
						|
    if get_alert_text_critical(devicea, sensora) != '':
 | 
						|
        alert_text = get_alert_text_critical(devicea, sensora)
 | 
						|
    elif get_alert_text_warning(devicea, sensora) != '':
 | 
						|
        alert_text = get_alert_text_warning(devicea, sensora)
 | 
						|
    return alert_text
 | 
						|
 | 
						|
def alert_count_critical():
 | 
						|
    count = 0
 | 
						|
    for device in conf['devices']:
 | 
						|
        for sensor in conf['devices'][device]['values'].keys():
 | 
						|
            if get_alert_text_critical(device, sensor) != '': count = count + 1
 | 
						|
    return count
 | 
						|
 | 
						|
def alert_count_warning():
 | 
						|
    count = 0
 | 
						|
    for device in conf['devices']:
 | 
						|
        for sensor in conf['devices'][device]['values'].keys():
 | 
						|
            if get_alert_text_warning(device, sensor) != '': count = count + 1
 | 
						|
    return count
 | 
						|
 | 
						|
def alert_count():
 | 
						|
    count = 0
 | 
						|
    for device in conf['devices']:
 | 
						|
        for sensor in conf['devices'][device]['values'].keys():
 | 
						|
            if get_alert_text_critical(device, sensor) != '' or get_alert_text_warning(device, sensor) != '': count = count + 1
 | 
						|
    return count
 | 
						|
  
 | 
						|
def get_icon():
 | 
						|
    global oldtmpfile
 | 
						|
    if oldtmpfile!='': os.remove(oldtmpfile)
 | 
						|
    icon_path = tempfile.mktemp()
 | 
						|
    oldtmpfile=icon_path
 | 
						|
    color = 'green'
 | 
						|
    if alert_count_critical() > 0:
 | 
						|
        color = 'red'
 | 
						|
    elif alert_count_warning() > 0:
 | 
						|
        color = 'yellow'
 | 
						|
    
 | 
						|
    with open(icon_path, 'wb') as f:
 | 
						|
       create_image(64, 64, alert_count(), color).save(f, 'PNG')
 | 
						|
    return icon_path
 | 
						|
 | 
						|
#def menun2(deviceg):
 | 
						|
#  itemn2 = []
 | 
						|
#  submenu = Gtk.Menu()
 | 
						|
#  for sensor in conf[deviceg]['values'].keys():
 | 
						|
#    text=''
 | 
						|
#    if 'value' in conf[deviceg]['values'][sensor]:
 | 
						|
#      alert_text = get_alert2(deviceg, sensor)
 | 
						|
#      text='{}{}: {}'.format(alert_text, sensor, conf[deviceg]['values'][sensor]['value'])
 | 
						|
#    else:
 | 
						|
#      text=sensor
 | 
						|
#    submenuitem = Gtk.MenuItem(text)
 | 
						|
#    submenu.append(submenuitem)
 | 
						|
#  return submenu
 | 
						|
 | 
						|
def build_menu():
 | 
						|
   menu = Gtk.Menu()
 | 
						|
   for device1 in conf['devices']:
 | 
						|
      devname = conf['devices'][device1]['name']
 | 
						|
      conf['devices'][device1]['menuitem'] = Gtk.MenuItem(label=devname)
 | 
						|
      submenu = Gtk.Menu()
 | 
						|
      for sensor in conf['devices'][device1]['values'].keys():
 | 
						|
         conf['devices'][device1]['values'][sensor]['menuitem'] = Gtk.MenuItem(label=conf['devices'][device1]['values'][sensor]['name'])
 | 
						|
         submenu.append(conf['devices'][device1]['values'][sensor]['menuitem'])
 | 
						|
      conf['devices'][device1]['menuitem'].set_submenu(submenu)
 | 
						|
      menu.append(conf['devices'][device1]['menuitem'])
 | 
						|
 | 
						|
   item_dashboard = Gtk.MenuItem(label='Open Dashboard')
 | 
						|
   item_dashboard.connect('activate', gtkdashboard)
 | 
						|
   menu.append(item_dashboard)
 | 
						|
   item_quit = Gtk.MenuItem(label='Quit')
 | 
						|
   item_quit.connect('activate', gtkquit)
 | 
						|
   menu.append(item_quit)
 | 
						|
      
 | 
						|
   menu.show_all()
 | 
						|
   return menu
 | 
						|
      
 | 
						|
 | 
						|
#def build_menu_old():
 | 
						|
#    global menu
 | 
						|
#    global quitcount
 | 
						|
#    global item_quit
 | 
						|
#    #menu = Gtk.Menu()
 | 
						|
#    menu.connect('popup-menu', menu_show)
 | 
						|
#    #menu.connect('destroy', menu_hide)
 | 
						|
#    for device1 in conf:
 | 
						|
#      devname = conf[device1]['name']
 | 
						|
#      if get_alert(device1): devname = "!!ALERT!! " + devname
 | 
						|
#      menuitem = Gtk.MenuItem(devname)
 | 
						|
#      menuitem.set_submenu(menun2(device1))
 | 
						|
#      menu.append(menuitem)
 | 
						|
#      
 | 
						|
#    if quitcount == 0:
 | 
						|
#      item_quit = Gtk.MenuItem('Quit')
 | 
						|
#      item_quit.connect('select', menu_show)
 | 
						|
#      print('Quit0')
 | 
						|
#      menu.append(item_quit)
 | 
						|
#      quitcount = quitcount + 1
 | 
						|
#    else:
 | 
						|
#      #item_quit = Gtk.MenuItem('Quit')
 | 
						|
#      item_quit.set_label(str(quitcount))
 | 
						|
#      print('QuitX')
 | 
						|
#      #menu.append(item_quit)
 | 
						|
#      #item_quit.show()
 | 
						|
#      quitcount = quitcount + 1
 | 
						|
#
 | 
						|
#    print("Alert Count: {}".format(alert_count()))
 | 
						|
#
 | 
						|
#    menu.show_all()
 | 
						|
#    #menu.show_now()
 | 
						|
#    return menu
 | 
						|
 | 
						|
def update_menu():
 | 
						|
    appindicator.set_menu(build_menu())
 | 
						|
 | 
						|
def set_value(topic, value):
 | 
						|
    global oldalertcount
 | 
						|
    topicds = topic.rsplit("/", 1)
 | 
						|
    devices=topicds[0]
 | 
						|
    devices = devices.removeprefix(mqttprefix+'/')
 | 
						|
    conf['devices'][devices]['values'][topicds[1]]['value'] = float(value)
 | 
						|
    #update_menu()
 | 
						|
  
 | 
						|
    alert_text = get_alert_text(devices, topicds[1])
 | 
						|
    text='{}{}: {} {}'.format(alert_text, conf['devices'][devices]['values'][topicds[1]]['name'], conf['devices'][devices]['values'][topicds[1]]['value'], conf['devices'][devices]['values'][topicds[1]]['unit'])
 | 
						|
    conf['devices'][devices]['values'][topicds[1]]['menuitem'].set_label(text)
 | 
						|
    #conf['devices'][devices]['values'][topicds[1]]['menuitem'].set_label("{}".format(conf['devices'][devices]['values'][topicds[1]]['value']))
 | 
						|
    devname = conf['devices'][devices]['name']
 | 
						|
    #print(get_alert(devices))
 | 
						|
    #if get_alert(devices): devname = "! " + devname
 | 
						|
    #if get_alert(devices): devname = "!!ALERT!! " + devname
 | 
						|
    #conf['devices'][devices]['menuitem'].set_label(devname) 
 | 
						|
  
 | 
						|
    if oldalertcount != (alert_count()):
 | 
						|
      oldalertcount = alert_count()
 | 
						|
      appindicator.set_icon_full(get_icon(), "mqtt-icon")
 | 
						|
      os.system("notify-send '{}' '{}'".format(conf['devices'][devices]['name'], text))
 | 
						|
 | 
						|
def subscribe_mqtt(mqttc):
 | 
						|
    for device in conf['devices']:
 | 
						|
      #print(conf[device])
 | 
						|
      for sensor in conf['devices'][device]['values'].keys():
 | 
						|
        #print(sensor)
 | 
						|
        tosubscribe = "{}/{}/{}".format(mqttprefix, device, sensor)
 | 
						|
        mqttc.subscribe(tosubscribe, 0)
 | 
						|
        print(tosubscribe)
 | 
						|
 | 
						|
def on_connect(mqttc, obj, flags, rc):
 | 
						|
    print("rc: " + str(rc))
 | 
						|
#def on_subscribe(mqttc, obj, mid, granted_qos):
 | 
						|
#    print("Subscribed: " + str(mid) + " " + str(granted_qos))
 | 
						|
def on_message(client, userdata, msg):
 | 
						|
    print(msg.topic+" "+str(msg.payload))
 | 
						|
    set_value(msg.topic, msg.payload)
 | 
						|
 | 
						|
 | 
						|
signal.signal(signal.SIGINT, signal_handler)
 | 
						|
 | 
						|
appindicator.set_icon_full(get_icon(), "mqtt-icon")
 | 
						|
appindicator.set_title('MQTT Alert')
 | 
						|
appindicator.set_status(AppIndicator.IndicatorStatus.ACTIVE)
 | 
						|
appindicator.set_menu(build_menu())
 | 
						|
 | 
						|
set_value("model1/1/1/temperature1C", "25.1")
 | 
						|
#set_value("model2/2/2/humidity2", "75")
 | 
						|
#print(conf)
 | 
						|
 | 
						|
mqttc = mqtt.Client()
 | 
						|
mqttc.on_message = on_message
 | 
						|
mqttc.on_connect = on_connect
 | 
						|
#mqttc.on_subscribe = on_subscribe
 | 
						|
connected = False
 | 
						|
while connected == False:
 | 
						|
    try:
 | 
						|
        mqttc.connect(mqtthost, 1883, 60)
 | 
						|
    except:
 | 
						|
        time.sleep(5)
 | 
						|
        connected=False
 | 
						|
    else:
 | 
						|
        connected=True
 | 
						|
mqttc.loop_start()
 | 
						|
 | 
						|
subscribe_mqtt(mqttc)
 | 
						|
 | 
						|
Gtk.main()
 |