feat: enhance message handling and logging in demodulation and TCP channel
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include "demod.h"
|
#include "demod.h"
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
bool is_message_ready = false;
|
bool is_message_ready = false;
|
||||||
|
|
||||||
@@ -188,6 +189,10 @@ void decodeBatch()
|
|||||||
function_bits = (code_words[i] >> 11) & 0x3;
|
function_bits = (code_words[i] >> 11) & 0x3;
|
||||||
int addressBits = (code_words[i] >> 13) & 0x3ffff;
|
int addressBits = (code_words[i] >> 13) & 0x3ffff;
|
||||||
address = (addressBits << 3) | frame;
|
address = (addressBits << 3) | frame;
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, "DEMOD", "addr_cw: raw=0x%08X addr=%u func=%d frame=%d bch_err=%d parity_err=%d",
|
||||||
|
code_words[i], address, function_bits, frame, code_words_bch_error[i] ? 1 : 0, parityError ? 1 : 0);
|
||||||
|
|
||||||
numeric_msg = "";
|
numeric_msg = "";
|
||||||
alpha_msg = "";
|
alpha_msg = "";
|
||||||
alpha_bit_buffer_bits = 0;
|
alpha_bit_buffer_bits = 0;
|
||||||
@@ -201,6 +206,9 @@ void decodeBatch()
|
|||||||
if (parityError) parity_errors++;
|
if (parityError) parity_errors++;
|
||||||
if (code_words_bch_error[i]) bch_errors++;
|
if (code_words_bch_error[i]) bch_errors++;
|
||||||
|
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, "DEMOD", "msg_cw: raw=0x%08X msgbits=0x%05X bch_err=%d parity_err=%d",
|
||||||
|
code_words[i], messageBits, code_words_bch_error[i] ? 1 : 0, parityError ? 1 : 0);
|
||||||
|
|
||||||
for (int j = 16; j >= 0; j -= 4)
|
for (int j = 16; j >= 0; j -= 4)
|
||||||
{
|
{
|
||||||
uint32_t numericBits = (messageBits >> j) & 0xf;
|
uint32_t numericBits = (messageBits >> j) & 0xf;
|
||||||
@@ -325,6 +333,7 @@ void processBasebandSample(double sample)
|
|||||||
|
|
||||||
if (got_SC)
|
if (got_SC)
|
||||||
{
|
{
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, "DEMOD", "sync_found: inverted=%d bits=0x%08X", bit_inverted ? 1 : 0, bits);
|
||||||
bits = 0;
|
bits = 0;
|
||||||
bit_cnt = 0;
|
bit_cnt = 0;
|
||||||
code_words[0] = POCSAG_SYNCCODE;
|
code_words[0] = POCSAG_SYNCCODE;
|
||||||
@@ -381,5 +390,90 @@ void processOneSample(int8_t i, int8_t q)
|
|||||||
float deviation;
|
float deviation;
|
||||||
double fmDemod = phaseDiscri.phaseDiscriminatorDelta(iq, magsqRaw, deviation);
|
double fmDemod = phaseDiscri.phaseDiscriminatorDelta(iq, magsqRaw, deviation);
|
||||||
|
|
||||||
processBasebandSample(fmDemod);
|
double filt = lowpassBaud.filter(fmDemod);
|
||||||
|
|
||||||
|
if (!got_SC) {
|
||||||
|
preambleMovingAverage(filt);
|
||||||
|
dc_offset = preambleMovingAverage.asDouble();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool data = (filt - dc_offset) >= 0.0;
|
||||||
|
|
||||||
|
if (data != prev_data) {
|
||||||
|
sync_cnt = SAMPLES_PER_SYMBOL / 2;
|
||||||
|
} else {
|
||||||
|
sync_cnt--;
|
||||||
|
|
||||||
|
if (sync_cnt <= 0) {
|
||||||
|
if (bit_inverted) {
|
||||||
|
data_bit = data;
|
||||||
|
} else {
|
||||||
|
data_bit = !data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits = (bits << 1) | data_bit;
|
||||||
|
bit_cnt++;
|
||||||
|
|
||||||
|
if (bit_cnt > 32) {
|
||||||
|
bit_cnt = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bit_cnt == 32 && !got_SC) {
|
||||||
|
if (bits == POCSAG_SYNCCODE) {
|
||||||
|
got_SC = true;
|
||||||
|
bit_inverted = false;
|
||||||
|
} else if (bits == POCSAG_SYNCCODE_INV) {
|
||||||
|
got_SC = true;
|
||||||
|
bit_inverted = true;
|
||||||
|
} else if (pop_cnt(bits ^ POCSAG_SYNCCODE) <= 3) {
|
||||||
|
uint32_t corrected_cw;
|
||||||
|
if (bchDecode(bits, corrected_cw) && corrected_cw == POCSAG_SYNCCODE) {
|
||||||
|
got_SC = true;
|
||||||
|
bit_inverted = false;
|
||||||
|
}
|
||||||
|
} else if (pop_cnt(bits ^ POCSAG_SYNCCODE_INV) <= 3) {
|
||||||
|
uint32_t corrected_cw;
|
||||||
|
if (bchDecode(~bits, corrected_cw) && corrected_cw == POCSAG_SYNCCODE) {
|
||||||
|
got_SC = true;
|
||||||
|
bit_inverted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_SC) {
|
||||||
|
__android_log_print(ANDROID_LOG_DEBUG, "DEMOD", "sync_found: inverted=%d bits=0x%08X", bit_inverted ? 1 : 0, bits);
|
||||||
|
bits = 0;
|
||||||
|
bit_cnt = 0;
|
||||||
|
code_words[0] = POCSAG_SYNCCODE;
|
||||||
|
word_cnt = 1;
|
||||||
|
}
|
||||||
|
} else if (bit_cnt == 32 && got_SC) {
|
||||||
|
uint32_t corrected_cw;
|
||||||
|
code_words_bch_error[word_cnt] = !bchDecode(bits, corrected_cw);
|
||||||
|
code_words[word_cnt] = corrected_cw;
|
||||||
|
word_cnt++;
|
||||||
|
|
||||||
|
if (word_cnt == 1 && corrected_cw != POCSAG_SYNCCODE) {
|
||||||
|
got_SC = false;
|
||||||
|
bit_inverted = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word_cnt == PAGERDEMOD_BATCH_WORDS) {
|
||||||
|
decodeBatch();
|
||||||
|
batch_num++;
|
||||||
|
word_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bits = 0;
|
||||||
|
bit_cnt = 0;
|
||||||
|
|
||||||
|
if (address > 0 && !numeric_msg.empty()) {
|
||||||
|
is_message_ready = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_cnt = SAMPLES_PER_SYMBOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_data = data;
|
||||||
}
|
}
|
||||||
@@ -255,27 +255,33 @@ void clientThread(std::string host, int port)
|
|||||||
std::lock_guard<std::mutex> demodLock(demodDataMutex);
|
std::lock_guard<std::mutex> demodLock(demodDataMutex);
|
||||||
processOneSample(i_ds, q_ds);
|
processOneSample(i_ds, q_ds);
|
||||||
|
|
||||||
|
if (is_message_ready)
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
std::lock_guard<std::mutex> msgLock(msgMutex);
|
||||||
|
|
||||||
|
std::string message_content;
|
||||||
|
if (function_bits == 3) {
|
||||||
|
message_content = alpha_msg;
|
||||||
|
} else {
|
||||||
|
message_content = numeric_msg;
|
||||||
|
}
|
||||||
|
if (message_content.empty()) {
|
||||||
|
message_content = alpha_msg.empty() ? numeric_msg : alpha_msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << "[MSG]" << address << "|" << function_bits << "|" << message_content;
|
||||||
|
messageBuffer.push_back(ss.str());
|
||||||
|
|
||||||
|
is_message_ready = false;
|
||||||
|
numeric_msg.clear();
|
||||||
|
alpha_msg.clear();
|
||||||
|
}
|
||||||
|
|
||||||
acc_i = acc_q = 0;
|
acc_i = acc_q = 0;
|
||||||
decim_counter = 0;
|
decim_counter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_message_ready)
|
|
||||||
{
|
|
||||||
std::ostringstream ss;
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> demodLock(demodDataMutex);
|
|
||||||
std::lock_guard<std::mutex> msgLock(msgMutex);
|
|
||||||
|
|
||||||
std::string message_content = alpha_msg.empty() ? numeric_msg : alpha_msg;
|
|
||||||
ss << "[MSG]" << address << "|" << function_bits << "|" << message_content;
|
|
||||||
messageBuffer.push_back(ss.str());
|
|
||||||
|
|
||||||
is_message_ready = false;
|
|
||||||
|
|
||||||
numeric_msg.clear();
|
|
||||||
alpha_msg.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n < 0 && running)
|
if (n < 0 && running)
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ class RtlTcpChannelHandler : EventChannel.StreamHandler {
|
|||||||
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
|
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
|
||||||
android.util.Log.d("RTL-TCP", "evt_listen")
|
android.util.Log.d("RTL-TCP", "evt_listen")
|
||||||
this.eventSink = events
|
this.eventSink = events
|
||||||
|
lastConnectedState = true
|
||||||
startPolling()
|
startPolling()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,34 +78,76 @@ class RtlTcpChannelHandler : EventChannel.StreamHandler {
|
|||||||
android.util.Log.w("RTL-TCP", "evt_null");
|
android.util.Log.w("RTL-TCP", "evt_null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
val connected = try {
|
||||||
|
isConnected()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("RTL-TCP", "isConnected() failed", e)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
val strength = try {
|
||||||
|
getSignalStrength()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("RTL-TCP", "getSignalStrength() failed", e)
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
val logs = try {
|
||||||
|
pollMessages()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("RTL-TCP", "pollMessages() failed", e)
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
val connected = isConnected()
|
|
||||||
val strength = getSignalStrength()
|
|
||||||
val logs = pollMessages()
|
|
||||||
val regex = "\\[MSG\\]\\s*(\\d+)\\|(-?\\d+)\\|(.*)".toRegex()
|
val regex = "\\[MSG\\]\\s*(\\d+)\\|(-?\\d+)\\|(.*)".toRegex()
|
||||||
|
|
||||||
if (connected != lastConnectedState || connected) {
|
android.util.Log.d("RTL-TCP", "poll: connected=$connected magsqRaw=$strength logsLen=${logs.length}")
|
||||||
|
if (logs.isNotEmpty()) {
|
||||||
|
val preview = if (logs.length > 1000) logs.substring(0, 1000) + "..." else logs
|
||||||
|
android.util.Log.d("RTL-TCP", "pollLogs: $preview")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connected != lastConnectedState) {
|
||||||
val statusMap = mutableMapOf<String, Any?>()
|
val statusMap = mutableMapOf<String, Any?>()
|
||||||
statusMap["connected"] = connected
|
statusMap["connected"] = connected
|
||||||
statusMap["magsqRaw"] = strength
|
statusMap["magsqRaw"] = strength
|
||||||
eventSink?.success(statusMap)
|
try {
|
||||||
|
eventSink?.success(statusMap)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("RTL-TCP", "eventSink status send failed", e)
|
||||||
|
}
|
||||||
lastConnectedState = connected
|
lastConnectedState = connected
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logs.isNotEmpty()) {
|
if (logs.isNotEmpty()) {
|
||||||
regex.findAll(logs).forEach { match ->
|
regex.findAll(logs).forEach { match ->
|
||||||
try {
|
try {
|
||||||
|
val addr = match.groupValues[1]
|
||||||
|
val func = match.groupValues[2]
|
||||||
|
val raw = match.groupValues[3]
|
||||||
|
android.util.Log.d("RTL-TCP", "msg_match: addr=$addr func=$func raw_len=${raw.length}")
|
||||||
|
|
||||||
|
val gbkBytes = raw.toByteArray(Charsets.ISO_8859_1)
|
||||||
|
val utf8String = try {
|
||||||
|
String(gbkBytes, Charset.forName("GBK"))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("RTL-TCP", "GBK decode failed", e)
|
||||||
|
raw
|
||||||
|
}
|
||||||
|
|
||||||
|
android.util.Log.d("RTL-TCP", "msg_decoded: addr=$addr func=$func numeric=$utf8String")
|
||||||
|
|
||||||
val dataMap = mutableMapOf<String, Any?>()
|
val dataMap = mutableMapOf<String, Any?>()
|
||||||
dataMap["address"] = match.groupValues[1]
|
dataMap["address"] = addr
|
||||||
dataMap["func"] = match.groupValues[2]
|
dataMap["func"] = func
|
||||||
|
|
||||||
val gbkBytes = match.groupValues[3].toByteArray(Charsets.ISO_8859_1)
|
|
||||||
val utf8String = String(gbkBytes, Charset.forName("GBK"))
|
|
||||||
dataMap["numeric"] = utf8String
|
dataMap["numeric"] = utf8String
|
||||||
|
|
||||||
dataMap["magsqRaw"] = strength
|
dataMap["magsqRaw"] = strength
|
||||||
|
|
||||||
eventSink?.success(dataMap)
|
try {
|
||||||
|
eventSink?.success(dataMap)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.util.Log.e("RTL-TCP", "eventSink data send failed", e)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
android.util.Log.e("RTL-TCP", "decode_fail", e)
|
android.util.Log.e("RTL-TCP", "decode_fail", e)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user