From b0ca9497a4b213ce7ee0de1cea7d033fd4d35039 Mon Sep 17 00:00:00 2001 From: enesbcs Date: Thu, 17 Jan 2019 19:15:03 +0100 Subject: [PATCH] Adding experimental PME support --- Settings.py | 11 +- _P011_PME.py | 286 ++++++++++++++++++++++++++++++++++++++++++++++++++ gpios.py | 2 +- plugindeps.py | 14 ++- webserver.py | 10 +- 5 files changed, 313 insertions(+), 10 deletions(-) create mode 100644 _P011_PME.py diff --git a/Settings.py b/Settings.py index 1f4c767..3f2d1ef 100644 --- a/Settings.py +++ b/Settings.py @@ -84,10 +84,13 @@ def callback_from_controllers(controllerindex,idx,values,taskname="",valuename=" def get_i2c_pins(): # get list of enabled i2c pin numbers global Pinout gplist = [] - for p in range(len(Pinout)): - if int(Pinout[p]["altfunc"])==1: - if "I2C" in Pinout[p]["name"][1]: - gplist.append(Pinout[p]["name"][0]+"/"+Pinout[p]["name"][1]) + try: + for p in range(len(Pinout)): + if int(Pinout[p]["altfunc"])==1: + if "I2C" in Pinout[p]["name"][1]: + gplist.append(Pinout[p]["name"][0]+"/"+Pinout[p]["name"][1]) + except: + pass return gplist def savesettings(): diff --git a/_P011_PME.py b/_P011_PME.py new file mode 100644 index 0000000..4969ce2 --- /dev/null +++ b/_P011_PME.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python3 +############################################################################# +################### Pro Mini Extender plugin for RPIEasy #################### +############################################################################# +# +# Copyright (C) 2018-2019 by Alexander Nagy - https://bitekmindenhol.blog.hu/ +# +import plugin +import webserver +import rpieGlobals +import rpieTime +import misc +import gpios +import fcntl +import time + +class Plugin(plugin.PluginProto): + PLUGIN_ID = 11 + PLUGIN_NAME = "Extra IO - ProMini Extender (TESTING)" + PLUGIN_VALUENAME1 = "Value" + + def __init__(self,taskindex): # general init + plugin.PluginProto.__init__(self,taskindex) + self.dtype = rpieGlobals.DEVICE_TYPE_I2C + self.vtype = rpieGlobals.SENSOR_TYPE_SINGLE + self.ports = 0 + self.readinprogress = 0 + self.valuecount = 1 + self.senddataoption = True + self.timeroption = True + self.timeroptional = False + self.formulaoption = True + self.pme = None + + def plugin_init(self,enableplugin=None): + plugin.PluginProto.plugin_init(self,enableplugin) + self.uservar[0] = 0 + self.initialized = False + if self.enabled: + i2cport = -1 + try: + for i in range(0,2): + if gpios.HWPorts.is_i2c_usable(i) and gpios.HWPorts.is_i2c_enabled(i): + i2cport = i + break + except: + i2cport = -1 + if i2cport>-1: + try: + dport = int(self.taskdevicepluginconfig[0]) + except: + dport = 0 + if dport == 0: + dport = 0x3f + self.pme = None + try: + self.pme = PME(i2cport,dport) + except Exception as e: + self.pme = None + if self.pme: + try: + self.initialized = self.pme.init + except: + self.pme = None + if self.pme is None: + self.initialized = False + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"PME can not be initialized! "+str(e)) + + def webform_load(self): # create html page for settings + choice1 = self.taskdevicepluginconfig[0] + options = ["0x3f","0x4f","0x5f","0x6f","0x7f"] + optionvalues = [0x3f,0x4f,0x5f,0x6f,0x7f] + webserver.addFormSelector("I2C address","plugin_011_addr",len(optionvalues),options,optionvalues,None,int(choice1)) + webserver.addFormNote("Enable I2C bus first, than search for the used address! 0x7F address is non-standard, so it may not work!") + choice2 = self.taskdevicepluginconfig[1] + options = ["Digital","Analog"] + optionvalues = [0,1] + webserver.addFormSelector("Type","plugin_011_ptype",2,options,optionvalues,None,int(choice2)) + webserver.addFormNumericBox("Port number","plugin_011_pnum",self.taskdevicepluginconfig[2],0,30) + webserver.addFormNote("Digital ports 0-13, Analog ports 0-7 (20-27)") + return True + + def webform_save(self,params): # process settings post reply + par = webserver.arg("plugin_011_addr",params) + if par == "": + par = 0 + self.taskdevicepluginconfig[0] = int(par) + par = webserver.arg("plugin_011_ptype",params) + try: + self.taskdevicepluginconfig[1] = int(par) + except: + self.taskdevicepluginconfig[1] = 0 + par = webserver.arg("plugin_011_pnum",params) + try: + self.taskdevicepluginconfig[2] = int(par) + except: + self.taskdevicepluginconfig[2] = 0 + return True + + def plugin_read(self): # deal with data processing at specified time interval + result = False + if self.initialized and self.enabled: + try: + pt = int(self.taskdevicepluginconfig[1]) + pn = int(self.taskdevicepluginconfig[2]) + result = self.pme.read(pt,pn) + self.set_value(1,result,True) + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,str(e)) + self._lastdataservetime = rpieTime.millis() + result = True + return result + + def plugin_write(self,cmd): # handle incoming commands + res = False + cmdarr = cmd.split(",") + cmdarr[0] = cmdarr[0].strip().lower() # implement scanning of devices to sync taskvalues?? + if cmdarr[0] == "extgpio": + pin = -1 + val = -1 + try: + pin = int(cmdarr[1].strip()) + val = int(cmdarr[2].strip()) + except: + pin = -1 + if pin>-1 and val in [0,1]: + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"EXTGPIO"+str(pin)+" set to "+str(val)) + try: + self.pme.write(0,pin,val) + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"EXTGPIO"+str(pin)+": "+str(e)) + res = True + elif cmdarr[0]=="extpwm": + pin = -1 + prop = -1 + try: + pin = int(cmdarr[1].strip()) + prop = int(cmdarr[2].strip()) + except: + pin = -1 + prop = -1 + if pin>-1 and prop>-1: + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"EXTPWM"+str(pin)+": "+str(prop)) + try: + self.pme.write(1,pin,prop) + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"EXTPWM"+str(pin)+": "+str(e)) + res = True + elif cmdarr[0]=="extpulse": + pin = -1 + val = -1 + try: + pin = int(cmdarr[1].strip()) + val = int(cmdarr[2].strip()) + except: + pin = -1 + dur = 100 + try: + dur = float(cmdarr[3].strip()) + except: + dur = 100 + if pin>-1 and val in [0,1]: + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"EXTGPIO"+str(pin)+": Pulse started") + try: + self.pme.write(0,pin,val) + s = (dur/1000) + time.sleep(s) + self.pme.write(0,pin,(1-val)) + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"EXTGPIO"+str(pin)+": "+str(e)) + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"EXTGPIO"+str(pin)+": Pulse ended") + res = True + elif cmdarr[0]=="extlongpulse": + pin = -1 + val = -1 + try: + pin = int(cmdarr[1].strip()) + val = int(cmdarr[2].strip()) + except: + pin = -1 + dur = 2 + try: + dur = float(cmdarr[3].strip()) + except: + dur = 2 + if pin>-1 and val in [0,1]: + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"EXTGPIO"+str(pin)+": LongPulse started") + try: + self.pme.write(0,pin,val) + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"EXTGPIO"+str(pin)+": "+str(e)) + rarr = [pin,(1-val)] + rpieTime.addsystemtimer(dur,self.p011_timercb,rarr) + res = True + return res + + def p011_timercb(self,stimerid,ioarray): + if ioarray[0] > -1: + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"EXTGPIO"+str(ioarray[0])+": LongPulse ended") + try: + self.pme.write(0,ioarray[0],ioarray[1]) + except Exception as e: + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"EXTGPIO"+str(ioarray[0])+": "+str(e)) + +class PME: + + I2C_SLAVE = 0x0703 + I2C_SLAVE_FORCE = 0x0706 + CMD_DIGITAL_WRITE = 1 + CMD_DIGITAL_READ = 2 + CMD_ANALOG_WRITE = 3 + CMD_ANALOG_READ = 4 + + def __init__(self, device_number=1,i2ca=0x3f): + self.i2caddress = int(i2ca) + try: + self.i2cr = open("/dev/i2c-"+str(device_number),"rb",buffering=0) + self.i2cw = open("/dev/i2c-"+str(device_number),"wb",buffering=0) + fcntl.ioctl(self.i2cr, self.I2C_SLAVE,self.i2caddress) + fcntl.ioctl(self.i2cw, self.I2C_SLAVE,self.i2caddress) + self.init = True + except: + self.init = False + + def read(self,ptype,pnum): + if self.init: + try: + pnum = int(pnum) & 0xFF + ptype = int(ptype) + except: + return False + if ptype == 1 and pnum>19: + pnum -= 20 + carr = [] + if ptype==0: + carr.append(self.CMD_DIGITAL_READ) # 0 or 1 + else: + carr.append(self.CMD_ANALOG_READ) # 0-1023 + carr.append(pnum) + carr.append(0) + carr.append(0) + barr = bytes(carr) +# print("send data",barr) + self.i2cw.write(barr) # send read data command + time.sleep(0.01) # wait some + data = self.i2cr.read(4) # read data +# print("rec data",data) + if len(data)>0: + if ptype==0: + return data[0] + elif len(data)>1: + return (data[1] << 8 | data[0]) # 0-1023 + return 0 + + def write(self,ptype,pnum,value): + # ptype 0=digital,1=analog + if self.init: + try: + pnum = int(pnum) & 0xFF + ptype = int(ptype) + except: + return False + if ptype == 1 and pnum>19: + pnum -= 20 + carr = [] + if ptype==0: + carr.append(self.CMD_DIGITAL_WRITE) # 0 or 1 + else: + carr.append(self.CMD_ANALOG_WRITE) # 0-255 + carr.append(pnum) + carr.append((value & 0xff)) + carr.append((value >> 8)) +# print("send data",carr) + self.i2cw.write(bytes(carr)) # send write data command + return True + + def close(self): + if self.init: + self.i2cr.close() + self.i2cw.close() + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() diff --git a/gpios.py b/gpios.py index 1219a1c..fa702e6 100644 --- a/gpios.py +++ b/gpios.py @@ -379,7 +379,7 @@ {"name": "BMP280 Temp/Barometric;BME180 Temp/Barometric/Humidity", "addr": [0x76,0x77]}, {"name": "ProMini Extender (standard)", - "addr": [0x3F]}, + "addr": [0x3F,0x4F,0x5F,0x6F]}, {"name": "ProMini Extender (non-standard)", "addr": [0x7F]} diff --git a/plugindeps.py b/plugindeps.py index 0d1e566..18be7c2 100644 --- a/plugindeps.py +++ b/plugindeps.py @@ -71,7 +71,13 @@ "installed":-1}, {"name":"linux-kernel", "testcmd" : "if misc.getosname(0)!='linux':\n raise Exception('Linux kernel needed')", -"installed":-1} +"installed":-1}, +{"name":"pyserial", + "apt": ["python3-pip"], + "pip": ["pyserial"], + "testcmd": "import serial.tools.list_ports", + "installed":-1} + ] @@ -99,6 +105,9 @@ {"pluginid": "10", # BH1750 "supported_os_level": [10], "modules":["i2c"]}, +{"pluginid": "11", # PME + "supported_os_level": [10], + "modules":["i2c"]}, {"pluginid": "14", # Si7021 "supported_os_level": [10], "modules":["i2c"]}, @@ -120,6 +129,9 @@ {"pluginid": "200", #Dual Switch "supported_os_level": [10], "modules":["GPIO"]}, +{"pluginid": "201", #Generic Serial + "supported_os_level": [1,2,10], + "modules":["pyserial"]}, {"pluginid": "501", # USB relay "modules":["hidapi"]}, {"pluginid": "502", # pygame play wav/mp3 diff --git a/webserver.py b/webserver.py index 28375f1..a53eef9 100644 --- a/webserver.py +++ b/webserver.py @@ -1135,15 +1135,17 @@ def handle_devices(self): TXBuffer += "" if (Settings.Tasks[x].dtype == rpieGlobals.DEVICE_TYPE_I2C): - i2cpins = Settings.get_i2c_pins() - TXBuffer += i2cpins[0] - TXBuffer += "
"+i2cpins[1] + try: + i2cpins = Settings.get_i2c_pins() + TXBuffer += i2cpins[0] + TXBuffer += "
"+i2cpins[1] + except: + TXBuffer += "NO-I2C" for tp in range(0,len(Settings.Tasks[x].taskdevicepin)): if int(Settings.Tasks[x].taskdevicepin[tp])>=0: TXBuffer += "
GPIO-" TXBuffer += str(Settings.Tasks[x].taskdevicepin[tp]) TXBuffer += "" - customValues = False # customValues = PluginCall(PLUGIN_WEBFORM_SHOW_VALUES, &TempEvent,TXBuffer.buf); if not(customValues):