mirror of
https://github.com/ckaczor/HomeMonitor.git
synced 2026-01-13 17:22:54 -05:00
More Wear OS work
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
android:value="true" />
|
||||
|
||||
<service
|
||||
android:name="com.chriskaczor.homemonitor.wear.PowerTileService"
|
||||
android:name="com.chriskaczor.homemonitor.wear.power.PowerTileService"
|
||||
android:description="@string/tile_description"
|
||||
android:icon="@drawable/ic_refresh"
|
||||
android:icon="@drawable/ic_plug"
|
||||
android:label="@string/power_tile_label"
|
||||
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
|
||||
<intent-filter>
|
||||
@@ -29,7 +29,22 @@
|
||||
|
||||
<meta-data
|
||||
android:name="androidx.wear.tiles.PREVIEW"
|
||||
android:resource="@drawable/tile_goals" />
|
||||
android:resource="@drawable/tile_power" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="com.chriskaczor.homemonitor.wear.weather.WeatherTileService"
|
||||
android:description="@string/tile_description"
|
||||
android:icon="@drawable/ic_sun"
|
||||
android:label="@string/weather_tile_label"
|
||||
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
|
||||
<intent-filter>
|
||||
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="androidx.wear.tiles.PREVIEW"
|
||||
android:resource="@drawable/tile_weather" />
|
||||
</service>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -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<PowerStatus>(json) ?: return powerStatus;
|
||||
|
||||
powerStatus = powerStatus.copy(generation = data.generation, consumption = data.consumption, timestamp = data.timestamp);
|
||||
val powerStatus = Klaxon().parse<PowerStatus>(json);
|
||||
|
||||
return powerStatus;
|
||||
}
|
||||
}
|
||||
|
||||
var powerStatus =
|
||||
PowerStatus(generation = 0, consumption = 0, timestamp = Timestamp(System.currentTimeMillis()).toString())
|
||||
@@ -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()
|
||||
@@ -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<WeatherStatus>(json);
|
||||
|
||||
return weatherStatus;
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
BIN
WearOS/src/src/main/res/drawable/tile_power.png
Normal file
BIN
WearOS/src/src/main/res/drawable/tile_power.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
WearOS/src/src/main/res/drawable/tile_weather.png
Normal file
BIN
WearOS/src/src/main/res/drawable/tile_weather.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -4,4 +4,5 @@
|
||||
<string name="tile_description">Home Monitor</string>
|
||||
|
||||
<string name="power_tile_label">Power</string>
|
||||
<string name="weather_tile_label">Weather</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user