Status: Reverse-Engineered Firmware Version: 1.0.10 Last Updated: 2025-11-02 Source: Device log analysis and BLE traffic capture
This document outlines the reverse-engineered API for the SFP Wizard (firmware ver:1.0.10). The device communicates over BLE using a text-based, REST-like API. All commands are sent as UTF-8 text strings to a "Write" characteristic, and responses are received as UTF-8 text or raw binary on "Notify" characteristics.
- Service UUID:
8E60F02E-F699-4865-B83F-F40501752184
- UUID:
9280F26C-A56F-43EA-B769-D5D732E1AC67 - Properties: Write
- Description: Accepts all text-based commands
- Format: UTF-8 encoded text strings
- UUID:
DC272A22-43F2-416B-8FA5-63A071542FAC - Properties: Notify
- Description: Sends text-based acknowledgments (e.g., "SIF write start") and status/version info. Also serves as the primary channel for binary data dumps (e.g., SFP EEPROM read).
- Format: UTF-8 text for status messages, raw binary for EEPROM data
- UUID:
D587C47F-AC6E-4388-A31C-E6CD380BA043 - Properties: Notify
- Description: Secondary notification channel. Purpose is less clear but may be used for file transfer progress or battery-level pushes.
Description: Fetches the device's firmware version.
Endpoint: /api/1.0/version
Request Format:
Type: Text (UTF-8)
Payload: "/api/1.0/version"
Response Format:
Channel: DC272A22-43F2-416B-8FA5-63A071542FAC (Notify)
Type: Text (UTF-8)
Example: "Version: 1.0.10"
Request Schema:
{
"type": "text",
"payload": "/api/1.0/version"
}Response Schema:
{
"type": "text",
"example": "Version: 1.0.10"
}Description: Fetches device status, including SFP presence, battery, and uptime.
Endpoint: [GET] /stats
Request Format:
Type: Text (UTF-8)
Payload: "[GET] /stats"
Response Format:
Channel: DC272A22-43F2-416B-8FA5-63A071542FAC (Notify)
Type: Text (UTF-8)
The response is a formatted text string. Key elements:
sfp:[ ]- No SFP module presentsfp:[x]- SFP module presentbat:[x]|^|XX%- Battery status and percentageble:[x]- Bluetooth enabledver:X.X.XX- Firmware version
Request Schema:
{
"type": "text",
"payload": "[GET] /stats"
}Response Schema:
{
"type": "text",
"example": "sysmon: ver:1.0.10, bat:[x]|^|35%, sfp:[ ], qsf:[ ], ble:[x], /fs:1.76%, dma: 46.41%, heap: 96.55%, spiram: 98.64%, mac:1c:6a:1b:05:f7:fe"
}Response Parsing:
- Check for
sfp:[x](module present) orsfp:[ ](no module) - Extract battery percentage:
bat:[x]|^|XX% - Extract firmware version:
ver:X.X.XX - Extract MAC address:
mac:XX:XX:XX:XX:XX:XX
Description: Initiates a read of the SFP module's EEPROM.
Endpoint: [POST] /sif/start
Request Format:
Type: Text (UTF-8)
Payload: "[POST] /sif/start"
Response Flow:
-
Text Acknowledgment (on DC272A22-43F2-416B-8FA5-63A071542FAC)
Type: Text (UTF-8) Example: "SIF start" -
Binary EEPROM Data (on DC272A22-43F2-416B-8FA5-63A071542FAC)
Type: Binary Size: 256 or 512 bytes (typically) Format: Raw EEPROM dump
The device first sends a text acknowledgment, then immediately follows up with one or more notifications containing the raw binary EEPROM data.
Request Schema:
{
"type": "text",
"payload": "[POST] /sif/start"
}Response Schema:
{
"acknowledgment": {
"type": "text",
"example": "SIF start"
},
"data": {
"type": "binary",
"size": "256-512 bytes",
"format": "Raw EEPROM dump following SFF-8472 specification"
}
}Description: Initiates a write to the SFP module's EEPROM. This command puts the device in a state to receive binary data.
Endpoint: [POST] /sif/write
Request Format:
Type: Text (UTF-8)
Payload: "[POST] /sif/write"
Response Flow:
-
Text Acknowledgment (on DC272A22-43F2-416B-8FA5-63A071542FAC)
Type: Text (UTF-8) Example: "SIF write start" -
Client Action: Send Binary Data
- Send raw EEPROM .bin data to the Write characteristic (9280F26C-A56F-43EA-B769-D5D732E1AC67)
- Data may need to be chunked due to BLE MTU limitations (typically 20-244 bytes)
- Send all chunks sequentially
-
Completion Acknowledgment (Assumed - on DC272A22-43F2-416B-8FA5-63A071542FAC)
Type: Text (UTF-8) Expected: "SIF write complete" or "SIF write stop"
Request Schema:
{
"type": "text",
"payload": "[POST] /sif/write"
}Response Schema:
{
"acknowledgment": {
"type": "text",
"example": "SIF write start"
},
"client_action": {
"description": "Client must send raw EEPROM binary to write characteristic",
"characteristic": "9280F26C-A56F-43EA-B769-D5D732E1AC67",
"chunking": "Required - chunk size dependent on BLE MTU (typically 20-244 bytes)"
},
"completion": {
"type": "text",
"expected": "SIF write complete or SIF write stop"
}
}Write Procedure:
- Send text command
[POST] /sif/writeto Write characteristic - Wait for
SIF write startacknowledgment on Notify characteristic - Chunk EEPROM data into MTU-appropriate sizes (recommend 20 bytes for compatibility)
- Send each chunk to Write characteristic sequentially
- Wait for completion message on Notify characteristic
Safety Considerations:
- Always backup original EEPROM before writing
- Verify data integrity before initiating write
- Monitor for error messages during write process
- Consider implementing read-back verification after write
Description: Triggers an erase operation on the SFP module's EEPROM.
Endpoint: [POST] /sif/erase
Request Format:
Type: Text (UTF-8)
Payload: "[POST] /sif/erase"
Response Flow:
-
Erase Start Acknowledgment (on DC272A22-43F2-416B-8FA5-63A071542FAC)
Type: Text (UTF-8) Example: "SIF erase start" -
Erase Complete Acknowledgment (on DC272A22-43F2-416B-8FA5-63A071542FAC)
Type: Text (UTF-8) Example: "SIF erase stop"
Request Schema:
{
"type": "text",
"payload": "[POST] /sif/erase"
}Response Schema:
{
"type": "text",
"start_message": "SIF erase start",
"stop_message": "SIF erase stop"
}Warning: Erasing EEPROM is destructive. Always backup module data before erasing.
Description: A command to stop the current SFP interface operation.
Endpoint: [POST] /sif/stop
Alternate Endpoint: /api/1.0/sif/stop
Request Format:
Type: Text (UTF-8)
Payload: "[POST] /sif/stop"
Response Format:
Channel: DC272A22-43F2-416B-8FA5-63A071542FAC (Notify)
Type: Text (UTF-8)
Expected: "SIF stop" (assumed)
Request Schema:
{
"type": "text",
"payload": "[POST] /sif/stop"
}Response Schema:
{
"type": "text",
"example": "SIF stop"
}The device sends both text and binary data on the same Notify characteristic (DC272A22-43F2-416B-8FA5-63A071542FAC). Client applications should implement heuristic detection:
- Text Data: All bytes are printable ASCII (32-126) or whitespace (9, 10, 13)
- Binary Data: Contains non-printable bytes
- Default BLE MTU is typically 23 bytes (20 bytes of payload after ATT overhead)
- Negotiated MTU can be up to 517 bytes in BLE 4.2+
- For maximum compatibility, chunk write data into 20-byte segments
- Some devices support larger MTU negotiation - test with your specific device
All text commands follow a REST-like pattern:
[HTTP_METHOD] /endpoint- Examples:
[GET] /stats,[POST] /sif/start - Some endpoints omit the HTTP method prefix:
/api/1.0/version
Error responses have not been fully documented. Monitor the Notify characteristic for:
- Text messages containing "error", "failed", or similar keywords
- Unexpected responses to commands
- Timeout conditions (no response within expected timeframe)
- Allow sufficient time between commands for device processing
- Wait for acknowledgment before sending binary data during writes
- Monitor for completion messages before initiating new operations
const SERVICE_UUID = "8E60F02E-F699-4865-B83F-F40501752184";
const WRITE_CHAR_UUID = "9280F26C-A56F-43EA-B769-D5D732E1AC67";
const NOTIFY_CHAR_UUID = "DC272A22-43F2-416B-8FA5-63A071542FAC";
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: [SERVICE_UUID] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService(SERVICE_UUID);
const writeChar = await service.getCharacteristic(WRITE_CHAR_UUID);
const notifyChar = await service.getCharacteristic(NOTIFY_CHAR_UUID);
await notifyChar.startNotifications();
notifyChar.addEventListener('characteristicvaluechanged', handleNotification);async function sendCommand(command) {
const encoder = new TextEncoder();
const data = encoder.encode(command);
await writeChar.writeValueWithoutResponse(data);
}
// Get version
await sendCommand("/api/1.0/version");
// Get status
await sendCommand("[GET] /stats");
// Read EEPROM
await sendCommand("[POST] /sif/start");async function writeEEPROM(binaryData) {
// 1. Initiate write mode
await sendCommand("[POST] /sif/write");
// 2. Wait for acknowledgment (monitor notifications)
await waitForMessage("SIF write start");
// 3. Chunk and send data
const chunkSize = 20; // Conservative for compatibility
const chunks = Math.ceil(binaryData.byteLength / chunkSize);
for (let i = 0; i < chunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize, binaryData.byteLength);
const chunk = binaryData.slice(start, end);
await writeChar.writeValueWithoutResponse(chunk);
await delay(10); // Small delay between chunks
}
// 4. Wait for completion
// Device can respond with either "SIF write stop" or "SIF write complete"
await Promise.race([
waitForMessage("SIF write stop"),
waitForMessage("SIF write complete")
]);
}- Always test with non-critical modules first
- Backup EEPROM data before any write operations
- Verify firmware version matches this specification (v1.0.10)
- Monitor all notification messages during operations
- Implement timeouts for all operations
- Test write operations with read-back verification
- Use BLE sniffers (nRF Sniffer, Ubertooth) to capture traffic for debugging
- Firmware Version Dependency: This specification is based on firmware v1.0.10. Behavior may change in future firmware versions.
- Error Codes: Specific error codes and messages have not been fully documented.
- Secondary Notify Characteristic: The purpose of UUID D587C47F-AC6E-4388-A31C-E6CD380BA043 is not fully understood.
- Write Verification: No documented endpoint for verifying write success beyond read-back comparison.
- Concurrent Operations: Behavior when multiple operations overlap is unknown.
CRITICAL WARNINGS:
- Writing incorrect EEPROM data can permanently damage modules
- Always backup original EEPROM before writing
- Never write to production modules until fully tested
- Some SFP modules have write-protection that could be bypassed
- Vendor lock-in mechanisms may be intentional (compatibility, warranty)
Recommended Safeguards:
- Require user confirmation with warning message
- Validate EEPROM data format before write
- Implement read-back verification
- Add "dry run" mode for testing
- Log all write operations
- Provide rollback/restore functionality
- Error Response Format: Document specific error messages and codes
- Secondary Notify Characteristic: Determine purpose and usage
- Write Verification: Investigate if device provides checksums or verification
- Firmware Update Protocol: Document if BLE supports firmware updates
- Advanced Features: Investigate any undocumented endpoints or capabilities
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2025-11-02 | Initial documentation based on reverse engineering of firmware v1.0.10 |
This documentation is provided as-is for educational and interoperability purposes. It is not affiliated with or endorsed by the device manufacturer. Use at your own risk.