kopia lustrzana https://github.com/SP8EBC/MeteoSystem
Porównaj commity
60 Commity
Autor | SHA1 | Data |
---|---|---|
Mateusz Lubecki | 4641945295 | |
Mateusz Lubecki | f8dbcff362 | |
Mateusz Lubecki | 4f192e9a15 | |
Mateusz Lubecki | b6123ec677 | |
Rafal Woloszyn | 4c3b17fbfe | |
Mateusz Lubecki | a2dd3149e9 | |
SP8EBC | ea23e7b5fb | |
Mateusz Lubecki | 57fe1bfbfd | |
Mateusz Lubecki | 5a211da64e | |
Rafal Woloszyn | 34d43825f9 | |
Mateusz Lubecki | 6bcdf9fdbb | |
Mateusz Lubecki | 1c7c805d58 | |
Mateusz Lubecki | 89b08a3d11 | |
SP8EBC | 898e85d3bc | |
SP8EBC | 1294a51f64 | |
SP8EBC | 1ab918a996 | |
Mateusz Lubecki | c15939a415 | |
Mateusz Lubecki | ed675f0233 | |
Mateusz Lubecki | a40fb19282 | |
Mateusz Lubecki | 4b967b6857 | |
Mateusz Lubecki | a08f06618b | |
Mateusz Lubecki | 63f4d64a4b | |
Mateusz Lubecki | 0b18117b9c | |
Mateusz Lubecki | 660390391a | |
Mateusz Lubecki | 31135df0c9 | |
Mateusz Lubecki | 5e984ce264 | |
Mateusz Lubecki | ef5277c4ff | |
SP8EBC | 375267bea4 | |
Mateusz Lubecki | a26da27200 | |
Mateusz Lubecki | 1a93c9aab2 | |
Mateusz Lubecki | 8c24b0fe7e | |
Mateusz Lubecki | 37fdbc6a58 | |
Mateusz Lubecki | 797352c30e | |
Mateusz Lubecki | 6e57412b1f | |
Mateusz Lubecki | 6566b24b15 | |
Mateusz Lubecki | a05a11988a | |
Mateusz Lubecki | a4dd0b9972 | |
Mateusz Lubecki | 6423966f9f | |
Mateusz Lubecki | 93aab76863 | |
Mateusz Lubecki | 8628529de0 | |
Mateusz Lubecki | f19b196aac | |
Mateusz Lubecki | bbd4657946 | |
Mateusz Lubecki | 22d340efbd | |
Mateusz Lubecki | 022016d605 | |
Mateusz Lubecki | 78093e489c | |
Mateusz Lubecki | 42256bf457 | |
Mateusz Lubecki | 7577673df6 | |
Mateusz Lubecki | f903a5e636 | |
Mateusz Lubecki | aa992cb23a | |
Mateusz Lubecki | 1907b88bbd | |
Mateusz Lubecki | 32ada27816 | |
Mateusz Lubecki | 2f1652a9fb | |
Mateusz Lubecki | e460611820 | |
Mateusz Lubecki | 8629960d88 | |
Mateusz Lubecki | 26067db9a2 | |
Mateusz Lubecki | c073b91d44 | |
SP8EBC | 94259bb4e5 | |
Andris Stikans | b4b183c480 | |
Mateusz Lubecki | e4793debe4 | |
Mateusz Lubecki | 03de2eda38 |
|
@ -13,3 +13,143 @@
|
|||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Gradle files
|
||||
.gradle
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Signing files
|
||||
.signing/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio
|
||||
/*/build/
|
||||
/*/local.properties
|
||||
/*/out
|
||||
/*/*/build
|
||||
/*/*/production
|
||||
captures/
|
||||
.navigation/
|
||||
*.ipr
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
*.keystore
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Android Patch
|
||||
gen-external-apklibs
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# NDK
|
||||
obj/
|
||||
|
||||
# IntelliJ IDEA
|
||||
*.iml
|
||||
*.iws
|
||||
/out/
|
||||
|
||||
# User-specific configurations
|
||||
.idea/caches/
|
||||
.idea/libraries/
|
||||
.idea/shelf/
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/.name
|
||||
.idea/compiler.xml
|
||||
.idea/copyright/profiles_settings.xml
|
||||
.idea/encodings.xml
|
||||
.idea/misc.xml
|
||||
.idea/modules.xml
|
||||
.idea/scopes/scope_settings.xml
|
||||
.idea/dictionaries
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
.idea/datasources.xml
|
||||
.idea/dataSources.ids
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/gradle.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/navEditor.xml
|
||||
|
||||
# OS-specific files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Legacy Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
|
||||
hs_err_pid*
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
### AndroidStudio Patch ###
|
||||
|
||||
!/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Pogoda.cc
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<targetSelectedWithDropDown>
|
||||
<Target>
|
||||
<type value="QUICK_BOOT_TARGET" />
|
||||
<deviceKey>
|
||||
<Key>
|
||||
<type value="VIRTUAL_DEVICE_PATH" />
|
||||
<value value="$USER_HOME$/.android/avd/Pixel_4_XL_API_28.avd" />
|
||||
</Key>
|
||||
</deviceKey>
|
||||
</Target>
|
||||
</targetSelectedWithDropDown>
|
||||
<timeTargetWasSelectedWithDropDown value="2023-10-01T07:46:55.840082Z" />
|
||||
</component>
|
||||
</project>
|
|
@ -4,7 +4,7 @@
|
|||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="PLATFORM" />
|
||||
<option name="testRunner" value="GRADLE" />
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="1.8" />
|
||||
|
@ -15,7 +15,6 @@
|
|||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AndroidLintUnknownNullness" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
|
@ -1,9 +1,44 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="DesignSurface">
|
||||
<option name="filePathToZoomLevelMap">
|
||||
<map>
|
||||
<entry key="../../../../../layout/custom_preview.xml" value="0.2171875" />
|
||||
<entry key="app/src/main/res/drawable/button_border.xml" value="0.38125" />
|
||||
<entry key="app/src/main/res/layout/activity_all_stations.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_all_stations_linear_layout.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_export_data.xml" value="0.25" />
|
||||
<entry key="app/src/main/res/layout/activity_favourites.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_favourites_empty.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_favourites_linear_layout.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_favourites_linear_layout_data.xml" value="0.5" />
|
||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.5451010886469674" />
|
||||
<entry key="app/src/main/res/layout/activity_settings.xml" value="0.67" />
|
||||
<entry key="app/src/main/res/layout/activity_station_details.xml" value="0.33" />
|
||||
<entry key="app/src/main/res/layout/activity_station_details_plots.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_station_details_summary.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/layout/activity_station_details_wind_rose.xml" value="0.5" />
|
||||
<entry key="app/src/main/res/layout/activity_trend.xml" value="0.3645833333333333" />
|
||||
<entry key="app/src/main/res/layout/fragment_pressure.xml" value="0.3645833333333333" />
|
||||
<entry key="app/src/main/res/layout/fragment_temperature.xml" value="0.3645833333333333" />
|
||||
<entry key="app/src/main/res/layout/fragment_wind.xml" value="0.3645833333333333" />
|
||||
<entry key="app/src/main/res/layout/spinner_item.xml" value="0.28306159420289856" />
|
||||
<entry key="app/src/main/res/menu/main_activity_menu.xml" value="0.3651041666666667" />
|
||||
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher_icon.xml" value="0.3335" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="VisualizationToolProject">
|
||||
<option name="state">
|
||||
<ProjectState>
|
||||
<option name="scale" value="0.3651041666666667" />
|
||||
</ProjectState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 188 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 196 KiB |
26
README.md
26
README.md
|
@ -1 +1,25 @@
|
|||
# Pogoda.cc
|
||||
# MeteoSystem
|
||||
|
||||
An Android application which displays meteo information from few APRS weather stations. Now mostly from Beskids mountins in Poland, but let's hope that it will widespread a little bit firther ;) The app was initialy called Pogoda.cc but then it was renamed to something more suitable for international use.
|
||||
|
||||
Google Play link to this software: https://play.google.com/store/apps/details?id=cc.pogoda.mobile.meteosystem
|
||||
|
||||
A list of currently avaliable weather stations (with APRS callsign in brackets) are below, with english or german site name after the comma. As for now all of them are located in southern Poland, mostly in Beskids Mountains but also in Low Beskids (located in SW Poland) and Oppelner Schlesien land.
|
||||
|
||||
- Skrzyczne (SR9NSK), Rauhkogel
|
||||
- Jaworzyna Skrzyczneńska (SR9NSK-5)
|
||||
- Kozia Góra (SR9WXS), Ziegenbock
|
||||
- Magurka Wilkowicka (SR9WXM)
|
||||
- Bezmiechowa Górna (SR8WXB)
|
||||
- Góra Chełm (SR9WXG)
|
||||
- Dukla, Wzgórze 534 (SR8WXD)
|
||||
- Polska Nowa Wieś (SR6WXP), Polnisch Neudorf
|
||||
- Leskowiec (SR9WXL)
|
||||
- Markowe Szczawiny (SR9WXM)
|
||||
- Jezioro Żywieckie (SR9WXZ)
|
||||
- Międzybrodzie Żywieckie
|
||||
|
||||
This application is a part of bigger weather station system. The rest of it is formed by:
|
||||
1. API: https://github.com/SP8EBC/meteo_backend
|
||||
2. Receiving data from stations via APRS and storing in DB: https://github.com/SP8EBC/aprs2rrd-se
|
||||
3. Firmware for APRS weather station controller and it's design: https://github.com/SP8EBC/ParaTNC
|
||||
|
|
|
@ -1 +1,155 @@
|
|||
/build
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
|
||||
# Built application files
|
||||
*.apk
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
*.dex
|
||||
|
||||
# Java class files
|
||||
*.class
|
||||
|
||||
# Generated files
|
||||
bin/
|
||||
gen/
|
||||
out/
|
||||
|
||||
# Gradle files
|
||||
.gradle
|
||||
.gradle/
|
||||
build/
|
||||
|
||||
# Signing files
|
||||
.signing/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
|
||||
# Android Studio
|
||||
/*/build/
|
||||
/*/local.properties
|
||||
/*/out
|
||||
/*/*/build
|
||||
/*/*/production
|
||||
captures/
|
||||
.navigation/
|
||||
*.ipr
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
*.keystore
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Android Patch
|
||||
gen-external-apklibs
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
|
||||
# NDK
|
||||
obj/
|
||||
|
||||
# IntelliJ IDEA
|
||||
*.iml
|
||||
*.iws
|
||||
/out/
|
||||
|
||||
# User-specific configurations
|
||||
.idea/caches/
|
||||
.idea/libraries/
|
||||
.idea/shelf/
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
.idea/.name
|
||||
.idea/compiler.xml
|
||||
.idea/copyright/profiles_settings.xml
|
||||
.idea/encodings.xml
|
||||
.idea/misc.xml
|
||||
.idea/modules.xml
|
||||
.idea/scopes/scope_settings.xml
|
||||
.idea/dictionaries
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
.idea/datasources.xml
|
||||
.idea/dataSources.ids
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/gradle.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/navEditor.xml
|
||||
|
||||
# OS-specific files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Legacy Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
|
||||
hs_err_pid*
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
### AndroidStudio Patch ###
|
||||
|
||||
!/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
|
|
@ -3,17 +3,17 @@ plugins {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion "30.0.2"
|
||||
compileSdkVersion 33
|
||||
buildToolsVersion "30.0.3"
|
||||
|
||||
apply plugin: "androidx.navigation.safeargs"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "cc.pogoda.mobile.pogodacc"
|
||||
applicationId "cc.pogoda.mobile.meteosystem"
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
targetSdkVersion 33
|
||||
versionCode 19
|
||||
versionName "0.19"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
@ -36,23 +36,29 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
implementation 'org.tinylog:tinylog-api:2.1.0'
|
||||
runtimeOnly 'org.tinylog:tinylog-impl:2.1.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.3.2'
|
||||
implementation 'androidx.navigation:navigation-ui:2.3.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||
testImplementation 'junit:junit:4.+'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.2'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.3.5'
|
||||
implementation 'androidx.navigation:navigation-ui:2.3.5'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.2'
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.2'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
implementation 'com.jakewharton.threetenabp:threetenabp:1.2.1'
|
||||
implementation 'org.greenrobot:eventbus:3.0.0'
|
||||
implementation 'org.apache.poi:poi:3.12'
|
||||
// implementation 'org.apache.poi:poi-ooxml:3.12'
|
||||
implementation 'com.fasterxml:aalto-xml:1.0.0'
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc;
|
||||
package cc.pogoda.mobile.meteosystem;
|
||||
|
||||
import android.content.Context;
|
||||
|
|
@ -1,31 +1,78 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cc.pogoda.mobile.pogodacc">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="cc.pogoda.mobile.meteosystem">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.MANAGE_DOCUMENTS"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<application
|
||||
android:name=".Main"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:icon="@drawable/sun_rays_cloud"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_icon_foreground"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Pogodacc">
|
||||
android:theme="@style/Theme.Meteosystem">
|
||||
<service
|
||||
android:name=".service.GetAllStationsService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||
|
||||
<activity
|
||||
android:name=".activity.SettingsActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.ExportDataActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.TrendActivity"
|
||||
android:label="@string/title_activity_trend"></activity>
|
||||
<activity android:name=".activity.StationDetailsWindRoseActivity" />
|
||||
<activity android:name=".activity.StationDetailsPlotsWind" />
|
||||
<activity android:name=".activity.StationDetailsPlotsDirection" />
|
||||
<activity android:name=".activity.StationDetailsPlotsTemperature" />
|
||||
<activity android:name=".activity.StationDetailsSummaryActivity" />
|
||||
<activity android:name=".activity.StationDetailsActivity" />
|
||||
<activity android:name=".activity.AllStationsActivity" />
|
||||
<activity android:name=".activity.FavouritesActivity"/>
|
||||
<activity android:name=".activity.MainActivity">
|
||||
android:exported="true"
|
||||
android:label="@string/title_activity_trend" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsWindRoseActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsPlotsWind"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsPlotsDirection"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsPlotsTemperature"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsPlotsHumidity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsSummaryActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.StationDetailsActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.AllStationsActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEARCH" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.app.searchable"
|
||||
android:resource="@xml/searchable" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.FavouritesActivity"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
android:exported="true" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 39 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 39 KiB |
|
@ -0,0 +1,317 @@
|
|||
package cc.pogoda.mobile.meteosystem;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import com.jakewharton.threetenabp.AndroidThreeTen;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.thread.FavouritesStationSummaryUpdaterThread;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.file.ConfigurationFile;
|
||||
import cc.pogoda.mobile.meteosystem.file.FavouritiesFile;
|
||||
import cc.pogoda.mobile.meteosystem.file.FileNames;
|
||||
import cc.pogoda.mobile.meteosystem.service.GetAllStationsService;
|
||||
import cc.pogoda.mobile.meteosystem.type.AllStationsReceivedEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.meteosystem.type.ThemeColours;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStationListEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
public class Main extends Application {
|
||||
private static String TAG = Main.class.getSimpleName();
|
||||
|
||||
private File directory;
|
||||
|
||||
private File directoryForLogs;
|
||||
|
||||
private Context ctx;
|
||||
|
||||
private ConfigurationFile confFile;
|
||||
|
||||
public FileNames getFileNames() {
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
private FileNames fileNames;
|
||||
|
||||
private FavouritiesFile favouritiesFile;
|
||||
|
||||
public List<WeatherStation> getListOfAllStations() {
|
||||
return listOfAllStations;
|
||||
}
|
||||
|
||||
private List<WeatherStation> listOfAllStations;
|
||||
|
||||
public List<WeatherStation> getFavs() {
|
||||
return favs;
|
||||
}
|
||||
|
||||
private List<WeatherStation> favs;
|
||||
|
||||
/**
|
||||
* This download summary for all stations stored on favourites list and stores results
|
||||
* in 'HashMap<String, Summary> stationSystemNameToSummary'
|
||||
*/
|
||||
private FavouritesStationSummaryUpdaterThread favsSummaryUpdater = null;
|
||||
|
||||
/**
|
||||
* This map stores summary for all favourites station
|
||||
*/
|
||||
private HashMap<String, Summary> hashmapFavStationSystemNameToSummary = null;
|
||||
|
||||
/**
|
||||
* This hash map stores available parameters for all stations defined in the system
|
||||
*/
|
||||
private HashMap<String, AvailableParameters> hashmapAllStationSystemNameToAvailParameters = null;
|
||||
|
||||
public ThemeColours getThemeColours() {
|
||||
return themeColours;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used everywhere, where a colour of any element is set programatically (not globally from the theme)
|
||||
*/
|
||||
private ThemeColours themeColours;
|
||||
|
||||
public File getDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
public File getDirectoryForLogs() {
|
||||
return directoryForLogs;
|
||||
}
|
||||
|
||||
public ConfigurationFile getConfFile() {
|
||||
return confFile;
|
||||
}
|
||||
|
||||
public HashMap<String, Summary> getHashmapFavStationSystemNameToSummary() {
|
||||
return hashmapFavStationSystemNameToSummary;
|
||||
}
|
||||
|
||||
public HashMap<String, AvailableParameters> getHashmapAllStationSystemNameToAvailParameters() {
|
||||
return hashmapAllStationSystemNameToAvailParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
ctx = this.getApplicationContext();
|
||||
|
||||
confFile = new ConfigurationFile(ctx);
|
||||
|
||||
directory = getApplicationContext().getDir("files", Context.MODE_PRIVATE);
|
||||
|
||||
directoryForLogs = new File(directory.getAbsolutePath() + "/logs/");
|
||||
|
||||
System.setProperty("tinylog.directory", directoryForLogs.getAbsolutePath());
|
||||
|
||||
Logger.info("Application starting...");
|
||||
|
||||
// StrictMode.VmPolicy.Builder b = new StrictMode.VmPolicy.Builder();
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
// StrictMode.VmPolicy policy = b.detectAll().detectNonSdkApiUsage().penaltyListener((Runnable r) -> r.run(), (Violation v) -> {
|
||||
// v.printStackTrace();
|
||||
// Logger.warn("[StrictMode.VmPolicy][penaltyListener][Violation][v.getLocalizedMessage() = " + v.getLocalizedMessage() + "]");
|
||||
// }).build();
|
||||
// StrictMode.setVmPolicy(policy);
|
||||
// }
|
||||
|
||||
AndroidThreeTen.init(this);
|
||||
|
||||
EventBus.getDefault().register(this);
|
||||
|
||||
ConfigurationFile confFile = new ConfigurationFile(ctx);
|
||||
|
||||
confFile.restoreFromFile();
|
||||
|
||||
hashmapFavStationSystemNameToSummary = new HashMap<>();
|
||||
|
||||
hashmapAllStationSystemNameToAvailParameters = new HashMap<>();
|
||||
|
||||
fileNames = new FileNames(ctx);
|
||||
|
||||
favouritiesFile = new FavouritiesFile(fileNames);
|
||||
|
||||
themeColours = new ThemeColours();
|
||||
|
||||
// Download all stations from API in background via JobIntentService. Results are send
|
||||
//back with Broadcast receiver.
|
||||
startGetAllStationsService();
|
||||
|
||||
// recreate list of favorites
|
||||
recreateListOfFavs();
|
||||
|
||||
favsSummaryUpdater = new FavouritesStationSummaryUpdaterThread(hashmapFavStationSystemNameToSummary, hashmapAllStationSystemNameToAvailParameters);
|
||||
|
||||
favsSummaryUpdater.start(50);
|
||||
|
||||
// if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
// Logger.debug("[Main][onCreate][AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
// Locale locale = new Locale(AppConfiguration.locale);
|
||||
// Locale.setDefault(locale);
|
||||
// Resources resources = this.getResources();
|
||||
// Configuration config = resources.getConfiguration();
|
||||
// config.setLocale(locale);
|
||||
// Logger.debug("[Main][onCreate][locale = " + locale.toLanguageTag() + "]");
|
||||
// resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
private void recreateListOfFavs() {
|
||||
|
||||
if(listOfAllStations == null) {
|
||||
Logger.info("[listOfAllStations=null]");
|
||||
return;
|
||||
}
|
||||
|
||||
// check if this is a first call after application start
|
||||
if (favs == null) {
|
||||
favs = favouritiesFile.loadFavourites();
|
||||
}
|
||||
|
||||
// if favs is still null it means that favourites file doesn't even exists
|
||||
// so and user hasn't added any station to it yet
|
||||
if (favs == null) {
|
||||
favs = new ArrayList<>();
|
||||
}
|
||||
else {
|
||||
// update values for the fav list with listOfAllStations
|
||||
//for (WeatherStation f : favs) {
|
||||
for (int i = 0; i < favs.size(); i++) {
|
||||
|
||||
//
|
||||
WeatherStation fromFavs = favs.get(i);
|
||||
|
||||
// find an index of updated station
|
||||
int idx = listOfAllStations.indexOf(fromFavs);
|
||||
|
||||
// get the station
|
||||
WeatherStation fromAllStations = listOfAllStations.get(idx);
|
||||
|
||||
// update all parameters
|
||||
fromFavs.setAvailableParameters(fromAllStations.getAvailableParameters());
|
||||
fromFavs.setMoreInfo(fromAllStations.getMoreInfo());
|
||||
fromFavs.setImageAlign(fromAllStations.getImageAlign());
|
||||
fromFavs.setImageUrl(fromAllStations.getImageUrl());
|
||||
fromFavs.setSponsorUrl(fromAllStations.getSponsorUrl());
|
||||
fromFavs.setMoreInfo(fromAllStations.getMoreInfo());
|
||||
fromFavs.setLon(fromAllStations.getLon());
|
||||
fromFavs.setLat(fromAllStations.getLat());
|
||||
fromFavs.setDisplayedName(fromAllStations.getDisplayedName());
|
||||
fromFavs.setDisplayedLocation(fromAllStations.getDisplayedLocation());
|
||||
fromFavs.setTimezone(fromAllStations.getTimezone());
|
||||
fromFavs.setCallsignSsid(fromAllStations.getCallsignSsid());
|
||||
fromFavs.setStationNameTextColor(fromAllStations.getStationNameTextColor());
|
||||
|
||||
// there is no need to delete and put object on the list once again
|
||||
// as a list does not make a copy of the object. It (ArrayList) keeps
|
||||
// only a reference to an object
|
||||
|
||||
hashmapFavStationSystemNameToSummary.put(fromAllStations.getSystemName(), null);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void weatherStationListHandler(WeatherStationListEvent serviceEvent) {
|
||||
Logger.info("[serviceEvent = " + serviceEvent + "]");
|
||||
|
||||
switch (serviceEvent.getEventReason()) {
|
||||
|
||||
case ADD:
|
||||
// check of list consist this station
|
||||
if (favs.contains(serviceEvent.getStation())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add favourites to list
|
||||
favs.add(serviceEvent.getStation());
|
||||
|
||||
try {
|
||||
// save the list into JSON file
|
||||
favouritiesFile.persistFavourities(favs);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
break;
|
||||
case DELETE:
|
||||
favs.remove(serviceEvent.getStation());
|
||||
|
||||
try {
|
||||
// save the list into JSON file
|
||||
favouritiesFile.persistFavourities(favs);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// recreate parceable object and pass it everywhere
|
||||
recreateListOfFavs();
|
||||
|
||||
favsSummaryUpdater.updateImmediately();
|
||||
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||
public void allStationsEventHandler(@NonNull AllStationsReceivedEvent event) {
|
||||
Logger.info("[event = " + event.toString() +"]");
|
||||
this.listOfAllStations = event.getStations();
|
||||
recreateListOfFavs();
|
||||
}
|
||||
|
||||
public boolean listOfAllStationsReady() {
|
||||
return listOfAllStations != null && listOfAllStations.size() > 0;
|
||||
}
|
||||
|
||||
public boolean listOfFavsReady() {
|
||||
/* && favs.size() > 0*/
|
||||
return favs != null;
|
||||
}
|
||||
|
||||
public boolean checkIsOnFavsList(String _system_name) {
|
||||
boolean out = false;
|
||||
|
||||
for (WeatherStation wx : favs) {
|
||||
if (wx.getSystemName().equals(_system_name)) {
|
||||
out = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
public void startGetAllStationsService () {
|
||||
Intent mIntent = new Intent(this, GetAllStationsService.class);
|
||||
GetAllStationsService.enqueueWork(this, mIntent);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.Main;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.adapter.WeatherStationRecyclerViewAdapter;
|
||||
import cc.pogoda.mobile.meteosystem.type.AllStationsReceivedEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
import cc.pogoda.mobile.meteosystem.type.StartStationsRefreshEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class AllStationsActivity extends AppCompatActivity {
|
||||
|
||||
private List<WeatherStation> allStationsList;
|
||||
private SwipeRefreshLayout refreshLayout;
|
||||
private WeatherStationRecyclerViewAdapter adapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_all_stations);
|
||||
|
||||
refreshLayout = findViewById(R.id.refreshAllStationsView);
|
||||
refreshLayout.setOnRefreshListener(
|
||||
() -> ((Main) getApplication()).startGetAllStationsService()
|
||||
);
|
||||
|
||||
RecyclerView recyclerViewAllStations = findViewById(R.id.recyclerViewAllStations);
|
||||
adapter = new WeatherStationRecyclerViewAdapter(
|
||||
new LinkedList<>(), this, ParceableFavsCallReason.Reason.ALL_STATIONS);
|
||||
recyclerViewAllStations.setAdapter(adapter);
|
||||
recyclerViewAllStations.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
||||
String query = intent.getStringExtra(SearchManager.QUERY);
|
||||
filterStationList(query);
|
||||
}
|
||||
}
|
||||
|
||||
private void filterStationList(String searchQuery) {
|
||||
if (allStationsList == null || allStationsList.isEmpty())
|
||||
return;
|
||||
|
||||
if(searchQuery.isEmpty())
|
||||
adapter.update(allStationsList);
|
||||
|
||||
List<WeatherStation> newList = allStationsList.stream()
|
||||
.filter(station -> station.getDisplayedName()
|
||||
.toLowerCase(Locale.ROOT).contains(searchQuery.toLowerCase(Locale.ROOT)))
|
||||
.collect(Collectors.toList());
|
||||
adapter.update(newList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
EventBus.getDefault().register(this);
|
||||
updateStationList(((Main) getApplication()).getListOfAllStations());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.main_activity_all_stations, menu);
|
||||
|
||||
// Associate searchable configuration with the SearchView
|
||||
SearchManager searchManager =
|
||||
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||
SearchView searchView =
|
||||
(SearchView) menu.findItem(R.id.search).getActionView();
|
||||
searchView.setSearchableInfo(
|
||||
searchManager.getSearchableInfo(getComponentName()));
|
||||
searchView.setMaxWidth(Integer.MAX_VALUE);
|
||||
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener(){
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String s) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String s) {
|
||||
filterStationList(s);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
searchView.setOnCloseListener(() -> {
|
||||
adapter.update(allStationsList);
|
||||
return false;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateStationList(List<WeatherStation> stations) {
|
||||
if (stations != null) {
|
||||
refreshLayout.setRefreshing(false);
|
||||
allStationsList = stations;
|
||||
adapter.update(stations);
|
||||
} else {
|
||||
EventBus.getDefault().post(new StartStationsRefreshEvent());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void allStationsEventHandler(@NonNull AllStationsReceivedEvent event) {
|
||||
updateStationList(event.getStations());
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void startStationsRefreshEventHandler(@NonNull StartStationsRefreshEvent event) {
|
||||
refreshLayout.setRefreshing(true);
|
||||
Toast.makeText(this, R.string.refreshing_station_list, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.DatePicker;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.file.CsvExport;
|
||||
import cc.pogoda.mobile.meteosystem.file.ExcelExport;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableStationsList;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
|
||||
public class ExportDataActivity extends AppCompatActivity {
|
||||
|
||||
private Spinner formatSpinner;
|
||||
|
||||
private Button selectStationButton;
|
||||
|
||||
private Button startExportButton, outputFileButton;
|
||||
|
||||
private Spinner outputFormat;
|
||||
|
||||
ExportDataActivity act;
|
||||
|
||||
TextView stationNameToExport;
|
||||
|
||||
EditText exportLn;
|
||||
|
||||
DatePicker datePicker;
|
||||
|
||||
WeatherStation stationToExport = null;
|
||||
|
||||
Uri exportUri = null;
|
||||
|
||||
public WeatherStation getStationToExport() {
|
||||
return stationToExport;
|
||||
}
|
||||
|
||||
public void openDirectory(String fn, int outputFormat) {
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
if (outputFormat == 1) {
|
||||
intent.setType("text/csv");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, fn + ".csv");
|
||||
|
||||
}
|
||||
if (outputFormat == 2) {
|
||||
intent.setType("application/vnd.ms-excel");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, fn + ".xls");
|
||||
}
|
||||
|
||||
startActivityForResult(intent, 123);
|
||||
|
||||
}
|
||||
|
||||
public int getExportLnInHours() {
|
||||
int out = 0;
|
||||
|
||||
Editable text = exportLn.getText();
|
||||
|
||||
try {
|
||||
Integer ln = Integer.valueOf(text.toString());
|
||||
|
||||
if (ln > 199) {
|
||||
out = 199;
|
||||
}
|
||||
else {
|
||||
out = ln;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ee) {
|
||||
out = -1;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public long getStartTimestamp() {
|
||||
long out = 0;
|
||||
|
||||
int year = datePicker.getYear();
|
||||
int month = datePicker.getMonth();
|
||||
int day = datePicker.getDayOfMonth();
|
||||
|
||||
ZonedDateTime dateTime = ZonedDateTime.of(year, month, day, 0, 0, 0, 0, ZoneId.systemDefault());
|
||||
|
||||
ZonedDateTime utc = dateTime.withZoneSameInstant(ZoneId.of("UTC"));
|
||||
|
||||
out = utc.toEpochSecond();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public int getOutputFormat() {
|
||||
|
||||
String selected = outputFormat.getSelectedItem().toString();
|
||||
|
||||
switch (selected) {
|
||||
case "CSV" : return 1;
|
||||
case "MS Excel XLS": return 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
|
||||
if (requestCode == 123 && resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
|
||||
grantUriPermission(getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
exportUri = uri;
|
||||
|
||||
}
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_export_data);
|
||||
|
||||
EventBus.getDefault().register(this);
|
||||
|
||||
act = this;
|
||||
|
||||
formatSpinner = findViewById(R.id.spinnerOutputFormat);
|
||||
selectStationButton = findViewById(R.id.buttonSelectStationExport);
|
||||
stationNameToExport = findViewById(R.id.textViewStationToExport);
|
||||
startExportButton = findViewById(R.id.buttonExportStart);
|
||||
exportLn = findViewById(R.id.editTextNumberExport);
|
||||
datePicker = findViewById(R.id.datePickerExportStartDate);
|
||||
outputFormat = findViewById(R.id.spinnerOutputFormat);
|
||||
outputFileButton = findViewById(R.id.buttonExportTarget);
|
||||
|
||||
outputFileButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
String fn;
|
||||
|
||||
if (stationToExport != null) {
|
||||
fn = stationToExport.getSystemName() + "_" + datePicker.getDayOfMonth() + "-" + String.format("%02d", datePicker.getMonth()) + "-" + datePicker.getYear() +"_" + act.getExportLnInHours() + "hrs";
|
||||
}
|
||||
else {
|
||||
fn = "export";
|
||||
}
|
||||
|
||||
openDirectory(fn, act.getOutputFormat());
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
selectStationButton.setOnClickListener(new View.OnClickListener() {
|
||||
|
||||
Intent intent;
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
intent = new Intent(act, FavouritesActivity.class);
|
||||
|
||||
ParceableFavsCallReason callReason = new ParceableFavsCallReason(ParceableFavsCallReason.Reason.EXPORT_SELECT);
|
||||
intent.putExtra("callReason", callReason);
|
||||
|
||||
act.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
startExportButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
StationDataDao stationDataDao;
|
||||
|
||||
WeatherStation toExport = act.getStationToExport();
|
||||
|
||||
if (toExport != null && exportUri != null) {
|
||||
long timestampStart = act.getStartTimestamp();
|
||||
long timestampStop = timestampStart + act.getExportLnInHours() * 3600;
|
||||
|
||||
stationDataDao = new StationDataDao();
|
||||
|
||||
ListOfStationData stationData = stationDataDao.getLastStationData(toExport.getSystemName(), timestampStart, timestampStop);
|
||||
|
||||
int format = act.getOutputFormat();
|
||||
|
||||
if (format == 2) {
|
||||
try {
|
||||
if (ExcelExport.exportToExcel(stationData, toExport, act.getApplicationContext(), getContentResolver().openOutputStream(exportUri))) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.success);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.failure);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if (format == 1) {
|
||||
try {
|
||||
if (CsvExport.exportToCsv(stationData, toExport, act.getApplicationContext(), getContentResolver().openOutputStream(exportUri))) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.success);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if (toExport == null) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.select_station_export);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.select_output_file);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.export_formats, android.R.layout.simple_spinner_item);
|
||||
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
|
||||
formatSpinner.setAdapter(adapter);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void stationToExportEvent(WeatherStation wx) {
|
||||
stationNameToExport.setText(wx.getDisplayedName());
|
||||
|
||||
stationToExport = wx;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.Main;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.adapter.WeatherStationRecyclerViewAdapter;
|
||||
import cc.pogoda.mobile.meteosystem.type.AllStationsReceivedEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
import cc.pogoda.mobile.meteosystem.type.StartStationsRefreshEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class FavouritesActivity extends AppCompatActivity {
|
||||
|
||||
RecyclerView recyclerViewFavourites;
|
||||
|
||||
private SwipeRefreshLayout refreshLayout;
|
||||
|
||||
List<WeatherStation> favourites = new LinkedList<>();
|
||||
|
||||
List<WeatherStation> sortedFavourites;
|
||||
|
||||
boolean sorting = false;
|
||||
|
||||
WeatherStationRecyclerViewAdapter adapter = null;
|
||||
|
||||
ParceableFavsCallReason callReason;
|
||||
|
||||
private static class WxStationComparator implements Comparator<WeatherStation> {
|
||||
|
||||
@Override
|
||||
public int compare(WeatherStation station, WeatherStation t1) {
|
||||
return (station.getDisplayedName().compareTo(t1.getDisplayedName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
|
||||
getMenuInflater().inflate(R.menu.menu_favourites, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
//return super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.fav_sort_alph_oder:
|
||||
sorting = true;
|
||||
|
||||
if (recyclerViewFavourites != null) {
|
||||
adapter = new WeatherStationRecyclerViewAdapter(sortedFavourites, this, callReason.getReason());
|
||||
|
||||
adapter.createAndStartUpdater();
|
||||
|
||||
recyclerViewFavourites.setAdapter(adapter);
|
||||
}
|
||||
|
||||
break;
|
||||
case R.id.fav_sort_add_order:
|
||||
sorting = false;
|
||||
|
||||
if (recyclerViewFavourites != null) {
|
||||
adapter = new WeatherStationRecyclerViewAdapter(favourites, this, callReason.getReason());
|
||||
|
||||
adapter.createAndStartUpdater();
|
||||
|
||||
recyclerViewFavourites.setAdapter(adapter);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_favourites);
|
||||
|
||||
recyclerViewFavourites = findViewById(R.id.recyclerViewFavourites);
|
||||
refreshLayout = findViewById(R.id.refreshViewFavourites);
|
||||
refreshLayout.setOnRefreshListener(
|
||||
() -> ((Main) getApplication()).startGetAllStationsService()
|
||||
);
|
||||
|
||||
callReason = getIntent().getParcelableExtra("callReason");
|
||||
adapter = new WeatherStationRecyclerViewAdapter(favourites,
|
||||
this, callReason.getReason());
|
||||
recyclerViewFavourites.setAdapter(adapter);
|
||||
recyclerViewFavourites.setLayoutManager(new LinearLayoutManager(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Logger.debug("[onResume]");
|
||||
|
||||
super.onResume();
|
||||
EventBus.getDefault().register(this);
|
||||
updateStationList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
adapter.stopUpdater();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void updateStationList() {
|
||||
List favList = ((Main) getApplication()).getFavs();
|
||||
|
||||
if(favList != null) {
|
||||
favourites.clear();
|
||||
favourites.addAll(favList);
|
||||
refreshLayout.setRefreshing(false);
|
||||
sortedFavourites = new ArrayList<>(favourites);
|
||||
sortedFavourites.sort(new WxStationComparator());
|
||||
adapter.notifyDataSetChanged();
|
||||
if (!favList.isEmpty()) {
|
||||
adapter.createAndStartUpdater();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void allStationsEventHandler(@NonNull AllStationsReceivedEvent event) {
|
||||
Logger.info("[event = " + event.toString() +"]");
|
||||
updateStationList();
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void startStationsRefreshEventHandler(@NonNull StartStationsRefreshEvent event) {
|
||||
refreshLayout.setRefreshing(true);
|
||||
Toast.makeText(this, R.string.refreshing_station_list, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
// https://www.softicons.com/web-icons/vector-stylish-weather-icons-by-bartosz-kaszubowski/sun-rays-cloud-icon#google_vignette
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.google.android.material.color.MaterialColors;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.Main;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.MainActImageButtonAllStationsClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.MainActImageButtonExportClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.MainActImageButtonFavouritesClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.MainActImageButtonSettingsClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.file.CopyLog;
|
||||
import cc.pogoda.mobile.meteosystem.type.ThemeColours;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private Main main;
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
EventBus.getDefault().unregister(this);
|
||||
Logger.info("[onDestroy]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a user goes back to the main screen
|
||||
*/
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
Logger.info("[onResume]");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Logger.info("[onCreate]");
|
||||
|
||||
main = (Main) getApplication();
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default")) {
|
||||
Logger.debug("[AppConfiguration.locale = "
|
||||
+ AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
Logger.debug("[locale = " + locale.toLanguageTag() + "]");
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
ImageButton imageButtonAllStations = findViewById(R.id.imageButtonAllStations);
|
||||
imageButtonAllStations.setOnClickListener(
|
||||
new MainActImageButtonAllStationsClickEvent(this));
|
||||
|
||||
ImageButton imageButtonFavourites = findViewById(R.id.imageButtonFavourites);
|
||||
imageButtonFavourites.setOnClickListener(
|
||||
new MainActImageButtonFavouritesClickEvent(this));
|
||||
|
||||
ImageButton exportButton = findViewById(R.id.imageButtonExport);
|
||||
exportButton.setOnClickListener(new MainActImageButtonExportClickEvent(this));
|
||||
|
||||
ImageButton settingsButton = findViewById(R.id.imageButtonSettings);
|
||||
settingsButton.setOnClickListener(
|
||||
new MainActImageButtonSettingsClickEvent(this, main.getConfFile()));
|
||||
|
||||
ThemeColours colours = ((Main) getApplication()).getThemeColours();
|
||||
|
||||
TypedValue typedValue = new TypedValue();
|
||||
Resources.Theme theme = getTheme();
|
||||
|
||||
//MaterialColors.getColor(, R.attr.colorOnPrimary);
|
||||
|
||||
theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
|
||||
TypedArray arr = obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorPrimary});
|
||||
colours.colorPrimary = arr.getColor(0, -1);
|
||||
arr.recycle();
|
||||
|
||||
theme.resolveAttribute(R.attr.colorPrimaryVariant, typedValue, true);
|
||||
arr = obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorPrimaryVariant});
|
||||
colours.colorPrimaryVariant = arr.getColor(0, -1);
|
||||
arr.recycle();
|
||||
|
||||
theme.resolveAttribute(R.attr.colorOnPrimary, typedValue, true);
|
||||
arr = obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorOnPrimary});
|
||||
colours.colorOnPrimary = arr.getColor(0, -1);
|
||||
arr.recycle();
|
||||
|
||||
theme.resolveAttribute(R.attr.colorSecondary, typedValue, true);
|
||||
arr = obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorSecondary});
|
||||
colours.colorSecondary = arr.getColor(0, -1);
|
||||
arr.recycle();
|
||||
|
||||
theme.resolveAttribute(R.attr.colorSecondaryVariant, typedValue, true);
|
||||
arr = obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorSecondaryVariant});
|
||||
colours.colorSecondaryVariant = arr.getColor(0, -1);
|
||||
arr.recycle();
|
||||
|
||||
theme.resolveAttribute(R.attr.colorOnSecondary, typedValue, true);
|
||||
arr = obtainStyledAttributes(typedValue.data, new int[]{R.attr.colorOnSecondary});
|
||||
colours.colorOnSecondary = arr.getColor(0, -1);
|
||||
arr.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
|
||||
if (requestCode == 123 && resultCode == RESULT_OK) {
|
||||
Uri uri = data.getData();
|
||||
|
||||
Logger.debug("[requestCode = 123][uri.getPath() = "
|
||||
+ uri.getPath() + "]");
|
||||
|
||||
grantUriPermission(getPackageName(), uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
getContentResolver().takePersistableUriPermission(uri,
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||
|
||||
try {
|
||||
CopyLog.forDay(main.getFileNames(), LocalDateTime.now(),
|
||||
getContentResolver().openOutputStream(uri));
|
||||
} catch (FileNotFoundException e) {
|
||||
Logger.error("[FileNotFoundException][e = " + e.toString() +"]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.main_activity_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
//return super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_item_translation_authors: {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage("ENG: Mateusz Lubecki\r\n" +
|
||||
"CZE: Sylwiusz Pachel\r\n" +
|
||||
"GER: Jakub Fiałek\r\n" +
|
||||
"LAT: Andris Stikāns\r\n" +
|
||||
"UKR, RUS: Влад Поливач \r\n" +
|
||||
"(Wład Polywacz)\r\n\r\nProgram Icon: Bartosz Kaszubowski");
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case (R.id.menu_item_log_export): {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("text/plain");
|
||||
intent.putExtra(Intent.EXTRA_TITLE, "meteosystem_" +
|
||||
LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE) + ".log");
|
||||
|
||||
startActivityForResult(intent, 123);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean listOfAllStationsReady() {
|
||||
return main.listOfAllStationsReady() && main != null;
|
||||
}
|
||||
|
||||
public boolean listOfAllFavsReady() {
|
||||
return main.listOfFavsReady() && main != null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.file.ConfigurationFile;
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity {
|
||||
|
||||
Switch windspdUnitSwitch;
|
||||
|
||||
TextView windspdUnitDisplayTv;
|
||||
|
||||
ConfigurationFile confFile;
|
||||
|
||||
Spinner language;
|
||||
|
||||
EditText enditTextMinutesPeriod;
|
||||
|
||||
AppCompatActivity act;
|
||||
|
||||
private static String languageNameFromShort(String shortName) {
|
||||
|
||||
Logger.info("[shortName = " + shortName +"]");
|
||||
|
||||
switch (shortName) {
|
||||
case "en-rUS": return "English";
|
||||
case "pl": return "Polski";
|
||||
case "cs": return "Čeština";
|
||||
case "uk": return "Українська мова";
|
||||
case "ru": return "Русский";
|
||||
case "lv": return "Latviešu";
|
||||
case "de": return "Deutsch";
|
||||
default: return "AUTO";
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWindspdUnitTv(boolean b) {
|
||||
if (windspdUnitDisplayTv != null) {
|
||||
if (b) {
|
||||
windspdUnitDisplayTv.setText(R.string.knots_long);
|
||||
}
|
||||
else {
|
||||
windspdUnitDisplayTv.setText(R.string.meters_per_second);
|
||||
}
|
||||
|
||||
confFile.storeToFile();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_settings);
|
||||
|
||||
Logger.info("[onCreate]");
|
||||
|
||||
confFile = new ConfigurationFile(getBaseContext());
|
||||
|
||||
act = this;
|
||||
|
||||
windspdUnitDisplayTv = (TextView) findViewById(R.id.textViewSettingsWindspeedUnitDisp);
|
||||
updateWindspdUnitTv(AppConfiguration.replaceMsWithKnots);
|
||||
|
||||
windspdUnitSwitch = (Switch) findViewById(R.id.switchKnots);
|
||||
if (windspdUnitSwitch != null) {
|
||||
windspdUnitSwitch.setChecked(AppConfiguration.replaceMsWithKnots);
|
||||
windspdUnitSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
||||
AppConfiguration.replaceMsWithKnots = b;
|
||||
|
||||
updateWindspdUnitTv(b);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
enditTextMinutesPeriod = (EditText) findViewById(R.id.editTextNumberSettingsMinTimeRes);
|
||||
enditTextMinutesPeriod.setText(Integer.toString(AppConfiguration.decimationPeriod));
|
||||
if (enditTextMinutesPeriod != null) {
|
||||
enditTextMinutesPeriod.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
if (i2 > 0) {
|
||||
try {
|
||||
int newValue = Integer.valueOf(String.valueOf(charSequence), 10);
|
||||
|
||||
if (newValue > 60) {
|
||||
newValue = 60;
|
||||
|
||||
enditTextMinutesPeriod.setText(Integer.toString(newValue));
|
||||
}
|
||||
|
||||
AppConfiguration.decimationPeriod = newValue;
|
||||
|
||||
confFile.storeToFile();
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
AppConfiguration.decimationPeriod = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
language = (Spinner) findViewById(R.id.spinnerSettingsLanguage);
|
||||
if (language != null) {
|
||||
ArrayAdapter spinnerLanguageAdapter = ArrayAdapter.createFromResource(getBaseContext(), R.array.languages, R.layout.spinner_item);
|
||||
|
||||
int currentLanguagePosition = spinnerLanguageAdapter.getPosition(SettingsActivity.languageNameFromShort(AppConfiguration.locale));
|
||||
|
||||
language.setAdapter(spinnerLanguageAdapter);
|
||||
|
||||
// if an item has been found (if no -1 is returned by 'getPosition'
|
||||
if (currentLanguagePosition >= 0) {
|
||||
language.setSelection(currentLanguagePosition);
|
||||
}
|
||||
|
||||
language.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
String languageSelected = adapterView.getItemAtPosition(i).toString();
|
||||
|
||||
Logger.debug("[AdapterView.OnItemSelectedListener()][languageSelected = " + languageSelected +"]");
|
||||
|
||||
switch (languageSelected) {
|
||||
case "English": AppConfiguration.locale = "en-rUS"; break;
|
||||
case "Polski": AppConfiguration.locale = "pl"; break;
|
||||
case "Čeština": AppConfiguration.locale = "cs"; break;
|
||||
case "Українська мова": AppConfiguration.locale = "uk"; break;
|
||||
case "Русский": AppConfiguration.locale = "ru"; break;
|
||||
case "Latviešu": AppConfiguration.locale = "lv"; break;
|
||||
case "Deutsch": AppConfiguration.locale = "de"; break;
|
||||
default: AppConfiguration.locale = "default";
|
||||
}
|
||||
|
||||
confFile.storeToFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> adapterView) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +1,44 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.text.HtmlCompat;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.database.DataSetObserver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.icu.text.LocaleDisplayNames;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActTemperaturePlotButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActTrendButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActWindDirectionPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActWindSpeedPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActSummaryButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.StationDetailsActWindRoseButtonClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActHumidityPlotButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActTemperaturePlotButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActTrendButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActWindDirectionPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActWindSpeedPlotsButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActSummaryButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.StationDetailsActWindRoseButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.StationBackgroundImageUpdater;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStationListEvent;
|
||||
import cc.pogoda.mobile.meteosystem.web.StationBackgroundDownloader;
|
||||
|
||||
public class StationDetailsActivity extends AppCompatActivity {
|
||||
|
||||
|
@ -48,11 +54,14 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
ImageButton windSpeedPlotsButton = null;
|
||||
ImageButton windDirectionPlotsButton = null;
|
||||
ImageButton temperatureButton = null;
|
||||
ImageButton humidityButton = null;
|
||||
ImageButton windRoseButton = null;
|
||||
ImageButton trendButton = null;
|
||||
|
||||
ImageView topBackground = null;
|
||||
|
||||
AppCompatActivity act;
|
||||
|
||||
/**
|
||||
* Click event on Station Summary Button
|
||||
*/
|
||||
|
@ -67,6 +76,8 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
|
||||
StationDetailsActTemperaturePlotButtonClickEvent temperaturePlotButtonClickEvent = null;
|
||||
|
||||
StationDetailsActHumidityPlotButtonClickEvent humidityPlotButtonClickEvent = null;
|
||||
|
||||
StationDetailsActTrendButtonClickEvent trendButtonClickEvent = null;
|
||||
|
||||
/**
|
||||
|
@ -84,34 +95,7 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
*/
|
||||
int selectedLn = 0;
|
||||
|
||||
/**
|
||||
* This class downloads the background JPG image from the internet and
|
||||
*/
|
||||
private class DownloadImage implements Runnable {
|
||||
|
||||
ImageView iv;
|
||||
String image_url;
|
||||
|
||||
Bitmap bitmap;
|
||||
|
||||
public DownloadImage(ImageView background, String url) {
|
||||
iv = background;
|
||||
image_url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
InputStream in = new java.net.URL(image_url).openStream();
|
||||
bitmap = BitmapFactory.decodeStream(in);
|
||||
|
||||
iv.setImageBitmap(bitmap);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Handler handler;
|
||||
|
||||
public StationDetailsActivity() {
|
||||
stationName = null;
|
||||
|
@ -130,9 +114,9 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
switch (item.getItemId()) {
|
||||
case R.id.menuItemStationDetailsAddFavourites:
|
||||
if (station != null) {
|
||||
boolean result = false;
|
||||
boolean result = true;
|
||||
|
||||
result = AppConfiguration.favourites.addFav(station);
|
||||
EventBus.getDefault().post(new WeatherStationListEvent(station, WeatherStationListEvent.EventReason.ADD));
|
||||
|
||||
if (result) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
|
@ -147,9 +131,10 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
break;
|
||||
case R.id.menuItemStationDetailsDeleteFavourites:
|
||||
if (station != null) {
|
||||
boolean result = false;
|
||||
boolean result = true;
|
||||
|
||||
result = AppConfiguration.favourites.removeFav(station);
|
||||
//result = AppConfiguration.favourites.removeFav(station);
|
||||
EventBus.getDefault().post(new WeatherStationListEvent(station, WeatherStationListEvent.EventReason.DELETE));
|
||||
|
||||
if (result) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
|
@ -179,9 +164,24 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
act = this;
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
Logger.info("[station.getSystemName() = " + station.getSystemName() +"]");
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_station_details);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
AvailableParameters parameters = station.getAvailableParameters();
|
||||
|
||||
stationName = findViewById(R.id.textViewStationName);
|
||||
stationLocation = findViewById(R.id.textViewLocalization);
|
||||
|
@ -213,6 +213,7 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
windSpeedPlotsClickEvent = new StationDetailsActWindSpeedPlotsButtonClickEvent(station, this);
|
||||
windDirectionPlotsClickEvent = new StationDetailsActWindDirectionPlotsButtonClickEvent(station, this);
|
||||
temperaturePlotButtonClickEvent = new StationDetailsActTemperaturePlotButtonClickEvent(station, this);
|
||||
humidityPlotButtonClickEvent = new StationDetailsActHumidityPlotButtonClickEvent(station, this);
|
||||
windRoseClickEvent = new StationDetailsActWindRoseButtonClickEvent(station, this);
|
||||
trendButtonClickEvent = new StationDetailsActTrendButtonClickEvent(station, this);
|
||||
|
||||
|
@ -220,10 +221,43 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
summaryButton.setOnClickListener(summaryClickEvent);
|
||||
|
||||
windSpeedPlotsButton = findViewById(R.id.imageButtonPlotsWindSpeed);
|
||||
windSpeedPlotsButton.setOnClickListener(windSpeedPlotsClickEvent);
|
||||
if (parameters.windSpeed) {
|
||||
windSpeedPlotsButton.setOnClickListener(windSpeedPlotsClickEvent);
|
||||
}
|
||||
else {
|
||||
windSpeedPlotsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.station_doesnt_measure);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
windDirectionPlotsButton = findViewById(R.id.imageButtonPlotsWindDirection);
|
||||
windDirectionPlotsButton.setOnClickListener(windDirectionPlotsClickEvent);
|
||||
if (parameters.windSpeed) {
|
||||
windDirectionPlotsButton.setOnClickListener(windDirectionPlotsClickEvent);
|
||||
}
|
||||
else {
|
||||
windDirectionPlotsButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.station_doesnt_measure);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
windRoseButton = findViewById(R.id.imageButtonWindRose);
|
||||
windRoseButton.setOnClickListener(windRoseClickEvent);
|
||||
|
@ -231,6 +265,25 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
temperatureButton = findViewById(R.id.imageButtonPlotsTemperature);
|
||||
temperatureButton.setOnClickListener(temperaturePlotButtonClickEvent);
|
||||
|
||||
humidityButton = findViewById(R.id.imageButtonPlotsHumidity);
|
||||
if (parameters.humidity) {
|
||||
humidityButton.setOnClickListener(humidityPlotButtonClickEvent);
|
||||
}
|
||||
else {
|
||||
humidityButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(act);
|
||||
builder.setMessage(R.string.station_doesnt_measure);
|
||||
builder.setPositiveButton(R.string.ok, (DialogInterface var1, int var2) -> {
|
||||
var1.dismiss();
|
||||
});
|
||||
builder.create();
|
||||
builder.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
trendButton = findViewById(R.id.imageButtonTrend);
|
||||
trendButton.setOnClickListener(trendButtonClickEvent);
|
||||
|
||||
|
@ -262,50 +315,82 @@ public class StationDetailsActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
|
||||
stationName.setText(station.getDisplayedName());
|
||||
if (station.getDisplayedName().length() > 18) {
|
||||
stationName.setText(station.getDisplayedName());
|
||||
stationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30.0f);
|
||||
}
|
||||
else {
|
||||
stationName.setText(station.getDisplayedName());
|
||||
stationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 36.0f);
|
||||
}
|
||||
|
||||
stationLocation.setText(station.getDisplayedLocation());
|
||||
|
||||
station_lat = station.getLat();
|
||||
station_lon = station.getLon();
|
||||
|
||||
stationSponsorUrl.setText(station.getSponsorUrl());
|
||||
stationSponsorUrl.setAutoLinkMask(0);
|
||||
stationSponsorUrl.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
String anchorText;
|
||||
if (station.getSponsorUrl().length() > 32) {
|
||||
anchorText = getString(R.string.www_link);
|
||||
} else {
|
||||
anchorText = station.getSponsorUrl();
|
||||
}
|
||||
stationSponsorUrl.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
stationSponsorUrl.setText(
|
||||
HtmlCompat.fromHtml(
|
||||
"<a href=\"" + station.getSponsorUrl() + "\">" + anchorText + "</a>\n", HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||
)
|
||||
);
|
||||
|
||||
// if (station.getSponsorUrl().length() > 32) {
|
||||
// stationSponsorUrl.setClickable(true);
|
||||
// stationSponsorUrl.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
// stationSponsorUrl.setText(Html.fromHtml("<a href=\"" + station.getSponsorUrl() +"\">" + getString(R.string.www_link) + "</a>\n", HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||
// }
|
||||
// else {
|
||||
// stationSponsorUrl.setText(station.getSponsorUrl());
|
||||
// }
|
||||
|
||||
stationMoreInfo.setText(station.getMoreInfo());
|
||||
|
||||
|
||||
DownloadImage downloadImage = new DownloadImage(topBackground, station.getImageUrl());
|
||||
Thread t = new Thread(downloadImage);
|
||||
StationBackgroundDownloader downloader = new StationBackgroundDownloader(station);
|
||||
Thread t = new Thread(downloader);
|
||||
t.start();
|
||||
//runOnUiThread(downloadImage);
|
||||
|
||||
handler = new Handler();
|
||||
handler.postDelayed(new StationBackgroundImageUpdater(topBackground, stationName, station, downloader, handler), 100);
|
||||
|
||||
if (station_lat > 0.0f && station_lon > 0.0f) {
|
||||
// europe
|
||||
sb.append(station_lon);
|
||||
sb.append(" N / ");
|
||||
sb.append(station_lat);
|
||||
sb.append(" N / ");
|
||||
sb.append(station_lon);
|
||||
sb.append(" E");
|
||||
|
||||
stationLatLon.setText(sb.toString());
|
||||
} else if (station_lat < 0.0f && station_lon > 0.0f) {
|
||||
// usa
|
||||
sb.append(station_lon);
|
||||
sb.append(station_lat);
|
||||
sb.append(" N / ");
|
||||
sb.append(-station_lat);
|
||||
sb.append(-station_lon);
|
||||
sb.append(" W");
|
||||
|
||||
stationLatLon.setText(sb.toString());
|
||||
} else if (station_lat < 0.0f && station_lon < 0.0f) {
|
||||
// brazil
|
||||
sb.append(-station_lon);
|
||||
sb.append(" S / ");
|
||||
sb.append(-station_lat);
|
||||
sb.append(" S / ");
|
||||
sb.append(-station_lon);
|
||||
sb.append(" W");
|
||||
|
||||
stationLatLon.setText(sb.toString());
|
||||
} else if (station_lat > 0.0f && station_lat > 0.0f) {
|
||||
// australia
|
||||
sb.append(-station_lon);
|
||||
sb.append(-station_lat);
|
||||
sb.append(" S / ");
|
||||
sb.append(station_lat);
|
||||
sb.append(station_lon);
|
||||
sb.append(" E");
|
||||
|
||||
stationLatLon.setText(sb.toString());
|
|
@ -1,5 +1,7 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
@ -21,18 +23,21 @@ import org.threeten.bp.ZoneId;
|
|||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationData;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationSummaryActElements;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsDirection extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
|
@ -70,8 +75,10 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
// and then shift to the user timezone for convinient display
|
||||
ZonedDateTime localDateTime = utcDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault());
|
||||
|
||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm");
|
||||
|
||||
/* format only the time to keep X axis clean */
|
||||
return DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(localDateTime);
|
||||
return fmt.format(localDateTime);
|
||||
|
||||
//return dt;
|
||||
}
|
||||
|
@ -123,10 +130,22 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
// get data length for this plot
|
||||
dataLn = (int)getIntent().getExtras().get("data_ln");
|
||||
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
Logger.info("[station.getSystemName() = " + station.getSystemName() +"][dataLn = " + dataLn +"]");
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
// download data from web service
|
||||
this.downloadDataFromWebservice();
|
||||
|
||||
|
@ -161,10 +180,13 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
xAxis.setTextColor(Color.WHITE);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
xAxis.setDrawGridLines(true);
|
||||
xAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
xAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setGranularity(1f); // one hour
|
||||
xAxis.setGranularity(100f); // one hour
|
||||
xAxis.setLabelRotationAngle(45.0f);
|
||||
xAxis.setValueFormatter(new StationDetailsPlotsDirection.ValueFormatter());
|
||||
xAxis.setTextSize(123.0f);
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
|
||||
|
@ -173,9 +195,10 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
leftAxis.setDrawGridLines(true);
|
||||
leftAxis.setGranularityEnabled(true);
|
||||
leftAxis.setAxisMinimum(0.0f);
|
||||
leftAxis.setAxisMaximum(360.0f);
|
||||
leftAxis.setAxisMaximum(400.0f);
|
||||
leftAxis.setYOffset(0.0f);
|
||||
leftAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
leftAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
leftAxis.setTextSize(123.0f);
|
||||
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setEnabled(false);
|
||||
|
@ -210,7 +233,7 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
|
||||
if (this.textViewSpeed != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewSpeed.setText(getString(R.string.wind_direction_short) + String.format(": %d", (int)direction));
|
||||
this.textViewSpeed.setText(getString(R.string.wind_direction_short) + String.format(": %d - ", (int)direction) + StationSummaryActElements.convertDegreesToDir((int) direction));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
@ -319,6 +342,8 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
// utc timestamp
|
||||
long utcTimestamp = utcTime.toEpochSecond();
|
||||
|
||||
Logger.debug("[station.getSystemName() = " + station.getSystemName() +"]");
|
||||
|
||||
if (this.dataLn < 0 || this.dataLn > 2) {
|
||||
// last 2000 points of data, regardless the timescale
|
||||
data = lastStationDataDao.getLastStationData(station.getSystemName());
|
||||
|
@ -339,6 +364,9 @@ public class StationDetailsPlotsDirection extends AppCompatActivity implements S
|
|||
valuesWindDirection = new ArrayList<>();
|
||||
|
||||
if (data != null) {
|
||||
|
||||
Logger.debug("[data.list_of_station_data.length = " + data.list_of_station_data.length +"]");
|
||||
|
||||
for (StationData d : data.list_of_station_data) {
|
||||
valuesWindDirection.add(new Entry(d.epoch * 1000, d.winddir));
|
||||
}
|
|
@ -0,0 +1,362 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.github.mikephil.charting.charts.LineChart;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsHumidity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
private LineChart chart = null;
|
||||
private SeekBar seekBarX = null;
|
||||
private TextView textViewTimestamp = null;
|
||||
private TextView textViewHumidity = null;
|
||||
|
||||
private int dataLn = -2;
|
||||
|
||||
private WeatherStation station;
|
||||
|
||||
private final LastStationDataDao lastStationDataDao;
|
||||
private final StationDataDao stationDataDao;
|
||||
|
||||
private PlotClickEvent plotClickEvent;
|
||||
|
||||
private ArrayList<Entry> valuesHumidity;
|
||||
|
||||
private static final int twelve_hours = 3600 * 12;
|
||||
private static final int twenty_four_hours = 3600 * 24;
|
||||
private static final int three_days = 3600 * 24 * 3;
|
||||
|
||||
private static class ValueFormatter extends com.github.mikephil.charting.formatter.ValueFormatter {
|
||||
|
||||
@Override
|
||||
public String getFormattedValue(float value) {
|
||||
|
||||
long millis = (long) value;
|
||||
|
||||
// the web service and the plot always stores the entries as UTC. So first convert epoch timestamp to the LocalDateTime
|
||||
LocalDateTime utcDateTime = LocalDateTime.ofEpochSecond(millis / 1000, 0, ZoneOffset.UTC);
|
||||
|
||||
// and then shift to the user timezone for convinient display
|
||||
ZonedDateTime localDateTime = utcDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault());
|
||||
|
||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm");
|
||||
|
||||
/* format only the time to keep X axis clean */
|
||||
return fmt.format(localDateTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public StationDetailsPlotsHumidity() {
|
||||
lastStationDataDao = new LastStationDataDao();
|
||||
stationDataDao = new StationDataDao();
|
||||
plotClickEvent = new PlotClickEvent(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
|
||||
// first and last index to display on plot
|
||||
int first_index, last_index = 0;
|
||||
|
||||
// display only 20% of the set at once
|
||||
int window_size = (int) (valuesHumidity.size() * 0.2f);
|
||||
|
||||
last_index = (int) ((seekBarX.getProgress() / 100.0f) * valuesHumidity.size());
|
||||
first_index = last_index - window_size;
|
||||
|
||||
if (first_index < 0) {
|
||||
first_index = 0;
|
||||
last_index = window_size;
|
||||
}
|
||||
|
||||
this.setData(first_index, last_index, false);
|
||||
|
||||
// redraw
|
||||
chart.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLabels(String date, Entry entry) {
|
||||
int humidity = 0;
|
||||
|
||||
// get a timestamp from the entry
|
||||
long timestamp = (long) entry.getX();
|
||||
|
||||
// look for the windspeed coresponding to that timestamp
|
||||
for (Entry e : valuesHumidity) {
|
||||
// if this is what we are looking for
|
||||
if (e.getX() == entry.getX()) {
|
||||
humidity = (int) e.getY();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this.textViewHumidity != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewHumidity.setText(getText(R.string.humidity) + String.format(": %d%%", humidity));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// get data length for this plot
|
||||
dataLn = (int)getIntent().getExtras().get("data_ln");
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
// download data from web service
|
||||
this.downloadDataFromWebservice();
|
||||
|
||||
Typeface tfLight = Typeface.MONOSPACE;
|
||||
|
||||
setTitle(R.string.humidity_plot);
|
||||
|
||||
textViewTimestamp = findViewById(R.id.textViewPlotsWindTimestamp);
|
||||
textViewHumidity = findViewById(R.id.textViewPlotsWindMean);
|
||||
seekBarX = findViewById(R.id.seekBarPlotsWind);
|
||||
chart = findViewById(R.id.chartPlotsWind);
|
||||
|
||||
// enable scaling and dragging
|
||||
chart.setDragEnabled(true);
|
||||
chart.setScaleEnabled(true);
|
||||
chart.setDrawGridBackground(false);
|
||||
chart.setHighlightPerDragEnabled(true);
|
||||
|
||||
// set an alternative background color
|
||||
chart.setBackgroundColor(Color.WHITE);
|
||||
chart.setViewPortOffsets(0f, 0f, 0f, 0f);
|
||||
|
||||
// add data
|
||||
seekBarX.setProgress(100);
|
||||
seekBarX.setOnSeekBarChangeListener(this);
|
||||
|
||||
XAxis xAxis = chart.getXAxis();
|
||||
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM_INSIDE);
|
||||
xAxis.setTypeface(tfLight);
|
||||
xAxis.setTextSize(10f);
|
||||
xAxis.setTextColor(Color.WHITE);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
xAxis.setDrawGridLines(true);
|
||||
xAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setGranularity(1f); // one hour
|
||||
xAxis.setValueFormatter(new StationDetailsPlotsHumidity.ValueFormatter());
|
||||
xAxis.setLabelRotationAngle(45.0f);
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
|
||||
leftAxis.setTypeface(tfLight);
|
||||
leftAxis.setTextColor(ColorTemplate.getHoloBlue());
|
||||
leftAxis.setDrawGridLines(true);
|
||||
leftAxis.setGranularityEnabled(true);
|
||||
leftAxis.setAxisMinimum(0.0f);
|
||||
leftAxis.setAxisMaximum(100.0f);
|
||||
leftAxis.setYOffset(0.0f);
|
||||
leftAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
leftAxis.setTextSize(123.0f);
|
||||
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setEnabled(false);
|
||||
|
||||
int lastDataIndex = valuesHumidity.size() - 1;
|
||||
|
||||
// display only the last data (20% of newest data)
|
||||
this.setData((long) (0.8 * (lastDataIndex)), lastDataIndex, false);
|
||||
|
||||
// set bar to maximum value
|
||||
seekBarX.setProgress(100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the data from the web service and stores it as entries ready to be displayed on the
|
||||
* plot. Web Service gives the data with the epoch timestamp in second resolution, but the plot
|
||||
* shows the data in millisecond resolution
|
||||
*/
|
||||
private void downloadDataFromWebservice() {
|
||||
|
||||
ListOfStationData data = null;
|
||||
|
||||
// utc time
|
||||
ZonedDateTime utcTime = ZonedDateTime.now().withZoneSameInstant(ZoneId.of("UTC"));
|
||||
|
||||
// utc timestamp
|
||||
long utcTimestamp = utcTime.toEpochSecond();
|
||||
|
||||
if (this.dataLn < 0 || this.dataLn > 2) {
|
||||
// last 2000 points of data, regardless the timescale
|
||||
data = lastStationDataDao.getLastStationData(station.getSystemName());
|
||||
}
|
||||
else if (dataLn == 0) {
|
||||
// 12 hours
|
||||
data = stationDataDao.getLastStationData(station.getSystemName(), utcTimestamp - twelve_hours, utcTimestamp);
|
||||
}
|
||||
else if (dataLn == 1) {
|
||||
// 24 hours
|
||||
data = stationDataDao.getLastStationData(station.getSystemName(), utcTimestamp - twenty_four_hours, utcTimestamp);
|
||||
}
|
||||
else if (dataLn == 2) {
|
||||
// 3 days
|
||||
data = stationDataDao.getLastStationData(station.getSystemName(), utcTimestamp - three_days, utcTimestamp);
|
||||
}
|
||||
|
||||
valuesHumidity = new ArrayList<>();
|
||||
|
||||
if (data != null) {
|
||||
for (StationData d : data.list_of_station_data) {
|
||||
valuesHumidity.add(new Entry(d.epoch * 1000, d.humidity));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param from
|
||||
* @param to
|
||||
* @param index_or_timestamp if set to false 'to' and 'from' are treated as an index, if they are set
|
||||
* to true this method will use it as epoch timestamps (in seconds)
|
||||
*/
|
||||
public void setData(long from, long to, boolean index_or_timestamp) {
|
||||
|
||||
// if only some part of input set needs to be displayed use this intermediate buffer
|
||||
ArrayList<Entry> narrowed_set, narrowed_set_gusts;
|
||||
|
||||
// data set to be displayed on the plot
|
||||
LineDataSet set_humidity;
|
||||
|
||||
|
||||
if (valuesHumidity.size() > 0) {
|
||||
|
||||
if (from != 0 || to != 0) {
|
||||
|
||||
// if 'from' and 'to' are the index values
|
||||
if (!index_or_timestamp) {
|
||||
// make a sublist
|
||||
narrowed_set = new ArrayList<>(valuesHumidity.subList((int)from, (int)to));
|
||||
|
||||
}
|
||||
else {
|
||||
// get first and last entry from the set
|
||||
Entry first = valuesHumidity.get(0);
|
||||
Entry last = valuesHumidity.get(valuesHumidity.size() - 1 );
|
||||
|
||||
// check if 'from' and 'to' timestamp epoch covers any data from the input set
|
||||
if ( (long)first.getX() > (to * 1000) ||
|
||||
(long)last.getX() < (from * 1000)) {
|
||||
|
||||
// if there is no data to display exit from an function
|
||||
return;
|
||||
}
|
||||
else {
|
||||
narrowed_set = new ArrayList<>();
|
||||
narrowed_set_gusts = new ArrayList<>();
|
||||
|
||||
// if not copy matching elements to narrowed set
|
||||
valuesHumidity.forEach((Entry e) -> {
|
||||
if (e.getX() > (from * 1000) &&
|
||||
e.getX() < (to * 1000)) {
|
||||
narrowed_set.add(e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// and generate the set from it
|
||||
set_humidity = new LineDataSet(narrowed_set, "Humidity");
|
||||
}
|
||||
else {
|
||||
// use 'values_wind_speed' directly as a whole
|
||||
set_humidity = new LineDataSet(valuesHumidity, "Humidity");
|
||||
}
|
||||
|
||||
// create a dataset and give it a type
|
||||
set_humidity.setAxisDependency(YAxis.AxisDependency.LEFT);
|
||||
set_humidity.setColor(ColorTemplate.getHoloBlue());
|
||||
set_humidity.setValueTextColor(ColorTemplate.getHoloBlue());
|
||||
set_humidity.setLineWidth(3.5f);
|
||||
set_humidity.setDrawCircles(true);
|
||||
set_humidity.setDrawValues(true);
|
||||
set_humidity.setFillAlpha(65);
|
||||
set_humidity.setFillColor(ColorTemplate.getHoloBlue());
|
||||
set_humidity.setHighLightColor(Color.rgb(244, 117, 117));
|
||||
set_humidity.setDrawCircleHole(false);
|
||||
|
||||
// create a data object with the data sets
|
||||
LineData line_data = new LineData();
|
||||
line_data.addDataSet(set_humidity);
|
||||
line_data.setValueTextColor(Color.WHITE);
|
||||
line_data.setValueTextSize(9f);
|
||||
|
||||
// set data
|
||||
chart.setData(line_data);
|
||||
chart.setDoubleTapToZoomEnabled(false);
|
||||
chart.setOnChartValueSelectedListener(plotClickEvent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
@ -21,18 +23,20 @@ import org.threeten.bp.ZoneId;
|
|||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationData;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsTemperature extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
|
@ -69,10 +73,10 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
// and then shift to the user timezone for convinient display
|
||||
ZonedDateTime localDateTime = utcDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault());
|
||||
|
||||
// format only the time to keep X axis clean
|
||||
String dt = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(localDateTime);
|
||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm");
|
||||
|
||||
return dt;
|
||||
/* format only the time to keep X axis clean */
|
||||
return fmt.format(localDateTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,6 +96,8 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
// utc timestamp
|
||||
long utcTimestamp = utcTime.toEpochSecond();
|
||||
|
||||
Logger.debug("[station.getSystemName() = " + station.getSystemName() +"]");
|
||||
|
||||
if (this.dataLn < 0 || this.dataLn > 2) {
|
||||
// last 2000 points of data, regardless the timescale
|
||||
data = lastStationDataDao.getLastStationData(station.getSystemName());
|
||||
|
@ -110,6 +116,9 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
}
|
||||
|
||||
if (data instanceof ListOfStationData) {
|
||||
|
||||
Logger.debug("[data.list_of_station_data.length = " + data.list_of_station_data.length +"]");
|
||||
|
||||
for (StationData d : data.list_of_station_data) {
|
||||
valuesTemperature.add(new Entry(d.epoch * 1000, d.temperature));
|
||||
}
|
||||
|
@ -137,7 +146,7 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
// use wind speed label (on the left) to display the temperature
|
||||
if (this.textViewSpeed != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewSpeed.setText(getString(R.string.temperature) + String.format(": %.1f°C", temperature));
|
||||
this.textViewSpeed.setText(getString(R.string.temperature) + String.format(": %.1f°C", temperature).replace(',', '.'));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
@ -242,14 +251,26 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// this activity layout is common for all plots
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
// get data length for this plot
|
||||
dataLn = (int)getIntent().getExtras().get("data_ln");
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
Logger.info("[StationDetailsPlotsTemperature][onCreate][station.getSystemName() = " + station.getSystemName() +"][dataLn = " + dataLn +"]");
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[StationDetailsPlotsHumidity][onCreate][AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
// this activity layout is common for all plots
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
// exit from the function if station object hasn't been added to the intent
|
||||
if (station == null) {
|
||||
return;
|
||||
|
@ -289,10 +310,13 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
xAxis.setTextColor(Color.WHITE);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
xAxis.setDrawGridLines(true);
|
||||
xAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
xAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setGranularity(1f); // one hour
|
||||
xAxis.setValueFormatter(new StationDetailsPlotsTemperature.ValueFormatter());
|
||||
xAxis.setTextSize(123.0f);
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setLabelRotationAngle(45.0f);
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
|
||||
|
@ -303,7 +327,8 @@ public class StationDetailsPlotsTemperature extends AppCompatActivity implements
|
|||
leftAxis.setAxisMinimum(-30.0f);
|
||||
leftAxis.setAxisMaximum(40.0f);
|
||||
leftAxis.setYOffset(0.0f);
|
||||
leftAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
leftAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
leftAxis.setTextSize(123.0f);
|
||||
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setEnabled(false);
|
|
@ -1,7 +1,9 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
|
@ -22,19 +24,20 @@ import org.threeten.bp.ZoneId;
|
|||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.pogodacc.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.pogodacc.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationData;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.PlotClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.dao.LastStationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.dao.StationDataDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationData;
|
||||
|
||||
public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, StationDetailsPlot {
|
||||
|
||||
|
@ -76,10 +79,10 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
// and then shift to the user timezone for convinient display
|
||||
ZonedDateTime localDateTime = utcDateTime.atZone(ZoneOffset.UTC).withZoneSameInstant(ZoneId.systemDefault());
|
||||
|
||||
// format only the time to keep X axis clean
|
||||
String dt = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).format(localDateTime);
|
||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm");
|
||||
|
||||
return dt;
|
||||
/* format only the time to keep X axis clean */
|
||||
return fmt.format(localDateTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -96,13 +99,26 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
int lastDataIndex = 0;
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
// get data length for this plot
|
||||
dataLn = (int)getIntent().getExtras().get("data_ln");
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
Logger.info("[station.getSystemName() = " + station.getSystemName() +"][dataLn = " + dataLn +"]");
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_station_details_plots);
|
||||
|
||||
// download data from web service
|
||||
this.downloadDataFromWebservice();
|
||||
|
||||
|
@ -137,10 +153,14 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
xAxis.setTextColor(Color.WHITE);
|
||||
xAxis.setDrawAxisLine(false);
|
||||
xAxis.setDrawGridLines(true);
|
||||
xAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
xAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setGranularity(1f); // one hour
|
||||
xAxis.setValueFormatter(new ValueFormatter());
|
||||
xAxis.setLabelRotationAngle(45.0f);
|
||||
xAxis.setTextSize(123.0f);
|
||||
xAxis.setCenterAxisLabels(true);
|
||||
xAxis.setLabelRotationAngle(45.0f);
|
||||
|
||||
YAxis leftAxis = chart.getAxisLeft();
|
||||
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
|
||||
|
@ -151,7 +171,8 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
leftAxis.setAxisMinimum(0.0f);
|
||||
leftAxis.setAxisMaximum(this.findMaxValueForPlotScale());
|
||||
leftAxis.setYOffset(0.0f);
|
||||
leftAxis.setTextColor(Color.rgb(255, 192, 56));
|
||||
leftAxis.setTextColor(R.color.design_default_color_primary_dark);
|
||||
leftAxis.setTextSize(123.0f);
|
||||
|
||||
YAxis rightAxis = chart.getAxisRight();
|
||||
rightAxis.setEnabled(false);
|
||||
|
@ -197,6 +218,8 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
// utc timestamp
|
||||
long utcTimestamp = utcTime.toEpochSecond();
|
||||
|
||||
Logger.debug("[station.getSystemName() = " + station.getSystemName() +"]");
|
||||
|
||||
if (this.dataLn < 0 || this.dataLn > 2) {
|
||||
// last 2000 points of data, regardless the timescale
|
||||
data = lastStationDataDao.getLastStationData(station.getSystemName());
|
||||
|
@ -218,6 +241,9 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
valuesWindGusts = new ArrayList<>();
|
||||
|
||||
if (data instanceof ListOfStationData) {
|
||||
|
||||
Logger.debug("[data.list_of_station_data.length = " + data.list_of_station_data.length +"]");
|
||||
|
||||
for (StationData d : data.list_of_station_data) {
|
||||
valuesWindSpeed.add(new Entry(d.epoch * 1000, d.windspeed));
|
||||
valuesWindGusts.add(new Entry(d.epoch * 1000, d.windgusts));
|
||||
|
@ -263,8 +289,8 @@ public class StationDetailsPlotsWind extends AppCompatActivity implements SeekBa
|
|||
|
||||
if (this.textViewGusts != null && this.textViewSpeed != null && this.textViewTimestamp != null) {
|
||||
this.textViewTimestamp.setText(date);
|
||||
this.textViewSpeed.setText(getString(R.string.mean_value_short) + String.format(": %.1f%s", mean, unit));
|
||||
this.textViewGusts.setText(getString(R.string.wind_gust_short) + String.format(": %.1f%s", gusts, unit));
|
||||
this.textViewSpeed.setText(getString(R.string.mean_value_short) + String.format(": %.1f%s", mean, unit).replace(',', '.'));
|
||||
this.textViewGusts.setText(getString(R.string.wind_gust_short) + String.format(": %.1f%s", gusts, unit).replace(',', '.'));
|
||||
}
|
||||
else {
|
||||
return;
|
|
@ -0,0 +1,163 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.util.TypedValue;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.Main;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.StationDetailsValuesOnActivityFromFavsUpdater;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.StationDetailsValuesOnActivityUpdater;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.thread.StationSummaryUpdaterThread;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.dao.SummaryDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationSummaryActElements;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
public class StationDetailsSummaryActivity extends AppCompatActivity {
|
||||
|
||||
StationSummaryActElements elems = null;
|
||||
|
||||
WeatherStation station = null;
|
||||
|
||||
StationSummaryUpdaterThread updaterThread = null;
|
||||
|
||||
StationDetailsValuesOnActivityUpdater valuesOnActUpdater = null;
|
||||
|
||||
StationDetailsValuesOnActivityFromFavsUpdater valuesFromFavsSummaryUpdater = null;
|
||||
|
||||
Handler handler = null;
|
||||
|
||||
Main main = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
main = (Main)getApplication();
|
||||
|
||||
elems = new StationSummaryActElements();
|
||||
|
||||
int color = main.getThemeColours().colorOnSecondary;
|
||||
|
||||
Summary summary = null;
|
||||
SummaryDao summary_dao = new SummaryDao();
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
Logger.info("[station.getSystemName() = " + station.getSystemName() +"]");
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_station_details_summary);
|
||||
|
||||
elems.title = findViewById(R.id.textViewStationDetailsSummaryTitle);
|
||||
elems.title.setText(station.getDisplayedName());
|
||||
|
||||
if (station.getDisplayedName().length() < 18) {
|
||||
elems.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 38);
|
||||
}
|
||||
else {
|
||||
elems.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);
|
||||
}
|
||||
|
||||
elems.wind_dir_val = findViewById(R.id.textViewWinddirValue);
|
||||
elems.wind_gusts_val = findViewById(R.id.textViewWindGustsValue);
|
||||
elems.wind_speed_val = findViewById(R.id.textViewWindSpeedValue);
|
||||
elems.temperature_val = findViewById(R.id.textViewTemperatureValue);
|
||||
elems.qnh_val = findViewById(R.id.textViewQnhVaue);
|
||||
elems.humidity_val = findViewById(R.id.textViewHumidityValue);
|
||||
elems.message = findViewById(R.id.textViewSummaryMessage);
|
||||
|
||||
elems.goodColor = color;
|
||||
elems.badColor = Color.RED;
|
||||
|
||||
// create a handler to update station data in background
|
||||
handler = new Handler();
|
||||
|
||||
// check if this station is on favourites list
|
||||
boolean onFavs = main.checkIsOnFavsList(station.getSystemName());
|
||||
|
||||
if (onFavs) {
|
||||
valuesFromFavsSummaryUpdater = new StationDetailsValuesOnActivityFromFavsUpdater(elems, handler, station, main.getHashmapFavStationSystemNameToSummary());
|
||||
|
||||
if (handler != null && valuesFromFavsSummaryUpdater != null) {
|
||||
handler.post(valuesFromFavsSummaryUpdater);
|
||||
}
|
||||
}
|
||||
else {
|
||||
updaterThread = new StationSummaryUpdaterThread(station.getSystemName());
|
||||
|
||||
// create a copy of updater class for this station
|
||||
valuesOnActUpdater = new StationDetailsValuesOnActivityUpdater(elems, handler, updaterThread, station);
|
||||
|
||||
if (handler != null && valuesOnActUpdater != null) {
|
||||
updaterThread.start(50);
|
||||
|
||||
handler.postDelayed(valuesOnActUpdater, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (updaterThread != null) {
|
||||
updaterThread.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (updaterThread != null) {
|
||||
updaterThread.start(50);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
|
||||
if (handler != null && valuesOnActUpdater != null) {
|
||||
handler.removeCallbacks(valuesOnActUpdater);
|
||||
}
|
||||
|
||||
if (updaterThread != null) {
|
||||
updaterThread.stop();
|
||||
}
|
||||
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
|
||||
if (updaterThread != null) {
|
||||
updaterThread.stop();
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.Main;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.StationDetailsValuesOnActivityFromFavsUpdater;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.StationDetailsValuesOnActivityUpdater;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.thread.StationSummaryUpdaterThread;
|
||||
import cc.pogoda.mobile.meteosystem.dao.SummaryDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationWindRoseActElements;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
public class StationDetailsWindRoseActivity extends AppCompatActivity {
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
Summary summary;
|
||||
|
||||
StationSummaryUpdaterThread updaterThread = null;
|
||||
|
||||
StationDetailsValuesOnActivityUpdater onActivityUpdater = null;
|
||||
|
||||
StationDetailsValuesOnActivityFromFavsUpdater fromSummaryUpdater = null;
|
||||
|
||||
Handler handler = null;
|
||||
|
||||
StationWindRoseActElements elements;
|
||||
|
||||
Main main = null;
|
||||
|
||||
public StationDetailsWindRoseActivity() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_station_details_wind_rose);
|
||||
|
||||
station = (WeatherStation) getIntent().getSerializableExtra("station");
|
||||
|
||||
Logger.info("[station.getSystemName() = " + station.getSystemName() +"]");
|
||||
|
||||
main = (Main)getApplication();
|
||||
|
||||
// find all elements in the xml layout file and set the references in a holding object
|
||||
elements = new StationWindRoseActElements();
|
||||
elements.windArrow = findViewById(R.id.imageViewWindRoseArrow);
|
||||
elements.windSpeed = findViewById(R.id.textViewWindRoseWindSpeedValue);
|
||||
elements.windGusts = findViewById(R.id.textViewWindRoseWindGustsValue);
|
||||
elements.windDirection = findViewById(R.id.textViewWindRoseWindDirectionValue);
|
||||
elements.temperature = findViewById(R.id.textViewWindRoseTemperaturaValue);
|
||||
elements.maxGust = findViewById(R.id.textViewWindRoseMaxHourGust);
|
||||
elements.minAverage = findViewById(R.id.textViewWindRoseMinHourSpeed);
|
||||
elements.pressure = findViewById(R.id.textViewWindRosePressure);
|
||||
elements.goodColor = ((Main) getApplication()).getThemeColours().colorOnSecondary;
|
||||
elements.badColor = Color.RED;
|
||||
elements.setActivity(this);
|
||||
|
||||
// create the handler which will update the screen in background
|
||||
handler = new Handler();
|
||||
|
||||
SummaryDao summary_dao = new SummaryDao();
|
||||
|
||||
handler = new Handler();
|
||||
|
||||
// check if this station is on favourites list
|
||||
boolean onFavs = main.checkIsOnFavsList(station.getSystemName());
|
||||
|
||||
if (onFavs) {
|
||||
fromSummaryUpdater = new StationDetailsValuesOnActivityFromFavsUpdater(elements, handler, station, main.getHashmapFavStationSystemNameToSummary());
|
||||
|
||||
if (handler != null && fromSummaryUpdater != null) {
|
||||
handler.post(fromSummaryUpdater);
|
||||
}
|
||||
}
|
||||
else {
|
||||
updaterThread = new StationSummaryUpdaterThread(station.getSystemName());
|
||||
|
||||
onActivityUpdater = new StationDetailsValuesOnActivityUpdater(elements, handler, updaterThread, station);
|
||||
|
||||
if (handler != null && onActivityUpdater != null) {
|
||||
updaterThread.start(50);
|
||||
|
||||
// start the handler to update the wind rose activity in background
|
||||
handler.postDelayed(onActivityUpdater, 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (updaterThread != null) {
|
||||
updaterThread.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (updaterThread != null && updaterThread.isEnabled() == false) {
|
||||
updaterThread.start(50);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
|
||||
// remove and stop background callback
|
||||
if (handler != null && onActivityUpdater != null) {
|
||||
handler.removeCallbacks(onActivityUpdater);
|
||||
}
|
||||
|
||||
if (updaterThread != null) {
|
||||
updaterThread.stop();
|
||||
}
|
||||
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (updaterThread != null) {
|
||||
updaterThread.stop();
|
||||
}
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity;
|
||||
package cc.pogoda.mobile.meteosystem.activity;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
@ -8,18 +10,19 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import androidx.navigation.NavArgument;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.NavDirections;
|
||||
import androidx.navigation.NavGraph;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.navigation.fragment.NavHostFragment;
|
||||
import androidx.navigation.ui.AppBarConfiguration;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.trend.pressure.PressureTrendFragment;
|
||||
import cc.pogoda.mobile.pogodacc.activity.trend.pressure.PressureTrendFragmentArgs;
|
||||
import cc.pogoda.mobile.pogodacc.activity.trend.pressure.PressureTrendFragmentDirections;
|
||||
import cc.pogoda.mobile.pogodacc.activity.trend.temperature.TemperatureTrendFragmentDirections;
|
||||
import cc.pogoda.mobile.pogodacc.activity.trend.wind.WindTrendFragmentDirections;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.trend.pressure.PressureTrendFragmentDirections;
|
||||
import cc.pogoda.mobile.meteosystem.activity.trend.temperature.TemperatureTrendFragmentDirections;
|
||||
import cc.pogoda.mobile.meteosystem.activity.trend.wind.WindTrendFragmentDirections;
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
|
||||
public class TrendActivity extends AppCompatActivity {
|
||||
|
||||
|
@ -33,15 +36,24 @@ public class TrendActivity extends AppCompatActivity {
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String stationName = (String)getIntent().getExtras().get("station");
|
||||
setContentView(R.layout.activity_trend);
|
||||
|
||||
NavArgument.Builder builder = new NavArgument.Builder();
|
||||
|
||||
if (AppConfiguration.locale != null && !AppConfiguration.locale.equals("default") ) {
|
||||
Logger.debug("[AppConfiguration.locale = " + AppConfiguration.locale + "]");
|
||||
Locale locale = new Locale(AppConfiguration.locale);
|
||||
Locale.setDefault(locale);
|
||||
Resources resources = this.getResources();
|
||||
Configuration config = resources.getConfiguration();
|
||||
config.setLocale(locale);
|
||||
resources.updateConfiguration(config, resources.getDisplayMetrics());
|
||||
}
|
||||
|
||||
this.station = stationName;
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("station", stationName);
|
||||
|
||||
this.station = stationName;
|
||||
setContentView(R.layout.activity_trend);
|
||||
|
||||
NavArgument.Builder builder = new NavArgument.Builder();
|
||||
|
||||
BottomNavigationView navView = findViewById(R.id.nav_view);
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
|
@ -55,20 +67,8 @@ public class TrendActivity extends AppCompatActivity {
|
|||
NavDirections wind = WindTrendFragmentDirections.actionNavigationWindToNavigationTemperature(stationName);
|
||||
NavDirections pressure = PressureTrendFragmentDirections.actionNavigationPressureToNavigationWind(stationName);
|
||||
|
||||
//NavHostFragment.create(R.navigation.mobile_navigation, bundle);
|
||||
|
||||
// NavGraph navGraph = navController.getNavInflater().inflate(R.navigation.mobile_navigation);
|
||||
// builder.setDefaultValue(stationName);
|
||||
// navGraph.addArgument("station", builder.build());
|
||||
// navController.setGraph(navGraph, bundle);
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||
NavigationUI.setupWithNavController(navView, navController);
|
||||
//navController.navigate(temperature);
|
||||
//
|
||||
// NavArgument.Builder builder = new NavArgument.Builder();
|
||||
// builder.setDefaultValue(stationName);
|
||||
// navGraph.addArgument("station", builder.build());
|
||||
// navController.setGraph(navGraph);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class AllStationsActRecyclerViewButtonClickEvent implements View.OnClickListener {
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
AppCompatActivity p;
|
||||
|
||||
Intent intent;
|
||||
|
||||
ParceableFavsCallReason.Reason reason;
|
||||
|
||||
public AllStationsActRecyclerViewButtonClickEvent(WeatherStation wx, AppCompatActivity parent, ParceableFavsCallReason.Reason r) {
|
||||
station = wx;
|
||||
p = parent;
|
||||
reason = r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (reason == null || reason == ParceableFavsCallReason.Reason.FAVOURITES || reason == ParceableFavsCallReason.Reason.ALL_STATIONS) {
|
||||
intent = new Intent(p, StationDetailsActivity.class);
|
||||
intent.putExtra("station", station);
|
||||
|
||||
p.startActivity(intent);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (reason == ParceableFavsCallReason.Reason.EXPORT_SELECT) {
|
||||
|
||||
EventBus.getDefault().post(station);
|
||||
|
||||
p.setResult(Activity.RESULT_OK);
|
||||
|
||||
p.finish();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +1,26 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.AllStationsActivity;
|
||||
import cc.pogoda.mobile.meteosystem.activity.AllStationsActivity;
|
||||
import cc.pogoda.mobile.meteosystem.activity.MainActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableStationsList;
|
||||
|
||||
public class MainActImageButtonAllStationsClickEvent implements View.OnClickListener {
|
||||
|
||||
AppCompatActivity parent;
|
||||
|
||||
MainActivity parent;
|
||||
Intent intent;
|
||||
|
||||
public MainActImageButtonAllStationsClickEvent(AppCompatActivity parent) {
|
||||
public MainActImageButtonAllStationsClickEvent(MainActivity parent) {
|
||||
this.parent = parent;
|
||||
|
||||
intent = new Intent(this.parent, AllStationsActivity.class);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
launchActivity();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private void launchActivity() {
|
||||
parent.startActivity(intent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.ExportDataActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableStationsList;
|
||||
|
||||
public class MainActImageButtonExportClickEvent implements View.OnClickListener{
|
||||
|
||||
AppCompatActivity parent;
|
||||
|
||||
Intent intent;
|
||||
|
||||
public MainActImageButtonExportClickEvent(AppCompatActivity p) {
|
||||
parent = p;
|
||||
|
||||
intent = new Intent(this.parent, ExportDataActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
||||
Logger.info("[onClick]");
|
||||
|
||||
parent.startActivity(intent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.FavouritesActivity;
|
||||
import cc.pogoda.mobile.meteosystem.activity.MainActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableStationsList;
|
||||
|
||||
public class MainActImageButtonFavouritesClickEvent implements View.OnClickListener{
|
||||
|
||||
MainActivity parent;
|
||||
|
||||
Intent intent;
|
||||
|
||||
public MainActImageButtonFavouritesClickEvent(MainActivity parent) {
|
||||
this.parent = parent;
|
||||
|
||||
intent = new Intent(this.parent, FavouritesActivity.class);
|
||||
|
||||
ParceableFavsCallReason callReason = new ParceableFavsCallReason(ParceableFavsCallReason.Reason.FAVOURITES);
|
||||
intent.putExtra("callReason", callReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
parent.startActivity(intent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.SettingsActivity;
|
||||
import cc.pogoda.mobile.meteosystem.file.ConfigurationFile;
|
||||
|
||||
public class MainActImageButtonSettingsClickEvent implements View.OnClickListener {
|
||||
|
||||
AppCompatActivity parent;
|
||||
|
||||
Intent intent;
|
||||
|
||||
public MainActImageButtonSettingsClickEvent(AppCompatActivity _parent, ConfigurationFile _configuration_file) {
|
||||
parent = _parent;
|
||||
|
||||
intent = new Intent(parent, SettingsActivity.class);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
parent.startActivity(intent);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
|
@ -13,7 +13,7 @@ import org.threeten.bp.format.FormatStyle;
|
|||
|
||||
import java.util.Date;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.StationDetailsPlot;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationDetailsPlot;
|
||||
|
||||
public class PlotClickEvent implements OnChartValueSelectedListener {
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsPlotsHumidity;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActHumidityPlotButtonClickEvent implements View.OnClickListener {
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
AppCompatActivity p;
|
||||
|
||||
Intent intent;
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
intent = new Intent(p, StationDetailsPlotsHumidity.class);
|
||||
intent.putExtra("station", station);
|
||||
intent.putExtra("data_ln", (int)p.getIntent().getExtras().get("data_ln"));
|
||||
|
||||
p.startActivity(intent);
|
||||
}
|
||||
|
||||
public StationDetailsActHumidityPlotButtonClickEvent(WeatherStation wx, AppCompatActivity parent) {
|
||||
station = wx;
|
||||
p = parent;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsActivity;
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsSummaryActivity;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsSummaryActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActSummaryButtonClickEvent implements View.OnClickListener {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsTemperature;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsPlotsTemperature;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActTemperaturePlotButtonClickEvent implements View.OnClickListener {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.TrendActivity;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.activity.TrendActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActTrendButtonClickEvent implements View.OnClickListener {
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsDirection;
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsTemperature;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsPlotsDirection;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActWindDirectionPlotsButtonClickEvent implements View.OnClickListener {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsWindRoseActivity;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsWindRoseActivity;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActWindRoseButtonClickEvent implements View.OnClickListener {
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.handler;
|
||||
package cc.pogoda.mobile.meteosystem.activity.handler;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.StationDetailsPlotsWind;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.activity.StationDetailsPlotsWind;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationDetailsActWindSpeedPlotsButtonClickEvent implements View.OnClickListener {
|
||||
|
|
@ -1,21 +1,20 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.trend.pressure;
|
||||
package cc.pogoda.mobile.meteosystem.activity.trend.pressure;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.TrendActivity;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.TrendActivity;
|
||||
|
||||
public class PressureTrendFragment extends Fragment {
|
||||
|
||||
|
@ -53,7 +52,15 @@ public class PressureTrendFragment extends Fragment {
|
|||
eightHours = root.findViewById(R.id.textViewPressureTrendEightHoursVal);
|
||||
|
||||
pressureTrendViewModel.getStationName().observe(getViewLifecycleOwner(), s -> {
|
||||
if (s.length() < 18) {
|
||||
stationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 38);
|
||||
}
|
||||
else {
|
||||
stationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 28);
|
||||
}
|
||||
|
||||
stationName.setText(s);
|
||||
|
||||
});
|
||||
|
||||
pressureTrendViewModel.getLastMeasuremenetTime().observe(getViewLifecycleOwner(), s -> {
|
|
@ -1,18 +1,16 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.trend.pressure;
|
||||
package cc.pogoda.mobile.meteosystem.activity.trend.pressure;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.dao.TrendDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Trend;
|
||||
import cc.pogoda.mobile.meteosystem.dao.TrendDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Trend;
|
||||
|
||||
public class PressureTrendViewModel extends ViewModel {
|
||||
|
||||
|
@ -51,11 +49,11 @@ public class PressureTrendViewModel extends ViewModel {
|
|||
stationName.postValue(trend.displayed_name);
|
||||
|
||||
if (!trend.current_qnh_qf.equals("NOT_AVALIABLE") && !trend.current_qnh_qf.equals("NO_DATA")) {
|
||||
currentValue.postValue(String.format("%.1f hPa", trend.pressure_trend.current_value));
|
||||
twoHoursValue.postValue(String.format("%.1f hPa", trend.pressure_trend.two_hours_value));
|
||||
fourHoursValue.postValue(String.format("%.1f hPa", trend.pressure_trend.four_hours_value));
|
||||
sixHoursValue.postValue(String.format("%.1f hPa", trend.pressure_trend.six_hours_value));
|
||||
eightHoursValue.postValue(String.format("%.1f hPa", trend.pressure_trend.eight_hours_value));
|
||||
currentValue.postValue(String.format("%shPa", trend.pressure_trend.getCurrentVal(true, true)));
|
||||
twoHoursValue.postValue(String.format("%shPa", trend.pressure_trend.getTwoHoursVal(true, true)));
|
||||
fourHoursValue.postValue(String.format("%shPa", trend.pressure_trend.getFourHoursVal(true, true)));
|
||||
sixHoursValue.postValue(String.format("%shPa", trend.pressure_trend.getSixHoursVal(true, true)));
|
||||
eightHoursValue.postValue(String.format("%shPa", trend.pressure_trend.getEightHoursVal(true, true)));
|
||||
}
|
||||
else {
|
||||
currentValue.postValue("-- hPa");
|
|
@ -1,23 +1,20 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.trend.temperature;
|
||||
package cc.pogoda.mobile.meteosystem.activity.trend.temperature;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.TrendActivity;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.TrendActivity;
|
||||
|
||||
public class TemperatureTrendFragment extends Fragment {
|
||||
|
||||
|
@ -72,6 +69,14 @@ public class TemperatureTrendFragment extends Fragment {
|
|||
textViewTemperatureTrendEightHoursHVal = root.findViewById(R.id.textViewTemperatureTrendEightHoursHVal);
|
||||
|
||||
temperatureTrendViewModel.getDisplayedStationName().observe(getViewLifecycleOwner(), s -> {
|
||||
|
||||
if (s.length() < 18) {
|
||||
textViewTemperatureTrendStationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 38);
|
||||
}
|
||||
else {
|
||||
textViewTemperatureTrendStationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 28);
|
||||
}
|
||||
|
||||
textViewTemperatureTrendStationName.setText(s);
|
||||
});
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.trend.temperature;
|
||||
package cc.pogoda.mobile.meteosystem.activity.trend.temperature;
|
||||
|
||||
import androidx.lifecycle.LiveData;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
|
@ -9,8 +8,8 @@ import org.threeten.bp.ZoneOffset;
|
|||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.dao.TrendDao;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Trend;
|
||||
import cc.pogoda.mobile.meteosystem.dao.TrendDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Trend;
|
||||
|
||||
public class TemperatureTrendViewModel extends ViewModel {
|
||||
|
||||
|
@ -118,11 +117,11 @@ public class TemperatureTrendViewModel extends ViewModel {
|
|||
if (!trend.current_humidity_qf.equals("NOT_AVALIABLE") && !trend.current_humidity_qf.equals("NO_DATA")) {
|
||||
|
||||
|
||||
currentHumidityValue.postValue(String.format("%.1f %%", trend.humidity_trend.current_value));
|
||||
twoHoursHumidityValue.postValue(String.format("%.1f %%", trend.humidity_trend.two_hours_value));
|
||||
fourHoursHumidityValue.postValue(String.format("%.1f %%", trend.humidity_trend.four_hours_value));
|
||||
sixHoursHumidityValue.postValue(String.format("%.1f %%", trend.humidity_trend.six_hours_value));
|
||||
eightHoursHumidityValue.postValue(String.format("%.1f %%", trend.humidity_trend.eight_hours_value));
|
||||
currentHumidityValue.postValue(String.format("%s%%", trend.humidity_trend.getCurrentVal(true, true)));
|
||||
twoHoursHumidityValue.postValue(String.format("%s%%", trend.humidity_trend.getTwoHoursVal(true, true)));
|
||||
fourHoursHumidityValue.postValue(String.format("%s%%", trend.humidity_trend.getFourHoursVal(true, true)));
|
||||
sixHoursHumidityValue.postValue(String.format("%s%%", trend.humidity_trend.getSixHoursVal(true, true)));
|
||||
eightHoursHumidityValue.postValue(String.format("%s%%", trend.humidity_trend.getEightHoursVal(true, true)));
|
||||
}
|
||||
else {
|
||||
|
||||
|
@ -136,11 +135,11 @@ public class TemperatureTrendViewModel extends ViewModel {
|
|||
}
|
||||
|
||||
if (!trend.current_temperature_qf.equals("NOT_AVALIABLE") && !trend.current_temperature_qf.equals("NO_DATA")) {
|
||||
currentTemperatureValue.postValue(String.format("%.1f °C", trend.temperature_trend.current_value));
|
||||
twoHoursTemperatureValue.postValue(String.format("%.1f °C", trend.temperature_trend.two_hours_value));
|
||||
fourHoursTemperatureValue.postValue(String.format("%.1f °C", trend.temperature_trend.four_hours_value));
|
||||
sixHoursTemperatureValue.postValue(String.format("%.1f °C", trend.temperature_trend.six_hours_value));
|
||||
eightHoursTemperatureValue.postValue(String.format("%.1f °C", trend.temperature_trend.eight_hours_value));
|
||||
currentTemperatureValue.postValue(String.format("%s°C", trend.temperature_trend.getCurrentVal(true, false)));
|
||||
twoHoursTemperatureValue.postValue(String.format("%s°C", trend.temperature_trend.getTwoHoursVal(true, false)));
|
||||
fourHoursTemperatureValue.postValue(String.format("%s°C", trend.temperature_trend.getFourHoursVal(true, false)));
|
||||
sixHoursTemperatureValue.postValue(String.format("%s°C", trend.temperature_trend.getSixHoursVal(true, false)));
|
||||
eightHoursTemperatureValue.postValue(String.format("%s°C", trend.temperature_trend.getEightHoursVal(true, false)));
|
||||
}
|
||||
else {
|
||||
currentTemperatureValue.postValue("-- °C");
|
|
@ -1,8 +1,9 @@
|
|||
package cc.pogoda.mobile.pogodacc.activity.trend.wind;
|
||||
package cc.pogoda.mobile.meteosystem.activity.trend.wind;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -12,8 +13,8 @@ import androidx.annotation.NonNull;
|
|||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.activity.TrendActivity;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.TrendActivity;
|
||||
|
||||
public class WindTrendFragment extends Fragment {
|
||||
|
||||
|
@ -64,6 +65,13 @@ public class WindTrendFragment extends Fragment {
|
|||
textViewWindTrendEightHoursGustsVal = root.findViewById(R.id.textViewTemperatureTrendEightHoursHVal);
|
||||
|
||||
windTrendViewModel.getDisplayedStationName().observe(getViewLifecycleOwner(), s -> {
|
||||
if (s.length() < 18) {
|
||||
textViewWindTrendStationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 38);
|
||||
}
|
||||
else {
|
||||
textViewWindTrendStationName.setTextSize(TypedValue.COMPLEX_UNIT_SP, 28);
|
||||
}
|
||||
|
||||
textViewWindTrendStationName.setText(s);
|
||||
});
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.trend.wind;
|
||||
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.format.FormatStyle;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.dao.TrendDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Trend;
|
||||
|
||||
public class WindTrendViewModel extends ViewModel {
|
||||
|
||||
public void setStation(String station) {
|
||||
this.station = station;
|
||||
}
|
||||
|
||||
private String station = "";
|
||||
|
||||
private TrendDao trendDao;
|
||||
|
||||
private MutableLiveData<String> displayedStationName;
|
||||
private MutableLiveData<String> lastMeasuremenetTime;
|
||||
|
||||
private MutableLiveData<String> currentMeanValue;
|
||||
private MutableLiveData<String> twoHoursMeanValue;
|
||||
private MutableLiveData<String> fourHoursMeanValue;
|
||||
private MutableLiveData<String> sixHoursMeanValue;
|
||||
private MutableLiveData<String> eightHoursMeanValue;
|
||||
|
||||
private MutableLiveData<String> currentGustValue;
|
||||
private MutableLiveData<String> twoHoursGustValue;
|
||||
private MutableLiveData<String> fourHoursGustValue;
|
||||
private MutableLiveData<String> sixHoursGustValue;
|
||||
private MutableLiveData<String> eightHoursGustValue;
|
||||
|
||||
public MutableLiveData<String> getDisplayedStationName() {
|
||||
return displayedStationName;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getLastMeasuremenetTime() {
|
||||
return lastMeasuremenetTime;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getCurrentMeanValue() {
|
||||
return currentMeanValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getTwoHoursMeanValue() {
|
||||
return twoHoursMeanValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getFourHoursMeanValue() {
|
||||
return fourHoursMeanValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getSixHoursMeanValue() {
|
||||
return sixHoursMeanValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getEightHoursMeanValue() {
|
||||
return eightHoursMeanValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getCurrentGustValue() {
|
||||
return currentGustValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getTwoHoursGustValue() {
|
||||
return twoHoursGustValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getFourHoursGustValue() {
|
||||
return fourHoursGustValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getSixHoursGustValue() {
|
||||
return sixHoursGustValue;
|
||||
}
|
||||
|
||||
public MutableLiveData<String> getEightHoursGustValue() {
|
||||
return eightHoursGustValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public WindTrendViewModel() {
|
||||
trendDao = new TrendDao();
|
||||
|
||||
displayedStationName = new MutableLiveData<String>();
|
||||
lastMeasuremenetTime = new MutableLiveData<String>();
|
||||
|
||||
currentMeanValue = new MutableLiveData<String>();
|
||||
twoHoursMeanValue = new MutableLiveData<String>();
|
||||
fourHoursMeanValue = new MutableLiveData<String>();
|
||||
sixHoursMeanValue = new MutableLiveData<String>();
|
||||
eightHoursMeanValue = new MutableLiveData<String>();
|
||||
|
||||
currentGustValue = new MutableLiveData<String>();
|
||||
twoHoursGustValue = new MutableLiveData<String>();
|
||||
fourHoursGustValue = new MutableLiveData<String>();
|
||||
sixHoursGustValue = new MutableLiveData<String>();
|
||||
eightHoursGustValue = new MutableLiveData<String>();
|
||||
|
||||
}
|
||||
|
||||
public boolean updateData() {
|
||||
if (station != null && station.length() > 0) {
|
||||
Trend trend = trendDao.getStationTrend(station);
|
||||
|
||||
if (trend != null) {
|
||||
|
||||
// format the time and date according to current locale
|
||||
String dt = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT).format(LocalDateTime.ofEpochSecond(trend.last_timestamp, 0, ZoneOffset.UTC).atOffset(ZoneOffset.UTC).atZoneSameInstant(ZoneOffset.systemDefault()));
|
||||
|
||||
lastMeasuremenetTime.postValue(dt);
|
||||
displayedStationName.postValue(trend.displayed_name);
|
||||
|
||||
if (!trend.current_wind_qf.equals("NOT_AVALIABLE") && !trend.current_wind_qf.equals("NO_DATA")) {
|
||||
currentMeanValue.postValue(String.format("%sm/s", trend.average_wind_speed_trend.getCurrentVal(true, false)));
|
||||
twoHoursMeanValue.postValue(String.format("%sm/s", trend.average_wind_speed_trend.getTwoHoursVal(true, false)));
|
||||
fourHoursMeanValue.postValue(String.format("%sm/s", trend.average_wind_speed_trend.getFourHoursVal(true, false)));
|
||||
sixHoursMeanValue.postValue(String.format("%sm/s", trend.average_wind_speed_trend.getSixHoursVal(true, false)));
|
||||
eightHoursMeanValue.postValue(String.format("%sm/s", trend.average_wind_speed_trend.getEightHoursVal(true, false)));
|
||||
|
||||
currentGustValue.postValue(String.format("%sm/s", trend.maximum_wind_speed_trend.getCurrentVal(true, false)));
|
||||
twoHoursGustValue.postValue(String.format("%sm/s", trend.maximum_wind_speed_trend.getTwoHoursVal(true, false)));
|
||||
fourHoursGustValue.postValue(String.format("%sm/s", trend.maximum_wind_speed_trend.getFourHoursVal(true, false)));
|
||||
sixHoursGustValue.postValue(String.format("%sm/s", trend.maximum_wind_speed_trend.getSixHoursVal(true, false)));
|
||||
eightHoursGustValue.postValue(String.format("%sm/s", trend.maximum_wind_speed_trend.getEightHoursVal(true, false)));
|
||||
|
||||
// if (AppConfiguration.replaceMsWithKnots) {
|
||||
// // if knots
|
||||
// currentMeanValue.postValue(String.format("%.0f kts", trend.average_wind_speed_trend.current_value));
|
||||
// twoHoursMeanValue.postValue(String.format("%.0f kts", trend.average_wind_speed_trend.two_hours_value));
|
||||
// fourHoursMeanValue.postValue(String.format("%.0f kts", trend.average_wind_speed_trend.four_hours_value));
|
||||
// sixHoursMeanValue.postValue(String.format("%.0f kts", trend.average_wind_speed_trend.six_hours_value));
|
||||
// eightHoursMeanValue.postValue(String.format("%.0f kts", trend.average_wind_speed_trend.eight_hours_value));
|
||||
//
|
||||
// currentGustValue.postValue(String.format("%.0f kts", trend.maximum_wind_speed_trend.current_value));
|
||||
// twoHoursGustValue.postValue(String.format("%.0f kts", trend.maximum_wind_speed_trend.two_hours_value));
|
||||
// fourHoursGustValue.postValue(String.format("%.0f kts", trend.maximum_wind_speed_trend.four_hours_value));
|
||||
// sixHoursGustValue.postValue(String.format("%.0f kts", trend.maximum_wind_speed_trend.six_hours_value));
|
||||
// eightHoursGustValue.postValue(String.format("%.0f kts", trend.maximum_wind_speed_trend.eight_hours_value));
|
||||
// } else {
|
||||
// // if meters per second
|
||||
// currentMeanValue.postValue(String.format("%.1f m/s", trend.average_wind_speed_trend.current_value));
|
||||
// twoHoursMeanValue.postValue(String.format("%.1f m/s", trend.average_wind_speed_trend.two_hours_value));
|
||||
// fourHoursMeanValue.postValue(String.format("%.1f m/s", trend.average_wind_speed_trend.four_hours_value));
|
||||
// sixHoursMeanValue.postValue(String.format("%.1f m/s", trend.average_wind_speed_trend.six_hours_value));
|
||||
// eightHoursMeanValue.postValue(String.format("%.1f m/s", trend.average_wind_speed_trend.eight_hours_value));
|
||||
//
|
||||
// currentGustValue.postValue(String.format("%.1f m/s", trend.maximum_wind_speed_trend.current_value));
|
||||
// twoHoursGustValue.postValue(String.format("%.1f m/s", trend.maximum_wind_speed_trend.two_hours_value));
|
||||
// fourHoursGustValue.postValue(String.format("%.1f m/s", trend.maximum_wind_speed_trend.four_hours_value));
|
||||
// sixHoursGustValue.postValue(String.format("%.1f m/s", trend.maximum_wind_speed_trend.six_hours_value));
|
||||
// eightHoursGustValue.postValue(String.format("%.1f m/s", trend.maximum_wind_speed_trend.eight_hours_value));
|
||||
// }
|
||||
} else {
|
||||
currentMeanValue.postValue("--");
|
||||
twoHoursMeanValue.postValue("--");
|
||||
fourHoursMeanValue.postValue("--");
|
||||
sixHoursMeanValue.postValue("--");
|
||||
eightHoursMeanValue.postValue("--");
|
||||
|
||||
currentGustValue.postValue("--");
|
||||
twoHoursGustValue.postValue("--");
|
||||
fourHoursGustValue.postValue("--");
|
||||
sixHoursGustValue.postValue("--");
|
||||
eightHoursGustValue.postValue("--");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
currentMeanValue.postValue("--");
|
||||
twoHoursMeanValue.postValue("--");
|
||||
fourHoursMeanValue.postValue("--");
|
||||
sixHoursMeanValue.postValue("--");
|
||||
eightHoursMeanValue.postValue("--");
|
||||
|
||||
currentGustValue.postValue("--");
|
||||
twoHoursGustValue.postValue("--");
|
||||
fourHoursGustValue.postValue("--");
|
||||
sixHoursGustValue.postValue("--");
|
||||
eightHoursGustValue.postValue("--");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.updater;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.DETAILS_ON_FAVS_LIST_DEFAULT_UPDATE;
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.DETAILS_ON_FAVS_LIST_REUPDATE;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Vector;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.thread.FavouritesStationSummaryUpdaterThread;
|
||||
import cc.pogoda.mobile.meteosystem.dao.AvailableParametersDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.meteosystem.type.ThemeColours;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.AvailableParametersWeb;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
/**
|
||||
* This class is used to update entries (TextView) on Favourites list using HashMap
|
||||
* which is updated by {@link FavouritesStationSummaryUpdaterThread}
|
||||
*/
|
||||
public class FavouritesStationDetailsOnListUpdater implements Runnable {
|
||||
|
||||
/**
|
||||
* Handler is used by Android to put a Runnable into MessageQueue handler by the Looper. This
|
||||
* runnable can be scheduled to be serviced at certain point of time
|
||||
*/
|
||||
private Handler handler;
|
||||
|
||||
/**
|
||||
* A collection which holds
|
||||
*/
|
||||
private HashMap<String, TextView> stationsToUpdate;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
//private AvailableParametersDao availableParametersDao = null;
|
||||
private HashMap<String, AvailableParameters> availParams;
|
||||
|
||||
/**
|
||||
* This map comes from 'Main' class and it is shared with @link{{@link FavouritesStationSummaryUpdaterThread}}
|
||||
*/
|
||||
HashMap<String, Summary> stationNameSummary = null;
|
||||
|
||||
/**
|
||||
* Not sure if this is really required but just to be sure that updater won't be started
|
||||
* after the activity had been torn down.
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Used everywhere, where a colour of any element is set programatically (not globally from the theme)
|
||||
*/
|
||||
private ThemeColours themeColours;
|
||||
|
||||
public FavouritesStationDetailsOnListUpdater(Handler _handler, HashMap<String, Summary> _station_system_name_to_summary, HashMap<String, AvailableParameters> _avail_params, ThemeColours _themeColours) {
|
||||
handler = _handler;
|
||||
stationsToUpdate = new HashMap<>();
|
||||
availParams = _avail_params;
|
||||
stationNameSummary = _station_system_name_to_summary;
|
||||
themeColours = _themeColours;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public void addNewStation(String _station_system_name, TextView _tv) {
|
||||
stationsToUpdate.put(_station_system_name, _tv);
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceAsColor")
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
int nextExecutionDelay = DETAILS_ON_FAVS_LIST_DEFAULT_UPDATE;
|
||||
|
||||
if (stationNameSummary != null && enabled && stationsToUpdate != null && stationsToUpdate.size() > 0) {
|
||||
|
||||
// get a set of all elements stored in the map
|
||||
Set<Map.Entry<String, TextView>> entries = stationsToUpdate.entrySet();
|
||||
|
||||
// create something iterable from the set. the set itself doesn't guarantee the same order than
|
||||
// objects were put in, but in this case it isn't a problem.
|
||||
Vector<Map.Entry<String, TextView>> vectorOfEntries = new Vector<>(entries);
|
||||
|
||||
for (Map.Entry<String, TextView> e : vectorOfEntries) {
|
||||
|
||||
// extract data from pair
|
||||
String stationSystemName = e.getKey();
|
||||
TextView toUpdate = e.getValue();
|
||||
|
||||
// query web service for station data
|
||||
Summary summary = stationNameSummary.get(stationSystemName);
|
||||
|
||||
// query for available parameters
|
||||
AvailableParameters params = availParams.get(stationSystemName);
|
||||
|
||||
// if data has been collected
|
||||
if (summary != null && params != null) {
|
||||
Logger.debug("[stationSystemName = " + stationSystemName +"][summary.last_timestamp = " + summary.last_timestamp +"]");
|
||||
|
||||
String str;
|
||||
|
||||
// check if this station transmits wind information
|
||||
if (params.windSpeed) {
|
||||
|
||||
// check if station transmits humidity
|
||||
if (params.humidity) {
|
||||
str = String.format("%s %d%% %s %s max %s", summary.getTemperatureStr(false, true), summary.humidity, summary.getWindDirStr(), summary.getWindspeedStr(false), summary.getWindgustsStr(false));
|
||||
}
|
||||
else {
|
||||
str = String.format("%s %s %s max %s", summary.getTemperatureStr(false, true), summary.getWindDirStr(), summary.getWindspeedStr(false), summary.getWindgustsStr(false));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (params.humidity) {
|
||||
str = String.format("%s %d%%", summary.getTemperatureStr(false, true), summary.humidity);
|
||||
}
|
||||
else {
|
||||
str = String.format("%s", summary.getTemperatureStr(false, true));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// update text view on the favourites list
|
||||
toUpdate.setText(str);
|
||||
|
||||
if ( (params.humidity && summary.humidity_qf_native.equals(QualityFactor.NOT_AVALIABLE)) ||
|
||||
(summary.temperature_qf_native.equals(QualityFactor.NOT_AVALIABLE)) ||
|
||||
(params.windSpeed && summary.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)))
|
||||
{
|
||||
toUpdate.setTextColor(Color.RED);
|
||||
}
|
||||
else {
|
||||
toUpdate.setTextColor(themeColours.colorPrimary);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger.error("[stationSystemName = " + stationSystemName + "][summary object is null!! Maybe the API responds exceptionally slow?]");
|
||||
nextExecutionDelay = DETAILS_ON_FAVS_LIST_REUPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
handler.postDelayed(this, nextExecutionDelay);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.updater;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.web.StationBackgroundDownloader;
|
||||
|
||||
public class StationBackgroundImageUpdater implements Runnable{
|
||||
ImageView iv;
|
||||
|
||||
TextView station_name;
|
||||
WeatherStation station;
|
||||
StationBackgroundDownloader downloader;
|
||||
|
||||
Handler handler;
|
||||
|
||||
public StationBackgroundImageUpdater(ImageView _background, TextView _station_name, WeatherStation _station, StationBackgroundDownloader _downloader, Handler _handler) {
|
||||
iv = _background;
|
||||
station = _station;
|
||||
station_name = _station_name;
|
||||
downloader = _downloader;
|
||||
handler = _handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
Bitmap bitmap = downloader.getBitmap();
|
||||
|
||||
if (bitmap != null) {
|
||||
station_name.setTextColor(station.getStationNameTextColor());
|
||||
station_name.setText(station.getDisplayedName());
|
||||
|
||||
iv.setImageBitmap(bitmap);
|
||||
}
|
||||
else {
|
||||
handler.postDelayed(this, 200);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.updater;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.NORMAL_UPDATE_VALUES_ON_ACTIVITY;
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.thread.FavouritesStationSummaryUpdaterThread;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationActivityElements;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
/**
|
||||
* This class uses external HashMap updated by @link{{@link FavouritesStationSummaryUpdaterThread}}
|
||||
*/
|
||||
public class StationDetailsValuesOnActivityFromFavsUpdater implements Runnable {
|
||||
|
||||
HashMap<String, Summary> mapWithSummary;
|
||||
|
||||
StationActivityElements elementsToUpdate;
|
||||
|
||||
Handler handler;
|
||||
|
||||
WeatherStation stationToUpdate;
|
||||
|
||||
public StationDetailsValuesOnActivityFromFavsUpdater(StationActivityElements elems, Handler h, WeatherStation station, HashMap<String, Summary> _map_with_summary_data) {
|
||||
stationToUpdate = station;
|
||||
handler = h;
|
||||
elementsToUpdate = elems;
|
||||
mapWithSummary = _map_with_summary_data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (mapWithSummary != null && elementsToUpdate != null) {
|
||||
|
||||
Logger.info("[stationToUpdate.getSystemName() = " + stationToUpdate.getSystemName() +"]");
|
||||
|
||||
Summary summary = mapWithSummary.get(stationToUpdate.getSystemName());
|
||||
|
||||
if (summary != null) {
|
||||
elementsToUpdate.updateFromSummary(summary, stationToUpdate.getAvailableParameters());
|
||||
handler.postDelayed(this, NORMAL_UPDATE_VALUES_ON_ACTIVITY);
|
||||
}
|
||||
else {
|
||||
handler.postDelayed(this, REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.updater;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.NORMAL_UPDATE_VALUES_ON_ACTIVITY;
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.thread.StationSummaryUpdaterThread;
|
||||
import cc.pogoda.mobile.meteosystem.dao.SummaryDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.StationActivityElements;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class used to update the content of StationDetailsSummaryActivity and
|
||||
* StationDetailsWindRoseActivity
|
||||
*/
|
||||
public class StationDetailsValuesOnActivityUpdater implements Runnable {
|
||||
|
||||
StationActivityElements elements = null;
|
||||
|
||||
Handler handler = null;
|
||||
|
||||
SummaryDao dao = null;
|
||||
|
||||
StationSummaryUpdaterThread updater_thread;
|
||||
|
||||
Summary station_summary = null;
|
||||
|
||||
String station_name;
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
public StationDetailsValuesOnActivityUpdater(StationActivityElements elems, Handler h, StationSummaryUpdaterThread updaterThread, WeatherStation station) {
|
||||
elements = elems;
|
||||
handler = h;
|
||||
updater_thread = updaterThread;
|
||||
this.station_name = station.getSystemName();
|
||||
this.station = station;
|
||||
|
||||
dao = new SummaryDao();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (elements == null || updater_thread == null) {
|
||||
Logger.error("[something is null even if it shouldn't!!!!]");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// get the current data from the Web Service
|
||||
station_summary = updater_thread.getSummary();
|
||||
|
||||
Logger.debug("[station_name = " + station_name +"]");
|
||||
|
||||
if (station_summary != null) {
|
||||
// null check is done inside this call
|
||||
elements.updateFromSummary(station_summary, station.getAvailableParameters());
|
||||
handler.postDelayed(this, NORMAL_UPDATE_VALUES_ON_ACTIVITY);
|
||||
}
|
||||
else {
|
||||
// 'station_summary' might be null if internet connection is poor and background
|
||||
// thread wasn't able to download a summary on time
|
||||
handler.postDelayed(this, REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.updater.thread;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.telephony.SubscriptionManager;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.dao.AvailableParametersDao;
|
||||
import cc.pogoda.mobile.meteosystem.dao.SummaryDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.AvailableParametersWeb;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
/**
|
||||
* This class is a runnable executed from background Thread by ScheduledExecuter
|
||||
* which periodically download current Summary for all stations stored on favourites list
|
||||
*/
|
||||
public class FavouritesStationSummaryUpdaterThread implements Runnable {
|
||||
|
||||
private HashMap<String, Summary> map;
|
||||
|
||||
private HashMap<String, AvailableParameters> availableParametersHashMap;
|
||||
|
||||
private SummaryDao summaryDao;
|
||||
|
||||
private AvailableParametersDao availableParametersDao;
|
||||
|
||||
private ScheduledExecutorService executor;
|
||||
|
||||
private ScheduledFuture scheduledTask;
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Set to true when a update is forced in case of a removal or adding new entry to the map
|
||||
*/
|
||||
private boolean forceUpdate = false;
|
||||
|
||||
public FavouritesStationSummaryUpdaterThread(HashMap<String, Summary> _out_map, HashMap<String, AvailableParameters> _avail_params_map) {
|
||||
map = _out_map;
|
||||
availableParametersHashMap = _avail_params_map;
|
||||
|
||||
summaryDao = new SummaryDao();
|
||||
availableParametersDao = new AvailableParametersDao();
|
||||
|
||||
executor = Executors.newScheduledThreadPool(5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// check if map was set so something
|
||||
if (map != null && map.size() > 0) {
|
||||
|
||||
Logger.info("[map.size() = " + map.size() +"]");
|
||||
|
||||
// get a set of all stations from favourites
|
||||
Set<Map.Entry<String, Summary>> _set_of_stations_names = map.entrySet();
|
||||
|
||||
// get an iterator to the set
|
||||
Iterator<Map.Entry<String, Summary>> it = _set_of_stations_names.iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
// get currently processed entry
|
||||
Map.Entry<String, Summary> entry = it.next();
|
||||
|
||||
// get station name
|
||||
String station_name = entry.getKey();
|
||||
|
||||
Summary summary = summaryDao.getStationSummary(station_name);
|
||||
|
||||
// check if summary was returned (as it will not in case on HTTP 500 or something else)
|
||||
if (summary != null) {
|
||||
Logger.info("[station_name = " + station_name + "][summary.last_timestamp = " + summary.last_timestamp + "]");
|
||||
|
||||
// put the summary back into the map
|
||||
map.put(station_name, summary);
|
||||
}
|
||||
|
||||
AvailableParameters parameters = AvailableParameters.fromWebData(availableParametersDao.getAvaliableParamsByStationName(station_name));
|
||||
|
||||
if (parameters != null) {
|
||||
availableParametersHashMap.put(station_name, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
// no station to update may be caused by two reasons
|
||||
// 1. there is no weather station to update
|
||||
// 2. API responds very slow or there is a problem with internet connection
|
||||
Logger.info("[no station to update]");
|
||||
|
||||
stop();
|
||||
start(REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL);
|
||||
}
|
||||
|
||||
if (forceUpdate) {
|
||||
forceUpdate = false;
|
||||
|
||||
start(66000);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateImmediately() {
|
||||
forceUpdate = true;
|
||||
stop();
|
||||
|
||||
Thread t = new Thread(this);
|
||||
t.start();
|
||||
}
|
||||
|
||||
public void start(int _initial_delay) {
|
||||
|
||||
Logger.debug("[_initial_delay = " + _initial_delay +"]");
|
||||
|
||||
if (enabled) {
|
||||
stop();
|
||||
}
|
||||
|
||||
scheduledTask = executor.scheduleAtFixedRate(this, _initial_delay, 123000, TimeUnit.MILLISECONDS);
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (enabled) {
|
||||
scheduledTask.cancel(true);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.updater.thread;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.ConstAppConfiguration.REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.dao.SummaryDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
/**
|
||||
* This class is simmilar to {@link FavouritesStationSummaryUpdaterThread}, but it
|
||||
* downloads summary data for any defined weather station
|
||||
*/
|
||||
public class StationSummaryUpdaterThread implements Runnable {
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
boolean enabled = false;
|
||||
|
||||
@NonNull
|
||||
String systemName;
|
||||
|
||||
ScheduledExecutorService executorService;
|
||||
|
||||
ScheduledFuture scheduledTask;
|
||||
|
||||
Summary summary = null;
|
||||
|
||||
public Summary getSummary() {
|
||||
return summary;
|
||||
}
|
||||
|
||||
public StationSummaryUpdaterThread(@NonNull String stationSystemName) {
|
||||
systemName = stationSystemName;
|
||||
|
||||
executorService = Executors.newScheduledThreadPool(3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (systemName != null) {
|
||||
Logger.info("[StationSummaryUpdaterThread][run][systemName = " + systemName +"]");
|
||||
|
||||
SummaryDao summaryDao = new SummaryDao();
|
||||
|
||||
summary = summaryDao.getStationSummary(systemName);
|
||||
|
||||
if (summary == null) {
|
||||
// no ssummary data may be caused by two reasons
|
||||
// 1. there is no weather station to update
|
||||
// 2. API responds very slow or there is a problem with internet connection
|
||||
Logger.info("[no station to update]");
|
||||
|
||||
stop();
|
||||
start(REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void start(int _initial_delay) {
|
||||
|
||||
Logger.info("[_initial_delay = " + _initial_delay +"]");
|
||||
|
||||
if (enabled) {
|
||||
stop();
|
||||
}
|
||||
|
||||
scheduledTask = executorService.scheduleAtFixedRate(this, _initial_delay, 60000, TimeUnit.MILLISECONDS);
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (enabled) {
|
||||
Logger.info("[systemName = " + systemName +"]");
|
||||
scheduledTask.cancel(true);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package cc.pogoda.mobile.meteosystem.activity.view;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
|
||||
public class AllStationsActRecyclerViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView textView;
|
||||
public Button button;
|
||||
public TextView textViewData;
|
||||
|
||||
public AllStationsActRecyclerViewHolder(@NonNull View itemView, ParceableFavsCallReason.Reason callReason) {
|
||||
super(itemView);
|
||||
|
||||
if (callReason.equals(ParceableFavsCallReason.Reason.EXPORT_SELECT) || callReason.equals(ParceableFavsCallReason.Reason.ALL_STATIONS)) {
|
||||
textView = itemView.findViewById(R.id.station_name);
|
||||
button = itemView.findViewById(R.id.station_button);
|
||||
textViewData = null;
|
||||
}
|
||||
else {
|
||||
textView = itemView.findViewById(R.id.station_name_fav);
|
||||
button = itemView.findViewById(R.id.station_button_fav);
|
||||
textViewData = itemView.findViewById(R.id.station_data_fav);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package cc.pogoda.mobile.meteosystem.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.Main;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.activity.handler.AllStationsActRecyclerViewButtonClickEvent;
|
||||
import cc.pogoda.mobile.meteosystem.activity.updater.FavouritesStationDetailsOnListUpdater;
|
||||
import cc.pogoda.mobile.meteosystem.activity.view.AllStationsActRecyclerViewHolder;
|
||||
import cc.pogoda.mobile.meteosystem.type.ParceableFavsCallReason;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class WeatherStationRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
final private List<WeatherStation> stations;
|
||||
|
||||
AppCompatActivity activity;
|
||||
|
||||
ParceableFavsCallReason.Reason reason;
|
||||
|
||||
/**
|
||||
* This updater takes data stored in the hashmap and then updates TextViews on View Holders on
|
||||
* Favourites list
|
||||
*/
|
||||
private FavouritesStationDetailsOnListUpdater favsUpdater = null;
|
||||
|
||||
Handler handler = null;
|
||||
|
||||
/**
|
||||
* This instance of 'Main' singleton class is used to obtain HashMap<String, Summary> stationSystemNameToSummary
|
||||
*/
|
||||
Main main;
|
||||
|
||||
private static final int VIEW_TYPE_EMPTY_LIST = 0;
|
||||
private static final int VIEW_TYPE_OBJECT = 1;
|
||||
|
||||
public WeatherStationRecyclerViewAdapter(
|
||||
List<WeatherStation> stations,
|
||||
AppCompatActivity parentActivity,
|
||||
ParceableFavsCallReason.Reason callReason) {
|
||||
this.stations = stations;
|
||||
this.activity = parentActivity;
|
||||
this.reason = callReason;
|
||||
this.main = (Main) parentActivity.getApplication();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
Context context = parent.getContext();
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
View view;
|
||||
|
||||
switch (viewType){
|
||||
case VIEW_TYPE_OBJECT:
|
||||
// check the call reason
|
||||
if (reason.equals(ParceableFavsCallReason.Reason.FAVOURITES)) {
|
||||
// inflate custom layout
|
||||
view = inflater.inflate(R.layout.activity_favourites_linear_layout_data,
|
||||
parent, false);
|
||||
}
|
||||
else {
|
||||
// Inflate the custom layout without current data
|
||||
view = inflater.inflate(R.layout.activity_all_stations_linear_layout,
|
||||
parent, false);
|
||||
}
|
||||
return new AllStationsActRecyclerViewHolder(view, reason);
|
||||
|
||||
case VIEW_TYPE_EMPTY_LIST:
|
||||
default:
|
||||
if (reason.equals(ParceableFavsCallReason.Reason.FAVOURITES)) {
|
||||
view = inflater.inflate(R.layout.activity_favourites_empty, parent,
|
||||
false);
|
||||
} else {
|
||||
view = inflater.inflate(R.layout.activity_all_stations_empty, parent,
|
||||
false);
|
||||
}
|
||||
return new EmptyViewHolder(view);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
if (stations.isEmpty()) {
|
||||
return VIEW_TYPE_EMPTY_LIST;
|
||||
} else {
|
||||
return VIEW_TYPE_OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
|
||||
|
||||
if(viewHolder instanceof AllStationsActRecyclerViewHolder) {
|
||||
AllStationsActRecyclerViewHolder holder =
|
||||
(AllStationsActRecyclerViewHolder) viewHolder;
|
||||
|
||||
// this TextView shows the station name
|
||||
TextView textView = holder.textView;
|
||||
|
||||
// this TextView shows station data if this is favourites list
|
||||
TextView textViewData = holder.textViewData;
|
||||
|
||||
// button to go to the StationDetailsActivity
|
||||
Button button = holder.button;
|
||||
|
||||
// get the station object from a list of either all stations or favourites
|
||||
WeatherStation station = stations.get(position);
|
||||
|
||||
if (station != null) {
|
||||
textView.setText(station.getDisplayedName());
|
||||
button.setText(R.string.select_station);
|
||||
|
||||
if (station.getDisplayedName().length() > 22) {
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20.0f);
|
||||
} else {
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 22.0f);
|
||||
}
|
||||
|
||||
button.setOnClickListener(new AllStationsActRecyclerViewButtonClickEvent(station, activity, reason));
|
||||
}
|
||||
|
||||
// this if distinguish between All Stations and Favorites view
|
||||
if (textViewData != null && favsUpdater != null) {
|
||||
|
||||
favsUpdater.addNewStation(station.getSystemName(), textViewData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update(@NonNull List<WeatherStation> updatedStations) {
|
||||
stations.clear();
|
||||
stations.addAll(updatedStations);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
// In case of empty station list at least 1 should be returned to properly select view type
|
||||
// and render empty list info.
|
||||
return stations.isEmpty() ? 1 : stations.size();
|
||||
}
|
||||
|
||||
public void createAndStartUpdater() {
|
||||
|
||||
// check if there is previous instance of updater
|
||||
if (favsUpdater != null && favsUpdater.isEnabled()) {
|
||||
stopUpdater();
|
||||
}
|
||||
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
favsUpdater = new FavouritesStationDetailsOnListUpdater(
|
||||
handler,
|
||||
main.getHashmapFavStationSystemNameToSummary(),
|
||||
main.getHashmapAllStationSystemNameToAvailParameters(),
|
||||
main.getThemeColours());
|
||||
|
||||
handler.postDelayed(favsUpdater, 100);
|
||||
favsUpdater.setEnabled(true);
|
||||
}
|
||||
|
||||
public void stopUpdater() {
|
||||
if (reason.equals(ParceableFavsCallReason.Reason.FAVOURITES)
|
||||
&& handler != null && favsUpdater != null) {
|
||||
handler.removeCallbacks(favsUpdater);
|
||||
favsUpdater.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class EmptyViewHolder extends RecyclerView.ViewHolder{
|
||||
|
||||
public EmptyViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package cc.pogoda.mobile.meteosystem.config;
|
||||
|
||||
public class AppConfiguration {
|
||||
|
||||
public static boolean replaceMsWithKnots = false;
|
||||
|
||||
public static String locale = "default";
|
||||
|
||||
public static int decimationPeriod = 0;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package cc.pogoda.mobile.meteosystem.config;
|
||||
|
||||
public class ConstAppConfiguration {
|
||||
|
||||
public static final int REUPDATE_VALUES_ON_ACTIVITY_ON_FAIL = 1000;
|
||||
|
||||
public static final int NORMAL_UPDATE_VALUES_ON_ACTIVITY = 60000;
|
||||
|
||||
/**
|
||||
* This is an interval how often labels on Favourites List (with station
|
||||
* summary) are updated.
|
||||
*/
|
||||
public static final int DETAILS_ON_FAVS_LIST_REUPDATE = 500;
|
||||
|
||||
public static final int DETAILS_ON_FAVS_LIST_DEFAULT_UPDATE = 45000;
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package cc.pogoda.mobile.meteosystem.config;
|
||||
|
||||
public class WebIoConfig {
|
||||
|
||||
public static final int TIMEOUT_SECOND = 20;
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
package cc.pogoda.mobile.pogodacc.dao;
|
||||
package cc.pogoda.mobile.meteosystem.dao;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.WebIoConfig.TIMEOUT_SECOND;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfAllStations;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationDefinition;
|
||||
import cc.pogoda.mobile.pogodacc.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.pogodacc.web.StationListConsumer;
|
||||
import cc.pogoda.mobile.meteosystem.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfAllStations;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationDefinition;
|
||||
import cc.pogoda.mobile.meteosystem.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.meteosystem.web.StationListConsumer;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class AllStationsDao {
|
||||
|
@ -30,6 +34,7 @@ public class AllStationsDao {
|
|||
try {
|
||||
resp = consumer.getAllStations().execute();
|
||||
} catch (Exception e) {
|
||||
Logger.error("[Exception][e = " + e.getLocalizedMessage() +"]");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +71,9 @@ public class AllStationsDao {
|
|||
elem.setStationNameTextColor(def.stationNameTextColour);
|
||||
elem.setImageAlign(def.backgroundJpgAlign);
|
||||
elem.setMoreInfo(def.moreInfo);
|
||||
elem.setTimezone(def.timezone);
|
||||
elem.setCallsignSsid(def.callsign, def.ssid);
|
||||
|
||||
|
||||
AvailableParameters availableParameters = AvailableParameters.fromStation(def);
|
||||
elem.setAvailableParameters(availableParameters);
|
|
@ -0,0 +1,77 @@
|
|||
package cc.pogoda.mobile.meteosystem.dao;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.WebIoConfig.TIMEOUT_SECOND;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.web.AvailableParametersWeb;
|
||||
import cc.pogoda.mobile.meteosystem.web.AvailableParametersConsumer;
|
||||
import cc.pogoda.mobile.meteosystem.web.RestClientConfig;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class AvailableParametersDao {
|
||||
|
||||
RestClientConfig restClient;
|
||||
|
||||
Response<AvailableParametersWeb> response = null;
|
||||
|
||||
String stationName;
|
||||
|
||||
class Worker implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
restClient = new RestClientConfig();
|
||||
|
||||
AvailableParametersConsumer consumer = restClient.getWeatherStationClient().create(AvailableParametersConsumer.class);
|
||||
|
||||
try {
|
||||
response = consumer.getParametersForStation(stationName).execute();
|
||||
} catch (IOException e) {
|
||||
Logger.error("[IOException][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
} catch (RuntimeException e) {
|
||||
Logger.error("[RuntimeException][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Logger.error("[Exception][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
Logger.error("[worker is done, response is null]");
|
||||
}
|
||||
else {
|
||||
Logger.info("[worker is done][response.code() = " + response.code() +"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AvailableParametersWeb getAvaliableParamsByStationName(String name) {
|
||||
AvailableParametersWeb out = null;
|
||||
|
||||
stationName = name;
|
||||
|
||||
Thread t = new Thread(new Worker());
|
||||
|
||||
t.start();
|
||||
|
||||
try {
|
||||
t.join();
|
||||
|
||||
if (response != null) {
|
||||
out = response.body();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
package cc.pogoda.mobile.pogodacc.dao;
|
||||
package cc.pogoda.mobile.meteosystem.dao;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.web.LastStationDataConsumer;
|
||||
import cc.pogoda.mobile.pogodacc.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.pogodacc.web.StationListConsumer;
|
||||
import static cc.pogoda.mobile.meteosystem.config.WebIoConfig.TIMEOUT_SECOND;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.web.LastStationDataConsumer;
|
||||
import cc.pogoda.mobile.meteosystem.web.RestClientConfig;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class LastStationDataDao {
|
||||
|
@ -24,6 +27,8 @@ public class LastStationDataDao {
|
|||
try {
|
||||
response = consumer.getLastDataForStation(station, true, true).execute();
|
||||
} catch (Exception e) {
|
||||
Logger.error("[Exception][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
package cc.pogoda.mobile.pogodacc.dao;
|
||||
package cc.pogoda.mobile.meteosystem.dao;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.pogodacc.web.LastStationDataConsumer;
|
||||
import cc.pogoda.mobile.pogodacc.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.pogodacc.web.StationDataConsumer;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.meteosystem.web.StationDataConsumer;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class StationDataDao {
|
||||
|
@ -27,6 +28,8 @@ public class StationDataDao {
|
|||
try {
|
||||
response = consumer.getDataForStation(station, from, to).execute();
|
||||
} catch (Exception e) {
|
||||
Logger.error("[Exception][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +52,9 @@ public class StationDataDao {
|
|||
thread.start();
|
||||
thread.join();
|
||||
|
||||
out = response.body();
|
||||
if (response != null) {
|
||||
out = response.body();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
package cc.pogoda.mobile.pogodacc.dao;
|
||||
package cc.pogoda.mobile.meteosystem.dao;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.WebIoConfig.TIMEOUT_SECOND;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Summary;
|
||||
import cc.pogoda.mobile.pogodacc.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.pogodacc.web.SummaryConsumer;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
import cc.pogoda.mobile.meteosystem.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.meteosystem.web.SummaryConsumer;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
|
@ -30,9 +34,29 @@ public class SummaryDao {
|
|||
SummaryConsumer consumer = restClient.getWeatherStationClient().create(SummaryConsumer.class);
|
||||
|
||||
try {
|
||||
Logger.info("[station = " + station +"]");
|
||||
|
||||
response = consumer.getSummaryForStation(station).execute();
|
||||
} catch (IOException e) {
|
||||
Logger.error("[station = " + station + "][IOException][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
} catch (RuntimeException e) {
|
||||
Logger.error("[station = " + station + "][RuntimeException][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (Exception e) {
|
||||
Logger.error("[station = " + station + "][Exception][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
Logger.error("[station = " + station + "][worker is done, response is null]");
|
||||
}
|
||||
else {
|
||||
Logger.info("[station = " + station + "][worker is done][response.code() = " + response.code() +"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,9 +87,17 @@ public class SummaryDao {
|
|||
out.humidity_qf_native = QualityFactor.valueOf(out.humidity_qf);
|
||||
out.qnh_qf_native = QualityFactor.valueOf(out.qnh_qf);
|
||||
}
|
||||
else {
|
||||
Logger.error("[station = " + station +"][response.code() = " + response.code() +"][response body is nulll, probably HTTP error" +
|
||||
"]");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Logger.error("[station = " + station +"][response is null!!]");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
Logger.error("[station = " + station +"][InterruptedException]");
|
||||
}
|
||||
|
||||
return out;
|
|
@ -1,14 +1,17 @@
|
|||
package cc.pogoda.mobile.pogodacc.dao;
|
||||
package cc.pogoda.mobile.meteosystem.dao;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.WebIoConfig.TIMEOUT_SECOND;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Trend;
|
||||
import cc.pogoda.mobile.pogodacc.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.pogodacc.web.TrendConsumer;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Trend;
|
||||
import cc.pogoda.mobile.meteosystem.web.RestClientConfig;
|
||||
import cc.pogoda.mobile.meteosystem.web.TrendConsumer;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class TrendDao {
|
||||
RestClientConfig restClient;
|
||||
|
||||
Response<Trend> trend;
|
||||
|
||||
|
@ -16,6 +19,8 @@ public class TrendDao {
|
|||
|
||||
class Worker implements Runnable {
|
||||
|
||||
RestClientConfig restClient;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
|
@ -27,7 +32,9 @@ public class TrendDao {
|
|||
trend = trendConsumer.getTrendForStation(station).execute();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.error("[TrendDao][Worker][Exception][e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,10 +50,15 @@ public class TrendDao {
|
|||
try {
|
||||
thread.join();
|
||||
|
||||
out = trend.body();
|
||||
if (trend != null) {
|
||||
out = trend.body();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package cc.pogoda.mobile.pogodacc.dao.mock;
|
||||
package cc.pogoda.mobile.meteosystem.dao.mock;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class AllStationsDaoMock {
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package cc.pogoda.mobile.meteosystem.file;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
|
||||
public class ConfigurationFile {
|
||||
|
||||
FileNames fileNames;
|
||||
|
||||
public ConfigurationFile(Context context) {
|
||||
fileNames = new FileNames(context);
|
||||
}
|
||||
|
||||
public void restoreFromFile() {
|
||||
|
||||
File file = fileNames.getAppConfigurationFile();
|
||||
|
||||
// create an input stream to load file content
|
||||
FileInputStream fns = null;
|
||||
try {
|
||||
fns = new FileInputStream(file);
|
||||
InputStreamReader streamReader = new InputStreamReader(fns);
|
||||
|
||||
// create a place fo JSON content
|
||||
char buffer[] = new char[(int) file.length()];
|
||||
|
||||
// read the content of file
|
||||
streamReader.read(buffer);
|
||||
|
||||
streamReader.close();
|
||||
|
||||
JSONObject mainObject = new JSONObject(String.valueOf(buffer));
|
||||
|
||||
AppConfiguration.replaceMsWithKnots = mainObject.getBoolean("replaceMsWithKnots");
|
||||
AppConfiguration.locale = mainObject.getString("locale");
|
||||
AppConfiguration.decimationPeriod = mainObject.getInt("decimationPeriodMinutes");
|
||||
|
||||
} catch (IOException | JSONException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
Logger.error("[e = " + e.getLocalizedMessage() +"]");
|
||||
|
||||
AppConfiguration.locale = "default";
|
||||
AppConfiguration.replaceMsWithKnots = false;
|
||||
AppConfiguration.decimationPeriod = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void storeToFile() {
|
||||
String jsonData = "";
|
||||
|
||||
try {
|
||||
FileOutputStream outputStream = new FileOutputStream(fileNames.getAppConfigurationFile());
|
||||
|
||||
JSONObject masterObject = new JSONObject();
|
||||
|
||||
masterObject.put("replaceMsWithKnots", AppConfiguration.replaceMsWithKnots);
|
||||
masterObject.put("locale", AppConfiguration.locale);
|
||||
masterObject.put("decimationPeriodMinutes", AppConfiguration.decimationPeriod);
|
||||
|
||||
jsonData = masterObject.toString();
|
||||
|
||||
// write JSON content to file on disk
|
||||
outputStream.write(jsonData.getBytes());
|
||||
|
||||
// synchronize and close stream
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package cc.pogoda.mobile.meteosystem.file;
|
||||
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
public class CopyLog {
|
||||
|
||||
public static class CopyLogRunner implements Runnable {
|
||||
|
||||
InputStreamReader streamReader;
|
||||
OutputStreamWriter streamWriter;
|
||||
|
||||
int logFileLn;
|
||||
|
||||
public CopyLogRunner(InputStreamReader _stream_reader, OutputStreamWriter _stream_writer, int _log_file_ln) {
|
||||
streamReader = _stream_reader;
|
||||
streamWriter = _stream_writer;
|
||||
logFileLn = _log_file_ln;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
char buffer[] = new char[logFileLn];
|
||||
|
||||
streamReader.read(buffer);
|
||||
|
||||
streamWriter.write(buffer);
|
||||
|
||||
streamReader.close();
|
||||
streamWriter.flush();
|
||||
streamWriter.close();
|
||||
|
||||
Logger.info("[log file copied succesfully]");
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.error("[IOException e = " + e.getLocalizedMessage() +"]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void forDay(FileNames _file_names, LocalDateTime _date, OutputStream _out) {
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
|
||||
File baseDir = _file_names.getDirectory();
|
||||
|
||||
File logfile = new File(baseDir.getAbsolutePath() + "/logs/log_" + _date.format(formatter) + ".txt");
|
||||
|
||||
Logger.debug("[logfile.getAbsolutePath() = " + logfile.getAbsolutePath() +"][logfile.length() = " + logfile.length() +"]");
|
||||
|
||||
try {
|
||||
// create an input stream to load log file
|
||||
FileInputStream fns = new FileInputStream(logfile);
|
||||
InputStreamReader streamReader = new InputStreamReader(fns);
|
||||
|
||||
// create output stream writer to copy log file into
|
||||
OutputStreamWriter writer = new OutputStreamWriter(_out);
|
||||
|
||||
CopyLogRunner runner = new CopyLogRunner(streamReader, writer, (int)logfile.length());
|
||||
|
||||
Thread t = new Thread(runner);
|
||||
|
||||
t.start();
|
||||
|
||||
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.error("[IOException e = " + e.getLocalizedMessage() +"]");
|
||||
}
|
||||
|
||||
// log_{date:yyyy-MM-dd}.txt
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package cc.pogoda.mobile.meteosystem.file;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationData;
|
||||
|
||||
public class CsvExport {
|
||||
|
||||
public static boolean exportToCsv(ListOfStationData data, WeatherStation station, Context context, OutputStream out) {
|
||||
|
||||
OutputStreamWriter writer = new OutputStreamWriter(out);
|
||||
|
||||
try {
|
||||
writer.write("epoch,temperature,pressure,humidity,winddirection,windspeed,windgusts\r\n");
|
||||
|
||||
|
||||
for (StationData d : data.list_of_station_data) {
|
||||
|
||||
writer.write( String.valueOf(d.epoch) + "," +
|
||||
String.valueOf(d.temperature) + "," +
|
||||
String.valueOf(d.pressure) + "," +
|
||||
String.valueOf(d.humidity) + "," +
|
||||
String.valueOf(d.winddir) + "," +
|
||||
String.valueOf(d.windspeed) + "," +
|
||||
String.valueOf(d.windgusts) + "\r\n");
|
||||
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
writer.close();
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
package cc.pogoda.mobile.meteosystem.file;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.threeten.bp.Instant;
|
||||
import org.threeten.bp.ZoneId;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationData;
|
||||
|
||||
public class ExcelExport {
|
||||
|
||||
private static final SimpleDateFormat SDF = new SimpleDateFormat("dd-M-yyyy HH:mm:ss");
|
||||
|
||||
private static double round (double in) {
|
||||
double out = 0;
|
||||
|
||||
long temp = (long)(in * 10);
|
||||
|
||||
out = temp / 10.0d;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public static boolean exportToExcel(ListOfStationData data, WeatherStation station, Context context, OutputStream out) {
|
||||
|
||||
if (out == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data == null || data.list_of_station_data.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int rowNumber = 0;
|
||||
|
||||
long previousEpoch = 0;
|
||||
|
||||
Cell cell;
|
||||
|
||||
ZonedDateTime first = ZonedDateTime.ofInstant(Instant.ofEpochSecond(data.list_of_station_data[0].epoch), ZoneId.of(station.getTimezone()));
|
||||
String generalTimezone = first.format(DateTimeFormatter.ofPattern("zzzz"));
|
||||
|
||||
Workbook workbook = new HSSFWorkbook();
|
||||
|
||||
CellStyle left = workbook.createCellStyle();
|
||||
left.setAlignment(CellStyle.ALIGN_LEFT);
|
||||
|
||||
Sheet sheet = workbook.createSheet(station.getSystemName());
|
||||
|
||||
{
|
||||
Row stationame = sheet.createRow(rowNumber++);
|
||||
Cell name = stationame.createCell(0);
|
||||
name.setCellValue("Station name:");
|
||||
name = stationame.createCell(1);
|
||||
name.setCellValue(station.getDisplayedName());
|
||||
|
||||
Row localization = sheet.createRow(rowNumber++);
|
||||
Cell loc = localization.createCell(0);
|
||||
loc.setCellValue("Location:");
|
||||
loc = localization.createCell(1);
|
||||
loc.setCellValue(station.getDisplayedLocation());
|
||||
|
||||
Row coordinates = sheet.createRow(rowNumber++);
|
||||
Cell coord = coordinates.createCell(0);
|
||||
coord.setCellValue("Coordinates:");
|
||||
coord = coordinates.createCell(1);
|
||||
coord.setCellValue("Lat " + station.getLat() + " , Lon " + station.getLon());
|
||||
|
||||
Row timezone = sheet.createRow(rowNumber++);
|
||||
Cell tz = timezone.createCell(0);
|
||||
tz.setCellValue("All date and time as in:");
|
||||
tz = timezone.createCell(1);
|
||||
tz.setCellValue(station.getTimezone());
|
||||
|
||||
Row generaltz = sheet.createRow(rowNumber++);
|
||||
Cell gtz = generaltz.createCell(0);
|
||||
gtz.setCellValue("Timezone in this export:");
|
||||
gtz = generaltz.createCell(1);
|
||||
gtz.setCellValue(generalTimezone);
|
||||
|
||||
Row offset = sheet.createRow(rowNumber++);
|
||||
Cell off = offset.createCell(0);
|
||||
off.setCellValue("Time offset for the timezone:");
|
||||
off = offset.createCell(1);
|
||||
off.setCellValue(first.getOffset().toString());
|
||||
|
||||
Row aprscall = sheet.createRow(rowNumber++);
|
||||
Cell call = aprscall.createCell(0);
|
||||
call.setCellValue("APRS Callsign:");
|
||||
call = aprscall.createCell(1);
|
||||
call.setCellValue(station.getCallsignSsid());
|
||||
}
|
||||
|
||||
rowNumber++;
|
||||
rowNumber++;
|
||||
|
||||
Row info = sheet.createRow(rowNumber++);
|
||||
cell = info.createCell(0);
|
||||
cell.setCellValue("Windspeed is exported both in m/s and knots. One knot equals one nautical mile per hour");
|
||||
|
||||
if (AppConfiguration.decimationPeriod > 0) {
|
||||
rowNumber++;
|
||||
|
||||
Row decim = sheet.createRow(rowNumber++);
|
||||
cell = decim.createCell(0);
|
||||
cell.setCellValue("Decimation has been applied to the station data and some measurements have been dropped during an export. Minimal time difference between consecutive records is set to " + AppConfiguration.decimationPeriod + " minutes");
|
||||
}
|
||||
|
||||
rowNumber++;
|
||||
rowNumber++;
|
||||
|
||||
Row header = sheet.createRow(rowNumber++);
|
||||
|
||||
cell = header.createCell(0);
|
||||
cell.setCellValue("UNIX Epoch Timestamp");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(1);
|
||||
cell.setCellValue("Date / Time [DD-MM-YYYY 24HH:MM]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(2);
|
||||
cell.setCellValue("Temperature [C]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(3);
|
||||
cell.setCellValue("QNH pressure [hPa]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(4);
|
||||
cell.setCellValue("Humidity [%]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(5);
|
||||
cell.setCellValue("Wind Direction");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(6);
|
||||
cell.setCellValue("Wind Average Speed [m/s]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(7);
|
||||
cell.setCellValue("Wind Gusts [m/s]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(8);
|
||||
cell.setCellValue("Wind Average Speed [knots]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
cell = header.createCell(9);
|
||||
cell.setCellValue("Wind Gusts [knots]");
|
||||
cell.setCellStyle(left);
|
||||
|
||||
// put data into output file
|
||||
for (StationData d : data.list_of_station_data) {
|
||||
|
||||
if (d.epoch - previousEpoch < AppConfiguration.decimationPeriod * 60) {
|
||||
continue;
|
||||
}
|
||||
|
||||
previousEpoch = d.epoch;
|
||||
|
||||
Row r = sheet.createRow(rowNumber++);
|
||||
|
||||
Cell epoch = r.createCell(0);
|
||||
epoch.setCellValue(d.epoch);
|
||||
epoch.setCellStyle(left);
|
||||
|
||||
ZonedDateTime zoneddatetime = ZonedDateTime.ofInstant(Instant.ofEpochSecond(d.epoch), ZoneId.of(station.getTimezone()));
|
||||
Cell datetime = r.createCell(1);
|
||||
datetime.setCellValue(zoneddatetime.format(DateTimeFormatter.ofPattern("dd-M-yyyy HH:mm:ss")));
|
||||
datetime.setCellStyle(left);
|
||||
|
||||
Cell temperature = r.createCell(2);
|
||||
temperature.setCellValue(round(d.temperature));
|
||||
temperature.setCellStyle(left);
|
||||
|
||||
Cell pressure = r.createCell(3);
|
||||
pressure.setCellValue(d.pressure);
|
||||
pressure.setCellStyle(left);
|
||||
|
||||
Cell humidity = r.createCell(4);
|
||||
humidity.setCellValue(d.humidity);
|
||||
humidity.setCellStyle(left);
|
||||
|
||||
Cell winddir = r.createCell(5);
|
||||
winddir.setCellValue(d.winddir);
|
||||
winddir.setCellStyle(left);
|
||||
|
||||
Cell windspeed = r.createCell(6);
|
||||
windspeed.setCellValue(round(d.windspeed));
|
||||
windspeed.setCellStyle(left);
|
||||
|
||||
Cell windgust = r.createCell(7);
|
||||
windgust.setCellValue(round(d.windgusts));
|
||||
windgust.setCellStyle(left);
|
||||
|
||||
Cell windspeed_kts = r.createCell(8);
|
||||
windspeed_kts.setCellValue(round(d.windspeed * 0.514));
|
||||
windspeed_kts.setCellStyle(left);
|
||||
|
||||
Cell windgust_kts = r.createCell(9);
|
||||
windgust_kts.setCellValue(round(d.windgusts * 0.514));
|
||||
windgust_kts.setCellStyle(left);
|
||||
}
|
||||
|
||||
sheet.setColumnWidth(0, 6600);
|
||||
sheet.setColumnWidth(1, 5900);
|
||||
sheet.setColumnWidth(2, 3900);
|
||||
sheet.setColumnWidth(3, 4600);
|
||||
sheet.setColumnWidth(4, 2900);
|
||||
sheet.setColumnWidth(5, 3200);
|
||||
sheet.setColumnWidth(6, 5000);
|
||||
sheet.setColumnWidth(7, 4400);
|
||||
sheet.setColumnWidth(8, 4900);
|
||||
sheet.setColumnWidth(9, 4400);
|
||||
|
||||
try {
|
||||
workbook.write(out);
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package cc.pogoda.mobile.meteosystem.file;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class FavouritiesFile {
|
||||
|
||||
FileNames fileNames;
|
||||
|
||||
public FavouritiesFile(FileNames fns) {
|
||||
fileNames = fns;
|
||||
}
|
||||
|
||||
public List<WeatherStation> loadFavourites() {
|
||||
|
||||
List<WeatherStation> out = new LinkedList<>();
|
||||
|
||||
File file = fileNames.getFavJsonFile();
|
||||
|
||||
Logger.info("[file = " + file + "]");
|
||||
|
||||
try {
|
||||
// create an input stream to load file content
|
||||
FileInputStream fns = new FileInputStream(file);
|
||||
InputStreamReader streamReader = new InputStreamReader(fns);
|
||||
|
||||
// create a place fo JSON content
|
||||
char buffer[] = new char[(int) file.length()];
|
||||
|
||||
try {
|
||||
// read the content of file
|
||||
streamReader.read(buffer);
|
||||
|
||||
streamReader.close();
|
||||
|
||||
// parse JSON to array
|
||||
JSONArray root = new JSONArray(new String(buffer));
|
||||
|
||||
if (root != null) {
|
||||
for (int i = 0 ; i < root.length(); i++) {
|
||||
|
||||
// create new weather station data object
|
||||
WeatherStation station = new WeatherStation();
|
||||
|
||||
// get onlu 'systemName' as the rest will be copied from current 'allStationsList'
|
||||
station.setSystemName(root.getJSONObject(i).getString("systemName"));
|
||||
|
||||
out.add(station);
|
||||
|
||||
Logger.debug("[i = " + i +"][station.getSystemName() = " + station.getSystemName() + "]");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (JSONException e) {
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public void persistFavourities(List<WeatherStation> favourites) throws IOException {
|
||||
|
||||
// do nothing in case that no statations have been added to favourites yet
|
||||
if (favourites == null || favourites.size() == 0)
|
||||
return;
|
||||
|
||||
String jsonData = "";
|
||||
|
||||
// main array for all stations
|
||||
JSONArray mainArray = new JSONArray();
|
||||
|
||||
Logger.info("[favourites.size() = " + favourites.size() + "]");
|
||||
|
||||
for (WeatherStation wx : favourites) {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
try {
|
||||
obj.put("systemName", wx.getSystemName());
|
||||
obj.put("displayedName", wx.getDisplayedName());
|
||||
obj.put("displayedLocation", wx.getDisplayedLocation());
|
||||
obj.put("sponsorUrl", wx.getSponsorUrl());
|
||||
obj.put("imageUrl", wx.getImageUrl());
|
||||
obj.put("imageAlign", wx.getImageAlign());
|
||||
obj.put("lat", wx.getLat());
|
||||
obj.put("lon", wx.getLon());
|
||||
|
||||
mainArray.put(obj);
|
||||
|
||||
Logger.debug("[wx.getSystemName() = " + wx.getSystemName() + "]");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
jsonData = mainArray.toString();
|
||||
|
||||
if (jsonData != null && jsonData.length() > 0) {
|
||||
File output = fileNames.getFavJsonFile();
|
||||
|
||||
// checks if file exists and delete it if yes
|
||||
if (output.exists()) {
|
||||
output.delete();
|
||||
output.createNewFile();
|
||||
}
|
||||
|
||||
FileOutputStream outputStream = new FileOutputStream(output);
|
||||
|
||||
// write JSON content to file on disk
|
||||
outputStream.write(jsonData.getBytes());
|
||||
|
||||
// synchronize and close stream
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package cc.pogoda.mobile.meteosystem.file;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class FileNames {
|
||||
|
||||
public static final String DIRECTORY = "files";
|
||||
|
||||
public static final String FAVS = "favourites.json";
|
||||
public static final String CONF = "app_configuration.json";
|
||||
|
||||
private Context ctx;
|
||||
|
||||
public FileNames(Context context) {
|
||||
ctx = context;
|
||||
}
|
||||
|
||||
public File getDirectory() {
|
||||
return ctx.getDir(DIRECTORY, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public File getFavJsonFile() {
|
||||
File dir = this.getDirectory();
|
||||
|
||||
return new File(dir.getAbsolutePath() + "/" + FAVS);
|
||||
|
||||
}
|
||||
|
||||
public File getAppConfigurationFile() {
|
||||
File dir = this.getDirectory();
|
||||
|
||||
return new File(dir.getAbsolutePath() + "/" + CONF);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package cc.pogoda.mobile.meteosystem.service;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.app.JobIntentService;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.dao.AllStationsDao;
|
||||
import cc.pogoda.mobile.meteosystem.dao.AvailableParametersDao;
|
||||
import cc.pogoda.mobile.meteosystem.type.AllStationsReceivedEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.AvailableParameters;
|
||||
import cc.pogoda.mobile.meteosystem.type.StartStationsRefreshEvent;
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class GetAllStationsService extends JobIntentService {
|
||||
private static final int JOB_ID = 1;
|
||||
|
||||
public static void enqueueWork(@NonNull Context context, @NonNull Intent intent) {
|
||||
enqueueWork(context, GetAllStationsService.class, JOB_ID, intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleWork(@NonNull Intent intent) {
|
||||
EventBus.getDefault().post(new StartStationsRefreshEvent());
|
||||
|
||||
// download all stations
|
||||
List<WeatherStation> allStations = new AllStationsDao().getAllStations();
|
||||
if (allStations != null){
|
||||
|
||||
EventBus.getDefault().post(new AllStationsReceivedEvent(allStations));
|
||||
Logger.debug("onHandleWork done. allStations size:" + allStations.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class AllStationsReceivedEvent {
|
||||
List<WeatherStation> stations;
|
||||
|
||||
public AllStationsReceivedEvent(@NonNull List<WeatherStation> stations) {
|
||||
this.stations = stations;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<WeatherStation> getStations(){
|
||||
return this.stations;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[AllStationsReceivedEvent][stations.size() = " + stations.size() +"]";
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.StationDefinition;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.AvailableParametersWeb;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.StationDefinition;
|
||||
|
||||
public class AvailableParameters implements Serializable {
|
||||
|
||||
|
@ -33,6 +34,20 @@ public class AvailableParameters implements Serializable {
|
|||
rain = false;
|
||||
}
|
||||
|
||||
public static AvailableParameters fromWebData(AvailableParametersWeb w) {
|
||||
AvailableParameters out = new AvailableParameters();
|
||||
|
||||
out.humidity = w.hasHumidity;
|
||||
out.windSpeed = w.hasWind;
|
||||
out.windGusts = w.hasWind;
|
||||
out.windDirection = w.hasWind;
|
||||
out.qnh = w.hasQnh;
|
||||
out.airTemperature = true;
|
||||
out.rain = w.hasRain;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public static AvailableParameters fromStation(StationDefinition s) {
|
||||
AvailableParameters out = new AvailableParameters();
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class ParceableFavsCallReason implements Parcelable {
|
||||
|
||||
public enum Reason {
|
||||
FAVOURITES,
|
||||
EXPORT_SELECT,
|
||||
ALL_STATIONS
|
||||
}
|
||||
|
||||
public Reason getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
private Reason reason;
|
||||
|
||||
public ParceableFavsCallReason(Reason r) {
|
||||
this.reason = r;
|
||||
}
|
||||
|
||||
protected ParceableFavsCallReason(Parcel in) {
|
||||
int reasonInt = in.readInt();
|
||||
|
||||
switch (reasonInt) {
|
||||
case 1: reason = Reason.FAVOURITES; break;
|
||||
case 2: reason = Reason.EXPORT_SELECT; break;
|
||||
case 3: reason = Reason.ALL_STATIONS; break;
|
||||
default: reason = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
switch (reason) {
|
||||
case FAVOURITES: dest.writeInt(1); break;
|
||||
case EXPORT_SELECT: dest.writeInt(2); break;
|
||||
case ALL_STATIONS: dest.writeInt(3); break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<ParceableFavsCallReason> CREATOR = new Creator<ParceableFavsCallReason>() {
|
||||
@Override
|
||||
public ParceableFavsCallReason createFromParcel(Parcel in) {
|
||||
return new ParceableFavsCallReason(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParceableFavsCallReason[] newArray(int size) {
|
||||
return new ParceableFavsCallReason[size];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ParceableStationsList implements Parcelable {
|
||||
|
||||
ArrayList<WeatherStation> list;
|
||||
|
||||
int listSize;
|
||||
|
||||
public ArrayList<WeatherStation> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public static ParceableStationsList createFromStdList(List<WeatherStation> stationList) {
|
||||
ParceableStationsList out = new ParceableStationsList();
|
||||
|
||||
out.list = new ArrayList<>(stationList);
|
||||
out.listSize = stationList.size();
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
public static final Creator<ParceableStationsList> CREATOR = new Creator<ParceableStationsList>() {
|
||||
@Override
|
||||
public ParceableStationsList createFromParcel(Parcel in) {
|
||||
return new ParceableStationsList(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParceableStationsList[] newArray(int size) {
|
||||
return new ParceableStationsList[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
if (list != null) {
|
||||
listSize = list.size();
|
||||
|
||||
parcel.writeInt(listSize);
|
||||
|
||||
for (WeatherStation s : list) {
|
||||
parcel.writeString(s.getSystemName());
|
||||
parcel.writeString(s.getDisplayedName());
|
||||
parcel.writeString(s.getDisplayedLocation());
|
||||
parcel.writeString(s.getSponsorUrl());
|
||||
parcel.writeString(s.getImageUrl());
|
||||
parcel.writeString(s.getTimezone());
|
||||
parcel.writeString(s.getCallsignSsid());
|
||||
|
||||
parcel.writeInt(s.getImageAlign());
|
||||
parcel.writeInt(s.getStationNameTextColor());
|
||||
|
||||
parcel.writeFloat(s.getLat());
|
||||
parcel.writeFloat(s.getLon());
|
||||
|
||||
parcel.writeString(s.getMoreInfo());
|
||||
|
||||
parcel.writeInt(s.getAvailableParameters().humidity ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().qnh ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().windDirection ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().windGusts ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().windSpeed ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().rain ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().waterTemperature ? 1 : 0);
|
||||
parcel.writeInt(s.getAvailableParameters().airTemperature ? 1 : 0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ParceableStationsList(Parcel in) {
|
||||
list = new ArrayList<>();
|
||||
listSize = in.readInt();
|
||||
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
WeatherStation wx = new WeatherStation();
|
||||
|
||||
wx.systemName = in.readString();
|
||||
wx.displayedName = in.readString();
|
||||
wx.displayedLocation = in.readString();
|
||||
wx.sponsorUrl = in.readString();
|
||||
wx.imageUrl = in.readString();
|
||||
wx.timezone = in.readString();
|
||||
wx.callsignSsid = in.readString();
|
||||
|
||||
wx.imageAlign = in.readInt();
|
||||
wx.stationNameTextColor = in.readInt();
|
||||
|
||||
wx.lat = in.readFloat();
|
||||
wx.lon = in.readFloat();
|
||||
|
||||
wx.moreInfo = in.readString();
|
||||
|
||||
AvailableParameters params = new AvailableParameters();
|
||||
|
||||
params.humidity = (in.readInt() > 0) ? true : false;
|
||||
params.qnh = (in.readInt() > 0) ? true : false;
|
||||
params.windDirection = (in.readInt() > 0) ? true : false;
|
||||
params.windGusts = (in.readInt() > 0) ? true : false;
|
||||
params.windSpeed = (in.readInt() > 0) ? true : false;
|
||||
params.rain = (in.readInt() > 0) ? true : false;
|
||||
params.waterTemperature = (in.readInt() > 0) ? true : false;
|
||||
params.airTemperature = (in.readInt() > 0) ? true : false;
|
||||
|
||||
wx.setAvailableParameters(params);
|
||||
|
||||
list.add(wx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ParceableStationsList(ParceableStationsList in ) {
|
||||
this.list = new ArrayList<>(in.getList());
|
||||
this.listSize = this.list.size();
|
||||
}
|
||||
|
||||
public ParceableStationsList() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
public class StartStationsRefreshEvent {
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Summary;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
/**
|
||||
* This is an interface which is used to implement classes used for updating the activity content
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
|
|
@ -1,22 +1,19 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import org.threeten.bp.Duration;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.OffsetDateTime;
|
||||
import org.threeten.bp.ZoneOffset;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.threeten.bp.temporal.ChronoUnit;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Summary;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
public class StationSummaryActElements implements StationActivityElements {
|
||||
|
||||
|
@ -29,7 +26,10 @@ public class StationSummaryActElements implements StationActivityElements {
|
|||
public TextView humidity_val = null;
|
||||
public TextView message = null;
|
||||
|
||||
private String convertDegreesToDir(int directionInDegrees) {
|
||||
public int goodColor = 0;
|
||||
public int badColor = 0;
|
||||
|
||||
public static String convertDegreesToDir(int directionInDegrees) {
|
||||
String out = null;
|
||||
|
||||
if (directionInDegrees <= 11 || directionInDegrees >= 349)
|
||||
|
@ -94,6 +94,8 @@ public class StationSummaryActElements implements StationActivityElements {
|
|||
|
||||
long minutes_difference = last_station_data.until(current, ChronoUnit.MINUTES);
|
||||
|
||||
Logger.debug("[last_station_data = " + last_station_data.format(DateTimeFormatter. ISO_LOCAL_DATE_TIME) +"]");
|
||||
|
||||
// calculate the duration between
|
||||
Duration duration = Duration.between(last_station_data, current);
|
||||
|
||||
|
@ -108,43 +110,80 @@ public class StationSummaryActElements implements StationActivityElements {
|
|||
message.setTextColor(Color.argb(0xFF, 0xFF, 0x0, 0x0));
|
||||
}
|
||||
|
||||
if (!s.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE) && enabledForStation.windSpeed) {
|
||||
wind_speed_val.setText(String.format("%.1f m/s", s.average_speed));
|
||||
if (enabledForStation.windSpeed) {
|
||||
wind_speed_val.setText(String.format("%s", s.getWindspeedStr(true)));
|
||||
|
||||
if (goodColor != 0 && !s.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
wind_speed_val.setTextColor(goodColor);
|
||||
}
|
||||
else if (badColor != 0) {
|
||||
wind_speed_val.setTextColor(badColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wind_speed_val.setText("---");
|
||||
}
|
||||
|
||||
if (!s.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE) && enabledForStation.windGusts) {
|
||||
wind_gusts_val.setText(String.format("%.1f m/s", s.gusts));
|
||||
if (enabledForStation.windGusts) {
|
||||
wind_gusts_val.setText(String.format("%s", s.getWindgustsStr(true)));
|
||||
|
||||
if (goodColor != 0 && !s.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
wind_gusts_val.setTextColor(goodColor);
|
||||
}
|
||||
else if (badColor != 0) {
|
||||
wind_gusts_val.setText(badColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wind_gusts_val.setText("---");
|
||||
}
|
||||
|
||||
if (!s.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE) && enabledForStation.windDirection) {
|
||||
if (enabledForStation.windDirection) {
|
||||
wind_dir_val.setText(this.convertDegreesToDir(s.direction));
|
||||
|
||||
if (goodColor != 0 && !s.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
wind_dir_val.setTextColor(goodColor);
|
||||
}
|
||||
else if (badColor != 0){
|
||||
wind_dir_val.setTextColor(badColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
wind_dir_val.setText("---");
|
||||
}
|
||||
|
||||
if (!s.temperature_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
temperature_val.setText(String.format("%.1f °C", s.avg_temperature));
|
||||
temperature_val.setText(String.format("%s", s.getTemperatureStr(true, false)));
|
||||
|
||||
if (goodColor != 0 && !s.temperature_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
temperature_val.setTextColor(goodColor);
|
||||
}
|
||||
else {
|
||||
temperature_val.setText("---");
|
||||
else if (badColor != 0){
|
||||
temperature_val.setTextColor(badColor);
|
||||
}
|
||||
// TODO
|
||||
if (!s.qnh_qf_native.equals(QualityFactor.NOT_AVALIABLE) && enabledForStation.qnh) {
|
||||
if (enabledForStation.qnh) {
|
||||
qnh_val.setText(String.format("%d hPa", s.qnh));
|
||||
|
||||
if (goodColor != 0 && !s.qnh_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
qnh_val.setTextColor(goodColor);
|
||||
}
|
||||
else if (badColor != 0) {
|
||||
qnh_val.setTextColor(badColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
qnh_val.setText("---");
|
||||
}
|
||||
|
||||
if (!s.humidity_qf_native.equals(QualityFactor.NOT_AVALIABLE) && enabledForStation.humidity) {
|
||||
if (enabledForStation.humidity) {
|
||||
humidity_val.setText(String.format("%d %%", s.humidity));
|
||||
|
||||
if (goodColor != 0 && !s.humidity_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
humidity_val.setTextColor(goodColor);
|
||||
}
|
||||
else {
|
||||
humidity_val.setTextColor(badColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
humidity_val.setText("---");
|
|
@ -1,7 +1,6 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
@ -9,11 +8,12 @@ import android.widget.TextView;
|
|||
import org.threeten.bp.Duration;
|
||||
import org.threeten.bp.LocalDateTime;
|
||||
import org.threeten.bp.ZonedDateTime;
|
||||
import org.w3c.dom.Text;
|
||||
import org.threeten.bp.format.DateTimeFormatter;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.R;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.pogodacc.type.web.Summary;
|
||||
import cc.pogoda.mobile.meteosystem.R;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.QualityFactor;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.Summary;
|
||||
|
||||
public class StationWindRoseActElements implements StationActivityElements {
|
||||
|
||||
|
@ -37,6 +37,9 @@ public class StationWindRoseActElements implements StationActivityElements {
|
|||
*/
|
||||
public TextView minAverage;
|
||||
|
||||
public int goodColor;
|
||||
public int badColor;
|
||||
|
||||
Activity activity;
|
||||
|
||||
public StationWindRoseActElements() {
|
||||
|
@ -84,6 +87,8 @@ public class StationWindRoseActElements implements StationActivityElements {
|
|||
// current date and time (in current time zone set in system configuration)
|
||||
LocalDateTime current = LocalDateTime.now();
|
||||
|
||||
Logger.debug("[last_station_data = " + last_station_data.format(DateTimeFormatter. ISO_LOCAL_DATE_TIME) +"]");
|
||||
|
||||
// calculate the duration between
|
||||
Duration duration = Duration.between(last_station_data, current);
|
||||
|
||||
|
@ -93,6 +98,12 @@ public class StationWindRoseActElements implements StationActivityElements {
|
|||
}
|
||||
}
|
||||
|
||||
Logger.debug("[no_data = " + no_data +"][old_data = " + old_data+"]");
|
||||
|
||||
// create strings with wind speed, gusts etc
|
||||
String average_speed = String.format("%s", data.getWindspeedStr(true));
|
||||
String gusts_speed = String.format("%s", data.getWindgustsStr(true));
|
||||
|
||||
// check if wind data is avaliable in the input data set
|
||||
if (!no_data && !data.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
windArrow.setRotation(data.direction - 225.0f);
|
||||
|
@ -103,35 +114,54 @@ public class StationWindRoseActElements implements StationActivityElements {
|
|||
}
|
||||
|
||||
if (!no_data && !data.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
windSpeed.setText(activity.getResources().getString(R.string.mean_value) + '\n' + data.average_speed + "m/s");
|
||||
windSpeed.setText(average_speed);
|
||||
windSpeed.setTextColor(goodColor);
|
||||
} else {
|
||||
windSpeed.setText(activity.getResources().getString(R.string.mean_value) + '\n' + "---");
|
||||
windSpeed.setText("---");
|
||||
}
|
||||
|
||||
if (!no_data && !data.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
windGusts.setText(activity.getResources().getString(R.string.wind_gust_short) + '\n' + data.gusts + "m/s");
|
||||
windGusts.setText(gusts_speed);
|
||||
windGusts.setTextColor(goodColor);
|
||||
} else {
|
||||
windGusts.setText(activity.getResources().getString(R.string.wind_gust_short) + '\n' + "---");
|
||||
windGusts.setText("---");
|
||||
|
||||
}
|
||||
|
||||
if (!no_data && !data.wind_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
windDirection.setText(activity.getResources().getString(R.string.wind_direction_short) + '\n' + data.direction + activity.getResources().getString(R.string.degrees_sign));
|
||||
windDirection.setText(String.valueOf(data.direction) + activity.getResources().getString(R.string.degrees_sign));
|
||||
windDirection.setTextColor(goodColor);
|
||||
} else {
|
||||
windDirection.setText(activity.getResources().getString(R.string.wind_direction_short) + '\n' + "---");
|
||||
windDirection.setText("---");
|
||||
}
|
||||
|
||||
// check if temperature is avaliable in input data set
|
||||
if (!no_data && !data.temperature_qf_native.equals(QualityFactor.NOT_AVALIABLE)) {
|
||||
temperature.setText(activity.getResources().getString(R.string.temperature_short) + '\n' + String.format("%.1f", data.avg_temperature) + "°C");
|
||||
if (!no_data) {
|
||||
temperature.setText(String.format("%s", data.getTemperatureStr(true, false)));
|
||||
|
||||
if (!data.temperature_qf_native.equals(QualityFactor.NOT_AVALIABLE) && goodColor != 0) {
|
||||
temperature.setTextColor(goodColor);
|
||||
}
|
||||
else if (badColor != 0) {
|
||||
temperature.setTextColor(badColor);
|
||||
}
|
||||
} else {
|
||||
temperature.setText(activity.getResources().getString(R.string.temperature_short) + '\n' + "---");
|
||||
temperature.setText("---");
|
||||
}
|
||||
|
||||
if (!no_data && !old_data) {
|
||||
String hour_max_gusts = String.format("%s", data.getHourWindgustsStr(true));
|
||||
String hour_min_avg = String.format("%s", data.getHourMinWindspeedStr(true));
|
||||
|
||||
pressure.setText(activity.getResources().getString(R.string.qnh) + ": " + String.format("%d hPa", data.qnh));
|
||||
maxGust.setText(activity.getResources().getString(R.string.max_1h_gust) + ": " + data.hour_gusts + "m/s");
|
||||
minAverage.setText(activity.getResources().getString(R.string.min_1h_avg) + ": " + data.hour_min_average_speed + "m/s");
|
||||
maxGust.setText(activity.getResources().getString(R.string.max_1h_gust) + ": " + hour_max_gusts);
|
||||
minAverage.setText(activity.getResources().getString(R.string.min_1h_avg) + ": " + hour_min_avg);
|
||||
|
||||
if (goodColor != 0) {
|
||||
pressure.setTextColor(goodColor);
|
||||
maxGust.setTextColor(goodColor);
|
||||
minAverage.setTextColor(goodColor);
|
||||
}
|
||||
} else if (!no_data && old_data) {
|
||||
maxGust.setText(activity.getResources().getString(R.string.warning));
|
||||
maxGust.setTextColor(Color.RED);
|
|
@ -0,0 +1,11 @@
|
|||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
public class ThemeColours {
|
||||
public int colorPrimary;
|
||||
public int colorPrimaryVariant;
|
||||
public int colorOnPrimary;
|
||||
public int colorSecondary;
|
||||
public int colorSecondaryVariant;
|
||||
public int colorOnSecondary;
|
||||
|
||||
}
|
|
@ -1,11 +1,9 @@
|
|||
package cc.pogoda.mobile.pogodacc.type;
|
||||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.activity.trend.pressure.PressureTrendFragment;
|
||||
|
||||
public class WeatherStation implements Serializable {
|
||||
|
||||
public WeatherStation() {
|
||||
|
@ -73,7 +71,12 @@ public class WeatherStation implements Serializable {
|
|||
}
|
||||
|
||||
public int getStationNameTextColor() {
|
||||
return stationNameTextColor;
|
||||
if (stationNameTextColor == 0) {
|
||||
return -16777216;
|
||||
}
|
||||
else {
|
||||
return stationNameTextColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void setStationNameTextColor(int stationNameTextColor) {
|
||||
|
@ -126,10 +129,35 @@ public class WeatherStation implements Serializable {
|
|||
|
||||
String displayedLocation;
|
||||
|
||||
public String getCallsignSsid() {
|
||||
return callsignSsid;
|
||||
}
|
||||
|
||||
public void setCallsignSsid(String callsign, int ssid) {
|
||||
if (ssid < 16)
|
||||
this.callsignSsid = callsign + "-" + ssid;
|
||||
}
|
||||
|
||||
public void setCallsignSsid(String callsignSsid) {
|
||||
this.callsignSsid = callsignSsid;
|
||||
}
|
||||
|
||||
String callsignSsid;
|
||||
|
||||
String sponsorUrl;
|
||||
|
||||
String imageUrl;
|
||||
|
||||
public String getTimezone() {
|
||||
return timezone.trim();
|
||||
}
|
||||
|
||||
public void setTimezone(String timezone) {
|
||||
this.timezone = timezone;
|
||||
}
|
||||
|
||||
String timezone;
|
||||
|
||||
int imageAlign;
|
||||
|
||||
int stationNameTextColor;
|
|
@ -0,0 +1,34 @@
|
|||
package cc.pogoda.mobile.meteosystem.type;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class WeatherStationListEvent {
|
||||
|
||||
public enum EventReason {
|
||||
ADD,
|
||||
DELETE;
|
||||
}
|
||||
|
||||
WeatherStation station;
|
||||
|
||||
EventReason eventReason;
|
||||
|
||||
public WeatherStationListEvent(WeatherStation wx, EventReason reason) {
|
||||
station = wx;
|
||||
eventReason = reason;
|
||||
}
|
||||
|
||||
public WeatherStation getStation() {
|
||||
return station;
|
||||
}
|
||||
|
||||
public EventReason getEventReason() {
|
||||
return eventReason;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[station.systemName = " + station.systemName + "][eventReason = " + eventReason + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public class AvailableParametersWeb {
|
||||
|
||||
public boolean hasWind;
|
||||
|
||||
public boolean hasQnh;
|
||||
|
||||
public boolean hasHumidity;
|
||||
|
||||
public boolean hasRain;
|
||||
|
||||
public byte telemetryVersion;
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type.web;
|
||||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public class ListOfAllStations {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type.web;
|
||||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public class ListOfStationData {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type.web;
|
||||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public enum QualityFactor {
|
||||
UNSET,
|
|
@ -1,8 +1,6 @@
|
|||
package cc.pogoda.mobile.pogodacc.type.web;
|
||||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.CustomLocalDateTime;
|
||||
import cc.pogoda.mobile.meteosystem.type.CustomLocalDateTime;
|
||||
|
||||
public class StationData {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type.web;
|
||||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public class StationDefinition {
|
||||
|
||||
|
@ -26,6 +26,8 @@ public class StationDefinition {
|
|||
|
||||
public String moreInfo;
|
||||
|
||||
public String timezone;
|
||||
|
||||
public float lat;
|
||||
|
||||
public float lon;
|
|
@ -0,0 +1,327 @@
|
|||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.config.AppConfiguration;
|
||||
|
||||
public class Summary {
|
||||
|
||||
private static final String SPACE = " ";
|
||||
private static final String NO_SPACE = "";
|
||||
|
||||
public long last_timestamp;
|
||||
|
||||
public int number_of_measurements;
|
||||
|
||||
private float avg_temperature;
|
||||
|
||||
public String temperature_qf;
|
||||
|
||||
public QualityFactor temperature_qf_native;
|
||||
|
||||
public short qnh;
|
||||
|
||||
public String qnh_qf;
|
||||
|
||||
public QualityFactor qnh_qf_native;
|
||||
|
||||
public byte humidity;
|
||||
|
||||
public String humidity_qf;
|
||||
|
||||
public QualityFactor humidity_qf_native;
|
||||
|
||||
public short direction;
|
||||
|
||||
private float average_speed;
|
||||
|
||||
private float gusts;
|
||||
|
||||
private float hour_gusts;
|
||||
|
||||
private float hour_max_average_speed;
|
||||
|
||||
private float hour_min_average_speed;
|
||||
|
||||
public String wind_qf;
|
||||
|
||||
public QualityFactor wind_qf_native;
|
||||
|
||||
public Summary() {
|
||||
temperature_qf_native = QualityFactor.UNSET;
|
||||
humidity_qf_native = QualityFactor.UNSET;
|
||||
wind_qf_native = QualityFactor.UNSET;
|
||||
}
|
||||
|
||||
public float getAvgTemperature() {
|
||||
return avg_temperature;
|
||||
}
|
||||
|
||||
public float getAverageSpeed() {
|
||||
return average_speed;
|
||||
}
|
||||
|
||||
public float getGusts() {
|
||||
return gusts;
|
||||
}
|
||||
|
||||
public float getHourGusts() {
|
||||
return hour_gusts;
|
||||
}
|
||||
|
||||
public float getHourMaxAverageSpeed() {
|
||||
return hour_max_average_speed;
|
||||
}
|
||||
|
||||
public float getHourMinAverageSpeed() {
|
||||
return hour_min_average_speed;
|
||||
}
|
||||
|
||||
public String getTemperatureStr(boolean space, boolean round) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (round) {
|
||||
out = String.format("%d%s°C", Math.round(avg_temperature), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%.1f%s°C", avg_temperature, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getWindspeedStr(boolean space) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (AppConfiguration.replaceMsWithKnots) {
|
||||
float knots = this.average_speed * 1.94f;
|
||||
|
||||
out = String.format("%2d%skn", Math.round(knots), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%4.1f%sm/s", this.average_speed, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getHourMinWindspeedStr(boolean space) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (AppConfiguration.replaceMsWithKnots) {
|
||||
float knots = this.hour_min_average_speed * 1.94f;
|
||||
|
||||
out = String.format("%2d%skn", Math.round(knots), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%4.1f%sm/s", this.hour_min_average_speed, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getHourMaxWindspeedStr(boolean space) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (AppConfiguration.replaceMsWithKnots) {
|
||||
float knots = this.hour_max_average_speed * 1.94f;
|
||||
|
||||
out = String.format("%2d%skn", Math.round(knots), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%4.1f%sm/s", this.hour_max_average_speed, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getWindgustsStr(boolean space) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (AppConfiguration.replaceMsWithKnots) {
|
||||
float knots = this.gusts * 1.94f;
|
||||
|
||||
out = String.format("%2d%skn", Math.round(knots), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%4.1f%sm/s", this.gusts, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getHourWindgustsStr(boolean space) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (AppConfiguration.replaceMsWithKnots) {
|
||||
float knots = this.hour_gusts * 1.94f;
|
||||
|
||||
out = String.format("%2d%skn", Math.round(knots), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%4.1f%sm/s", this.hour_gusts, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getWindDirStr() {
|
||||
String out;
|
||||
|
||||
if (direction <= 11 || direction >= 349) {
|
||||
out = String.format("%5s", "N");
|
||||
}
|
||||
else if (direction <= 34 && direction > 11) {
|
||||
out = String.format("%5s", "N NE");
|
||||
}
|
||||
else if (direction <= 56 && direction > 34) {
|
||||
out = String.format("%5s", "NE");
|
||||
}
|
||||
else if (direction <= 79 && direction > 56) {
|
||||
out = String.format("%5s", "E NE");
|
||||
}
|
||||
else if (direction <= 101 && direction > 79) {
|
||||
out = String.format("%5s", "E");
|
||||
}
|
||||
else if (direction <= 124 && direction > 101) {
|
||||
out = String.format("%5s", "E SE");
|
||||
}
|
||||
else if (direction <= 146 && direction > 124) {
|
||||
out = String.format("%5s", "SE");
|
||||
}
|
||||
else if (direction <= 169 && direction > 146) {
|
||||
out = String.format("%5s", "S SE");
|
||||
}
|
||||
else if (direction <= 191 && direction > 169) {
|
||||
out = String.format("%5s", "S");
|
||||
}
|
||||
else if (direction <= 214 && direction > 191) {
|
||||
out = String.format("%5s", "S SW");
|
||||
}
|
||||
else if (direction <= 236 && direction > 214) {
|
||||
out = String.format("%5s", "SW");
|
||||
}
|
||||
else if (direction <= 259 && direction > 236) {
|
||||
out = String.format("%5s", "W SW");
|
||||
}
|
||||
else if (direction <= 281 && direction > 259) {
|
||||
out = String.format("%5s", "W");
|
||||
}
|
||||
else if (direction <= 304 && direction > 281) {
|
||||
out = String.format("%5s", "W NW");
|
||||
}
|
||||
else if (direction <= 327 && direction > 304) {
|
||||
out = String.format("%5s", "NW");
|
||||
}
|
||||
else if (direction <= 349 && direction > 327) {
|
||||
out = String.format("%5s", "N NW");
|
||||
}
|
||||
else {
|
||||
out = "";
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
if (WX.wind_direction <= 11 && WX.wind_direction >= 349)
|
||||
html << "- N";
|
||||
else if (WX.wind_direction <= 34 && WX.wind_direction > 11)
|
||||
html << "- N NE";
|
||||
else if (WX.wind_direction <= 56 && WX.wind_direction > 34)
|
||||
html << "- NE";
|
||||
else if (WX.wind_direction <= 79 && WX.wind_direction > 56)
|
||||
html << "- E NE";
|
||||
else if (WX.wind_direction <= 101 && WX.wind_direction > 79)
|
||||
html << "- E";
|
||||
else if (WX.wind_direction <= 124 && WX.wind_direction > 101)
|
||||
html << "- E SE";
|
||||
else if (WX.wind_direction <= 146 && WX.wind_direction > 124)
|
||||
html << "- SE";
|
||||
else if (WX.wind_direction <= 169 && WX.wind_direction > 146)
|
||||
html << "- S SE";
|
||||
else if (WX.wind_direction <= 191 && WX.wind_direction > 169)
|
||||
html << "- S";
|
||||
else if (WX.wind_direction <= 214 && WX.wind_direction > 191)
|
||||
html << "- S SW";
|
||||
else if (WX.wind_direction <= 236 && WX.wind_direction > 214)
|
||||
html << "- SW";
|
||||
else if (WX.wind_direction <= 259 && WX.wind_direction > 236)
|
||||
html <<"- W SW";
|
||||
else if (WX.wind_direction <= 281 && WX.wind_direction > 259)
|
||||
html << "- W";
|
||||
else if (WX.wind_direction <= 304 && WX.wind_direction > 281)
|
||||
html << "- W NW";
|
||||
else if (WX.wind_direction <= 327 && WX.wind_direction > 304)
|
||||
html << "- NW";
|
||||
else if (WX.wind_direction <= 349 && WX.wind_direction > 327)
|
||||
html << "- N NW";
|
||||
else;
|
||||
*/
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cc.pogoda.mobile.pogodacc.type.web;
|
||||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public class Trend {
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
package cc.pogoda.mobile.meteosystem.type.web;
|
||||
|
||||
public class TrendData {
|
||||
|
||||
private static final String SPACE = " ";
|
||||
private static final String NO_SPACE = "";
|
||||
|
||||
private float current_value;
|
||||
|
||||
private float two_hours_value;
|
||||
|
||||
private float four_hours_value;
|
||||
|
||||
private float six_hours_value;
|
||||
|
||||
private float eight_hours_value;
|
||||
|
||||
public String getCurrentVal(boolean space, boolean round) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (round) {
|
||||
out = String.format("%d%s", Math.round(current_value), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%.1f%s", current_value, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getTwoHoursVal(boolean space, boolean round) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (round) {
|
||||
out = String.format("%d%s", Math.round(two_hours_value), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%.1f%s", two_hours_value, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getFourHoursVal(boolean space, boolean round) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (round) {
|
||||
out = String.format("%d%s", Math.round(four_hours_value), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%.1f%s", four_hours_value, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getSixHoursVal(boolean space, boolean round) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (round) {
|
||||
out = String.format("%d%s", Math.round(six_hours_value), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%.1f%s", six_hours_value, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public String getEightHoursVal(boolean space, boolean round) {
|
||||
String out;
|
||||
|
||||
String s;
|
||||
|
||||
if (space) {
|
||||
s = SPACE;
|
||||
}
|
||||
else {
|
||||
s = NO_SPACE;
|
||||
}
|
||||
|
||||
if (round) {
|
||||
out = String.format("%d%s", Math.round(eight_hours_value), s);
|
||||
}
|
||||
else {
|
||||
out = String.format("%.1f%s", eight_hours_value, s);
|
||||
}
|
||||
|
||||
out = out.replace(',', '.');
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package cc.pogoda.mobile.meteosystem.web;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.web.AvailableParametersWeb;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Path;
|
||||
|
||||
public interface AvailableParametersConsumer {
|
||||
|
||||
@GET("meteo_backend/station/{name}/availableParameters")
|
||||
Call<AvailableParametersWeb> getParametersForStation(@Path("name") String name);
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
package cc.pogoda.mobile.pogodacc.web;
|
||||
package cc.pogoda.mobile.meteosystem.web;
|
||||
|
||||
import cc.pogoda.mobile.pogodacc.type.web.ListOfStationData;
|
||||
import cc.pogoda.mobile.meteosystem.type.web.ListOfStationData;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface LastStationDataConsumer {
|
||||
|
||||
@GET("meteo_backend/lastStationData/")
|
||||
Call<ListOfStationData> getLastDataForStation(@Query("station")String station,
|
||||
@GET("meteo_backend/station/{stationName}/lastStationData/")
|
||||
Call<ListOfStationData> getLastDataForStation(@Path("stationName")String station,
|
||||
@Query("ascendingOrder")boolean ascendingOrder,
|
||||
@Query("isLong")boolean isLong);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package cc.pogoda.mobile.meteosystem.web;
|
||||
|
||||
import static cc.pogoda.mobile.meteosystem.config.WebIoConfig.TIMEOUT_SECOND;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.CustomLocalDateTime;
|
||||
import cc.pogoda.mobile.meteosystem.web.deserializer.CustomLocalDateTimeDeserializer;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
public class RestClientConfig {
|
||||
|
||||
public Retrofit getWeatherStationClient() {
|
||||
Retrofit out = null;
|
||||
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(CustomLocalDateTime.class, new CustomLocalDateTimeDeserializer()).setLenient().create();
|
||||
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
|
||||
builder.readTimeout(TIMEOUT_SECOND, TimeUnit.SECONDS);
|
||||
builder.writeTimeout(TIMEOUT_SECOND, TimeUnit.SECONDS);
|
||||
builder.connectTimeout(TIMEOUT_SECOND, TimeUnit.SECONDS);
|
||||
builder.callTimeout(TIMEOUT_SECOND, TimeUnit.SECONDS);
|
||||
|
||||
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
|
||||
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
|
||||
OkHttpClient client = builder.addInterceptor(loggingInterceptor).build();//new OkHttpClient(builder);
|
||||
|
||||
out = new Retrofit.Builder().baseUrl("http://pogoda.cc:8080/").addConverterFactory(GsonConverterFactory.create(gson)).client(client).build();
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package cc.pogoda.mobile.meteosystem.web;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import cc.pogoda.mobile.meteosystem.type.WeatherStation;
|
||||
|
||||
public class StationBackgroundDownloader implements Runnable {
|
||||
|
||||
private WeatherStation station;
|
||||
|
||||
public Bitmap getBitmap() {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private Bitmap bitmap;
|
||||
|
||||
public StationBackgroundDownloader(WeatherStation _wx_station) {
|
||||
station = _wx_station;
|
||||
|
||||
bitmap = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
InputStream in = null;
|
||||
try {
|
||||
URL url = new java.net.URL(station.getImageUrl());
|
||||
|
||||
Logger.debug("[url = " + url.toString() +"]");
|
||||
|
||||
in = url.openStream();
|
||||
bitmap = BitmapFactory.decodeStream(in);
|
||||
|
||||
in.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
Logger.error("[IOException][e = " + e.getLocalizedMessage() +"]");
|
||||
e.printStackTrace();
|
||||
bitmap = null;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue