Skip to content

kitprojects/nanlite-reverse-engineering

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nanlite FS-300B BLE Mesh Reverse Engineering

Reverse engineering tools and documentation for controlling Nanlite FS-300B LED studio lights via BLE mesh, bypassing the official Nanlink app.

What This Is

The Nanlite FS-300B is a 350W LED studio light that uses Bluetooth Low Energy (BLE) mesh for wireless control. Nanlite's official Nanlink app provisions the light into a BLE mesh network with encrypted communication.

This project provides:

  1. Protocol documentation - Complete breakdown of the vendor-specific BLE mesh commands
  2. Python CLI tool - Interactive controller using the mesh proxy protocol
  3. Key extraction guide - How to get your mesh keys from an Android device

Why?

  • The Nanlink app is closed-source and cloud-connected
  • No official API or local control option
  • BLE mesh encryption prevents simple sniffing
  • We want Home Assistant / MQTT integration

Quick Start

1. Install Dependencies

pip install bleak pycryptodome

2. Extract Your Mesh Keys

See Extracting Mesh Keys below. You need to extract these from your phone after pairing the light.

3. Configure and Run

Edit nanlite_mesh.py and fill in your keys:

NID = 0x7A              # Your Network ID
ENCRYPTION_KEY = bytes.fromhex("...")  # Your EncryptionKey
PRIVACY_KEY = bytes.fromhex("...")     # Your PrivacyKey  
APP_KEY = bytes.fromhex("...")         # Your AppKey

Then run:

python nanlite_mesh.py

Extracting Mesh Keys

The mesh keys are provisioned when you first pair the light with the Nanlink app. They're stored on your phone and used to encrypt all BLE mesh traffic. You need to extract them to control the light independently.

Method 1: Android Bugreport (Recommended)

This method extracts keys from the Nanlink app's logcat output in an Android bugreport.

Requirements

  • Android phone with the light already paired in Nanlink app
  • USB debugging enabled (Settings → Developer Options → USB Debugging)
  • adb installed on your computer

Steps

  1. Make sure the Nanlink app has been used recently (within the current boot cycle). The keys are logged when the app initializes the mesh.

  2. Generate a bugreport:

    adb bugreport

    This creates a zip file like bugreport-DEVICE-DATE.zip

  3. Extract and search the bugreport:

    unzip bugreport-*.zip
    # The main log file is named like:
    # bugreport-DEVICE-DATE.txt
  4. Search for mesh keys:

    grep -i "encryptionkey\|privacykey\|appkey\|devicekey\|netkey" bugreport*.txt

    Look for logcat entries from the Nanlink app or BLE mesh stack. You'll see entries like:

    D NanMesh: EncryptionKey: 80EDA875409E2FF2B78310D4B45641C4
    D NanMesh: PrivacyKey: F86F6FDD9FC1054722BB57C283214F57
    D NanMesh: AppKey: 63964771734FBD76E3B40519D1D94A48
    
  5. Also search for NID and AID:

    grep -i "nid\|aid\|netkey" bugreport*.txt

    The NID (Network ID) is 7 bits derived from the NetKey. The AID is derived from the AppKey.

Alternative: Live logcat

If you can reproduce the key logging:

adb logcat -c  # Clear existing logs
# Open Nanlink app and connect to the light
adb logcat | grep -i "key\|mesh"

Method 2: Decompile the APK

If the keys are hardcoded or you want to understand the key derivation:

  1. Download the Nanlink APK:

    # From your phone
    adb shell pm path com.nanguang.nanlinkforhome
    adb pull /path/to/base.apk nanlink.apk
  2. Decompile with jadx:

    jadx -d nanlink_decompiled nanlink.apk
  3. Search for mesh-related code:

    grep -r "AppKey\|NetKey\|EncryptionKey" nanlink_decompiled/
  4. Look at the provisioning logic in classes like:

    • MeshProvisionerService
    • NanMeshManager
    • FeasyMeshConfig

Method 3: Capture BLE Traffic + Known Plaintext

If you can capture the BLE traffic during provisioning:

  1. Enable HCI snoop log on Android:

    • Settings → Developer Options → Enable Bluetooth HCI snoop log
    • (Reboot may be required)
  2. Pair the light in Nanlink app

  3. Extract the snoop log:

    adb pull /data/misc/bluetooth/logs/btsnoop_hci.log
  4. Analyze in Wireshark with the BT Mesh dissector. You can see encrypted PDUs and, if you have known plaintexts (like brightness=100), attempt key recovery.

Key Derivation (Technical Background)

BLE Mesh key hierarchy:

  • NetKey (128-bit) → Primary network key, provisioned per-network
  • NID (7-bit) → Derived from NetKey, used to identify network
  • EncryptionKey (128-bit) → Derived from NetKey, encrypts network layer
  • PrivacyKey (128-bit) → Derived from NetKey, obfuscates network header
  • AppKey (128-bit) → Application-level key, encrypts access layer
  • AID (6-bit) → Derived from AppKey, identifies which AppKey was used

The Nanlite lights use standard BLE Mesh key derivation (k2, k4 functions from the BT Mesh spec).

Protocol Documentation

Access PDU Format

All commands use the vendor-specific opcode C1 11 11 (0x1111 = Nanlite's Bluetooth SIG company ID).

After the opcode, commands have an 8-byte parameter block:

Byte Name Description
0 rCode Rolling counter 0-7
1 funcCode Bitfield: SET=0x20, QUERY=0x01
2 typeCode Command category (0x01=control, 0x07=fan, 0x0C=query-all)
3 optionCode Command ID
4-5 value Big-endian 16-bit value
6-7 channel Big-endian 16-bit (0x0001 for direct control)

Command Option Codes

Code Name Value Range Notes
0x01 DIM 0-100 Brightness percentage
0x03 CCT 2700-6500 Color temperature in Kelvin
0x04 GM varies Green-magenta tint
0x28 PC_MODE 0-2 Power constant mode
0x60 CCT_OUTPUT 2 or 3 2=max output, 3=constant output

Fan Control

Fan uses a different format with typeCode=0x07. The mode goes in optionCode:

  • 0x00 = Fan off
  • 0x01 = Fan on

Important: When fan is off, brightness is capped at 25%. The light doesn't auto-scale; it just limits output.

Mesh Proxy Protocol

The light exposes a standard BLE Mesh Proxy service (UUID 0x1828). Communication flow:

  1. Connect to GATT
  2. Send Feasycom auth handshake on 0xFFF2: $FSCCMD001$\r\n
  3. Subscribe to 0x2ADE (Mesh Proxy Data Out)
  4. Write commands to 0x2ADD (Mesh Proxy Data In)

Replay Protection

BLE Mesh has replay protection based on sequence numbers. The light rejects any message with seq ≤ last seen seq from that source address.

The script persists its sequence number to ~/.nanlite_seq to survive restarts. If you get no response, your seq might be behind - delete the file and restart (will use seq=50000).

Files

  • nanlite_mesh.py - Interactive CLI controller
  • PROTOCOL.md - Detailed protocol documentation (if you want more)

Related Projects

License

MIT

Credits

Reverse engineered from the Nanlink Android app and btsnoop captures. No Nanlite proprietary code is included.

About

Reverse engineering tools and documentation for Nanlite FS-300B LED lights BLE mesh protocol

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages