Improve app reliability
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Signed-off-by: Severin Kaderli <severin@kaderli.dev>
This commit is contained in:
parent
5fb08ef5b4
commit
efd8e63e4e
3 changed files with 82 additions and 33 deletions
|
@ -5,7 +5,7 @@ class Constants {
|
|||
* @type {Number}
|
||||
*/
|
||||
static get CLOCK_TIME() {
|
||||
return 1000;
|
||||
return 500;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,7 @@ abstract class BaseSensorActivity : BaseActivity(), SensorEventListener {
|
|||
super.onResume()
|
||||
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
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() {
|
||||
|
|
|
@ -25,6 +25,9 @@ class ReceiveActivity : BaseSensorActivity() {
|
|||
*/
|
||||
private var signal = ArrayList<Sample<Signal>>()
|
||||
|
||||
/**
|
||||
* Flag that determines if the preamble was already received.
|
||||
*/
|
||||
private var preambleReceived = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -50,19 +53,51 @@ class ReceiveActivity : BaseSensorActivity() {
|
|||
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 {
|
||||
val maxValue = samples.maxByOrNull { 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 {
|
||||
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 {
|
||||
val cleanedSignal = cleanSignal(signal)
|
||||
val compressedSignal = compressSignal(cleanedSignal)
|
||||
|
@ -89,9 +124,11 @@ class ReceiveActivity : BaseSensorActivity() {
|
|||
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>> {
|
||||
// TODO: Improve this method
|
||||
// Remove outliers from the signal (single signal spikes or drops)
|
||||
val cleanSignal = signal.filterIndexed { index, sample ->
|
||||
var elementCount = 1
|
||||
|
||||
|
@ -127,40 +164,51 @@ class ReceiveActivity : BaseSensorActivity() {
|
|||
|
||||
private fun analyzePacketSignal(): List<Int> {
|
||||
val cleanedSignal = cleanSignal(signal)
|
||||
val compressedSignal = compressSignal(cleanedSignal)
|
||||
|
||||
if (compressedSignal.size < 2) {
|
||||
return listOf()
|
||||
}
|
||||
|
||||
val timeDifferences = ArrayList<Long>()
|
||||
compressedSignal.forEachIndexed { index, sample ->
|
||||
var maxSamplesInARow = 0
|
||||
var count = 0
|
||||
cleanedSignal.forEachIndexed { index, sample ->
|
||||
if(index == 0) {
|
||||
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>()
|
||||
compressedSignal.forEachIndexed { index, sample ->
|
||||
if (index == 0) {
|
||||
return@forEachIndexed
|
||||
var lastSignal: Sample<Signal>? = null
|
||||
var isFirstSignal = true
|
||||
var samplesSinceLastSignal = 0
|
||||
cleanedSignal.forEach { sample ->
|
||||
if (lastSignal == null) {
|
||||
lastSignal = sample
|
||||
}
|
||||
|
||||
val timeDifference = sample.timestamp - compressedSignal[index - 1].timestamp
|
||||
if (timeDifference > clockTimeThreshold && timeDifference < 2500) {
|
||||
if (sample.value != lastSignal!!.value) {
|
||||
if(samplesSinceLastSignal > (maxSamplesInARow * 0.75) || isFirstSignal) {
|
||||
//Log.i(TAG, "$samplesSinceLastSignal")
|
||||
if (sample.value == Signal.High) {
|
||||
packetData.add(0)
|
||||
} else {
|
||||
packetData.add(1)
|
||||
}
|
||||
isFirstSignal = false
|
||||
samplesSinceLastSignal=0
|
||||
}
|
||||
lastSignal = sample
|
||||
}
|
||||
samplesSinceLastSignal++
|
||||
}
|
||||
|
||||
Log.i(TAG, "$timeDifferences")
|
||||
|
||||
//Log.i(TAG, "$cleanSignal")
|
||||
|
||||
return packetData
|
||||
|
@ -171,15 +219,12 @@ class ReceiveActivity : BaseSensorActivity() {
|
|||
samples.add(Sample(magneticFieldStrength))
|
||||
|
||||
// Determine whether the sample is a high or low signal
|
||||
val currentSignal: Sample<Signal> = if (isHigh(magneticFieldStrength)) {
|
||||
Sample(Signal.High)
|
||||
} else {
|
||||
Sample(Signal.Low)
|
||||
}
|
||||
val currentSignal = getSignalForSample(samples.last()) ?: return
|
||||
signal.add(currentSignal)
|
||||
|
||||
// Try to detect the preamble in the signal
|
||||
if (!preambleReceived) {
|
||||
// If we detect the preamble we change the status on the screen and clear the existing signal data.
|
||||
if (detectPreamble()) {
|
||||
preambleReceived = true
|
||||
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) {
|
||||
val packet = analyzePacketSignal();
|
||||
// Get the decoded packet data
|
||||
val packet = analyzePacketSignal()
|
||||
|
||||
// Get the payload length of in the data
|
||||
var payloadLength = 0
|
||||
if (packet.size >= 4) {
|
||||
payloadLength = listToInteger(packet.take(4))
|
||||
|
@ -207,6 +255,7 @@ class ReceiveActivity : BaseSensorActivity() {
|
|||
|
||||
receiveValue.text = payload
|
||||
|
||||
// TODO: CRC show and calculate if it's correct
|
||||
if (packet.size >= 4 + (8 * payloadLength) + 8) {
|
||||
// CRC Check
|
||||
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 {
|
||||
var value: Int = 0
|
||||
var value = 0
|
||||
|
||||
for (bit in values) {
|
||||
value = (value shl 1) + bit
|
||||
|
|
Reference in a new issue