Improve app reliability
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

Signed-off-by: Severin Kaderli <severin@kaderli.dev>
This commit is contained in:
Severin Kaderli 2022-12-22 20:39:09 +01:00
parent 5fb08ef5b4
commit efd8e63e4e
Signed by: severinkaderli
GPG key ID: F419F8835B72F0C4
3 changed files with 82 additions and 33 deletions

View file

@ -5,7 +5,7 @@ class Constants {
* @type {Number} * @type {Number}
*/ */
static get CLOCK_TIME() { static get CLOCK_TIME() {
return 1000; return 500;
} }
/** /**

View file

@ -16,7 +16,7 @@ abstract class BaseSensorActivity : BaseActivity(), SensorEventListener {
super.onResume() super.onResume()
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI); sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME);
} }
override fun onStop() { override fun onStop() {

View file

@ -25,6 +25,9 @@ class ReceiveActivity : BaseSensorActivity() {
*/ */
private var signal = ArrayList<Sample<Signal>>() private var signal = ArrayList<Sample<Signal>>()
/**
* Flag that determines if the preamble was already received.
*/
private var preambleReceived = false private var preambleReceived = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -50,19 +53,51 @@ class ReceiveActivity : BaseSensorActivity() {
return getMidRangeOfData() + 3 return getMidRangeOfData() + 3
} }
return getMidRangeOfData(); return getMidRangeOfData() + 2
}
private fun getThresholdForLowSignals(): Float {
if (getRangeOfData() < 3) {
return getMidRangeOfData() + 3
}
return getMidRangeOfData() - 2
} }
private fun getMidRangeOfData(): Float { private fun getMidRangeOfData(): Float {
val maxValue = samples.maxByOrNull { it.value } ?: Sample(0f) val maxValue = samples.maxByOrNull { it.value } ?: Sample(0f)
val minValue = samples.minByOrNull { it.value } ?: Sample(0f) val minValue = samples.minByOrNull { it.value } ?: Sample(0f)
return (maxValue.value + minValue.value) / 2; return (maxValue.value + minValue.value) / 2
} }
private fun isHigh(value: Float): Boolean { private fun isHigh(value: Float): Boolean {
return value > getThresholdForHighSignals() return value > getThresholdForHighSignals()
} }
private fun isLow(value: Float): Boolean {
return value < getThresholdForLowSignals()
}
/**
* Check if the given sample should count as a high or low signal. If the sample is inside
* the threshold area it is not counted.
*/
private fun getSignalForSample(sample: Sample<Float>): Sample<Signal>? {
if (isHigh(sample.value)) {
return Sample(Signal.High)
}
if (isLow(sample.value)) {
return Sample(Signal.Low)
}
return null
}
/**
* Attempts to detect the preamble in the already received signal. If it can find the preamble it returns true and
* false otherwise.
*/
private fun detectPreamble(): Boolean { private fun detectPreamble(): Boolean {
val cleanedSignal = cleanSignal(signal) val cleanedSignal = cleanSignal(signal)
val compressedSignal = compressSignal(cleanedSignal) val compressedSignal = compressSignal(cleanedSignal)
@ -89,9 +124,11 @@ class ReceiveActivity : BaseSensorActivity() {
return false return false
} }
/**
* This functions takes the signal and filters out samples that are only in a cluster of 3 or less of the same signal.
* This way we can remove single jumps that occur in the signal.
*/
private fun cleanSignal(signal: List<Sample<Signal>>): List<Sample<Signal>> { private fun cleanSignal(signal: List<Sample<Signal>>): List<Sample<Signal>> {
// TODO: Improve this method
// Remove outliers from the signal (single signal spikes or drops)
val cleanSignal = signal.filterIndexed { index, sample -> val cleanSignal = signal.filterIndexed { index, sample ->
var elementCount = 1 var elementCount = 1
@ -127,40 +164,51 @@ class ReceiveActivity : BaseSensorActivity() {
private fun analyzePacketSignal(): List<Int> { private fun analyzePacketSignal(): List<Int> {
val cleanedSignal = cleanSignal(signal) val cleanedSignal = cleanSignal(signal)
val compressedSignal = compressSignal(cleanedSignal)
if (compressedSignal.size < 2) { var maxSamplesInARow = 0
return listOf() var count = 0
} cleanedSignal.forEachIndexed { index, sample ->
if(index == 0) {
val timeDifferences = ArrayList<Long>()
compressedSignal.forEachIndexed { index, sample ->
if (index == 0) {
return@forEachIndexed return@forEachIndexed
} }
timeDifferences.add(sample.timestamp - compressedSignal[index - 1].timestamp) if(sample.value == cleanedSignal[index - 1].value) {
count ++
if(count > maxSamplesInARow) {
maxSamplesInARow = count
}
} else {
count = 0
}
} }
val clockTimeThreshold = 900//timeDifferences.max() * 0.75
val packetData = ArrayList<Int>() val packetData = ArrayList<Int>()
compressedSignal.forEachIndexed { index, sample -> var lastSignal: Sample<Signal>? = null
if (index == 0) { var isFirstSignal = true
return@forEachIndexed var samplesSinceLastSignal = 0
cleanedSignal.forEach { sample ->
if (lastSignal == null) {
lastSignal = sample
} }
val timeDifference = sample.timestamp - compressedSignal[index - 1].timestamp if (sample.value != lastSignal!!.value) {
if (timeDifference > clockTimeThreshold && timeDifference < 2500) { if(samplesSinceLastSignal > (maxSamplesInARow * 0.75) || isFirstSignal) {
if (sample.value == Signal.High) { //Log.i(TAG, "$samplesSinceLastSignal")
packetData.add(0) if (sample.value == Signal.High) {
} else { packetData.add(0)
packetData.add(1) } else {
packetData.add(1)
}
isFirstSignal = false
samplesSinceLastSignal=0
} }
lastSignal = sample
} }
samplesSinceLastSignal++
} }
Log.i(TAG, "$timeDifferences")
//Log.i(TAG, "$cleanSignal") //Log.i(TAG, "$cleanSignal")
return packetData return packetData
@ -171,15 +219,12 @@ class ReceiveActivity : BaseSensorActivity() {
samples.add(Sample(magneticFieldStrength)) samples.add(Sample(magneticFieldStrength))
// Determine whether the sample is a high or low signal // Determine whether the sample is a high or low signal
val currentSignal: Sample<Signal> = if (isHigh(magneticFieldStrength)) { val currentSignal = getSignalForSample(samples.last()) ?: return
Sample(Signal.High)
} else {
Sample(Signal.Low)
}
signal.add(currentSignal) signal.add(currentSignal)
// Try to detect the preamble in the signal // Try to detect the preamble in the signal
if (!preambleReceived) { if (!preambleReceived) {
// If we detect the preamble we change the status on the screen and clear the existing signal data.
if (detectPreamble()) { if (detectPreamble()) {
preambleReceived = true preambleReceived = true
preambleStatus.setText(R.string.preamble_status_detected) preambleStatus.setText(R.string.preamble_status_detected)
@ -189,9 +234,12 @@ class ReceiveActivity : BaseSensorActivity() {
} }
} }
// After the preamble is detected we attempt to decode the packet.
if (preambleReceived) { if (preambleReceived) {
val packet = analyzePacketSignal(); // Get the decoded packet data
val packet = analyzePacketSignal()
// Get the payload length of in the data
var payloadLength = 0 var payloadLength = 0
if (packet.size >= 4) { if (packet.size >= 4) {
payloadLength = listToInteger(packet.take(4)) payloadLength = listToInteger(packet.take(4))
@ -207,6 +255,7 @@ class ReceiveActivity : BaseSensorActivity() {
receiveValue.text = payload receiveValue.text = payload
// TODO: CRC show and calculate if it's correct
if (packet.size >= 4 + (8 * payloadLength) + 8) { if (packet.size >= 4 + (8 * payloadLength) + 8) {
// CRC Check // CRC Check
val crc = listToInteger(packet.take(4 + (8 * payloadLength) + 8).takeLast(8)) val crc = listToInteger(packet.take(4 + (8 * payloadLength) + 8).takeLast(8))
@ -217,7 +266,7 @@ class ReceiveActivity : BaseSensorActivity() {
} }
private fun listToInteger(values: List<Int>): Int { private fun listToInteger(values: List<Int>): Int {
var value: Int = 0 var value = 0
for (bit in values) { for (bit in values) {
value = (value shl 1) + bit value = (value shl 1) + bit