24 Commits

Author SHA1 Message Date
235cf5f613 change 9patch and attempt to find way to package icons. 2019-11-18 00:51:35 -05:00
e1581cd424 add some build files and small changes to get android to build. Doesn't seems to show any bluetooth devices. 2019-11-18 00:17:42 -05:00
5479b04190 remove old patch 2019-11-18 00:13:05 -05:00
e247a486e1 update build commit 2019-11-15 12:46:54 -05:00
23fdbd27b6 Update screenshots. 2019-11-15 12:45:34 -05:00
bdebc0833e fix using wrong translation function and bump version. 2019-11-15 12:40:59 -05:00
0ec59fc409 update wording to specify plants. 2019-11-14 11:08:10 -05:00
ad1fdee6c4 update images with latest changes 2019-11-14 11:06:18 -05:00
c9720c9dea update commit 2019-11-14 10:56:25 -05:00
16db502a04 updated version 2019-11-14 10:55:31 -05:00
003a484fc4 Added units of graphs and rounded temperature. 2019-11-14 10:53:42 -05:00
f0d203c6d6 make sure next build is a release build. 2019-11-13 22:26:15 -05:00
9e7bf90831 another flathub build update. 2019-11-13 22:16:44 -05:00
93a71a56e1 Flip order of releases as they are in reverse order of what I expected. 2019-11-13 22:14:56 -05:00
0df4b858d0 Point to new commit for release. 2019-11-13 22:02:42 -05:00
9bad2c73ff Remove uris, since flathub doesn't like them. 2019-11-13 22:00:23 -05:00
60e5c8b0df Update build script with new tag. 2019-11-13 21:47:56 -05:00
90da697f84 Update packaging and use KF5 for about screen. Implement basic notifications for error messages. Use icon for app icon. 2019-11-13 21:43:58 -05:00
9c5c50ef95 Move extra files to packaging. 2019-11-13 16:27:28 -05:00
e8d666d922 Clean up some old test code and make sure graphs have right paramaters to be viewed. 2019-11-13 16:23:51 -05:00
1303626dd8 replace flatpak config with published one. Only builds from git now.
Made large progress on getting history from device.
2019-11-12 23:14:40 -05:00
ed00901a2f Add themed chart layout to gui. Needs backend code. 2019-11-11 15:00:07 -05:00
f6f574875d remove unneeded tag 2019-11-11 11:13:20 -05:00
b35385b306 Quickly add Fahrenheit to temp screen. 2019-11-08 16:05:40 -05:00
25 changed files with 734 additions and 320 deletions

View File

@@ -1,8 +1,8 @@
project(qiflora) project(qiflora)
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8.12)
set(KF5_MIN_VERSION "5.18.0") set(KF5_MIN_VERSION "5.44.0")
set(QT_MIN_VERSION "5.5.0") set(QT_MIN_VERSION "5.12.0")
################# Disallow in-source build ################# ################# Disallow in-source build #################
@@ -28,8 +28,9 @@ include(KDECompilerSettings NO_POLICY_SCOPE)
################# Find dependencies ################# ################# Find dependencies #################
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg QuickControls2 Bluetooth) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Core Quick Test Gui Svg QuickControls2 Bluetooth Charts)
find_package(KF5Kirigami2 ${KF5_MIN_VERSION}) find_package(KF5Kirigami2 ${KF5_MIN_VERSION} REQUIRED)
find_package(KF5CoreAddons ${KF5_MIN_VERSION} REQUIRED)
################# Enable C++11 features for clang and gcc ################# ################# Enable C++11 features for clang and gcc #################
@@ -38,8 +39,8 @@ set(CMAKE_CXX_STANDARD 11)
################# build and install ################# ################# build and install #################
add_subdirectory(src) add_subdirectory(src)
install(PROGRAMS org.eyecreate.qiflora.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(PROGRAMS packaging/org.eyecreate.qiflora.desktop DESTINATION ${KDE_INSTALL_APPDIR})
install(FILES org.eyecreate.qiflora.svg DESTINATION ${KDE_INSTALL_ICONDIR}) install(FILES packaging/org.eyecreate.qiflora.svg DESTINATION ${KDE_INSTALL_ICONDIR})
install(FILES org.eyecreate.qiflora.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) install(FILES packaging/org.eyecreate.qiflora.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<component type="desktop-application">
<id>org.eyecreate.qiflora</id>
<name>QiFlora</name>
<summary>Mobile friendly application to monitor Mi Flora devices.</summary>
<metadata_license>FSFAP</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<content_rating type="oars-1.1" />
<url type="homepage">https://git.eyecreate.org/eyecreate/qiflora</url>
<developer_name>eyecreate</developer_name>
<description>
<p>Mobile friendly application to monitor Mi Flora devices.</p>
<p>Plants using this device will have thier data logged when app is used and graphed to better monitor plant health.</p>
</description>
<screenshots>
<screenshot type="default">
<image type="source">https://git.eyecreate.org/eyecreate/qiflora/raw/v1.0/packaging/main_window.png</image>
</screenshot>
</screenshots>
<releases>
<release version="1.0" date="2019-11-8" type="stable"/>
</releases>
</component>

View File

@@ -1,120 +0,0 @@
{
"id": "org.eyecreate.qiflora",
"runtime": "org.kde.Platform",
"runtime-version": "5.12",
"sdk": "org.kde.Sdk",
"command": "qiflora",
"tags": ["kde"],
"finish-args": [
"--share=ipc",
"--allow=bluetooth",
"--system-talk-name=org.bluez",
"--share=network",
"--socket=x11",
"--socket=wayland",
"--device=dri",
"--filesystem=home",
"--talk-name=org.freedesktop.Notifications"
],
"separate-locales": false,
"modules": [
{
"name": "udev",
"rm-configure": true,
"config-opts": [
"--disable-hwdb",
"--disable-logging",
"--disable-introspection",
"--disable-keymap",
"--disable-mtd_probe",
"--with-systemdsystemunitdir=/app/lib/systemd/"
],
"cleanup": [
"/include",
"/etc",
"/libexec",
"/sbin",
"/lib/pkgconfig",
"/lib/systemd",
"/man",
"/share/aclocal",
"/share/doc",
"/share/gtk-doc",
"/share/man",
"/share/pkgconfig",
"*.la",
"*.a"
],
"sources": [
{
"type": "archive",
"url": "https://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-175.tar.bz2",
"sha256": "4c7937fe5a1521316ea571188745b9a00a9fdf314228cffc53a7ba9e5968b7ab"
},
{
"type": "patch",
"path": "sysmacros.patch"
},
{
"type": "script",
"dest-filename": "autogen.sh",
"commands": [
"autoreconf -vfi"
]
}
],
"post-install": [
"sed -i 's|${exec_prefix}|/app|g' /app/share/pkgconfig/udev.pc"
]
},
{
"name": "ical",
"cleanup": [
"/lib/cmake"
],
"buildsystem": "cmake-ninja",
"config-opts": [
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
"-DCMAKE_INSTALL_LIBDIR=/app/lib",
"-DBUILD_SHARED_LIBS=ON"
],
"sources": [ { "type": "archive", "url": "https://github.com/libical/libical/archive/v3.0.5.tar.gz", "sha256": "483acbf7fee66ca071c2ff8183e46b6f2b3a89e1e866eadf4870eaaa281c8db1" } ]
},
{
"name": "bluez",
"config-opts": [
"--disable-datafiles",
"--disable-systemd",
"--enable-library",
"--prefix=/app",
"--sysconfdir=/app/etc"
],
"sources": [ { "type": "archive", "url": "https://mirrors.edge.kernel.org/pub/linux/bluetooth/bluez-5.50.tar.xz", "sha256": "5ffcaae18bbb6155f1591be8c24898dc12f062075a40b538b745bfd477481911"} ]
},
{
"name": "qtconnectivity",
"buildsystem": "simple",
"cleanup-platform": [
"/bin",
"/mkspecs"
],
"sources": [ { "type": "git", "url": "https://github.com/qt/qtconnectivity", "branch": "5.12.4", "commit": "f6be1f73a810514335ab3d27e1d05825a36b06af" } ],
"build-commands": [
"qmake",
"make -j $FLATPAK_BUILDER_N_JOBS",
"cp -r -n bin /app",
"cp -r -n include /app",
"cp -r -n lib /app",
"mkdir -p /app/src/bluetooth",
"cp -r src/bluetooth /app/src/"
]
},
{
"name": "qiflora",
"buildsystem": "cmake-ninja",
"builddir": true,
"sources": [ { "type": "dir", "path": ".", "skip": [".git"] } ]
}
]
}

View File

@@ -0,0 +1,63 @@
<?xml version='1.0' encoding='utf-8'?>
<manifest package="org.eyecreate.qiflora" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.3" android:versionCode="7" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="QiFlora" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.qtproject.qt5.android.bindings.QtActivity"
android:label="QiFlora"
android:theme="@style/AppTheme"
android:screenOrientation="unspecified"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="qiflora"/>
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
<meta-data android:name="android.app.repository" android:value="default"/>
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<!-- Messages maps -->
<!-- Splash screen -->
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
<meta-data android:name="android.app.background_running" android:value="false"/>
<!-- Background running -->
<!-- auto screen scale factor -->
<meta-data android:name="android.app.auto_screen_scale_factor" android:value="false"/>
<!-- auto screen scale factor -->
</activity>
</application>
<uses-sdk android:minSdkVersion="24" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_FEATURES -->
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle" >
<solid android:color="#FF1fca05"/>
</shape>
</item>
<item>
<bitmap android:src="@drawable/qiflora_splash"
android:gravity="center"/>
</item>
</layer-list>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
<item name="android:windowBackground">@drawable/qiflora_splash</item>
</style>
</resources>

View File

@@ -0,0 +1,4 @@
#!/bin/bash
#makes use of: kdeorg/android-arm-sdk
mkdir ../build-android
cmake -B build-android -DANDROID_EXTRA_LIBS="/opt/kdeandroid-deps/lib/libcrypto.so;/opt/kdeandroid-deps/lib/libssl.so" -DQTANDROID_EXPORTED_TARGET=qiflora -DANDROID_APK_DIR=./android -DCMAKE_TOOLCHAIN_FILE=/opt/kdeandroid-deps/share/ECM/toolchain/Android.cmake -DCMAKE_PREFIX_PATH="$QT_ANDROID;/opt/kdeandroid-deps" -DKF5Kirigami2_DIR=/opt/kdeandroid-deps/lib/cmake/KF5Kirigami2 -DKF5CoreAddons_DIR=/opt/kdeandroid-deps/lib/cmake/KF5CoreAddons -DECM_DIR=/opt/kdeandroid-deps/share/ECM/cmake -DECM_ADDITIONAL_FIND_ROOT_PATH=$QT_ANDROID ..

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 129 KiB

BIN
packaging/mobile_window.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<component type="desktop-application">
<id>org.eyecreate.qiflora</id>
<name>QiFlora</name>
<summary>Mobile friendly application to monitor plants using Mi Flora devices.</summary>
<metadata_license>FSFAP</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<content_rating type="oars-1.1" />
<url type="homepage">https://git.eyecreate.org/eyecreate/qiflora</url>
<url type="contact">https://www.eyecreate.org</url>
<developer_name>eyecreate</developer_name>
<description>
<p>Mobile friendly application to monitor Mi Flora devices.</p>
<p>Plants using this device will have thier data logged when app is used and graphed to better monitor plant health.</p>
</description>
<screenshots>
<screenshot type="default">
<image type="source">https://git.eyecreate.org/eyecreate/qiflora/raw/v1.1.2/packaging/main_window.png</image>
</screenshot>
<screenshot>
<image type="source">https://git.eyecreate.org/eyecreate/qiflora/raw/v1.1.2/packaging/mobile_window.png</image>
</screenshot>
</screenshots>
<releases>
<release version="1.1.2" date="2019-11-15" type="stable">
<description>
<p>Fixed code causing text to sometimes not appear.</p>
</description>
</release>
<release version="1.1.1" date="2019-11-14" type="stable">
<description>
<p>Cleaned up graph markings and temperature rounding.</p>
</description>
</release>
<release version="1.1" date="2019-11-13" type="stable">
<description>
<p>This release adds history graph for the last 48 hours.</p>
</description>
</release>
<release version="1.0" date="2019-11-8" type="stable"/>
</releases>
</component>

View File

@@ -1,7 +1,7 @@
[Desktop Entry] [Desktop Entry]
Name=QiFlora Name=QiFlora
Comment=Monitor plants with Mi Flora sensors. Comment=Monitor plants with Mi Flora sensors.
Version=1.0 Version=1.1.2
Exec=qiflora Exec=qiflora
MimeType=application/x-qiflora; MimeType=application/x-qiflora;
Icon=org.eyecreate.qiflora Icon=org.eyecreate.qiflora

View File

@@ -0,0 +1,99 @@
{
"id": "org.eyecreate.qiflora",
"runtime": "org.kde.Platform",
"command": "qiflora",
"finish-args": [
"--share=ipc",
"--allow=bluetooth",
"runtime-version": "5.13",
"sdk": "org.kde.Sdk",
"--system-talk-name=org.bluez",
"--share=network",
"--socket=x11",
"--socket=wayland",
"--device=dri",
"--filesystem=home",
"--talk-name=org.freedesktop.Notifications"
],
"separate-locales": false,
"modules": [
{
"name": "ical",
"cleanup": [
"/lib/cmake"
],
"buildsystem": "cmake-ninja",
"config-opts": [
"-DCMAKE_BUILD_TYPE=RelWithDebInfo",
"-DCMAKE_INSTALL_LIBDIR=/app/lib",
"-DBUILD_SHARED_LIBS=ON"
],
"sources": [
{
"type": "archive",
"url": "https://github.com/libical/libical/archive/v3.0.5.tar.gz",
"sha256": "483acbf7fee66ca071c2ff8183e46b6f2b3a89e1e866eadf4870eaaa281c8db1"
}
]
},
{
"name": "bluez",
"config-opts": [
"--disable-datafiles",
"--disable-systemd",
"--enable-library",
"--prefix=/app",
"--sysconfdir=/app/etc",
"--disable-udev"
],
"sources": [
{
"type": "archive",
"url": "https://mirrors.edge.kernel.org/pub/linux/bluetooth/bluez-5.52.tar.xz",
"sha256": "f7144ce2039202cfac18ccb52426efea11c98e4f6e1bb8041bcb994b8378560a"
}
]
},
{
"name": "qtconnectivity",
"buildsystem": "simple",
"cleanup-platform": [
"/bin",
"/mkspecs"
],
"sources": [
{
"type": "git",
"url": "https://github.com/qt/qtconnectivity",
"branch": "5.13.2",
"commit": "f6be1f73a810514335ab3d27e1d05825a36b06af"
}
],
"build-commands": [
"qmake",
"make -j $FLATPAK_BUILDER_N_JOBS",
"cp -r -n bin /app",
"cp -r -n include /app",
"cp -r -n lib /app",
"mkdir -p /app/src/bluetooth",
"cp -r src/bluetooth /app/src/"
]
},
{
"name": "qiflora",
"buildsystem": "cmake-ninja",
"builddir": true,
"config-opts": [
"-DCMAKE_BUILD_TYPE=Release"
]
"sources": [
{
"type": "git",
"url": "https://git.eyecreate.org/eyecreate/qiflora.git",
"tag": "v1.1.2",
"commit": "23fdbd27b63dc48085287dcad206786ebfadb9df"
}
]
}
]
}

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -2,10 +2,15 @@
set(qiflora_SRCS set(qiflora_SRCS
miflora/miflora.cpp miflora/miflora.cpp
miflora/bluetoothdevices.cpp miflora/bluetoothdevices.cpp
miflora/florahistory.cpp
main.cpp main.cpp
) )
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
kirigami_package_breeze_icons(ICONS view-refresh help-about filename-bpm-amarok colors-chromablue quickopen contrast window-close)
endif()
qt5_add_resources(RESOURCES resources.qrc) qt5_add_resources(RESOURCES resources.qrc)
add_executable(qiflora ${qiflora_SRCS} ${RESOURCES}) add_executable(qiflora ${qiflora_SRCS} ${RESOURCES})
target_link_libraries(qiflora Qt5::Core Qt5::Qml Qt5::Quick Qt5::Svg Qt5::Bluetooth) target_link_libraries(qiflora Qt5::Core Qt5::Qml Qt5::Quick Qt5::Svg Qt5::Bluetooth Qt5::Charts KF5::CoreAddons KF5::Kirigami2 Qt5::QuickControls2)
install(TARGETS qiflora ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(TARGETS qiflora ${KF5_INSTALL_TARGETS_DEFAULT_ARGS})

View File

@@ -1,8 +1,10 @@
import QtQuick 2.6 import QtQuick 2.6
import org.kde.kirigami 2.4 as Kirigami import org.kde.kirigami 2.6 as Kirigami
import QtQuick.Controls 2.0 as Controls import QtQuick.Controls 2.0 as Controls
import QtQuick.Layouts 1.12 as Layouts import QtQuick.Layouts 1.12 as Layouts
import org.eyecreate.qiflora 1.0 import QtQml.Models 2.2 //This only exists here to help build on android.
import QtCharts 2.3 as Charts
import org.eyecreate.qiflora 1.1
Kirigami.ApplicationWindow { Kirigami.ApplicationWindow {
id: root id: root
@@ -11,6 +13,7 @@ Kirigami.ApplicationWindow {
pageStack.initialPage: mainPageComponent pageStack.initialPage: mainPageComponent
contextDrawer: Kirigami.ContextDrawer {}
QiFlora { QiFlora {
id: qiflora id: qiflora
@@ -19,62 +22,179 @@ Kirigami.ApplicationWindow {
Component { Component {
id: mainPageComponent id: mainPageComponent
Kirigami.ScrollablePage { Kirigami.Page {
id: mainPage
mainAction: Kirigami.Action { mainAction: Kirigami.Action {
iconName: "view-refresh" iconName: "view-refresh"
text: i18n("Query Device") text: qsTr("Query Device")
onTriggered: { onTriggered: {
deviceSelect.open(); deviceSelect.open();
} }
} }
contextualActions: [
Kirigami.Action {
iconName: "help-about"
text: qsTr("About")
onTriggered: {
pageStack.replace(aboutPageComponent);
}
}
]
title: "Monitor" title: "Monitor"
leftPadding: 0
Component.onCompleted: { rightPadding: 0
monitorTypes.append({"chartType": "temperature", "title": i18n("Temperature"), "icon": "filename-bpm-amarok"});
monitorTypes.append({"chartType": "moisture", "title": i18n("Moisture"), "icon": "colors-chromablue"});
monitorTypes.append({"chartType": "conductivity", "title": i18n("Conductivity"), "icon": "quickopen"});
monitorTypes.append({"chartType": "brightness", "title": i18n("Brightness"), "icon": "contrast"});
}
Kirigami.CardsListView { Layouts.ColumnLayout {
id: monitorView anchors.fill: parent
model: ListModel { Kirigami.InlineMessage {
id: monitorTypes Layouts.Layout.fillWidth: true
Layouts.Layout.leftMargin: 10
Layouts.Layout.rightMargin: 10
z: 9997
type: Kirigami.MessageType.Error
id: errorMessage
showCloseButton: true
Connections {
target: qiflora
onErrorHappened: {
errorMessage.text = description;
errorMessage.visible = true;
}
}
} }
delegate: Kirigami.Card { Kirigami.CardsListView {
id: card Layouts.Layout.fillWidth: true
banner { Layouts.Layout.fillHeight: true
title: model.title id: monitorView
titleIcon: model.icon model: ListModel {
titleLevel: 2 id: monitorTypes
} ListElement{
header: Row { chartType: "temperature"
layoutDirection: Qt.RightToLeft title: "Temperature"
topPadding: 10.0 icon: "filename-bpm-amarok"
rightPadding: 10.0 lineColor: "red"
Layouts.ColumnLayout { units: "&deg;C"
Kirigami.Heading { yMin: -20
Layouts.Layout.alignment: Qt.AlignCenter yMax: 40
level: 4 modelCol: 1
text: i18n("Last Measured") }
} ListElement{
Kirigami.Heading { chartType: "moisture"
Layouts.Layout.alignment: Qt.AlignCenter title: "Moisture"
level: 3 icon: "colors-chromablue"
text: { lineColor: "cyan"
if(model.chartType == "temperature") qiflora.temperature + "°C" units: "%"
else if(model.chartType == "moisture") qiflora.moisture + "%" yMin: 0
else if(model.chartType == "conductivity") qiflora.conduction + " µS/cm" yMax: 75
else if(model.chartType == "brightness") qiflora.brightness + " lux" modelCol: 3
}
ListElement{
chartType: "conductivity"
title: "Conductivity"
icon: "quickopen"
lineColor: "gold"
units: "&#181;S/cm"
yMin: 0
yMax: 6000
modelCol: 4
}
ListElement{
chartType: "brightness"
title: "Brightness"
icon: "contrast"
lineColor: "orange"
units: "lux"
yMin: 0
yMax: 30000
modelCol: 2
}
}
delegate: Kirigami.Card {
id: card
banner {
title: qsTr(model.title)
titleIcon: model.icon
titleLevel: 2
}
header: Row {
layoutDirection: Qt.RightToLeft
topPadding: 10.0
rightPadding: 10.0
Layouts.ColumnLayout {
Kirigami.Heading {
Layouts.Layout.alignment: Qt.AlignCenter
level: 4
text: qsTr("Last Measured")
}
Kirigami.Heading {
Layouts.Layout.alignment: Qt.AlignCenter
level: 3
text: {
if(model.chartType == "temperature") Math.round(qiflora.temperature*10)/10 + "°C\n" + (Math.round((qiflora.temperature*1.8+32)*10)/10) + "°F"
else if(model.chartType == "moisture") qiflora.moisture + "%"
else if(model.chartType == "conductivity") qiflora.conduction + " µS/cm"
else if(model.chartType == "brightness") qiflora.brightness + " lux"
}
} }
} }
} }
} contentItem: Item {
contentItem: Controls.Label { implicitWidth: 300
wrapMode: Text.WordWrap implicitHeight: 200
text: i18n("") //TODO: replace with graph? Charts.ChartView {
id: chart
antialiasing: true
backgroundColor: Kirigami.Theme.buttonBackgroundColor
titleColor: Kirigami.Theme.textColor
legend.visible: false
anchors.fill: parent
Charts.LineSeries {
id: series
axisX: Charts.DateTimeAxis {
id: dateAx
labelsColor: Kirigami.Theme.textColor
format: "MMM d yyyy ha"
Component.onCompleted: {
//On load, change date span to last 24 to remove awkward 1969 empty dates.
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() -1);
dateAx.min = yesterday;
dateAx.max = new Date();
}
}
axisY: Charts.ValueAxis {
id: valueAx
labelFormat: "%d "+units
labelsColor: Kirigami.Theme.textColor
min: yMin
max: yMax
}
color: model.lineColor
name: model.title
Charts.VXYModelMapper {
model: qiflora.model
xColumn: 0
yColumn: modelCol
}
}
Connections {
target: qiflora.model
onRowsInserted: {
//Readjust graphs to show date range from earliest item.
dateAx.max = new Date();
dateAx.min = qiflora.model.data(qiflora.model.index(0,0));
}
}
}
} }
}
Controls.ScrollBar.vertical: Controls.ScrollBar {}
} }
} }
@@ -86,15 +206,13 @@ Kirigami.ApplicationWindow {
Rectangle { Rectangle {
height: 10 height: 10
color: "transparent" color: "transparent"
width: parent.width
} }
Kirigami.Heading { Kirigami.Heading {
text: i18n("Select Device to Query") text: qsTr("Select Device to Query")
} }
Rectangle { Rectangle {
height: 10 height: 10
color: "transparent" color: "transparent"
width: parent.width
} }
} }
id: deviceList id: deviceList
@@ -126,4 +244,20 @@ Kirigami.ApplicationWindow {
} }
} }
} }
Component {
id:aboutPageComponent
Kirigami.AboutPage {
id: aboutPage
actions.main: Kirigami.Action {
iconName: "window-close"
text: qsTr("Close")
onTriggered: {
pageStack.clear();
pageStack.push(mainPageComponent);
}
}
aboutData: appAboutData
}
}
} }

View File

@@ -4,18 +4,30 @@
#include <QUrl> #include <QUrl>
#include "miflora/miflora.h" #include "miflora/miflora.h"
#include "miflora/bluetoothdevices.h" #include "miflora/bluetoothdevices.h"
#include <KAboutData>
#include <QIcon>
Q_DECL_EXPORT int main(int argc, char *argv[]) Q_DECL_EXPORT int main(int argc, char *argv[])
{ {
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv); QApplication app(argc, argv);
KAboutData aboutData("org.eyecreate.qiflora", "QiFlora", "1.1.2", "Mobile friendly application to monitor Mi Flora devices.",KAboutLicense::GPL_V3);//TODO:i18n
aboutData.setProductName("qiflora");
aboutData.addAuthor("Kevin Whitaker",QString(),"eyecreate@eyecreate.org","https://www.eyecreate.org");
aboutData.setDesktopFileName("org.eyecreate.qiflora");
QCoreApplication::setOrganizationName("eyecreate"); QCoreApplication::setOrganizationName("eyecreate");
QCoreApplication::setOrganizationDomain("eyecreate.org"); QCoreApplication::setOrganizationDomain("eyecreate.org");
QCoreApplication::setApplicationName("qiflora"); QCoreApplication::setApplicationName(aboutData.productName());
QCoreApplication::setApplicationVersion(aboutData.version());
app.setWindowIcon(QIcon::fromTheme("org.eyecreate.qiflora"));
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
qmlRegisterType<BluetoothDevices>(); qmlRegisterType<BluetoothDevices>();
qmlRegisterType<MiFlora>("org.eyecreate.qiflora",1,0,"QiFlora"); qmlRegisterType<MiFlora>("org.eyecreate.qiflora",1,1,"QiFlora");
engine.rootContext()->setContextProperty(QStringLiteral("appAboutData"), QVariant::fromValue(aboutData));
engine.load(QUrl(QStringLiteral("qrc:///main.qml"))); engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
if (engine.rootObjects().isEmpty()) { if (engine.rootObjects().isEmpty()) {

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2019 Kevin Whitaker <eyecreate@eyecreate.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "florahistory.h"
#include <QDebug>
#include <cmath>
QVariant FloraHistory::data(const QModelIndex& index, int role) const
{
if(role == Qt::DisplayRole && tableData.size()-1 >= index.row()) {
if(index.column() == 0) {
return QVariant(tableData[index.row()].time);
} else if(index.column() == 1) {
return QVariant(std::round(tableData[index.row()].temperature*10)/10); //temp in C
} else if(index.column() == 2) {
return QVariant(tableData[index.row()].brightness);
} else if(index.column() == 3) {
return QVariant(tableData[index.row()].moisture);
} else if(index.column() == 4) {
return QVariant(tableData[index.row()].conductivity);
} else if(index.column() == 5) {
return QVariant((std::round((tableData[index.row()].temperature*1.8+32)*10)/10)); //temp in F
} else {
return QVariant();
}
} else {
return QVariant();
}
}
int FloraHistory::columnCount(const QModelIndex& parent) const
{
return 6;
}
int FloraHistory::rowCount(const QModelIndex& parent) const
{
return tableData.size();
}
void FloraHistory::addData(QDateTime time, float temperature, quint32 brightness, quint8 moisture, quint16 conductivity)
{
beginInsertRows(QModelIndex(),tableData.size(),tableData.size());
tableData.append(flora_data{time, temperature, brightness, moisture, conductivity});
endInsertRows();
}
void FloraHistory::clear()
{
tableData.clear();
emit layoutChanged();
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2019 Kevin Whitaker <eyecreate@eyecreate.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FLORAHISTORY_H
#define FLORAHISTORY_H
#include <qabstractitemmodel.h>
#include <QDateTime>
#include <QList>
/**
* Model class to hold history data from MiFlora device.
*/
class FloraHistory : public QAbstractTableModel
{
Q_OBJECT
public:
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
int columnCount(const QModelIndex& parent) const override;
int rowCount(const QModelIndex& parent) const override;
void clear();
void addData(QDateTime time, float temperature, quint32 brightness, quint8 moisture, quint16 conductivity);
private:
struct flora_data {
QDateTime time;
float temperature;
quint32 brightness;
quint8 moisture;
quint16 conductivity;
};
QList<flora_data> tableData;
};
#endif // FLORAHISTORY_H

View File

@@ -55,6 +55,11 @@ void MiFlora::updateDataFromDevice ( QString mac )
} }
} }
QAbstractTableModel * MiFlora::getModel()
{
return floraModel;
}
void MiFlora::foundDevice ( const QBluetoothDeviceInfo& device ) void MiFlora::foundDevice ( const QBluetoothDeviceInfo& device )
{ {
if(device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration && device.address().toString().startsWith("C4:7C")) { if(device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration && device.address().toString().startsWith("C4:7C")) {
@@ -72,20 +77,34 @@ QQmlListProperty<BluetoothDevices> MiFlora::getDeviceList()
void MiFlora::logControllerError ( QLowEnergyController::Error err ) void MiFlora::logControllerError ( QLowEnergyController::Error err )
{ {
qDebug() << "Error:" << err; qDebug() << "Error:" << err;
emit errorHappened(currentController->errorString());
} }
void MiFlora::logServiceError(QLowEnergyService::ServiceError err) void MiFlora::logServiceError(QLowEnergyService::ServiceError err)
{ {
qDebug() << "Service Error:" << err; qDebug() << "Service Error:" << err;
emit errorHappened("Possible Read/Write error!");
} }
void MiFlora::serviceStateChanges ( QLowEnergyService::ServiceState state ) void MiFlora::sensorServiceStateChanges ( QLowEnergyService::ServiceState state )
{ {
if(state == QLowEnergyService::ServiceState::ServiceDiscovered) { if(state == QLowEnergyService::ServiceState::ServiceDiscovered) {
for(QLowEnergyCharacteristic chrt : sensorService->characteristics()) { for(QLowEnergyCharacteristic chrt : sensorService->characteristics()) {
if(chrt.uuid().toUInt16() == magicChar) { if(chrt.uuid().toUInt16() == magicChar) {
sensorService->writeCharacteristic(chrt, QByteArray::fromHex("a01f")); sensorService->writeCharacteristic(chrt, magicBytes);
}
}
}
}
void MiFlora::historyServiceStateChanges ( QLowEnergyService::ServiceState state )
{
if(state == QLowEnergyService::ServiceState::ServiceDiscovered) {
for(QLowEnergyCharacteristic chrt : historyService->characteristics()) {
if(chrt.uuid().toUInt16() == historyTimeChar) {
qDebug() << "Asking for device's view on time.";
historyService->readCharacteristic(chrt);
} }
} }
} }
@@ -134,15 +153,135 @@ void MiFlora::serviceCharRead(QLowEnergyCharacteristic readChar, QByteArray valu
} }
} }
QLowEnergyCharacteristic MiFlora::getCharFromValue(QLowEnergyService *service, quint16 characteristic)
{
for(QLowEnergyCharacteristic chrt : service->characteristics()) {
if(chrt.uuid().toUInt16() == characteristic) {
return chrt;
}
}
return QLowEnergyCharacteristic();
}
void MiFlora::historyServiceCharRead(QLowEnergyCharacteristic readChar, QByteArray value)
{
if(readChar.uuid().toUInt16() == historyReaderChar) {
QDataStream parser(value);
parser.setByteOrder(QDataStream::LittleEndian);
quint16 size;
parser >> size;
//change connect signals/slots to perform history read task.
disconnect(historyService, &QLowEnergyService::characteristicRead, this, &MiFlora::historyServiceCharRead);
connect(historyService, &QLowEnergyService::characteristicRead, this, &MiFlora::historyServiceCharReadData);
disconnect(historyService, &QLowEnergyService::characteristicWritten, this, &MiFlora::historyServiceCharWritten);
connect(historyService, &QLowEnergyService::characteristicWritten, this, &MiFlora::historyServiceCharWrittenData);
//Take size given and start by giving the last 48 numbers(if that many) to represent the last day of data. TODO: look to have amount of time be configurable.
lastHistoryEntry = 0;
if(size > 48) {
currentHistoryEntry = 48;
} else {
currentHistoryEntry = size;
}
floraModel->clear();
//Ask for first history value
QByteArray historyIndex(QByteArray::fromHex("a1"));
QDataStream historyParser(&historyIndex, QIODevice::ReadWrite);
historyParser.setByteOrder(QDataStream::LittleEndian);
historyParser.skipRawData(1);
historyParser << currentHistoryEntry;
historyService->writeCharacteristic(getCharFromValue(historyService, historyControllerChar), historyIndex);
} else if(readChar.uuid().toUInt16() == historyTimeChar) {
//Determine when device started counting by comparing system and device time.
quint32 time;
QDataStream parser(value);
parser.setByteOrder(QDataStream::LittleEndian);
parser >> time;
qint64 systemTime = QDateTime::currentSecsSinceEpoch();
deviceStartTime = systemTime - time;
//Now we start the history reading process.
qDebug() << "Writing history init.";
historyService->writeCharacteristic(getCharFromValue(historyService, historyControllerChar), historyReadInit);
}
}
void MiFlora::historyServiceCharReadData(QLowEnergyCharacteristic readChar, QByteArray value)
{
//We are in a read loop. Read data and determine if we should stop asking for history.
if(value == QByteArray::fromHex("ffffffffffffffffffffffffffffffff") || value == QByteArray::fromHex("00000000000000000000000000000000") || value == QByteArray::fromHex("aabbccddeeff99887766554433221110")) {
qDebug() << "invalid history response:" << value;
} else {
quint16 origTemp;
quint32 time;
quint32 bright;
quint8 moisture;
quint16 conduct;
float temp;
QDataStream parser(value);
parser.setByteOrder(QDataStream::LittleEndian);
parser >> time;
parser >> origTemp;
temp = origTemp/ 10.0; //original value in 0.1 C
parser.skipRawData(1);
parser >> bright;
parser >> moisture;
parser >> conduct;
QDateTime convTime;
convTime.setSecsSinceEpoch(deviceStartTime+time);
//Write out items to table
floraModel->addData(convTime, temp, bright, moisture, conduct);
}
if(lastHistoryEntry == currentHistoryEntry) {
disconnect(historyService, &QLowEnergyService::characteristicRead, this, &MiFlora::historyServiceCharReadData);
connect(historyService, &QLowEnergyService::characteristicRead, this, &MiFlora::historyServiceCharRead);
disconnect(historyService, &QLowEnergyService::characteristicWritten, this, &MiFlora::historyServiceCharWrittenData);
connect(historyService, &QLowEnergyService::characteristicWritten, this, &MiFlora::historyServiceCharWritten);
} else {
//Get next history entry
currentHistoryEntry -= 1;
QByteArray historyIndex(QByteArray::fromHex("a1"));
QDataStream parser(&historyIndex, QIODevice::ReadWrite);
parser.setByteOrder(QDataStream::LittleEndian);
parser.skipRawData(1);
parser << currentHistoryEntry;
historyService->writeCharacteristic(getCharFromValue(historyService, historyControllerChar), historyIndex);
}
}
void MiFlora::historyServiceCharWrittenData(QLowEnergyCharacteristic changedChar, QByteArray value)
{
//We are in a read loop. Ask to read from history what should have just been requested by a write.
historyService->readCharacteristic(getCharFromValue(historyService, historyReaderChar));
}
void MiFlora::historyServiceCharWritten(QLowEnergyCharacteristic changedChar, QByteArray value)
{
if(changedChar.uuid().toUInt16() == historyControllerChar) {
for(QLowEnergyCharacteristic chrt : historyService->characteristics()) {
if(chrt.uuid().toUInt16() == historyReaderChar) {
historyService->readCharacteristic(chrt);
}
}
}
}
void MiFlora::serviceDiscovered ( const QBluetoothUuid& gatt ) void MiFlora::serviceDiscovered ( const QBluetoothUuid& gatt )
{ {
if(gatt == QBluetoothUuid(dataService)) { if(gatt == QBluetoothUuid(dataServiceChar)) {
sensorService = currentController->createServiceObject(gatt); sensorService = currentController->createServiceObject(gatt);
connect(sensorService, &QLowEnergyService::stateChanged, this, &MiFlora::serviceStateChanges); connect(sensorService, &QLowEnergyService::stateChanged, this, &MiFlora::sensorServiceStateChanges);
connect(sensorService, static_cast<void (QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), this, &MiFlora::logServiceError); connect(sensorService, static_cast<void (QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), this, &MiFlora::logServiceError);
connect(sensorService, &QLowEnergyService::characteristicWritten, this, &MiFlora::serviceCharWritten); connect(sensorService, &QLowEnergyService::characteristicWritten, this, &MiFlora::serviceCharWritten);
connect(sensorService, &QLowEnergyService::characteristicRead, this, &MiFlora::serviceCharRead); connect(sensorService, &QLowEnergyService::characteristicRead, this, &MiFlora::serviceCharRead);
sensorService->discoverDetails(); sensorService->discoverDetails();
} else if(gatt == QBluetoothUuid(historyServiceChar)) {
historyService = currentController->createServiceObject(gatt);
connect(historyService, &QLowEnergyService::stateChanged, this, &MiFlora::historyServiceStateChanges);
connect(historyService, static_cast<void (QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), this, &MiFlora::logServiceError);
connect(historyService, &QLowEnergyService::characteristicWritten, this, &MiFlora::historyServiceCharWritten);
connect(historyService, &QLowEnergyService::characteristicRead, this, &MiFlora::historyServiceCharRead);
historyService->discoverDetails();
} }
} }

View File

@@ -26,6 +26,10 @@
#include <QtBluetooth/QLowEnergyCharacteristic> #include <QtBluetooth/QLowEnergyCharacteristic>
#include "bluetoothdevices.h" #include "bluetoothdevices.h"
#include <QQmlListProperty> #include <QQmlListProperty>
#include <QAbstractItemModel>
#include <QDateTime>
#include "florahistory.h"
#include <QXYSeries>
/** /**
* Class using QtBluetooth to find and retrive info from Mi Flora devices. * Class using QtBluetooth to find and retrive info from Mi Flora devices.
@@ -39,17 +43,21 @@ class MiFlora : public QObject
Q_PROPERTY(quint16 conduction NOTIFY conductionChanged MEMBER conduct) Q_PROPERTY(quint16 conduction NOTIFY conductionChanged MEMBER conduct)
Q_PROPERTY(quint8 battery NOTIFY batteryChanged MEMBER battery) Q_PROPERTY(quint8 battery NOTIFY batteryChanged MEMBER battery)
Q_PROPERTY(QQmlListProperty<BluetoothDevices> devices READ getDeviceList NOTIFY newDeviceFound) Q_PROPERTY(QQmlListProperty<BluetoothDevices> devices READ getDeviceList NOTIFY newDeviceFound)
Q_PROPERTY(QAbstractTableModel* model READ getModel NOTIFY modelUpdated)
public: public:
Q_INVOKABLE void startSearch(); Q_INVOKABLE void startSearch();
Q_INVOKABLE void stopSearch(); Q_INVOKABLE void stopSearch();
Q_INVOKABLE void updateDataFromDevice(QString mac); Q_INVOKABLE void updateDataFromDevice(QString mac);
QQmlListProperty<BluetoothDevices> getDeviceList(); QQmlListProperty<BluetoothDevices> getDeviceList();
//TODO:History? QAbstractTableModel* getModel();
signals: signals:
void newDeviceFound(); void newDeviceFound();
void modelUpdated();
void errorHappened(QString description);
void temperatureChanged(float temperature); void temperatureChanged(float temperature);
void brightnessChanged(quint32 brightness); void brightnessChanged(quint32 brightness);
void moistureChanged(quint8 moisture); void moistureChanged(quint8 moisture);
@@ -61,19 +69,33 @@ private:
void serviceDiscovered(const QBluetoothUuid &gatt); void serviceDiscovered(const QBluetoothUuid &gatt);
void logControllerError(QLowEnergyController::Error err); void logControllerError(QLowEnergyController::Error err);
void logServiceError(QLowEnergyService::ServiceError err); void logServiceError(QLowEnergyService::ServiceError err);
void serviceStateChanges(QLowEnergyService::ServiceState state); void sensorServiceStateChanges(QLowEnergyService::ServiceState state);
void historyServiceStateChanges(QLowEnergyService::ServiceState state);
void serviceCharWritten(QLowEnergyCharacteristic changedChar, QByteArray value); void serviceCharWritten(QLowEnergyCharacteristic changedChar, QByteArray value);
void serviceCharRead(QLowEnergyCharacteristic readChar, QByteArray value); void serviceCharRead(QLowEnergyCharacteristic readChar, QByteArray value);
void historyServiceCharWritten(QLowEnergyCharacteristic changedChar, QByteArray value);
void historyServiceCharWrittenData(QLowEnergyCharacteristic changedChar, QByteArray value);
void historyServiceCharRead(QLowEnergyCharacteristic readChar, QByteArray value);
void historyServiceCharReadData(QLowEnergyCharacteristic readChar, QByteArray value);
QLowEnergyCharacteristic getCharFromValue(QLowEnergyService *service, quint16 characteristic);
QBluetoothDeviceDiscoveryAgent *agent; QBluetoothDeviceDiscoveryAgent *agent;
QList<BluetoothDevices*> devices; QList<BluetoothDevices*> devices;
QLowEnergyController *currentController; QLowEnergyController *currentController;
QLowEnergyService *sensorService; QLowEnergyService *sensorService;
QLowEnergyService *historyService;
const quint16 dataService = 4612; //0x1204 const quint16 dataServiceChar = 4612; //0x1204
const quint16 historyServiceChar = 4614; //0x1206
const quint16 batteryFirmwareChar = 6658;//0x1a02 const quint16 batteryFirmwareChar = 6658;//0x1a02
const quint16 sensorsChar = 6657; //0x1a01 const quint16 sensorsChar = 6657; //0x1a01
const quint16 magicChar = 6656; //0x1a00 const quint16 magicChar = 6656; //0x1a00
const quint16 historyControllerChar = 6672; //0x1a10
const quint16 historyReaderChar = 6673; //0x1a11
const quint16 historyTimeChar = 6674; //0x1a12
const QByteArray magicBytes = QByteArray::fromHex("a01f");
const QByteArray historyReadInit = QByteArray::fromHex("a00000");
float temp = 0.0; float temp = 0.0;
quint32 bright = 0; quint32 bright = 0;
@@ -81,6 +103,11 @@ private:
quint16 conduct = 0; quint16 conduct = 0;
quint8 battery = 0; quint8 battery = 0;
QString version; QString version;
qint64 deviceStartTime;
qint16 currentHistoryEntry;
qint16 lastHistoryEntry;
FloraHistory *floraModel = new FloraHistory();
}; };

View File

@@ -1,112 +0,0 @@
diff -Naur udev-175/extras/cdrom_id/cdrom_id.c udev-175-fix/extras/cdrom_id/cdrom_id.c
--- udev-175/extras/cdrom_id/cdrom_id.c 2011-06-17 03:28:33.251601571 +0200
+++ udev-175-fix/extras/cdrom_id/cdrom_id.c 2019-04-02 12:24:40.131653700 +0200
@@ -37,6 +37,7 @@
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
+#include <sys/sysmacros.h>
#include "libudev.h"
#include "libudev-private.h"
diff -Naur udev-175/extras/scsi_id/scsi_serial.c udev-175-fix/extras/scsi_id/scsi_serial.c
--- udev-175/extras/scsi_id/scsi_serial.c 2011-04-15 00:14:23.739780499 +0200
+++ udev-175-fix/extras/scsi_id/scsi_serial.c 2019-04-02 12:24:18.781548109 +0200
@@ -33,6 +33,7 @@
#include <scsi/sg.h>
#include <linux/types.h>
#include <linux/bsg.h>
+#include <sys/sysmacros.h>
#include "libudev.h"
#include "libudev-private.h"
diff -Naur udev-175/libudev/libudev-device.c udev-175-fix/libudev/libudev-device.c
--- udev-175/libudev/libudev-device.c 2011-09-23 14:43:44.305381687 +0200
+++ udev-175-fix/libudev/libudev-device.c 2019-04-02 12:19:17.220061349 +0200
@@ -24,6 +24,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/sockios.h>
+#include <sys/sysmacros.h>
#include "libudev.h"
#include "libudev-private.h"
diff -Naur udev-175/libudev/libudev-device-private.c udev-175-fix/libudev/libudev-device-private.c
--- udev-175/libudev/libudev-device-private.c 2011-04-24 00:13:02.466797877 +0200
+++ udev-175-fix/libudev/libudev-device-private.c 2019-04-02 12:19:38.570166315 +0200
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include "libudev.h"
#include "libudev-private.h"
diff -Naur udev-175/libudev/libudev-enumerate.c udev-175-fix/libudev/libudev-enumerate.c
--- udev-175/libudev/libudev-enumerate.c 2011-08-04 04:26:50.130004746 +0200
+++ udev-175-fix/libudev/libudev-enumerate.c 2019-04-02 12:23:07.947864764 +0200
@@ -20,7 +20,7 @@
#include <stdbool.h>
#include <sys/stat.h>
#include <sys/param.h>
-
+#include <sys/sysmacros.h>
#include "libudev.h"
#include "libudev-private.h"
diff -Naur udev-175/udev/udevadm-info.c udev-175-fix/udev/udevadm-info.c
--- udev-175/udev/udevadm-info.c 2011-10-09 22:49:21.817999569 +0200
+++ udev-175-fix/udev/udevadm-info.c 2019-04-02 12:25:44.908641018 +0200
@@ -28,6 +28,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include "udev.h"
diff -Naur udev-175/udev/udevd.c udev-175-fix/udev/udevd.c
--- udev-175/udev/udevd.c 2011-10-11 13:25:39.619713005 +0200
+++ udev-175-fix/udev/udevd.c 2019-04-02 12:17:59.529679774 +0200
@@ -43,6 +43,7 @@
#include <sys/ioctl.h>
#include <sys/inotify.h>
#include <sys/utsname.h>
+#include <sys/sysmacros.h>
#include "udev.h"
#include "sd-daemon.h"
diff -Naur udev-175/udev/udev-event.c udev-175-fix/udev/udev-event.c
--- udev-175/udev/udev-event.c 2011-10-06 00:58:11.372582876 +0200
+++ udev-175-fix/udev/udev-event.c 2019-04-02 12:18:11.513071921 +0200
@@ -33,6 +33,7 @@
#include <sys/socket.h>
#include <sys/signalfd.h>
#include <linux/sockios.h>
+#include <sys/sysmacros.h>
#include "udev.h"
diff -Naur udev-175/udev/udev-node.c udev-175-fix/udev/udev-node.c
--- udev-175/udev/udev-node.c 2011-11-01 13:08:15.803635931 +0100
+++ udev-175-fix/udev/udev-node.c 2019-04-02 12:18:21.729788742 +0200
@@ -28,6 +28,7 @@
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/sysmacros.h>
#include "udev.h"
diff -Naur udev-175/udev/udev-rules.c udev-175-fix/udev/udev-rules.c
--- udev-175/udev/udev-rules.c 2011-10-22 21:17:06.587663679 +0200
+++ udev-175-fix/udev/udev-rules.c 2019-04-02 12:18:55.866623075 +0200
@@ -29,6 +29,7 @@
#include <dirent.h>
#include <fnmatch.h>
#include <time.h>
+#include <sys/sysmacros.h>
#include "udev.h"