Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Bug Report
description: Create a report to help us fix bugs in Betaflight Configurator.
description: Create a report to help us fix bugs in Betaflight App.
labels: ["Template: Bug"]
body:

Expand Down Expand Up @@ -36,8 +36,8 @@ body:
- type: input
attributes:
label: Configurator version
description: Specify the version of the configurator (as displayed in the app).
label: App version
description: Specify the version of the app (as displayed in the app).
validations:
required: true

Expand Down
12 changes: 6 additions & 6 deletions CAPACITOR_SERIAL_IMPLEMENTATION.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
src/js/protocols/CapacitorSerial.js # Protocol adapter

# Betaflight Configurator - Custom Capacitor USB Serial Plugin
# Betaflight App - Custom Capacitor USB Serial Plugin

## Overview

This implementation creates a **custom Capacitor USB Serial plugin** specifically designed for Betaflight Configurator, replacing the patched `capacitor-plugin-usb-serial` with a clean, purpose-built solution.
This implementation creates a **custom Capacitor USB Serial plugin** specifically designed for the Betaflight App, replacing the patched `capacitor-plugin-usb-serial` with a clean, purpose-built solution.

## 🎯 Key Improvements

Expand All @@ -19,10 +19,10 @@ This implementation creates a **custom Capacitor USB Serial plugin** specificall
### 🏗️ Architecture

```text
betaflight-configurator/
betaflight-app/
├── android/app/src/main/java/
│ ├── betaflight/configurator/MainActivity.java # Registers the plugin
│ └── betaflight/configurator/protocols/serial/ # Native plugin source
│ ├── betaflight/app/MainActivity.java # Registers the plugin
│ └── betaflight/app/protocols/serial/ # Native plugin source
│ ├── BetaflightSerialPlugin.java
│ └── UsbPermissionReceiver.java
Expand All @@ -37,7 +37,7 @@ betaflight-configurator/

### Native Android Layer

**File**: `android/app/src/main/java/betaflight/configurator/protocols/serial/BetaflightSerialPlugin.java`
**File**: `android/app/src/main/java/betaflight/app/protocols/serial/BetaflightSerialPlugin.java`

**Key Features**:
- Uses `usb-serial-for-android` library (proven, mature library)
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
apply plugin: 'com.android.application'

android {
namespace "betaflight.configurator"
namespace "betaflight.app"
compileSdk rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "betaflight.configurator"
applicationId "betaflight.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

<!-- Explicit receiver to handle USB permission PendingIntent on Android 14+ -->
<receiver
android:name="betaflight.configurator.protocols.serial.UsbPermissionReceiver"
android:name="betaflight.app.protocols.serial.UsbPermissionReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.betaflight.USB_PERMISSION" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package betaflight.configurator;
package betaflight.app;

import android.os.Bundle;

import betaflight.configurator.protocols.serial.BetaflightSerialPlugin;
import betaflight.app.protocols.serial.BetaflightSerialPlugin;
import com.getcapacitor.BridgeActivity;
import betaflight.configurator.protocols.tcp.BetaflightTcpPlugin;
import betaflight.app.protocols.tcp.BetaflightTcpPlugin;

public class MainActivity extends BridgeActivity {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package betaflight.configurator.protocols.serial;
package betaflight.app.protocols.serial;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
Expand Down Expand Up @@ -33,8 +33,8 @@

/**
* Capacitor plugin for USB Serial communication
* Designed specifically for Betaflight Configurator with binary protocol support (MSP)
*
* Designed specifically for Betaflight App with binary protocol support (MSP)
*
* Features:
* - Automatic USB device permission handling
* - Support for multiple USB-to-serial chipsets (FTDI, CP210x, CH34x, PL2303, etc.)
Expand All @@ -61,15 +61,15 @@ public class BetaflightSerialPlugin extends Plugin implements SerialInputOutputM
private UsbSerialDriver currentDriver;
private UsbDeviceConnection connection;
private SerialInputOutputManager ioManager;

private final Map<String, UsbDevice> permissionRequestedDevices = new HashMap<>();
private PluginCall pendingPermissionCall;

private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();

if (ACTION_USB_PERMISSION.equals(action)) {
handlePermissionResult(intent);
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
Expand All @@ -85,19 +85,19 @@ public void load() {
super.load();
sInstance = new java.lang.ref.WeakReference<>(this);
usbManager = (UsbManager) getContext().getSystemService(Context.USB_SERVICE);

// Register USB broadcast receivers
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getContext().registerReceiver(usbReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
} else {
getContext().registerReceiver(usbReceiver, filter);
}

Log.d(TAG, "BetaflightSerial plugin loaded");
}

Expand Down Expand Up @@ -125,7 +125,7 @@ public void requestPermission(PluginCall call) {
}

List<UsbSerialDriver> availableDrivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);

if (availableDrivers.isEmpty()) {
JSObject result = new JSObject();
result.put("devices", new JSArray());
Expand Down Expand Up @@ -321,7 +321,7 @@ public void write(PluginCall call) {

// Convert hex string to bytes
byte[] data = hexStringToByteArray(hexData);

// Write data to serial port
serialPort.write(data, WRITE_WAIT_MILLIS);

Expand Down Expand Up @@ -352,7 +352,7 @@ public void read(PluginCall call) {

byte[] buffer = new byte[8192];
int numBytes = serialPort.read(buffer, READ_WAIT_MILLIS);

String hexData = "";
if (numBytes > 0) {
byte[] data = new byte[numBytes];
Expand All @@ -379,7 +379,7 @@ public void read(PluginCall call) {
public void onNewData(byte[] data) {
// Convert received data to hex string and notify listeners
String hexData = byteArrayToHexString(data);

JSObject eventData = new JSObject();
eventData.put("data", hexData);
notifyListeners("dataReceived", eventData);
Expand Down Expand Up @@ -489,12 +489,12 @@ private JSObject createDeviceInfo(UsbDevice device) throws JSONException {
info.put("deviceName", device.getDeviceName());
info.put("deviceClass", device.getDeviceClass());
info.put("deviceSubclass", device.getDeviceSubclass());

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
info.put("manufacturer", device.getManufacturerName());
info.put("product", device.getProductName());
}

return info;
}

Expand Down Expand Up @@ -528,7 +528,7 @@ private void closeSerialPort() {

private int parseParity(String parity) {
if (parity == null) return UsbSerialPort.PARITY_NONE;

switch (parity.toLowerCase()) {
case "even":
return UsbSerialPort.PARITY_EVEN;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package betaflight.configurator.protocols.serial;
package betaflight.app.protocols.serial;

import android.content.BroadcastReceiver;
import android.content.Context;
Expand All @@ -11,7 +11,7 @@
*/
public class UsbPermissionReceiver extends BroadcastReceiver {
private static final String TAG = "BetaflightSerial";

@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "UsbPermissionReceiver.onReceive called with action: " + intent.getAction());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package betaflight.configurator.protocols.tcp;
package betaflight.app.protocols.tcp;

import android.util.Base64;
import android.util.Log;
Expand Down Expand Up @@ -71,14 +71,13 @@ public void connect(final PluginCall call) {
call.setKeepAlive(false);
return;
}

if (!compareAndSetState(ConnectionState.DISCONNECTED, ConnectionState.CONNECTING)) {
call.reject(ERROR_ALREADY_CONNECTED);
call.setKeepAlive(false);
return;
}


new Thread(() -> {
socketLock.lock();
try {
Expand Down Expand Up @@ -109,7 +108,7 @@ public void connect(final PluginCall call) {
}
}).start();
}

@PluginMethod
public void send(final PluginCall call) {
String data = call.getString("data");
Expand Down
8 changes: 4 additions & 4 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<string name="app_name">Betaflight Configurator</string>
<string name="title_activity_main">Betaflight Configurator</string>
<string name="package_name">betaflight.configurator</string>
<string name="custom_url_scheme">betaflight.configurator</string>
<string name="app_name">Betaflight App</string>
<string name="title_activity_main">Betaflight App</string>
<string name="package_name">betaflight.app</string>
<string name="custom_url_scheme">betaflight.app</string>
</resources>
8 changes: 8 additions & 0 deletions assets/linux/betaflight-app.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Desktop Entry]
Name=Betaflight App
Comment=Crossplatform configuration and management tool for the Betaflight flight control system
Exec=/opt/betaflight/betaflight-app/betaflight-app
Icon=/opt/betaflight/betaflight-app/icon/bf_icon_128.png
Terminal=false
Type=Application
Categories=Utility
8 changes: 0 additions & 8 deletions assets/linux/betaflight-configurator.desktop

This file was deleted.

2 changes: 1 addition & 1 deletion assets/linux/copyright
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: Betaflight Configurator
Upstream-Name: Betaflight App
Source: https://github.com/betaflight/betaflight-configurator

Files: *
Expand Down
34 changes: 16 additions & 18 deletions assets/windows/installer.iss
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
; ------------------------------------------
; Installer for Betaflight Configurator
; Installer for Betaflight App
; ------------------------------------------
; It receives from the command line with /D the parameters:
; It receives from the command line with /D the parameters:
; version
; archName
; archAllowed
; archInstallIn64bit
; sourceFolder
; targetFolder

#define ApplicationName "Betaflight Configurator"
#define ApplicationName "Betaflight App"
#define CompanyName "The Betaflight open source project"
#define CompanyUrl "https://betaflight.com/"
#define ExecutableFileName "betaflight-configurator.exe"
#define ExecutableFileName "betaflight-app.exe"
#define GroupName "Betaflight"
#define InstallerFileName "betaflight-configurator_" + version + "_" + archName + "-installer"
#define SourcePath "..\..\" + sourceFolder + "\betaflight-configurator\" + archName
#define TargetFolderName "Betaflight-Configurator"
#define InstallerFileName "betaflight-app_" + version + "_" + archName + "-installer"
#define SourcePath "..\..\" + sourceFolder + "\betaflight-app\" + archName
#define TargetFolderName "Betaflight-App"
#define UpdatesUrl "https://github.com/betaflight/betaflight-configurator/releases"

[CustomMessages]
AppName=betaflight-configurator
AppName=betaflight-app
LaunchProgram=Start {#ApplicationName}

[Files]
Expand All @@ -30,7 +30,7 @@ Source: "{#SourcePath}\*"; DestDir: "{app}"; Flags: recursesubdirs
; Programs group
Name: "{group}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
; Desktop icon
Name: "{autodesktop}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
Name: "{autodesktop}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
; Non admin users, uninstall icon
Name: "{group}\Uninstall {#ApplicationName}"; Filename: "{uninstallexe}"; Check: not IsAdminInstallMode

Expand Down Expand Up @@ -101,11 +101,11 @@ var
begin
Result := '';
// Look into the different registry entries: win32, win64 and without user rights
if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Betaflight Configurator', 'UninstallString', Result) then
if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Betaflight App', 'UninstallString', Result) then
begin
if not RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Betaflight Configurator', 'UninstallString', Result) then
if not RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Betaflight App', 'UninstallString', Result) then
begin
RegQueryStringValue(HKCU, 'SOFTWARE\Betaflight\Betaflight Configurator', 'UninstallString', Result)
RegQueryStringValue(HKCU, 'SOFTWARE\Betaflight\Betaflight App', 'UninstallString', Result)
end;
end;
end;
Expand All @@ -128,16 +128,14 @@ var
ParameterStr : String;
UninstPath : String;
begin

Result := True;

// Check if the application is already installed by the old NSIS installer, and uninstall it
UninstPath := GetOldNsisUninstallerPath();

// Found, start uninstall
if UninstPath <> '' then
if UninstPath <> '' then
begin

UninstPath := RemoveQuotes(UninstPath);

// Add this parameter to not return until uninstall finished. The drawback is that the uninstaller file is not deleted
Expand All @@ -151,8 +149,8 @@ begin
end
else begin
Result := False;
MsgBox('Error uninstalling old Configurator ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
end;
MsgBox('Error uninstalling old App ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
end;
end
else begin

Expand All @@ -163,7 +161,7 @@ begin
if not Exec('>', UninstPath, '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
Result := False;
MsgBox('Error uninstalling Configurator ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
MsgBox('Error uninstalling App ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
end;
end;
end;
Expand Down
4 changes: 2 additions & 2 deletions capacitor.config.base.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"appId": "betaflight.configurator",
"appName": "Betaflight Configurator",
"appId": "betaflight.app",
"appName": "Betaflight App",
"webDir": "src/dist"
}
Loading