feat: extend DeviceInfo with battery, manufacturer, heartbeat
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,9 +13,12 @@ data class AuthMessage(
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class DeviceInfoMsg(
|
data class DeviceInfoMsg(
|
||||||
val model: String,
|
val model: String,
|
||||||
|
val manufacturer: String,
|
||||||
val androidVersion: String,
|
val androidVersion: String,
|
||||||
val screenWidth: Int,
|
val screenWidth: Int,
|
||||||
val screenHeight: Int
|
val screenHeight: Int,
|
||||||
|
val batteryLevel: Int,
|
||||||
|
val isCharging: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@@ -48,6 +51,13 @@ data class PongMessage(
|
|||||||
val type: String = "pong"
|
val type: String = "pong"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class HeartbeatMessage(
|
||||||
|
val type: String = "heartbeat",
|
||||||
|
val batteryLevel: Int,
|
||||||
|
val isCharging: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ServerMessage(
|
data class ServerMessage(
|
||||||
val type: String,
|
val type: String,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.thisux.droidclaw.util
|
package com.thisux.droidclaw.util
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.os.BatteryManager
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import com.thisux.droidclaw.model.DeviceInfoMsg
|
import com.thisux.droidclaw.model.DeviceInfoMsg
|
||||||
@@ -11,11 +14,30 @@ object DeviceInfoHelper {
|
|||||||
val metrics = DisplayMetrics()
|
val metrics = DisplayMetrics()
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
wm.defaultDisplay.getRealMetrics(metrics)
|
wm.defaultDisplay.getRealMetrics(metrics)
|
||||||
|
|
||||||
|
val batteryIntent = context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
|
||||||
|
val level = batteryIntent?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1
|
||||||
|
val scale = batteryIntent?.getIntExtra(BatteryManager.EXTRA_SCALE, -1) ?: -1
|
||||||
|
val batteryPct = if (level >= 0 && scale > 0) (level * 100 / scale) else -1
|
||||||
|
val plugged = batteryIntent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) ?: 0
|
||||||
|
|
||||||
return DeviceInfoMsg(
|
return DeviceInfoMsg(
|
||||||
model = android.os.Build.MODEL,
|
model = android.os.Build.MODEL,
|
||||||
|
manufacturer = android.os.Build.MANUFACTURER.replaceFirstChar { it.uppercase() },
|
||||||
androidVersion = android.os.Build.VERSION.RELEASE,
|
androidVersion = android.os.Build.VERSION.RELEASE,
|
||||||
screenWidth = metrics.widthPixels,
|
screenWidth = metrics.widthPixels,
|
||||||
screenHeight = metrics.heightPixels
|
screenHeight = metrics.heightPixels,
|
||||||
|
batteryLevel = batteryPct,
|
||||||
|
isCharging = plugged != 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getBattery(context: Context): Pair<Int, Boolean> {
|
||||||
|
val batteryIntent = context.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
|
||||||
|
val level = batteryIntent?.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) ?: -1
|
||||||
|
val scale = batteryIntent?.getIntExtra(BatteryManager.EXTRA_SCALE, -1) ?: -1
|
||||||
|
val batteryPct = if (level >= 0 && scale > 0) (level * 100 / scale) else -1
|
||||||
|
val plugged = batteryIntent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) ?: 0
|
||||||
|
return Pair(batteryPct, plugged != 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ export type DeviceMessage =
|
|||||||
| { type: "screen"; requestId: string; elements: UIElement[]; screenshot?: string; packageName?: string }
|
| { type: "screen"; requestId: string; elements: UIElement[]; screenshot?: string; packageName?: string }
|
||||||
| { type: "result"; requestId: string; success: boolean; error?: string; data?: string }
|
| { type: "result"; requestId: string; success: boolean; error?: string; data?: string }
|
||||||
| { type: "goal"; text: string }
|
| { type: "goal"; text: string }
|
||||||
| { type: "pong" };
|
| { type: "pong" }
|
||||||
|
| { type: "heartbeat"; batteryLevel: number; isCharging: boolean };
|
||||||
|
|
||||||
export type ServerToDeviceMessage =
|
export type ServerToDeviceMessage =
|
||||||
| { type: "auth_ok"; deviceId: string }
|
| { type: "auth_ok"; deviceId: string }
|
||||||
@@ -38,4 +39,5 @@ export type DashboardMessage =
|
|||||||
| { type: "device_offline"; deviceId: string }
|
| { type: "device_offline"; deviceId: string }
|
||||||
| { type: "step"; sessionId: string; step: number; action: Record<string, unknown>; reasoning: string; screenHash: string }
|
| { type: "step"; sessionId: string; step: number; action: Record<string, unknown>; reasoning: string; screenHash: string }
|
||||||
| { type: "goal_started"; sessionId: string; goal: string; deviceId: string }
|
| { type: "goal_started"; sessionId: string; goal: string; deviceId: string }
|
||||||
| { type: "goal_completed"; sessionId: string; success: boolean; stepsUsed: number };
|
| { type: "goal_completed"; sessionId: string; success: boolean; stepsUsed: number }
|
||||||
|
| { type: "device_status"; deviceId: string; batteryLevel: number; isCharging: boolean };
|
||||||
|
|||||||
@@ -53,9 +53,12 @@ export interface ActionResult {
|
|||||||
|
|
||||||
export interface DeviceInfo {
|
export interface DeviceInfo {
|
||||||
model: string;
|
model: string;
|
||||||
|
manufacturer: string;
|
||||||
androidVersion: string;
|
androidVersion: string;
|
||||||
screenWidth: number;
|
screenWidth: number;
|
||||||
screenHeight: number;
|
screenHeight: number;
|
||||||
|
batteryLevel: number;
|
||||||
|
isCharging: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ScreenState {
|
export interface ScreenState {
|
||||||
|
|||||||
Reference in New Issue
Block a user