mirror of
https://gitlab.com/eql/lqml.git
synced 2025-12-06 02:30:38 -08:00
example 'meshtastic': add WiFi connection mode (currently tested on desktop only)
This commit is contained in:
parent
b8b34b36c4
commit
f56a468983
14 changed files with 204 additions and 26 deletions
|
|
@ -166,13 +166,15 @@ SOURCES += \
|
||||||
cpp/connection/connection.h \
|
cpp/connection/connection.h \
|
||||||
cpp/connection/ble/ble.h \
|
cpp/connection/ble/ble.h \
|
||||||
cpp/connection/ble/ble_me.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 += \
|
SOURCES += \
|
||||||
cpp/connection/connection.cpp \
|
cpp/connection/connection.cpp \
|
||||||
cpp/connection/ble/ble.cpp \
|
cpp/connection/ble/ble.cpp \
|
||||||
cpp/connection/ble/ble_me.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/*)
|
RESOURCES += $$files(qml/*)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ class QtAndroidService {
|
||||||
SLOT(void read2());
|
SLOT(void read2());
|
||||||
SLOT(void write2(const QVariant&));
|
SLOT(void write2(const QVariant&));
|
||||||
SLOT(void setBackgroundMode(bool));
|
SLOT(void setBackgroundMode(bool));
|
||||||
|
|
||||||
SIGNAL(deviceDiscovered(const QVariant&));
|
SIGNAL(deviceDiscovered(const QVariant&));
|
||||||
SIGNAL(bleError());
|
SIGNAL(bleError());
|
||||||
SIGNAL(setReady(const QVariant&));
|
SIGNAL(setReady(const QVariant&));
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,14 @@ HEADERS += \
|
||||||
../connection/connection.h \
|
../connection/connection.h \
|
||||||
../connection/ble/ble.h \
|
../connection/ble/ble.h \
|
||||||
../connection/ble/ble_me.h \
|
../connection/ble/ble_me.h \
|
||||||
|
../connection/wifi/wifi_me.h \
|
||||||
qtandroidservice_ro.h
|
qtandroidservice_ro.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
../connection/connection.cpp \
|
../connection/connection.cpp \
|
||||||
../connection/ble/ble.cpp \
|
../connection/ble/ble.cpp \
|
||||||
../connection/ble/ble_me.cpp \
|
../connection/ble/ble_me.cpp \
|
||||||
|
../connection/wifi/wifi_me.cpp \
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
REPC_SOURCE += qtandroidservice.rep
|
REPC_SOURCE += qtandroidservice.rep
|
||||||
|
|
|
||||||
|
|
@ -128,13 +128,13 @@ void BLE_ME::characteristicRead(const QLowEnergyCharacteristic&,
|
||||||
const QByteArray& data) {
|
const QByteArray& data) {
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
if (!con->backgroundMode) {
|
if (!con->backgroundMode) {
|
||||||
emitter->receivingDone();
|
|
||||||
static bool startup = true;
|
static bool startup = true;
|
||||||
if (startup) {
|
if (startup) {
|
||||||
con->sendSavedBytes(); // for eventual, saved but not sent packets
|
con->sendSavedBytes(); // for eventual, saved but not sent packets
|
||||||
} else {
|
} else {
|
||||||
startup = false;
|
startup = false;
|
||||||
}
|
}
|
||||||
|
emitter->receivingDone();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (con->backgroundMode) {
|
if (con->backgroundMode) {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ Q_SIGNALS:
|
||||||
void setReady(bool, const QString&, const QStringList&);
|
void setReady(bool, const QString&, const QStringList&);
|
||||||
void receivedFromRadio(const QByteArray&, const QString&);
|
void receivedFromRadio(const QByteArray&, const QString&);
|
||||||
void receivingDone();
|
void receivingDone();
|
||||||
void sendSavedPackets(const QVariant&);
|
|
||||||
|
|
||||||
/*** </INTERFACE> ***************************************/
|
/*** </INTERFACE> ***************************************/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "ble/ble_me.h"
|
#include "ble/ble_me.h"
|
||||||
|
#include "wifi/wifi_me.h"
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
|
@ -19,37 +20,44 @@ Connection::Connection(QtAndroidService* service) {
|
||||||
// forward signal
|
// forward signal
|
||||||
connect(this, &Connection::sendSavedPackets, service, &QtAndroidService::sendSavedPackets);
|
connect(this, &Connection::sendSavedPackets, service, &QtAndroidService::sendSavedPackets);
|
||||||
ble = new BLE_ME(service, this);
|
ble = new BLE_ME(service, this);
|
||||||
|
wifi = new WiFi_ME(service, this);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Connection::Connection() {
|
Connection::Connection() {
|
||||||
ble = new BLE_ME(this);
|
ble = new BLE_ME(this);
|
||||||
usb = new USB_ME(this);
|
usb = new USB_ME(this);
|
||||||
|
wifi = new WiFi_ME(this);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Connection::setConnectionType(const QVariant& vType) {
|
void Connection::setConnectionType(const QVariant& var) {
|
||||||
QByteArray t = vType.toByteArray();
|
type = Type(BLE + (QList<QByteArray>() << "BLE" << "USB" << "WIFI")
|
||||||
if (t == "USB") {
|
.indexOf(var.toByteArray()));
|
||||||
type = USB;
|
|
||||||
} else {
|
|
||||||
type = BLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::startDeviceDiscovery(const QVariant& vName) {
|
void Connection::startDeviceDiscovery(const QVariant& var) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BLE:
|
case BLE:
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
usb->disconnect();
|
usb->disconnect();
|
||||||
#endif
|
#endif
|
||||||
ble->startDeviceDiscovery(vName.toString());
|
wifi->disconnect();
|
||||||
|
ble->startDeviceDiscovery(var.toString());
|
||||||
break;
|
break;
|
||||||
case USB:
|
case USB:
|
||||||
ble->disconnect();
|
ble->disconnect();
|
||||||
|
wifi->disconnect();
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
usb->connectToRadio();
|
usb->connectToRadio();
|
||||||
#endif
|
#endif
|
||||||
break;
|
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() {
|
void Connection::disconnect() {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case BLE: ble->disconnect(); break;
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
case USB: usb->disconnect(); break;
|
case USB: usb->disconnect(); break;
|
||||||
#endif
|
#endif
|
||||||
case BLE: ble->disconnect(); break;
|
case WiFi: wifi->disconnect(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,6 +94,9 @@ void Connection::write2(const QVariant& vBytes) {
|
||||||
usb->write2(bytes);
|
usb->write2(bytes);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case WiFi:
|
||||||
|
wifi->write2(bytes);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,11 @@
|
||||||
|
|
||||||
class BLE_ME;
|
class BLE_ME;
|
||||||
class USB_ME;
|
class USB_ME;
|
||||||
class QtAndroidService;
|
class WiFi_ME;
|
||||||
|
|
||||||
|
#ifdef Q_OS_ANDROID
|
||||||
|
class QtAndroidService;
|
||||||
|
#endif
|
||||||
|
|
||||||
class Connection : public QObject {
|
class Connection : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
@ -18,12 +22,13 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
BLE, USB
|
BLE, USB, WiFi
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type = BLE;
|
Type type = BLE;
|
||||||
BLE_ME* ble = nullptr;
|
BLE_ME* ble = nullptr;
|
||||||
USB_ME* usb = nullptr;
|
USB_ME* usb = nullptr;
|
||||||
|
WiFi_ME* wifi = nullptr;
|
||||||
bool backgroundMode = false;
|
bool backgroundMode = false;
|
||||||
|
|
||||||
void setConnectionType(const QVariant&);
|
void setConnectionType(const QVariant&);
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ void USB_ME::disconnect() {
|
||||||
|
|
||||||
void USB_ME::write2(const QByteArray& data) {
|
void USB_ME::write2(const QByteArray& data) {
|
||||||
if (ready) {
|
if (ready) {
|
||||||
write(data.constData(), data.size());
|
write(data);
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "USB not ready: write()";
|
qDebug() << "USB not ready: write()";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
87
examples/meshtastic/cpp/connection/wifi/wifi_me.cpp
Normal file
87
examples/meshtastic/cpp/connection/wifi/wifi_me.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
51
examples/meshtastic/cpp/connection/wifi/wifi_me.h
Normal file
51
examples/meshtastic/cpp/connection/wifi/wifi_me.h
Normal 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);
|
||||||
|
};
|
||||||
|
|
@ -14,6 +14,7 @@ HEADERS += \
|
||||||
connection/ble/ble.h \
|
connection/ble/ble.h \
|
||||||
connection/ble/ble_me.h \
|
connection/ble/ble_me.h \
|
||||||
connection/usb/usb_me.h \
|
connection/usb/usb_me.h \
|
||||||
|
connection/wifi/wifi_me.h \
|
||||||
qt.h
|
qt.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
|
@ -21,6 +22,7 @@ SOURCES += \
|
||||||
connection/ble/ble.cpp \
|
connection/ble/ble.cpp \
|
||||||
connection/ble/ble_me.cpp \
|
connection/ble/ble_me.cpp \
|
||||||
connection/usb/usb_me.cpp \
|
connection/usb/usb_me.cpp \
|
||||||
|
connection/wifi/wifi_me.cpp \
|
||||||
qt.cpp
|
qt.cpp
|
||||||
|
|
||||||
linux {
|
linux {
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,10 @@
|
||||||
*schedule-clear* t)
|
*schedule-clear* t)
|
||||||
(unless radios:*found*
|
(unless radios:*found*
|
||||||
(radios:clear))
|
(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)))
|
(q> |playing| ui:*busy* t)))
|
||||||
|
|
||||||
(defun get-node-config ()
|
(defun get-node-config ()
|
||||||
|
|
@ -81,7 +84,12 @@
|
||||||
(destructuring-bind (port)
|
(destructuring-bind (port)
|
||||||
args
|
args
|
||||||
(setf *ready* t)
|
(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)
|
(get-node-config)
|
||||||
(values))
|
(values))
|
||||||
|
|
||||||
|
|
@ -152,11 +160,13 @@
|
||||||
(let* ((bytes (pr:serialize-to-bytes to-radio))
|
(let* ((bytes (pr:serialize-to-bytes to-radio))
|
||||||
(header (header (length bytes))))
|
(header (header (length bytes))))
|
||||||
(case radios:*connection*
|
(case radios:*connection*
|
||||||
(:ble (qrun*
|
(:ble
|
||||||
(qt:write* qt:*cpp* header)
|
(qrun*
|
||||||
(qt:write* qt:*cpp* bytes)))
|
(qt:write* qt:*cpp* header)
|
||||||
(:usb (qrun*
|
(qt:write* qt:*cpp* bytes)))
|
||||||
(qt:write* qt:*cpp* (concatenate 'vector header bytes)))))))
|
((:usb :wifi)
|
||||||
|
(qrun*
|
||||||
|
(qt:write* qt:*cpp* (concatenate 'vector header bytes)))))))
|
||||||
|
|
||||||
(defun received-from-radio (args) ; see Qt
|
(defun received-from-radio (args) ; see Qt
|
||||||
(destructuring-bind (bytes &optional notified)
|
(destructuring-bind (bytes &optional notified)
|
||||||
|
|
@ -302,7 +312,7 @@
|
||||||
:custom-name (or (app:setting name :custom-name) "")
|
:custom-name (or (app:setting name :custom-name) "")
|
||||||
:node-num (me:num info)
|
:node-num (me:num info)
|
||||||
:current (equal name (app:setting :latest-receiver)))))
|
:current (equal name (app:setting :latest-receiver)))))
|
||||||
(when (or (and (eql radios:*connection* :usb)
|
(when (or (and (find radios:*connection* '(:usb :wifi))
|
||||||
current)
|
current)
|
||||||
(find name *ble-names* :test 'string=))
|
(find name *ble-names* :test 'string=))
|
||||||
(setf radios:*found* t)
|
(setf radios:*found* t)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
(in-package :radios)
|
(in-package :radios)
|
||||||
|
|
||||||
(defvar *connection* nil)
|
(defvar *connection* nil) ; :ble :usb :wifi
|
||||||
(defvar *found* nil)
|
(defvar *found* nil)
|
||||||
|
|
||||||
(defun ini ()
|
(defun ini ()
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,13 @@ Item {
|
||||||
enabled: (Qt.platform.os !== "android") && (Qt.platform.os !== "ios")
|
enabled: (Qt.platform.os !== "android") && (Qt.platform.os !== "ios")
|
||||||
onTriggered: connection.changed(objectName)
|
onTriggered: connection.changed(objectName)
|
||||||
}
|
}
|
||||||
|
Com.MenuItem {
|
||||||
|
objectName: "WIFI"
|
||||||
|
text: "WiFi"
|
||||||
|
autoExclusive: true
|
||||||
|
checkable: true
|
||||||
|
onTriggered: connection.changed(objectName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Com.MenuItem {
|
Com.MenuItem {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue