diff --git a/RPIEasy.py b/RPIEasy.py index 9b7cbae..9226a78 100755 --- a/RPIEasy.py +++ b/RPIEasy.py @@ -162,6 +162,33 @@ def CPluginInit(): return 0 def NPluginInit(): + tarr = [] + filenames = glob.glob('_N*.py') + filenames.sort() + for fname in filenames: + tarr = [0,0,0] + tarr[0] = fname + with open(fname,"r") as fcont: + for line in fcont: + if "NPLUGIN_ID" in line: + tarr[1] = line[line.find("=")+1:].strip().replace('"',"") + if "NPLUGIN_NAME" in line: + tarr[2] = line[line.find("=")+1:].strip().replace('"',"") + break + tarr[0] = tarr[0].replace(".py","") + rpieGlobals.notifierselector.append(tarr) # create list for form select + + #print("Load controllers from file") + Settings.loadnotifiers() + + for x in range(0,len(Settings.Notifiers)): + if (Settings.Notifiers[x]) and type(Settings.Notifiers[x]) is not bool: # device exists + try: + if (Settings.Notifiers[x].enabled): # device enabled + Settings.Notifiers[x].plugin_init(None) # init plugin at startup + except: + pass + return 0 def RulesInit(): diff --git a/Settings.py b/Settings.py index 3f2d1ef..b83a25e 100644 --- a/Settings.py +++ b/Settings.py @@ -16,6 +16,7 @@ settingsfile = 'data/settings.json' tasksfile = 'data/tasks.json' controllersfile = 'data/controllers.json' +notifiersfile = 'data/notifiers.json' pinoutfile = 'data/pinout.json' netdevfile = 'data/netdev.json' netmanfile = 'data/netman.json' @@ -44,6 +45,7 @@ Tasks = [False] Controllers = [False] +Notifiers = [False] NetworkDevices = [] NetMan = None @@ -232,3 +234,26 @@ def saveadvsettings(): except: success = 0 return success + +def savenotifiers(): + global Notifiers, notifiersfile + success = 1 + try: + f = open(notifiersfile,'w') + settingjson = jsonpickle.encode(Notifiers,max_depth=2) # Restrict Jsonpickle to encode vars at first object + f.write(settingjson) + except: + success = 0 + return success + +def loadnotifiers(): + global Notifiers, notifiersfile + success = 1 + try: + f = open(notifiersfile) + settingjson = f.read() + Notifiers = jsonpickle.decode(settingjson) + except Exception as e: +# print("Critical Jsonpickle error:",str(e)) + success = 0 + return success diff --git a/_C002_DomoMQTT.py b/_C002_DomoMQTT.py index ab30267..a907b08 100644 --- a/_C002_DomoMQTT.py +++ b/_C002_DomoMQTT.py @@ -9,7 +9,6 @@ # # Copyright (C) 2018-2019 by Alexander Nagy - https://bitekmindenhol.blog.hu/ # -# missing! complete it based on c014! import controller import paho.mqtt.client as mqtt import json @@ -331,7 +330,7 @@ def senddata(self,idx,sensortype,value,userssi=-1,usebattery=-1,tasknum=-1,chang misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"MQTT idx error, sending failed.") else: misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"MQTT not connected, sending failed.") - if (time.time()-self.lastreconnect)>30: + if ((time.time()-self.lastreconnect)>30) and (self.connectinprogress==0): self.connect() def on_connect(self): diff --git a/_C013_ESPEasyP2P.py b/_C013_ESPEasyP2P.py index 883ca01..55e3f96 100644 --- a/_C013_ESPEasyP2P.py +++ b/_C013_ESPEasyP2P.py @@ -277,10 +277,16 @@ def encode(self,ptype): tbuf = [255,1] ta = self.infopacket["mac"].split(":") for m in ta: - tbuf.append(int(m,16)) + try: + tbuf.append(int(m,16)) + except: + tbuf.append(0) ta = self.infopacket["ip"].split(".") for m in ta: - tbuf.append(int(m)) + try: + tbuf.append(int(m)) + except: + tbuf.append(255) tbuf.append(int(self.infopacket["unitno"])) tbuf.append(int(self.infopacket["build"]%256)) tbuf.append(int(self.infopacket["build"]/256)) diff --git a/_N001_Email.py b/_N001_Email.py new file mode 100644 index 0000000..46e7a75 --- /dev/null +++ b/_N001_Email.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +############################################################################# +################### Email notifier plugin for RPIEasy ####################### +############################################################################# +# +# Copyright (C) 2019 by Alexander Nagy - https://bitekmindenhol.blog.hu/ +# +import nplugin +import webserver +import rpieGlobals +import misc +import smtplib +import commands + +class Plugin(nplugin.NPluginProto): + NPLUGIN_ID = 1 + NPLUGIN_NAME = "Email (SMTP)" + + def __init__(self,nindex): # general init + nplugin.NPluginProto.__init__(self,nindex) + self.server = "0.0.0.0" + self.port = 25 #25/465 + self.security = 0 # 0:plain,1:ssl + self.sender = "" + self.receiver = "" + self.login = "" + self.passw = "" + self.subject ="" # template + self.body="" # template + + def getuniquename(self): + return self.server + + def plugin_init(self,enableplugin=None): + nplugin.NPluginProto.plugin_init(self,enableplugin) + if self.passw=="*****": + self.passw="" + + def webform_load(self): # create html page for settings + webserver.addFormTextBox("Server","server",self.server,64) + options = ["Plain","SSL"] + optionvalues = [0,1] + webserver.addFormSelector("Protocol","security",len(options),options,optionvalues,None,self.security) + webserver.addFormNumericBox("Port","port",self.port,1,65535) + webserver.addFormTextBox("Sender","sender",self.sender,64) + webserver.addFormTextBox("Receiver","receiver",self.receiver,64) + webserver.addFormTextBox("SMTP login name","login",self.login,64) + webserver.addFormPasswordBox("STMP password","passw",self.passw,64) + webserver.addFormTextBox("Subject","subject",self.subject,64) + webserver.addHtml("Body:") + return True + + def webform_save(self,params): # process settings post reply + self.server = webserver.arg("server",params) + par1 = webserver.arg("security",params) + try: + par1=int(par1) + except: + par1=0 + if par1<0 or par1>1: + par1=0 + self.security=par1 + par1 = webserver.arg("port",params) + try: + par1=int(par1) + except: + par1=25 + if par1<1 or par1>65534: + par1=25 + self.port=par1 + self.sender = webserver.arg("sender",params) + self.receiver = webserver.arg("receiver",params) + self.login = webserver.arg("login",params) + passw = webserver.arg("passw",params) + if "**" not in passw: + self.passw = passw + self.subject = webserver.arg("subject",params) + self.body = webserver.arg("body",params) + return True + + def notify(self,pmsg=""): + if self.initialized==False or self.enabled==False: + return False + if self.sender=="" or self.receiver=="": + return False + message = ("From: %s\r\nTo: %s\r\n" % (self.sender,self.receiver)) + message += "Subject: "+self.mailparse(self.subject)+"\r\n\r\n" + if pmsg=="": + message += self.mailparse(self.body) + else: + message += self.mailparse(pmsg) + if self.server=="0.0.0.0" or self.server=="": + return False + try: + if self.security==0: + smtpObj = smtplib.SMTP(self.server, self.port) + elif self.security==1: + smtpObj = smtplib.SMTP_SSL(self.server, port=self.port, timeout=2) + if self.login!="" and self.passw!="": + smtpObj.login(self.login,self.passw) + smtpObj.sendmail(self.sender, self.receiver, message) + smtpObj.quit() + misc.addLog(rpieGlobals.LOG_LEVEL_INFO,"Mail sent!") + return True + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,str(e)) + return False + + def mailparse(self,ostr): + cl, st = commands.parseruleline(ostr) + if st=="CMD": + resstr=str(cl) + else: + resstr=str(ostr) + return resstr diff --git a/commands.py b/commands.py index 82890f5..91dfb76 100644 --- a/commands.py +++ b/commands.py @@ -67,7 +67,9 @@ def doExecuteCommand(cmdline,Parse=True): else: retval = cmdline cmdarr = retval.split(",") - if (" " in retval) and ("," in retval): # workaround for possible space instead comma problem + if (" " in retval) and not("," in retval): + cmdarr = retval.split(" ") + elif (" " in retval) and ("," in retval): # workaround for possible space instead comma problem fsp = retval.find(" ") fco = retval.find(",") if fsp1 and plugin>0: + sepp = ( len(cmdarr[0]) + len(cmdarr[1])+ 2 ) + data = cmdline[sepp:].replace("==","=") + commandfound = doExecuteNotification(plugin-1,data) + return commandfound + if commandfound==False: commandfound = doExecutePluginCommand(retval) if commandfound==False: @@ -379,6 +394,18 @@ def doExecutePluginCommand(cmdline): return retvalue return retvalue +def doExecuteNotification(num,cmdline): + retvalue = False + if len(Settings.Notifiers)<1: + return False + try: + num=int(num) + if num>=0 and num 0): # submitted + try: + if (Settings.Notifiers[nindex]): + Settings.Notifiers[nindex].enabled = enabled + Settings.Notifiers[nindex].webform_save(responsearr) + Settings.savenotifiers() + except: + pass + else: + try: + if (Settings.Notifiers[nindex]): + protocol = Settings.Notifiers[nindex].number + except: + pass + TXBuffer += "
" + if (nNotSet): # show all in table + TXBuffer += "
" + TXBuffer += "NrEnabledServiceID" + for x in range(rpieGlobals.NOTIFICATION_MAX): + TXBuffer += "
Edit" + TXBuffer += str(x + 1) + TXBuffer += "" + try: + if (Settings.Notifiers[x]): + addEnabled(Settings.Notifiers[x].enabled) + TXBuffer += "" + TXBuffer += str(Settings.Notifiers[x].getdevicename()) + TXBuffer += "" + TXBuffer += str(Settings.Notifiers[x].getuniquename()) + else: + TXBuffer += "" + except: + TXBuffer += "" + TXBuffer += "
" + else: # edit + TXBuffer += "
Notification Settings" + TXBuffer += "
Notification:" + addSelector_Head("protocol", True) + for x in range(len(rpieGlobals.notifierselector)): + addSelector_Item(rpieGlobals.notifierselector[x][2],int(rpieGlobals.notifierselector[x][1]),(str(protocol) == str(rpieGlobals.notifierselector[x][1])),False,"") + addSelector_Foot() + if (int(protocol) > 0): + createnewn = True + try: + if (Settings.Notifiers[nindex].getnpluginid()==int(protocol)): + createnewn = False + except: + pass + exceptstr = "" + if createnewn: + for y in range(len(rpieGlobals.notifierselector)): + if int(rpieGlobals.notifierselector[y][1]) == int(protocol): + if len(Settings.Notifiers)<=nindex: + while len(Settings.Notifiers)<=nindex: + Settings.Notifiers.append(False) + try: + m = __import__(rpieGlobals.notifierselector[y][0]) + except Exception as e: + Settings.Notifiers[nindex] = False + exceptstr += str(e) + m = False + if m: + try: + Settings.Notifiers[nindex] = m.Plugin(nindex) + except Exception as e: + Settings.Notifiers.append(m.Plugin(nindex)) + exceptstr += str(e) + break + if Settings.Notifiers[nindex] == False: + errormsg = "Importing failed, please double check dependencies! "+str(exceptstr) + TXBuffer += errormsg+"
" + sendHeadandTail("TmplStd",_TAIL) + return TXBuffer + else: + try: + Settings.Notifiers[nindex].plugin_init() # call plugin init + except: + pass + if nindex != '': + TXBuffer += "" + if int(protocol)>0: + addFormCheckBox("Enabled", "nenabled", Settings.Notifiers[nindex].enabled) + Settings.Notifiers[nindex].webform_load() + + addFormSeparator(2) + TXBuffer += "" + TXBuffer += "Close" + addSubmitButton() + if nindex != '': + addSubmitButton("Delete", "del") + TXBuffer += "" + sendHeadandTail("TmplStd",_TAIL); return TXBuffer