Skip to content

Commit

Permalink
Ezsp
Browse files Browse the repository at this point in the history
  • Loading branch information
tcharp38 committed May 14, 2024
1 parent 4f9ccdf commit 608c223
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 37 deletions.
23 changes: 8 additions & 15 deletions core/python/AbeilleEzsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
50 changes: 38 additions & 12 deletions core/python/AbeilleEzspAnswers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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")
Expand All @@ -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:
Expand All @@ -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)
Expand All @@ -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}
Expand All @@ -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

Expand All @@ -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):
Expand All @@ -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
18 changes: 9 additions & 9 deletions core/python/AbeilleEzspCmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
15 changes: 15 additions & 0 deletions docs/dev/ezsp_notes.txt
Original file line number Diff line number Diff line change
@@ -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
3 changes: 2 additions & 1 deletion docs/fr_FR/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions plugin_info/packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"apt": {
"python3": {}
},
"pip3": {
"pyserial": { "reinstall": true }
},
"post-install": {
"restart_apache": true
}
Expand Down

0 comments on commit 608c223

Please sign in to comment.