diff --git a/examples/meshtastic/app.pro b/examples/meshtastic/app.pro index 7d6c83a..70f8677 100644 --- a/examples/meshtastic/app.pro +++ b/examples/meshtastic/app.pro @@ -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/*) diff --git a/examples/meshtastic/cpp/android_service/qtandroidservice.rep b/examples/meshtastic/cpp/android_service/qtandroidservice.rep index f219b51..8cdd632 100644 --- a/examples/meshtastic/cpp/android_service/qtandroidservice.rep +++ b/examples/meshtastic/cpp/android_service/qtandroidservice.rep @@ -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&)); diff --git a/examples/meshtastic/cpp/android_service/service.pro b/examples/meshtastic/cpp/android_service/service.pro index 8c83a4b..35b55dc 100644 --- a/examples/meshtastic/cpp/android_service/service.pro +++ b/examples/meshtastic/cpp/android_service/service.pro @@ -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 diff --git a/examples/meshtastic/cpp/connection/ble/ble_me.cpp b/examples/meshtastic/cpp/connection/ble/ble_me.cpp index f56a79a..9ac9a4e 100644 --- a/examples/meshtastic/cpp/connection/ble/ble_me.cpp +++ b/examples/meshtastic/cpp/connection/ble/ble_me.cpp @@ -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) { diff --git a/examples/meshtastic/cpp/connection/ble/ble_me.h b/examples/meshtastic/cpp/connection/ble/ble_me.h index d2dfe2c..5e9f5bb 100644 --- a/examples/meshtastic/cpp/connection/ble/ble_me.h +++ b/examples/meshtastic/cpp/connection/ble/ble_me.h @@ -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&); /*** ***************************************/ diff --git a/examples/meshtastic/cpp/connection/connection.cpp b/examples/meshtastic/cpp/connection/connection.cpp index 692f52e..0c39363 100644 --- a/examples/meshtastic/cpp/connection/connection.cpp +++ b/examples/meshtastic/cpp/connection/connection.cpp @@ -1,5 +1,6 @@ #include "connection.h" #include "ble/ble_me.h" +#include "wifi/wifi_me.h" #include #include #include @@ -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() << "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; } } diff --git a/examples/meshtastic/cpp/connection/connection.h b/examples/meshtastic/cpp/connection/connection.h index f03bb67..eb68e89 100644 --- a/examples/meshtastic/cpp/connection/connection.h +++ b/examples/meshtastic/cpp/connection/connection.h @@ -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&); diff --git a/examples/meshtastic/cpp/connection/usb/usb_me.cpp b/examples/meshtastic/cpp/connection/usb/usb_me.cpp index 3b6469c..6d9840d 100644 --- a/examples/meshtastic/cpp/connection/usb/usb_me.cpp +++ b/examples/meshtastic/cpp/connection/usb/usb_me.cpp @@ -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()"; } diff --git a/examples/meshtastic/cpp/connection/wifi/wifi_me.cpp b/examples/meshtastic/cpp/connection/wifi/wifi_me.cpp new file mode 100644 index 0000000..2b169fe --- /dev/null +++ b/examples/meshtastic/cpp/connection/wifi/wifi_me.cpp @@ -0,0 +1,87 @@ +#include "wifi_me.h" +#include "../connection.h" +#include + +#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(); +} + diff --git a/examples/meshtastic/cpp/connection/wifi/wifi_me.h b/examples/meshtastic/cpp/connection/wifi/wifi_me.h new file mode 100644 index 0000000..6e342d6 --- /dev/null +++ b/examples/meshtastic/cpp/connection/wifi/wifi_me.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#ifdef Q_OS_ANDROID +class QtAndroidService; +#endif +class Connection; + +class WiFi_ME : public QTcpSocket { + Q_OBJECT + + /*** ****************************************/ + +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(); + + /*** ***************************************/ + +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); +}; diff --git a/examples/meshtastic/cpp/qt.pro b/examples/meshtastic/cpp/qt.pro index cff4119..b8c40d9 100644 --- a/examples/meshtastic/cpp/qt.pro +++ b/examples/meshtastic/cpp/qt.pro @@ -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 { diff --git a/examples/meshtastic/lisp/lora.lisp b/examples/meshtastic/lisp/lora.lisp index 48f2495..5b68961 100644 --- a/examples/meshtastic/lisp/lora.lisp +++ b/examples/meshtastic/lisp/lora.lisp @@ -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,11 +160,13 @@ (let* ((bytes (pr:serialize-to-bytes to-radio)) (header (header (length bytes)))) (case radios:*connection* - (:ble (qrun* - (qt:write* qt:*cpp* header) - (qt:write* qt:*cpp* bytes))) - (:usb (qrun* - (qt:write* qt:*cpp* (concatenate 'vector header bytes))))))) + (:ble + (qrun* + (qt:write* qt:*cpp* header) + (qt:write* qt:*cpp* bytes))) + ((:usb :wifi) + (qrun* + (qt:write* qt:*cpp* (concatenate 'vector header bytes))))))) (defun received-from-radio (args) ; see Qt (destructuring-bind (bytes &optional notified) @@ -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) diff --git a/examples/meshtastic/lisp/radios.lisp b/examples/meshtastic/lisp/radios.lisp index 656eff4..d1a3c50 100644 --- a/examples/meshtastic/lisp/radios.lisp +++ b/examples/meshtastic/lisp/radios.lisp @@ -1,6 +1,6 @@ (in-package :radios) -(defvar *connection* nil) +(defvar *connection* nil) ; :ble :usb :wifi (defvar *found* nil) (defun ini () diff --git a/examples/meshtastic/qml/main.qml b/examples/meshtastic/qml/main.qml index 352bd81..5924ee7 100644 --- a/examples/meshtastic/qml/main.qml +++ b/examples/meshtastic/qml/main.qml @@ -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 {