mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-29 07:37:48 +01:00
somewhat working file sync
This commit is contained in:
@@ -25,5 +25,65 @@ This SwiftUI app connects to the Cardboy device over Bluetooth Low Energy and up
|
||||
2. Ensure the `CoreBluetooth` capability is enabled for the `cardboy-companion` target and keep the *Uses Bluetooth LE accessories* background mode on (preconfigured in this project).
|
||||
3. Build & run on a real device (BLE is not available in the simulator).
|
||||
4. Allow Bluetooth permissions when prompted. The app keeps scanning in the background, so the Cardboy can request a sync even while the companion is not foregrounded. Tap **Sync Now** any time you want to trigger a manual refresh.
|
||||
5. Switch to the **Files** tab to browse the LittleFS volume on the Cardboy: you can upload ROMs from the Files picker, create/remove folders, rename entries, delete files, and download items back to the phone for sharing.
|
||||
|
||||
## BLE File Service Protocol
|
||||
|
||||
The ESP firmware exposes a custom GATT service (UUID `00000010-CA7B-4EFD-B5A6-10C3F4D3F230`) with two characteristics:
|
||||
|
||||
| Characteristic | UUID | Properties | Direction | Description |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| File Command | `00000011-CA7B-4EFD-B5A6-10C3F4D3F231` | Write / Write Without Response | iOS → ESP | Sends file management requests |
|
||||
| File Response | `00000012-CA7B-4EFD-B5A6-10C3F4D3F232` | Notify | ESP → iOS | Streams command results (responses or data) |
|
||||
|
||||
All payloads share the same framing. Commands written to the File Command characteristic use:
|
||||
|
||||
```
|
||||
Offset | Size | Description
|
||||
-------+------+------------
|
||||
0 | 1 | Opcode (see table below)
|
||||
1 | 1 | Reserved (set to 0)
|
||||
2 | 2 | Little-endian payload length in bytes (N)
|
||||
4 | N | Command payload
|
||||
```
|
||||
|
||||
Notifications from the File Response characteristic use:
|
||||
|
||||
```
|
||||
Offset | Size | Description
|
||||
-------+------+------------
|
||||
0 | 1 | Opcode (echoed from command)
|
||||
1 | 1 | Status byte (bit 7 = completion flag; lower 7 bits = error code)
|
||||
2 | 2 | Little-endian payload length (N)
|
||||
4 | N | Response payload (command-specific)
|
||||
```
|
||||
|
||||
Status byte semantics:
|
||||
- Bit 7 (0x80) set → final packet for the current command (no further fragments).
|
||||
- Lower 7 bits = error code (`0` = success, otherwise `errno`-style code echoed back).
|
||||
- On error the response payload may contain a UTF-8 message.
|
||||
|
||||
### Opcodes and Payloads
|
||||
|
||||
| Opcode | Name | Command Payload | Response Payload |
|
||||
| --- | --- | --- | --- |
|
||||
| `0x01` | List Directory | `uint16 path_len` + UTF-8 path | One or more fragments, each entry encoded as:<br> - `uint8 type` (0=file, 1=dir)<br> - `uint8 reserved`<br> - `uint16 name_len`<br> - `uint32 size` (0 for dirs)<br> - `name_len` bytes UTF-8 name<br> Final notification has completion bit set. |
|
||||
| `0x02` | Upload Begin | `uint16 path_len` + UTF-8 path + `uint32 file_size` | Empty payload on success. Starts upload session (expects `UploadChunk` packets). |
|
||||
| `0x03` | Upload Chunk | Raw file bytes | Empty payload ack for each chunk. |
|
||||
| `0x04` | Upload End | No payload | Empty payload confirming completion. |
|
||||
| `0x05` | Download Request | `uint16 path_len` + UTF-8 path | First notification: 4-byte little-endian total file size; subsequent notifications stream raw file data fragments. Completion bit marks the final chunk. |
|
||||
| `0x06` | Delete File | `uint16 path_len` + UTF-8 path | Empty payload on success. |
|
||||
| `0x07` | Create Directory | `uint16 path_len` + UTF-8 path | Empty payload on success. |
|
||||
| `0x08` | Delete Directory | `uint16 path_len` + UTF-8 path | Empty payload on success. |
|
||||
| `0x09` | Rename Path | `uint16 src_len` + UTF-8 source path + `uint16 dst_len` + UTF-8 destination path | Empty payload on success. |
|
||||
|
||||
### Notes
|
||||
|
||||
- Paths are absolute within the LittleFS volume; the firmware normalizes them and rejects entries containing `..`.
|
||||
- Large responses (directory lists, downloads) may arrive in multiple notifications; the iOS client aggregates fragments until it sees the completion flag.
|
||||
- Uploads are initiated with `Upload Begin` (including total size), followed by one or more `Upload Chunk` writes, and `Upload End` when done.
|
||||
- Errors from the firmware propagate via the status byte; when `status & 0x7F != 0`, the notification payload typically includes a UTF-8 error message (e.g., `"stat failed"`).
|
||||
|
||||
This protocol mirrors the implementation in `components/backend-esp/src/time_sync_service.cpp` and the Swift client in `TimeSyncManager.swift`. Update both sides if new commands are added.
|
||||
|
||||
Optionally bundle this code into your existing app—`TimeSyncManager` is self‑contained and can be reused.
|
||||
|
||||
Reference in New Issue
Block a user