diff --git a/WearOS/src/src/debug/java/com/chriskaczor/homemonitor/wear/TilePreviewActivity.kt b/WearOS/src/src/debug/java/com/chriskaczor/homemonitor/wear/TilePreviewActivity.kt
index 312a86a..6c0c60c 100644
--- a/WearOS/src/src/debug/java/com/chriskaczor/homemonitor/wear/TilePreviewActivity.kt
+++ b/WearOS/src/src/debug/java/com/chriskaczor/homemonitor/wear/TilePreviewActivity.kt
@@ -5,6 +5,7 @@ import android.os.Bundle
import android.widget.FrameLayout
import androidx.activity.ComponentActivity
import androidx.wear.tiles.manager.TileUiClient
+import com.chriskaczor.homemonitor.wear.power.PowerTileService
class TilePreviewActivity : ComponentActivity() {
lateinit var tileUiClient: TileUiClient
diff --git a/WearOS/src/src/main/AndroidManifest.xml b/WearOS/src/src/main/AndroidManifest.xml
index 0610587..cd1885e 100644
--- a/WearOS/src/src/main/AndroidManifest.xml
+++ b/WearOS/src/src/main/AndroidManifest.xml
@@ -18,9 +18,9 @@
android:value="true" />
@@ -29,7 +29,22 @@
+ android:resource="@drawable/tile_power" />
+
+
+
+
+
+
+
+
diff --git a/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/PowerRepository.kt b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/power/PowerRepository.kt
similarity index 51%
rename from WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/PowerRepository.kt
rename to WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/power/PowerRepository.kt
index 59ad660..e1b5e3a 100644
--- a/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/PowerRepository.kt
+++ b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/power/PowerRepository.kt
@@ -1,4 +1,4 @@
-package com.chriskaczor.homemonitor.wear
+package com.chriskaczor.homemonitor.wear.power
import com.beust.klaxon.Json
import com.beust.klaxon.Klaxon
@@ -17,16 +17,11 @@ data class PowerStatus(
)
object PowerRepository {
- suspend fun getPowerStatus(): PowerStatus {
+ suspend fun getPowerStatus(): PowerStatus? {
val json = URL("http://home.kaczorzoo.net/api/power/status/recent").readText();
- val data = Klaxon().parse(json) ?: return powerStatus;
-
- powerStatus = powerStatus.copy(generation = data.generation, consumption = data.consumption, timestamp = data.timestamp);
+ val powerStatus = Klaxon().parse(json);
return powerStatus;
}
}
-
-var powerStatus =
- PowerStatus(generation = 0, consumption = 0, timestamp = Timestamp(System.currentTimeMillis()).toString())
diff --git a/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/PowerTileService.kt b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/power/PowerTileService.kt
similarity index 93%
rename from WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/PowerTileService.kt
rename to WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/power/PowerTileService.kt
index 3491513..bbefe6a 100644
--- a/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/PowerTileService.kt
+++ b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/power/PowerTileService.kt
@@ -1,4 +1,4 @@
-package com.chriskaczor.homemonitor.wear
+package com.chriskaczor.homemonitor.wear.power
import androidx.core.content.ContextCompat
import androidx.wear.tiles.ActionBuilders
@@ -15,6 +15,7 @@ import androidx.wear.tiles.TileBuilders.Tile
import androidx.wear.tiles.TileService
import androidx.wear.tiles.TimelineBuilders.Timeline
import androidx.wear.tiles.TimelineBuilders.TimelineEntry
+import com.chriskaczor.homemonitor.wear.R
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
@@ -95,17 +96,17 @@ class PowerTileService : TileService() {
serviceScope.cancel()
}
- private fun layout(goalProgress: PowerStatus, deviceParameters: DeviceParameters) =
+ private fun layout(goalProgress: PowerStatus?, deviceParameters: DeviceParameters) =
Box.Builder()
.setWidth(expand())
.setHeight(expand())
.addContent(
Column.Builder()
.addContent(
- generationLayout(goalProgress.generation, deviceParameters)
+ generationLayout(goalProgress?.generation ?: -1, deviceParameters)
)
.addContent(
- consumptionLayout(goalProgress.consumption, deviceParameters)
+ consumptionLayout(goalProgress?.consumption ?: -1, deviceParameters)
)
.addContent(Spacer.Builder().setHeight(VERTICAL_SPACING_HEIGHT).build())
.addContent(refreshButton())
@@ -135,7 +136,7 @@ class PowerTileService : TileService() {
)
.addContent(
Text.Builder()
- .setText(generation.toString())
+ .setText(if (generation <= 0) "0" else generation.toString())
.setFontStyle(FontStyles.display3(deviceParameters).build())
.build()
).build()
@@ -163,7 +164,7 @@ class PowerTileService : TileService() {
)
.addContent(
Text.Builder()
- .setText(consumption.toString())
+ .setText(if (consumption <= 0) "0" else consumption.toString())
.setFontStyle(FontStyles.display3(deviceParameters).build())
.build()
).build()
diff --git a/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/weather/WeatherRepository.kt b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/weather/WeatherRepository.kt
new file mode 100644
index 0000000..14467f3
--- /dev/null
+++ b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/weather/WeatherRepository.kt
@@ -0,0 +1,24 @@
+package com.chriskaczor.homemonitor.wear.weather
+
+import com.beust.klaxon.Json
+import com.beust.klaxon.Klaxon
+import java.net.URL
+import java.sql.Timestamp
+
+data class WeatherStatus(
+ @Json(name = "humidity")
+ val humidity: Double,
+
+ @Json(name = "pressure")
+ val pressure: Double,
+)
+
+object WeatherRepository {
+ suspend fun getWeatherStatus(): WeatherStatus? {
+ var json = URL("http://home.kaczorzoo.net/api/weather/readings/recent").readText();
+
+ var weatherStatus = Klaxon().parse(json);
+
+ return weatherStatus;
+ }
+}
diff --git a/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/weather/WeatherTileService.kt b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/weather/WeatherTileService.kt
new file mode 100644
index 0000000..f8fdd6c
--- /dev/null
+++ b/WearOS/src/src/main/java/com/chriskaczor/homemonitor/wear/weather/WeatherTileService.kt
@@ -0,0 +1,200 @@
+package com.chriskaczor.homemonitor.wear.weather
+
+import androidx.core.content.ContextCompat
+import androidx.wear.tiles.ActionBuilders
+import androidx.wear.tiles.ColorBuilders.argb
+import androidx.wear.tiles.DeviceParametersBuilders.DeviceParameters
+import androidx.wear.tiles.DimensionBuilders.dp
+import androidx.wear.tiles.DimensionBuilders.expand
+import androidx.wear.tiles.LayoutElementBuilders.*
+import androidx.wear.tiles.ModifiersBuilders.*
+import androidx.wear.tiles.RequestBuilders.ResourcesRequest
+import androidx.wear.tiles.RequestBuilders.TileRequest
+import androidx.wear.tiles.ResourceBuilders.*
+import androidx.wear.tiles.TileBuilders.Tile
+import androidx.wear.tiles.TileService
+import androidx.wear.tiles.TimelineBuilders.Timeline
+import androidx.wear.tiles.TimelineBuilders.TimelineEntry
+import com.chriskaczor.homemonitor.wear.R
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.guava.future
+
+private const val RESOURCES_VERSION = "1"
+
+// dimensions
+private val BUTTON_SIZE = dp(48f)
+private val BUTTON_RADIUS = dp(24f)
+private val BUTTON_PADDING = dp(12f)
+private val VERTICAL_SPACING_HEIGHT = dp(8f)
+
+// identifiers
+private const val ID_IMAGE_REFRESH = "image_refresh"
+private const val ID_IMAGE_GENERATION = "image_generation"
+private const val ID_IMAGE_CONSUMPTION = "image_consumption"
+private const val ID_CLICK_REFRESH = "click_refresh"
+
+class WeatherTileService : TileService() {
+ private val serviceScope = CoroutineScope(Dispatchers.IO)
+
+ override fun onTileRequest(requestParams: TileRequest) = serviceScope.future {
+ val powerStatus = WeatherRepository.getWeatherStatus()
+
+ val deviceParams = requestParams.deviceParameters!!
+
+ Tile.Builder()
+ .setResourcesVersion(RESOURCES_VERSION)
+ .setTimeline(
+ Timeline.Builder()
+ .addTimelineEntry(
+ TimelineEntry.Builder()
+ .setLayout(
+ Layout.Builder()
+ .setRoot(
+ layout(powerStatus, deviceParams)
+ ).build()
+ ).build()
+ ).build()
+ ).build()
+ }
+
+ override fun onResourcesRequest(requestParams: ResourcesRequest) = serviceScope.future {
+ Resources.Builder()
+ .setVersion(RESOURCES_VERSION)
+ .addIdToImageMapping(
+ ID_IMAGE_REFRESH,
+ ImageResource.Builder()
+ .setAndroidResourceByResId(
+ AndroidImageResourceByResId.Builder()
+ .setResourceId(R.drawable.ic_refresh)
+ .build()
+ ).build()
+ )
+ .addIdToImageMapping(
+ ID_IMAGE_GENERATION,
+ ImageResource.Builder()
+ .setAndroidResourceByResId(
+ AndroidImageResourceByResId.Builder()
+ .setResourceId(R.drawable.ic_sun)
+ .build()
+ ).build()
+ )
+ .addIdToImageMapping(
+ ID_IMAGE_CONSUMPTION,
+ ImageResource.Builder()
+ .setAndroidResourceByResId(
+ AndroidImageResourceByResId.Builder()
+ .setResourceId(R.drawable.ic_plug)
+ .build()
+ ).build()
+ ).build()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ serviceScope.cancel()
+ }
+
+ private fun layout(goalProgress: WeatherStatus?, deviceParameters: DeviceParameters) =
+ Box.Builder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContent(
+ Column.Builder()
+ .addContent(
+ generationLayout(goalProgress?.humidity ?: -1.0, deviceParameters)
+ )
+ .addContent(
+ consumptionLayout(goalProgress?.pressure ?: -1.0, deviceParameters)
+ )
+ .addContent(Spacer.Builder().setHeight(VERTICAL_SPACING_HEIGHT).build())
+ .addContent(refreshButton())
+ .build()
+ ).build()
+
+ private fun generationLayout(generation: Double, deviceParameters: DeviceParameters) =
+ Row.Builder()
+ .addContent(
+ Image.Builder()
+ .setHeight(dp(36f))
+ .setWidth(dp(36f))
+ .setModifiers(
+ Modifiers.Builder()
+ .setPadding(
+ Padding.Builder()
+ .setStart(dp(0f))
+ .setEnd(dp(10f))
+ .setTop(dp(1f))
+ .setBottom(dp(0f))
+ .build()
+ )
+ .build()
+ )
+ .setResourceId(ID_IMAGE_GENERATION)
+ .build()
+ )
+ .addContent(
+ Text.Builder()
+ .setText(if (generation <= 0) "0" else generation.toString())
+ .setFontStyle(FontStyles.display3(deviceParameters).build())
+ .build()
+ ).build()
+
+ private fun consumptionLayout(consumption: Double, deviceParameters: DeviceParameters) =
+ Row.Builder()
+ .addContent(
+ Image.Builder()
+ .setHeight(dp(36f))
+ .setWidth(dp(36f))
+ .setModifiers(
+ Modifiers.Builder()
+ .setPadding(
+ Padding.Builder()
+ .setStart(dp(0f))
+ .setEnd(dp(10f))
+ .setTop(dp(1f))
+ .setBottom(dp(0f))
+ .build()
+ )
+ .build()
+ )
+ .setResourceId(ID_IMAGE_CONSUMPTION)
+ .build()
+ )
+ .addContent(
+ Text.Builder()
+ .setText(if (consumption <= 0) "0" else consumption.toString())
+ .setFontStyle(FontStyles.display3(deviceParameters).build())
+ .build()
+ ).build()
+
+ private fun refreshButton() =
+ Image.Builder()
+ .setWidth(BUTTON_SIZE)
+ .setHeight(BUTTON_SIZE)
+ .setResourceId(ID_IMAGE_REFRESH)
+ .setModifiers(
+ Modifiers.Builder()
+ .setPadding(
+ Padding.Builder()
+ .setStart(BUTTON_PADDING)
+ .setEnd(BUTTON_PADDING)
+ .setTop(BUTTON_PADDING)
+ .setBottom(BUTTON_PADDING)
+ .build()
+ )
+ .setBackground(
+ Background.Builder()
+ .setCorner(Corner.Builder().setRadius(BUTTON_RADIUS).build())
+ .setColor(argb(ContextCompat.getColor(this, R.color.primaryDark)))
+ .build()
+ )
+ .setClickable(
+ Clickable.Builder()
+ .setId(ID_CLICK_REFRESH)
+ .setOnClick(ActionBuilders.LoadAction.Builder().build())
+ .build()
+ ).build()
+ ).build()
+}
diff --git a/WearOS/src/src/main/res/drawable/tile_goals.png b/WearOS/src/src/main/res/drawable/tile_goals.png
deleted file mode 100644
index 6e20270..0000000
Binary files a/WearOS/src/src/main/res/drawable/tile_goals.png and /dev/null differ
diff --git a/WearOS/src/src/main/res/drawable/tile_power.png b/WearOS/src/src/main/res/drawable/tile_power.png
new file mode 100644
index 0000000..17fdc02
Binary files /dev/null and b/WearOS/src/src/main/res/drawable/tile_power.png differ
diff --git a/WearOS/src/src/main/res/drawable/tile_weather.png b/WearOS/src/src/main/res/drawable/tile_weather.png
new file mode 100644
index 0000000..2962bad
Binary files /dev/null and b/WearOS/src/src/main/res/drawable/tile_weather.png differ
diff --git a/WearOS/src/src/main/res/values/strings.xml b/WearOS/src/src/main/res/values/strings.xml
index af3adc2..9c5f799 100644
--- a/WearOS/src/src/main/res/values/strings.xml
+++ b/WearOS/src/src/main/res/values/strings.xml
@@ -4,4 +4,5 @@
Home Monitor
Power
+ Weather