From 608c223eac65f3bb2e55ca86a4e9a3f5d906a40e Mon Sep 17 00:00:00 2001 From: Tcharp38 Date: Tue, 14 May 2024 14:34:45 +0200 Subject: [PATCH] Ezsp --- core/python/AbeilleEzsp.py | 23 +++++--------- core/python/AbeilleEzspAnswers.py | 50 +++++++++++++++++++++++-------- core/python/AbeilleEzspCmds.py | 18 +++++------ docs/dev/ezsp_notes.txt | 15 ++++++++++ docs/fr_FR/Changelog.md | 3 +- plugin_info/packages.json | 3 ++ 6 files changed, 75 insertions(+), 37 deletions(-) create mode 100644 docs/dev/ezsp_notes.txt diff --git a/core/python/AbeilleEzsp.py b/core/python/AbeilleEzsp.py index 37d7421f58..3ac535e269 100644 --- a/core/python/AbeilleEzsp.py +++ b/core/python/AbeilleEzsp.py @@ -175,27 +175,20 @@ def shutdown(): # NCP->Host: RSTACK frame => CONNECTED state # Host->NCP: version => Ask for desired protocol version (currently 13) +# Get IEEE addr: Read token 0x0002 (TOKEN_MFG_CUSTOM_EUI_64), size 8 bytes +# Get board name: Read token 0x002A or 0x0020 + sendCmd(serPort, "RST") while True: # Until RSTACK received - msg = bytes(0) - while True: - b = serPort.read(1) - msg += b - if (b[0] == 0x7e): - break - - status, cmd = ashDecode(msg) + status, cmd = ashRead(serPort) if (cmd["name"] == 'RSTACK'): break sendCmd(serPort, "version") -msg = bytes(0) -while True: - b = serPort.read(1) - msg += b - if (b[0] == 0x7e): +while True: # Until transmitted + status, cmd = ashRead(serPort) + if (cmd["name"] != "NAK"): break - -status, cmd = ashDecode(msg) + sendCmd(serPort, "version") # Retransmit logging.info('Exiting AbeilleEzsp') diff --git a/core/python/AbeilleEzspAnswers.py b/core/python/AbeilleEzspAnswers.py index 699db6dfe9..74cd6a0dab 100644 --- a/core/python/AbeilleEzspAnswers.py +++ b/core/python/AbeilleEzspAnswers.py @@ -2,6 +2,17 @@ # EmberZnet/EZSP answer decoding # Tcharp38 +# Read then decode ASH frame +def ashRead(serPort): + msg = bytes(0) + while True: + b = serPort.read(1) + msg += b + if (b[0] == 0x7e): + break + status, cmd = ashDecode(msg) + return status, cmd + # Reminder: ASH reserved values # 0x7E Flag Byte: Marks the end of a frame. When a Flag Byte is received, the data received since the last Flag Byte or CancelByte is tested to see whether it is a valid frame. # 0x7D Escape Byte: Indicates that the following byte is escaped. If the byte after the Escape Byte is not a reserved byte, bit 5 ofthe byte is complemented to restore its original value. If the byte after the Escape Byte is a reserved value, the EscapeByte has no effect. @@ -21,8 +32,15 @@ def ashDecode(msg): data = bytes(0) crc = bytes(0) crcSize = 2 # Always 2 + escaped = False + reservedBytes = [0x11, 0x13, 0x18, 0x1A, 0x7D, 0x7E] for i in range(len(msg)): b = msg[i] + if escaped: + print("ESCAPED byte 0x%X" % b) + b = b ^ (1 << 5) + # print("ESCAPED byte after 0x%X" % b) + escaped = False if (b == 0x11): print("XON") @@ -33,7 +51,9 @@ def ashDecode(msg): elif (b == 0x1A): print("CANCEL byte") elif (b == 0x7D): - print("ESCAPED byte") + unescaped = msg[i + 1] ^ (1 << 5) + if not (unescaped in reservedBytes): + escaped = True # Next byte is escaped elif (b == 0x7E): print("Flag byte") else: @@ -43,14 +63,16 @@ def ashDecode(msg): dataFieldSize = 0 if (ctrlByte >> 5) == 0x4: - print("ctrlByte=0x%02X => ACK" % ctrlByte) + # print("ctrlByte=0x%02X => ACK" % ctrlByte) + pass elif (ctrlByte >> 5) == 0x5: - print("ctrlByte=0x%02X => NAK" % ctrlByte) + # print("ctrlByte=0x%02X => NAK" % ctrlByte) + pass elif ctrlByte == 0xC1: - print("ctrlByte=0x%02X => RSTACK" % ctrlByte) + # print("ctrlByte=0x%02X => RSTACK" % ctrlByte) dataFieldSize = 2 elif ctrlByte == 0xC2: - print("ctrlByte=0x%02X => ERROR" % ctrlByte) + # print("ctrlByte=0x%02X => ERROR" % ctrlByte) dataFieldSize = 2 else: print("ctrlByte=0x%02X => DATA" % ctrlByte) @@ -72,7 +94,12 @@ def ashDecode(msg): print("CRC=%s" % crc.hex()) status = True - if (ctrlByte >> 5) == 0x4: + if (ctrlByte >> 7) == 0x0: # DATA + frmNum = (ctrlByte >> 4) & 0x7 + reTx = (ctrlByte >> 3) & 0x1 + ackNum = (ctrlByte >> 0) & 0x7 + cmd = {"name":"DATA", "frmNum": frmNum, "ackNum":ackNum, "reTx":reTx} + elif (ctrlByte >> 5) == 0x4: cmd = {"name":"ACK", "ackNum":ctrlByte & 0x7} elif (ctrlByte >> 5) == 0x5: cmd = {"name":"NAK", "ackNum":ctrlByte & 0x7} @@ -81,9 +108,7 @@ def ashDecode(msg): elif (ctrlByte == 0xC2): status, cmd = ashDecodeERROR(data) else: - frmNum = (ctrlByte >> 4) & 0x7 - ackNum = (ctrlByte >> 0) & 0x7 - cmd = {"name":"DATA", "frmNum": frmNum, "ackNum":ackNum} + cmd = {"name":"?"} print("cmd=", cmd) return status, cmd @@ -99,9 +124,10 @@ def ashDecodeRSTACK(data): # 0x0B Reset: Software # 0x51 Error: Exceeded maximum ACK timeout count # 0x80 Chip-specific error reset code + version = data[0] resetCode = data[1] - cmd = {"name":"RSTACK", "resetCode":resetCode} - print("RSTACK: ResetCode=0x%02X" % resetCode) + cmd = {"name":"RSTACK", "version":version, "resetCode":resetCode} + # print("RSTACK: ResetCode=0x%02X" % resetCode) return True, cmd def ashDecodeERROR(data): @@ -117,5 +143,5 @@ def ashDecodeERROR(data): # 0x51 Error: Exceeded maximum ACK timeout count # 0x80 Chip-specific error reset code cmd = {"name":"ERROR", "errCode":data[1]} - print("ERROR: ErrCode=0x%02X" % data[1]) + # print("ERROR: ErrCode=0x%02X" % data[1]) return True, cmd diff --git a/core/python/AbeilleEzspCmds.py b/core/python/AbeilleEzspCmds.py index bc11dac1f9..5c0b455f2a 100644 --- a/core/python/AbeilleEzspCmds.py +++ b/core/python/AbeilleEzspCmds.py @@ -2,18 +2,18 @@ # EmberZnet/EZSP commands # Tcharp38 -def sendCmd(serPort, cmd): - print("send(%s)" % cmd) +def sendCmd(serPort, cmdName): + print("send(%s)" % cmdName) - if (cmd == "RST"): - reset = [0xC0, 0x38, 0xBC, 0x7E] - dataBytes = bytes(reset) + if (cmdName == "RST"): + ezsp = [0xC0, 0x38, 0xBC, 0x7E] - elif (cmd == "version"): - version = [0x25, 0x00, 0x00, 0x00, 0x02, 0x1A, 0xAD, 0x7E] - dataBytes = bytes(version) + elif (cmdName == "version"): + ezsp = [0x25, 0x00, 0x00, 0x00, 0x02, 0x1A, 0xAD, 0x7E] else: - print("ERROR") + print("sendCmd() ERROR: Unknown cmd %s" % cmdName) + return + dataBytes = bytes(ezsp) serPort.write(dataBytes) diff --git a/docs/dev/ezsp_notes.txt b/docs/dev/ezsp_notes.txt new file mode 100644 index 0000000000..489c9fed85 --- /dev/null +++ b/docs/dev/ezsp_notes.txt @@ -0,0 +1,15 @@ +*** +*** Abeille developer internal doc +*** Emberznet/EZSP notes +*** Tcharp38 +*** + +EZSP_PROTOCOL_VERSION + 7.4.3.0 => 13 + 7.4.2.0 => 13 + 7.4.1.0 => 13 + 7.3.0.0 => 12 + 7.2.2.0 => 11 + 7.1.0.0 => 09 + 6.7.0.0 => 8 + and Secure EZSP Protocol Version 2 diff --git a/docs/fr_FR/Changelog.md b/docs/fr_FR/Changelog.md index 9b6e6d3dd8..b1459cad0d 100644 --- a/docs/fr_FR/Changelog.md +++ b/docs/fr_FR/Changelog.md @@ -23,7 +23,8 @@ - Amélioration aspect visuel. - Support multi-passerelles: Des tas de modifs internes. -- Interne: Cmd: Mise-à-jour 'getBindingTable()' (suppression champ 'address') +- Interne: Cmd: Mise-à-jour 'getBindingTable()' (suppression champ 'address') +- Dépendance nécessaire: Ajout 'pyserial'. ## 240501-STABLE-1 diff --git a/plugin_info/packages.json b/plugin_info/packages.json index ea7d264d65..68e4d53455 100644 --- a/plugin_info/packages.json +++ b/plugin_info/packages.json @@ -2,6 +2,9 @@ "apt": { "python3": {} }, + "pip3": { + "pyserial": { "reinstall": true } + }, "post-install": { "restart_apache": true }