### Setup Zephyr Environment with West Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md This section details the initial setup for the Zephyr development environment. It includes creating and activating a virtual environment, installing the 'west' build tool, initializing the Zephyr workspace, updating dependencies, and configuring build directory formatting. ```bash python -m venv .venv . ./envr.ps1 pip install west west init . west update pip install -r zephyr/scripts/requirements.txt west config build.dir-fmt "build/{board}" ``` ```bash west init -m https://github.com/nrfconnect/sdk-nrf --mr v2.6.0 ``` -------------------------------- ### Install SMP Client via pip Source: https://context7.com/intercreate/smpclient/llms.txt Commands to install the smpclient library with various transport-specific dependencies. ```bash pip install smpclient[all] pip install smpclient[serial] pip install smpclient[ble] pip install smpclient pip install smpclient[serial,ble] ``` -------------------------------- ### Perform File System Upload and Download Source: https://context7.com/intercreate/smpclient/llms.txt Provides examples for transferring files to and from a device's filesystem. Includes progress tracking for uploads and simple retrieval for downloads. ```python import asyncio import time from smpclient import SMPClient from smpclient.transport.serial import SMPSerialTransport async def upload_file(): """Upload a file to the device filesystem.""" file_content = b"Configuration data: key=value\nmode=production\n" async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: start_time = time.time() async for offset in client.upload_file( file_data=file_content, file_path="/lfs/config.txt", # Target path on device timeout_s=5.0, # Timeout per chunk ): elapsed = time.time() - start_time speed = offset / elapsed / 1000 if elapsed > 0 else 0 print(f"\rUploaded {offset:,} / {len(file_content):,} bytes ({speed:.2f} KB/s)", end="") print("\nFile upload complete!") async def download_file(): """Download a file from the device filesystem.""" async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: start_time = time.time() file_data = await client.download_file( file_path="/lfs/config.txt", timeout_s=5.0, ) elapsed = time.time() - start_time print(f"Downloaded {len(file_data)} bytes in {elapsed:.2f}s") print(f"Content: {file_data.decode('utf-8')}") if __name__ == "__main__": asyncio.run(upload_file()) asyncio.run(download_file()) ``` -------------------------------- ### Flash Signed App and Merge Hex for NXP Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md Instructions for flashing signed application firmware onto the NXP MIMXRT1060-EVKB board and an example of merging bootloader and application HEX files for a single flash operation. ```bash west flash --runner=linkserver -d build/mimxrt1060_evkb ``` ```python python zephyr/scripts/build/mergehex.py --output a_smp_dut_8192_1_8192.merged.hex build/mimxrt1060_evkb_mcuboot/zephyr/zephyr.hex build/mimxrt1060_evkb/zephyr/zephyr.signed.hex ``` ```bash west flash --runner=linkserver -d build/mimxrt1060_evkb --hex-file a_smp_dut_8192_1_8192.merged.hex ``` -------------------------------- ### Manage Firmware Images with SMPClient Source: https://context7.com/intercreate/smpclient/llms.txt This Python code snippet illustrates how to manage firmware images on a device using SMPClient. It covers reading image states, marking images for testing or confirmation, and erasing image slots. Proper setup of the smpclient library and serial transport is required. Use erase operations with caution. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.image_management import ( ImageStatesRead, ImageStatesWrite, ImageErase, ) from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Read current image states states = await client.request(ImageStatesRead()) if success(states): for image in states.images: print(f"Slot {image.slot}:") print(f" Version: {image.version}") print(f" Hash: {image.hash.hex()}") print(f" Bootable: {image.bootable}") print(f" Pending: {image.pending}") print(f" Confirmed: {image.confirmed}") print(f" Active: {image.active}") print(f" Permanent: {image.permanent}") # Mark an image for test boot (by hash) if success(states) and len(states.images) > 1: target_hash = states.images[1].hash confirm = await client.request(ImageStatesWrite(hash=target_hash)) if success(confirm): print("Image marked for test boot") # Or confirm permanently # await client.request(ImageStatesWrite(hash=target_hash, confirm=True)) # Erase secondary slot (slot 1) erase = await client.request(ImageErase(slot=1)) if success(erase): print("Secondary slot erased") elif error(erase): print(f"Erase failed: {erase.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Python: Type-Safe Response Handling with SMPClient Source: https://context7.com/intercreate/smpclient/llms.txt This Python code snippet demonstrates how to use the SMPClient to send a request and then handle the response in a type-safe manner. It utilizes helper functions like `success()`, `error()`, `error_v1()`, and `error_v2()` for exhaustive pattern matching on different response types. The example also includes error handling for common exceptions like `TimeoutError`, `SMPBadSequence`, `SMPUploadError`, and `ConnectionError`. Dependencies include `asyncio`, `typing_extensions`, and the `smpclient` library. ```python import asyncio from typing_extensions import assert_never from smpclient import SMPClient from smpclient.generics import error, error_v1, error_v2, success from smpclient.requests.os_management import EchoWrite from smpclient.transport.serial import SMPSerialTransport from smpclient.exceptions import SMPBadSequence, SMPUploadError async def main(): try: async with SMPClient( SMPSerialTransport(), "/dev/ttyACM0", timeout_s=5.0 # Default timeout for all requests ) as client: # Send request with custom timeout response = await client.request( EchoWrite(d="test"), timeout_s=10.0 # Override default timeout ) # Exhaustive type-safe response handling if success(response): # response is narrowed to EchoWriteResponse print(f"Success: {response.d}") elif error(response): # response is narrowed to ErrorV1 | ErrorV2 if error_v1(response): # response is narrowed to ErrorV1 print(f"Error V1 - rc: {response.rc}") elif error_v2(response): # response is narrowed to ErrorV2 print(f"Error V2 - rc: {response.rc}, group: {response.group}") else: assert_never(response) # Exhaustiveness check else: assert_never(response) # Exhaustiveness check except TimeoutError as e: print(f"Request timed out: {e}") except SMPBadSequence as e: print(f"Protocol sequence mismatch: {e}") except SMPUploadError as e: print(f"Upload failed: {e}") except ConnectionError as e: print(f"Connection failed: {e}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### View SMP Upgrade Help Source: https://github.com/intercreate/smpclient/blob/main/examples/ble/README.md Displays the help menu for the upgrade script, detailing required positional arguments and available options for the DFU test. ```bash python -m examples.ble.upgrade --help ``` -------------------------------- ### Build SMP Server Firmware for Nordic Boards Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md These commands demonstrate how to build the SMP server firmware for various Nordic Semiconductor development boards. It specifies the board, the Zephyr sample to build, and extra configuration files for Bluetooth or USB CDC ACM communication. ```bash west build -b nrf52dk_nrf52832 zephyr/samples/subsys/mgmt/mcumgr/smp_svr -- -DEXTRA_CONF_FILE="overlay-bt.conf;${ENVR_ROOT}/ble_a_smp_dut.conf" ``` ```bash west build -b adafruit_feather_nrf52840 zephyr/samples/subsys/mgmt/mcumgr/smp_svr -- -DEXTRA_CONF_FILE="overlay-cdc.conf" -DEXTRA_DTC_OVERLAY_FILE="usb.overlay" ``` ```bash west build -b nrf52840dk_nrf52840 zephyr/samples/subsys/mgmt/mcumgr/smp_svr -- -DEXTRA_CONF_FILE="overlay-cdc.conf;${ENVR_ROOT}/usb_a_smp_dut.conf;${ENVR_ROOT}/usb_smp_dut_512_8_4096.conf" -DEXTRA_DTC_OVERLAY_FILE="usb.overlay" ``` ```bash west build -b nrf52840dk_nrf52840 zephyr/samples/subsys/mgmt/mcumgr/smp_svr -- -DEXTRA_CONF_FILE="overlay-bt.conf;overlay-cdc.conf;${ENVR_ROOT}/usb_a_smp_dut.conf" -DEXTRA_DTC_OVERLAY_FILE="usb.overlay" -Dmcuboot_CONF_FILE="../../../../mcuboot_usb.conf" -Dmcuboot_DTS_FILE="../../../../mcuboot_usb.overlay" ``` -------------------------------- ### Scan and Connect to BLE SMP Servers Source: https://context7.com/intercreate/smpclient/llms.txt Shows how to discover available SMP-compatible BLE devices and establish a connection for communication. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.os_management import EchoWrite from smpclient.transport.ble import SMPBLETransport async def main(): smp_servers = await SMPBLETransport.scan(timeout=5) if not smp_servers: return async with SMPClient(SMPBLETransport(), smp_servers[0].address) as client: response = await client.request(EchoWrite(d="Hello via BLE!")) if success(response): print(f"Response: {response.d}") elif error(response): print(f"Error code: {response.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Configure UDP Transport for SMPClient Source: https://context7.com/intercreate/smpclient/llms.txt Demonstrates how to initialize an SMPClient using UDP transport. It includes setting the MTU and performing a basic echo request to verify connectivity. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.os_management import EchoWrite from smpclient.transport.udp import SMPUDPTransport async def main(): # Configure UDP transport with MTU (default: 1500) transport = SMPUDPTransport(mtu=1500) # Connect to device IP address (default SMP port: 1337) async with SMPClient(transport, "192.168.1.100") as client: response = await client.request(EchoWrite(d="Hello via UDP!")) if success(response): print(f"Response: {response.d}") elif error(response): print(f"Error code: {response.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Initialize SMPClient with BLE Transport Source: https://context7.com/intercreate/smpclient/llms.txt Demonstrates how to instantiate an SMPClient using the BLE transport to send an echo request to an embedded device. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.os_management import EchoWrite from smpclient.transport.ble import SMPBLETransport async def main(): async with SMPClient(SMPBLETransport(), "00:11:22:33:44:55") as client: response = await client.request(EchoWrite(d="Hello, World!")) if success(response): print(f"Echo response: {response.d}") elif error(response): print(f"Error: {response.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Build and Flash MCUBoot for NXP MIMXRT1060-EVKB Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md Instructions for building and flashing the MCUBoot bootloader onto the NXP MIMXRT1060-EVKB board. This is a prerequisite for flashing signed application firmware. ```bash west build -b mimxrt1060_evkb -d build/mimxrt1060_evkb_mcuboot bootloader/mcuboot/boot/zephyr -- -DCONFIG_BUILD_OUTPUT_HEX=y ``` ```bash west flash --runner=linkserver -d build/mimxrt1060_evkb_mcuboot ``` -------------------------------- ### Build SMP Server Firmware for NXP MIMXRT1060-EVKB Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md Commands to build the SMP server firmware for the NXP MIMXRT1060-EVKB board, supporting USB CDC ACM and UDP (Ethernet) communication. It includes options for generating HEX output and specifying configuration files. ```bash west build -b mimxrt1060_evkb zephyr/samples/subsys/mgmt/mcumgr/smp_svr -- -DEXTRA_CONF_FILE="overlay-cdc.conf;${ENVR_ROOT}/usb_a_smp_dut.conf;${ENVR_ROOT}/usb_smp_dut_8192_1_8192.conf" -DEXTRA_DTC_OVERLAY_FILE="usb.overlay" -DCONFIG_BUILD_OUTPUT_HEX=y ``` ```bash west build -b mimxrt1060_evkb zephyr/samples/subsys/mgmt/mcumgr/smp_svr -- -DEXTRA_CONF_FILE="overlay-udp.conf;${ENVR_ROOT}/udp_a_smp_dut.conf" -DCONFIG_BUILD_OUTPUT_HEX=y ``` -------------------------------- ### Execute SMP BLE Upgrade Test Source: https://github.com/intercreate/smpclient/blob/main/examples/ble/README.md Runs the SMP DFU upgrade test script for a specified target board. This script flashes the firmware, connects via BLE, uploads the new image, and verifies the swap process. ```bash python -m examples.ble.upgrade adafruit_feather_nrf52840 python -m examples.ble.upgrade nrf52dk_nrf52832 ``` -------------------------------- ### Execute OS Management Commands with SMPClient Source: https://context7.com/intercreate/smpclient/llms.txt This Python code snippet demonstrates how to use SMPClient to execute various OS-level commands on a device. It includes functionalities for echo tests, reading/writing device time, querying application and bootloader information, and retrieving task statistics. Ensure the smpclient library and a serial transport are correctly set up. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.os_management import ( EchoWrite, ResetWrite, DateTimeRead, DateTimeWrite, MCUMgrParametersRead, OSApplicationInfoRead, BootloaderInformationRead, TaskStatisticsRead, MemoryPoolStatisticsRead, ) from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Echo test - verify connectivity echo_response = await client.request(EchoWrite(d="ping")) if success(echo_response): print(f"Echo: {echo_response.d}") # Read MCUMgr parameters (buffer size, etc.) params = await client.request(MCUMgrParametersRead()) if success(params): print(f"Buffer size: {params.buf_size} bytes") print(f"Buffer count: {params.buf_count}") # Read application info app_info = await client.request(OSApplicationInfoRead()) if success(app_info): print(f"App output: {app_info.output}") # Read bootloader info boot_info = await client.request(BootloaderInformationRead()) if success(boot_info): print(f"Bootloader: {boot_info.bootloader}") # Read/write datetime dt_response = await client.request(DateTimeRead()) if success(dt_response): print(f"Device time: {dt_response.datetime}") # Set datetime (ISO 8601 format) await client.request(DateTimeWrite(datetime="2024-01-15T12:00:00")) # Read task statistics tasks = await client.request(TaskStatisticsRead()) if success(tasks): for task in tasks.tasks.values(): print(f"Task: {task}") # Reset device (use with caution) # await client.request(ResetWrite()) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### File Management Commands with SMPClient (Python) Source: https://context7.com/intercreate/smpclient/llms.txt Manage files on the device filesystem using SMPClient. This includes checking file status, verifying hashes, downloading, uploading, and closing file handles. It requires the smpclient library and asyncio. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.file_management import ( FileDownload, FileUpload, FileStatus, FileHashChecksum, SupportedFileHashChecksumTypes, FileClose, ) from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Check supported hash/checksum types hash_types = await client.request(SupportedFileHashChecksumTypes()) if success(hash_types): print(f"Supported hash types: {hash_types.types}") # Get file status (size) status = await client.request(FileStatus(name="/lfs/config.txt")) if success(status): print(f"File size: {status.len} bytes") elif error(status): print(f"File not found or error: {status.rc}") # Get file hash/checksum checksum = await client.request(FileHashChecksum( name="/lfs/config.txt", type="sha256", # or "crc32" depending on device support )) if success(checksum): print(f"File hash: {checksum.output.hex()}") # Low-level file download (chunked) download = await client.request(FileDownload(off=0, name="/lfs/config.txt")) if success(download): print(f"File length: {download.len}") print(f"First chunk: {download.data}") # Low-level file upload (single chunk) upload = await client.request(FileUpload( name="/lfs/test.txt", off=0, data=b"Hello, device!", len=14, # Total file length (required on first chunk) )) if success(upload): print(f"Uploaded to offset: {upload.off}") # Close file handle close = await client.request(FileClose()) if success(close): print("File handle closed") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Settings Management Commands with SMPClient (Python) Source: https://context7.com/intercreate/smpclient/llms.txt Read, write, and manage device settings stored in persistent storage using SMPClient. This includes operations like reading, writing, deleting settings, saving, loading, and committing changes. It requires the smpclient library and asyncio. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.settings_management import ( ReadSetting, WriteSetting, DeleteSetting, CommitSettings, LoadSettings, SaveSettings, ) from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Read a setting by name setting = await client.request(ReadSetting(name="device/name")) if success(setting): print(f"Setting value: {setting.val}") elif error(setting): print(f"Setting not found: {setting.rc}") # Write a setting write = await client.request(WriteSetting( name="device/name", val=b"MyDevice", # Value as bytes )) if success(write): print("Setting written") # Delete a setting delete = await client.request(DeleteSetting(name="device/temp_config")) if success(delete): print("Setting deleted") # Save settings to persistent storage save = await client.request(SaveSettings()) if success(save): print("Settings saved to flash") # Load settings from persistent storage load = await client.request(LoadSettings()) if success(load): print("Settings loaded from flash") # Commit pending setting changes commit = await client.request(CommitSettings()) if success(commit): print("Settings committed") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Flash Firmware on Nordic Boards Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md Commands to flash the compiled firmware onto Nordic development boards. Includes options for recovering the device and flashing specific build outputs. ```bash west flash -d build/nrf52dk_nrf52832 --recover ``` -------------------------------- ### Query Runtime Statistics Groups and Data with SMPClient (Python) Source: https://context7.com/intercreate/smpclient/llms.txt This snippet demonstrates how to list available statistics groups and retrieve data for a specific group using the smpclient library. It requires the smpclient and asyncio libraries. The input is a device connection, and the output is printed statistics data or error codes. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.statistics_management import GroupData, ListOfGroups from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # List available statistics groups groups = await client.request(ListOfGroups()) if success(groups): print(f"Available groups: {groups.stat_list}") # Get data for a specific group data = await client.request(GroupData(name="sys")) if success(data): print(f"Group: {data.name}") print(f"Statistics: {data.fields}") elif error(data): print(f"Group not found: {data.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### SMPClient Core Operations Source: https://context7.com/intercreate/smpclient/llms.txt Demonstrates the core usage of the SMPClient class to send requests to an SMP server and handle responses using type-safe Pydantic models. ```APIDOC ## POST /request/echo ### Description Sends an echo request to the SMP server to verify connectivity and protocol handling. ### Method POST ### Endpoint /request/echo ### Request Body - **d** (string) - Required - The message string to be echoed back by the device. ### Request Example { "d": "Hello, World!" } ### Response #### Success Response (200) - **d** (string) - The echoed message string from the device. #### Response Example { "d": "Hello, World!" } ``` -------------------------------- ### Shell Management Commands with SMPClient (Python) Source: https://context7.com/intercreate/smpclient/llms.txt Execute shell commands on the device and retrieve their output using SMPClient. This functionality allows for running arbitrary commands and processing their return codes and standard output. It requires the smpclient library and asyncio. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.shell_management import Execute from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Execute a shell command result = await client.request(Execute(argv=["kernel", "version"])) if success(result): print(f"Return code: {result.ret}") print(f"Output: {result.o}") elif error(result): print(f"Shell error: {result.rc}") # Execute another command result = await client.request(Execute(argv=["device", "list"])) if success(result): print(f"Devices:\n{result.o}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Inspect MCUBoot Firmware Images (Python) Source: https://context7.com/intercreate/smpclient/llms.txt This Python script allows inspection of MCUBoot-compatible firmware images, extracting header information, version details, and TLV data. It utilizes the smpclient.mcuboot module and can process .bin and .hex files. The input is a firmware file path, and the output includes detailed image information. ```python from smpclient.mcuboot import ImageInfo, IMAGE_TLV, ImageHeader, ImageVersion # Load and inspect a firmware image (supports .bin and .hex files) image_info = ImageInfo.load_file("firmware.bin") # Access header information header = image_info.header print(f"Image version: {header.ver}") # e.g., "1.2.3-build45" print(f"Image size: {header.img_size} bytes") print(f"Header size: {header.hdr_size} bytes") print(f"Load address: 0x{header.load_addr:08x}") print(f"Flags: {header.flags}") # Access individual version components version: ImageVersion = header.ver print(f"Major: {version.major}") print(f"Minor: {version.minor}") print(f"Revision: {version.revision}") print(f"Build: {version.build_num}") # Access TLV (Type-Length-Value) data print(f"\nTLV Info: {image_info.tlv_info}") for tlv in image_info.tlvs: print(f" {tlv}") # Get specific TLV by type try: sha256_tlv = image_info.get_tlv(IMAGE_TLV.SHA256) print(f"\nSHA256 hash: {sha256_tlv.value.hex()}") except Exception as e: print(f"SHA256 TLV not found: {e}") # Full image info string representation print(f"\n{image_info}") # Command-line usage: mcuimg firmware.bin ``` -------------------------------- ### Upload Firmware Images via Serial Source: https://context7.com/intercreate/smpclient/llms.txt Shows how to upload MCUBoot-compatible firmware images to a device using serial transport. It covers checking image states, tracking upload progress, and triggering a device reset for firmware swapping. ```python import asyncio import time from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.image_management import ImageStatesRead, ImageStatesWrite from smpclient.requests.os_management import ResetWrite from smpclient.transport.serial import SMPSerialTransport async def main(): # Load firmware image with open("firmware.bin", "rb") as f: firmware_data = f.read() async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Check current image states states = await client.request(ImageStatesRead()) if success(states): print(f"Current images: {states.images}") # Upload firmware to slot 0 (primary) or slot 1 (secondary) start_time = time.time() async for offset in client.upload( image=firmware_data, slot=0, # Target slot (0=primary, 1=secondary) upgrade=False, # Don't auto-confirm (safer) first_timeout_s=40.0, # First packet may take longer (flash erase) subsequent_timeout_s=2.5, # Subsequent packets timeout use_sha=True, # Include SHA256 for verification ): elapsed = time.time() - start_time speed = offset / elapsed / 1000 if elapsed > 0 else 0 print(f"\rUploaded {offset:,} / {len(firmware_data):,} bytes ({speed:.2f} KB/s)", end="") print("\nUpload complete!") # Verify upload by checking image states states = await client.request(ImageStatesRead()) if success(states) and len(states.images) > 1: # Mark new image for test boot new_image_hash = states.images[1].hash await client.request(ImageStatesWrite(hash=new_image_hash)) # Reset device to boot new firmware await client.request(ResetWrite()) print("Device reset for firmware swap") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Execute Zephyr Management Operations with SMPClient (Python) Source: https://context7.com/intercreate/smpclient/llms.txt This code snippet shows how to perform Zephyr-specific management operations, such as erasing storage, using the smpclient library. It depends on smpclient, asyncio, and specific request modules. The input is a device connection, and the output indicates success or failure of the storage erase operation. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.zephyr_management import EraseStorage from smpclient.transport.serial import SMPSerialTransport async def main(): async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Erase storage partition (use with caution!) erase = await client.request(EraseStorage()) if success(erase): print("Storage erased successfully") elif error(erase): print(f"Erase failed: {erase.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Serial Transport Configuration Source: https://context7.com/intercreate/smpclient/llms.txt Details the configuration parameters for establishing a serial connection (UART, USB, CAN) with an SMP server. ```APIDOC ## CONNECT /transport/serial ### Description Establishes a serial connection to an SMP server with specific framing and baud rate settings. ### Method CONNECT ### Parameters #### Request Body - **max_smp_encoded_frame_size** (integer) - Optional - Maximum encoded frame size. - **line_length** (integer) - Optional - SMP packet line length. - **baudrate** (integer) - Optional - Baud rate for UART connections. ``` -------------------------------- ### File Upload and Download Source: https://context7.com/intercreate/smpclient/llms.txt Enables the transfer of files to and from the device's filesystem, supporting chunked transfers and progress tracking. ```APIDOC ## File Upload and Download Transfer files to and from the device filesystem with chunked transfers and progress tracking. ### Method POST (Implicit through SMPClient) ### Endpoint `/dev/ttyACM0` (Serial Port) ### Description This section provides examples for uploading a file to the device's filesystem and downloading a file from it using `SMPSerialTransport`. Both operations include progress tracking. #### File Upload ### Parameters (upload_file) #### Request Body (Implicit in `client.upload_file`) - **file_data** (bytes) - The content of the file to upload. - **file_path** (string) - The target path on the device filesystem. - **timeout_s** (float) - Timeout for each chunk transfer. ### Request Example (upload_file) ```python import asyncio import time from smpclient import SMPClient from smpclient.transport.serial import SMPSerialTransport async def upload_file(): """Upload a file to the device filesystem.""" file_content = b"Configuration data: key=value\nmode=production\n" async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: start_time = time.time() async for offset in client.upload_file( file_data=file_content, file_path="/lfs/config.txt", # Target path on device timeout_s=5.0, # Timeout per chunk ): elapsed = time.time() - start_time speed = offset / elapsed / 1000 if elapsed > 0 else 0 print(f"\rUploaded {offset:,} / {len(file_content):,} bytes ({speed:.2f} KB/s)", end="") print("\nFile upload complete!") if __name__ == "__main__": asyncio.run(upload_file()) ``` #### File Download ### Parameters (download_file) #### Query Parameters - **file_path** (string) - Required - The path to the file on the device. - **timeout_s** (float) - Optional - Timeout for the transfer. ### Request Example (download_file) ```python import asyncio import time from smpclient import SMPClient from smpclient.transport.serial import SMPSerialTransport async def download_file(): """Download a file from the device filesystem.""" async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: start_time = time.time() file_data = await client.download_file( file_path="/lfs/config.txt", timeout_s=5.0, ) elapsed = time.time() - start_time print(f"Downloaded {len(file_data)} bytes in {elapsed:.2f}s") print(f"Content: {file_data.decode('utf-8')}") if __name__ == "__main__": asyncio.run(download_file()) ``` ### Response #### Success Response (200 OK) - File Download - **file_data** (bytes) - The content of the downloaded file. #### Response Example (File Download) ``` Downloaded 45 bytes in 0.12s Content: Configuration data: key=value\nmode=production\n ``` #### Progress Indicator (during upload) - Displays uploaded bytes and transfer speed. #### Response Example (during upload) ``` Uploaded 45 / 45 bytes (375.00 KB/s) ``` ``` -------------------------------- ### Firmware Image Upload Source: https://context7.com/intercreate/smpclient/llms.txt Facilitates the upload of MCUBoot-compatible firmware images to a device, featuring progress tracking and automatic data chunking. ```APIDOC ## Firmware Image Upload Upload MCUBoot-compatible firmware images to a device with progress tracking and automatic chunking. ### Method POST (Implicit through SMPClient) ### Endpoint `/dev/ttyACM0` (Serial Port) ### Description This example shows how to upload a firmware image to a device using `SMPSerialTransport`. It includes steps for checking image states, uploading the image in chunks, and verifying the upload. ### Parameters #### Request Body (Implicit in `client.upload`) - **image** (bytes) - The firmware image data. - **slot** (integer) - The target slot for the firmware (0 for primary, 1 for secondary). - **upgrade** (boolean) - Whether to automatically confirm the upgrade. - **first_timeout_s** (float) - Timeout for the first packet. - **subsequent_timeout_s** (float) - Timeout for subsequent packets. - **use_sha** (boolean) - Whether to include SHA256 for verification. ### Request Example ```python import asyncio import time from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.image_management import ImageStatesRead, ImageStatesWrite from smpclient.requests.os_management import ResetWrite from smpclient.transport.serial import SMPSerialTransport async def main(): # Load firmware image with open("firmware.bin", "rb") as f: firmware_data = f.read() async with SMPClient(SMPSerialTransport(), "/dev/ttyACM0") as client: # Check current image states states = await client.request(ImageStatesRead()) if success(states): print(f"Current images: {states.images}") # Upload firmware to slot 0 (primary) or slot 1 (secondary) start_time = time.time() async for offset in client.upload( image=firmware_data, slot=0, # Target slot (0=primary, 1=secondary) upgrade=False, # Don't auto-confirm (safer) first_timeout_s=40.0, # First packet may take longer (flash erase) subsequent_timeout_s=2.5, # Subsequent packets timeout use_sha=True, # Include SHA256 for verification ): elapsed = time.time() - start_time speed = offset / elapsed / 1000 if elapsed > 0 else 0 print(f"\rUploaded {offset:,} / {len(firmware_data):,} bytes ({speed:.2f} KB/s)", end="") print("\nUpload complete!") # Verify upload by checking image states states = await client.request(ImageStatesRead()) if success(states) and len(states.images) > 1: # Mark new image for test boot new_image_hash = states.images[1].hash await client.request(ImageStatesWrite(hash=new_image_hash)) # Reset device to boot new firmware await client.request(ResetWrite()) print("Device reset for firmware swap") if __name__ == "__main__": asyncio.run(main()) ``` ### Response #### Success Response (200 OK) - **images** (list) - A list of image status objects, each containing details like hash, len, and active status. #### Response Example (ImageStatesRead) ```json { "images": [ { "hash": "0xabcdef1234567890...", "len": 102400, "active": true, "pending": false } ] } ``` #### Progress Indicator (during upload) - Displays uploaded bytes and transfer speed. #### Response Example (during upload) ``` Uploaded 51200 / 102400 bytes (50.00 KB/s) ``` ``` -------------------------------- ### Build MCUBoot with Serial Recovery for ST STM32F4-DISCO Source: https://github.com/intercreate/smpclient/blob/main/dutfirmware/README.md This command builds the MCUBoot bootloader for the STMicroelectronics STM32F4-DISCO board, configured with serial recovery capabilities. It specifies DTS overlays and configuration files for serial communication and recovery button functionality. ```bash west build -b stm32f4_disco -d build/stm32f4_disco_mcuboot bootloader/mcuboot/boot/zephyr -- -DCONFIG_BUILD_OUTPUT_HEX=y -DEXTRA_DTC_OVERLAY_FILE="${ENVR_ROOT}/stm32f4_disco_flash_overlay.dts;${ENVR_ROOT}/stm32f4_disco_serial_overlay.dts;${ENVR_ROOT}/stm32f4_disco_serial_recovery_button_overlay.dts" -DEXTRA_CONF_FILE="${ENVR_ROOT}/mcuboot_serial.conf" ``` -------------------------------- ### BLE Transport Discovery Source: https://context7.com/intercreate/smpclient/llms.txt Explains how to scan for and connect to SMP-compatible devices over Bluetooth Low Energy. ```APIDOC ## GET /transport/ble/scan ### Description Scans for nearby BLE devices that advertise the SMP GATT service. ### Method GET ### Parameters #### Query Parameters - **timeout** (integer) - Optional - Time in seconds to perform the scan. Default is 5. ### Response #### Success Response (200) - **devices** (array) - A list of discovered SMP server objects containing address and name properties. ``` -------------------------------- ### Error Handling and Type Safety Source: https://context7.com/intercreate/smpclient/llms.txt Guidelines for handling SMP responses using type-safe helpers and exhaustive pattern matching. ```APIDOC ## Response Handling ### Description Use the `success()`, `error()`, `error_v1()`, and `error_v2()` helpers to perform exhaustive type-safe checking on responses. ### Pattern - `success(response)`: Returns true if the request was successful. - `error(response)`: Returns true if the response contains an error code. - `error_v1(response)`: Narrows the error to V1 schema. - `error_v2(response)`: Narrows the error to V2 schema. ### Example ```python if success(response): # Handle success elif error(response): if error_v1(response): # Handle V1 error elif error_v2(response): # Handle V2 error ``` ``` -------------------------------- ### Configure and Connect via Serial Transport Source: https://context7.com/intercreate/smpclient/llms.txt Configures the serial transport with custom framing parameters and connects to a specific serial port. ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.os_management import EchoWrite from smpclient.transport.serial import SMPSerialTransport async def main(): transport = SMPSerialTransport( max_smp_encoded_frame_size=256, line_length=128, line_buffers=2, baudrate=115200, ) async with SMPClient(transport, "/dev/ttyACM0") as client: response = await client.request(EchoWrite(d="Hello via Serial!")) if success(response): print(f"Response: {response.d}") elif error(response): print(f"Error code: {response.rc}") if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### POST /echo Source: https://context7.com/intercreate/smpclient/llms.txt Sends an echo request to the device to verify connectivity and communication integrity. ```APIDOC ## POST /echo ### Description Sends a string payload to the device which returns the same string in the response. ### Method POST ### Endpoint /echo ### Parameters #### Request Body - **d** (string) - Required - The string payload to echo. ### Request Example { "d": "test" } ### Response #### Success Response (200) - **d** (string) - The echoed string payload. #### Response Example { "d": "test" } ``` -------------------------------- ### UDP Transport Source: https://context7.com/intercreate/smpclient/llms.txt Establishes network connections over Wi-Fi or Ethernet using UDP transport, with automatic IPv4/IPv6 detection. ```APIDOC ## UDP Transport UDP transport for network connections over Wi-Fi or Ethernet with automatic IPv4/IPv6 detection. ### Method POST (Implicit through SMPClient) ### Endpoint (Device IP Address, default SMP port: 1337) ### Description This example demonstrates how to configure and use the `SMPUDPTransport` to send an `EchoWrite` request to a device. ### Request Example ```python import asyncio from smpclient import SMPClient from smpclient.generics import error, success from smpclient.requests.os_management import EchoWrite from smpclient.transport.udp import SMPUDPTransport async def main(): # Configure UDP transport with MTU (default: 1500) transport = SMPUDPTransport(mtu=1500) # Connect to device IP address (default SMP port: 1337) async with SMPClient(transport, "192.168.1.100") as client: response = await client.request(EchoWrite(d="Hello via UDP!")) if success(response): print(f"Response: {response.d}") elif error(response): print(f"Error code: {response.rc}") if __name__ == "__main__": asyncio.run(main()) ``` ### Response #### Success Response (200 OK) - **d** (string) - The echoed data from the device. #### Response Example ```json { "d": "Hello via UDP!" } ``` #### Error Response (e.g., 400 Bad Request) - **rc** (integer) - The error code returned by the device. #### Error Response Example ```json { "rc": 1 } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.