Nochmal zusammengefasst:
zuerst setzt man das Template.
Für einen 1Ch
2Ch
{"NAME":"TX Ultimate 2","GPIO":[0,0,7808,0,7840,3872,0,0,0,1376,0,7776,0,225,224,3232,0,480,3200,0,0,0,3840,0,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"Backlog Pixels 28"}3Ch
{"NAME":"TX Ultimate 3","GPIO":[0,0,7808,0,7840,3872,0,0,0,1376,0,7776,0,225,224,3232,0,480,3200,0,0,0,3840,226,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"Backlog Pixels 28"}4Ch
{"NAME":"TX Ultimate 4","GPIO":[0,0,7808,0,7840,3872,0,0,0,1376,0,7776,0,225,224,3232,0,480,3200,227,0,0,3840,226,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"Backlog Pixels 28"}Danach erstelle ich unter Werkzeuge -> Dateisystem verwalten eine Datei mit dem Namen txultimate.be mit folgendem Inhalt:
class TXUltimate : Driver static header = bytes('AA55') var ser # create serial port object # intialize the serial port, if unspecified Tx/Rx are GPIO 16/17 def init(tx, rx) if !tx tx = 19 end if !rx rx = 22 end self.ser = serial(rx, tx, 115200, serial.SERIAL_8N1) tasmota.add_driver(self) end def split_55(b) var ret = [] var s = size(b) var i = s-2 # start from last-1 while i > 0 if b[i] == 0xAA && b[i+1] == 0x55 ret.push(b[i..s-1]) # push last msg to list b = b[(0..i-1)] # write the rest back to b end i -= 1 end ret.push(b) return ret end def crc16(data, poly) if !poly poly = 0x1021 end # CRC-16/CCITT-FALSE HASHING ALGORITHM var crc = 0xFFFF for i:0..size(data)-1 crc = crc ^ data[i] << 8 for j:0..7 if crc & 0x8000 crc = (crc << 1) ^ poly else crc = crc << 1 end end end return crc & 0xFFFF end def encode(payload) var msg_crc = self.crc16(bytes(payload)) # calc crc var b = bytes('AA55') # add header b += bytes(payload) # add payload b.add(msg_crc, -2) # add calculated crc 2 bytes, big endian return b end # send a string payload (needs to be a valid json string) def send(payload) print("TXU: Sent =", payload) var payload_bin = self.encode(payload) self.ser.write(payload_bin) log("TXU: Sent = " + str(payload_bin), 2) end # read serial port def every_50ms() if self.ser.available() > 0 var msg = self.ser.read() # read bytes from serial as bytes import string if size(msg) > 0 # print("TXU: Raw =", msg) if msg[0..1] == self.header var lst = self.split_55(msg) for i:0..size(lst)-1 msg = lst[i] print(msg) var event = "" var params = "" if msg[3] == 0x02 # 02 signifies a touch event # print('Touch event') if msg[4] == 0x01 # data lenght 1 is a press if msg[5] < 0x0B event = "Short" params = ',"Channel":' + str(msg[5]) print('Short press zone:', msg[5]) elif msg[5] == 0x0B event = "Multi" print('Multi press') elif msg[5] > 0x0B event = "Long" params = ',"Channel":' + str(msg[5]-16) print('Long press zone:', msg[5]) end elif msg[4] == 0x02 # data length 3 is a release event = "Touch" params = ',"Channel":' + str(msg[6]) print('Touch event:', msg[5], 'pos:', msg[6]) if msg[5] != 0x00 event = "Dash" params = ',"From":' + str(msg[6]) + ',"To":' + str(msg[5]) print('Mini swipe channel', msg[5], '->', msg[6]) end elif msg[4] == 0x03 # data lenght 1 is a swipe if msg[5] == 0x0C event = "Swipe right" params = ',"From":' + str(msg[6]) + ',"To":' + str(msg[7]) print('Swipe left-right', msg[6], '->', msg[7]) elif msg[5] == 0x0D event = "Swipe left" params = ',"From":' + str(msg[6]) + ',"To":' + str(msg[7]) print('Swipe right-left', msg[6], '->', msg[7]) end end var jm = string.format("{\"TXUltimate\":{\"Action\":\"%s\"%s}}",event,params) tasmota.publish_result(jm, "RESULT") end end end end end end end txu=TXUltimate()und damit diese Datei auch beim Start geladen wird, noch eine weitere Datei mit dem Namen autoexec.be mit dem Inhalt
load("txultimate.be")Dann geht es weiter mit den Rules. Ich lasse ganz bewusst Rule1 von dieser Seite weg, da sie bei mir ziemliches Chaos verursacht. Bei Mehrchannelschaltern werden z.b. die Channel wild durcheinander geschaltet. Außerdem habe ich bei mir das Backlight per Script geschaltet. Es schaltet sich abends an und morgens aus. Das funktioniert mit der Rule auch nicht, da es sich dann bei jedem Tastendruck an- bzw ausschaltet.
Damit der Touch die Relais schaltet, benutze ich folgende Rule von @Dieter_P
rule2 On TXultimate#Action$!Touch do break rule2 + On TXUltimate#Channel=1 do power1 toggle endon rule2 + On TXUltimate#Channel=<xxx> do power1 toggle endon rule2 + On TXUltimate#Channel=5 do power2 toggle endon rule2 + On TXUltimate#Channel=<xxx> do power2 toggle endon rule2 + On TXUltimate#Channel=10 do power3 toggle endon rule2 + On TXUltimate#Channel=<xxx> do power3 toggle endonHier im Beispiel für einen 3Ch-Schalter. Wobei ich aber nicht einfach die Channel übernehme, sondern sie selber austeste. Da man sowieso in der Konsole ist, muss man hier nur auf das Touch an der gewünschten Stelle drücken und die Konsole gibt den Channel aus. Den übernehme ich dann in die Rule, hier gekennzeichnet mit dem <xxx>.
Das wars eigentlich auch schon. Der Schalter sollte nun funktionieren.