Skip to content

Add display - #569

Open
tigroo wants to merge 5 commits into
masterfrom
add_display
Open

Add display#569
tigroo wants to merge 5 commits into
masterfrom
add_display

Conversation

@tigroo

@tigroo tigroo commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Changes

  • IoT3 SDK:
    • mobility add helpers on quadtree
  • examples:
    • display: create the server and the log and the mqtt readers

Close #568

Close #369

Test

How to test

  1. Create a log file with 1 CAM + 1 CPM with 1 perceived object (Toulouse area):
mkdir -p /tmp/logs
cat > /tmp/logs/its.log << 'EOF'
{"message_type":"cam","origin":"self","version":"2.4.0","source_uuid":"car_001","timestamp":1784727122140,"message":{"protocol_version":1,"station_id":555,"generation_delta_time":64291,"basic_container":{"station_type":5,"reference_position":{"latitude":436004000,"longitude":14500000,"position_confidence_ellipse":{"semi_major":10,"semi_minor":50,"semi_major_orientation":1},"altitude":{"value":14750,"confidence":1}}},"high_frequency_container":{"basic_vehicle_container_high_frequency":{"heading":{"value":1800,"confidence":2},"speed":{"value":144,"confidence":3},"drive_direction":0,"vehicle_length":{"value":40,"confidence":0},"vehicle_width":20,"longitudinal_acceleration":{"value":10,"confidence":2},"curvature":{"value":11,"confidence":4},"curvature_calculation_mode":0,"yaw_rate":{"value":562,"confidence":2}}}}}
{"type":"cpm","origin":"self","version":"2.2.0","source_uuid":"car_001","timestamp":1784727122141,"message":{"protocol_version":1,"station_id":555,"management_container":{"reference_position":{"latitude":436004000,"longitude":14500000,"position_confidence_ellipse":{"semi_major":10,"semi_minor":50,"semi_major_orientation":1},"altitude":{"value":14750,"confidence":1}}},"perceived_object_container":[{"object_id":1,"position":{"x_coordinate":{"value":500},"y_coordinate":{"value":-200},"confidence":{"position_confidence_ellipse":{"semi_major_confidence":20,"semi_minor_confidence":30,"semi_major_orientation":1}}}}]}}
EOF
  1. Execute the 3 display example binaries following the documentation into the README file.
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/examples/display_log_reader /tmp/logs 26 /tmp/display.db`
INFO [libits::client::logger] Logger ready on stdout
📂 Input directory: /tmp/logs
📊 Zoom level: 26
🗄️  Database: /tmp/display.db

📂 Scanning directory: /tmp/logs
   Found 1 log file(s)
🗄️  Opening database: /tmp/display.db
📖 Parsing at zoom level 26...

  📄 Processing: /tmp/logs/its.log

✅ Parsing complete:
   - Files processed: 1
   - Messages stored: 3
   - Messages skipped (no position): 0
   - Duplicates skipped: 0
   - Errors: 0
   - Database: /tmp/display.db
📊 Database Statistics
   Database: /tmp/display.db
   Total unique quadtiles: 2
   Total messages: 3

📅 Days with data: 1
   2025-03-17 : 3 messages

📨 Message types:
   cam : 1 messages
   cpm : 1 messages
   cpm po : 1 messages

🔝 Top 10 quadkeys (global):
Quadkey                       Count Mean Confidence    Type(s)
----------------------------------------------------------------------
12022203022221313333211031          2             0.0    cam,cpm
12022203022221313333300331          1            25.0     cpm po
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/examples/display_mqtt_reader --config examples/config.ini`
INFO [libits::client::logger] Logger ready on stdout
INFO [libits::transport::mqtt] Transport: standard MQTT; TLS enabled
🔌 Connecting to MQTT broker: test.mosquitto.org:8886
   Client ID: com_app_its-client-1
   Topics: ["#"]
   Zoom level: 18
   Database: examples/display.db
✅ Subscribed to topics
📡 Listening for messages...
JSON parse error on topic Ahoydtu_Kraftwerk120240107/version: trailing characters at line 1 column 4
...
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
     Running `target/debug/examples/display_server --config examples/config.ini`
INFO [libits::client::logger] Logger ready on stdout
📊 Database Statistics
   Database: /tmp/display.db
   Total unique quadtiles: 2
   Total messages: 3

📅 Days with data: 1
   2025-03-17 : 3 messages

📨 Message types:
   cam : 1 messages
   cpm : 1 messages
   cpm po : 1 messages

🔝 Top 10 quadkeys (global):
Quadkey                       Count Mean Confidence    Type(s)
----------------------------------------------------------------------
12022203022221313333211031          2             0.0    cam,cpm
12022203022221313333300331          1            25.0     cpm po

🚀 Server running on http://0.0.0.0:3000 (DB: /tmp/display.db)
📍 Open your browser and navigate to the URL above

Select the date (DAY) 2026-07-22. You should see 1 CAM and 1 CPM with 1 PO (3 messages).

imatge
  1. Publish another CAM + CPM from nearby (slightly different location):
docker run -it --rm eclipse-mosquitto mosquitto_pub -h test.mosquitto.org -p 8886 -t default/outQueue/v2x/cam/car_002/1/2/0/2/2/2/0/3/0/2/2/2/2/1/3/1/3/3/3/3/1/1/3/3/2/2 --tls-version tlsv1.2 --capath /etc/ssl/certs/ -m '{"message_type":"cam","origin":"self","version":"2.4.0","source_uuid":"car_002","timestamp":1784727122142,"message":{"protocol_version":1,"station_id":666,"generation_delta_time":64291,"basic_container":{"station_type":5,"reference_position":{"latitude":436005000,"longitude":14501000,"position_confidence_ellipse":{"semi_major":10,"semi_minor":50,"semi_major_orientation":1},"altitude":{"value":14750,"confidence":1}}},"high_frequency_container":{"basic_vehicle_container_high_frequency":{"heading":{"value":1800,"confidence":2},"speed":{"value":144,"confidence":3},"drive_direction":0,"vehicle_length":{"value":40,"confidence":0},"vehicle_width":20,"longitudinal_acceleration":{"value":10,"confidence":2},"curvature":{"value":11,"confidence":4},"curvature_calculation_mode":0,"yaw_rate":{"value":562,"confidence":2}}}}}'
docker run -it --rm eclipse-mosquitto mosquitto_pub -h test.mosquitto.org -p 8886 -t default/outQueue/v2x/cpm/car_002/1/2/0/2/2/2/0/3/0/2/2/2/2/1/3/1/3/3/3/3/1/1/3/3/2/2 --tls-version tlsv1.2 --capath /etc/ssl/certs/ -m '{"type":"cpm","origin":"self","version":"2.2.0","source_uuid":"car_002","timestamp":1784727122143,"message":{"protocol_version":1,"station_id":666,"management_container":{"reference_position":{"latitude":436005000,"longitude":14501000,"position_confidence_ellipse":{"semi_major":10,"semi_minor":50,"semi_major_orientation":1},"altitude":{"value":14750,"confidence":1}}},"perceived_object_container":[{"object_id":1,"position":{"x_coordinate":{"value":500},"y_coordinate":{"value":-200},"confidence":{"position_confidence_ellipse":{"semi_major_confidence":20,"semi_minor_confidence":30,"semi_major_orientation":1}}}}]}}'

NB: if a huge traffic is on the broker, you may retry to be served.

Refresh the map - you should now see 2 CAMs and 2 CPMs with 1 PO at different locations (6 messages).

imatge

@tigroo tigroo self-assigned this Jul 22, 2026
@tigroo tigroo added the Rust Rust code label Jul 22, 2026
@tigroo tigroo added this to Kanban Jul 22, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in Kanban Jul 22, 2026
@tigroo tigroo moved this from Backlog to In progress in Kanban Jul 22, 2026
@tigroo
tigroo requested a review from nbuffon July 22, 2026 14:43
@tigroo
tigroo marked this pull request as ready for review July 22, 2026 14:57

@nbuffon nbuffon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really wonder why theses "examples" are barely using libits, and mostly rewriting parsing and data manipulation functions.
What's the rational behind not using the messages' structures through Message to access the values they carry for example ?

let po_qk2 = quadtree::lat_lon_to_quadkey(po_lat2, po_lon2, 26);
eprintln!("PO2 zoom 26: {} ({}, {})", po_qk2, po_lat2, po_lon2);
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no mod.rs anywhere in the project, as recommended by the Rust doc

Prior to rustc 1.30, using mod.rs files was the way to load a module with nested children. It is encouraged to use the new naming convention as it is more consistent, and avoids having many files named mod.rs within a project.

Please stick to quadtree.rs

Comment thread rust/src/mobility/quadtree/quadkey.rs Outdated
if number_of_slash > 0 && ((number_of_slash * 2) + 1 == s.len()) {
if number_of_slash > 0 {
if (number_of_slash * 2) + 1 != s.len() {
return Err(ParseError::InvalidTileChar('/'));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use a dedicated error for this ?
If I understand it correctly it just checks that you don't have two consecutive / or that it does not start or end with a / and not that an invalid char was found (valid characters being [0,1,2,3,/]).

Something like ParseError::MalformedSequence or MalformedQuadKey might be more relevant.

Note that just comparing the number of / might consider typo as valid (0//01 or /01/1)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try...

}
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not

impl TryFrom<char> for Tile {
    type Error = ParseError;

    fn try_from(tile: char) -> Result<Self, Self::Error> {
        ...
    }
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try...

Comment thread rust/src/mobility/quadtree/tile.rs Outdated
_ => panic!("Unable to convert the char {tile} as a Tile"),
}
Tile::try_from_char(tile)
.unwrap_or_else(|_| panic!("Unable to convert the char {tile} as a Tile"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can .expect("message"), it will panic with the provided message in case of error

struct LogEntry {
#[serde(rename = "type", alias = "message_type")]
message_type: String,
message: Option<Value>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason of not using the SDK's types and functions but re-parsing the JSON and checking types and all ?

Using Message/Content/Mobile and even by "casting" to the correct type you should be able to achieve the same thing (without having to redefine everything).

        match log_entry.message {
            Message::CAM(cam) => {
                ...

Comment thread rust/examples/display/mqtt/main.rs Outdated
// (e.g. [mobility]) that a display-only config does not provide.
let mqtt_properties = ini
.section(Some(MQTT_SECTION))
.unwrap_or_else(|| panic!("Missing [{}] section in {}", MQTT_SECTION, config_path));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use expect(...), it will panic for you

/// Extracts the message type from an MQTT topic.
/// Topic format: {context}/outQueue/v2x/{msgtype}/+/{quadkey_path}
/// or simpler: just look for known message types in the topic segments.
fn extract_message_type_from_topic(topic: &str) -> String {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not to use GeoTopic ?

};
let year = if month <= 2 { year + 1 } else { year };
format!("{:04}-{:02}-{:02}", year, month, day)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a lot of code duplicated from here

Comment thread rust/examples/display/server/main.rs Outdated

if !Path::new(&db_path).exists() {
eprintln!("❌ Database not found: {}", db_path);
eprintln!(" Run 'display_log_reader' or 'display_mqtt_reader' first.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why eprintln and not error! ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use an ensure! instead...

Comment thread rust/examples/display/database.rs Outdated
* Authors: see CONTRIBUTORS.md
*/

#![allow(dead_code)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

database.rs contains elements used by the server and not by the log reader, so it throws warnings. It's ugly, I try to dispath database functions not used by the 23 example bins (server, file, mqtt) differently...

@tigroo
tigroo marked this pull request as draft August 6, 2026 13:01
@tigroo
tigroo force-pushed the add_display branch 10 times, most recently from 991eb17 to 908396d Compare August 10, 2026 07:10
tigroo added 3 commits August 10, 2026 16:30
Signed-off-by: Frédéric Gardes <frederic.gardes@orange.com>
Precise the minor versions of dependencies.
Remove useless dev dependency.

Signed-off-by: Frédéric Gardes <frederic.gardes@orange.com>
Signed-off-by: Frédéric Gardes <frederic.gardes@orange.com>
@tigroo
tigroo marked this pull request as ready for review August 10, 2026 14:49
@tigroo
tigroo requested a review from nbuffon August 10, 2026 14:49
Add comments on Rust elements.
Provide a coordinate / tile converter
Factorize caracter conversion.
Use a Result to manage the slashes.
Use "quadkey" everywhere (no "quad_key").
Add position_confidence() to Mobile trait with default implementation.
Implement position_confidence() in CAM, DENM, CPM, CAM113.
Add confidence_mean() to PositionConfidenceEllipse (v2.x and v1.1.3).
Declare the 3 examples.

Signed-off-by: Frédéric Gardes <frederic.gardes@orange.com>
Add a log parser,
a mqtt client
and a web server.
Describe the database.
Provide the configuration file.

Signed-off-by: Frédéric Gardes <frederic.gardes@orange.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Rust Rust code

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

Metrics display Remove flexi_logger from dev-dependencies

2 participants