Нативная реализация BLE/WiFi сканера для Luckfox Pico Ultra W на Alpine Linux.
Один физический радиомодуль для WiFi + BLE:
✓ РАБОТАЕТ:
- BLE scan + WiFi client одновременно
- BLE scan + WiFi monitor одновременно
- BLE scan + WiFi AP одновременно
✗ НЕ РАБОТАЕТ:
- WiFi client + monitor одновременно (data transfer blocked)
РЕШЕНИЕ В КОДЕ:
- Меняем режимы WiFi ТОЛЬКО когда BLE остановлен
- При подключении WiFi client - BLE временно останавливается
- После WiFi подключения - BLE автоматически перезапускается
- С WiFi monitor тоже самое.
USB SWITCH (U10) между Type-C и USB-A:
- SEL подтянут к VBUS через R70 (62K)
Type-C питание → USB-A НЕ РАБОТАЕТ (data на Type-C)
POE питание → USB-A РАБОТАЕТ
5V на гребёнку → USB-A РАБОТАЕТ
ДЛЯ USB-МОДЕМА: требуется POE или внешний 5V!
┌──────────────┐ ┌──────────────┐
│ CLOUD MODE │ │ LAN MODE │
│ (default) │ │ │
├──────────────┤ ├──────────────┤
│ • Config from│ │ • Config │
│ server │ │ local only │
│ • Polling ON │ │ • Polling OFF│
│ (30 sec) │ │ │
└──────────────┘ └──────────────┘
Первая регистрация ВСЕГДА через интернет (для получения device_password)
Priority 1: eth0 (carrier detect)
│
├── Link UP → DHCP/Static → ONLINE
│
└── Link DOWN
│
Priority 2: wlan0 client (if configured, НЕЗАВИСИМО от eth0!)
│
├── WiFi.ClientEnabled = true → Connect
│ └── Success → ONLINE (eth0 + wlan0 одновременно)
│
└── WiFi.ClientEnabled = false OR connection failed
│
WiFi Scanner: если wlan0 free AND MonitorEnabled
│ └── BLE останавливается (AIC8800 conflict)
│
Fallback: wlan0 AP (120 сек без сети)
│
└── AP UP (SSID: mybeacon_XXXX, пароль: device_password)
└── Продолжаем пробовать wlan0 client каждые 30 сек!
AP Settings:
SSID: "mybeacon_<4 последних символа MAC>" (например: mybeacon_1bac)
Password: device_password из /opt/mybeacon/etc/device.json (8 цифр с регистрации)
fallback: "mybeacon" (если device_password пустой)
IP: 192.168.4.1
DHCP: 192.168.4.100-200 (dnsmasq)
iBeacon (Apple 0x004C)
my-beacon_acc (Nordic 0x0059)
rt_mybeacon (Custom 0xFFFF)
┌─────────────────────────────────────────────────────────────┐
│ beacon-daemon (Go) │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Network Manager │ │
│ │ - eth0 (DHCP/Static) │ │
│ │ - wlan0 client (WPA2-PSK) │ │
│ │ - wlan0 AP fallback (120s timeout) │ │
│ │ - NTP sync (auto-start on network up) │ │
│ │ - WiFi/BLE scanner coordination (AIC8800 workaround) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Scanner Manager │ │
│ │ - Starts/stops ble-scanner and wifi-scanner │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ ZMQ SUB │ │ ZMQ SUB │ │ HTTP API + WS │ │
│ │ (BLE) │ │ (WiFi) │ │ (Dashboard) │ │
│ │ :5555 │ │ :5556 │ │ :80 │ │
│ └──────┬──────┘ └──────┬──────┘ └─────────────────────┘ │
│ │ │ │
│ └───────┬────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Event Batcher → gzip → HTTP POST → Server │ │
│ │ ↓ (on failure) │ │
│ │ Spooler (max 100MB) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Config │ │ Registration│ │ SSH Tunnel │ │
│ │ Poller │ │ Handler │ │ Manager │ │
│ │ (30s) │ │ │ │ (reverse) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│ │
│ spawns │ spawns
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ ble-scanner │ │ wifi-scanner │
│ (Go) │ │ (Go) │
│ │ │ │
│ BlueZ D-Bus API │ │ pcap + nl80211 │
│ ZMQ PUB :5555 │ │ ZMQ PUB :5556 │
└─────────────────┘ └─────────────────┘
Сканеры публикуют события в формате: topic JSON
Топики:
ble.ibeacon — iBeaconble.acc — my-beacon accelerometerble.relay — relay beaconwifi.probe — WiFi probe requestПример:
ble.ibeacon {"type":"ble.ibeacon","mac":"AA:BB:CC:DD:EE:FF","rssi":-65,"ts_ms":1703001234567,...}
GET /api/status - статус (сеть, режим, counters, uptime)
GET /api/metrics - метрики системы (CPU, mem, temp)
GET /api/ble/recent - последние BLE события (15 sec TTL)
GET /api/wifi/recent - последние WiFi события
GET /api/config - конфиг (без секретов)
POST /api/settings - применить настройки (требует пароль)
POST /api/unlock - проверить device_password
GET /api/logs - daemon logs (last 100 lines)
WS /api/ws - live updates (BLE/WiFi events)
Static: / - Vue.js dashboard
┌─────────────────────────────────────────────────────────────┐
│ 🟢 MyBeacon Device: 38:54:39:4b:1b:ac │
├─────────────────────────────────────────────────────────────┤
│ [Status] [Daemon Log] [Settings] │
├─────────────────────────────────────────────────────────────┤
│ │
│ Status Tab: │
│ - System info (uptime, CPU, memory, temp) │
│ - Server connection status │
│ - NTP server │
│ - Ethernet (IP, gateway, DNS, RX/TX) │
│ - Wireless (IP, SSID, gateway, channel, RSSI, RX/TX) │
│ - Live BLE devices (last 15s with TTL countdown) │
│ │
│ Settings Tab (device_password protected): │
│ - Mode (Cloud/LAN) │
│ - eth0 config (DHCP/Static IP/Gateway/DNS) │
│ - WiFi client (Enable/SSID/PSK) │
│ - WiFi monitor mode (Enable/Disable) │
│ - NTP servers │
│ - API endpoints (для LAN mode) │
│ - SSH Tunnel config │
│ │
│ Daemon Log Tab: │
│ - Real-time logs через WebSocket │
│ │
└─────────────────────────────────────────────────────────────┘
Доступ: http://192.168.4.1 (AP mode) или http://<device-ip>
/opt/mybeacon/etc/device.jsonПароль забыт? → Посмотреть в личном кабинете на сервере или в /opt/mybeacon/etc/device.json (требуется SSH доступ)
/opt/mybeacon/
├── bin/
│ ├── ble-scanner # BLE сканер
│ ├── wifi-scanner # WiFi сканер
│ ├── beacon-daemon # Главный демон
│ ├── wifi-connect.sh # WiFi client подключение
│ ├── ap-start.sh # Запуск AP fallback
│ └── ap-stop.sh # Остановка AP fallback
├── etc/
│ ├── config.json # Конфигурация (user-editable)
│ ├── device.json # Device state (device_id, device_token, device_password)
│ └── tunnel_key # SSH private key для туннеля
└── www/ # Vue.js dashboard (dist)
├── index.html
└── assets/
/var/spool/mybeacon/ # Очередь событий (при отсутствии сети)
├── ble/
└── wifi/
/var/log/ # tmpfs (10MB, не убивает eMMC)
├── mybeacon.log # Daemon logs
├── wifi-connect.log # WiFi connection logs
└── ap.log # AP fallback logs
/etc/init.d/
├── S01tmpfs-log # Mount /var/log as tmpfs
├── S10udev
├── S10usbhost
├── S15wireless # Load AIC8800 modules
├── S20dbus # D-Bus (required for BlueZ)
├── S30network # Базовая сеть (deprecated, управляет Network Manager)
├── S30usbmodem # USB modem support
├── S36bluetooth # BlueZ (required for BLE)
├── S50sshd # SSH server
└── S98mybeacon # MyBeacon daemon (управляет сетью и NTP!)
# Prerequisites
sudo apt install golang libzmq3-dev gcc-arm-linux-gnueabihf
# Clone
cd /home/user/work/luckfox/alpine/mybeacon
# Download Go dependencies
go mod download
# ARM cross-compile (для Luckfox)
make arm
# Результат в bin/arm/:
# - beacon-daemon
# - ble-scanner
# - wifi-scanner
{
"mode": "cloud",
"api_base": "http://server:5000/api/v1",
"zmq_addr_ble": "tcp://127.0.0.1:5555",
"zmq_addr_wifi": "tcp://127.0.0.1:5556",
"spool_dir": "/var/spool/mybeacon",
"wifi_iface": "wlan0",
"debug": false,
"ble": {
"enabled": true,
"batch_interval_ms": 2500
},
"wifi": {
"monitor_enabled": true,
"client_enabled": false,
"ssid": "",
"psk": "",
"batch_interval_ms": 10000
},
"network": {
"ntp_servers": ["pool.ntp.org"],
"eth0": {
"static": false,
"address": "",
"gateway": "",
"dns": ""
}
},
"ap_fallback": {
"password": "mybeacon"
},
"dashboard": {
"enabled": true
},
"ssh_tunnel": {
"enabled": false,
"server": "tunnel.example.com",
"port": 22,
"user": "tunnel",
"key_path": "/opt/mybeacon/etc/tunnel_key",
"remote_port": 12345,
"keepalive_interval": 30,
"reconnect_delay": 5
}
}
{
"device_id": "38:54:39:4b:1b:ac",
"device_token": "VL9tUGZrxGR7G4KmSDYjhrfZT7Por7C/ghvH9HdwMjQ=",
"device_password": "62358673"
}
Конфигурация, которую устройство получает с сервера каждые 30 секунд в cloud mode:
{
"force_cloud": false,
"ble": {
"enabled": true,
"batch_interval_ms": 2500,
"uuid_filter_hex": ""
},
"wifi": {
"client_enabled": false,
"ssid": "AP_name",
"psk": "123456789",
"monitor_enabled": true,
"batch_interval_ms": 10000
},
"ssh_tunnel": {
"enabled": false,
"server": "tunnel.example.com",
"port": 22,
"user": "tunnel",
"remote_port": 0,
"keepalive_interval": 30
},
"dashboard": {
"enabled": true
},
"net": {
"ntp": {
"servers": ["pool.ntp.org", "time.google.com"]
}
},
"debug": false
}
Приоритет настроек:
Устройство взаимодействует с сервером через следующие endpoints:
Регистрация нового устройства. Отправляется один раз при первом запуске.
Request:
{
"device_id": "38:54:39:4b:1b:ac",
"eth_ip": "192.168.1.100",
"wlan_ip": "192.168.1.101"
}
Response:
{
"device_token": "secure-token-here",
"device_password": "generated-password"
}
Получение конфигурации от сервера (polling каждые 30 секунд в Cloud Mode).
Headers:
Authorization: Bearer {device_token}
Response: см. выше (Server Config)
Загрузка BLE событий.
Headers:
Authorization: Bearer {device_token}
Content-Type: application/json
Content-Encoding: gzip
Request (gzipped):
{
"device_id": "38:54:39:4b:1b:ac",
"events": [
{
"timestamp": 1234567890,
"mac": "AA:BB:CC:DD:EE:FF",
"rssi": -65,
"name": "Device Name"
}
]
}
Загрузка WiFi событий.
Headers:
Authorization: Bearer {device_token}
Content-Type: application/json
Content-Encoding: gzip
Request (gzipped):
{
"device_id": "38:54:39:4b:1b:ac",
"events": [
{
"timestamp": 1234567890,
"mac": "AA:BB:CC:DD:EE:FF",
"rssi": -65,
"ssid": "Network Name"
}
]
}
Обновление WiFi credentials пользователем через Dashboard (только в Cloud Mode).
Headers:
Authorization: Bearer {device_token}
Content-Type: application/json
Request:
{
"ssid": "NewNetwork",
"psk": "password123"
}
Response:
{
"success": true
}
Назначение: Когда пользователь в Cloud Mode изменяет WiFi Client credentials через Dashboard, устройство:
Сервер может использовать эти данные для:
cd /home/user/work/luckfox/alpine
# 1. Собрать бинарники
cd mybeacon && make arm && cd ..
# 2. Скопировать в overlay
cp mybeacon/bin/arm/* overlay/opt/mybeacon/bin/
# 3. Собрать dashboard
cd mybeacon/dashboard && npm run build && cd ../..
cp -r mybeacon/dashboard/dist/* overlay/opt/mybeacon/www/
# 4. Собрать образ
cd scripts && sudo ./build_update_img.sh
# 5. Прошить (device в maskrom mode)
sudo /home/user/work/luckfox/upgrade_tool_v2.17_for_linux/upgrade_tool uf output/update.img
# Собрать
cd /home/user/work/luckfox/alpine/mybeacon && make arm
# Залить
scp bin/arm/beacon-daemon root@<device-ip>:/opt/mybeacon/bin/
# Перезапустить
ssh root@<device-ip> '/etc/init.d/S98mybeacon restart'
ip link del - решено (используется iw dev ap0 del)Proprietary - All Rights Reserved