v0.0.7
This commit is contained in:
parent
26d3fce10a
commit
984c5acacc
7 changed files with 376 additions and 37 deletions
|
|
@ -16,10 +16,22 @@ qt_add_executable(appwaterLevelSensor
|
||||||
|
|
||||||
|
|
||||||
if(ANDROID)
|
if(ANDROID)
|
||||||
|
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
android_openssl
|
||||||
|
DOWNLOAD_EXTRACT_TIMESTAMP true
|
||||||
|
URL https://github.com/KDAB/android_openssl/archive/refs/heads/master.zip
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(android_openssl)
|
||||||
|
include(${android_openssl_SOURCE_DIR}/android_openssl.cmake)
|
||||||
|
|
||||||
qt_add_library(service SHARED
|
qt_add_library(service SHARED
|
||||||
servicemain.cpp
|
servicemain.cpp
|
||||||
service.h service.cpp
|
service.h service.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
set_property(TARGET appwaterLevelSensor APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
set_property(TARGET appwaterLevelSensor APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/android)
|
${CMAKE_CURRENT_SOURCE_DIR}/android)
|
||||||
set_property(TARGET service APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
set_property(TARGET service APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
|
||||||
|
|
@ -45,6 +57,7 @@ qt_add_qml_module(appwaterLevelSensor
|
||||||
SOURCES service.h
|
SOURCES service.h
|
||||||
RESOURCES README.md
|
RESOURCES README.md
|
||||||
)
|
)
|
||||||
|
add_android_openssl_libraries(service appwaterLevelSensor)
|
||||||
target_link_libraries(appwaterLevelSensor
|
target_link_libraries(appwaterLevelSensor
|
||||||
PRIVATE Qt6::Quick Qt6::Network service
|
PRIVATE Qt6::Quick Qt6::Network service
|
||||||
)
|
)
|
||||||
|
|
|
||||||
130
Main.qml
130
Main.qml
|
|
@ -11,6 +11,7 @@ Window {
|
||||||
title: qsTr("Hello World")
|
title: qsTr("Hello World")
|
||||||
id: root
|
id: root
|
||||||
property color accent_color: "#F05FAF5F"
|
property color accent_color: "#F05FAF5F"
|
||||||
|
property color dark_accent_color: "#FF5F7F5F"
|
||||||
property color danger_color: "#F0AF2F1F"
|
property color danger_color: "#F0AF2F1F"
|
||||||
property color water_color: "#F00F7FAF"
|
property color water_color: "#F00F7FAF"
|
||||||
Material.accent: root.accent_color
|
Material.accent: root.accent_color
|
||||||
|
|
@ -18,6 +19,7 @@ Window {
|
||||||
property int font_normal_text_size: 16
|
property int font_normal_text_size: 16
|
||||||
property double distance: 0
|
property double distance: 0
|
||||||
property int distance_count: 0
|
property int distance_count: 0
|
||||||
|
property string mode: "http"
|
||||||
// visibility: Window.FullScreen
|
// visibility: Window.FullScreen
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if(Qt.platform.os !== "android") {
|
if(Qt.platform.os !== "android") {
|
||||||
|
|
@ -150,8 +152,8 @@ Window {
|
||||||
border.color: root.accent_color
|
border.color: root.accent_color
|
||||||
border.width: 1
|
border.width: 1
|
||||||
}
|
}
|
||||||
height: parent.height / 1.5
|
height: parent.height / 1.2
|
||||||
width: parent.width / 1.5
|
width: parent.width / 1.1
|
||||||
anchors.centerIn: Overlay.overlay
|
anchors.centerIn: Overlay.overlay
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -279,7 +281,95 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: settings_mode_text
|
||||||
|
anchors {
|
||||||
|
topMargin: 20
|
||||||
|
top: flip_bits_box.bottom
|
||||||
|
left: parent.left
|
||||||
|
}
|
||||||
|
font.pointSize: root.font_normal_text_size
|
||||||
|
color: root.accent_color
|
||||||
|
text: "Mode: "
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
id: mode_row
|
||||||
|
anchors {
|
||||||
|
left: settings_mode_text.right
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: settings_mode_text.verticalCenter
|
||||||
|
leftMargin: 10
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
id: udp_radio_button
|
||||||
|
checked: config.mode === "udp" ? true : false
|
||||||
|
text: "UDP"
|
||||||
|
font.pointSize: root.font_normal_text_size
|
||||||
|
contentItem: Text {
|
||||||
|
text: udp_radio_button.text
|
||||||
|
font: udp_radio_button.font
|
||||||
|
opacity: enabled ? 1.0 : 0.3
|
||||||
|
color: udp_radio_button.down ? root.dark_accent_color : root.accent_color
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
leftPadding: udp_radio_button.indicator.width + udp_radio_button.spacing
|
||||||
|
}
|
||||||
|
onCheckedChanged: {
|
||||||
|
if(checked) {
|
||||||
|
root.mode = "udp";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RadioButton {
|
||||||
|
id: http_radio_button
|
||||||
|
checked: config.mode === "http" ? true : false
|
||||||
|
text: "HTTP"
|
||||||
|
font.pointSize: root.font_normal_text_size
|
||||||
|
contentItem: Text {
|
||||||
|
text: http_radio_button.text
|
||||||
|
font: http_radio_button.font
|
||||||
|
opacity: enabled ? 1.0 : 0.3
|
||||||
|
color: http_radio_button.down ? root.dark_accent_color : root.accent_color
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
leftPadding: http_radio_button.indicator.width + http_radio_button.spacing
|
||||||
|
}
|
||||||
|
onCheckedChanged: {
|
||||||
|
if(checked) {
|
||||||
|
root.mode = "http";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: http_url_label
|
||||||
|
text: "Url: "
|
||||||
|
anchors {
|
||||||
|
topMargin: 20
|
||||||
|
top: settings_mode_text.bottom
|
||||||
|
left: parent.left
|
||||||
|
verticalCenter: http_url_input.verticalCenter
|
||||||
|
}
|
||||||
|
height: http_url_input.height
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: root.accent_color
|
||||||
|
font.pointSize: root.font_normal_text_size
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: http_url_input
|
||||||
|
text: config.url
|
||||||
|
anchors {
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: 20
|
||||||
|
leftMargin: 20
|
||||||
|
top: mode_row.bottom
|
||||||
|
topMargin: 20
|
||||||
|
}
|
||||||
|
enabled: root.mode === "http" ? true : false
|
||||||
|
width: Math.max(parent.width / 2, parent.width - http_url_label.width - anchors.leftMargin)
|
||||||
|
color: root.accent_color
|
||||||
|
font.pointSize: root.font_normal_text_size
|
||||||
|
cursorPosition: 0
|
||||||
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: settings_error_label
|
id: settings_error_label
|
||||||
|
|
@ -288,8 +378,8 @@ Window {
|
||||||
visible: settings_error_text === "" ? false : true
|
visible: settings_error_text === "" ? false : true
|
||||||
anchors {
|
anchors {
|
||||||
topMargin: 20
|
topMargin: 20
|
||||||
top: flip_bits_box.bottom
|
top: http_url_label.bottom
|
||||||
bottom: flip_bits_box.top
|
bottom: reset_averages.top
|
||||||
bottomMargin: 10
|
bottomMargin: 10
|
||||||
left: parent.left
|
left: parent.left
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
|
@ -387,6 +477,8 @@ Window {
|
||||||
let min = parseFloat(min_thres_input.text);
|
let min = parseFloat(min_thres_input.text);
|
||||||
let alert = parseFloat(alert_thres_input.text);
|
let alert = parseFloat(alert_thres_input.text);
|
||||||
let flipBits = flip_bits_box.checked;
|
let flipBits = flip_bits_box.checked;
|
||||||
|
let mode = root.mode;
|
||||||
|
let url = http_url_input.text;
|
||||||
console.log("Parsed values:", max, min, alert, flip_bits_box.checked);
|
console.log("Parsed values:", max, min, alert, flip_bits_box.checked);
|
||||||
if(max < min) {
|
if(max < min) {
|
||||||
settings_error_label.settings_error_text = "Max cannot be less than min";
|
settings_error_label.settings_error_text = "Max cannot be less than min";
|
||||||
|
|
@ -400,8 +492,8 @@ Window {
|
||||||
let effective_max_reading = Math.max(0, (parseFloat(max_thres_input.text)) - current_min_reading);
|
let effective_max_reading = Math.max(0, (parseFloat(max_thres_input.text)) - current_min_reading);
|
||||||
let alert_effective_reading = (effective_max_reading * (100 - alert) / 100) + current_min_reading;
|
let alert_effective_reading = (effective_max_reading * (100 - alert) / 100) + current_min_reading;
|
||||||
console.log("Alert effective reading is: " + alert_effective_reading + " for value: " + alert);
|
console.log("Alert effective reading is: " + alert_effective_reading + " for value: " + alert);
|
||||||
listener.setConfig(alert_effective_reading, flipBits);
|
listener.setConfig(alert_effective_reading, flipBits, mode, url);
|
||||||
config.saveConfig(max_thres_input.text, min_thres_input.text, alert_thres_input.text, flip_bits_box.checked);
|
config.saveConfig(max_thres_input.text, min_thres_input.text, alert_thres_input.text, flip_bits_box.checked, mode, url);
|
||||||
settings_popup.close();
|
settings_popup.close();
|
||||||
}
|
}
|
||||||
onReleased: {
|
onReleased: {
|
||||||
|
|
@ -520,11 +612,30 @@ Window {
|
||||||
|
|
||||||
ConfigInterface {
|
ConfigInterface {
|
||||||
id: config
|
id: config
|
||||||
onConfigData: (max, min, alert) => {
|
onConfigData: (max, min, alert, mode, url) => {
|
||||||
console.log("Got config data as: ", max, min, alert);
|
console.log("Got config data as: ", max, min, alert, mode, url);
|
||||||
}
|
}
|
||||||
|
onModeChanged: {
|
||||||
|
root.mode = mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timer {
|
||||||
|
id: init_timer
|
||||||
|
running: true
|
||||||
|
repeat: false
|
||||||
|
interval: 1000
|
||||||
|
onTriggered: {
|
||||||
|
console.log("Timer triggered saving config, hope everything is loaded by now");
|
||||||
|
let current_min_reading = Math.max(0, (parseFloat(min_thres_input.text)));
|
||||||
|
let effective_max_reading = Math.max(0, (parseFloat(max_thres_input.text)) - current_min_reading);
|
||||||
|
let alert = parseFloat(alert_thres_input.text);
|
||||||
|
let alert_effective_reading = (effective_max_reading * (100 - alert) / 100) + current_min_reading;
|
||||||
|
console.log("Setting initial configs: ", alert_effective_reading, config.flipBits , config.mode, config.url);
|
||||||
|
listener.setConfig(alert_effective_reading, config.flipBits , config.mode, config.url);
|
||||||
|
http_url_input.cursorPosition = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
UDPListener {
|
UDPListener {
|
||||||
id: listener
|
id: listener
|
||||||
|
|
@ -585,8 +696,7 @@ Window {
|
||||||
let alert = parseFloat(alert_thres_input.text);
|
let alert = parseFloat(alert_thres_input.text);
|
||||||
let alert_effective_reading = (effective_max_reading * (100 - alert) / 100) + current_min_reading;
|
let alert_effective_reading = (effective_max_reading * (100 - alert) / 100) + current_min_reading;
|
||||||
console.log("Alert effective reading is: " + alert_effective_reading + " for value: " + alert);
|
console.log("Alert effective reading is: " + alert_effective_reading + " for value: " + alert);
|
||||||
|
listener.setConfig(alert_effective_reading, flip_bits_box.checked, root.mode, http_url_input.text);
|
||||||
listener.setConfig(alert_effective_reading, flip_bits_box.checked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
distance_count += 1;
|
distance_count += 1;
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,18 @@ import org.qtproject.qt.android.bindings.QtActivity;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
|
||||||
public class WaterLevelService extends Service {
|
public class WaterLevelService extends Service {
|
||||||
|
|
||||||
private static float alert_thres_distance = 1000000;
|
private static float alert_thres_distance = 1000000;
|
||||||
private boolean bits_flipped = false;
|
private boolean bits_flipped = false;
|
||||||
|
private String mode = "";
|
||||||
|
private String url = "";
|
||||||
|
|
||||||
public class UDPCommandClient implements Runnable {
|
public class UDPCommandClient implements Runnable {
|
||||||
private DatagramSocket socket_cmd_recv;
|
private DatagramSocket socket_cmd_recv;
|
||||||
|
|
@ -60,7 +67,20 @@ public class WaterLevelService extends Service {
|
||||||
bits_flipped = true;
|
bits_flipped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(str.startsWith("<SET NAME=MODE VALUE=")) {
|
||||||
|
str = str.replace("<SET NAME=MODE VALUE=", "");
|
||||||
|
str = str.replace("=", "");
|
||||||
|
str = str.replace(">", "");
|
||||||
|
Log.d("UDP Service ", "Mode " + str);
|
||||||
|
mode = str.toLowerCase();
|
||||||
|
}
|
||||||
|
else if(str.startsWith("<SET NAME=URL VALUE=")) {
|
||||||
|
str = str.replace("<SET NAME=URL VALUE=", "");
|
||||||
|
str = str.replace("=", "");
|
||||||
|
str = str.replace(">", "");
|
||||||
|
Log.d("UDP Service ", "Url " + str);
|
||||||
|
url = str.toLowerCase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
|
|
@ -108,16 +128,61 @@ public class WaterLevelService extends Service {
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
count++;
|
count++;
|
||||||
if(count == 3) {
|
if(count == 3) {
|
||||||
Log.i("UDP Service", "Thread is running");
|
Log.i("UDP Service", "Thread is running with mode: " + mode);
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
byte[] buffer = new byte[4];
|
byte[] buffer = null;
|
||||||
|
if(mode.equals("udp")) {
|
||||||
try {
|
try {
|
||||||
|
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) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if(mode.equals("http")) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(2000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log.d("UDP Service", "Http String Url: " + url);
|
||||||
|
URL t_url = new URL(url);
|
||||||
|
HttpURLConnection con = (HttpURLConnection) t_url.openConnection();
|
||||||
|
con.setRequestMethod("GET");
|
||||||
|
con.setConnectTimeout(5000);
|
||||||
|
con.setReadTimeout(5000);
|
||||||
|
con.setInstanceFollowRedirects(true);
|
||||||
|
int status = con.getResponseCode();
|
||||||
|
Log.d("UDP Service", "Got status from http: " + status);
|
||||||
|
if(status == 200) {
|
||||||
|
BufferedReader streamReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||||
|
String data = streamReader.readLine();
|
||||||
|
try {
|
||||||
|
JSONObject obj = new JSONObject(data);
|
||||||
|
JSONArray arr = obj.getJSONArray("water_level");
|
||||||
|
float f = (float ) arr.getDouble(0);
|
||||||
|
buffer = ByteBuffer.allocate(4).putFloat(f).array();
|
||||||
|
Log.d("UDP Service", "Got value from http: " + f);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e("UDP Service", "Invalid Json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
InputStreamReader streamReader = new InputStreamReader(con.getErrorStream());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
Thread.sleep(3000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log.d("UDP Service", "Invalid mode: " + mode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
float f;
|
float f;
|
||||||
if(bits_flipped) {
|
if(bits_flipped) {
|
||||||
f = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getFloat();
|
f = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getFloat();
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,20 @@ ConfigInterface::ConfigInterface(QObject *parent)
|
||||||
auto data = config.readAll();
|
auto data = config.readAll();
|
||||||
config.close();
|
config.close();
|
||||||
QJsonObject top = QJsonDocument::fromJson(data).object();
|
QJsonObject top = QJsonDocument::fromJson(data).object();
|
||||||
QString max, min, alert;
|
QString max, min, alert, mode, url;
|
||||||
bool flipbits;
|
bool flipbits;
|
||||||
max = top["max_threshold"].toString();
|
max = top["max_threshold"].toString();
|
||||||
min = top["min_threshold"].toString();
|
min = top["min_threshold"].toString();
|
||||||
alert = top["alert_threshold"].toString();
|
alert = top["alert_threshold"].toString();
|
||||||
flipbits = top["flip_bits"].toBool();
|
flipbits = top["flip_bits"].toBool();
|
||||||
|
mode = top["mode"].toString();
|
||||||
|
url = top["url"].toString();
|
||||||
setMax(max);
|
setMax(max);
|
||||||
setMin(min);
|
setMin(min);
|
||||||
setAlert(alert);
|
setAlert(alert);
|
||||||
setFlipBits(flipbits);
|
setFlipBits(flipbits);
|
||||||
|
setMode(mode);
|
||||||
|
setUrl(url);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug() << "File does not exist creating one...";
|
qDebug() << "File does not exist creating one...";
|
||||||
|
|
@ -38,6 +42,9 @@ ConfigInterface::ConfigInterface(QObject *parent)
|
||||||
top["max_threshold"] = "125";
|
top["max_threshold"] = "125";
|
||||||
top["min_threshold"] = "25";
|
top["min_threshold"] = "25";
|
||||||
top["alert_threshold"] = "100";
|
top["alert_threshold"] = "100";
|
||||||
|
top["flip_bits"] = true;
|
||||||
|
top["mode"] = "http";
|
||||||
|
top["url"] = "https://unrealdragon.in/server/waterlevel";
|
||||||
QByteArray data = QJsonDocument(top).toJson();
|
QByteArray data = QJsonDocument(top).toJson();
|
||||||
bool ok = config.open(QFile::WriteOnly);
|
bool ok = config.open(QFile::WriteOnly);
|
||||||
if(!ok) {
|
if(!ok) {
|
||||||
|
|
@ -47,10 +54,17 @@ ConfigInterface::ConfigInterface(QObject *parent)
|
||||||
config.write(data);
|
config.write(data);
|
||||||
config.flush();
|
config.flush();
|
||||||
config.close();
|
config.close();
|
||||||
|
setMax("125");
|
||||||
|
setMin("25");
|
||||||
|
setAlert("100");
|
||||||
|
setFlipBits(true);
|
||||||
|
setMode("http");
|
||||||
|
setUrl("https://unrealdragon.in/server/waterlevel");
|
||||||
|
qDebug() << "Config set initial values completed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigInterface::saveConfig(QString max, QString min, QString alert, bool flipbits)
|
void ConfigInterface::saveConfig(QString max, QString min, QString alert, bool flipbits, QString mode, QString url)
|
||||||
{
|
{
|
||||||
auto paths = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
auto paths = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
qDebug() << "Got writable path as: " << paths;
|
qDebug() << "Got writable path as: " << paths;
|
||||||
|
|
@ -62,9 +76,12 @@ void ConfigInterface::saveConfig(QString max, QString min, QString alert, bool f
|
||||||
top["min_threshold"] = min;
|
top["min_threshold"] = min;
|
||||||
top["alert_threshold"] = alert;
|
top["alert_threshold"] = alert;
|
||||||
top["flip_bits"] = flipbits;
|
top["flip_bits"] = flipbits;
|
||||||
|
top["mode"] = mode;
|
||||||
|
top["url"] = url;
|
||||||
setMax(max);
|
setMax(max);
|
||||||
setMin(min);
|
setMin(min);
|
||||||
setAlert(alert);
|
setAlert(alert);
|
||||||
|
setMode(mode);
|
||||||
QByteArray data = QJsonDocument(top).toJson();
|
QByteArray data = QJsonDocument(top).toJson();
|
||||||
config.open(QIODevice::WriteOnly);
|
config.open(QIODevice::WriteOnly);
|
||||||
config.write(data);
|
config.write(data);
|
||||||
|
|
@ -123,3 +140,29 @@ void ConfigInterface::setFlipBits(bool newFlipBits)
|
||||||
m_flipBits = newFlipBits;
|
m_flipBits = newFlipBits;
|
||||||
emit flipBitsChanged();
|
emit flipBitsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ConfigInterface::mode() const
|
||||||
|
{
|
||||||
|
return m_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInterface::setMode(const QString &newMode)
|
||||||
|
{
|
||||||
|
if (m_mode == newMode)
|
||||||
|
return;
|
||||||
|
m_mode = newMode;
|
||||||
|
emit modeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ConfigInterface::url() const
|
||||||
|
{
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigInterface::setUrl(const QString &newUrl)
|
||||||
|
{
|
||||||
|
if (m_url == newUrl)
|
||||||
|
return;
|
||||||
|
m_url = newUrl;
|
||||||
|
emit urlChanged();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ class ConfigInterface : public QObject
|
||||||
Q_PROPERTY(QString min READ min WRITE setMin NOTIFY minChanged FINAL)
|
Q_PROPERTY(QString min READ min WRITE setMin NOTIFY minChanged FINAL)
|
||||||
Q_PROPERTY(QString max READ max WRITE setMax NOTIFY maxChanged FINAL)
|
Q_PROPERTY(QString max READ max WRITE setMax NOTIFY maxChanged FINAL)
|
||||||
Q_PROPERTY(QString alert READ alert WRITE setAlert NOTIFY alertChanged FINAL)
|
Q_PROPERTY(QString alert READ alert WRITE setAlert NOTIFY alertChanged FINAL)
|
||||||
|
Q_PROPERTY(QString mode READ mode WRITE setMode NOTIFY modeChanged FINAL)
|
||||||
|
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged FINAL)
|
||||||
Q_PROPERTY(bool flipBits READ flipBits WRITE setFlipBits NOTIFY flipBitsChanged FINAL)
|
Q_PROPERTY(bool flipBits READ flipBits WRITE setFlipBits NOTIFY flipBitsChanged FINAL)
|
||||||
public:
|
public:
|
||||||
explicit ConfigInterface(QObject *parent = nullptr);
|
explicit ConfigInterface(QObject *parent = nullptr);
|
||||||
|
|
@ -32,21 +34,30 @@ public:
|
||||||
bool flipBits() const;
|
bool flipBits() const;
|
||||||
void setFlipBits(bool newFlipBits);
|
void setFlipBits(bool newFlipBits);
|
||||||
|
|
||||||
|
QString mode() const;
|
||||||
|
void setMode(const QString &newMode);
|
||||||
|
|
||||||
|
QString url() const;
|
||||||
|
void setUrl(const QString &newUrl);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void configData(QString max, QString min, QString alert, bool flipbits);
|
void configData(QString max, QString min, QString alert, bool flipbits, QString mode, QString url);
|
||||||
void alertChanged();
|
void alertChanged();
|
||||||
void maxChanged();
|
void maxChanged();
|
||||||
void minChanged();
|
void minChanged();
|
||||||
|
|
||||||
void flipBitsChanged();
|
void flipBitsChanged();
|
||||||
|
void modeChanged();
|
||||||
|
void urlChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void saveConfig(QString max, QString min, QString alert, bool flipbits);
|
void saveConfig(QString max, QString min, QString alert, bool flipbits, QString mode, QString url);
|
||||||
private:
|
private:
|
||||||
QString m_alert;
|
QString m_alert;
|
||||||
QString m_max;
|
QString m_max;
|
||||||
QString m_min;
|
QString m_min;
|
||||||
bool m_flipBits;
|
bool m_flipBits;
|
||||||
|
QString m_mode;
|
||||||
|
QString m_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONFIGINTERFACE_H
|
#endif // CONFIGINTERFACE_H
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ UDPListener::UDPListener(QObject *parent)
|
||||||
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);
|
||||||
|
connect(this, &UDPListener::changeWorkerMode, worker, &Worker::changeMode);
|
||||||
thread->start();
|
thread->start();
|
||||||
emit startWorker();
|
emit startWorker();
|
||||||
timer = new QTimer(this);
|
timer = new QTimer(this);
|
||||||
|
|
@ -54,16 +55,18 @@ void UDPListener::setFlipBits(bool flip_bits)
|
||||||
m_flip_bits = flip_bits;
|
m_flip_bits = flip_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDPListener::setConfig(float distance, bool flip_bits)
|
void UDPListener::setConfig(float distance, bool flip_bits, QString mode, QString url)
|
||||||
{
|
{
|
||||||
setFlipBits(flip_bits);
|
setFlipBits(flip_bits);
|
||||||
if(!command_socket) {
|
if(!command_socket) {
|
||||||
command_socket = new QUdpSocket(this);
|
command_socket = new QUdpSocket(this);
|
||||||
bool bind = command_socket->bind(8181);
|
bool bind = command_socket->bind(8181);
|
||||||
if(bind) {
|
if(bind) {
|
||||||
QNetworkDatagram data1, data2;
|
QNetworkDatagram data1, data2, data3, data4;
|
||||||
data1.setDestination(QHostAddress::LocalHost, 8178);
|
data1.setDestination(QHostAddress::LocalHost, 8178);
|
||||||
data2.setDestination(QHostAddress::LocalHost, 8178);
|
data2.setDestination(QHostAddress::LocalHost, 8178);
|
||||||
|
data3.setDestination(QHostAddress::LocalHost, 8178);
|
||||||
|
data4.setDestination(QHostAddress::LocalHost, 8178);
|
||||||
|
|
||||||
QString s_data = "<SET NAME=ALERT VALUE=" + QString::number(distance) + ">";
|
QString s_data = "<SET NAME=ALERT VALUE=" + QString::number(distance) + ">";
|
||||||
while(s_data.toUtf8().size() != 1024) {
|
while(s_data.toUtf8().size() != 1024) {
|
||||||
|
|
@ -72,6 +75,7 @@ void UDPListener::setConfig(float distance, bool flip_bits)
|
||||||
data1.setData(s_data.toUtf8());
|
data1.setData(s_data.toUtf8());
|
||||||
command_socket->writeDatagram(data1);
|
command_socket->writeDatagram(data1);
|
||||||
command_socket->flush();
|
command_socket->flush();
|
||||||
|
|
||||||
QString b_data = "<SET NAME=BITS_FLIPPED VALUE=" + QString((flip_bits ? "TRUE" : "FALSE")) + ">";
|
QString b_data = "<SET NAME=BITS_FLIPPED VALUE=" + QString((flip_bits ? "TRUE" : "FALSE")) + ">";
|
||||||
while(b_data.toUtf8().size() != 1024) {
|
while(b_data.toUtf8().size() != 1024) {
|
||||||
b_data += "=";
|
b_data += "=";
|
||||||
|
|
@ -79,9 +83,28 @@ void UDPListener::setConfig(float distance, bool flip_bits)
|
||||||
data2.setData(b_data.toUtf8());
|
data2.setData(b_data.toUtf8());
|
||||||
command_socket->writeDatagram(data2);
|
command_socket->writeDatagram(data2);
|
||||||
command_socket->flush();
|
command_socket->flush();
|
||||||
|
|
||||||
|
QString m_data = "<SET NAME=MODE VALUE=" + mode + ">";
|
||||||
|
while(m_data.toUtf8().size() != 1024) {
|
||||||
|
m_data += "=";
|
||||||
|
}
|
||||||
|
data3.setData(m_data.toUtf8());
|
||||||
|
command_socket->writeDatagram(data3);
|
||||||
|
command_socket->flush();
|
||||||
|
|
||||||
|
QString u_data = "<SET NAME=URL VALUE=" + url + ">";
|
||||||
|
while(u_data.toUtf8().size() != 1024) {
|
||||||
|
u_data += "=";
|
||||||
|
}
|
||||||
|
data4.setData(u_data.toUtf8());
|
||||||
|
command_socket->writeDatagram(data4);
|
||||||
|
command_socket->flush();
|
||||||
|
|
||||||
command_socket->close();
|
command_socket->close();
|
||||||
command_socket->deleteLater();
|
command_socket->deleteLater();
|
||||||
command_socket = nullptr;
|
command_socket = nullptr;
|
||||||
|
|
||||||
|
emit changeWorkerMode(mode, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
averages.clear();
|
averages.clear();
|
||||||
|
|
@ -179,10 +202,45 @@ Worker::Worker(QObject *parent)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worker::gotHttpReply(QNetworkReply *rep)
|
||||||
|
{
|
||||||
|
QByteArray m_data = rep->readAll();
|
||||||
|
rep->deleteLater();
|
||||||
|
QJsonObject top = QJsonDocument::fromJson(m_data).object();
|
||||||
|
float distance = top["water_level"].toArray()[0].toDouble();
|
||||||
|
QByteArray data, data2;
|
||||||
|
data = QByteArray::fromRawData((char *)&distance, sizeof(float));
|
||||||
|
char *buff = new char[4];
|
||||||
|
char *reader = (char *) &distance;
|
||||||
|
for(int i=0;i< sizeof(float) ;i++) {
|
||||||
|
buff[i] = reader[sizeof(float) - 1 - i];
|
||||||
|
}
|
||||||
|
data2 = QByteArray::fromRawData(buff, sizeof(float));
|
||||||
|
emit datagramReceived(data, data2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Worker::httpTimerTimeout()
|
||||||
|
{
|
||||||
|
QNetworkRequest req;
|
||||||
|
req.setUrl(QUrl("https://unrealdragon.in/server/waterlevel"));
|
||||||
|
disconnect(manager, nullptr, nullptr, nullptr);
|
||||||
|
connect(manager, &QNetworkAccessManager::finished, this, &Worker::gotHttpReply);
|
||||||
|
manager->get(req);
|
||||||
|
}
|
||||||
|
|
||||||
void Worker::stop()
|
void Worker::stop()
|
||||||
{
|
{
|
||||||
disconnect(socket, nullptr, nullptr, nullptr);
|
disconnect(socket, nullptr, nullptr, nullptr);
|
||||||
delete socket;
|
delete socket;
|
||||||
|
if(httpTimer) {
|
||||||
|
disconnect(httpTimer, nullptr, nullptr, nullptr);
|
||||||
|
delete httpTimer;
|
||||||
|
}
|
||||||
|
if(manager) {
|
||||||
|
disconnect(manager, nullptr, nullptr, nullptr);
|
||||||
|
delete manager;
|
||||||
|
}
|
||||||
emit stopped();
|
emit stopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,9 +248,13 @@ void Worker::run()
|
||||||
{
|
{
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
socket = new QUdpSocket(this);
|
socket = new QUdpSocket(this);
|
||||||
|
httpTimer = new QTimer(this);
|
||||||
|
manager = new QNetworkAccessManager(this);
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
|
// If it is android use it as a command socket;
|
||||||
bool bind = socket->bind(QHostAddress::Any, 8180);
|
bool bind = socket->bind(QHostAddress::Any, 8180);
|
||||||
#else
|
#else
|
||||||
|
// 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);
|
||||||
#endif
|
#endif
|
||||||
if(!bind)
|
if(!bind)
|
||||||
|
|
@ -200,13 +262,30 @@ void Worker::run()
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
connect(httpTimer, &QTimer::timeout, this, &Worker::httpTimerTimeout);
|
||||||
connect(socket, &QUdpSocket::readyRead, this, &Worker::socketDataReceived);
|
connect(socket, &QUdpSocket::readyRead, this, &Worker::socketDataReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Worker::changeMode(QString mode, QString url)
|
||||||
|
{
|
||||||
|
qDebug() << "Worker changing mode: " << mode << url;
|
||||||
|
this->mode = mode;
|
||||||
|
this->url = url;
|
||||||
|
if(mode == "http") {
|
||||||
|
httpTimer->setInterval(2000);
|
||||||
|
httpTimer->setSingleShot(false);
|
||||||
|
httpTimer->start();
|
||||||
|
}
|
||||||
|
else if(mode == "udp") {
|
||||||
|
httpTimer->stop();
|
||||||
|
socketDataReceived();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Worker::socketDataReceived()
|
void Worker::socketDataReceived()
|
||||||
{
|
{
|
||||||
if(socket->hasPendingDatagrams()) {
|
if(socket->hasPendingDatagrams()) {
|
||||||
|
if(mode == "udp") {
|
||||||
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);
|
||||||
|
|
@ -220,4 +299,8 @@ void Worker::socketDataReceived()
|
||||||
qDebug() << "Distance received: " << correct_order;
|
qDebug() << "Distance received: " << correct_order;
|
||||||
emit datagramReceived(data, data2);
|
emit datagramReceived(data, data2);
|
||||||
}
|
}
|
||||||
|
else if(mode == "http") {
|
||||||
|
qDebug() << "Socket data received in http mode ignoring it.";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,21 @@
|
||||||
#include <QQmlEngine>
|
#include <QQmlEngine>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonObject>
|
||||||
#include "moving_container.h"
|
#include "moving_container.h"
|
||||||
|
|
||||||
class Worker: public QObject {
|
class Worker: public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QUdpSocket *socket = nullptr;
|
QUdpSocket *socket = nullptr;
|
||||||
|
QString mode = "";
|
||||||
|
QString url = "";
|
||||||
|
QNetworkAccessManager *manager = nullptr;
|
||||||
|
QTimer *httpTimer = nullptr;
|
||||||
public:
|
public:
|
||||||
explicit Worker(QObject *parent = nullptr);
|
explicit Worker(QObject *parent = nullptr);
|
||||||
signals:
|
signals:
|
||||||
|
|
@ -20,8 +30,11 @@ signals:
|
||||||
void socketError(QString error);
|
void socketError(QString error);
|
||||||
void datagramReceived(QByteArray data, QByteArray data2);
|
void datagramReceived(QByteArray data, QByteArray data2);
|
||||||
public slots:
|
public slots:
|
||||||
|
void gotHttpReply(QNetworkReply *rep);
|
||||||
|
void httpTimerTimeout();
|
||||||
void stop();
|
void stop();
|
||||||
void run();
|
void run();
|
||||||
|
void changeMode(QString mode, QString url);
|
||||||
private slots:
|
private slots:
|
||||||
void socketDataReceived();
|
void socketDataReceived();
|
||||||
};
|
};
|
||||||
|
|
@ -44,11 +57,12 @@ signals:
|
||||||
void connected();
|
void connected();
|
||||||
void disconnected();
|
void disconnected();
|
||||||
void distanceReceived(double dist, QString timestamp);
|
void distanceReceived(double dist, QString timestamp);
|
||||||
|
void changeWorkerMode(QString mode, QString url);
|
||||||
public slots:
|
public slots:
|
||||||
void continueDestruction();
|
void continueDestruction();
|
||||||
void resetAverages();
|
void resetAverages();
|
||||||
void setFlipBits(bool flip_bits);
|
void setFlipBits(bool flip_bits);
|
||||||
void setConfig(float distance, bool flip_bits);
|
void setConfig(float distance, bool flip_bits, QString mode, QString url);
|
||||||
void socketError(QString err);
|
void socketError(QString err);
|
||||||
void startService();
|
void startService();
|
||||||
void datagramRecieved(QByteArray data, QByteArray data2);
|
void datagramRecieved(QByteArray data, QByteArray data2);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue