AgentSkillsCN

vmi-reverse-engineering

当用户提出“对 VMI 进行逆向工程”、“捕获 BLE 流量”、“分析 VMI 协议”、“通过 ADB 控制 VMI 应用”、“拉取 btsnoop 日志”,或讨论 Ventilairsec 设备协议分析时,应使用此技能。

SKILL.md
--- frontmatter
name: vmi-reverse-engineering
description: This skill should be used when the user asks to "reverse engineer VMI", "capture BLE traffic", "analyze VMI protocol", "control VMI app via ADB", "pull btsnoop logs", or discusses Ventilairsec device protocol analysis.

VMI App Reverse Engineering

Control the Ventilairsec VMI+ app via ADB to capture and analyze BLE protocol traffic.

Quick Start

bash
# 1. Enable BT snoop logging (one-time setup)
./scripts/capture/vmictl.py btsnoop-enable

# 2. Connect to device
./scripts/capture/vmictl.py connect

# 3. Start capture session
SESSION=$(./scripts/capture/vmictl.py session-start my_session)
# Navigate, take checkpoints, record values, then end session
./scripts/capture/vmictl.py session-end "$SESSION"

For phone setup, ADB connection, BT snoop logging details, and troubleshooting, see playbook.md section 1.

App Control Commands

Connection

CommandDescription
connectFull sequence: launch → scan → pair → dismiss update dialog
launchJust launch the app
vmciTap VMCI device type
pairTap PAIR on scan results
dismissDismiss update dialog

Navigation (from home screen)

CommandDescription
menuOpen hamburger menu
configMenu → Configuration
simplifiedConfiguration → Simplified
maintenanceMenu → Maintenance
sensorsMenu → Sensor management

Maintenance Screens

CommandDescription
available-infoMaintenance → Available info
equipment-lifeAvailable info → Equipment life
measurementsAvailable info → Measurements (temp/humidity)
measurements-fullFull nav: home → menu → maintenance → available info → measurements
diagnosticAvailable info → Diagnostic

Configuration Screens

CommandDescription
special-modesConfiguration → Special modes (holiday, etc.)
special-modes-fullFull nav from home to Special modes
time-slotsConfiguration → Time slot configuration

Sensor Selection (from Sensor management)

CommandDescription
sensor-probe1Select Probe 1 (outlet)
sensor-probe2Select Probe 2 (inlet)
sensor-remoteSelect Remote Control

Fan Control (from home screen)

CommandDescription
fan-minSet to LOW (131 m³/h)
fan-midSet to MEDIUM (164 m³/h)
fan-maxSet to HIGH (201 m³/h)
boostActivate BOOST mode

Holiday Mode (from Special modes screen)

CommandDescription
holiday-toggleToggle Holiday mode ON/OFF
holiday-days <n>Set Holiday duration to n days

Utility

CommandDescription
screenshot [file]Take screenshot
scrollScroll down
backPress back button
uiDump UI hierarchy (XML)
resolutionShow detected resolution

Bluetooth Capture

CommandDescription
btsnoop-enableEnable FULL BT snoop logging
btstartEnable logging (basic, may be filtered)
btpullPull btsnoop logs via bugreport
session-start <name>Start capture session, outputs directory path
session-checkpoint <dir>Take timestamped screenshot, outputs image path
session-end <dir>End session, pull btsnoop logs
collect-sensors [--force]Build timestamped UI+packet evidence session for sensor analysis
should-collectCheck if sensor collection is due

Screen Hierarchy

code
HOME (fan control buttons)
├── menu
│   ├── Configuration
│   │   ├── Simplified (airflow slider)
│   │   ├── Special modes (holiday, night vent, fixed airflow)
│   │   └── Time slot configuration
│   ├── Maintenance
│   │   └── Available info
│   │       ├── Equipment life (filter days, serial)
│   │       ├── Instantaneous measurements (temp/humidity)
│   │       └── Diagnostic (component health)
│   └── Sensor management (probe selection)

Capture Session Workflow

bash
# 1. Start session (outputs directory path)
SESSION=$(./scripts/capture/vmictl.py session-start humidity_test)

# 2. Navigate to screen, take checkpoint (outputs screenshot path)
SCREENSHOT=$(./scripts/capture/vmictl.py session-checkpoint "$SESSION")

# 3. Read the screenshot to see values, then append to checkpoints.txt

# 4. End session and pull btsnoop logs
./scripts/capture/vmictl.py session-end "$SESSION"

After each checkpoint, append observed values to $SESSION/checkpoints.txt:

code
remote_temp=19
remote_humidity=55
probe1_temp=16
probe1_humidity=71
notes=after switching to Probe1 sensor

Packet Analysis

bash
# Basic extraction
python scripts/capture/extract_packets.py session/btsnoop.log

# With checkpoint correlation
python scripts/capture/extract_packets.py session/btsnoop.log \
    --checkpoints session/checkpoints.txt --window 10

# Export status packets as hex
python scripts/capture/extract_packets.py session/btsnoop.log --status-hex

For packet type reference, field offsets, and encoding details, see protocol.md.

Instructions for Claude

When helping with reverse engineering:

  1. Before capturing: Ensure BT snoop is enabled with btsnoop-enable
  2. For new protocol fields: Use capture session with checkpoints
  3. Record values: Read each checkpoint screenshot, append values to checkpoints.txt
  4. Compare packets: Use --checkpoints flag to correlate bytes with app values
  5. Navigation: Follow screen hierarchy - can't jump directly to submenus
  6. Verify results: Check screenshots in session directory

Opportunistic Data Collection

At the start of any VMI debugging session, run the sensor collection command:

bash
./scripts/capture/vmictl.py collect-sensors

This command:

  1. Checks if 15+ minutes have passed since last collection (skip if too recent)
  2. Navigates to Instantaneous Measurements screen
  3. Takes a screenshot and pulls btsnoop logs
  4. Extracts packet byte values and displays them for comparison

Use --force to collect even if less than 15 minutes have passed.

After running, read the screenshot and compare app values to packet bytes. If they differ, add a data point to GitHub issue #9.

FieldApp ScreenPacket Location
Remote tempRemote Control → TemperatureSTATUS byte 8
Remote humidityRemote Control → HumiditySTATUS byte 4
Probe 1 tempProbe N°1 → TemperatureHISTORY byte 6
Probe 1 humidityProbe N°1 → HumidityHISTORY byte 8
Probe 2 tempProbe N°2 → TemperatureHISTORY byte 11

Data is stored persistently in data/captures/ (gitignored, survives reboots).