hw sensors

This commit is contained in:
Martin Ptáček
2023-07-26 23:49:57 +02:00
parent bac7c4e62f
commit 247c6f1ccd
3 changed files with 214 additions and 69 deletions

View File

@ -18,7 +18,7 @@ class AndroidCustomExporter(private val metricEngine: MetricsEngine) : Collector
// metrics definitions // metrics definitions
// collectBatteryStatus(mfs) // collectBatteryStatus(mfs)
collectGps(mfs) // collectGps(mfs)
collectSteps(mfs) collectSteps(mfs)
Log.d(TAG, "Metrics collected") Log.d(TAG, "Metrics collected")
@ -37,9 +37,9 @@ class AndroidCustomExporter(private val metricEngine: MetricsEngine) : Collector
// mfs.add(batteryPercentageGauge) // mfs.add(batteryPercentageGauge)
// } // }
private fun collectGps(mfs: MutableList<MetricFamilySamples>){ // private fun collectGps(mfs: MutableList<MetricFamilySamples>){
//TODO // //TODO
} // }
private fun collectSteps(mfs: MutableList<MetricFamilySamples>){ private fun collectSteps(mfs: MutableList<MetricFamilySamples>){
val gauge = GaugeMetricFamily( val gauge = GaugeMetricFamily(
@ -51,7 +51,6 @@ class AndroidCustomExporter(private val metricEngine: MetricsEngine) : Collector
metricEngine.hwSensorsValues().numberOfSteps?.let{ metricEngine.hwSensorsValues().numberOfSteps?.let{
gauge.addMetric(listOf(), it.toDouble()) gauge.addMetric(listOf(), it.toDouble())
mfs.add(gauge) mfs.add(gauge)
Log.d(TAG, "heeeeeeeeeeeeeeeeeeeeeeeeeeeee")
} }
} }
} }

View File

@ -3,108 +3,254 @@
package com.birdthedeveloper.prometheus.android.exporter.worker package com.birdthedeveloper.prometheus.android.exporter.worker
import android.content.Context import android.content.Context
import android.hardware.Sensor
import android.content.Intent import android.content.Intent
import android.content.IntentFilter import android.content.IntentFilter
import android.hardware.Sensor
import android.hardware.SensorManager import android.hardware.SensorManager
import android.os.BatteryManager
import android.app.Activity
import android.hardware.SensorEvent import android.hardware.SensorEvent
import android.hardware.SensorEventListener import android.hardware.SensorEventListener
import android.os.BatteryManager
import android.os.Build
import android.os.CpuUsageInfo
import android.os.HardwarePropertiesManager
import android.os.SystemClock
import android.system.Os
import android.system.OsConstants
import android.util.Log import android.util.Log
private const val TAG = "METRICS_ENGINE" private const val TAG = "METRICS_ENGINE"
data class AxisSpecificGauge(
val x : Double,
val y : Double,
val z : Double,
)
class HwSensorsCache( class HwSensorsCache(
var batteryChargeRatio : Double? = null, var batteryChargeRatio : Double? = null,
var numberOfSteps : Int? = null, var numberOfSteps : Int? = null,
var headingDegrees : Double? = null,
var headingAccuracyDegrees : Double? = null,
var hingeAngleDegrees : Double? = null,
var offbodyDetect : Double? = null,
var ambientTemperatureCelsius : Double? = null,
var relativeHumidityPercent : Double? = null,
var accelerometer : AxisSpecificGauge? = null,
var magneticFieldMicroTesla : AxisSpecificGauge? = null,
var gyroscopeRadiansPerSecond: AxisSpecificGauge? = null,
var ambientLightLux : Double? = null,
var pressureHectoPascal : Double? = null,
var proximityCentimeters : Double? = null,
var gravityAcceleration : AxisSpecificGauge? = null,
var linearAcceleration : AxisSpecificGauge? = null,
var rotationVectorValues : AxisSpecificGauge? = null,
var rotationVectorCosinusThetaHalf : Double? = null,
var rotationVectorAccuracyRadians : Double? = null,
); );
//TODO for cpu, use HardwarePropertiesManager
private val supportedSensors : List<Int> = listOf(
Sensor.TYPE_HEADING,
Sensor.TYPE_HINGE_ANGLE,
Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT,
Sensor.TYPE_AMBIENT_TEMPERATURE,
Sensor.TYPE_RELATIVE_HUMIDITY,
Sensor.TYPE_ACCELEROMETER,
Sensor.TYPE_MAGNETIC_FIELD,
Sensor.TYPE_GYROSCOPE,
Sensor.TYPE_LIGHT,
Sensor.TYPE_PRESSURE,
Sensor.TYPE_PROXIMITY,
Sensor.TYPE_GRAVITY,
Sensor.TYPE_LINEAR_ACCELERATION,
Sensor.TYPE_ROTATION_VECTOR,
)
val temperatureTypes : Map<Int, String> = mapOf(
HardwarePropertiesManager.DEVICE_TEMPERATURE_BATTERY to "battery",
HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU to "cpu",
HardwarePropertiesManager.DEVICE_TEMPERATURE_GPU to "gpu",
HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN to "skin",
)
class MetricsEngine(private val context: Context) : SensorEventListener { class MetricsEngine(private val context: Context) : SensorEventListener {
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val hwSensorsCache = HwSensorsCache() private val hwSensorsCache = HwSensorsCache()
val hwPropertiesManager = context.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE) as HardwarePropertiesManager
init { init {
registerAllHwEventHandlers() registerAllHwEventHandlers()
} }
fun hwSensorsValues() : HwSensorsCache{ fun hwSensorsValues(): HwSensorsCache {
return hwSensorsCache return hwSensorsCache
} }
private fun registerAllHwEventHandlers(){ private fun registerAllHwEventHandlers() {
Log.d(TAG, "Registering all hw sensors") Log.d(TAG, "Registering all hardware sensors")
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
sensor?.let{
Log.d(TAG, "Sensor exists!")
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
}
//sensorManager.flush(this)
}
override fun onSensorChanged(event: SensorEvent?) { //TODO test registering and unregistering as optimization
Log.d(TAG, "Sensor Changed !!!!!!!!!!!!!!")
if(event == null){
return
}
if (event.values == null){
return
}
when(event.sensor.type){ supportedSensors.forEach { supportedSensor ->
Sensor.TYPE_PROXIMITY -> { val sensor: Sensor? = sensorManager.getDefaultSensor(supportedSensor)
hwSensorsCache.numberOfSteps = event.values[0].toInt() sensor?.let {
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
} }
} }
} }
fun dispose() {
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent?) {
if (event == null) {
return
}
if (event.values == null) {
return
}
when (event.sensor.type) {
Sensor.TYPE_HEADING -> {
hwSensorsCache.headingDegrees = event.values[0].toDouble()
hwSensorsCache.headingAccuracyDegrees = event.values[1].toDouble()
}
Sensor.TYPE_HINGE_ANGLE -> {
hwSensorsCache.hingeAngleDegrees = event.values[0].toDouble()
}
Sensor.TYPE_LOW_LATENCY_OFFBODY_DETECT -> {
hwSensorsCache.offbodyDetect = event.values[0].toDouble()
}
Sensor.TYPE_AMBIENT_TEMPERATURE -> {
hwSensorsCache.ambientTemperatureCelsius = event.values[0].toDouble()
}
Sensor.TYPE_RELATIVE_HUMIDITY -> {
hwSensorsCache.relativeHumidityPercent = event.values[0].toDouble()
}
Sensor.TYPE_ACCELEROMETER -> {
hwSensorsCache.accelerometer = valuesToAxisSpecificGauge(event.values)
}
Sensor.TYPE_MAGNETIC_FIELD -> {
hwSensorsCache.magneticFieldMicroTesla = valuesToAxisSpecificGauge(event.values)
}
Sensor.TYPE_GYROSCOPE -> {
hwSensorsCache.gyroscopeRadiansPerSecond = valuesToAxisSpecificGauge(event.values)
}
Sensor.TYPE_LIGHT -> {
hwSensorsCache.ambientLightLux = event.values[0].toDouble()
}
Sensor.TYPE_PRESSURE -> {
hwSensorsCache.pressureHectoPascal = event.values[0].toDouble()
}
Sensor.TYPE_PROXIMITY -> {
hwSensorsCache.proximityCentimeters = event.values[0].toDouble()
}
Sensor.TYPE_GRAVITY -> {
hwSensorsCache.gravityAcceleration = valuesToAxisSpecificGauge(event.values)
}
Sensor.TYPE_LINEAR_ACCELERATION -> {
hwSensorsCache.linearAcceleration = valuesToAxisSpecificGauge(event.values)
}
Sensor.TYPE_ROTATION_VECTOR -> {
hwSensorsCache.rotationVectorValues = valuesToAxisSpecificGauge(event.values)
hwSensorsCache.rotationVectorCosinusThetaHalf = event.values[3].toDouble()
hwSensorsCache.rotationVectorAccuracyRadians = event.values[4].toDouble()
}
}
}
private fun valuesToAxisSpecificGauge(values: FloatArray): AxisSpecificGauge {
return AxisSpecificGauge(
x = values[0].toDouble(),
y = values[1].toDouble(),
z = values[2].toDouble(),
)
}
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
Log.d(TAG, "Sensor accuracy changed.") // Do nothing
} }
//TODO
///TYPE_ACCELEROMETER Yes Yes Yes Yes
//TYPE_AMBIENT_TEMPERATURE Yes n/a n/a n/a
//TYPE_GRAVITY Yes Yes n/a n/a
//TYPE_GYROSCOPE Yes Yes n/a1 n/a1
//TYPE_LIGHT Yes Yes Yes Yes
//TYPE_LINEAR_ACCELERATION Yes Yes n/a n/a
//TYPE_MAGNETIC_FIELD Yes Yes Yes Yes
//TYPE_ORIENTATION Yes2 Yes2 Yes2 Yes
//TYPE_PRESSURE Yes Yes n/a1 n/a1
//TYPE_PROXIMITY Yes Yes Yes Yes
//TYPE_RELATIVE_HUMIDITY Yes n/a n/a n/a
//TYPE_ROTATION_VECTOR Yes Yes n/a n/a
//TYPE_TEMPERATURE
// - hardware metrics:
// - basic hw sensors
// - network availability // - network availability
// - 4G, 5G // - 4G, 5G
// - gps - glonass beidou ...
// - battery, charging
// node exporter metrics
// - cpu
// - ram // - ram
// - scrape duration // - scrape duration
// - bluetooth - mac bluetooth // - bluetooth - mac bluetooth
// - nfc
// - storage information // - storage information
// - system information - version .. device name, doba provozu
}
// public fun batteryChargeRatio(): Float { fun batteryChargeRatio(): Float {
// val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter -> val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter ->
// context.registerReceiver(null, intFilter) context.registerReceiver(null, intFilter)
// } }
// //val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1 //val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
//
// val batteryPct: Float? = batteryStatus?.let { intent -> val batteryRatio: Float? = batteryStatus?.let { intent ->
// val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
// val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
// level * 100 / scale.toFloat() level / scale.toFloat()
// } }
//
// batteryPct ?: return -1.0f batteryRatio ?: return -1.0f
// return batteryPct return batteryRatio
// } }
fun getNumberOfCpuCores(): Int {
return Os.sysconf(OsConstants._SC_NPROCESSORS_CONF).toInt()
}
fun getUptimeInSeconds(): Double {
return SystemClock.elapsedRealtime() / 1000.0
}
fun cpuUsage() : Array<CpuUsageInfo> {
return hwPropertiesManager.cpuUsages
}
fun getDeviceTemperatures() : Map<String, Double> {
val result = mutableMapOf<String, Double>()
temperatureTypes.keys.forEach { type ->
val array = hwPropertiesManager.getDeviceTemperatures(
type,
HardwarePropertiesManager.TEMPERATURE_CURRENT
)
if(array.isNotEmpty()){
result[temperatureTypes[type]!!] = array[0].toDouble()
}
}
return result
}
fun getAndroidOsVersion(): String{
return Build.VERSION.RELEASE
}
fun getAndroidModel(): String {
return Build.MODEL
}
fun getAndroidManufacturer() : String {
return Build.MANUFACTURER
}
}

View File

@ -4,7 +4,6 @@ package com.birdthedeveloper.prometheus.android.exporter.worker
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.hardware.SensorManager
import android.util.Log import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.work.CoroutineWorker import androidx.work.CoroutineWorker
@ -117,6 +116,7 @@ class PromWorker(
withContext(NonCancellable) { withContext(NonCancellable) {
Log.v(TAG, "Canceling prom worker") Log.v(TAG, "Canceling prom worker")
backgroundDispatcher.close() backgroundDispatcher.close()
metricsEngine.dispose()
} }
} }
} }