mirror of
https://github.com/mii443/prometheus-android-exporter.git
synced 2025-08-22 15:15:35 +00:00
hw sensors
This commit is contained in:
@ -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")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user