mirror of
https://github.com/markqvist/Reticulum.git
synced 2024-11-22 13:40:19 +00:00
Compare commits
8 Commits
583e65419e
...
0b66649158
Author | SHA1 | Date | |
---|---|---|---|
|
0b66649158 | ||
|
e28dd6e14a | ||
|
0a15b4c6c1 | ||
|
62db09571d | ||
|
444ae0206b | ||
|
4b07e30b9d | ||
|
746a38f818 | ||
|
c230eceaa6 |
@ -181,78 +181,90 @@ class AutoInterface(Interface):
|
|||||||
|
|
||||||
suitable_interfaces = 0
|
suitable_interfaces = 0
|
||||||
for ifname in self.list_interfaces():
|
for ifname in self.list_interfaces():
|
||||||
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
try:
|
||||||
RNS.log(str(self)+" skipping Darwin AWDL or tethering interface "+str(ifname), RNS.LOG_EXTREME)
|
if RNS.vendor.platformutils.is_darwin() and ifname in AutoInterface.DARWIN_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
||||||
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
|
RNS.log(str(self)+" skipping Darwin AWDL or tethering interface "+str(ifname), RNS.LOG_EXTREME)
|
||||||
RNS.log(str(self)+" skipping Darwin loopback interface "+str(ifname), RNS.LOG_EXTREME)
|
elif RNS.vendor.platformutils.is_darwin() and ifname == "lo0":
|
||||||
elif RNS.vendor.platformutils.is_android() and ifname in AutoInterface.ANDROID_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
RNS.log(str(self)+" skipping Darwin loopback interface "+str(ifname), RNS.LOG_EXTREME)
|
||||||
RNS.log(str(self)+" skipping Android system interface "+str(ifname), RNS.LOG_EXTREME)
|
elif RNS.vendor.platformutils.is_android() and ifname in AutoInterface.ANDROID_IGNORE_IFS and not ifname in self.allowed_interfaces:
|
||||||
elif ifname in self.ignored_interfaces:
|
RNS.log(str(self)+" skipping Android system interface "+str(ifname), RNS.LOG_EXTREME)
|
||||||
RNS.log(str(self)+" ignoring disallowed interface "+str(ifname), RNS.LOG_EXTREME)
|
elif ifname in self.ignored_interfaces:
|
||||||
elif ifname in AutoInterface.ALL_IGNORE_IFS:
|
RNS.log(str(self)+" ignoring disallowed interface "+str(ifname), RNS.LOG_EXTREME)
|
||||||
RNS.log(str(self)+" skipping interface "+str(ifname), RNS.LOG_EXTREME)
|
elif ifname in AutoInterface.ALL_IGNORE_IFS:
|
||||||
else:
|
RNS.log(str(self)+" skipping interface "+str(ifname), RNS.LOG_EXTREME)
|
||||||
if len(self.allowed_interfaces) > 0 and not ifname in self.allowed_interfaces:
|
|
||||||
RNS.log(str(self)+" ignoring interface "+str(ifname)+" since it was not allowed", RNS.LOG_EXTREME)
|
|
||||||
else:
|
else:
|
||||||
addresses = self.list_addresses(ifname)
|
if len(self.allowed_interfaces) > 0 and not ifname in self.allowed_interfaces:
|
||||||
if self.netinfo.AF_INET6 in addresses:
|
RNS.log(str(self)+" ignoring interface "+str(ifname)+" since it was not allowed", RNS.LOG_EXTREME)
|
||||||
link_local_addr = None
|
else:
|
||||||
for address in addresses[self.netinfo.AF_INET6]:
|
addresses = self.list_addresses(ifname)
|
||||||
if "addr" in address:
|
if self.netinfo.AF_INET6 in addresses:
|
||||||
if address["addr"].startswith("fe80:"):
|
link_local_addr = None
|
||||||
link_local_addr = self.descope_linklocal(address["addr"])
|
for address in addresses[self.netinfo.AF_INET6]:
|
||||||
self.link_local_addresses.append(link_local_addr)
|
if "addr" in address:
|
||||||
self.adopted_interfaces[ifname] = link_local_addr
|
if address["addr"].startswith("fe80:"):
|
||||||
self.multicast_echoes[ifname] = time.time()
|
link_local_addr = self.descope_linklocal(address["addr"])
|
||||||
RNS.log(str(self)+" Selecting link-local address "+str(link_local_addr)+" for interface "+str(ifname), RNS.LOG_EXTREME)
|
self.link_local_addresses.append(link_local_addr)
|
||||||
|
self.adopted_interfaces[ifname] = link_local_addr
|
||||||
if link_local_addr == None:
|
self.multicast_echoes[ifname] = time.time()
|
||||||
RNS.log(str(self)+" No link-local IPv6 address configured for "+str(ifname)+", skipping interface", RNS.LOG_EXTREME)
|
nice_name = self.netinfo.interface_name_to_nice_name(ifname)
|
||||||
else:
|
if nice_name != None and nice_name != ifname:
|
||||||
mcast_addr = self.mcast_discovery_address
|
RNS.log(f"{self} Selecting link-local address {link_local_addr} for interface {nice_name} / {ifname}", RNS.LOG_EXTREME)
|
||||||
RNS.log(str(self)+" Creating multicast discovery listener on "+str(ifname)+" with address "+str(mcast_addr), RNS.LOG_EXTREME)
|
else:
|
||||||
|
RNS.log(f"{self} Selecting link-local address {link_local_addr} for interface {ifname}", RNS.LOG_EXTREME)
|
||||||
# Struct with interface index
|
|
||||||
if_struct = struct.pack("I", self.interface_name_to_index(ifname))
|
|
||||||
|
|
||||||
# Set up multicast socket
|
|
||||||
discovery_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
|
||||||
discovery_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
if hasattr(socket, "SO_REUSEPORT"):
|
|
||||||
discovery_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
|
||||||
discovery_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, if_struct)
|
|
||||||
|
|
||||||
# Join multicast group
|
|
||||||
mcast_group = socket.inet_pton(socket.AF_INET6, mcast_addr) + if_struct
|
|
||||||
discovery_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mcast_group)
|
|
||||||
|
|
||||||
# Bind socket
|
|
||||||
if RNS.vendor.platformutils.is_windows():
|
|
||||||
|
|
||||||
# window throws "[WinError 10049] The requested address is not valid in its context"
|
|
||||||
# when trying to use the multicast address as host, or when providing interface index
|
|
||||||
# passing an empty host appears to work, but probably not exactly how we want it to...
|
|
||||||
discovery_socket.bind(('', self.discovery_port))
|
|
||||||
|
|
||||||
|
if link_local_addr == None:
|
||||||
|
RNS.log(str(self)+" No link-local IPv6 address configured for "+str(ifname)+", skipping interface", RNS.LOG_EXTREME)
|
||||||
else:
|
else:
|
||||||
|
mcast_addr = self.mcast_discovery_address
|
||||||
|
RNS.log(str(self)+" Creating multicast discovery listener on "+str(ifname)+" with address "+str(mcast_addr), RNS.LOG_EXTREME)
|
||||||
|
|
||||||
|
# Struct with interface index
|
||||||
|
if_struct = struct.pack("I", self.interface_name_to_index(ifname))
|
||||||
|
|
||||||
|
# Set up multicast socket
|
||||||
|
discovery_socket = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
discovery_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
if hasattr(socket, "SO_REUSEPORT"):
|
||||||
|
discovery_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
||||||
|
discovery_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, if_struct)
|
||||||
|
|
||||||
|
# Join multicast group
|
||||||
|
mcast_group = socket.inet_pton(socket.AF_INET6, mcast_addr) + if_struct
|
||||||
|
discovery_socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mcast_group)
|
||||||
|
|
||||||
|
# Bind socket
|
||||||
|
if RNS.vendor.platformutils.is_windows():
|
||||||
|
|
||||||
|
# window throws "[WinError 10049] The requested address is not valid in its context"
|
||||||
|
# when trying to use the multicast address as host, or when providing interface index
|
||||||
|
# passing an empty host appears to work, but probably not exactly how we want it to...
|
||||||
|
discovery_socket.bind(('', self.discovery_port))
|
||||||
|
|
||||||
if self.discovery_scope == AutoInterface.SCOPE_LINK:
|
|
||||||
addr_info = socket.getaddrinfo(mcast_addr+"%"+ifname, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
|
||||||
else:
|
else:
|
||||||
addr_info = socket.getaddrinfo(mcast_addr, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
|
||||||
|
|
||||||
discovery_socket.bind(addr_info[0][4])
|
if self.discovery_scope == AutoInterface.SCOPE_LINK:
|
||||||
|
addr_info = socket.getaddrinfo(mcast_addr+"%"+ifname, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
else:
|
||||||
|
addr_info = socket.getaddrinfo(mcast_addr, self.discovery_port, socket.AF_INET6, socket.SOCK_DGRAM)
|
||||||
|
|
||||||
# Set up thread for discovery packets
|
discovery_socket.bind(addr_info[0][4])
|
||||||
def discovery_loop():
|
|
||||||
self.discovery_handler(discovery_socket, ifname)
|
|
||||||
|
|
||||||
thread = threading.Thread(target=discovery_loop)
|
# Set up thread for discovery packets
|
||||||
thread.daemon = True
|
def discovery_loop():
|
||||||
thread.start()
|
self.discovery_handler(discovery_socket, ifname)
|
||||||
|
|
||||||
suitable_interfaces += 1
|
thread = threading.Thread(target=discovery_loop)
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
suitable_interfaces += 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
nice_name = self.netinfo.interface_name_to_nice_name(ifname)
|
||||||
|
if nice_name != None and nice_name != ifname:
|
||||||
|
RNS.log(f"Could not configure the system interface {nice_name} / {ifname} for use with {self}, skipping it. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
else:
|
||||||
|
RNS.log(f"Could not configure the system interface {ifname} for use with {self}, skipping it. The contained exception was: {e}", RNS.LOG_ERROR)
|
||||||
|
|
||||||
if suitable_interfaces == 0:
|
if suitable_interfaces == 0:
|
||||||
RNS.log(str(self)+" could not autoconfigure. This interface currently provides no connectivity.", RNS.LOG_WARNING)
|
RNS.log(str(self)+" could not autoconfigure. This interface currently provides no connectivity.", RNS.LOG_WARNING)
|
||||||
|
@ -128,6 +128,10 @@ class ROM():
|
|||||||
MCU_ESP32 = 0x81
|
MCU_ESP32 = 0x81
|
||||||
MCU_NRF52 = 0x71
|
MCU_NRF52 = 0x71
|
||||||
|
|
||||||
|
PRODUCT_RAK4631 = 0x10
|
||||||
|
MODEL_11 = 0x11
|
||||||
|
MODEL_12 = 0x12
|
||||||
|
|
||||||
PRODUCT_RNODE = 0x03
|
PRODUCT_RNODE = 0x03
|
||||||
MODEL_A1 = 0xA1
|
MODEL_A1 = 0xA1
|
||||||
MODEL_A6 = 0xA6
|
MODEL_A6 = 0xA6
|
||||||
@ -196,7 +200,7 @@ class ROM():
|
|||||||
BOARD_GENERIC_ESP32 = 0x35
|
BOARD_GENERIC_ESP32 = 0x35
|
||||||
BOARD_LORA32_V2_0 = 0x36
|
BOARD_LORA32_V2_0 = 0x36
|
||||||
BOARD_LORA32_V2_1 = 0x37
|
BOARD_LORA32_V2_1 = 0x37
|
||||||
BOARD_RAK4630 = 0x51
|
BOARD_RAK4631 = 0x51
|
||||||
|
|
||||||
mapped_product = ROM.PRODUCT_RNODE
|
mapped_product = ROM.PRODUCT_RNODE
|
||||||
products = {
|
products = {
|
||||||
@ -208,22 +212,25 @@ products = {
|
|||||||
ROM.PRODUCT_T32_21: "LilyGO LoRa32 v2.1",
|
ROM.PRODUCT_T32_21: "LilyGO LoRa32 v2.1",
|
||||||
ROM.PRODUCT_H32_V2: "Heltec LoRa32 v2",
|
ROM.PRODUCT_H32_V2: "Heltec LoRa32 v2",
|
||||||
ROM.PRODUCT_H32_V3: "Heltec LoRa32 v3",
|
ROM.PRODUCT_H32_V3: "Heltec LoRa32 v3",
|
||||||
|
ROM.PRODUCT_RAK4631: "RAK4631",
|
||||||
}
|
}
|
||||||
|
|
||||||
platforms = {
|
platforms = {
|
||||||
ROM.PLATFORM_AVR: "AVR",
|
ROM.PLATFORM_AVR: "AVR",
|
||||||
ROM.PLATFORM_ESP32:"ESP32",
|
ROM.PLATFORM_ESP32:"ESP32",
|
||||||
ROM.PLATFORM_NRF52:"NRF52",
|
ROM.PLATFORM_NRF52: "NRF52",
|
||||||
}
|
}
|
||||||
|
|
||||||
mcus = {
|
mcus = {
|
||||||
ROM.MCU_1284P: "ATmega1284P",
|
ROM.MCU_1284P: "ATmega1284P",
|
||||||
ROM.MCU_2560:"ATmega2560",
|
ROM.MCU_2560:"ATmega2560",
|
||||||
ROM.MCU_ESP32:"Espressif Systems ESP32",
|
ROM.MCU_ESP32:"Espressif Systems ESP32",
|
||||||
ROM.MCU_NRF52:"Nordic nRF52840",
|
ROM.MCU_NRF52: "Nordic Semiconductor nRF52840",
|
||||||
}
|
}
|
||||||
|
|
||||||
models = {
|
models = {
|
||||||
|
0x11: [430000000, 510000000, 22, "430 - 510 MHz", "rnode_firmware_rak4631.zip", "SX1262"],
|
||||||
|
0x12: [779000000, 928000000, 22, "779 - 928 MHz", "rnode_firmware_rak4631.zip", "SX1262"],
|
||||||
0xA4: [410000000, 525000000, 14, "410 - 525 MHz", "rnode_firmware.hex", "SX1278"],
|
0xA4: [410000000, 525000000, 14, "410 - 525 MHz", "rnode_firmware.hex", "SX1278"],
|
||||||
0xA9: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware.hex", "SX1276"],
|
0xA9: [820000000, 1020000000, 17, "820 - 1020 MHz", "rnode_firmware.hex", "SX1276"],
|
||||||
0xA1: [410000000, 525000000, 22, "410 - 525 MHz", "rnode_firmware_t3s3.zip", "SX1268"],
|
0xA1: [410000000, 525000000, 22, "410 - 525 MHz", "rnode_firmware_t3s3.zip", "SX1268"],
|
||||||
@ -306,6 +313,7 @@ class RNode():
|
|||||||
self.bandwidth = None
|
self.bandwidth = None
|
||||||
|
|
||||||
self.detected = None
|
self.detected = None
|
||||||
|
self.usb_serial_id = None
|
||||||
|
|
||||||
self.platform = None
|
self.platform = None
|
||||||
self.mcu = None
|
self.mcu = None
|
||||||
@ -324,6 +332,7 @@ class RNode():
|
|||||||
self.checksum = None
|
self.checksum = None
|
||||||
self.device_hash = None
|
self.device_hash = None
|
||||||
self.firmware_hash = None
|
self.firmware_hash = None
|
||||||
|
self.firmware_hash_target = None
|
||||||
self.signature = None
|
self.signature = None
|
||||||
self.signature_valid = False
|
self.signature_valid = False
|
||||||
self.locally_signed = False
|
self.locally_signed = False
|
||||||
@ -471,6 +480,8 @@ class RNode():
|
|||||||
escape = False
|
escape = False
|
||||||
command_buffer = command_buffer+bytes([byte])
|
command_buffer = command_buffer+bytes([byte])
|
||||||
if (len(command_buffer) == 33):
|
if (len(command_buffer) == 33):
|
||||||
|
if command_buffer[0] == 0x01:
|
||||||
|
self.firmware_hash_target = command_buffer[1:]
|
||||||
if command_buffer[0] == 0x02:
|
if command_buffer[0] == 0x02:
|
||||||
self.firmware_hash = command_buffer[1:]
|
self.firmware_hash = command_buffer[1:]
|
||||||
|
|
||||||
@ -588,7 +599,7 @@ class RNode():
|
|||||||
self.version = str(self.major_version)+"."+minstr
|
self.version = str(self.major_version)+"."+minstr
|
||||||
|
|
||||||
def detect(self):
|
def detect(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND, KISS.CMD_BOARD, 0x00, KISS.FEND, KISS.CMD_DEV_HASH, 0x01, KISS.FEND, KISS.CMD_HASHES, 0x02, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_DETECT, KISS.DETECT_REQ, KISS.FEND, KISS.CMD_FW_VERSION, 0x00, KISS.FEND, KISS.CMD_PLATFORM, 0x00, KISS.FEND, KISS.CMD_MCU, 0x00, KISS.FEND, KISS.CMD_BOARD, 0x00, KISS.FEND, KISS.CMD_DEV_HASH, 0x01, KISS.FEND, KISS.CMD_HASHES, 0x01, KISS.FEND, KISS.CMD_HASHES, 0x02, KISS.FEND])
|
||||||
written = self.serial.write(kiss_command)
|
written = self.serial.write(kiss_command)
|
||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while detecting hardware for "+self(str))
|
raise IOError("An IO error occurred while detecting hardware for "+self(str))
|
||||||
@ -735,6 +746,10 @@ class RNode():
|
|||||||
if written != len(kiss_command):
|
if written != len(kiss_command):
|
||||||
raise IOError("An IO error occurred while wiping EEPROM")
|
raise IOError("An IO error occurred while wiping EEPROM")
|
||||||
sleep(13);
|
sleep(13);
|
||||||
|
# Due to the current janky emulated EEPROM implementation for the
|
||||||
|
# RAK4631, extra time must be given to allow for writing.
|
||||||
|
if self.board == ROM.BOARD_RAK4631:
|
||||||
|
sleep(10)
|
||||||
|
|
||||||
def hard_reset(self):
|
def hard_reset(self):
|
||||||
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
kiss_command = bytes([KISS.FEND, KISS.CMD_RESET, 0xf8, KISS.FEND])
|
||||||
@ -1249,6 +1264,8 @@ def main():
|
|||||||
parser.add_argument("-k", "--key", action="store_true", help="Generate a new signing key and exit") #
|
parser.add_argument("-k", "--key", action="store_true", help="Generate a new signing key and exit") #
|
||||||
parser.add_argument("-S", "--sign", action="store_true", help="Display public part of signing key")
|
parser.add_argument("-S", "--sign", action="store_true", help="Display public part of signing key")
|
||||||
parser.add_argument("-H", "--firmware-hash", action="store", help="Display installed firmware hash")
|
parser.add_argument("-H", "--firmware-hash", action="store", help="Display installed firmware hash")
|
||||||
|
parser.add_argument("-K", "--get-target-firmware-hash", action="store_true", help=argparse.SUPPRESS) # Get target firmware hash from device
|
||||||
|
parser.add_argument("-L", "--get-firmware-hash", action="store_true", help=argparse.SUPPRESS) # Get calculated firmware hash from device
|
||||||
parser.add_argument("--platform", action="store", metavar="platform", type=str, default=None, help="Platform specification for device bootstrap")
|
parser.add_argument("--platform", action="store", metavar="platform", type=str, default=None, help="Platform specification for device bootstrap")
|
||||||
parser.add_argument("--product", action="store", metavar="product", type=str, default=None, help="Product specification for device bootstrap") #
|
parser.add_argument("--product", action="store", metavar="product", type=str, default=None, help="Product specification for device bootstrap") #
|
||||||
parser.add_argument("--model", action="store", metavar="model", type=str, default=None, help="Model code for device bootstrap")
|
parser.add_argument("--model", action="store", metavar="model", type=str, default=None, help="Model code for device bootstrap")
|
||||||
@ -1400,6 +1417,7 @@ def main():
|
|||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
rnode = RNode(rnode_serial)
|
rnode = RNode(rnode_serial)
|
||||||
|
rnode.usb_serial_id = port_serialno
|
||||||
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
||||||
try:
|
try:
|
||||||
rnode.device_probe()
|
rnode.device_probe()
|
||||||
@ -1412,54 +1430,58 @@ def main():
|
|||||||
else:
|
else:
|
||||||
RNS.log("Could not detect a connected RNode")
|
RNS.log("Could not detect a connected RNode")
|
||||||
|
|
||||||
if rnode.provisioned:
|
if rnode.platform == ROM.PLATFORM_ESP32:
|
||||||
if not rnode.signature_valid:
|
if rnode.provisioned:
|
||||||
print("\nThe device signature in this RNode is unknown and cannot be verified. It is still")
|
if not rnode.signature_valid:
|
||||||
print("possible to extract the firmware from it, but you should make absolutely sure that")
|
print("\nThe device signature in this RNode is unknown and cannot be verified. It is still")
|
||||||
print("it comes from a trusted source. It is possible that someone could have modified the")
|
print("possible to extract the firmware from it, but you should make absolutely sure that")
|
||||||
print("firmware. If that is the case, these modifications will propagate to any new RNodes")
|
print("it comes from a trusted source. It is possible that someone could have modified the")
|
||||||
print("descendent from this one!")
|
print("firmware. If that is the case, these modifications will propagate to any new RNodes")
|
||||||
print("\nHit enter if you are sure you want to continue.")
|
print("descendent from this one!")
|
||||||
input()
|
print("\nHit enter if you are sure you want to continue.")
|
||||||
|
input()
|
||||||
|
|
||||||
if rnode.firmware_hash != None:
|
if rnode.firmware_hash != None:
|
||||||
extracted_hash = rnode.firmware_hash
|
extracted_hash = rnode.firmware_hash
|
||||||
extracted_version = rnode.version
|
extracted_version = rnode.version
|
||||||
rnode.disconnect()
|
rnode.disconnect()
|
||||||
v_str = str(extracted_version)+" "+RNS.hexrep(extracted_hash, delimit=False)
|
v_str = str(extracted_version)+" "+RNS.hexrep(extracted_hash, delimit=False)
|
||||||
print("\nFound RNode Firmvare v"+v_str)
|
print("\nFound RNode Firmvare v"+v_str)
|
||||||
|
|
||||||
print("\nReady to extract firmware images from the RNode")
|
print("\nReady to extract firmware images from the RNode")
|
||||||
print("Press enter to start the extraction process")
|
print("Press enter to start the extraction process")
|
||||||
input()
|
input()
|
||||||
extract_recovery_esptool()
|
extract_recovery_esptool()
|
||||||
|
|
||||||
hash_f = open(EXT_DIR+"/extracted_rnode_firmware.version", "wb")
|
hash_f = open(EXT_DIR+"/extracted_rnode_firmware.version", "wb")
|
||||||
hash_f.write(v_str.encode("utf-8"))
|
hash_f.write(v_str.encode("utf-8"))
|
||||||
hash_f.close()
|
hash_f.close()
|
||||||
|
|
||||||
extraction_parts = [
|
extraction_parts = [
|
||||||
("bootloader", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x1000 0x4650 \""+EXT_DIR+"/extracted_rnode_firmware.bootloader\""),
|
("bootloader", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x1000 0x4650 \""+EXT_DIR+"/extracted_rnode_firmware.bootloader\""),
|
||||||
("partition table", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x8000 0xC00 \""+EXT_DIR+"/extracted_rnode_firmware.partitions\""),
|
("partition table", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x8000 0xC00 \""+EXT_DIR+"/extracted_rnode_firmware.partitions\""),
|
||||||
("app boot", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0xe000 0x2000 \""+EXT_DIR+"/extracted_rnode_firmware.boot_app0\""),
|
("app boot", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0xe000 0x2000 \""+EXT_DIR+"/extracted_rnode_firmware.boot_app0\""),
|
||||||
("application image", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x10000 0x200000 \""+EXT_DIR+"/extracted_rnode_firmware.bin\""),
|
("application image", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x10000 0x200000 \""+EXT_DIR+"/extracted_rnode_firmware.bin\""),
|
||||||
("console image", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x210000 0x1F0000 \""+EXT_DIR+"/extracted_console_image.bin\""),
|
("console image", "python \""+CNF_DIR+"/recovery_esptool.py\" --chip esp32 --port "+port_path+" --baud "+args.baud_flash+" --before default_reset --after hard_reset read_flash 0x210000 0x1F0000 \""+EXT_DIR+"/extracted_console_image.bin\""),
|
||||||
]
|
]
|
||||||
import subprocess, shlex
|
import subprocess, shlex
|
||||||
for part, command in extraction_parts:
|
for part, command in extraction_parts:
|
||||||
print("Extracting "+part+"...")
|
print("Extracting "+part+"...")
|
||||||
if subprocess.call(shlex.split(command), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) != 0:
|
if subprocess.call(shlex.split(command), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) != 0:
|
||||||
print("The extraction failed, the following command did not complete successfully:\n"+command)
|
print("The extraction failed, the following command did not complete successfully:\n"+command)
|
||||||
graceful_exit(182)
|
exit(182)
|
||||||
|
|
||||||
print("\nFirmware successfully extracted!")
|
print("\nFirmware successfully extracted!")
|
||||||
print("\nYou can now use this firmware to update or autoinstall other RNodes")
|
print("\nYou can now use this firmware to update or autoinstall other RNodes")
|
||||||
graceful_exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
print("Could not read firmware information from device")
|
print("Could not read firmware information from device")
|
||||||
|
|
||||||
print("\nRNode firmware extraction failed")
|
print("\nRNode firmware extraction failed")
|
||||||
graceful_exit(180)
|
graceful_exit(180)
|
||||||
|
else:
|
||||||
|
print("\nFirmware extraction is currently only supported on ESP32-based RNodes.")
|
||||||
|
graceful_exit(170)
|
||||||
|
|
||||||
if args.autoinstall:
|
if args.autoinstall:
|
||||||
clear()
|
clear()
|
||||||
@ -1533,6 +1555,7 @@ def main():
|
|||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
rnode = RNode(rnode_serial)
|
rnode = RNode(rnode_serial)
|
||||||
|
rnode.usb_serial_id = port_serialno
|
||||||
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
||||||
try:
|
try:
|
||||||
rnode.device_probe()
|
rnode.device_probe()
|
||||||
@ -1577,6 +1600,7 @@ def main():
|
|||||||
print("[7] Heltec LoRa32 v2")
|
print("[7] Heltec LoRa32 v2")
|
||||||
print("[8] Heltec LoRa32 v3")
|
print("[8] Heltec LoRa32 v3")
|
||||||
#print("[9] LilyGO LoRa T3S3")
|
#print("[9] LilyGO LoRa T3S3")
|
||||||
|
print("[10] RAK4631")
|
||||||
print(" .")
|
print(" .")
|
||||||
print(" / \\ Select one of these options if you want to easily turn")
|
print(" / \\ Select one of these options if you want to easily turn")
|
||||||
print(" | a supported development board into an RNode.")
|
print(" | a supported development board into an RNode.")
|
||||||
@ -1588,7 +1612,7 @@ def main():
|
|||||||
try:
|
try:
|
||||||
c_dev = int(input())
|
c_dev = int(input())
|
||||||
c_mod = False
|
c_mod = False
|
||||||
if c_dev < 1 or c_dev > 9:
|
if c_dev < 1 or c_dev > 10:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
elif c_dev == 1:
|
elif c_dev == 1:
|
||||||
selected_product = ROM.PRODUCT_RNODE
|
selected_product = ROM.PRODUCT_RNODE
|
||||||
@ -1717,6 +1741,15 @@ def main():
|
|||||||
print("")
|
print("")
|
||||||
print("Please note that Bluetooth is currently not implemented on this board.")
|
print("Please note that Bluetooth is currently not implemented on this board.")
|
||||||
print("")
|
print("")
|
||||||
|
elif c_dev == 10:
|
||||||
|
selected_product = ROM.PRODUCT_RAK4631
|
||||||
|
clear()
|
||||||
|
print("")
|
||||||
|
print("---------------------------------------------------------------------------")
|
||||||
|
print(" RAK4631 RNode Installer")
|
||||||
|
print("")
|
||||||
|
print("Important! Using RNode firmware on RAKwireless devices should currently be")
|
||||||
|
print("considered experimental. It is not intended for production or critical use.")
|
||||||
print("The currently supplied firmware is provided AS-IS as a courtesey to those")
|
print("The currently supplied firmware is provided AS-IS as a courtesey to those")
|
||||||
print("who would like to experiment with it. Hit enter to continue.")
|
print("who would like to experiment with it. Hit enter to continue.")
|
||||||
print("---------------------------------------------------------------------------")
|
print("---------------------------------------------------------------------------")
|
||||||
@ -1969,11 +2002,6 @@ def main():
|
|||||||
elif selected_product == ROM.PRODUCT_H32_V3:
|
elif selected_product == ROM.PRODUCT_H32_V3:
|
||||||
selected_mcu = ROM.MCU_ESP32
|
selected_mcu = ROM.MCU_ESP32
|
||||||
print("\nWhat band is this Heltec LoRa32 V3 for?\n")
|
print("\nWhat band is this Heltec LoRa32 V3 for?\n")
|
||||||
print("[1] 433 MHz")
|
|
||||||
print("[2] 868 MHz")
|
|
||||||
print("[3] 915 MHz")
|
|
||||||
print("[4] 923 MHz")
|
|
||||||
print("\n? ", end="")
|
|
||||||
try:
|
try:
|
||||||
c_model = int(input())
|
c_model = int(input())
|
||||||
if c_model < 1 or c_model > 4:
|
if c_model < 1 or c_model > 4:
|
||||||
@ -1984,6 +2012,27 @@ def main():
|
|||||||
elif c_model > 1:
|
elif c_model > 1:
|
||||||
selected_model = ROM.MODEL_CA
|
selected_model = ROM.MODEL_CA
|
||||||
selected_platform = ROM.PLATFORM_ESP32
|
selected_platform = ROM.PLATFORM_ESP32
|
||||||
|
except Exception as e:
|
||||||
|
print("That band does not exist, exiting now.")
|
||||||
|
exit()
|
||||||
|
elif selected_product == ROM.PRODUCT_RAK4631:
|
||||||
|
selected_mcu = ROM.MCU_NRF52
|
||||||
|
print("\nWhat band is this RAK4631 for?\n")
|
||||||
|
print("[1] 433 MHz")
|
||||||
|
print("[2] 868 MHz")
|
||||||
|
print("[3] 915 MHz")
|
||||||
|
print("[4] 923 MHz")
|
||||||
|
print("\n? ", end="")
|
||||||
|
try:
|
||||||
|
c_model = int(input())
|
||||||
|
if c_model < 1 or c_model > 4:
|
||||||
|
raise ValueError()
|
||||||
|
elif c_model == 1:
|
||||||
|
selected_model = ROM.MODEL_11
|
||||||
|
selected_platform = ROM.PLATFORM_NRF52
|
||||||
|
elif c_model > 1:
|
||||||
|
selected_model = ROM.MODEL_12
|
||||||
|
selected_platform = ROM.PLATFORM_NRF52
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("That band does not exist, exiting now.")
|
print("That band does not exist, exiting now.")
|
||||||
graceful_exit()
|
graceful_exit()
|
||||||
@ -2173,16 +2222,26 @@ def main():
|
|||||||
if not args.autoinstall:
|
if not args.autoinstall:
|
||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
def get_partition_hash(partition_file):
|
def get_partition_hash(platform, partition_file):
|
||||||
try:
|
try:
|
||||||
firmware_data = open(partition_file, "rb").read()
|
if platform == ROM.PLATFORM_ESP32 or platform == ROM.PLATFORM_AVR:
|
||||||
calc_hash = hashlib.sha256(firmware_data[0:-32]).digest()
|
firmware_data = open(partition_file, "rb").read()
|
||||||
part_hash = firmware_data[-32:]
|
# Calculate the digest manually and see if it matches the
|
||||||
|
# SHA256 digest included in the ESP32 image.
|
||||||
|
calc_hash = hashlib.sha256(firmware_data[0:-32]).digest()
|
||||||
|
part_hash = firmware_data[-32:]
|
||||||
|
|
||||||
if calc_hash == part_hash:
|
if calc_hash == part_hash:
|
||||||
return part_hash
|
return part_hash
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
elif platform == ROM.PLATFORM_NRF52:
|
||||||
|
# Calculate digest manually, as it is not included in the image.
|
||||||
|
firmware_data = open(partition_file, "rb")
|
||||||
|
hash = hashlib.file_digest(firmware_data, 'sha256').digest()
|
||||||
|
firmware_data.close()
|
||||||
|
return hash
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Could not calculate firmware partition hash. The contained exception was:")
|
RNS.log("Could not calculate firmware partition hash. The contained exception was:")
|
||||||
RNS.log(str(e))
|
RNS.log(str(e))
|
||||||
@ -2684,6 +2743,21 @@ def main():
|
|||||||
RNS.log("Please install \""+flasher+"\" and try again.")
|
RNS.log("Please install \""+flasher+"\" and try again.")
|
||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
|
elif platform == ROM.PLATFORM_NRF52:
|
||||||
|
flasher = "adafruit-nrfutil"
|
||||||
|
if which(flasher) is not None:
|
||||||
|
return [flasher, "dfu", "serial", "--package", UPD_DIR+"/"+selected_version+"/"+fw_filename, "-p", args.port, "-b", "115200", "-t", "1200"]
|
||||||
|
else:
|
||||||
|
RNS.log("")
|
||||||
|
RNS.log("You do not currently have the \""+flasher+"\" program installed on your system.")
|
||||||
|
RNS.log("Unfortunately, that means we can't proceed, since it is needed to flash your")
|
||||||
|
RNS.log("board. You can install it via your package manager, for example:")
|
||||||
|
RNS.log("")
|
||||||
|
RNS.log(" pip3 install --user adafruit-nrfutil")
|
||||||
|
RNS.log("")
|
||||||
|
RNS.log("Please install \""+flasher+"\" and try again.")
|
||||||
|
graceful_exit()
|
||||||
|
|
||||||
if args.port:
|
if args.port:
|
||||||
wants_fw_provision = False
|
wants_fw_provision = False
|
||||||
if args.flash:
|
if args.flash:
|
||||||
@ -2745,6 +2819,11 @@ def main():
|
|||||||
wants_fw_provision = True
|
wants_fw_provision = True
|
||||||
RNS.log("Waiting for ESP32 reset...")
|
RNS.log("Waiting for ESP32 reset...")
|
||||||
time.sleep(7)
|
time.sleep(7)
|
||||||
|
if args.platform == ROM.PLATFORM_NRF52:
|
||||||
|
wants_fw_provision = True
|
||||||
|
RNS.log("Waiting for NRF52 reset...")
|
||||||
|
# Don't need to wait as long this time.
|
||||||
|
time.sleep(5)
|
||||||
else:
|
else:
|
||||||
RNS.log("Error from flasher ("+str(flash_status)+") while writing.")
|
RNS.log("Error from flasher ("+str(flash_status)+") while writing.")
|
||||||
RNS.log("Some boards have trouble flashing at high speeds, and you can")
|
RNS.log("Some boards have trouble flashing at high speeds, and you can")
|
||||||
@ -2770,6 +2849,11 @@ def main():
|
|||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
rnode = RNode(rnode_serial)
|
rnode = RNode(rnode_serial)
|
||||||
|
ports = list_ports.comports()
|
||||||
|
for port in ports:
|
||||||
|
if port.device == args.port:
|
||||||
|
rnode.usb_serial_id = port.serial_number
|
||||||
|
break
|
||||||
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -2788,7 +2872,10 @@ def main():
|
|||||||
if args.eeprom_wipe:
|
if args.eeprom_wipe:
|
||||||
RNS.log("WARNING: EEPROM is being wiped! Power down device NOW if you do not want this!")
|
RNS.log("WARNING: EEPROM is being wiped! Power down device NOW if you do not want this!")
|
||||||
rnode.wipe_eeprom()
|
rnode.wipe_eeprom()
|
||||||
rnode.hard_reset()
|
|
||||||
|
if rnode.platform != ROM.PLATFORM_NRF52:
|
||||||
|
rnode.hard_reset()
|
||||||
|
|
||||||
graceful_exit()
|
graceful_exit()
|
||||||
|
|
||||||
RNS.log("Reading EEPROM...")
|
RNS.log("Reading EEPROM...")
|
||||||
@ -2811,8 +2898,12 @@ def main():
|
|||||||
fw_filename = "rnode_firmware_featheresp32.zip"
|
fw_filename = "rnode_firmware_featheresp32.zip"
|
||||||
elif rnode.board == ROM.BOARD_GENERIC_ESP32:
|
elif rnode.board == ROM.BOARD_GENERIC_ESP32:
|
||||||
fw_filename = "rnode_firmware_esp32_generic.zip"
|
fw_filename = "rnode_firmware_esp32_generic.zip"
|
||||||
|
elif rnode.platform == ROM.PLATFORM_NRF52:
|
||||||
|
if rnode.board == ROM.BOARD_RAK4631:
|
||||||
|
fw_filename = "rnode_firmware_rak4631.zip"
|
||||||
else:
|
else:
|
||||||
fw_filename = None
|
fw_filename = None
|
||||||
|
|
||||||
if args.update:
|
if args.update:
|
||||||
RNS.log("ERROR: No firmware found for this board. Cannot update.")
|
RNS.log("ERROR: No firmware found for this board. Cannot update.")
|
||||||
graceful_exit()
|
graceful_exit()
|
||||||
@ -2893,12 +2984,16 @@ def main():
|
|||||||
partition_full_path = EXT_DIR+"/extracted_rnode_firmware.bin"
|
partition_full_path = EXT_DIR+"/extracted_rnode_firmware.bin"
|
||||||
else:
|
else:
|
||||||
partition_full_path = UPD_DIR+"/"+selected_version+"/"+partition_filename
|
partition_full_path = UPD_DIR+"/"+selected_version+"/"+partition_filename
|
||||||
partition_hash = get_partition_hash(partition_full_path)
|
partition_hash = get_partition_hash(rnode.platform, partition_full_path)
|
||||||
if partition_hash != None:
|
if partition_hash != None:
|
||||||
rnode.set_firmware_hash(partition_hash)
|
rnode.set_firmware_hash(partition_hash)
|
||||||
rnode.indicate_firmware_update()
|
rnode.indicate_firmware_update()
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
|
if rnode.platform == ROM.PLATFORM_NRF52:
|
||||||
|
# Allow extra time for writing to EEPROM on NRF52. Current implementation is slow.
|
||||||
|
sleep(14)
|
||||||
|
|
||||||
rnode.disconnect()
|
rnode.disconnect()
|
||||||
flash_status = call(get_flasher_call(rnode.platform, fw_filename))
|
flash_status = call(get_flasher_call(rnode.platform, fw_filename))
|
||||||
if flash_status == 0:
|
if flash_status == 0:
|
||||||
@ -3090,6 +3185,27 @@ def main():
|
|||||||
if rnode.platform == ROM.PLATFORM_ESP32:
|
if rnode.platform == ROM.PLATFORM_ESP32:
|
||||||
RNS.log("Waiting for ESP32 reset...")
|
RNS.log("Waiting for ESP32 reset...")
|
||||||
time.sleep(6)
|
time.sleep(6)
|
||||||
|
elif rnode.platform == ROM.PLATFORM_NRF52:
|
||||||
|
rnode_serial.close()
|
||||||
|
RNS.log("Waiting for NRF52 reset...")
|
||||||
|
time.sleep(14)
|
||||||
|
selected_port = None
|
||||||
|
ports = list_ports.comports()
|
||||||
|
for port in ports:
|
||||||
|
if port.serial_number == rnode.usb_serial_id:
|
||||||
|
selected_port = port
|
||||||
|
break
|
||||||
|
if selected_port is None:
|
||||||
|
RNS.log("Could not detect new port for NRF52...")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
rnode_serial = rnode_open_serial(selected_port.device)
|
||||||
|
rnode.serial = rnode_serial
|
||||||
|
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Could not open the specified serial port. The contained exception was:")
|
||||||
|
RNS.log(str(e))
|
||||||
|
exit()
|
||||||
else:
|
else:
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
@ -3114,6 +3230,8 @@ def main():
|
|||||||
if args.product != None:
|
if args.product != None:
|
||||||
if args.product == "03":
|
if args.product == "03":
|
||||||
mapped_product = ROM.PRODUCT_RNODE
|
mapped_product = ROM.PRODUCT_RNODE
|
||||||
|
elif args.product == "10":
|
||||||
|
mapped_product = ROM.PRODUCT_RAK4631
|
||||||
elif args.product == "f0":
|
elif args.product == "f0":
|
||||||
mapped_product = ROM.PRODUCT_HMBRW
|
mapped_product = ROM.PRODUCT_HMBRW
|
||||||
elif args.product == "e0":
|
elif args.product == "e0":
|
||||||
@ -3130,7 +3248,11 @@ def main():
|
|||||||
else:
|
else:
|
||||||
model = mapped_model
|
model = mapped_model
|
||||||
else:
|
else:
|
||||||
if args.model == "a4":
|
if args.model == "11":
|
||||||
|
model = ROM.MODEL_11
|
||||||
|
elif args.model == "12":
|
||||||
|
model = ROM.MODEL_12
|
||||||
|
elif args.model == "a4":
|
||||||
model = ROM.MODEL_A4
|
model = ROM.MODEL_A4
|
||||||
elif args.model == "a9":
|
elif args.model == "a9":
|
||||||
model = ROM.MODEL_A9
|
model = ROM.MODEL_A9
|
||||||
@ -3243,7 +3365,9 @@ def main():
|
|||||||
time.sleep(0.006)
|
time.sleep(0.006)
|
||||||
|
|
||||||
rnode.write_eeprom(ROM.ADDR_INFO_LOCK, ROM.INFO_LOCK_BYTE)
|
rnode.write_eeprom(ROM.ADDR_INFO_LOCK, ROM.INFO_LOCK_BYTE)
|
||||||
|
if rnode.platform == ROM.PLATFORM_NRF52:
|
||||||
|
# Allow extra time for writing to EEPROM on NRF52. Current implementation is slow.
|
||||||
|
sleep(3)
|
||||||
RNS.log("EEPROM written! Validating...")
|
RNS.log("EEPROM written! Validating...")
|
||||||
|
|
||||||
if wants_fw_provision:
|
if wants_fw_provision:
|
||||||
@ -3257,18 +3381,58 @@ def main():
|
|||||||
vf.close()
|
vf.close()
|
||||||
else:
|
else:
|
||||||
partition_filename = fw_filename.replace(".zip", ".bin")
|
partition_filename = fw_filename.replace(".zip", ".bin")
|
||||||
partition_hash = get_partition_hash(UPD_DIR+"/"+selected_version+"/"+partition_filename)
|
partition_hash = get_partition_hash(rnode.platform, UPD_DIR+"/"+selected_version+"/"+partition_filename)
|
||||||
|
|
||||||
if partition_hash != None:
|
if partition_hash != None:
|
||||||
time.sleep(0.75)
|
time.sleep(0.75)
|
||||||
RNS.log("Setting firmware checksum...")
|
RNS.log("Setting firmware checksum...")
|
||||||
rnode.set_firmware_hash(partition_hash)
|
rnode.set_firmware_hash(partition_hash)
|
||||||
|
|
||||||
rnode.hard_reset()
|
|
||||||
if rnode.platform == ROM.PLATFORM_ESP32:
|
if rnode.platform == ROM.PLATFORM_ESP32:
|
||||||
|
rnode.hard_reset()
|
||||||
RNS.log("Waiting for ESP32 reset...")
|
RNS.log("Waiting for ESP32 reset...")
|
||||||
time.sleep(6.5)
|
time.sleep(6.5)
|
||||||
|
|
||||||
|
elif rnode.platform == ROM.PLATFORM_NRF52:
|
||||||
|
rnode.hard_reset()
|
||||||
|
# The hard reset on this platform is different
|
||||||
|
# to that of the ESP32 platform, it causes
|
||||||
|
# disruption to the serial connection.
|
||||||
|
# Therefore, we have to reestablish the serial
|
||||||
|
# connection after the reset.
|
||||||
|
rnode_serial.close()
|
||||||
|
RNS.log("Waiting for NRF52 reset...")
|
||||||
|
|
||||||
|
# Give plenty of time for to allow for
|
||||||
|
# potential e-ink display refresh too.
|
||||||
|
time.sleep(14)
|
||||||
|
|
||||||
|
# After the hard reset, the port number will
|
||||||
|
# change. We need to find the new port number,
|
||||||
|
# which can be done non-interactively by
|
||||||
|
# comparing the USB serial numbers of the
|
||||||
|
# original port and the one we are currently
|
||||||
|
# iterating.
|
||||||
|
selected_port = None
|
||||||
|
ports = list_ports.comports()
|
||||||
|
for port in ports:
|
||||||
|
if port.serial_number == rnode.usb_serial_id:
|
||||||
|
selected_port = port
|
||||||
|
break
|
||||||
|
if selected_port is None:
|
||||||
|
RNS.log("Could not detect new port for NRF52...")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
rnode_serial = rnode_open_serial(selected_port.device)
|
||||||
|
rnode.serial = rnode_serial
|
||||||
|
thread = threading.Thread(target=rnode.readLoop, daemon=True).start()
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Could not open the specified serial port. The contained exception was:")
|
||||||
|
RNS.log(str(e))
|
||||||
|
exit()
|
||||||
|
else:
|
||||||
|
rnode.hard_reset()
|
||||||
|
|
||||||
rnode.download_eeprom()
|
rnode.download_eeprom()
|
||||||
if rnode.provisioned:
|
if rnode.provisioned:
|
||||||
RNS.log("EEPROM Bootstrapping successful!")
|
RNS.log("EEPROM Bootstrapping successful!")
|
||||||
@ -3367,6 +3531,22 @@ def main():
|
|||||||
RNS.log("This device has not been provisioned yet, cannot set firmware hash")
|
RNS.log("This device has not been provisioned yet, cannot set firmware hash")
|
||||||
graceful_exit(77)
|
graceful_exit(77)
|
||||||
|
|
||||||
|
if args.get_target_firmware_hash:
|
||||||
|
if rnode.provisioned:
|
||||||
|
RNS.log(f"The target firmware hash is: {rnode.firmware_hash_target.hex()}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
RNS.log("This device has not been provisioned yet, cannot get firmware hash")
|
||||||
|
exit(77)
|
||||||
|
|
||||||
|
if args.get_firmware_hash:
|
||||||
|
if rnode.provisioned:
|
||||||
|
RNS.log(f"The actual firmware hash is: {rnode.firmware_hash.hex()}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
RNS.log("This device has not been provisioned yet, cannot get firmware hash")
|
||||||
|
exit(77)
|
||||||
|
|
||||||
if rnode.provisioned:
|
if rnode.provisioned:
|
||||||
if args.normal:
|
if args.normal:
|
||||||
rnode.setNormalMode()
|
rnode.setNormalMode()
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "0.7.4"
|
__version__ = "0.7.5"
|
||||||
|
12
RNS/vendor/ifaddr/niwrapper.py
vendored
12
RNS/vendor/ifaddr/niwrapper.py
vendored
@ -18,6 +18,18 @@ def interface_names_to_indexes() -> dict:
|
|||||||
results[adapter.name] = adapter.index
|
results[adapter.name] = adapter.index
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
def interface_name_to_nice_name(ifname) -> str:
|
||||||
|
try:
|
||||||
|
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
|
||||||
|
for adapter in adapters:
|
||||||
|
if adapter.name == ifname:
|
||||||
|
if hasattr(adapter, "nice_name"):
|
||||||
|
return adapter.nice_name
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def ifaddresses(ifname) -> dict:
|
def ifaddresses(ifname) -> dict:
|
||||||
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
|
adapters = RNS.vendor.ifaddr.get_adapters(include_unconfigured=True)
|
||||||
ifa = {}
|
ifa = {}
|
||||||
|
Loading…
Reference in New Issue
Block a user