Skip to content

Commit

Permalink
Merge pull request #50 from mutualmobile/development
Browse files Browse the repository at this point in the history
Merge `development` changes for version 0.2.0
  • Loading branch information
shubhamsinghmutualmobile committed Apr 20, 2023
2 parents ff4e987 + 56c0c8f commit b3887e6
Show file tree
Hide file tree
Showing 4 changed files with 301 additions and 7 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Linear Acceleration | ✅️ | rememberLinearAccelerationSensorState()
Rotation Vector | ✅️️ | rememberRotationVectorSensorState()
Relative Humidity | ⚠️ | WIP
Ambient Temperature | ✅️ | rememberAmbientTemperatureSensorState()
Magnetic Field (Uncalibrated) | | N/A
Magnetic Field (Uncalibrated) | ✅️️ | rememberUncalibratedMagneticFieldSensorState()
GameRotation Vector | ✅️ | rememberGameRotationVectorSensorState()
Gyroscope (Uncalibrated) | ⚠️ | WIP
Significant Motion | — | N/A
Expand All @@ -96,16 +96,16 @@ Step Counter | ✅️ | rememberStepCounterSensorState()
Geomagnetic Rotation Vector | ✅️️ | rememberGeomagneticRotationVectorSensorState()
Heart Rate | ✅️ | rememberHeartRateSensorState()
Pose6DOF | — | N/A
Stationary Detect | | N/A
Motion Detect | | N/A
Stationary Detect | ⚠️ | WIP
Motion Detect | ⚠️ | WIP
Heart Beat | — | N/A
Low Latency Off-Body Detect | — | N/A
Accelerometer (Uncalibrated) | ⚠️ | WIP
Hinge Angle | ️ | WIP
Hinge Angle | ️ | rememberHingeAngleSensorState()
Head Tracker | — | N/A
Accelerometer Limited Axes | | N/A
Gyroscope Limited Axes | | N/A
Accelerometer Limited Axes (Uncalibrated) | | N/A
Accelerometer Limited Axes | ⚠️ | WIP
Gyroscope Limited Axes | ✅️️ | rememberLimitedAxesGyroscopeSensorState()
Accelerometer Limited Axes (Uncalibrated) | ⚠️ | WIP
Gyroscope Limited Axes (Uncalibrated) | — | N/A
Heading | ⚠️ | WIP
All | — | N/A
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.mutualmobile.composesensors

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

/**
* A hinge angle sensor measures the angle, in degrees, between two integral parts of the device.
* Movement of a hinge measured by this sensor type is expected to alter the ways in which the user
* can interact with the device, for example, by unfolding or revealing a display.
* @param angle Angle between two integral parts of the device (in degrees)
* @param isAvailable Whether the current device has a HingeAngle sensor. Defaults to false.
* @param accuracy Accuracy factor of the HingeAngle sensor. Defaults to 0.
* @see [rememberHingeAngleSensorState]
*/
@Immutable
class HingeAngleSensorState internal constructor(
val angle: Float = 0f,
val isAvailable: Boolean = false,
val accuracy: Int = 0
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is HingeAngleSensorState) return false

if (angle != other.angle) return false
if (isAvailable != other.isAvailable) return false
if (accuracy != other.accuracy) return false

return true
}

override fun hashCode(): Int {
var result = angle.hashCode()
result = 31 * result + isAvailable.hashCode()
result = 31 * result + accuracy.hashCode()
return result
}

override fun toString(): String {
return "HingeAngleSensorState(angle=$angle, isAvailable=$isAvailable, accuracy=$accuracy)"
}
}

/**
* Creates and [remember]s an instance of [HingeAngleSensorState].
* @param sensorDelay The rate at which the raw sensor data should be received.
* Defaults to [SensorDelay.Normal].
* @param onError Callback invoked on every error state.
*/
@Composable
fun rememberHingeAngleSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {}
): HingeAngleSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.HingeAngle,
sensorDelay = sensorDelay,
onError = onError
)
val hingeAngleSensorState = remember { mutableStateOf(HingeAngleSensorState()) }

LaunchedEffect(
key1 = sensorState,
block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
hingeAngleSensorState.value = HingeAngleSensorState(
angle = sensorStateValues[0],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy
)
}
}
)

return hingeAngleSensorState.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.mutualmobile.composesensors

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

/**
* Equivalent to Gyroscope Sensor but supporting cases where one or two axes are not supported.
* @param xRotation Angular speed around the x-axis (if supported). Defaults to 0f.
* @param yRotation Angular speed around the y-axis (if supported). Defaults to 0f.
* @param zRotation Angular speed around the z-axis (if supported). Defaults to 0f.
* @param xAxisSupported Angular speed supported for x-axis. Defaults to 0f.
* @param yAxisSupported Angular speed supported for y-axis. Defaults to 0f.
* @param zAxisSupported Angular speed supported for z-axis. Defaults to 0f.
* @param isAvailable Whether the current device has a gyroscope sensor. Defaults to false.
* @param accuracy Accuracy factor of the gyroscope sensor. Defaults to 0.
*/
@Immutable
class LimitedAxesGyroscopeSensorState internal constructor(
val xRotation: Float = 0f,
val yRotation: Float = 0f,
val zRotation: Float = 0f,
val xAxisSupported: Float = 0f,
val yAxisSupported: Float = 0f,
val zAxisSupported: Float = 0f,
val isAvailable: Boolean = false,
val accuracy: Int = 0
) {

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as LimitedAxesGyroscopeSensorState

if (xRotation != other.xRotation) return false
if (yRotation != other.yRotation) return false
if (zRotation != other.zRotation) return false
if (xAxisSupported != other.xAxisSupported) return false
if (yAxisSupported != other.yAxisSupported) return false
if (zAxisSupported != other.zAxisSupported) return false
if (isAvailable != other.isAvailable) return false
if (accuracy != other.accuracy) return false

return true
}

override fun hashCode(): Int {
var result = xRotation.hashCode()
result = 31 * result + yRotation.hashCode()
result = 31 * result + zRotation.hashCode()
result = 31 * result + xAxisSupported.hashCode()
result = 31 * result + yAxisSupported.hashCode()
result = 31 * result + zAxisSupported.hashCode()
result = 31 * result + isAvailable.hashCode()
result = 31 * result + accuracy
return result
}

override fun toString(): String {
return "LimitedAxesGyroscopeSensorState(xRotation=$xRotation, yRotation=$yRotation, " +
"zRotation=$zRotation, xAxisSupported=$xAxisSupported, " +
"yAxisSupported=$yAxisSupported, zAxisSupported=$zAxisSupported, " +
"isAvailable=$isAvailable, accuracy=$accuracy)"
}
}

/**
* Creates and [remember]s an instance of [LimitedAxesGyroscopeSensorState].
* @param sensorDelay The rate at which the raw sensor data should be received.
* Defaults to [SensorDelay.Normal].
* @param onError Callback invoked on every error state.
*/

@Composable
fun rememberLimitedAxesGyroscopeSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {}
): LimitedAxesGyroscopeSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.GyroscopeLimitedAxes,
sensorDelay = sensorDelay,
onError = onError
)

val gyroscopeLimitedAxesSensor = remember { mutableStateOf(LimitedAxesGyroscopeSensorState()) }

LaunchedEffect(key1 = sensorState, block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
gyroscopeLimitedAxesSensor.value = LimitedAxesGyroscopeSensorState(
xRotation = sensorStateValues[0],
yRotation = sensorStateValues[1],
zRotation = sensorStateValues[2],
xAxisSupported = sensorStateValues[3],
yAxisSupported = sensorStateValues[4],
zAxisSupported = sensorStateValues[5],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy
)
}
})

return gyroscopeLimitedAxesSensor.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.mutualmobile.composesensors

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

/**
* An Uncalibrated Magnetic Field sensor is similar to [SensorType.MagneticField] but the hard iron calibration is reported separately instead of being included in the measurement. Factory calibration and temperature compensation will still be applied to the "uncalibrated" measurement. Assumptions are that the magnetic field is due to the Earth's poles being avoided.
* Hard iron - These distortions arise due to the magnetized iron, steel or permanent magnets on the device.
* Soft iron - These distortions arise due to the interaction with the earth's magnetic field.
* @param xStrength The measured magnetic field in X-axis. Soft iron and temperature calibrations are applied. But the hard iron calibration is not applied. The value is calculated in micro-Tesla (uT).
* @param yStrength The measured magnetic field in Y-axis. Soft iron and temperature calibrations are applied. But the hard iron calibration is not applied. The value is calculated in micro-Tesla (uT).
* @param zStrength The measured magnetic field in Z-axis. Soft iron and temperature calibrations are applied. But the hard iron calibration is not applied. The value is calculated in micro-Tesla (uT).
* @param xBias The iron bias estimated in X-axis. It is a component of the estimated hard iron calibration. The value is calculated in micro-Tesla (uT).
* @param yBias The iron bias estimated in Y-axis. It is a component of the estimated hard iron calibration. The value is calculated in micro-Tesla (uT).
* @param zBias The iron bias estimated in Z-axis. It is a component of the estimated hard iron calibration. The value is calculated in micro-Tesla (uT).
* @param isAvailable Whether the current device has an uncalibrated magnetic field sensor. Defaults to false.
* @param accuracy Accuracy factor of the uncalibrated magnetic field sensor. Defaults to 0.
*/
@Immutable
class UncalibratedMagneticFieldSensorState internal constructor(
val xStrength: Float = 0f,
val yStrength: Float = 0f,
val zStrength: Float = 0f,
val xBias: Float = 0f,
val yBias: Float = 0f,
val zBias: Float = 0f,
val isAvailable: Boolean = false,
val accuracy: Int = 0
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is UncalibratedMagneticFieldSensorState) return false

if (xStrength != other.xStrength) return false
if (yStrength != other.yStrength) return false
if (zStrength != other.zStrength) return false
if (xBias != other.xBias) return false
if (yBias != other.yBias) return false
if (zBias != other.zBias) return false
if (isAvailable != other.isAvailable) return false
if (accuracy != other.accuracy) return false

return true
}

override fun hashCode(): Int {
var result = xStrength.hashCode()
result = 31 * result + yStrength.hashCode()
result = 31 * result + zStrength.hashCode()
result = 31 * result + xBias.hashCode()
result = 31 * result + yBias.hashCode()
result = 31 * result + zBias.hashCode()
result = 31 * result + accuracy.hashCode()
result = 31 * result + isAvailable.hashCode()
return result
}

override fun toString(): String {
return "UncalibratedMagneticFieldSensorState(xStrength=$xStrength, yStrength=$yStrength, zStrength=$zStrength, " +
"xBias=$xBias, yBias=$yBias, zBias=$zBias, " +
"isAvailable=$isAvailable, accuracy=$accuracy)"
}
}

/**
* Creates and [remember]s an instance of [UncalibratedMagneticFieldSensorState].
* @param sensorDelay The rate at which the raw sensor data should be received.
* Defaults to [SensorDelay.Normal].
* @param onError Callback invoked on every error state.
*/
@Composable
fun rememberUncalibratedMagneticFieldSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {}
): UncalibratedMagneticFieldSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.MagneticFieldUncalibrated,
sensorDelay = sensorDelay,
onError = onError
)
val uncalibratedMagneticFieldSensorState =
remember { mutableStateOf(UncalibratedMagneticFieldSensorState()) }

LaunchedEffect(
key1 = sensorState,
block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
uncalibratedMagneticFieldSensorState.value = UncalibratedMagneticFieldSensorState(
xStrength = sensorStateValues[0],
yStrength = sensorStateValues[1],
zStrength = sensorStateValues[2],
xBias = sensorStateValues[3],
yBias = sensorStateValues[4],
zBias = sensorStateValues[5],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy
)
}
}
)

return uncalibratedMagneticFieldSensorState.value
}

0 comments on commit b3887e6

Please sign in to comment.