diff --git a/t5-4c-86/rules.be b/t5-4c-86/rules.be new file mode 100644 index 0000000..d5965dc --- /dev/null +++ b/t5-4c-86/rules.be @@ -0,0 +1,174 @@ +# Touch events handlers +var eventtopic = "stat/lrms01" +var led_state = [] +for i:0..27 + led_state += ['#000000'] +end + +def get_leds_for_channel(ch) + if ch <= 2 + return [13,21] + elif ch >= 3 && ch <= 5 + return [11,23] + elif ch >= 6 && ch <= 8 + return [9,25] + else + return [7,27] + end +end + +def get_leds_for_power(power) + if power == 0 + return [13,21] + elif power == 1 + return [11,23] + elif power == 2 + return [9,25] + else + return [7,27] + end +end + +# Set initial state of leds +var power_state = [tasmota.get_power(0), tasmota.get_power(1), tasmota.get_power(2), tasmota.get_power(3), tasmota.get_power(4)] +def TXUltimate_UpdateLeds() + for i:0..size(power_state)-1 + if power_state[i] + var leds = get_leds_for_power(i) + TXUltimate_Led(leds, 'ON') + else + var leds = get_leds_for_power(i) + TXUltimate_Led(leds, 'OFF') + end + end +end + + +def TXUltimate_Led(leds, state) + import string + var color + print("Set LED", leds, "to", state) + if state == 'ON' + color = '#14f240' + elif state == 'OFF' + color = '#ef3716' + else + color = state + end + + + for i:0..size(leds)-1 + led_state[leds[i]-1] = color + end + for i:0..2 + tasmota.cmd("Color #F0F0F0") + tasmota.cmd("Color #000000") + end + for i:0..size(led_state)-1 + tasmota.cmd(string.format("Led%d %s", i+1, led_state[i])) + end +end + +def TXUltimate_Touch(value, trigger, msg) + tasmota.cmd('Buzzer') +end + +def TXUltimate_Short(value, trigger, msg) + #print("message:") + #print(msg) + import mqtt + var Channel = msg['TXUltimate']['Channel'] + var ind + var leds = [] + if Channel <= 2 + ind = 0 + leds = [13,21] + elif Channel >= 3 && Channel <= 5 + ind = 1 + leds = [11,23] + elif Channel >= 6 && Channel <= 8 + ind = 2 + leds = [9,25] + else + ind = 3 + leds = [7,27] + end + tasmota.set_power(ind, ! tasmota.get_power(ind)) + if tasmota.get_power(ind) + TXUltimate_Led(leds, 'ON') + else + TXUltimate_Led(leds, 'OFF') + end + mqtt.publish(eventtopic .. "/Short", str(ind+1), false) +end + +def TXUltimate_Long(value, trigger, msg) + import mqtt + var Channel = msg['TXUltimate']['Channel'] + var ind + if Channel <= 2 + ind = 0 + elif Channel >= 3 && Channel <= 5 + ind = 1 + elif Channel >= 6 && Channel <= 8 + ind = 2 + else + ind = 3 + end + mqtt.publish(eventtopic .. "/Long", str(ind+1), false) +end + +def TXUltimate_Swipe(value, trigger, msg) + #print("message:") + #print(msg) + import mqtt + var Action = msg['TXUltimate']['Action'] + var targetstate + if Action == 'Swipe right' + targetstate = '1' + var From = msg['TXUltimate']['From'] + var To = msg['TXUltimate']['To'] + mqtt.publish(eventtopic .. "/EVENT", "SwipeRight", false) + # NOTE: Power0 manage all channels include backlight + tasmota.cmd('Power0 1') + elif Action == 'Swipe left' + targetstate = '0' + var From = msg['TXUltimate']['From'] + var To = msg['TXUltimate']['To'] + mqtt.publish(eventtopic .. "/EVENT", "SwipeLeft", false) + # NOTE: Power0 manage all channels include backlight + tasmota.cmd('Power0 0') + end + TXUltimate_UpdateLeds() +end + + +def TXUltimate_Multi(value, trigger, msg) + print("Handler Multi.") + #print("message:") + #print(msg) + import mqtt + mqtt.publish("stat/tasmota_E09620/EVENT", "Multi", false) + # tasmota.publish_result("{'Action': 'Multi'}", "EVENT") +end +TXUltimate_UpdateLeds() + + +#tasmota.remove_rule("TXUltimate#Action=Touch", "TXUltimate_Touch") +tasmota.add_rule("TXUltimate#Action=Touch", TXUltimate_Touch, "TXUltimate_Touch") + +#tasmota.remove_rule("TXUltimate#Action=Short", "TXUltimate_Short") +tasmota.add_rule("TXUltimate#Action=Short", TXUltimate_Short, "TXUltimate_Short") + +#tasmota.remove_rule("TXUltimate#Action=Long", "TXUltimate_Long") +tasmota.add_rule("TXUltimate#Action=Long", TXUltimate_Long, "TXUltimate_Long") + +#tasmota.remove_rule("TXUltimate#Action=Swipe right", "TXUltimate_Swipe_right") +tasmota.add_rule("TXUltimate#Action=Swipe right", TXUltimate_Swipe, "TXUltimate_Swipe_right") +#tasmota.remove_rule("TXUltimate#Action=Swipe left", "TXUltimate_Swipe_left") +tasmota.add_rule("TXUltimate#Action=Swipe left", TXUltimate_Swipe, "TXUltimate_Swipe_left") + +#tasmota.remove_rule("TXUltimate#Action=Multi", "TXUltimate_Multi") +tasmota.add_rule("TXUltimate#Action=Multi", TXUltimate_Multi, "TXUltimate_Multi") +tasmota.cmd('Buzzer') +print("Events loaded.") diff --git a/t5-4c-86/txultimate.be b/t5-4c-86/txultimate.be new file mode 100644 index 0000000..31cc4cd --- /dev/null +++ b/t5-4c-86/txultimate.be @@ -0,0 +1,113 @@ +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 + print("TXU: Message", msg, msg[4], msg[5]) + var lst = self.split_55(msg) + for i:0..size(lst)-1 + msg = lst[i] + var event = "" + var params = "" + if msg[2] == 0x01 && msg[3] == 0x02 # 02 signifies a touch event + print('Message Type:', msg[4], msg[5]) + if (msg[4] == 0x02 && msg[5] != 0) || msg[4] == 0x01 # 2 is a press and 1 is release + if msg[5] < 0x0B + event= "Short" + params = ',"Channel":' + str(msg[5]) + elif msg[5] == 0x0B + event= "Multi" + elif msg[5] > 0x0B + event = "Long" + params = ',"Channel":' + str(msg[5]-16) + end + elif msg[4] == 0x03 # 3 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 + if event != "" + var jm = string.format("{\"TXUltimate\":{\"Action\":\"%s\"%s}}",event,params) + tasmota.publish_result(jm, "RESULT") + jm = string.format("{\"TXUltimate\":{\"Action\":\"Touch\",\"Event\":\"%s\"}}",event) + tasmota.publish_result(jm, "RESULT") + end + end + end + end + end + end + end +end + +txu=TXUltimate()