python-mobius 0.11.0__py3-none-any.whl → 0.12.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mobius/__init__.py +5 -5
- mobius/cli.py +85 -83
- mobius/device.py +559 -539
- mobius/device_status.py +19 -7
- mobius/discovery.py +44 -29
- mobius/dump.py +12 -17
- mobius/modifiers.py +0 -2
- mobius/relay.py +14 -48
- mobius/scenes.py +4 -3
- mobius/schedule.py +31 -19
- mobius/timezone.py +2 -6
- {python_mobius-0.11.0.dist-info → python_mobius-0.12.0.dist-info}/METADATA +1 -1
- python_mobius-0.12.0.dist-info/RECORD +27 -0
- python_mobius-0.11.0.dist-info/RECORD +0 -27
- {python_mobius-0.11.0.dist-info → python_mobius-0.12.0.dist-info}/WHEEL +0 -0
- {python_mobius-0.11.0.dist-info → python_mobius-0.12.0.dist-info}/entry_points.txt +0 -0
- {python_mobius-0.11.0.dist-info → python_mobius-0.12.0.dist-info}/licenses/LICENSE +0 -0
mobius/__init__.py
CHANGED
|
@@ -64,14 +64,14 @@ from .mesh_address import (
|
|
|
64
64
|
is_short_address_derived, format_mesh_address,
|
|
65
65
|
)
|
|
66
66
|
from .relay import RelayedMobiusDevice
|
|
67
|
-
from .device import firmware_label
|
|
67
|
+
from .device import firmware_label, main_firmware_version
|
|
68
68
|
from .firmware import (
|
|
69
69
|
FIRMWARE_CLOUD_HOST, ImageId, FirmwareImage, installable_images, firmware_images,
|
|
70
70
|
firmware_check_url, AvailableFirmware, FirmwareCheck, parse_firmware_check,
|
|
71
71
|
ChangelogEntry, Changelog, parse_changelog, version_tuple,
|
|
72
72
|
)
|
|
73
73
|
from .device import (
|
|
74
|
-
MobiusDevice,
|
|
74
|
+
MobiusDevice, LightIntensityResult, LightPollResult, FullPollResult,
|
|
75
75
|
schedule_capacity, min_schedule_capacity, tank_group,
|
|
76
76
|
SERVICE_GENERAL, CHAR_RX_DATA, CHAR_RX_FINAL, CHAR_TX_DATA, CHAR_TX_FINAL,
|
|
77
77
|
)
|
|
@@ -93,7 +93,7 @@ from .mob import (
|
|
|
93
93
|
MAX_PUMP_PRIMITIVE_SIZE,
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
-
__version__ = "0.
|
|
96
|
+
__version__ = "0.12.0"
|
|
97
97
|
|
|
98
98
|
__all__ = [
|
|
99
99
|
"__version__",
|
|
@@ -120,7 +120,7 @@ __all__ = [
|
|
|
120
120
|
"get_pump_reverse",
|
|
121
121
|
"FirmwareType", "FIRMWARE_TYPE_LABELS_ETM", "HardwareInfo",
|
|
122
122
|
# firmware
|
|
123
|
-
"firmware_label", "FIRMWARE_CLOUD_HOST", "ImageId", "FirmwareImage", "installable_images", "firmware_images",
|
|
123
|
+
"firmware_label", "main_firmware_version", "FIRMWARE_CLOUD_HOST", "ImageId", "FirmwareImage", "installable_images", "firmware_images",
|
|
124
124
|
"firmware_check_url", "AvailableFirmware", "FirmwareCheck", "parse_firmware_check",
|
|
125
125
|
"ChangelogEntry", "Changelog", "parse_changelog", "version_tuple",
|
|
126
126
|
"Color", "COLOR_LABELS", "RadioType", "RADIO_TYPE_LABELS",
|
|
@@ -153,7 +153,7 @@ __all__ = [
|
|
|
153
153
|
"format_mesh_address", "posix_tz_string", "TIME_ZONE_FIELD_SIZE",
|
|
154
154
|
"RelayedMobiusDevice",
|
|
155
155
|
# device
|
|
156
|
-
"MobiusDevice", "
|
|
156
|
+
"MobiusDevice", "LightIntensityResult", "LightPollResult", "FullPollResult",
|
|
157
157
|
"schedule_capacity", "min_schedule_capacity", "tank_group",
|
|
158
158
|
"SERVICE_GENERAL", "CHAR_RX_DATA", "CHAR_RX_FINAL", "CHAR_TX_DATA", "CHAR_TX_FINAL",
|
|
159
159
|
# discovery
|
mobius/cli.py
CHANGED
|
@@ -13,19 +13,22 @@ import argparse
|
|
|
13
13
|
import asyncio
|
|
14
14
|
import contextlib
|
|
15
15
|
import json
|
|
16
|
+
import logging
|
|
16
17
|
import struct
|
|
17
18
|
from typing import Optional
|
|
18
19
|
|
|
19
20
|
from .checksums import configured_scenes_checksum, schedule_checksum, supported_attributes_crc
|
|
20
|
-
from .device import
|
|
21
|
+
from .device import (
|
|
22
|
+
ALL_ELEMENTS, MobiusDevice, min_schedule_capacity, decode_mesh_peer_arrays, decode_networked_thread_devices,
|
|
23
|
+
)
|
|
21
24
|
from .relay import RelayedMobiusDevice
|
|
22
25
|
from .device_status import MeshPeer
|
|
23
26
|
from .mesh_address import (
|
|
24
27
|
is_valid_mesh_address, mesh_local_prefix_from_own_address,
|
|
25
|
-
mesh_local_prefix_from_mlprefix,
|
|
28
|
+
mesh_local_prefix_from_mlprefix,
|
|
26
29
|
)
|
|
27
30
|
from .constants import (
|
|
28
|
-
PrimitiveType, C2Attribute,
|
|
31
|
+
PrimitiveType, C2Attribute,
|
|
29
32
|
primitive_type_from_name, support_tier,
|
|
30
33
|
)
|
|
31
34
|
from .discovery import (
|
|
@@ -82,13 +85,11 @@ async def _dump_schedule(device: MobiusDevice, support: str) -> None:
|
|
|
82
85
|
and for lights the lunar/insolation/intensity/acclimation state."""
|
|
83
86
|
print(" --- full schedule ---")
|
|
84
87
|
if support == "light":
|
|
85
|
-
|
|
86
|
-
for point in sorted(
|
|
88
|
+
poll = await device.get_light_poll_batch(which=1)
|
|
89
|
+
for point in sorted(poll.schedule_points, key=lambda p: p.time_minutes):
|
|
87
90
|
print(f" {_format_time(point.time_minutes)}{_format_flags(point)}: "
|
|
88
91
|
f"{_format_channels(point.light.channels)}")
|
|
89
|
-
|
|
90
|
-
lunar_enabled = await device.get_lunar_enabled()
|
|
91
|
-
print(f" lunar_enabled: {lunar_enabled}")
|
|
92
|
+
print(f" lunar_enabled: {poll.lunar_enabled}")
|
|
92
93
|
|
|
93
94
|
# Firmware-computed lunar state, to compare with the calculated
|
|
94
95
|
# "current_intensities"/"light_diagnostics" of the summary.
|
|
@@ -98,12 +99,9 @@ async def _dump_schedule(device: MobiusDevice, support: str) -> None:
|
|
|
98
99
|
except Exception as e:
|
|
99
100
|
print(f" lunar_phase_info: read failed: {e}")
|
|
100
101
|
|
|
101
|
-
insolation_active
|
|
102
|
-
schedule_intensity
|
|
103
|
-
acclimation
|
|
104
|
-
print(f" insolation_active: {insolation_active}")
|
|
105
|
-
print(f" schedule_intensity: {schedule_intensity}")
|
|
106
|
-
print(f" acclimation: {acclimation}")
|
|
102
|
+
print(f" insolation_active: {poll.intensities.diagnostics['insolation_active']}")
|
|
103
|
+
print(f" schedule_intensity: {poll.schedule_intensity}")
|
|
104
|
+
print(f" acclimation: {poll.acclimation}")
|
|
107
105
|
|
|
108
106
|
elif support.startswith("pump"):
|
|
109
107
|
points = await device.get_pump_schedule(which=1)
|
|
@@ -120,6 +118,18 @@ def _support_from_primitive_type(primitive_type_name: str | None) -> str:
|
|
|
120
118
|
return support_tier(primitive_type_from_name(primitive_type_name))
|
|
121
119
|
|
|
122
120
|
|
|
121
|
+
async def _target_identity(target, serial: str, fallback_support: str) -> tuple[str, Optional[int]]:
|
|
122
|
+
"""(support tier, group_mask) read from `target` itself; when its device
|
|
123
|
+
info can't be read, (`fallback_support`, None) with a message."""
|
|
124
|
+
try:
|
|
125
|
+
info = await target.get_device_info()
|
|
126
|
+
except Exception as e:
|
|
127
|
+
print(f" Could not read {serial!r}'s own device info ({e}) -- using support={fallback_support!r} "
|
|
128
|
+
f"and leaving out the rest of its schedule group.")
|
|
129
|
+
return fallback_support, None
|
|
130
|
+
return _support_from_primitive_type(info.get("primitive_type")), info.get("group_mask")
|
|
131
|
+
|
|
132
|
+
|
|
123
133
|
async def _dump_schedule_to_file(device: MobiusDevice, support: str, serial: str, path: str) -> int:
|
|
124
134
|
"""
|
|
125
135
|
Writes Schedule1 and Schedule2 to `path` as JSON
|
|
@@ -200,8 +210,7 @@ async def _dump_schedule_to_mob_file(device: MobiusDevice, support: str, path: s
|
|
|
200
210
|
points = await device.get_light_schedule(which=1)
|
|
201
211
|
mob = light_schedule_to_mob(points, template_name)
|
|
202
212
|
elif support.startswith("pump"):
|
|
203
|
-
|
|
204
|
-
primitive_type = PrimitiveType[info["primitive_type"]]
|
|
213
|
+
primitive_type = await device.identify_device_type()
|
|
205
214
|
points = await device.get_pump_schedule(which=1)
|
|
206
215
|
mob = pump_schedule_to_mob(points, primitive_type, template_name)
|
|
207
216
|
else:
|
|
@@ -235,7 +244,7 @@ async def _load_schedule_from_mob_file(device: MobiusDevice, support: str, path:
|
|
|
235
244
|
|
|
236
245
|
async def _resolve_group_targets(
|
|
237
246
|
gateway: MobiusDevice, target_serial: str, target_device, target_group_mask,
|
|
238
|
-
support: str,
|
|
247
|
+
support: str, pan_id: Optional[int] = None,
|
|
239
248
|
stack: Optional[contextlib.AsyncExitStack] = None, args=None,
|
|
240
249
|
) -> list[tuple[str, object]]:
|
|
241
250
|
"""
|
|
@@ -267,7 +276,7 @@ async def _resolve_group_targets(
|
|
|
267
276
|
for peer in (tank.peers if tank is not None else []):
|
|
268
277
|
if peer.serial == target_serial:
|
|
269
278
|
continue
|
|
270
|
-
relayed = RelayedMobiusDevice(gateway, peer
|
|
279
|
+
relayed = RelayedMobiusDevice(gateway, peer)
|
|
271
280
|
try:
|
|
272
281
|
peer_info = await relayed.get_device_info()
|
|
273
282
|
except Exception as e:
|
|
@@ -378,7 +387,7 @@ async def _check_checksums(target) -> None:
|
|
|
378
387
|
if data_attr not in supported_ids:
|
|
379
388
|
print(f" {label}: not supported by this device")
|
|
380
389
|
continue
|
|
381
|
-
values = await target.
|
|
390
|
+
values = await target.get_attribute(data_attr, 0, ALL_ELEMENTS)
|
|
382
391
|
if data_attr == C2Attribute.ConfiguredScenes:
|
|
383
392
|
computed = configured_scenes_checksum(values)
|
|
384
393
|
used = sum(1 for v in values if len(v) >= 2 and struct.unpack_from("<H", v)[0] != 0)
|
|
@@ -410,7 +419,7 @@ async def _debug_mesh_discovery(device) -> list:
|
|
|
410
419
|
print(f" MLPrefix OK. Derived mesh-local prefix: {prefix.hex()}")
|
|
411
420
|
try:
|
|
412
421
|
entries_raw = await device.get_attribute(
|
|
413
|
-
C2Attribute.NetworkedThreadDevices, index=0, count=
|
|
422
|
+
C2Attribute.NetworkedThreadDevices, index=0, count=ALL_ELEMENTS,
|
|
414
423
|
)
|
|
415
424
|
except Exception as e:
|
|
416
425
|
print(f" NetworkedThreadDevices FAILED: {e!r}")
|
|
@@ -418,25 +427,10 @@ async def _debug_mesh_discovery(device) -> list:
|
|
|
418
427
|
print(f" NetworkedThreadDevices returned {len(entries_raw)} element(s): "
|
|
419
428
|
f"{[e.hex() for e in entries_raw]}")
|
|
420
429
|
|
|
421
|
-
peers = []
|
|
422
430
|
for entry in entries_raw:
|
|
423
431
|
if len(entry) != 28:
|
|
424
|
-
print(f" Skipping malformed entry (expected 28 bytes, got "
|
|
425
|
-
|
|
426
|
-
continue
|
|
427
|
-
try:
|
|
428
|
-
serial = entry[14:28].decode("ascii").rstrip("\x00")
|
|
429
|
-
except UnicodeDecodeError:
|
|
430
|
-
continue
|
|
431
|
-
if not serial or serial == "00000000000000":
|
|
432
|
-
continue
|
|
433
|
-
address = prefix + entry[0:8]
|
|
434
|
-
model_raw = struct.unpack("<h", entry[12:14])[0]
|
|
435
|
-
peers.append(MeshPeer(
|
|
436
|
-
serial=serial, model_raw=model_raw, model=enum_or_none(Model, model_raw),
|
|
437
|
-
short_address=extract_short_address(address), address=address,
|
|
438
|
-
age=struct.unpack("<I", entry[8:12])[0],
|
|
439
|
-
))
|
|
432
|
+
print(f" Skipping malformed entry (expected 28 bytes, got {len(entry)}): {entry.hex()}")
|
|
433
|
+
peers = decode_networked_thread_devices(prefix, entries_raw)
|
|
440
434
|
if peers:
|
|
441
435
|
print(f" Parsed {len(peers)} peer(s) via NetworkedThreadDevices -- "
|
|
442
436
|
f"skipping the MXM-hub steps below.")
|
|
@@ -474,7 +468,7 @@ async def _debug_mesh_discovery(device) -> list:
|
|
|
474
468
|
for attr in (C2Attribute.SerialNumberArray, C2Attribute.DeviceModelArray, C2Attribute.ShortAddressArray):
|
|
475
469
|
print(f" Step 2: {attr.name} ({attr.value})...")
|
|
476
470
|
try:
|
|
477
|
-
values = await device.get_attribute(attr, index=0, count=
|
|
471
|
+
values = await device.get_attribute(attr, index=0, count=ALL_ELEMENTS)
|
|
478
472
|
except Exception as e:
|
|
479
473
|
print(f" FAILED: {e!r}")
|
|
480
474
|
values = []
|
|
@@ -482,24 +476,10 @@ async def _debug_mesh_discovery(device) -> list:
|
|
|
482
476
|
print(f" Returned {len(values)} element(s): {[v.hex() for v in values]}")
|
|
483
477
|
arrays[attr] = values
|
|
484
478
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
arrays[C2Attribute.SerialNumberArray], arrays[C2Attribute.DeviceModelArray],
|
|
479
|
+
return decode_mesh_peer_arrays(
|
|
480
|
+
prefix, arrays[C2Attribute.SerialNumberArray], arrays[C2Attribute.DeviceModelArray],
|
|
488
481
|
arrays[C2Attribute.ShortAddressArray],
|
|
489
|
-
)
|
|
490
|
-
try:
|
|
491
|
-
serial = serial_bytes.decode("ascii").rstrip("\x00")
|
|
492
|
-
except (UnicodeDecodeError, AttributeError):
|
|
493
|
-
continue
|
|
494
|
-
if not serial or serial == "00000000000000" or len(model_bytes) < 2 or len(short_bytes) < 2:
|
|
495
|
-
continue
|
|
496
|
-
model_raw = struct.unpack("<h", model_bytes[:2])[0]
|
|
497
|
-
short_address = struct.unpack("<H", short_bytes[:2])[0]
|
|
498
|
-
peers.append(MeshPeer(
|
|
499
|
-
serial=serial, model_raw=model_raw, model=enum_or_none(Model, model_raw),
|
|
500
|
-
short_address=short_address, address=build_rloc_address(prefix, short_address),
|
|
501
|
-
))
|
|
502
|
-
return peers
|
|
482
|
+
)
|
|
503
483
|
|
|
504
484
|
|
|
505
485
|
def _print_mesh_peers_or_hint(peers: list) -> None:
|
|
@@ -511,6 +491,28 @@ def _print_mesh_peers_or_hint(peers: list) -> None:
|
|
|
511
491
|
_print_peers(peers)
|
|
512
492
|
|
|
513
493
|
|
|
494
|
+
# Diagnostic getters printed by --dump-diagnostics, in order.
|
|
495
|
+
_DIAGNOSTIC_GETTERS = (
|
|
496
|
+
"get_fsci_diagnostic_info", "get_clock_sync_info", "get_thread_provisioning_info",
|
|
497
|
+
"get_thread_network_state_info", "get_ble_connection_info", "get_scene_diagnostic_info",
|
|
498
|
+
"get_calibration_extra_info", "get_legacy_device_info", "get_wifi_remnant_info",
|
|
499
|
+
"get_engineering_diagnostic_info", "get_channel_intensities", "get_insolation_tables",
|
|
500
|
+
"get_device_local_date",
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
async def _dump_diagnostics(device: MobiusDevice) -> None:
|
|
505
|
+
"""Prints every diagnostic getter's result (each field is None when the
|
|
506
|
+
device doesn't support it)."""
|
|
507
|
+
print(" --- diagnostics ---")
|
|
508
|
+
for name in _DIAGNOSTIC_GETTERS:
|
|
509
|
+
try:
|
|
510
|
+
value = await getattr(device, name)()
|
|
511
|
+
except Exception as e:
|
|
512
|
+
value = f"read failed: {e}"
|
|
513
|
+
print(f" {name.removeprefix('get_')}: {value}")
|
|
514
|
+
|
|
515
|
+
|
|
514
516
|
async def _print_summary(mdevice: MobiusDevice, args) -> dict:
|
|
515
517
|
"""Prints get_device_summary() plus the optional schedule/scene dumps."""
|
|
516
518
|
summary = await mdevice.get_device_summary()
|
|
@@ -520,6 +522,8 @@ async def _print_summary(mdevice: MobiusDevice, args) -> dict:
|
|
|
520
522
|
await _dump_schedule(mdevice, summary.get("support", ""))
|
|
521
523
|
if args.dump_scenes:
|
|
522
524
|
await _dump_scenes(mdevice, primitive_type_from_name(summary.get("primitive_type")))
|
|
525
|
+
if args.dump_diagnostics:
|
|
526
|
+
await _dump_diagnostics(mdevice)
|
|
523
527
|
return summary
|
|
524
528
|
|
|
525
529
|
|
|
@@ -538,11 +542,8 @@ async def _learn_peer_directly(args, found_target) -> Optional[MeshPeer]:
|
|
|
538
542
|
return None
|
|
539
543
|
print(f" Learned address directly: {target_address.hex()}")
|
|
540
544
|
return MeshPeer(
|
|
541
|
-
serial=args.relay_target,
|
|
542
|
-
model_raw=target_info.model_raw if target_info else
|
|
543
|
-
model=target_info.model if target_info else None,
|
|
544
|
-
short_address=extract_short_address(target_address),
|
|
545
|
-
address=target_address,
|
|
545
|
+
serial=args.relay_target, address=target_address,
|
|
546
|
+
model_raw=target_info.model_raw if target_info else None,
|
|
546
547
|
)
|
|
547
548
|
|
|
548
549
|
|
|
@@ -556,20 +557,14 @@ async def _write_to_group(mdevice, args, target, label: str, serial: str, summar
|
|
|
556
557
|
exceeds the smallest capacity in the group. `write(device, support,
|
|
557
558
|
serial)` performs the write for one device and returns a summary line.
|
|
558
559
|
"""
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
target_support = _support_from_primitive_type(target_info.get("primitive_type"))
|
|
564
|
-
except Exception as e:
|
|
565
|
-
print(f" Could not read {serial!r}'s own device info ({e}) -- "
|
|
566
|
-
f"writing only to it, not the rest of its group.")
|
|
567
|
-
target_group_mask = None
|
|
568
|
-
target_support = summary.get("support", "") if not args.relay_target else ""
|
|
560
|
+
# Read from the actual target: the summary describes the gateway.
|
|
561
|
+
target_support, target_group_mask = await _target_identity(
|
|
562
|
+
target, serial, summary.get("support", "") if not args.relay_target else "",
|
|
563
|
+
)
|
|
569
564
|
|
|
570
565
|
print(f"\n=== resolving schedule-group targets for {label} ===")
|
|
571
566
|
group_targets = await _resolve_group_targets(
|
|
572
|
-
mdevice, serial, target, target_group_mask, target_support,
|
|
567
|
+
mdevice, serial, target, target_group_mask, target_support,
|
|
573
568
|
pan_id=pan_id, stack=stack, args=args,
|
|
574
569
|
)
|
|
575
570
|
if len(group_targets) > 1:
|
|
@@ -653,7 +648,7 @@ async def _run_by_serial(args) -> None:
|
|
|
653
648
|
f"brief direct connection to {args.relay_target!r} to learn its address...")
|
|
654
649
|
target_peer = await _learn_peer_directly(args, found_target)
|
|
655
650
|
if target_peer is not None:
|
|
656
|
-
relayed = RelayedMobiusDevice(mdevice, target_peer
|
|
651
|
+
relayed = RelayedMobiusDevice(mdevice, target_peer)
|
|
657
652
|
try:
|
|
658
653
|
for k, v in (await relayed.get_device_summary()).items():
|
|
659
654
|
print(f" {k}: {v}")
|
|
@@ -678,12 +673,10 @@ async def _run_by_serial(args) -> None:
|
|
|
678
673
|
return f"{args.relay_target!r} (via relay through {args.by_serial!r})", relayed, args.relay_target
|
|
679
674
|
|
|
680
675
|
async def target_support(target, serial: str) -> str:
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
f"falling back to {args.by_serial!r}'s own support.")
|
|
686
|
-
return summary.get("support", "") if not args.relay_target else ""
|
|
676
|
+
support, _group_mask = await _target_identity(
|
|
677
|
+
target, serial, summary.get("support", "") if not args.relay_target else "",
|
|
678
|
+
)
|
|
679
|
+
return support
|
|
687
680
|
|
|
688
681
|
if args.reboot and (picked := pick_target("reboot()")):
|
|
689
682
|
label, target, _serial = picked
|
|
@@ -971,6 +964,11 @@ def main() -> None:
|
|
|
971
964
|
help="Also print every configured scene on each connected device -- "
|
|
972
965
|
"id, name, timeout and light/pump payload of every slot, including "
|
|
973
966
|
"empty ones.")
|
|
967
|
+
parser.add_argument("--dump-diagnostics", action="store_true",
|
|
968
|
+
help="Also print each connected device's diagnostic attributes: FSCI, "
|
|
969
|
+
"clock sync, Thread provisioning and network state, BLE connection, "
|
|
970
|
+
"scene, calibration, legacy, Wi-Fi and engineering diagnostics, "
|
|
971
|
+
"channel intensities, insolation tables and the device's local date.")
|
|
974
972
|
parser.add_argument("--dump-mesh-peers", action="store_true",
|
|
975
973
|
help="Only usable with --by-serial. After connecting, calls "
|
|
976
974
|
"discover_mesh_peers_auto() on it and prints every other device "
|
|
@@ -988,11 +986,10 @@ def main() -> None:
|
|
|
988
986
|
"get_device_summary() read to it through the gateway and prints "
|
|
989
987
|
"the result. The other --by-serial actions apply to this target.")
|
|
990
988
|
parser.add_argument("--debug-relay", action="store_true",
|
|
991
|
-
help="
|
|
992
|
-
"
|
|
993
|
-
"
|
|
994
|
-
"
|
|
995
|
-
"indication).")
|
|
989
|
+
help="Logs the raw bytes of every layer of each relayed "
|
|
990
|
+
"request/response (inner frame, outer frame, CoAP response) and "
|
|
991
|
+
"every frame the gateway receives (debug logging for "
|
|
992
|
+
"mobius.relay and mobius.device).")
|
|
996
993
|
parser.add_argument("--set-time-to-now", action="store_true",
|
|
997
994
|
help="Only usable with --by-serial. A WRITE -- use on hardware you're "
|
|
998
995
|
"prepared to have its clock changed on. Calls set_time_to_now() "
|
|
@@ -1106,6 +1103,11 @@ def main() -> None:
|
|
|
1106
1103
|
print(f"\t{element['raw_hex']}{suffix}")
|
|
1107
1104
|
return
|
|
1108
1105
|
|
|
1106
|
+
if args.debug_relay:
|
|
1107
|
+
logging.basicConfig(format=" [%(name)s] %(message)s")
|
|
1108
|
+
for name in ("mobius.relay", "mobius.device"):
|
|
1109
|
+
logging.getLogger(name).setLevel(logging.DEBUG)
|
|
1110
|
+
|
|
1109
1111
|
asyncio.run(_run(args))
|
|
1110
1112
|
|
|
1111
1113
|
|