Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/infuse_iot/generated/kv_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,22 @@ class bluetooth_peer(VLACompatLittleEndianStruct):
]
_pack_ = 1

class lora_config(VLACompatLittleEndianStruct):
"""LoRa modem configuration"""

NAME = "LORA_CONFIG"
BASE_ID = 51
RANGE = 1
_fields_ = [
("frequency", ctypes.c_uint32),
("bandwidth", ctypes.c_uint8),
("spreading_factor", ctypes.c_uint8),
("coding_rate", ctypes.c_uint8),
("preamble_len", ctypes.c_uint16),
("tx_power", ctypes.c_int8),
]
_pack_ = 1

class gravity_reference(VLACompatLittleEndianStruct):
"""Reference gravity vector for tilt calculations"""

Expand Down Expand Up @@ -352,6 +368,7 @@ class secure_storage_reserved(VLACompatLittleEndianStruct):
45: lte_pdp_config,
46: lte_networking_modes,
50: bluetooth_peer,
51: lora_config,
60: gravity_reference,
100: geofence,
101: geofence,
Expand Down
29 changes: 29 additions & 0 deletions src/infuse_iot/generated/rpc_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,18 @@ class rpc_struct_sockaddr(VLACompatLittleEndianStruct):
_pack_ = 1


class rpc_struct_heap_info(VLACompatLittleEndianStruct):
"""struct k_heap information"""

_fields_ = [
("addr", ctypes.c_uint32),
("free_bytes", ctypes.c_uint32),
("allocated_bytes", ctypes.c_uint32),
("max_allocated_bytes", ctypes.c_uint32),
]
_pack_ = 1


class rpc_enum_bt_le_addr_type(enum.IntEnum):
"""Bluetooth LE address type"""

Expand Down Expand Up @@ -599,6 +611,23 @@ class response(VLACompatLittleEndianStruct):
_pack_ = 1


class heap_stats:
"""Query stats of heaps"""

HELP = "Query stats of heaps"
DESCRIPTION = "Query stats of heaps"
COMMAND_ID = 19

class request(VLACompatLittleEndianStruct):
_fields_ = []
_pack_ = 1

class response(VLACompatLittleEndianStruct):
_fields_ = []
vla_field = ("stats", 0 * rpc_struct_heap_info)
_pack_ = 1


class lte_at_cmd:
"""Run AT command against LTE modem"""

Expand Down
38 changes: 38 additions & 0 deletions src/infuse_iot/generated/tdf_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,42 @@ class annotation(TdfReadingBase):
"event": "{}",
}

class lora_rx(TdfReadingBase):
"""Received LoRa packet"""

name = "LORA_RX"
_fields_ = [
("snr", ctypes.c_int8),
("rssi", ctypes.c_int16),
("payload", 0 * ctypes.c_uint8),
]
_pack_ = 1
_postfix_ = {
"snr": "",
"rssi": "",
"payload": "",
}
_display_fmt_ = {
"snr": "{}",
"rssi": "{}",
"payload": "{}",
}

class lora_tx(TdfReadingBase):
"""Transmitted LoRa packet"""

name = "LORA_TX"
_fields_ = [
("payload", 0 * ctypes.c_uint8),
]
_pack_ = 1
_postfix_ = {
"payload": "",
}
_display_fmt_ = {
"payload": "{}",
}

class array_type(TdfReadingBase):
"""Example array type"""

Expand Down Expand Up @@ -1319,5 +1355,7 @@ class array_type(TdfReadingBase):
41: readings.adc_raw_16,
42: readings.adc_raw_32,
43: readings.annotation,
44: readings.lora_rx,
45: readings.lora_tx,
100: readings.array_type,
}
2 changes: 2 additions & 0 deletions src/infuse_iot/rpc_wrappers/data_logger_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ def sizeof_fmt(num, suffix="B"):
print(f"{self.logger.name}")
print(f"\t Logged: {sizeof_fmt(total_logged)}")
print(f"\t Blocks: {r.current_block}/{r.logical_blocks} ({percent:.0f}%)")
if r.earliest_block > 0:
print(f"\t Earliest: {r.earliest_block}")
if byte_rate == 0.0:
print("\t Block Rate: N/A")
print("\t Byte Rate: N/A")
Expand Down
45 changes: 45 additions & 0 deletions src/infuse_iot/rpc_wrappers/heap_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env python3

import tabulate

import infuse_iot.generated.rpc_definitions as defs
from infuse_iot.commands import InfuseRpcCommand
from infuse_iot.zephyr.errno import errno


class heap_stats(InfuseRpcCommand, defs.heap_stats):
@classmethod
def add_parser(cls, parser):
pass

def __init__(self, args):
self.args = args

def request_struct(self):
return self.request()

def request_json(self):
return {}

def handle_response(self, return_code, response):
if return_code != 0:
print(f"Failed to query heap stats ({errno.strerror(-return_code)})")
return

stats = []
for heap in response.stats:
total = heap.free_bytes + heap.allocated_bytes
current_percent = 100 * (heap.allocated_bytes / total)
max_percent = 100 * (heap.max_allocated_bytes / total)
stats.append(
[
f"0x{heap.addr:08x}",
total,
heap.allocated_bytes,
f"{current_percent:4.1f}%",
heap.max_allocated_bytes,
f"{max_percent:4.1f}%",
]
)

print(tabulate.tabulate(stats, headers=["Address", "Total Size", "Current Usage", "", "Max Usage", ""]))
5 changes: 3 additions & 2 deletions src/infuse_iot/tools/bt_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ def run(self):
if evt.epacket.ptype == InfuseType.TDF:
for tdf in self._decoder.decode(evt.epacket.payload):
t = tdf.data[-1]
t_str = f"{tdf.time:.3f}" if tdf.time else "N/A"
if len(tdf.data) > 1:
print(f"{tdf.time:.3f} TDF: {t.name}[{len(tdf.data)}]")
print(f"{t_str} TDF: {t.name}[{len(tdf.data)}]")
else:
print(f"{tdf.time:.3f} TDF: {t.name}")
print(f"{t_str} TDF: {t.name}")

except KeyboardInterrupt:
print(f"Disconnecting from {self._id:016x}")
Expand Down
24 changes: 21 additions & 3 deletions src/infuse_iot/tools/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ def __init__(
common: CommonThreadState,
):
self._common = common
self._connected: dict[int, int] = {}
self._queue: queue.Queue = queue.Queue()
super().__init__(self._iter)

Expand Down Expand Up @@ -297,6 +298,10 @@ def _bt_connect_cb(self, pkt: PacketReceived, rc: int, response: bytes):
if rc < 0:
rsp = ClientNotificationConnectionFailed(infuse_id)
else:
if infuse_id in self._connected:
self._connected[infuse_id] += 1
else:
self._connected[infuse_id] = 1
rsp = ClientNotificationConnectionCreated(infuse_id, 244 - ctypes.sizeof(CtypeBtGattFrame) - 16)
self._common.server.broadcast(rsp)

Expand All @@ -314,12 +319,17 @@ def _handle_conn_request(self, req: GatewayRequestConnectionRequest):
return

subs = 0
bt_char = defs.rpc_enum_infuse_bt_characteristic
if req.data_types & req.DataType.COMMAND:
subs |= defs.rpc_enum_infuse_bt_characteristic.COMMAND
subs |= bt_char.COMMAND
if req.data_types & req.DataType.DATA:
subs |= defs.rpc_enum_infuse_bt_characteristic.DATA
subs |= bt_char.DATA
if req.data_types & req.DataType.LOGGING:
subs |= defs.rpc_enum_infuse_bt_characteristic.LOGGING
subs |= bt_char.LOGGING

# Multiple connection users, subscribe all
if req.infuse_id in self._connected:
subs = bt_char.COMMAND | bt_char.DATA | bt_char.LOGGING

connect_args = defs.bt_connect_infuse.request(
state.bt_addr.to_rpc_struct(),
Expand Down Expand Up @@ -347,6 +357,14 @@ def _handle_conn_release(self, req: GatewayRequestConnectionRelease):
# Unknown device, nothing to do
return

if req.infuse_id in self._connected:
# Decrement reference count
self._connected[req.infuse_id] -= 1
if self._connected[req.infuse_id] > 0:
# Someone is still using the connection
return
self._connected.pop(req.infuse_id)

disconnect_args = defs.bt_disconnect.request(state.bt_addr.to_rpc_struct())
cmd = self._common.rpc.generate(defs.bt_disconnect.COMMAND_ID, bytes(disconnect_args), Auth.DEVICE, None)
encrypted = cmd.to_serial(self._common.ddb)
Expand Down