Skip to content

Repository files navigation

ABComm - Advanced Bluetooth & Wi-Fi Relay Control

ABComm is a futuristic Android client application designed for high-performance, real-time control of 8-channel relay boards powered by Raspberry Pi Pico running microHIL firmware.

Developed with Kotlin, Android Jetpack, and Kotlin Coroutines.

The application features a Cyberpunk-styled interface supporting dual-mode connectivity (Bluetooth Low Energy / RFCOMM and Wi-Fi TCP Socket), automated hardware telemetry synchronization, and robust error handling.

Build Status License: MIT GitHub issues open GitHub contributors


Table of Contents


✨ Features

  • Dual Connectivity: Seamlessly switch between Bluetooth (BLE / RFCOMM) and Wi-Fi (TCP Socket).
  • Settings Persistence: User-configured Wi-Fi IP address and Port are securely persisted via SharedPreferences.
  • 8-Channel Independent Control: Instant toggle for individual channels (1 to 8) with dynamic active/inactive states.
  • Master Controls: Quick-action ALL ON and ALL OFF buttons for simultaneous relay switching.
  • Automated Telemetry Sync: Automatically queries and displays hardware Board ID (mh:333:2023:0), Firmware Version (microHIL v1.0.0), and live relay states on connect.
  • Manual Sync & Device Reboot: Dedicated SYNC button for manual state refreshing and RESET button with a confirmation dialog.
  • Robust Disconnection Handling: Immediate socket cleanup and automatic UI state reset to OFF when the device disconnects or powers down.
  • Clean Architecture: 100% Type-Safe (ConnectionStatus, DeviceResponse), Dependency Inversion (DIP), Open/Closed (OCP) response matchers, and Coroutine-based background I/O (Dispatchers.IO).
  • Hardware-Free Testing Scripts: Ready-to-use scripts in scripts/ to emulate both Bluetooth SPP and Wi-Fi TCP servers from a laptop without physical Pico hardware.

πŸ“‘ microHIL Communication Protocol

All messages exchanged between the ABComm Android client and the Raspberry Pi Pico server are framed with < at the start and > at the end:

Action Command Frame Response Format
Toggle Channel ON <mh#ch#1#on#end> <mh#sys#channel 1 on#end>
Toggle Channel OFF <mh#ch#1#off#end> <mh#sys#channel 1 off#end>
All Channels ON <mh#all#on#end> <mh#sys#all channels on#end>
All Channels OFF <mh#all#off#end> <mh#sys#all channels off#end>
Query All Channels <mh#all#stat#end> <mh#sys#channels: 1:ON 2:OFF 3:OFF 4:OFF 5:OFF 6:OFF 7:OFF 8:OFF #end>
Query Board ID <mh#sys#id#end> <mh#sys#mh:333:2023:0#end>
Query Firmware Version <mh#sys#version#end> <mh#sys#microHIL v1.0.0#end>
System Reboot <mh#sys#reset#end> <mh#sys#system resetting...#end>
Set Channel Mask <mh#all#mask#10101010#end> <mh#sys#channels mask applied: 10101010#end>

πŸš€ Installation & Building

Developed and tested on Android 14 (API 34) and backwards compatible down to Android 7.0 (API 24).

Build from Source

# 1. Clone repository
git clone https://github.com/electux/abcomm.git
cd abcomm

# 2. Build Debug APK
./gradlew assembleDebug

# Output APK path:
# app/build/outputs/apk/debug/app-debug.apk

Run Unit Tests

Execute the complete test suite (Protocol formatters, Stream parsers, OCP Matchers, ViewModel state, and Repositories):

./gradlew testDebugUnitTest

πŸ“¦ Dependencies & Permissions

The app declares and dynamically requests appropriate permissions:

  • Bluetooth: BLUETOOTH_SCAN, BLUETOOTH_CONNECT (Android 12+ / API 31+), ACCESS_FINE_LOCATION (Android 11 and earlier).
  • Wi-Fi / Network: INTERNET, ACCESS_NETWORK_STATE.

πŸ“ Project Architecture

The codebase strictly follows the Single Type per File and SOLID principles, organized into domain packages:

abcomm/
β”œβ”€β”€ app/
β”‚   └── src/
β”‚       β”œβ”€β”€ main/java/com/abcomm/
β”‚       β”‚   β”œβ”€β”€ protocol/
β”‚       β”‚   β”‚   β”œβ”€β”€ MicrohilProtocolConstants.kt       # Delimiters and command keywords
β”‚       β”‚   β”‚   β”œβ”€β”€ CommandFormatter.kt                # Outbound formatting contract
β”‚       β”‚   β”‚   β”œβ”€β”€ MicrohilCommandFormatter.kt        # Implementation of CommandFormatter
β”‚       β”‚   β”‚   β”œβ”€β”€ FrameParser.kt                     # Stream framing contract (<...>)
β”‚       β”‚   β”‚   β”œβ”€β”€ MicrohilFrameParser.kt             # Chunked stream extractor
β”‚       β”‚   β”‚   β”œβ”€β”€ DeviceResponse.kt                  # Typed device response model
β”‚       β”‚   β”‚   β”œβ”€β”€ ResponseParser.kt                  # Response parser contract
β”‚       β”‚   β”‚   β”œβ”€β”€ ResponseMatcher.kt                 # Response matcher interface (OCP)
β”‚       β”‚   β”‚   β”œβ”€β”€ MicrohilResponseParser.kt          # Parser delegating to matchers
β”‚       β”‚   β”‚   └── matchers/                          # Individual pattern matchers
β”‚       β”‚   β”‚       β”œβ”€β”€ ChannelStateMatcher.kt
β”‚       β”‚   β”‚       β”œβ”€β”€ AllChannelsStateMatcher.kt
β”‚       β”‚   β”‚       β”œβ”€β”€ AllChannelsSnapshotMatcher.kt
β”‚       β”‚   β”‚       β”œβ”€β”€ MaskAppliedMatcher.kt
β”‚       β”‚   β”‚       β”œβ”€β”€ BoardIdMatcher.kt
β”‚       β”‚   β”‚       β”œβ”€β”€ FirmwareVersionMatcher.kt
β”‚       β”‚   β”‚       └── SystemResettingMatcher.kt
β”‚       β”‚   β”‚
β”‚       β”‚   β”œβ”€β”€ communication/
β”‚       β”‚   β”‚   β”œβ”€β”€ ConnectionMode.kt                  # Enum: BLE, WIFI
β”‚       β”‚   β”‚   β”œβ”€β”€ ConnectionTarget.kt                # Sealed: Bluetooth, Wifi
β”‚       β”‚   β”‚   β”œβ”€β”€ ConnectionStatus.kt                # Sealed: Disconnected, Connecting, Connected, Error
β”‚       β”‚   β”‚   β”œβ”€β”€ ConnectionController.kt            # Lifecycle contract
β”‚       β”‚   β”‚   β”œβ”€β”€ CommandSender.kt                   # Dispatch contract
β”‚       β”‚   β”‚   β”œβ”€β”€ ConnectionObservable.kt            # Observer contract
β”‚       β”‚   β”‚   β”œβ”€β”€ CommunicationProvider.kt           # Composite provider contract
β”‚       β”‚   β”‚   β”œβ”€β”€ CommunicationProviderRegistry.kt   # Provider registry contract
β”‚       β”‚   β”‚   β”œβ”€β”€ DefaultCommunicationProviderRegistry.kt
β”‚       β”‚   β”‚   β”œβ”€β”€ BluetoothService.kt                # RFCOMM provider (Coroutines / Dispatchers.IO)
β”‚       β”‚   β”‚   └── WifiService.kt                     # TCP Socket provider (Coroutines / Dispatchers.IO)
β”‚       β”‚   β”‚
β”‚       β”‚   β”œβ”€β”€ settings/
β”‚       β”‚   β”‚   β”œβ”€β”€ AppSettings.kt                     # Config data model & port boundaries
β”‚       β”‚   β”‚   β”œβ”€β”€ AppSettingsRepository.kt           # Storage contract
β”‚       β”‚   β”‚   └── SharedPreferencesSettingsRepository.kt
β”‚       β”‚   β”‚
β”‚       β”‚   β”œβ”€β”€ ui/
β”‚       β”‚   β”‚   β”œβ”€β”€ MainUiState.kt                     # Immutable UI State model
β”‚       β”‚   β”‚   β”œβ”€β”€ MainViewModel.kt                   # ViewModel state machine
β”‚       β”‚   β”‚   β”œβ”€β”€ MainViewModelFactory.kt            # Dependency injection factory
β”‚       β”‚   β”‚   β”œβ”€β”€ BluetoothPermissionChecker.kt      # Permission checker interface
β”‚       β”‚   β”‚   β”œβ”€β”€ BluetoothPermissionHelper.kt       # SDK version-aware helper
β”‚       β”‚   β”‚   β”œβ”€β”€ BluetoothDeviceProvider.kt         # Bluetooth adapter interface
β”‚       β”‚   β”‚   └── BluetoothDeviceManager.kt          # Paired device manager
β”‚       β”‚   β”‚
β”‚       β”‚   └── MainActivity.kt                        # Primary Android Activity view layer
β”‚       β”‚
β”‚       └── test/java/com/abcomm/                      # Complete MockK Unit Test Suite
β”‚
β”œβ”€β”€ docs/                                              # Sphinx / ReadTheDocs Documentation
β”‚   └── source/
β”‚       β”œβ”€β”€ conf.py
β”‚       └── index.rst
β”‚
└── scripts/                                           # Hardware Emulation & Testing Scripts
    β”œβ”€β”€ ble/
    β”‚   β”œβ”€β”€ ble_listen.sh                              # Linux RFCOMM SPP sniffer/server script
    β”‚   └── README.md                                  # Bluetooth test setup guide
    └── wifi/
        β”œβ”€β”€ wifi_server.py                             # Python TCP microHIL mock server
        └── README.md                                  # Wi-Fi test setup guide

πŸ›  Usage & Hardware Emulation Guide

Bluetooth (BLE / RFCOMM) Mode

  1. Select the BLE mode toggle at the top of the screen.
  2. Tap CONNECT.
  3. Grant Bluetooth permissions if prompted.
  4. Select your Raspberry Pi Pico device from the paired devices list.
  5. Once connected, device info and current relay states will load automatically.

Wi-Fi (TCP Socket) Mode

  1. Select the WIFI mode toggle at the top.
  2. Enter the IP Address and Port of your microHIL device (e.g. 192.168.1.100, Port 5000). Values are automatically saved for subsequent app launches.
  3. Tap CONNECT.
  4. Telemetry and relay buttons will update automatically upon connection.

Testing Bluetooth with Linux Laptop

To test Bluetooth connectivity without physical Raspberry Pi Pico hardware, configure a Linux (Ubuntu) laptop as an RFCOMM server:

# In Terminal A on Ubuntu:
chmod +x scripts/ble/ble_listen.sh
./scripts/ble/ble_listen.sh

# In Terminal B (to monitor commands sent from phone):
sudo cat /dev/rfcomm10

Refer to scripts/ble/README.md for full Bluetooth pairing and compatibility instructions.

Testing Wi-Fi with Python Mock Server

To test Wi-Fi communication without physical hardware, run the Python mock server:

# Run the mock server from the repository root
python3 scripts/wifi/wifi_server.py --port 5000
  1. The script will print the laptop's local IP address (e.g. 192.168.1.150).
  2. In the ABComm app, switch to WIFI mode, enter the printed IP and port 5000, and tap CONNECT.
  3. All button presses will update real-time terminal logs and reflect microHIL firmware behavior.

Refer to scripts/wifi/README.md for further details.


πŸ‘₯ Contributing

Contributions are welcome! Please read CONTRIBUTING.md for development guidelines.


πŸ“„ License

License: MIT

Copyright (C) 2026 by electux.github.io/abcomm

ABComm is open-source software licensed under the MIT License.

Releases

Packages

Contributors

Languages