mirror of
https://github.com/meshtastic/firmware.git
synced 2025-07-29 18:05:42 +00:00
Merge branch 'master' into feature/stm32wl-correctness
This commit is contained in:
commit
3de02d0ce6
@ -205,6 +205,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
// app not to send locations on our behalf.
|
||||
fromRadioScratch.which_payload_variant = meshtastic_FromRadio_my_info_tag;
|
||||
strncpy(myNodeInfo.pio_env, optstr(APP_ENV), sizeof(myNodeInfo.pio_env));
|
||||
myNodeInfo.nodedb_count = static_cast<uint16_t>(nodeDB->getNumMeshNodes());
|
||||
fromRadioScratch.my_info = myNodeInfo;
|
||||
state = STATE_SEND_UIDATA;
|
||||
|
||||
|
@ -652,11 +652,12 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
shouldIgnoreNonstandardPorts = true;
|
||||
#endif
|
||||
if (shouldIgnoreNonstandardPorts && p->which_payload_variant == meshtastic_MeshPacket_decoded_tag &&
|
||||
IS_ONE_OF(p->decoded.portnum, meshtastic_PortNum_ATAK_FORWARDER, meshtastic_PortNum_ATAK_PLUGIN,
|
||||
meshtastic_PortNum_PAXCOUNTER_APP, meshtastic_PortNum_IP_TUNNEL_APP, meshtastic_PortNum_AUDIO_APP,
|
||||
meshtastic_PortNum_PRIVATE_APP, meshtastic_PortNum_DETECTION_SENSOR_APP, meshtastic_PortNum_RANGE_TEST_APP,
|
||||
meshtastic_PortNum_REMOTE_HARDWARE_APP)) {
|
||||
LOG_DEBUG("Ignore packet on blacklisted portnum for CORE_PORTNUMS_ONLY");
|
||||
!IS_ONE_OF(p->decoded.portnum, meshtastic_PortNum_TEXT_MESSAGE_APP, meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP,
|
||||
meshtastic_PortNum_POSITION_APP, meshtastic_PortNum_NODEINFO_APP, meshtastic_PortNum_ROUTING_APP,
|
||||
meshtastic_PortNum_TELEMETRY_APP, meshtastic_PortNum_ADMIN_APP, meshtastic_PortNum_ALERT_APP,
|
||||
meshtastic_PortNum_KEY_VERIFICATION_APP, meshtastic_PortNum_WAYPOINT_APP,
|
||||
meshtastic_PortNum_STORE_FORWARD_APP, meshtastic_PortNum_TRACEROUTE_APP)) {
|
||||
LOG_DEBUG("Ignore packet on non-standard portnum for CORE_PORTNUMS_ONLY");
|
||||
cancelSending(p->from, p->id);
|
||||
skipHandle = true;
|
||||
}
|
||||
|
@ -100,6 +100,9 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
|
||||
if (decoded->variant.environment_metrics.has_iaq) {
|
||||
msgPayload["iaq"] = new JSONValue((uint)decoded->variant.environment_metrics.iaq);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_distance) {
|
||||
msgPayload["distance"] = new JSONValue(decoded->variant.environment_metrics.distance);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_wind_speed) {
|
||||
msgPayload["wind_speed"] = new JSONValue(decoded->variant.environment_metrics.wind_speed);
|
||||
}
|
||||
@ -115,6 +118,27 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp,
|
||||
if (decoded->variant.environment_metrics.has_radiation) {
|
||||
msgPayload["radiation"] = new JSONValue(decoded->variant.environment_metrics.radiation);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_ir_lux) {
|
||||
msgPayload["ir_lux"] = new JSONValue(decoded->variant.environment_metrics.ir_lux);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_uv_lux) {
|
||||
msgPayload["uv_lux"] = new JSONValue(decoded->variant.environment_metrics.uv_lux);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_weight) {
|
||||
msgPayload["weight"] = new JSONValue(decoded->variant.environment_metrics.weight);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_rainfall_1h) {
|
||||
msgPayload["rainfall_1h"] = new JSONValue(decoded->variant.environment_metrics.rainfall_1h);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_rainfall_24h) {
|
||||
msgPayload["rainfall_24h"] = new JSONValue(decoded->variant.environment_metrics.rainfall_24h);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_soil_moisture) {
|
||||
msgPayload["soil_moisture"] = new JSONValue((uint)decoded->variant.environment_metrics.soil_moisture);
|
||||
}
|
||||
if (decoded->variant.environment_metrics.has_soil_temperature) {
|
||||
msgPayload["soil_temperature"] = new JSONValue(decoded->variant.environment_metrics.soil_temperature);
|
||||
}
|
||||
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
||||
if (decoded->variant.air_quality_metrics.has_pm10_standard) {
|
||||
msgPayload["pm10"] = new JSONValue((unsigned int)decoded->variant.air_quality_metrics.pm10_standard);
|
||||
|
50
test/test_meshpacket_serializer/ports/test_encrypted.cpp
Normal file
50
test/test_meshpacket_serializer/ports/test_encrypted.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
// Test encrypted packet serialization
|
||||
void test_encrypted_packet_serialization()
|
||||
{
|
||||
meshtastic_MeshPacket packet = meshtastic_MeshPacket_init_zero;
|
||||
packet.from = 0x11223344;
|
||||
packet.to = 0x55667788;
|
||||
packet.id = 0x9999;
|
||||
packet.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
|
||||
|
||||
// Add some dummy encrypted data
|
||||
const char *encrypted_data = "encrypted_payload_data";
|
||||
packet.encrypted.size = strlen(encrypted_data);
|
||||
memcpy(packet.encrypted.bytes, encrypted_data, packet.encrypted.size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerializeEncrypted(&packet);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check basic packet fields
|
||||
TEST_ASSERT_TRUE(jsonObj.find("from") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(0x11223344, (uint32_t)jsonObj["from"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(jsonObj.find("to") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(0x55667788, (uint32_t)jsonObj["to"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(jsonObj.find("id") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(0x9999, (uint32_t)jsonObj["id"]->AsNumber());
|
||||
|
||||
// Check that it has encrypted data fields (not "payload" but "bytes" and "size")
|
||||
TEST_ASSERT_TRUE(jsonObj.find("bytes") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["bytes"]->IsString());
|
||||
|
||||
TEST_ASSERT_TRUE(jsonObj.find("size") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(22, (int)jsonObj["size"]->AsNumber()); // strlen("encrypted_payload_data") = 22
|
||||
|
||||
// The encrypted data should be hex-encoded
|
||||
std::string encrypted_hex = jsonObj["bytes"]->AsString();
|
||||
TEST_ASSERT_TRUE(encrypted_hex.length() > 0);
|
||||
// Should be twice the size of the original data (hex encoding)
|
||||
TEST_ASSERT_EQUAL(44, encrypted_hex.length()); // 22 * 2 = 44
|
||||
|
||||
delete root;
|
||||
}
|
51
test/test_meshpacket_serializer/ports/test_nodeinfo.cpp
Normal file
51
test/test_meshpacket_serializer/ports/test_nodeinfo.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static size_t encode_user_info(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_User user = meshtastic_User_init_zero;
|
||||
strcpy(user.short_name, "TEST");
|
||||
strcpy(user.long_name, "Test User");
|
||||
strcpy(user.id, "!12345678");
|
||||
user.hw_model = meshtastic_HardwareModel_HELTEC_V3;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_User_msg, &user);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Test NODEINFO_APP port
|
||||
void test_nodeinfo_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_user_info(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_NODEINFO_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check message type
|
||||
TEST_ASSERT_TRUE(jsonObj.find("type") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL_STRING("nodeinfo", jsonObj["type"]->AsString().c_str());
|
||||
|
||||
// Check payload
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Verify user data
|
||||
TEST_ASSERT_TRUE(payload.find("shortname") != payload.end());
|
||||
TEST_ASSERT_EQUAL_STRING("TEST", payload["shortname"]->AsString().c_str());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("longname") != payload.end());
|
||||
TEST_ASSERT_EQUAL_STRING("Test User", payload["longname"]->AsString().c_str());
|
||||
|
||||
delete root;
|
||||
}
|
57
test/test_meshpacket_serializer/ports/test_position.cpp
Normal file
57
test/test_meshpacket_serializer/ports/test_position.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static size_t encode_position(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Position position = meshtastic_Position_init_zero;
|
||||
position.latitude_i = 374208000; // 37.4208 degrees * 1e7
|
||||
position.longitude_i = -1221981000; // -122.1981 degrees * 1e7
|
||||
position.altitude = 123;
|
||||
position.time = 1609459200;
|
||||
position.has_altitude = true;
|
||||
position.has_latitude_i = true;
|
||||
position.has_longitude_i = true;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Position_msg, &position);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Test POSITION_APP port
|
||||
void test_position_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_position(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_POSITION_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check message type
|
||||
TEST_ASSERT_TRUE(jsonObj.find("type") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL_STRING("position", jsonObj["type"]->AsString().c_str());
|
||||
|
||||
// Check payload
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Verify position data
|
||||
TEST_ASSERT_TRUE(payload.find("latitude_i") != payload.end());
|
||||
TEST_ASSERT_EQUAL(374208000, (int)payload["latitude_i"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("longitude_i") != payload.end());
|
||||
TEST_ASSERT_EQUAL(-1221981000, (int)payload["longitude_i"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("altitude") != payload.end());
|
||||
TEST_ASSERT_EQUAL(123, (int)payload["altitude"]->AsNumber());
|
||||
|
||||
delete root;
|
||||
}
|
528
test/test_meshpacket_serializer/ports/test_telemetry.cpp
Normal file
528
test/test_meshpacket_serializer/ports/test_telemetry.cpp
Normal file
@ -0,0 +1,528 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
// Helper function to create and encode device metrics
|
||||
static size_t encode_telemetry_device_metrics(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_device_metrics_tag;
|
||||
telemetry.variant.device_metrics.battery_level = 85;
|
||||
telemetry.variant.device_metrics.has_battery_level = true;
|
||||
telemetry.variant.device_metrics.voltage = 3.72f;
|
||||
telemetry.variant.device_metrics.has_voltage = true;
|
||||
telemetry.variant.device_metrics.channel_utilization = 15.56f;
|
||||
telemetry.variant.device_metrics.has_channel_utilization = true;
|
||||
telemetry.variant.device_metrics.air_util_tx = 8.23f;
|
||||
telemetry.variant.device_metrics.has_air_util_tx = true;
|
||||
telemetry.variant.device_metrics.uptime_seconds = 12345;
|
||||
telemetry.variant.device_metrics.has_uptime_seconds = true;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Helper function to create and encode empty environment metrics (no fields set)
|
||||
static size_t encode_telemetry_environment_metrics_empty(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
|
||||
// NO fields are set - all has_* flags remain false
|
||||
// This tests that empty environment metrics don't produce any JSON fields
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Helper function to create environment metrics with ALL possible fields set
|
||||
// This function should be updated whenever new fields are added to the protobuf
|
||||
static size_t encode_telemetry_environment_metrics_all_fields(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
|
||||
// Basic environment metrics
|
||||
telemetry.variant.environment_metrics.temperature = 23.56f;
|
||||
telemetry.variant.environment_metrics.has_temperature = true;
|
||||
telemetry.variant.environment_metrics.relative_humidity = 65.43f;
|
||||
telemetry.variant.environment_metrics.has_relative_humidity = true;
|
||||
telemetry.variant.environment_metrics.barometric_pressure = 1013.27f;
|
||||
telemetry.variant.environment_metrics.has_barometric_pressure = true;
|
||||
|
||||
// Gas and air quality
|
||||
telemetry.variant.environment_metrics.gas_resistance = 50.58f;
|
||||
telemetry.variant.environment_metrics.has_gas_resistance = true;
|
||||
telemetry.variant.environment_metrics.iaq = 120;
|
||||
telemetry.variant.environment_metrics.has_iaq = true;
|
||||
|
||||
// Power measurements
|
||||
telemetry.variant.environment_metrics.voltage = 3.34f;
|
||||
telemetry.variant.environment_metrics.has_voltage = true;
|
||||
telemetry.variant.environment_metrics.current = 0.53f;
|
||||
telemetry.variant.environment_metrics.has_current = true;
|
||||
|
||||
// Light measurements (ALL 4 types)
|
||||
telemetry.variant.environment_metrics.lux = 450.12f;
|
||||
telemetry.variant.environment_metrics.has_lux = true;
|
||||
telemetry.variant.environment_metrics.white_lux = 380.95f;
|
||||
telemetry.variant.environment_metrics.has_white_lux = true;
|
||||
telemetry.variant.environment_metrics.ir_lux = 25.37f;
|
||||
telemetry.variant.environment_metrics.has_ir_lux = true;
|
||||
telemetry.variant.environment_metrics.uv_lux = 15.68f;
|
||||
telemetry.variant.environment_metrics.has_uv_lux = true;
|
||||
|
||||
// Distance measurement
|
||||
telemetry.variant.environment_metrics.distance = 150.29f;
|
||||
telemetry.variant.environment_metrics.has_distance = true;
|
||||
|
||||
// Wind measurements (ALL 4 types)
|
||||
telemetry.variant.environment_metrics.wind_direction = 180;
|
||||
telemetry.variant.environment_metrics.has_wind_direction = true;
|
||||
telemetry.variant.environment_metrics.wind_speed = 5.52f;
|
||||
telemetry.variant.environment_metrics.has_wind_speed = true;
|
||||
telemetry.variant.environment_metrics.wind_gust = 8.24f;
|
||||
telemetry.variant.environment_metrics.has_wind_gust = true;
|
||||
telemetry.variant.environment_metrics.wind_lull = 2.13f;
|
||||
telemetry.variant.environment_metrics.has_wind_lull = true;
|
||||
|
||||
// Weight measurement
|
||||
telemetry.variant.environment_metrics.weight = 75.56f;
|
||||
telemetry.variant.environment_metrics.has_weight = true;
|
||||
|
||||
// Radiation measurement
|
||||
telemetry.variant.environment_metrics.radiation = 0.13f;
|
||||
telemetry.variant.environment_metrics.has_radiation = true;
|
||||
|
||||
// Rainfall measurements (BOTH types)
|
||||
telemetry.variant.environment_metrics.rainfall_1h = 2.57f;
|
||||
telemetry.variant.environment_metrics.has_rainfall_1h = true;
|
||||
telemetry.variant.environment_metrics.rainfall_24h = 15.89f;
|
||||
telemetry.variant.environment_metrics.has_rainfall_24h = true;
|
||||
|
||||
// Soil measurements (BOTH types)
|
||||
telemetry.variant.environment_metrics.soil_moisture = 85;
|
||||
telemetry.variant.environment_metrics.has_soil_moisture = true;
|
||||
telemetry.variant.environment_metrics.soil_temperature = 18.54f;
|
||||
telemetry.variant.environment_metrics.has_soil_temperature = true;
|
||||
|
||||
// IMPORTANT: When new environment fields are added to the protobuf,
|
||||
// they MUST be added here too, or the coverage test will fail!
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Helper function to create and encode environment metrics with all current fields
|
||||
static size_t encode_telemetry_environment_metrics(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
telemetry.time = 1609459200;
|
||||
telemetry.which_variant = meshtastic_Telemetry_environment_metrics_tag;
|
||||
|
||||
// Basic environment metrics
|
||||
telemetry.variant.environment_metrics.temperature = 23.56f;
|
||||
telemetry.variant.environment_metrics.has_temperature = true;
|
||||
telemetry.variant.environment_metrics.relative_humidity = 65.43f;
|
||||
telemetry.variant.environment_metrics.has_relative_humidity = true;
|
||||
telemetry.variant.environment_metrics.barometric_pressure = 1013.27f;
|
||||
telemetry.variant.environment_metrics.has_barometric_pressure = true;
|
||||
|
||||
// Gas and air quality
|
||||
telemetry.variant.environment_metrics.gas_resistance = 50.58f;
|
||||
telemetry.variant.environment_metrics.has_gas_resistance = true;
|
||||
telemetry.variant.environment_metrics.iaq = 120;
|
||||
telemetry.variant.environment_metrics.has_iaq = true;
|
||||
|
||||
// Power measurements
|
||||
telemetry.variant.environment_metrics.voltage = 3.34f;
|
||||
telemetry.variant.environment_metrics.has_voltage = true;
|
||||
telemetry.variant.environment_metrics.current = 0.53f;
|
||||
telemetry.variant.environment_metrics.has_current = true;
|
||||
|
||||
// Light measurements
|
||||
telemetry.variant.environment_metrics.lux = 450.12f;
|
||||
telemetry.variant.environment_metrics.has_lux = true;
|
||||
telemetry.variant.environment_metrics.white_lux = 380.95f;
|
||||
telemetry.variant.environment_metrics.has_white_lux = true;
|
||||
telemetry.variant.environment_metrics.ir_lux = 25.37f;
|
||||
telemetry.variant.environment_metrics.has_ir_lux = true;
|
||||
telemetry.variant.environment_metrics.uv_lux = 15.68f;
|
||||
telemetry.variant.environment_metrics.has_uv_lux = true;
|
||||
|
||||
// Distance measurement
|
||||
telemetry.variant.environment_metrics.distance = 150.29f;
|
||||
telemetry.variant.environment_metrics.has_distance = true;
|
||||
|
||||
// Wind measurements
|
||||
telemetry.variant.environment_metrics.wind_direction = 180;
|
||||
telemetry.variant.environment_metrics.has_wind_direction = true;
|
||||
telemetry.variant.environment_metrics.wind_speed = 5.52f;
|
||||
telemetry.variant.environment_metrics.has_wind_speed = true;
|
||||
telemetry.variant.environment_metrics.wind_gust = 8.24f;
|
||||
telemetry.variant.environment_metrics.has_wind_gust = true;
|
||||
telemetry.variant.environment_metrics.wind_lull = 2.13f;
|
||||
telemetry.variant.environment_metrics.has_wind_lull = true;
|
||||
|
||||
// Weight measurement
|
||||
telemetry.variant.environment_metrics.weight = 75.56f;
|
||||
telemetry.variant.environment_metrics.has_weight = true;
|
||||
|
||||
// Radiation measurement
|
||||
telemetry.variant.environment_metrics.radiation = 0.13f;
|
||||
telemetry.variant.environment_metrics.has_radiation = true;
|
||||
|
||||
// Rainfall measurements
|
||||
telemetry.variant.environment_metrics.rainfall_1h = 2.57f;
|
||||
telemetry.variant.environment_metrics.has_rainfall_1h = true;
|
||||
telemetry.variant.environment_metrics.rainfall_24h = 15.89f;
|
||||
telemetry.variant.environment_metrics.has_rainfall_24h = true;
|
||||
|
||||
// Soil measurements
|
||||
telemetry.variant.environment_metrics.soil_moisture = 85;
|
||||
telemetry.variant.environment_metrics.has_soil_moisture = true;
|
||||
telemetry.variant.environment_metrics.soil_temperature = 18.54f;
|
||||
telemetry.variant.environment_metrics.has_soil_temperature = true;
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Telemetry_msg, &telemetry);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Test TELEMETRY_APP port with device metrics
|
||||
void test_telemetry_device_metrics_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_device_metrics(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check message type
|
||||
TEST_ASSERT_TRUE(jsonObj.find("type") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL_STRING("telemetry", jsonObj["type"]->AsString().c_str());
|
||||
|
||||
// Check payload
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Verify telemetry data
|
||||
TEST_ASSERT_TRUE(payload.find("battery_level") != payload.end());
|
||||
TEST_ASSERT_EQUAL(85, (int)payload["battery_level"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("voltage") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 3.72f, payload["voltage"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("channel_utilization") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.56f, payload["channel_utilization"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("uptime_seconds") != payload.end());
|
||||
TEST_ASSERT_EQUAL(12345, (int)payload["uptime_seconds"]->AsNumber());
|
||||
|
||||
// Note: JSON serialization may not preserve exact 2-decimal formatting due to float precision
|
||||
// We verify the numeric values are correct within tolerance
|
||||
|
||||
delete root;
|
||||
}
|
||||
|
||||
// Test that telemetry environment metrics are properly serialized
|
||||
void test_telemetry_environment_metrics_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check payload exists
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Test key fields that should be present in the serializer
|
||||
TEST_ASSERT_TRUE(payload.find("temperature") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 23.56f, payload["temperature"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("relative_humidity") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 65.43f, payload["relative_humidity"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("distance") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 150.29f, payload["distance"]->AsNumber());
|
||||
|
||||
// Note: JSON serialization may have float precision limitations
|
||||
// We focus on verifying numeric accuracy rather than exact string formatting
|
||||
|
||||
delete root;
|
||||
}
|
||||
|
||||
// Test comprehensive environment metrics coverage
|
||||
void test_telemetry_environment_metrics_comprehensive()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check payload exists
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Check all 15 originally supported fields
|
||||
TEST_ASSERT_TRUE(payload.find("temperature") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("relative_humidity") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("barometric_pressure") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("gas_resistance") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("voltage") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("current") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("iaq") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("distance") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("lux") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("white_lux") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_direction") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_speed") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_gust") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_lull") != payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("radiation") != payload.end());
|
||||
|
||||
delete root;
|
||||
}
|
||||
|
||||
// Test for the 7 environment fields that were added to complete coverage
|
||||
void test_telemetry_environment_metrics_missing_fields()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check payload exists
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Check the 7 fields that were previously missing
|
||||
TEST_ASSERT_TRUE(payload.find("ir_lux") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 25.37f, payload["ir_lux"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("uv_lux") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.68f, payload["uv_lux"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("weight") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 75.56f, payload["weight"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("rainfall_1h") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 2.57f, payload["rainfall_1h"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("rainfall_24h") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.89f, payload["rainfall_24h"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("soil_moisture") != payload.end());
|
||||
TEST_ASSERT_EQUAL(85, (int)payload["soil_moisture"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("soil_temperature") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 18.54f, payload["soil_temperature"]->AsNumber());
|
||||
|
||||
// Note: JSON float serialization may not preserve exact decimal formatting
|
||||
// We verify the values are numerically correct within tolerance
|
||||
|
||||
delete root;
|
||||
}
|
||||
|
||||
// Test that ALL environment fields are serialized (canary test for forgotten fields)
|
||||
// This test will FAIL if a new environment field is added to the protobuf but not to the serializer
|
||||
void test_telemetry_environment_metrics_complete_coverage()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics_all_fields(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check payload exists
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// ✅ ALL 22 environment fields MUST be present and correct
|
||||
// If this test fails, it means either:
|
||||
// 1. A new field was added to the protobuf but not to the serializer
|
||||
// 2. The encode_telemetry_environment_metrics_all_fields() function wasn't updated
|
||||
|
||||
// Basic environment (3 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("temperature") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 23.56f, payload["temperature"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("relative_humidity") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 65.43f, payload["relative_humidity"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("barometric_pressure") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 1013.27f, payload["barometric_pressure"]->AsNumber());
|
||||
|
||||
// Gas and air quality (2 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("gas_resistance") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 50.58f, payload["gas_resistance"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("iaq") != payload.end());
|
||||
TEST_ASSERT_EQUAL(120, (int)payload["iaq"]->AsNumber());
|
||||
|
||||
// Power measurements (2 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("voltage") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 3.34f, payload["voltage"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("current") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 0.53f, payload["current"]->AsNumber());
|
||||
|
||||
// Light measurements (4 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("lux") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 450.12f, payload["lux"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("white_lux") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 380.95f, payload["white_lux"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("ir_lux") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 25.37f, payload["ir_lux"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("uv_lux") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.68f, payload["uv_lux"]->AsNumber());
|
||||
|
||||
// Distance measurement (1 field)
|
||||
TEST_ASSERT_TRUE(payload.find("distance") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 150.29f, payload["distance"]->AsNumber());
|
||||
|
||||
// Wind measurements (4 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("wind_direction") != payload.end());
|
||||
TEST_ASSERT_EQUAL(180, (int)payload["wind_direction"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_speed") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 5.52f, payload["wind_speed"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_gust") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 8.24f, payload["wind_gust"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_lull") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 2.13f, payload["wind_lull"]->AsNumber());
|
||||
|
||||
// Weight measurement (1 field)
|
||||
TEST_ASSERT_TRUE(payload.find("weight") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 75.56f, payload["weight"]->AsNumber());
|
||||
|
||||
// Radiation measurement (1 field)
|
||||
TEST_ASSERT_TRUE(payload.find("radiation") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 0.13f, payload["radiation"]->AsNumber());
|
||||
|
||||
// Rainfall measurements (2 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("rainfall_1h") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 2.57f, payload["rainfall_1h"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("rainfall_24h") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 15.89f, payload["rainfall_24h"]->AsNumber());
|
||||
|
||||
// Soil measurements (2 fields)
|
||||
TEST_ASSERT_TRUE(payload.find("soil_moisture") != payload.end());
|
||||
TEST_ASSERT_EQUAL(85, (int)payload["soil_moisture"]->AsNumber());
|
||||
TEST_ASSERT_TRUE(payload.find("soil_temperature") != payload.end());
|
||||
TEST_ASSERT_FLOAT_WITHIN(0.01f, 18.54f, payload["soil_temperature"]->AsNumber());
|
||||
|
||||
// Total: 22 environment fields
|
||||
// This test ensures 100% coverage of environment metrics
|
||||
|
||||
// Note: JSON float serialization precision may vary due to the underlying library
|
||||
// The important aspect is that all values are numerically accurate within tolerance
|
||||
|
||||
delete root;
|
||||
}
|
||||
|
||||
// Test that unset environment fields are not present in JSON
|
||||
void test_telemetry_environment_metrics_unset_fields()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_telemetry_environment_metrics_empty(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_TELEMETRY_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check payload exists
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// With completely empty environment metrics, NO fields should be present
|
||||
// Only basic telemetry fields like "time" might be present
|
||||
|
||||
// All 22 environment fields should be absent (none were set)
|
||||
TEST_ASSERT_TRUE(payload.find("temperature") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("relative_humidity") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("barometric_pressure") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("gas_resistance") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("iaq") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("voltage") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("current") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("lux") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("white_lux") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("ir_lux") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("uv_lux") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("distance") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_direction") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_speed") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_gust") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("wind_lull") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("weight") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("radiation") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("rainfall_1h") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("rainfall_24h") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("soil_moisture") == payload.end());
|
||||
TEST_ASSERT_TRUE(payload.find("soil_temperature") == payload.end());
|
||||
|
||||
delete root;
|
||||
}
|
42
test/test_meshpacket_serializer/ports/test_text_message.cpp
Normal file
42
test/test_meshpacket_serializer/ports/test_text_message.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
// Test TEXT_MESSAGE_APP port
|
||||
void test_text_message_serialization()
|
||||
{
|
||||
const char *test_text = "Hello Meshtastic!";
|
||||
meshtastic_MeshPacket packet =
|
||||
create_test_packet(meshtastic_PortNum_TEXT_MESSAGE_APP, (const uint8_t *)test_text, strlen(test_text));
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check basic packet fields
|
||||
TEST_ASSERT_TRUE(jsonObj.find("from") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(0x11223344, (uint32_t)jsonObj["from"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(jsonObj.find("to") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(0x55667788, (uint32_t)jsonObj["to"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(jsonObj.find("id") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL(0x9999, (uint32_t)jsonObj["id"]->AsNumber());
|
||||
|
||||
// Check message type
|
||||
TEST_ASSERT_TRUE(jsonObj.find("type") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL_STRING("text", jsonObj["type"]->AsString().c_str());
|
||||
|
||||
// Check payload
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
TEST_ASSERT_TRUE(payload.find("text") != payload.end());
|
||||
TEST_ASSERT_EQUAL_STRING("Hello Meshtastic!", payload["text"]->AsString().c_str());
|
||||
|
||||
delete root;
|
||||
}
|
53
test/test_meshpacket_serializer/ports/test_waypoint.cpp
Normal file
53
test/test_meshpacket_serializer/ports/test_waypoint.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "../test_helpers.h"
|
||||
|
||||
static size_t encode_waypoint(uint8_t *buffer, size_t buffer_size)
|
||||
{
|
||||
meshtastic_Waypoint waypoint = meshtastic_Waypoint_init_zero;
|
||||
waypoint.id = 12345;
|
||||
waypoint.latitude_i = 374208000;
|
||||
waypoint.longitude_i = -1221981000;
|
||||
waypoint.expire = 1609459200 + 3600; // 1 hour from now
|
||||
strcpy(waypoint.name, "Test Point");
|
||||
strcpy(waypoint.description, "Test waypoint description");
|
||||
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buffer_size);
|
||||
pb_encode(&stream, &meshtastic_Waypoint_msg, &waypoint);
|
||||
return stream.bytes_written;
|
||||
}
|
||||
|
||||
// Test WAYPOINT_APP port
|
||||
void test_waypoint_serialization()
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
size_t payload_size = encode_waypoint(buffer, sizeof(buffer));
|
||||
|
||||
meshtastic_MeshPacket packet = create_test_packet(meshtastic_PortNum_WAYPOINT_APP, buffer, payload_size);
|
||||
|
||||
std::string json = MeshPacketSerializer::JsonSerialize(&packet, false);
|
||||
TEST_ASSERT_TRUE(json.length() > 0);
|
||||
|
||||
JSONValue *root = JSON::Parse(json.c_str());
|
||||
TEST_ASSERT_NOT_NULL(root);
|
||||
TEST_ASSERT_TRUE(root->IsObject());
|
||||
|
||||
JSONObject jsonObj = root->AsObject();
|
||||
|
||||
// Check message type
|
||||
TEST_ASSERT_TRUE(jsonObj.find("type") != jsonObj.end());
|
||||
TEST_ASSERT_EQUAL_STRING("waypoint", jsonObj["type"]->AsString().c_str());
|
||||
|
||||
// Check payload
|
||||
TEST_ASSERT_TRUE(jsonObj.find("payload") != jsonObj.end());
|
||||
TEST_ASSERT_TRUE(jsonObj["payload"]->IsObject());
|
||||
|
||||
JSONObject payload = jsonObj["payload"]->AsObject();
|
||||
|
||||
// Verify waypoint data
|
||||
TEST_ASSERT_TRUE(payload.find("id") != payload.end());
|
||||
TEST_ASSERT_EQUAL(12345, (int)payload["id"]->AsNumber());
|
||||
|
||||
TEST_ASSERT_TRUE(payload.find("name") != payload.end());
|
||||
TEST_ASSERT_EQUAL_STRING("Test Point", payload["name"]->AsString().c_str());
|
||||
|
||||
delete root;
|
||||
}
|
44
test/test_meshpacket_serializer/test_helpers.h
Normal file
44
test/test_meshpacket_serializer/test_helpers.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "serialization/JSON.h"
|
||||
#include "serialization/MeshPacketSerializer.h"
|
||||
#include <Arduino.h>
|
||||
#include <meshtastic/mesh.pb.h>
|
||||
#include <meshtastic/mqtt.pb.h>
|
||||
#include <meshtastic/telemetry.pb.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
#include <unity.h>
|
||||
|
||||
// Helper function to create a test packet with the given port and payload
|
||||
static meshtastic_MeshPacket create_test_packet(meshtastic_PortNum port, const uint8_t *payload, size_t payload_size)
|
||||
{
|
||||
meshtastic_MeshPacket packet = meshtastic_MeshPacket_init_zero;
|
||||
|
||||
packet.id = 0x9999;
|
||||
packet.from = 0x11223344;
|
||||
packet.to = 0x55667788;
|
||||
packet.channel = 0;
|
||||
packet.hop_limit = 3;
|
||||
packet.want_ack = false;
|
||||
packet.priority = meshtastic_MeshPacket_Priority_UNSET;
|
||||
packet.rx_time = 1609459200;
|
||||
packet.rx_snr = 10.5f;
|
||||
packet.hop_start = 3;
|
||||
packet.rx_rssi = -85;
|
||||
packet.delayed = meshtastic_MeshPacket_Delayed_NO_DELAY;
|
||||
|
||||
// Set decoded variant
|
||||
packet.which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
||||
packet.decoded.portnum = port;
|
||||
memcpy(packet.decoded.payload.bytes, payload, payload_size);
|
||||
packet.decoded.payload.size = payload_size;
|
||||
packet.decoded.want_response = false;
|
||||
packet.decoded.dest = 0x55667788;
|
||||
packet.decoded.source = 0x11223344;
|
||||
packet.decoded.request_id = 0;
|
||||
packet.decoded.reply_id = 0;
|
||||
packet.decoded.emoji = 0;
|
||||
|
||||
return packet;
|
||||
}
|
51
test/test_meshpacket_serializer/test_serializer.cpp
Normal file
51
test/test_meshpacket_serializer/test_serializer.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "test_helpers.h"
|
||||
#include <Arduino.h>
|
||||
#include <unity.h>
|
||||
|
||||
// Forward declarations for test functions
|
||||
void test_text_message_serialization();
|
||||
void test_position_serialization();
|
||||
void test_nodeinfo_serialization();
|
||||
void test_waypoint_serialization();
|
||||
void test_telemetry_device_metrics_serialization();
|
||||
void test_telemetry_environment_metrics_serialization();
|
||||
void test_telemetry_environment_metrics_comprehensive();
|
||||
void test_telemetry_environment_metrics_missing_fields();
|
||||
void test_telemetry_environment_metrics_complete_coverage();
|
||||
void test_telemetry_environment_metrics_unset_fields();
|
||||
void test_encrypted_packet_serialization();
|
||||
|
||||
void setup()
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
||||
// Text message tests
|
||||
RUN_TEST(test_text_message_serialization);
|
||||
|
||||
// Position tests
|
||||
RUN_TEST(test_position_serialization);
|
||||
|
||||
// Nodeinfo tests
|
||||
RUN_TEST(test_nodeinfo_serialization);
|
||||
|
||||
// Waypoint tests
|
||||
RUN_TEST(test_waypoint_serialization);
|
||||
|
||||
// Telemetry tests
|
||||
RUN_TEST(test_telemetry_device_metrics_serialization);
|
||||
RUN_TEST(test_telemetry_environment_metrics_serialization);
|
||||
RUN_TEST(test_telemetry_environment_metrics_comprehensive);
|
||||
RUN_TEST(test_telemetry_environment_metrics_missing_fields);
|
||||
RUN_TEST(test_telemetry_environment_metrics_complete_coverage);
|
||||
RUN_TEST(test_telemetry_environment_metrics_unset_fields);
|
||||
|
||||
// Encrypted packet test
|
||||
RUN_TEST(test_encrypted_packet_serialization);
|
||||
|
||||
UNITY_END();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(1000);
|
||||
}
|
@ -19,8 +19,6 @@
|
||||
#ifndef _VARIANT_GAT562_MESH_TRIAL_TRACKER_
|
||||
#define _VARIANT_GAT562_MESH_TRIAL_TRACKER_
|
||||
|
||||
#define GAT562_MESH_TRIAL_TRACKER
|
||||
|
||||
// led pin 2 (blue), see https://github.com/meshtastic/firmware/blob/master/src/mesh/NodeDB.cpp#L723
|
||||
#define RAK4630
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user