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 gi.require_version('AppIndicator3', '0.1') from gi.repository import AppIndicator3 as AppIndicator from PIL import Image, ImageDraw, ImageFont import yaml mqttprefix = "devices" mqtthost = '192.168.67.1' oldtmpfile = '' oldalertcount = 0 menu = Gtk.Menu() fp = open("mqtt-systray.yaml") conf = yaml.safe_load(fp) fp.close() appindicator = AppIndicator.Indicator.new( 'mqttalert', '', AppIndicator.IndicatorCategory.APPLICATION_STATUS) def create_image(width, height, count): # Generate an image and draw a pattern image = Image.new('RGB', (width, height), 'white') dc = ImageDraw.Draw(image) color_circle = 'green' if count > 0: color_circle = 'red' #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 get_alert(devicea): for sensor in conf[devicea]['values'].keys(): if 'value' in conf[devicea]['values'][sensor] and (conf[devicea]['values'][sensor]['value'] > conf[devicea]['values'][sensor]['max'] or conf[devicea]['values'][sensor]['value'] < conf[devicea]['values'][sensor]['min']): return True return False def get_alert2(devicea, sensora): alert_text = '' if 'value' in conf[devicea]['values'][sensora]: if conf[devicea]['values'][sensora]['value'] > conf[devicea]['values'][sensora]['max']: alert_text = '!!HIGH!! ' elif conf[devicea]['values'][sensora]['value'] < conf[devicea]['values'][sensora]['min']: alert_text = '!!LOW!! ' return alert_text def alert_count(): count = 0 for device in conf: for sensor in conf[device]['values'].keys(): if get_alert2(device, sensor) != '': count = count + 1 return count def get_icon(): global oldtmpfile if oldtmpfile!='': os.remove(oldtmpfile) icon_path = tempfile.mktemp() oldtmpfile=icon_path with open(icon_path, 'wb') as f: create_image(64, 64, alert_count()).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: devname = conf[device1]['name'] conf[device1]['menuitem'] = Gtk.MenuItem(devname) submenu = Gtk.Menu() for sensor in conf[device1]['values'].keys(): conf[device1]['values'][sensor]['menuitem'] = Gtk.MenuItem(sensor) submenu.append(conf[device1]['values'][sensor]['menuitem']) conf[device1]['menuitem'].set_submenu(submenu) menu.append(conf[device1]['menuitem']) item_quit = Gtk.MenuItem('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]['values'][topicds[1]]['value'] = float(value) print("menu") #update_menu() alert_text = get_alert2(devices, topicds[1]) text='{}{}: {}'.format(alert_text, topicds[1], conf[devices]['values'][topicds[1]]['value']) conf[devices]['values'][topicds[1]]['menuitem'].set_label(text) #conf[devices]['values'][topicds[1]]['menuitem'].set_label("{}".format(conf[devices]['values'][topicds[1]]['value'])) devname = conf[devices]['name'] #print(get_alert(devices)) #if get_alert(devices): devname = "! " + devname #if get_alert(devices): devname = "!!ALERT!! " + devname #conf[devices]['menuitem'].set_label(devname) if oldalertcount != alert_count(): oldalertcount = alert_count() appindicator.set_icon(get_icon()) os.system("notify-send '{}' '{}'".format(conf[devices]['name'], text)) def subscribe_mqtt(mqttc): for device in conf: #print(conf[device]) for sensor in conf[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(get_icon()) appindicator.set_title('MQTT Alert') appindicator.set_status(AppIndicator.IndicatorStatus.ACTIVE) appindicator.set_menu(build_menu()) set_value("model1/1/1/temperature1C", "10.1") 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()