Skip to content

Commit 98f51d1

Browse files
committed
rpc_wrappers: bt_file_copy_coap: add wrapper
Add a wrapper for the OTA upgrade command `bt_file_copy_coap`. Signed-off-by: Jordan Yates <jordan@embeint.com>
1 parent 1d4c87b commit 98f51d1

2 files changed

Lines changed: 152 additions & 0 deletions

File tree

src/infuse_iot/generated/rpc_definitions.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,38 @@ class response(VLACompatLittleEndianStruct):
863863
_pack_ = 1
864864

865865

866+
class bt_file_copy_coap:
867+
"""Copy a file fetched from COAP to a remote device over Bluetooth"""
868+
869+
HELP = "Copy a file fetched from COAP to a remote device over Bluetooth"
870+
DESCRIPTION = "Copy a file fetched from COAP to a remote device over Bluetooth"
871+
COMMAND_ID = 53
872+
873+
class request(VLACompatLittleEndianStruct):
874+
_fields_ = [
875+
("peer", rpc_struct_bt_addr_le),
876+
("conn_timeout_ms", ctypes.c_uint16),
877+
("action", ctypes.c_uint8),
878+
("file_idx", ctypes.c_uint8),
879+
("ack_period", ctypes.c_uint8),
880+
("pipelining", ctypes.c_uint8),
881+
("server_address", 48 * ctypes.c_char),
882+
("server_port", ctypes.c_uint16),
883+
("block_timeout_ms", ctypes.c_uint16),
884+
("resource_len", ctypes.c_uint32),
885+
("resource_crc", ctypes.c_uint32),
886+
]
887+
vla_field = ("resource", 0 * ctypes.c_char)
888+
_pack_ = 1
889+
890+
class response(VLACompatLittleEndianStruct):
891+
_fields_ = [
892+
("resource_len", ctypes.c_uint32),
893+
("resource_crc", ctypes.c_uint32),
894+
]
895+
_pack_ = 1
896+
897+
866898
class gravity_reference_update:
867899
"""Store the current accelerometer vector as the gravity reference"""
868900

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python3
2+
3+
import ctypes
4+
5+
import infuse_iot.generated.rpc_definitions as defs
6+
from infuse_iot.commands import InfuseRpcCommand
7+
from infuse_iot.generated.rpc_definitions import rpc_enum_bt_le_addr_type, rpc_enum_file_action, rpc_struct_bt_addr_le
8+
from infuse_iot.rpc_wrappers.coap_download import coap_download, coap_server_file_stats
9+
from infuse_iot.util.argparse import BtLeAddress
10+
from infuse_iot.util.ctypes import bytes_to_uint8
11+
from infuse_iot.zephyr.errno import errno
12+
13+
14+
class bt_file_copy_coap(InfuseRpcCommand, defs.bt_file_copy_coap):
15+
@classmethod
16+
def add_parser(cls, parser):
17+
parser.add_argument(
18+
"--server",
19+
type=str,
20+
default=coap_download.INFUSE_COAP_SERVER_ADDR,
21+
help="COAP server name",
22+
)
23+
parser.add_argument(
24+
"--port",
25+
type=int,
26+
default=coap_download.INFUSE_COAP_SERVER_PORT,
27+
help="COAP server port",
28+
)
29+
parser.add_argument(
30+
"--resource",
31+
"-r",
32+
type=str,
33+
required=True,
34+
help="Resource path",
35+
)
36+
group = parser.add_mutually_exclusive_group(required=True)
37+
group.add_argument(
38+
"--discard",
39+
dest="action",
40+
action="store_const",
41+
const=rpc_enum_file_action.DISCARD,
42+
help="Download file and discard without action",
43+
)
44+
group.add_argument(
45+
"--dfu",
46+
dest="action",
47+
action="store_const",
48+
const=rpc_enum_file_action.APP_IMG,
49+
help="Download complete image file and perform DFU",
50+
)
51+
group.add_argument(
52+
"--cpatch",
53+
dest="action",
54+
action="store_const",
55+
const=rpc_enum_file_action.APP_CPATCH,
56+
help="Download CPatch binary diff and perform DFU",
57+
)
58+
group.add_argument(
59+
"--nrf91-modem",
60+
dest="action",
61+
action="store_const",
62+
const=rpc_enum_file_action.NRF91_MODEM_DIFF,
63+
help="nRF91 LTE modem diff upgrade",
64+
)
65+
addr_group = parser.add_mutually_exclusive_group(required=True)
66+
addr_group.add_argument("--public", type=BtLeAddress, help="Public Bluetooth address")
67+
addr_group.add_argument("--random", type=BtLeAddress, help="Random Bluetooth address")
68+
parser.add_argument("--conn-timeout", type=int, default=5000, help="Connection timeout (ms)")
69+
parser.add_argument("--bt-pipelining", type=int, default=4, help="Bluetooth data pipelining")
70+
71+
def __init__(self, args):
72+
self.server = args.server.encode("utf-8")
73+
self.port = args.port
74+
self.resource = args.resource.encode("utf-8")
75+
self.action = args.action
76+
self.conn_timeout = args.conn_timeout
77+
self.pipelining = args.bt_pipelining
78+
if args.public:
79+
self.peer = rpc_struct_bt_addr_le(
80+
rpc_enum_bt_le_addr_type.PUBLIC,
81+
bytes_to_uint8(args.public.to_bytes(6, "little")),
82+
)
83+
else:
84+
self.peer = rpc_struct_bt_addr_le(
85+
rpc_enum_bt_le_addr_type.RANDOM,
86+
bytes_to_uint8(args.random.to_bytes(6, "little")),
87+
)
88+
self.file_len, self.file_crc = coap_server_file_stats(args.server, args.resource)
89+
90+
def request_struct(self):
91+
class request(ctypes.LittleEndianStructure):
92+
_fields_ = [
93+
*self.request._fields_,
94+
("resource", (len(self.resource) + 1) * ctypes.c_char),
95+
]
96+
_pack_ = 1
97+
98+
return request(
99+
self.peer,
100+
self.conn_timeout,
101+
self.action,
102+
0,
103+
1,
104+
self.pipelining,
105+
self.server,
106+
self.port,
107+
2000,
108+
self.file_len,
109+
self.file_crc,
110+
self.resource,
111+
)
112+
113+
def handle_response(self, return_code, response):
114+
if return_code != 0:
115+
print(f"Failed to download file ({errno.strerror(-return_code)})")
116+
return
117+
else:
118+
print("File downloaded and copied")
119+
print(f"\tLength: {response.resource_len}")
120+
print(f"\t CRC: 0x{response.resource_crc:08x}")

0 commit comments

Comments
 (0)