This commit is contained in:
TheUnrealDragon 2026-04-13 19:34:36 +05:30
commit f59704545b
5 changed files with 98 additions and 16 deletions

View file

@ -578,6 +578,20 @@ Window {
color: root.accent_color color: root.accent_color
font.pixelSize: root.font_normal_text_size 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 { Text {
id: error_text id: error_text
@ -585,7 +599,7 @@ Window {
text: "Error: " + error_string text: "Error: " + error_string
visible: error_string === "" ? false : true; visible: error_string === "" ? false : true;
anchors { anchors {
top: info_percent_text.bottom top: last_updated_text.bottom
topMargin: 10 topMargin: 10
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
} }
@ -644,6 +658,11 @@ Window {
error_text.error_string = err; error_text.error_string = err;
} }
onLastUpdatedChanged: (update) => {
console.log("QML Last Updated: ", update);
last_updated_text.last_updated = update;
}
onDistanceChanged: { onDistanceChanged: {
console.log("Distance changed"); console.log("Distance changed");
root.distance = listener.distance; root.distance = listener.distance;

View file

@ -24,6 +24,7 @@ import java.io.InputStreamReader;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.json.JSONArray; import org.json.JSONArray;
import android.widget.Toast;
public class WaterLevelService extends Service { public class WaterLevelService extends Service {
@ -84,7 +85,8 @@ public class WaterLevelService extends Service {
} }
} }
catch (IOException e) { 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; count = 0;
} }
byte[] buffer = null; byte[] buffer = null;
String updated = "";
if(mode.equals("udp")) { if(mode.equals("udp")) {
try { try {
buffer = new byte[4]; buffer = new byte[4];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length); DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket_recv.receive(packet); socket_recv.receive(packet);
} catch(java.net.SocketTimeoutException e) { } catch(java.net.SocketTimeoutException e) {
// showToast("Socket Timeout: " + e);
continue; continue;
} }
} }
@ -163,24 +167,30 @@ public class WaterLevelService extends Service {
JSONObject obj = new JSONObject(data); JSONObject obj = new JSONObject(data);
JSONArray arr = obj.getJSONArray("water_level"); JSONArray arr = obj.getJSONArray("water_level");
float f = (float ) arr.getDouble(0); float f = (float ) arr.getDouble(0);
updated = obj.getString("updated_on");
buffer = ByteBuffer.allocate(4).putFloat(f).array(); buffer = ByteBuffer.allocate(4).putFloat(f).array();
Log.d("UDP Service", "Got value from http: " + f); Log.d("UDP Service", "Got value from http: " + f);
Log.d("UDP Service", "Last updated on: " + updated);
} catch (JSONException e) { } catch (JSONException e) {
Log.e("UDP Service", "Invalid Json"); Log.e("UDP Service", "Invalid Json");
// showToast("Invalid Json" + e);
continue;
} }
} }
else { else {
// showToast("Bad Response From Server: " + status);
InputStreamReader streamReader = new InputStreamReader(con.getErrorStream()); InputStreamReader streamReader = new InputStreamReader(con.getErrorStream());
continue; continue;
} }
} }
else { else {
Log.d("UDP Service", "Invalid mode: " + mode);
// showToast("Invalid mode: " + mode);
try { try {
Thread.sleep(3000); Thread.sleep(3000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
continue; continue;
} }
Log.d("UDP Service", "Invalid mode: " + mode);
continue; continue;
} }
float f; float f;
@ -220,10 +230,17 @@ public class WaterLevelService extends Service {
DatagramPacket send_packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 8180); DatagramPacket send_packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 8180);
socket_send.send(send_packet); socket_send.send(send_packet);
Log.d("UDP Service ", "Sent 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) { catch (IOException e) {
Log.e("UDP Service", "Socket Error", e); // showToast("IOException: " + e);
Log.e("UDP Service", "IOException Error" + e);
} finally { } finally {
if (wifiLock.isHeld()) if (wifiLock.isHeld())
wifiLock.release(); wifiLock.release();
@ -282,6 +299,11 @@ public class WaterLevelService extends Service {
return START_STICKY; 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() { private Notification createNotification() {
String channelId = "water_level_channel"; String channelId = "water_level_channel";

View file

@ -23,12 +23,12 @@ ConfigInterface::ConfigInterface(QObject *parent)
QJsonObject top = QJsonDocument::fromJson(data).object(); QJsonObject top = QJsonDocument::fromJson(data).object();
QString max, min, alert, mode, url; QString max, min, alert, mode, url;
bool flipbits; bool flipbits;
max = top["max_threshold"].toString(); max = top["max_threshold"].toString("100");
min = top["min_threshold"].toString(); min = top["min_threshold"].toString("20");
alert = top["alert_threshold"].toString(); alert = top["alert_threshold"].toString("60");
flipbits = top["flip_bits"].toBool(); flipbits = top["flip_bits"].toBool(true);
mode = top["mode"].toString(); mode = top["mode"].toString("http");
url = top["url"].toString(); url = top["url"].toString("https://unrealdragon.in/server/waterlevel");
setMax(max); setMax(max);
setMin(min); setMin(min);
setAlert(alert); setAlert(alert);

View file

@ -11,6 +11,7 @@ UDPListener::UDPListener(QObject *parent)
worker = new Worker(this); worker = new Worker(this);
thread = new QThread(this); thread = new QThread(this);
worker->moveToThread(thread); worker->moveToThread(thread);
connect(worker, &Worker::lastUpdateddatagramReceived, this, &UDPListener::lastUpdateddatagramReceived);
connect(worker, &Worker::datagramReceived, this, &UDPListener::datagramRecieved); connect(worker, &Worker::datagramReceived, this, &UDPListener::datagramRecieved);
connect(worker, &Worker::socketError, this, &UDPListener::socketError); connect(worker, &Worker::socketError, this, &UDPListener::socketError);
connect(this, &UDPListener::startWorker, worker, &Worker::run); connect(this, &UDPListener::startWorker, worker, &Worker::run);
@ -40,6 +41,13 @@ void UDPListener::setDistance(double newDistance)
emit distanceChanged(); 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() void UDPListener::continueDestruction()
{ {
destroyed = true; destroyed = true;
@ -206,18 +214,22 @@ void Worker::gotHttpReply(QNetworkReply *rep)
{ {
QByteArray m_data = rep->readAll(); QByteArray m_data = rep->readAll();
rep->deleteLater(); rep->deleteLater();
qDebug() << "Got reply from http server";
QJsonObject top = QJsonDocument::fromJson(m_data).object(); 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; QByteArray data, data2;
qDebug() << "Updated on: " << top["updated_on"].toString();
data = QByteArray::fromRawData((char *)&distance, sizeof(float)); data = QByteArray::fromRawData((char *)&distance, sizeof(float));
char *buff = new char[4]; char *buff = new char[4];
char *reader = (char *) &distance; char *reader = (char *) &distance;
for(int i=0;i< sizeof(float) ;i++) { for(int i=0;i< sizeof(float) ;i++) {
qDebug() << i << "vs" << sizeof(float) - 1 - i;
buff[i] = reader[sizeof(float) - 1 - i]; buff[i] = reader[sizeof(float) - 1 - i];
} }
delete[] buff;
data2 = QByteArray::fromRawData(buff, sizeof(float)); data2 = QByteArray::fromRawData(buff, sizeof(float));
emit datagramReceived(data, data2); emit datagramReceived(data, data2);
emit lastUpdateddatagramReceived(top["updated_on"].toString().toUtf8());
} }
void Worker::httpTimerTimeout() void Worker::httpTimerTimeout()
@ -248,22 +260,28 @@ void Worker::run()
{ {
using namespace std::chrono_literals; using namespace std::chrono_literals;
socket = new QUdpSocket(this); socket = new QUdpSocket(this);
socket_2 = new QUdpSocket(this);
httpTimer = new QTimer(this); httpTimer = new QTimer(this);
manager = new QNetworkAccessManager(this); manager = new QNetworkAccessManager(this);
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
// If it is android use it as a command socket; // If it is android use it as a command socket;
bool bind = socket->bind(QHostAddress::Any, 8180); bool bind = socket->bind(QHostAddress::Any, 8180);
bool bind2 = socket_2->bind(QHostAddress::Any, 8185);
#else #else
// Else use it as a receiver; // Else use it as a receiver;
bool bind = socket->bind(QHostAddress("192.168.1.255"), 8176); bool bind = socket->bind(QHostAddress("192.168.1.255"), 8176);
bool bind2 = true;
#endif #endif
if(!bind) if(!bind || !bind2)
{ {
qDebug() << "UI Worker socket bind failed" << bind << socket->errorString(); qDebug() << "UI Worker socket bind failed" << bind << socket->errorString();
emit socketError(socket->errorString()); emit socketError(socket->errorString());
emit socketError(socket_2->errorString());
} }
connect(httpTimer, &QTimer::timeout, this, &Worker::httpTimerTimeout); connect(httpTimer, &QTimer::timeout, this, &Worker::httpTimerTimeout);
connect(socket, &QUdpSocket::readyRead, this, &Worker::socketDataReceived); connect(socket, &QUdpSocket::readyRead, this, &Worker::socketDataReceived);
connect(socket_2, &QUdpSocket::readyRead, this, &Worker::socket2DataReceived);
} }
void Worker::changeMode(QString mode, QString url) void Worker::changeMode(QString mode, QString url)
@ -271,7 +289,7 @@ void Worker::changeMode(QString mode, QString url)
qDebug() << "Worker changing mode: " << mode << url; qDebug() << "Worker changing mode: " << mode << url;
this->mode = mode; this->mode = mode;
this->url = url; this->url = url;
if(mode == "http") { if(mode == "http" && QSysInfo::productType() != "android") {
httpTimer->setInterval(2000); httpTimer->setInterval(2000);
httpTimer->setSingleShot(false); httpTimer->setSingleShot(false);
httpTimer->start(); 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() void Worker::socketDataReceived()
{ {
if(socket->hasPendingDatagrams()) { if(socket->hasPendingDatagrams()) {
if(mode == "udp") { if(mode == "udp" || (mode == "http" && QSysInfo::productType() == "android")) {
qDebug() << "Socket has pending data: " << socket->pendingDatagramSize(); qDebug() << "Socket has pending data: " << socket->pendingDatagramSize();
char buff[4] = {0x00, 0x00, 0x00, 0x00}; char buff[4] = {0x00, 0x00, 0x00, 0x00};
socket->readDatagram(buff, 4); socket->readDatagram(buff, 4);

View file

@ -19,6 +19,7 @@
class Worker: public QObject { class Worker: public QObject {
Q_OBJECT Q_OBJECT
QUdpSocket *socket = nullptr; QUdpSocket *socket = nullptr;
QUdpSocket *socket_2 = nullptr;
QString mode = ""; QString mode = "";
QString url = ""; QString url = "";
QNetworkAccessManager *manager = nullptr; QNetworkAccessManager *manager = nullptr;
@ -28,6 +29,7 @@ public:
signals: signals:
void stopped(); void stopped();
void socketError(QString error); void socketError(QString error);
void lastUpdateddatagramReceived(QByteArray data);
void datagramReceived(QByteArray data, QByteArray data2); void datagramReceived(QByteArray data, QByteArray data2);
public slots: public slots:
void gotHttpReply(QNetworkReply *rep); void gotHttpReply(QNetworkReply *rep);
@ -36,6 +38,7 @@ public slots:
void run(); void run();
void changeMode(QString mode, QString url); void changeMode(QString mode, QString url);
private slots: private slots:
void socket2DataReceived();
void socketDataReceived(); void socketDataReceived();
}; };
@ -50,6 +53,7 @@ public:
double distance() const; double distance() const;
void setDistance(double newDistance); void setDistance(double newDistance);
signals: signals:
void lastUpdatedChanged(QString last_updated);
void stopWorker(); void stopWorker();
void showError(QString err); void showError(QString err);
void distanceChanged(); void distanceChanged();
@ -59,6 +63,7 @@ signals:
void distanceReceived(double dist, QString timestamp); void distanceReceived(double dist, QString timestamp);
void changeWorkerMode(QString mode, QString url); void changeWorkerMode(QString mode, QString url);
public slots: public slots:
void lastUpdateddatagramReceived(QByteArray data);
void continueDestruction(); void continueDestruction();
void resetAverages(); void resetAverages();
void setFlipBits(bool flip_bits); void setFlipBits(bool flip_bits);