Skip to content

feat/openadr3_1_mdns#367

Open
Jagaskak wants to merge 10 commits intoOpenLEADR:openadr3_1from
Jagaskak:feat/openadr3_1_mdns
Open

feat/openadr3_1_mdns#367
Jagaskak wants to merge 10 commits intoOpenLEADR:openadr3_1from
Jagaskak:feat/openadr3_1_mdns

Conversation

@Jagaskak
Copy link

@Jagaskak Jagaskak commented Feb 11, 2026

Summary

Implements mDNS service discovery for VTN servers (resolves #276) with corresponding client-side discovery capabilities.
Implement mDNS in VTN for and an example implementation of VTN discovery for the client.

Details

VTN Changes

  • mDNS Service Registration: VTN advertises itself via mDNS on startup
    • Service type: _openadr-http._tcp.local.
    • Service metadata: OpenADR version (3.1) and API path (/programs)
    • Configurable via environment variables (see .env)
  • Refactored server creation to make more accessible for testing

Client Changes

  • mDNS discovery implementation in openleadr-client/mdns.rs
    • Searches for VTN services on local network
    • Returns list of discovered VTNs
  • Example implementation in examples/discover_vtns.rs

Testing

  • Added a unit test for VTN implementation
  • Added integration test to test broadcast and discovery between VTN and VEN

Limitations

  • In environments with many virtual networking interfaces, explicit configuration of IP Address is needed
  • Discovery timeout is hardcoded to 20 seconds in the client

Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
Signed-off-by: Akshaya Jagannadharao <[email protected]>
@pohlm01 pohlm01 self-requested a review February 13, 2026 08:34
@pohlm01 pohlm01 linked an issue Feb 13, 2026 that may be closed by this pull request
@codecov
Copy link

codecov bot commented Feb 13, 2026

Codecov Report

❌ Patch coverage is 96.03175% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.82%. Comparing base (a39857b) to head (fbf04ec).
⚠️ Report is 4 commits behind head on openadr3_1.

Files with missing lines Patch % Lines
openleadr-vtn/src/main.rs 0.00% 3 Missing ⚠️
openleadr-client/src/mdns.rs 94.73% 1 Missing ⚠️
openleadr-vtn/src/lib.rs 97.05% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff               @@
##           openadr3_1     #367      +/-   ##
==============================================
+ Coverage       80.07%   80.82%   +0.75%     
==============================================
  Files              41       44       +3     
  Lines            4898     5013     +115     
==============================================
+ Hits             3922     4052     +130     
+ Misses            976      961      -15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Member

@pohlm01 pohlm01 left a comment

Choose a reason for hiding this comment

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

Thanks a lot for your PR! As mentioned, it runs on my machine, which is great. I still found a couple of points that could use some improvement. Let me know if you could use any help.

async fn main() {
info!("Searching for VTN servers...");

let vtns = discover_local_vtns("_openadr-http._tcp.local.").await;
Copy link
Member

Choose a reason for hiding this comment

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

According to the spec, this should be _openadr3._tcp.local., shouldn't it? (Also see various other places in the code)

https://github.com/oadr3-org/specification/blob/main/3.1.1/Definition.md#discovery-and-configuration-of-local-vtns

Comment on lines +11 to +12
let timeout = tokio::time::sleep(std::time::Duration::from_secs(20));
tokio::pin!(timeout);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe move the sleep in the loop. I think that would look cleaner to me, and you can skip the pin!. Additionally, it might be nice to add two more parameters to the function:

  • The maximum time you want to search, i.e., the timeout
  • An optional limit of VTNs to discover. I imagine most users want to discover only a single VTN and immediately return as soon as it's found instead of waiting for the full timeout.

let mdns = ServiceDaemon::new().expect("Failed to create daemon");

// Include metadata about the VTN service, such as version and API path
let properties = [("version", "3.1"), ("path", "/programs")];
Copy link
Member

Choose a reason for hiding this comment

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

I think you should double-check that with the spec:

  • The version has three parts, i.e, 3.1.0
  • The path isn't a property that's specified
  • base_path is missing
  • local_url is missing
  • We might want to skip proram_names, requires_auth, and openapi_url for now. Especially the program_names seem like a challenge to me, as it changes over the curse of the VTN lifetime.


// Search for the ServiceResolved event, timeout after 5 seconds if not found
let mut found = false;
let timeout = tokio::time::sleep(Duration::from_secs(5));
Copy link
Member

Choose a reason for hiding this comment

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

Moving the sleep right into the select! branch seems cleaner to me

}
}

assert!(found, "The mDNS service was not discovered within the 5s timeout.");
Copy link
Member

Choose a reason for hiding this comment

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

nitpik: The timeout is 0.5s

Comment on lines +8 to +11
std::env::set_var("PORT", "3999"); // Random port
std::env::set_var("MDNS_SERVICE_TYPE", "_openadr-test._tcp.local.");
std::env::set_var("MDNS_SERVER_NAME", "test-vtn-integration");
std::env::set_var("MDNS_IP_ADDRESS", "127.0.0.1");
Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately, set_var is marked unsafe from the 2024 edition onwards (and was already unsafe before, but the marking was missing). We have an outstanding issue to migrate to the 2024 edition that's currently blocked by other tests that also use the set_var function.
Maybe you can find a way to either make sure the usage of unsafe is fine here and mark it as such (with an explanation), or avoid the set_var function. I haven't looked into this myself now, so I don't know what the best solution from the top of my head, but let me know if you could use any assistance.

Comment on lines +18 to +22
if let Some(host) = info.get_addresses().iter().next() {
let port = info.get_port();
if let Ok(url) = url::Url::parse(&format!("http://{}:{}", host, port)) {
found_urls.push(url);
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we gain a lot from formatting the url here. Instead, I think we should return a struct with all the information we can get from the announcement (version, base_path, local_url, etc.).

@pohlm01
Copy link
Member

pohlm01 commented Feb 13, 2026

Also, please make sure to run cargo fmt and fix the Clippy issues. The "Audit dependencies" failure should be solved if you merge the latest changes from the openadr3_1 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mDNS for finding local VTNs

2 participants