diff --git a/Main.qml b/Main.qml index b2886d5..0f60281 100644 --- a/Main.qml +++ b/Main.qml @@ -578,6 +578,20 @@ Window { color: root.accent_color font.pixelSize: root.font_normal_text_size } + Text { + id: last_updated_text + property string last_updated: "" + text: "Last Updated On Server On: " + last_updated + anchors { + top: info_percent_text.bottom + topMargin: 10 + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + color: root.accent_color + font.pixelSize: root.font_normal_text_size + visible: config.mode === "http" ? true : false + } Text { id: error_text @@ -585,7 +599,7 @@ Window { text: "Error: " + error_string visible: error_string === "" ? false : true; anchors { - top: info_percent_text.bottom + top: last_updated_text.bottom topMargin: 10 horizontalCenter: parent.horizontalCenter } @@ -644,6 +658,11 @@ Window { error_text.error_string = err; } + onLastUpdatedChanged: (update) => { + console.log("QML Last Updated: ", update); + last_updated_text.last_updated = update; + } + onDistanceChanged: { console.log("Distance changed"); root.distance = listener.distance; diff --git a/android/src/org/qtproject/example/appwaterLevelSensor/WaterLevelService.java b/android/src/org/qtproject/example/appwaterLevelSensor/WaterLevelService.java index a1becb2..79c4728 100644 --- a/android/src/org/qtproject/example/appwaterLevelSensor/WaterLevelService.java +++ b/android/src/org/qtproject/example/appwaterLevelSensor/WaterLevelService.java @@ -24,6 +24,7 @@ import java.io.InputStreamReader; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONArray; +import android.widget.Toast; public class WaterLevelService extends Service { @@ -84,7 +85,8 @@ public class WaterLevelService extends Service { } } catch (IOException e) { - Log.e("UDP Service", "Socket Error", e); + // showToast("IOException: " + e); + Log.e("UDP Service", "IOException Error" + e); } } @@ -132,12 +134,14 @@ public class WaterLevelService extends Service { count = 0; } byte[] buffer = null; + String updated = ""; if(mode.equals("udp")) { try { buffer = new byte[4]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket_recv.receive(packet); } catch(java.net.SocketTimeoutException e) { + // showToast("Socket Timeout: " + e); continue; } } @@ -163,24 +167,30 @@ public class WaterLevelService extends Service { JSONObject obj = new JSONObject(data); JSONArray arr = obj.getJSONArray("water_level"); float f = (float ) arr.getDouble(0); + updated = obj.getString("updated_on"); buffer = ByteBuffer.allocate(4).putFloat(f).array(); Log.d("UDP Service", "Got value from http: " + f); + Log.d("UDP Service", "Last updated on: " + updated); } catch (JSONException e) { Log.e("UDP Service", "Invalid Json"); + // showToast("Invalid Json" + e); + continue; } } else { + // showToast("Bad Response From Server: " + status); InputStreamReader streamReader = new InputStreamReader(con.getErrorStream()); continue; } } else { + Log.d("UDP Service", "Invalid mode: " + mode); + // showToast("Invalid mode: " + mode); try { Thread.sleep(3000); } catch (InterruptedException e) { continue; } - Log.d("UDP Service", "Invalid mode: " + mode); continue; } float f; @@ -220,10 +230,17 @@ public class WaterLevelService extends Service { DatagramPacket send_packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 8180); socket_send.send(send_packet); Log.d("UDP Service ", "Sent packet"); - } + if(mode.equals("http")) { + byte[] buff2 = updated.getBytes(StandardCharsets.UTF_8); + DatagramPacket send_packet_2 = new DatagramPacket(buff2, buff2.length, InetAddress.getByName("localhost"), 8185); + socket_send.send(send_packet_2); + Log.d("UDP Service ", "Sent last updated packet"); + } + } } catch (IOException e) { - Log.e("UDP Service", "Socket Error", e); + // showToast("IOException: " + e); + Log.e("UDP Service", "IOException Error" + e); } finally { if (wifiLock.isHeld()) wifiLock.release(); @@ -282,6 +299,11 @@ public class WaterLevelService extends Service { return START_STICKY; } + public void showToast(String str) { + int duration = Toast.LENGTH_SHORT; + Toast toast = Toast.makeText(this, str, duration); + toast.show(); + } private Notification createNotification() { String channelId = "water_level_channel"; diff --git a/configinterface.cpp b/configinterface.cpp index dcadda1..ab97ecb 100644 --- a/configinterface.cpp +++ b/configinterface.cpp @@ -23,12 +23,12 @@ ConfigInterface::ConfigInterface(QObject *parent) QJsonObject top = QJsonDocument::fromJson(data).object(); QString max, min, alert, mode, url; bool flipbits; - max = top["max_threshold"].toString(); - min = top["min_threshold"].toString(); - alert = top["alert_threshold"].toString(); - flipbits = top["flip_bits"].toBool(); - mode = top["mode"].toString(); - url = top["url"].toString(); + max = top["max_threshold"].toString("100"); + min = top["min_threshold"].toString("20"); + alert = top["alert_threshold"].toString("60"); + flipbits = top["flip_bits"].toBool(true); + mode = top["mode"].toString("http"); + url = top["url"].toString("https://unrealdragon.in/server/waterlevel"); setMax(max); setMin(min); setAlert(alert); diff --git a/udplistener.cpp b/udplistener.cpp index 5eb7f3a..52aaa8d 100644 --- a/udplistener.cpp +++ b/udplistener.cpp @@ -11,6 +11,7 @@ UDPListener::UDPListener(QObject *parent) worker = new Worker(this); thread = new QThread(this); worker->moveToThread(thread); + connect(worker, &Worker::lastUpdateddatagramReceived, this, &UDPListener::lastUpdateddatagramReceived); connect(worker, &Worker::datagramReceived, this, &UDPListener::datagramRecieved); connect(worker, &Worker::socketError, this, &UDPListener::socketError); connect(this, &UDPListener::startWorker, worker, &Worker::run); @@ -40,6 +41,13 @@ void UDPListener::setDistance(double newDistance) emit distanceChanged(); } +void UDPListener::lastUpdateddatagramReceived(QByteArray data) +{ + QString s_data = QString::fromUtf8(data); + qDebug() << "Main Class last updated on: " << s_data; + emit lastUpdatedChanged(s_data); +} + void UDPListener::continueDestruction() { destroyed = true; @@ -206,18 +214,22 @@ void Worker::gotHttpReply(QNetworkReply *rep) { QByteArray m_data = rep->readAll(); rep->deleteLater(); + qDebug() << "Got reply from http server"; QJsonObject top = QJsonDocument::fromJson(m_data).object(); - float distance = top["water_level"].toArray()[0].toDouble(); + float distance = (float ) top["water_level"].toArray()[0].toDouble(); QByteArray data, data2; + qDebug() << "Updated on: " << top["updated_on"].toString(); data = QByteArray::fromRawData((char *)&distance, sizeof(float)); char *buff = new char[4]; char *reader = (char *) &distance; for(int i=0;i< sizeof(float) ;i++) { + qDebug() << i << "vs" << sizeof(float) - 1 - i; buff[i] = reader[sizeof(float) - 1 - i]; } + delete[] buff; data2 = QByteArray::fromRawData(buff, sizeof(float)); emit datagramReceived(data, data2); - + emit lastUpdateddatagramReceived(top["updated_on"].toString().toUtf8()); } void Worker::httpTimerTimeout() @@ -248,22 +260,28 @@ void Worker::run() { using namespace std::chrono_literals; socket = new QUdpSocket(this); + socket_2 = new QUdpSocket(this); httpTimer = new QTimer(this); manager = new QNetworkAccessManager(this); #ifdef Q_OS_ANDROID // If it is android use it as a command socket; bool bind = socket->bind(QHostAddress::Any, 8180); + bool bind2 = socket_2->bind(QHostAddress::Any, 8185); #else // Else use it as a receiver; bool bind = socket->bind(QHostAddress("192.168.1.255"), 8176); + bool bind2 = true; #endif - if(!bind) + if(!bind || !bind2) { qDebug() << "UI Worker socket bind failed" << bind << socket->errorString(); emit socketError(socket->errorString()); + emit socketError(socket_2->errorString()); } connect(httpTimer, &QTimer::timeout, this, &Worker::httpTimerTimeout); connect(socket, &QUdpSocket::readyRead, this, &Worker::socketDataReceived); + connect(socket_2, &QUdpSocket::readyRead, this, &Worker::socket2DataReceived); + } void Worker::changeMode(QString mode, QString url) @@ -271,7 +289,7 @@ void Worker::changeMode(QString mode, QString url) qDebug() << "Worker changing mode: " << mode << url; this->mode = mode; this->url = url; - if(mode == "http") { + if(mode == "http" && QSysInfo::productType() != "android") { httpTimer->setInterval(2000); httpTimer->setSingleShot(false); httpTimer->start(); @@ -282,10 +300,28 @@ void Worker::changeMode(QString mode, QString url) } } +void Worker::socket2DataReceived() +{ + if(socket_2->hasPendingDatagrams()) { + if(mode == "http") { + size_t data_size = socket_2->pendingDatagramSize(); + qDebug() << "Socket 2 has pending data: " << data_size; + char buff[data_size]; + socket_2->readDatagram(buff, data_size); + QByteArray data = QByteArray::fromRawData(buff, data_size); + emit lastUpdateddatagramReceived(data); + } + else if(mode == "udp") { + qDebug() << "Last Updated on Socket data received in udp mode ignoring it."; + } + } + +} + void Worker::socketDataReceived() { if(socket->hasPendingDatagrams()) { - if(mode == "udp") { + if(mode == "udp" || (mode == "http" && QSysInfo::productType() == "android")) { qDebug() << "Socket has pending data: " << socket->pendingDatagramSize(); char buff[4] = {0x00, 0x00, 0x00, 0x00}; socket->readDatagram(buff, 4); diff --git a/udplistener.h b/udplistener.h index 71f9f79..0a950e5 100644 --- a/udplistener.h +++ b/udplistener.h @@ -19,6 +19,7 @@ class Worker: public QObject { Q_OBJECT QUdpSocket *socket = nullptr; + QUdpSocket *socket_2 = nullptr; QString mode = ""; QString url = ""; QNetworkAccessManager *manager = nullptr; @@ -28,6 +29,7 @@ public: signals: void stopped(); void socketError(QString error); + void lastUpdateddatagramReceived(QByteArray data); void datagramReceived(QByteArray data, QByteArray data2); public slots: void gotHttpReply(QNetworkReply *rep); @@ -36,6 +38,7 @@ public slots: void run(); void changeMode(QString mode, QString url); private slots: + void socket2DataReceived(); void socketDataReceived(); }; @@ -50,6 +53,7 @@ public: double distance() const; void setDistance(double newDistance); signals: + void lastUpdatedChanged(QString last_updated); void stopWorker(); void showError(QString err); void distanceChanged(); @@ -59,6 +63,7 @@ signals: void distanceReceived(double dist, QString timestamp); void changeWorkerMode(QString mode, QString url); public slots: + void lastUpdateddatagramReceived(QByteArray data); void continueDestruction(); void resetAverages(); void setFlipBits(bool flip_bits);