diff --git a/_P205_EPD.py b/_P205_EPD.py index c03f275..9e9c4d2 100644 --- a/_P205_EPD.py +++ b/_P205_EPD.py @@ -286,6 +286,7 @@ def display_init(self): self.initprogress = False def webform_load(self): # create html page for settings + webserver.addFormNote("SPI selector unused as library do not support changing wiring, it is hardcoded!") choice1 = str(self.taskdevicepluginconfig[0]) # store display type options = ['1.54" (200x200)','1.54"B (200x200)','1.54"C (150x150)','2.13" (250x122)','2.13"B (212x104)','2.7" (264x176)','2.7"B (264x176)','2.9" (296x128)','2.9"B (296x128)','4.2" (400x300)','4.2"B (400x300)','7.5" (800x480)','7.5"B (800x480)','9.7" (1200x825)'] optionvalues = ["154","154b","154c","213","213b","270","270b","290","290b","420","420b","750","750b","970"] diff --git a/_P210_MCP3008.py b/_P210_MCP3008.py index fe40ce1..b1d7e4e 100644 --- a/_P210_MCP3008.py +++ b/_P210_MCP3008.py @@ -46,9 +46,15 @@ def plugin_init(self,enableplugin=None): nextr = self.interval self._lastdataservetime = rpieTime.millis()-(nextr*1000) self.preread = self.samples*1000 - self.ports = "SPI"+str(self.taskdevicepluginconfig[0])+"/"+str(self.taskdevicepluginconfig[1])+" CH"+str(self.taskdevicepluginconfig[2]) try: - self.adc = ADC.request_adc_device(int(self.taskdevicepluginconfig[0]),int(self.taskdevicepluginconfig[1])) + if self.spi<0 or self.spidnum<0: + return + except: + self.spi = 0 + self.spidnum = 0 + self.ports = "SPI"+str(self.spi)+"/"+str(self.spidnum)+" CH"+str(self.taskdevicepluginconfig[2]) + try: + self.adc = ADC.request_adc_device(int(self.spi),int(self.spidnum)) self.initialized = self.adc.initialized except Exception as e: misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"ADC can not be initialized! "+str(e)) @@ -57,32 +63,7 @@ def plugin_init(self,enableplugin=None): self.ports = "" def webform_load(self): # create html page for settings - ok = True - spichannels = [] - try: - for i in range(4): - if gpios.HWPorts.is_spi_usable(i) and gpios.HWPorts.is_spi_enabled(i): - spichannels.append(i) - except: - pass - options = [] - optionvalues = [] - for i in range(len(spichannels)): - options.append(str(spichannels[i])) - optionvalues.append(int(spichannels[i])) - choice1 = self.taskdevicepluginconfig[0] - webserver.addFormSelector("SPI bus","p210_bus",len(options),options,optionvalues,None,int(choice1)) - if len(spichannels)<1: - webserver.addFormNote("No usable SPI channel found, be sure to enable it at hardware settings!") - ok = False - if ok: - choice2 = self.taskdevicepluginconfig[1] - options = [] - optionvalues = [] - for i in range(4): - options.append("CE"+str(i)) - optionvalues.append(int(i)) - webserver.addFormSelector("Device number","p210_addr",len(options),options,optionvalues,None,int(choice2)) + ok = True choice3 = self.taskdevicepluginconfig[2] options = [] optionvalues = [] @@ -91,19 +72,9 @@ def webform_load(self): # create html page for settings optionvalues.append(int(i)) webserver.addFormSelector("Channel number","p210_chan",len(options),options,optionvalues,None,int(choice3)) webserver.addFormCheckBox("Oversampling","p210_over",self.timer1s) - return True + return True def webform_save(self,params): # process settings post reply - par = webserver.arg("p210_bus",params) - if par == "": - par = 0 - self.taskdevicepluginconfig[0] = int(par) - - par = webserver.arg("p210_addr",params) - if par == "": - par = 0 - self.taskdevicepluginconfig[1] = int(par) - par = webserver.arg("p210_chan",params) if par == "": par = 0 diff --git a/_P211_RC522.py b/_P211_RC522.py new file mode 100644 index 0000000..d594579 --- /dev/null +++ b/_P211_RC522.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +############################################################################# +################## RC522 RFID Reader for RPIEasy ############################ +############################################################################# +# +# Copyright (C) 2020 by Alexander Nagy - https://bitekmindenhol.blog.hu/ +# +import plugin +import webserver +import rpieGlobals +import rpieTime +import misc +import time +import gpios +from mfrc522 import MFRC522 + +class Plugin(plugin.PluginProto): + PLUGIN_ID = 211 + PLUGIN_NAME = "RFID - RC522" + PLUGIN_VALUENAME1 = "Tag" + + def __init__(self,taskindex): # general init + plugin.PluginProto.__init__(self,taskindex) + self.dtype = rpieGlobals.DEVICE_TYPE_SPI + self.vtype = rpieGlobals.SENSOR_TYPE_TEXT + self.valuecount = 1 + self.senddataoption = True + self.timeroption = False + self.timeroptional = False + self.formulaoption = False + self.reader = None + self.lastread = 0 + self.readinprogress = 0 + self.trigger = 0 + + def plugin_init(self,enableplugin=None): + plugin.PluginProto.plugin_init(self,enableplugin) + self.decimals[0] = -1 + self.initialized = False + if self.enabled: + try: + spil = self.spi + except: + spil = -1 + try: + rstpin = self.taskdevicepin[0] + except: + rstpin = -1 + spil = -1 + try: + ipin = self.taskdevicepin[1] + except: + ipin = -1 + spil = -1 + if spil>-1: + try: + gpios.HWPorts.remove_event_detect(int(ipin)) + except: + pass + try: + self.reader = MFRC522(bus=spil,device=self.spidnum,pin_rst=rstpin) + self.initialized = True + self.timer100ms = True + self.readinprogress = 0 + self.trigger = 0 + self.lastread = 0 + try: + if ipin>-1: + gpios.HWPorts.add_event_detect(int(ipin),gpios.FALLING,self.callback) + except: + pass + self.rc_clear_irq() + misc.addLog(rpieGlobals.LOG_LEVEL_DEBUG,"RC522 init ok") + except Exception as e: + self.initialized = False + misc.addLog(rpieGlobals.LOG_LEVEL_ERROR,"RC522 init error:"+str(e)) + if self.initialized==False: + self.timer100ms = False + + def timer_ten_per_second(self): + if self.timer100ms and self.initialized and self.trigger==0 and self.readinprogress==0: + self.trigger=1 + try: + self.rc_activate_trigger() + except: + pass + self.trigger=0 + return self.timer100ms + + def callback(self,channel): + if self.readinprogress==0: + self.readinprogress = 1 + if time.time()-self.lastread>=2: #do not retrigger within 2 seconds + id = None + try: + c = 0 + while not id and c<3: + id = self.rc_read_id_no_block() + c += 1 + except Exception as e: + id = None + if id is not None: + self.set_value(1,str(id),True) + self.lastread = time.time() + self._lastdataservetime = rpieTime.millis() + else: + time.sleep(0.5) #suppress quick readings + self.readinprogress = 0 + self.rc_clear_irq() + if self.trigger==0: + self.rc_activate_trigger() + + def rc_uid_to_num(self,uid): + n = 0 + for i in range(0, 5): + n = n * 256 + uid[i] + return n + + def rc_read_id_no_block(self): + (status, TagType) = self.reader.MFRC522_Request(self.reader.PICC_REQIDL) + if status != self.reader.MI_OK: + return None + (status, uid) = self.reader.MFRC522_Anticoll() + if status != self.reader.MI_OK: + return None + return self.rc_uid_to_num(uid) + + def rc_activate_trigger(self): + self.reader.Write_MFRC522(0x09,0x26) + self.reader.Write_MFRC522(0x01,0x0C) + self.reader.Write_MFRC522(0x0D,0x87) + + def rc_clear_irq(self): + self.reader.Write_MFRC522(0x04,0x7F) # clear all active irq + self.reader.Write_MFRC522(0x02,0xA0) # ComIEnReg active low, receive int + + def webform_load(self): # create html page for settings + webserver.addFormPinSelect("Reset pin (required)","taskdevicepin1",self.taskdevicepin[0]) + webserver.addFormNote("Set to an Output pin connected to RC522 reset pin!") + webserver.addFormPinSelect("IRQ pin (required)","taskdevicepin2",self.taskdevicepin[1]) + webserver.addFormNote("Set to an Input-Pullup pin connected to RC522 IRQ pin!") + return True + + def webform_save(self,params): # process settings post reply + changed = False + par = webserver.arg("taskdevicepin1",params) + if par == "": + par = 25 + pval = self.taskdevicepin[0] + self.taskdevicepin[0] = int(par) + if pval != self.taskdevicepin[0]: + changed = True + par = webserver.arg("taskdevicepin2",params) + if par == "": + par = 18 + pval = self.taskdevicepin[1] + self.taskdevicepin[1] = int(par) + if pval != self.taskdevicepin[1]: + changed = True + if changed: + self.plugin_init() + return True + + def plugin_exit(self): + self.initialized = False + self.timer100ms = False + return True diff --git a/lib/lib_ftdigpios.py b/lib/lib_ftdigpios.py index 36e099a..76ca004 100644 --- a/lib/lib_ftdigpios.py +++ b/lib/lib_ftdigpios.py @@ -1100,6 +1100,16 @@ def geti2clist(self): resarr.append(i) return resarr + def getspilist(self): + resarr = [] + darr = [] + for i in range(20): + if self.is_spi_usable(i): + resarr.append(i) + for i in range(6): # provisoric + darr.append(i) + return resarr, darr + def removedevpinout(self,ftdidevicename,devtype=""): for p in reversed(range(len(Settings.Pinout))): try: diff --git a/lib/lib_opigpios.py b/lib/lib_opigpios.py index ceed224..27ce492 100644 --- a/lib/lib_opigpios.py +++ b/lib/lib_opigpios.py @@ -1015,6 +1015,16 @@ def geti2clist(self): resarr.append(i) return resarr + def getspilist(self): + resarr = [] + darr = [] + for i in range(10): #needs some enhancement! + if self.is_spi_usable(i): + resarr.append(i) + for i in range(2): #provisoric + darr.append(i) + return resarr, darr + def createpinout(self,pinout): global PINOUT40 if ("40" in pinout and len(Settings.Pinout)<41) or ("26" in pinout and len(Settings.Pinout)<27): diff --git a/lib/lib_rpigpios.py b/lib/lib_rpigpios.py index 9b703e7..28287c4 100644 --- a/lib/lib_rpigpios.py +++ b/lib/lib_rpigpios.py @@ -1391,6 +1391,29 @@ def geti2clist(self): rlist = [] return rlist + def getspilist(self): + import glob + sch = [] + sdev = [] + try: + devlist = glob.glob('/dev/spi*') + if len(devlist)>0: + for d in devlist: + try: + dstr = d.replace("/dev/spidev","") + d2str = dstr.split(".") + if int(d2str[0]) not in sch: + sch.append(int(d2str[0])) + if int(d2str[1]) not in sdev: + sdev.append(int(d2str[1])) + except: + pass + sch.sort() + sdev.sort() + except: + rlist = [] + return sch, sdev + def createpinout(self,pinout): global PINOUT40, PINOUT26R1_DELTA, PINOUT26R2_DELTA if pinout == "40" and len(Settings.Pinout)!=41: diff --git a/plugin.py b/plugin.py index 9fe17ce..7ce1854 100644 --- a/plugin.py +++ b/plugin.py @@ -33,6 +33,7 @@ def __init__(self,taskindex): # general init self.uart = -1 self.i2c = -1 self.spi = -1 + self.spidnum = -1 # self.pullupoption = False # self.pullup = False self.inverselogicoption = False diff --git a/plugindeps.py b/plugindeps.py index 2b71597..59314f7 100644 --- a/plugindeps.py +++ b/plugindeps.py @@ -257,6 +257,11 @@ "pip": ["spidev"], "testcmd": "import spidev", "installed":-1}, +{"name":"mfrc522", + "apt": [], + "pip": ["mfrc522"], + "testcmd": "import mfrc522", + "installed":-1}, {"name":"pytz", "apt": ["python3-pip","python3-setuptools"], "pip": ["pytz"], @@ -488,6 +493,9 @@ {"pluginid": "210", #MCP3008 "supported_os_level": [3,10], "modules":["GPIO","spidev"]}, +{"pluginid": "211", #RC522 + "supported_os_level": [10], + "modules":["GPIO","spidev","mfrc522"]}, {"pluginid": "501", # USB relay "modules":["hidapi"]}, {"pluginid": "502", # pygame play wav/mp3 diff --git a/rpieGlobals.py b/rpieGlobals.py index bdbe69e..a6224fb 100644 --- a/rpieGlobals.py +++ b/rpieGlobals.py @@ -6,7 +6,7 @@ # Copyright (C) 2018-2020 by Alexander Nagy - https://bitekmindenhol.blog.hu/ # PROGNAME = "RPIEasy" -BUILD = 20327 +BUILD = 20330 PROGVER = str(BUILD)[:1]+"."+str(BUILD)[1:2]+"."+str(BUILD)[2:] gpMenu = [] diff --git a/webserver.py b/webserver.py index bc783f2..9790968 100644 --- a/webserver.py +++ b/webserver.py @@ -1423,6 +1423,16 @@ def handle_devices(self): TXBuffer += "
"+str(i2cpins[1]) except: TXBuffer += "NO-I2C" + elif (Settings.Tasks[x].dtype == rpieGlobals.DEVICE_TYPE_SPI): + try: + c = Settings.Tasks[x].spi + except: + c = -1 + Settings.Tasks[x].spi = -1 + try: + TXBuffer += "SPI"+str(c) + except: + TXBuffer += "NO-SPI" try: for tp in range(0,len(Settings.Tasks[x].taskdevicepin)): if int(Settings.Tasks[x].taskdevicepin[tp])>=0: @@ -1633,6 +1643,27 @@ def handle_devices(self): Settings.Tasks[taskIndex].i2c = int(arg("i2c",responsearr)) except: pass + elif (Settings.Tasks[taskIndex].dtype==rpieGlobals.DEVICE_TYPE_SPI): + try: + if Settings.Tasks[taskIndex].spi>-1: + pass + except: + Settings.Tasks[taskIndex].spi = -1 # set to default in case of error + try: + Settings.Tasks[taskIndex].spi = int(arg("spi",responsearr)) + except: + pass + try: + if Settings.Tasks[taskIndex].spidnum>-1: + pass + except: + Settings.Tasks[taskIndex].spidnum = -1 # set to default in case of error + try: + Settings.Tasks[taskIndex].spidnum = int(arg("spidnum",responsearr)) + except: + pass + + if Settings.Tasks[taskIndex].taskname=="": Settings.Tasks[taskIndex].enabled = False Settings.savetasks() # savetasksettings!!! @@ -1676,6 +1707,29 @@ def handle_devices(self): except: pass addSelector_Foot() + elif (Settings.Tasks[taskIndex].dtype==rpieGlobals.DEVICE_TYPE_SPI): + try: + import gpios + options1, options2 = gpios.HWPorts.getspilist() + except Exception as e: + options1 = [] + options2 = [] + addHtml("SPI line:") + addSelector_Head("spi",False) + for d in range(len(options1)): + try: + addSelector_Item("SPI"+str(options1[d]),options1[d],(Settings.Tasks[taskIndex].spi==options1[d]),False) + except: + pass + addSelector_Foot() + addHtml("SPI device num:") + addSelector_Head("spidnum",False) + for d in range(len(options2)): + try: + addSelector_Item("CE"+str(options2[d]),options2[d],(Settings.Tasks[taskIndex].spidnum==options2[d]),False) + except: + pass + addSelector_Foot() try: Settings.Tasks[taskIndex].webform_load() # call plugin function to fill TXBuffer