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

View File

@ -3,108 +3,254 @@
package com.birdthedeveloper.prometheus.android.exporter.worker
import android.content.Context
import android.hardware.Sensor
import android.content.Intent
import android.content.IntentFilter
import android.hardware.Sensor
import android.hardware.SensorManager
import android.os.BatteryManager
import android.app.Activity
import android.hardware.SensorEvent
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
private const val TAG = "METRICS_ENGINE"
data class AxisSpecificGauge(
val x : Double,
val y : Double,
val z : Double,
)
class HwSensorsCache(
var batteryChargeRatio : Double? = 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 {
private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
private val hwSensorsCache = HwSensorsCache()
val hwPropertiesManager = context.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE) as HardwarePropertiesManager
init {
registerAllHwEventHandlers()
}
fun hwSensorsValues() : HwSensorsCache{
fun hwSensorsValues(): HwSensorsCache {
return hwSensorsCache
}
private fun registerAllHwEventHandlers(){
Log.d(TAG, "Registering all hw sensors")
val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
sensor?.let{
Log.d(TAG, "Sensor exists!")
private fun registerAllHwEventHandlers() {
Log.d(TAG, "Registering all hardware sensors")
//TODO test registering and unregistering as optimization
supportedSensors.forEach { supportedSensor ->
val sensor: Sensor? = sensorManager.getDefaultSensor(supportedSensor)
sensor?.let {
sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
}
//sensorManager.flush(this)
}
}
fun dispose() {
sensorManager.unregisterListener(this)
}
override fun onSensorChanged(event: SensorEvent?) {
Log.d(TAG, "Sensor Changed !!!!!!!!!!!!!!")
if(event == null){
if (event == null) {
return
}
if (event.values == null){
if (event.values == null) {
return
}
when(event.sensor.type){
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.numberOfSteps = event.values[0].toInt()
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) {
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
// - 4G, 5G
// - gps - glonass beidou ...
// - battery, charging
// node exporter metrics
// - cpu
// - ram
// - scrape duration
// - bluetooth - mac bluetooth
// - nfc
// - storage information
// - system information - version .. device name, doba provozu
}
// public fun batteryChargeRatio(): Float {
// val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter ->
// context.registerReceiver(null, intFilter)
// }
// //val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
//
// val batteryPct: Float? = batteryStatus?.let { intent ->
// val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
// val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
// level * 100 / scale.toFloat()
// }
//
// batteryPct ?: return -1.0f
// return batteryPct
// }
fun batteryChargeRatio(): Float {
val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { intFilter ->
context.registerReceiver(null, intFilter)
}
//val status: Int = batteryStatus?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
val batteryRatio: Float? = batteryStatus?.let { intent ->
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
level / scale.toFloat()
}
batteryRatio ?: return -1.0f
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.content.Context
import android.hardware.SensorManager
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.work.CoroutineWorker
@ -117,6 +116,7 @@ class PromWorker(
withContext(NonCancellable) {
Log.v(TAG, "Canceling prom worker")
backgroundDispatcher.close()
metricsEngine.dispose()
}
}
}