example 'meshtastic': add WiFi connection mode (currently tested on desktop only)

This commit is contained in:
pls.153 2024-05-02 19:42:26 +02:00
parent b8b34b36c4
commit f56a468983
14 changed files with 204 additions and 26 deletions

View file

@ -166,13 +166,15 @@ SOURCES += \
cpp/connection/connection.h \
cpp/connection/ble/ble.h \
cpp/connection/ble/ble_me.h \
cpp/connection/usb/usb_me.h
cpp/connection/usb/usb_me.h \
cpp/connection/wifi/wifi_me.h
SOURCES += \
cpp/connection/connection.cpp \
cpp/connection/ble/ble.cpp \
cpp/connection/ble/ble_me.cpp \
cpp/connection/usb/usb_me.cpp
cpp/connection/usb/usb_me.cpp \
cpp/connection/wifi/wifi_me.cpp
}
RESOURCES += $$files(qml/*)

View file

@ -7,6 +7,7 @@ class QtAndroidService {
SLOT(void read2());
SLOT(void write2(const QVariant&));
SLOT(void setBackgroundMode(bool));
SIGNAL(deviceDiscovered(const QVariant&));
SIGNAL(bleError());
SIGNAL(setReady(const QVariant&));

View file

@ -18,12 +18,14 @@ HEADERS += \
../connection/connection.h \
../connection/ble/ble.h \
../connection/ble/ble_me.h \
../connection/wifi/wifi_me.h \
qtandroidservice_ro.h
SOURCES += \
../connection/connection.cpp \
../connection/ble/ble.cpp \
../connection/ble/ble_me.cpp \
../connection/wifi/wifi_me.cpp \
main.cpp
REPC_SOURCE += qtandroidservice.rep

View file

@ -128,13 +128,13 @@ void BLE_ME::characteristicRead(const QLowEnergyCharacteristic&,
const QByteArray& data) {
if (data.isEmpty()) {
if (!con->backgroundMode) {
emitter->receivingDone();
static bool startup = true;
if (startup) {
con->sendSavedBytes(); // for eventual, saved but not sent packets
} else {
startup = false;
}
emitter->receivingDone();
}
} else {
if (con->backgroundMode) {

View file

@ -31,7 +31,6 @@ Q_SIGNALS:
void setReady(bool, const QString&, const QStringList&);
void receivedFromRadio(const QByteArray&, const QString&);
void receivingDone();
void sendSavedPackets(const QVariant&);
/*** </INTERFACE> ***************************************/

View file

@ -1,5 +1,6 @@
#include "connection.h"
#include "ble/ble_me.h"
#include "wifi/wifi_me.h"
#include <QStandardPaths>
#include <QFile>
#include <QDataStream>
@ -19,37 +20,44 @@ Connection::Connection(QtAndroidService* service) {
// forward signal
connect(this, &Connection::sendSavedPackets, service, &QtAndroidService::sendSavedPackets);
ble = new BLE_ME(service, this);
wifi = new WiFi_ME(service, this);
}
#else
Connection::Connection() {
ble = new BLE_ME(this);
usb = new USB_ME(this);
wifi = new WiFi_ME(this);
}
#endif
void Connection::setConnectionType(const QVariant& vType) {
QByteArray t = vType.toByteArray();
if (t == "USB") {
type = USB;
} else {
type = BLE;
}
void Connection::setConnectionType(const QVariant& var) {
type = Type(BLE + (QList<QByteArray>() << "BLE" << "USB" << "WIFI")
.indexOf(var.toByteArray()));
}
void Connection::startDeviceDiscovery(const QVariant& vName) {
void Connection::startDeviceDiscovery(const QVariant& var) {
switch (type) {
case BLE:
#ifndef Q_OS_ANDROID
usb->disconnect();
#endif
ble->startDeviceDiscovery(vName.toString());
wifi->disconnect();
ble->startDeviceDiscovery(var.toString());
break;
case USB:
ble->disconnect();
wifi->disconnect();
#ifndef Q_OS_ANDROID
usb->connectToRadio();
#endif
break;
case WiFi:
ble->disconnect();
#ifndef Q_OS_ANDROID
usb->disconnect();
#endif
wifi->connectToRadio(var.toString());
break;
}
}
@ -59,10 +67,11 @@ void Connection::stopDeviceDiscovery() {
void Connection::disconnect() {
switch (type) {
case BLE: ble->disconnect(); break;
#ifndef Q_OS_ANDROID
case USB: usb->disconnect(); break;
#endif
case BLE: ble->disconnect(); break;
case WiFi: wifi->disconnect(); break;
}
}
@ -85,6 +94,9 @@ void Connection::write2(const QVariant& vBytes) {
usb->write2(bytes);
#endif
break;
case WiFi:
wifi->write2(bytes);
break;
}
}

View file

@ -5,7 +5,11 @@
class BLE_ME;
class USB_ME;
class QtAndroidService;
class WiFi_ME;
#ifdef Q_OS_ANDROID
class QtAndroidService;
#endif
class Connection : public QObject {
Q_OBJECT
@ -18,12 +22,13 @@ public:
#endif
enum Type {
BLE, USB
BLE, USB, WiFi
};
Type type = BLE;
BLE_ME* ble = nullptr;
USB_ME* usb = nullptr;
WiFi_ME* wifi = nullptr;
bool backgroundMode = false;
void setConnectionType(const QVariant&);

View file

@ -69,7 +69,7 @@ void USB_ME::disconnect() {
void USB_ME::write2(const QByteArray& data) {
if (ready) {
write(data.constData(), data.size());
write(data);
} else {
qDebug() << "USB not ready: write()";
}

View file

@ -0,0 +1,87 @@
#include "wifi_me.h"
#include "../connection.h"
#include <QHostAddress>
#ifdef Q_OS_ANDROID
#include "../../android_service/qtandroidservice_ro.h"
#endif
#ifdef Q_OS_ANDROID
WiFi_ME::WiFi_ME(QtAndroidService* service, Connection* _con) : emitter(service), con(_con) {
#else
WiFi_ME::WiFi_ME(Connection* _con) : emitter(_con), con(_con) {
#endif
connect(this, &QTcpSocket::stateChanged, this, &WiFi_ME::stateChanged);
connect(this, &QTcpSocket::errorOccurred,
[](QAbstractSocket::SocketError error) {
qDebug() << "WiFi error:" << error;
});
connect(this, &QTcpSocket::readyRead, this, &WiFi_ME::read2);
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, this, &WiFi_ME::done);
}
void WiFi_ME::connectToRadio(const QString& ip) {
connectToHost(ip, 4403);
}
void WiFi_ME::stateChanged(SocketState state) {
if (state == ConnectedState) {
emitter->setReady(QVariant(QVariantList() << peerAddress().toString()));
}
qDebug() << "WiFi state:" << state;
}
void WiFi_ME::disconnect() {
disconnectFromHost();
}
void WiFi_ME::write2(const QByteArray& data) {
if (state() == ConnectedState) {
write(data);
} else {
qDebug() << "not ready to write";
}
}
void WiFi_ME::read2() {
packets << readAll();
timer.start(1000); // assume receiving done after pause of 1 sec
}
void WiFi_ME::received(const QByteArray& data) {
if (!data.isEmpty()) {
if (con->backgroundMode) {
con->saveBytes(data);
} else {
emitter->receivedFromRadio(QVariant(QVariantList() << data));
}
}
}
void WiFi_ME::done() {
if (!con->backgroundMode) {
static bool startup = true;
if (startup) {
con->sendSavedBytes(); // for eventual, saved but not sent packets
} else {
startup = false;
}
}
const QByteArray HEADER = QByteArray::fromHex("94c3");
const int LEN = 4;
QByteArray data(packets.join());
packets.clear();
int start = 0;
while ((start = data.indexOf(HEADER, start)) != -1) {
int i_len = start + 2;
int len = (data.at(i_len) << 8) + data.at(i_len + 1);
received(data.mid(start + LEN, len));
start += LEN + len;
}
emitter->receivingDone();
}

View file

@ -0,0 +1,51 @@
#pragma once
#include <QTcpSocket>
#include <QTimer>
#ifdef Q_OS_ANDROID
class QtAndroidService;
#endif
class Connection;
class WiFi_ME : public QTcpSocket {
Q_OBJECT
/*** <INTERFACE> ****************************************/
public:
#ifdef Q_OS_ANDROID
WiFi_ME(QtAndroidService*, Connection*);
#else
WiFi_ME(Connection*);
#endif
public Q_SLOTS:
void connectToRadio(const QString&);
void disconnect();
void read2();
void write2(const QByteArray&);
Q_SIGNALS:
void setReady(const QString&);
void receivedFromRadio(const QByteArray&, const QString&);
void receivingDone();
/*** </INTERFACE> ***************************************/
public:
#ifdef Q_OS_ANDROID
QtAndroidService* emitter = nullptr;
#else
Connection* emitter = nullptr;
#endif
Connection* con = nullptr;
QTimer timer;
QByteArrayList packets;
void received(const QByteArray&);
public Q_SLOTS:
void done();
void stateChanged(SocketState);
};

View file

@ -14,6 +14,7 @@ HEADERS += \
connection/ble/ble.h \
connection/ble/ble_me.h \
connection/usb/usb_me.h \
connection/wifi/wifi_me.h \
qt.h
SOURCES += \
@ -21,6 +22,7 @@ SOURCES += \
connection/ble/ble.cpp \
connection/ble/ble_me.cpp \
connection/usb/usb_me.cpp \
connection/wifi/wifi_me.cpp \
qt.cpp
linux {

View file

@ -53,7 +53,10 @@
*schedule-clear* t)
(unless radios:*found*
(radios:clear))
(qrun* (qt:start-device-discovery qt:*cpp* name))
(qrun* (qt:start-device-discovery qt:*cpp*
(if (eql :wifi radios:*connection*)
(app:setting :wifi-ip)
name)))
(q> |playing| ui:*busy* t)))
(defun get-node-config ()
@ -81,7 +84,12 @@
(destructuring-bind (port)
args
(setf *ready* t)
(app:toast "USB" 2))))
(app:toast "USB" 2)))
(:wifi
(destructuring-bind (ip)
args
(setf *ready* t)
(app:toast (x:cc "WiFi: " ip) 2))))
(get-node-config)
(values))
@ -152,10 +160,12 @@
(let* ((bytes (pr:serialize-to-bytes to-radio))
(header (header (length bytes))))
(case radios:*connection*
(:ble (qrun*
(:ble
(qrun*
(qt:write* qt:*cpp* header)
(qt:write* qt:*cpp* bytes)))
(:usb (qrun*
((:usb :wifi)
(qrun*
(qt:write* qt:*cpp* (concatenate 'vector header bytes)))))))
(defun received-from-radio (args) ; see Qt
@ -302,7 +312,7 @@
:custom-name (or (app:setting name :custom-name) "")
:node-num (me:num info)
:current (equal name (app:setting :latest-receiver)))))
(when (or (and (eql radios:*connection* :usb)
(when (or (and (find radios:*connection* '(:usb :wifi))
current)
(find name *ble-names* :test 'string=))
(setf radios:*found* t)

View file

@ -1,6 +1,6 @@
(in-package :radios)
(defvar *connection* nil)
(defvar *connection* nil) ; :ble :usb :wifi
(defvar *found* nil)
(defun ini ()

View file

@ -83,6 +83,13 @@ Item {
enabled: (Qt.platform.os !== "android") && (Qt.platform.os !== "ios")
onTriggered: connection.changed(objectName)
}
Com.MenuItem {
objectName: "WIFI"
text: "WiFi"
autoExclusive: true
checkable: true
onTriggered: connection.changed(objectName)
}
}
Com.MenuItem {