KAKU – TPC-300 laten schakelen via Linux
Op deze pagina vind je een Python (2.x) script om de TPC-200 en TPC-300 te schakelen in een Linux omgeving, we maken daarvoor gebruik van python en pyUSB om de TPC kastjes aan te sturen met een “bit-reeks”, om erachter te komen welkte bit-reeks er verstuurd wordt, gaan we dit aftappen met USBPcap, en bekijken/analyseren we het resultaat in Wireshark.
Wat heb je nodig?
1) Python 2.x met pyUSB
2) Wireshark
3) USBPcap
4) KAKUcli
USB Sniffen op de TPC-300
Omdat de KAKU TPC software alleen op Windows werkt, moeten we via Windows de bit-reeks achterhalen wat naar de TPC-300 gezonden wordt, start daarvoor USBPcapCMD.exe
Ontvangers met codeschijfjes
1) Selecteer het juiste USB apparaat (de TPC-300) kan lastig zijn te vinden, anders moet je even wat apparaten uitproberen ;-)
2) Als uitvoer vul je in “tpc300.pcap“.
3) Nadat je op enter hebt gedrukt wordt het desbetreffende apparaat “afgeluisterd”.
4) Gebruik KAKUcli.exe om nu schakel commando’s van het oude draaischijfjes systeem naar de TPC-300 te sturen:
1 2 3 4 5 6 |
KAKUcli.exe a1 aan KAKUcli.exe a2 aan KAKUcli.exe a3 aan KAKUcli.exe a3 uit KAKUcli.exe a2 uit KAKUcli.exe a1 uit |
5) Nu hebben we een 6-tal commando’s uitgevoerd om gegevens te vergaren, sluit “USBPcapCMD.exe” door op het kruisje te drukken.
6) Er is nu een bestandje tpc300.pcap aangemaakt, deze kun je openen in Wireshark:
We kijken naar wat er gestuurd (URB_INTERRUPT_OUT) wordt van de HOST naar DESTINATION, als je de regel aanklikt, zie je staan:
Leftover Capture Data: 5a0002050000000000000000000000000000000000000000...
Dit is een byte-reeks van 64 byte (achteraf hebben we maar de eerste 4 byte nodig), als we nu alle 6 commando uitlezen, komen we tot het volgende:
1 2 3 4 5 6 |
KAKUcli.exe a1 aan > geeft [0x5A,0x00,0x02,0x05] KAKUcli.exe a2 aan > geeft [0x5A,0x10,0x02,0x05] KAKUcli.exe a3 aan > geeft [0x5A,0x20,0x02,0x05] KAKUcli.exe a3 uit > geeft [0x5A,0x20,0x00,0x05] KAKUcli.exe a2 uit > geeft [0x5A,0x10,0x00,0x05] KAKUcli.exe a1 uit > geeft [0x5A,0x00,0x00,0x05] |
Hieruit kunnen we concluderen dat de eerste 4 bytes veranderen, (de laatste reeks zijn allemaal 0x00):
Byte 1 > Startbyte
Byte 2 > Kanaal (1e nibble 0 t/m F = Kanaal, 2e nibble 0 t/m F = Letter)
Byte 3 > Aan/Uit (0x02 = Aan, 0x00 = Uit)
Byte 4 > Eindbyte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
A1 = 00 (hex 0x00) / B1 = 01 (hex 0x01) / ... / P1 = 15 (hex 0x0F) A2 = 16 (hex 0x10) / B2 = 17 (hex 0x11) / ... / P2 = 31 (hex 0x1F) A3 = 32 (hex 0x20) / B3 = 33 (hex 0x21) / ... / P3 = 47 (hex 0x2F) A4 = 48 (hex 0x30) / B4 = 49 (hex 0x31) / ... / P4 = 63 (hex 0x3F) A5 = 64 (hex 0x40) / B5 = 65 (hex 0x41) / ... / P5 = 79 (hex 0x4F) A6 = 80 (hex 0x50) / B6 = 81 (hex 0x51) / ... / P6 = 95 (hex 0x5F) A7 = 96 (hex 0x60) / B7 = 97 (hex 0x61) / ... / P7 = 111 (hex 0x6F) A8 = 112 (hex 0x70) / B8 = 113 (hex 0x71) / ... / P8 = 127 (hex 0x7F) A9 = 128 (hex 0x80) / B9 = 129 (hex 0x81) / ... / P9 = 143 (hex 0x8F) A10 = 144 (hex 0x90) / B10 = 145 (hex 0x91) / ... / P10 = 159 (hex 0x9F) A11 = 160 (hex 0xA0) / B11 = 161 (hex 0xA1) / ... / P11 = 175 (hex 0xAF) A12 = 176 (hex 0xB0) / B12 = 177 (hex 0xB1) / ... / P12 = 191 (hex 0xBF) A13 = 192 (hex 0xC0) / B13 = 193 (hex 0xC1) / ... / P13 = 207 (hex 0xCF) A14 = 208 (hex 0xD0) / B14 = 209 (hex 0xD1) / ... / P14 = 223 (hex 0xDF) A15 = 224 (hex 0xE0) / B15 = 225 (hex 0xE1) / ... / P15 = 239 (hex 0xEF) A16 = 240 (hex 0xF0) / B16 = 241 (hex 0xF1) / ... / P16 = 255 (hex 0xFF) |
1 2 |
AAN = 2 (hex 0x02) UIT = 0 (hex 0x00) |
Nieuwe zelflerende ontvangers
1) Selecteer het juiste USB apparaat (de TPC-300) kan lastig zijn te vinden, anders moet je even wat apparaten uitproberen ;-)
2) Als uitvoer vul je in “tpc300.pcap“.
3) Nadat je op enter hebt gedrukt wordt het desbetreffende apparaat “afgeluisterd”.
4) Gebruik KAKUcli.exe om nu schakel commando’s van het oude draaischijfjes systeem naar de TPC-300 te sturen:
1 2 3 4 5 6 |
KAKUcli.exe 105 aan KAKUcli.exe 106 aan KAKUcli.exe 107 aan KAKUcli.exe 107 uit KAKUcli.exe 106 uit KAKUcli.exe 105 uit |
5) Nu hebben we een 6-tal commando’s uitgevoerd om gegevens te vergaren, sluit “USBPcapCMD.exe” door op het kruisje te drukken.
6) Er is nu een bestandje tpc300.pcap aangemaakt, deze kun je openen in Wireshark:
We kijken naar wat er gestuurd (URB_INTERRUPT_OUT) wordt van de HOST naar DESTINATION, als je de regel aanklikt, zie je staan:
Leftover Capture Data: 5a6923050000000000000000000000000000000000000000...
Dit is een byte-reeks van 64 byte (achteraf hebben we maar de eerste 4 byte nodig), als we nu alle 6 commando uitlezen, komen we tot het volgende:
1 2 3 4 5 6 |
KAKUcli.exe a1 aan > geeft [0x5A,0x69,0x23,0x05] KAKUcli.exe a2 aan > geeft [0x5A,0x6A,0x23,0x05] KAKUcli.exe a3 aan > geeft [0x5A,0x6B,0x23,0x05] KAKUcli.exe a3 uit > geeft [0x5A,0x6B,0x01,0x05] KAKUcli.exe a2 uit > geeft [0x5A,0x6A,0x01,0x05] KAKUcli.exe a1 uit > geeft [0x5A,0x69,0x01,0x05] |
Hieruit kunnen we concluderen dat de eerste 4 bytes veranderen, (de laatste reeks zijn allemaal 0x00):
Byte 1 > Startbyte
Byte 2 > Kanaal (0x00 = 0 / 0x69 = 105 (6x16+9) / 0xFF = 256)
Byte 3 > Aan/Uit (0x23 = Aan, 0x01 = Uit)
Byte 4 > Eindbyte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
1 = hex 0x00 / 17 = hex 0x10) 2 = hex 0x01 / 18 = hex 0x11) 3 = hex 0x02 / 19 = hex 0x12) 4 = hex 0x03 / 20 = hex 0x13) 5 = hex 0x04 / 21 = hex 0x14) 6 = hex 0x05 / 22 = hex 0x15) 7 = hex 0x06 / 23 = hex 0x16) 8 = hex 0x07 / 24 = hex 0x17) 9 = hex 0x08 / 25 = hex 0x18) 10 = hex 0x09 / 26 = hex 0x19) 11 = hex 0x0A / 27 = hex 0x1A) 12 = hex 0x0B / 28 = hex 0x1B) 13 = hex 0x0C / 29 = hex 0x1C) 14 = hex 0x0D / 30 = hex 0x1D) 15 = hex 0x0E / 31 = hex 0x1E) 16 = hex 0x0F / 32 = hex 0x1F) ..... |
1 2 |
AAN = 2 (hex 0x23) UIT = 0 (hex 0x01) |
Dimstanden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
UIT = 1 (hex 0x01) DIMSTAND 1 = 3 (hex 0x03) DIMSTAND 2 = 5 (hex 0x05) DIMSTAND 3 = 7 (hex 0x07) DIMSTAND 4 = 9 (hex 0x09) DIMSTAND 5 = 11 (hex 0x0B) DIMSTAND 6 = 13 (hex 0x0D) DIMSTAND 7 = 15 (hex 0x0F) DIMSTAND 8 = 17 (hex 0x11) DIMSTAND 9 = 19 (hex 0x13) DIMSTAND 10 = 21 (hex 0x15) DIMSTAND 11 = 23 (hex 0x17) DIMSTAND 12 = 25 (hex 0x19) DIMSTAND 13 = 27 (hex 0x1B) DIMSTAND 14 = 29 (hex 0x1D) DIMSTAND 15 = 31 (hex 0x1F) DIMSTAND 16 = 33 (hex 0x21) AAN = 35 (hex 0x23) |
Het script
Het script hieronder is een “kant-en-klaar” voorbeeld van pyUSB, we laten de byte-reeks verzenden naar de TPC op de USB poort.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#!/usr/bin/python import usb.core import usb.util import sys import logging # Selecteer eerst de juiste TPC zender door een hekje weg te halen en toe te voegen, # dit om het juiste USB apparaaat (via VID & PID) te selecteren. # TPC-200 #dev = usb.core.find(idVendor=0xfeff, idProduct=0x0301) # TPC-300 dev = usb.core.find(idVendor=0xfeff, idProduct=0x0802) if dev is None: raise ValueError('Device not found') if dev.is_kernel_driver_active(0) is True: dev.detach_kernel_driver(0) print 'Now reading data' dev.set_configuration() cfg = dev.get_active_configuration() interface_number = cfg[(0,0)].bInterfaceNumber intf = usb.util.find_descriptor( cfg, bInterfaceNumber = interface_number, ) ep = usb.util.find_descriptor( intf, custom_match = \ lambda e: \ usb.util.endpoint_direction(e.bEndpointAddress) == \ usb.util.ENDPOINT_OUT ) count = 0 # Kanaal A7 aan zetten #result=[0x5A,0x60,0x02,0x05] # Kanaal A7 uit zetten result=[0x5A,0x60,0x00,0x05] assert ep is not None ep.write(result) |
Nu het script werkt kunnen we het makkelijker maken door een commandolijn parameter te gebruiken:
sudo python kakutpc.py [kanaal] [actie]
Schakelvoorbeelden:
kakutpc.py c7 aan  > schakelt op een codeschijfjes ontvanger kanaal c7 aan.
kakutpc.py k13 0  > schakelt op een codeschijfjes ontvanger kanaal k13 uit.
kakutpc.py 25 17  > schakelt op een automatisch codesysteem ontvanger kanaal 25 aan.
kakutpc.py 63 uit  > schakelt op een automatisch codesysteem ontvanger kanaal 63 uit.
kakutpc.py 215 11   > schakelt op een automatisch codesysteem ontvanger kanaal 215 aan in dimstand 11.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
#!/usr/bin/python import usb.core import usb.util import sys import logging #KAKU TPC-300 SCRIPT door S. Ebeltjes, Domoticx.nl # Selecteer eerst de juiste TPC zender door een hekje weg te halen en toe te voegen, # dit om het juiste USB apparaaat (via VID & PID) te selecteren. # TPC-200 #dev = usb.core.find(idVendor=0xfeff, idProduct=0x0301) # TPC-300 dev = usb.core.find(idVendor=0xfeff, idProduct=0x0802) if dev is None: raise ValueError('Device not found') if dev.is_kernel_driver_active(0) is True: dev.detach_kernel_driver(0) print 'Now reading data' dev.set_configuration() cfg = dev.get_active_configuration() interface_number = cfg[(0,0)].bInterfaceNumber intf = usb.util.find_descriptor( cfg, bInterfaceNumber = interface_number, ) ep = usb.util.find_descriptor( intf, custom_match = \ lambda e: \ usb.util.endpoint_direction(e.bEndpointAddress) == \ usb.util.ENDPOINT_OUT ) count = 0 # sys.argv[1] > 1e parameter van de commandolijn # sys.argv[1][0] > 1e byte van de 1e parameter van de commandolijn # .isalpha() > Check of deze string alfanumeriek is (a-z) if sys.argv[1][0].isalpha() is True: # Oude codeschijfje systeem # Omzetlijst codesysteem naar HEX kanaal_letter_hex = "" kanaal_letter = sys.argv[1][0] if kanaal_letter == "a": kanaal_letter_hex = "0" if kanaal_letter == "b": kanaal_letter_hex = "1" if kanaal_letter == "c": kanaal_letter_hex = "2" if kanaal_letter == "d": kanaal_letter_hex = "3" if kanaal_letter == "e": kanaal_letter_hex = "4" if kanaal_letter == "f": kanaal_letter_hex = "5" if kanaal_letter == "g": kanaal_letter_hex = "6" if kanaal_letter == "h": kanaal_letter_hex = "7" if kanaal_letter == "i": kanaal_letter_hex = "8" if kanaal_letter == "j": kanaal_letter_hex = "9" if kanaal_letter == "k": kanaal_letter_hex = "a" if kanaal_letter == "l": kanaal_letter_hex = "b" if kanaal_letter == "m": kanaal_letter_hex = "c" if kanaal_letter == "n": kanaal_letter_hex = "d" if kanaal_letter == "o": kanaal_letter_hex = "e" if kanaal_letter == "p": kanaal_letter_hex = "f" kanaal_cijfer = sys.argv[1][1:3] kanaal_cijfer_hex = "" if kanaal_cijfer == "1": kanaal_cijfer_hex = "0" if kanaal_cijfer == "2": kanaal_cijfer_hex = "1" if kanaal_cijfer == "3": kanaal_cijfer_hex = "2" if kanaal_cijfer == "4": kanaal_cijfer_hex = "3" if kanaal_cijfer == "5": kanaal_cijfer_hex = "4" if kanaal_cijfer == "6": kanaal_cijfer_hex = "5" if kanaal_cijfer == "7": kanaal_cijfer_hex = "6" if kanaal_cijfer == "8": kanaal_cijfer_hex = "7" if kanaal_cijfer == "9": kanaal_cijfer_hex = "8" if kanaal_cijfer == "10": kanaal_cijfer_hex = "9" if kanaal_cijfer == "11": kanaal_cijfer_hex = "a" if kanaal_cijfer == "12": kanaal_cijfer_hex = "b" if kanaal_cijfer == "13": kanaal_cijfer_hex = "c" if kanaal_cijfer == "14": kanaal_cijfer_hex = "d" if kanaal_cijfer == "15": kanaal_cijfer_hex = "e" if kanaal_cijfer == "16": kanaal_cijfer_hex = "f" # Maak HEX codes van de kanalen (zorg dat ze INT zijn) kanaal_hex = int("0x" + kanaal_cijfer_hex + kanaal_letter_hex, 16) actie = sys.argv[2] actie_cijfer_hex = "" if actie == "aan": actie_cijfer_hex = "2" if actie == "uit": actie_cijfer_hex = "0" # Maak HEX codes van de actie (zorg dat het INT is) actie_hex = int("0x0" + actie_cijfer_hex, 16) if sys.argv[1][0].isalpha() is False: # Nieuwe zelf lerende systeem kanaal_cijfer = sys.argv[1][0:3] # Maak HEX codes van de kanalen (zorg dat ze INT zijn) kanaal_hex = int(kanaal_cijfer) actie = sys.argv[2] actie_cijfer_hex = "" if actie == "aan": actie_cijfer_hex = "23" if actie == "1": actie_cijfer_hex = "3" if actie == "2": actie_cijfer_hex = "5" if actie == "3": actie_cijfer_hex = "7" if actie == "4": actie_cijfer_hex = "9" if actie == "5": actie_cijfer_hex = "B" if actie == "6": actie_cijfer_hex = "D" if actie == "7": actie_cijfer_hex = "F" if actie == "8": actie_cijfer_hex = "11" if actie == "9": actie_cijfer_hex = "13" if actie == "10": actie_cijfer_hex = "15" if actie == "11": actie_cijfer_hex = "17" if actie == "12": actie_cijfer_hex = "19" if actie == "13": actie_cijfer_hex = "1B" if actie == "14": actie_cijfer_hex = "1D" if actie == "15": actie_cijfer_hex = "1F" if actie == "16": actie_cijfer_hex = "21" if actie == "uit": actie_cijfer_hex = "01" # Maak HEX codes van de actie (zorg dat het INT is) actie_hex = int("0x" + actie_cijfer_hex, 16) result=[0x5A, kanaal_hex, actie_hex, 0x05] assert ep is not None ep.write(result) |
TPC informatie (Linux)
1 2 3 4 5 6 |
[ 310.856333] usb 1-1.2: new full-speed USB device number 4 using dwc_otg [ 310.967531] usb 1-1.2: New USB device found, idVendor=feff, idProduct=0301 [ 310.967568] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 310.967583] usb 1-1.2: Product: TPC-200 [ 310.967596] usb 1-1.2: Manufacturer: Shannon [ 310.989488] hid-generic 0003:FEFF:0301.0001: hiddev0,hidraw0: USB HID v1.10 Device [Shannon TPC-200] on usb-bcm2708_usb-1.2/input0 |
1 2 3 4 5 6 |
[ 3571.460627] usb 1-1.2: new full-speed USB device number 9 using dwc_otg [ 3571.568010] usb 1-1.2: New USB device found, idVendor=feff, idProduct=0802 [ 3571.568046] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [ 3571.568062] usb 1-1.2: Product: TPC-300 [ 3571.568076] usb 1-1.2: Manufacturer: Shannon [ 3571.582356] hid-generic 0003:FEFF:0802.0006: hiddev0,hidraw0: USB HID v1.10 Device [Shannon TPC-300] on usb-bcm2708_usb-1.2/input0 |