feat: initial meshservice implementation
Generic decentralized service layer for mesh networks. Includes FAPP (psychotherapy) and Housing as reference services. - ServiceMessage with Ed25519 signatures - Wire protocol (64-byte header + CBOR) - ServiceRouter with pluggable handlers - Verification framework (3 trust levels) - 32 tests, 3 examples
This commit is contained in:
86
examples/fapp_service.rs
Normal file
86
examples/fapp_service.rs
Normal file
@@ -0,0 +1,86 @@
|
||||
//! FAPP Service Demo
|
||||
//!
|
||||
//! Demonstrates therapist announcement and patient query flow.
|
||||
|
||||
use meshservice::{
|
||||
capabilities,
|
||||
identity::ServiceIdentity,
|
||||
router::ServiceRouter,
|
||||
services::fapp::{create_announce, create_query, FappService, Modality, SlotAnnounce, SlotQuery, Specialism},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
println!("=== FAPP Service Demo ===\n");
|
||||
|
||||
// Create identities
|
||||
let therapist = ServiceIdentity::generate();
|
||||
let patient = ServiceIdentity::generate();
|
||||
let relay = ServiceIdentity::generate();
|
||||
|
||||
println!("Therapist address: {:?}", hex(&therapist.address()));
|
||||
println!("Patient address: {:?}", hex(&patient.address()));
|
||||
println!("Relay address: {:?}\n", hex(&relay.address()));
|
||||
|
||||
// Create router with FAPP service
|
||||
let mut router = ServiceRouter::new(capabilities::RELAY);
|
||||
router.register(Box::new(FappService::relay()));
|
||||
|
||||
// Therapist creates announcement
|
||||
let announce = SlotAnnounce::new(
|
||||
&[Specialism::CognitiveBehavioral, Specialism::TraumaFocused],
|
||||
Modality::VideoCall,
|
||||
"104", // Berlin Kreuzberg
|
||||
)
|
||||
.with_slots(3)
|
||||
.with_profile("https://therapists.de/dr-schmidt")
|
||||
.with_name("Dr. Anna Schmidt");
|
||||
|
||||
println!("Therapist announces:");
|
||||
println!(" Specialisms: CBT, Trauma");
|
||||
println!(" Modality: Video");
|
||||
println!(" Location: 104xx");
|
||||
println!(" Slots: 3");
|
||||
println!(" Profile: https://therapists.de/dr-schmidt\n");
|
||||
|
||||
let msg = create_announce(&therapist, &announce, 1).unwrap();
|
||||
let action = router.handle(msg.clone(), Some(therapist.public_key())).unwrap();
|
||||
println!("Router action: {:?}", action);
|
||||
println!("Stored messages: {}\n", router.store().len());
|
||||
|
||||
// Patient creates query
|
||||
let query = SlotQuery::new(Specialism::CognitiveBehavioral, "104")
|
||||
.with_modality(Modality::VideoCall)
|
||||
.with_max_wait(30);
|
||||
|
||||
println!("Patient queries:");
|
||||
println!(" Looking for: CBT");
|
||||
println!(" Location: 104xx");
|
||||
println!(" Modality: Video");
|
||||
println!(" Max wait: 30 days\n");
|
||||
|
||||
let query_msg = create_query(&patient, &query).unwrap();
|
||||
|
||||
// Find matches
|
||||
let matches = router.query(&query_msg);
|
||||
println!("Found {} matching therapist(s):", matches.len());
|
||||
|
||||
for (i, m) in matches.iter().enumerate() {
|
||||
if let Ok(data) = meshservice::services::fapp::SlotAnnounce::from_bytes(&m.message.payload) {
|
||||
println!(" {}. {} in {}xx ({} slots)",
|
||||
i + 1,
|
||||
data.display_name.as_deref().unwrap_or("Unknown"),
|
||||
data.postal_prefix,
|
||||
data.available_slots
|
||||
);
|
||||
if let Some(profile) = &data.profile_url {
|
||||
println!(" Verify: {}", profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n=== Demo Complete ===");
|
||||
}
|
||||
|
||||
fn hex(bytes: &[u8]) -> String {
|
||||
bytes.iter().map(|b| format!("{b:02x}")).collect()
|
||||
}
|
||||
Reference in New Issue
Block a user