use std::{path::Path, sync::Arc}; use spotflow::DeviceClientBuilder; use http::Uri; use serde_json::json; use uuid::Uuid; mod common; #[allow(deprecated)] // We're using all the functions here until they are stabilized or removed fn main() { env_logger::Builder::from_env( env_logger::Env::default() .default_filter_or("sqlx=warn,ureq=warn,rumqtt=warn,ingress=info,spotflow=trace,info"), ) .init(); let path = Path::new("./test.db"); let device_id = format!("twin_example_{}", Uuid::new_v4()); log::info!("Using device ID {}", device_id); log::info!("Initiating Device Twin example"); let workspace_id = "98d5945d-bf04-49de-ad48-45fc01869075"; let instance_url = Uri::from_static("https://tst1.dataplatform.datamole.dev"); // 1 minute registration tokens. Device must choose device ID let pt = String::from("CAEQAQ.ChIJrQttEdCSxUARoVQJDmRVorI.cF63b-v-FUd_1QwUIOyEWfJ_9dyQwrM6kBw0vO22JtoZ60ZnRAkMKAec6hd7Zwcl6Mqx_-rk9VY6EmK3ycyb_gVLsT9Tw3vqh0OEUfM9FpTeSNv0_GReFMJkb_95kpwg"); log::info!("Creating ingress client"); let client = DeviceClientBuilder::new(Some(device_id.clone()), pt, path) .with_instance(instance_url.to_string()) .with_display_provisioning_operation_callback(Box::new( common::ProvisioningOperationApprovalHandler::new( instance_url.clone(), workspace_id.to_string(), ), )) .build() .expect("Unable to build ingress connection"); log::info!("Obtaining desired properties"); let desired = client.desired_properties(); log::info!("Properties obtained:\n{:?}", desired); update_twin(&instance_url, &device_id, workspace_id); log::info!("Awaiting desired properties change"); let desired = client.wait_desired_properties_changed(); log::info!("Properties obtained:\n{:?}", desired); log::info!("Updating reported properties"); client .patch_reported_properties(r#"{"abc": "def", "lorem": 42}"#) .expect("Unable to update reported properties"); let reported = client.reported_properties(); log::info!("Reported properties:\n{:?}", reported); std::thread::sleep(std::time::Duration::from_secs(10)); log::info!("Terminating connection"); drop(client); log::info!("Deleting the Device"); common::delete_device(&instance_url, workspace_id, &device_id) .expect("Unable to delete the device"); } fn update_twin(instance_url: &Uri, device_id: &str, workspace_id: &str) { let token = common::get_azure_token(instance_url, "device-management"); let url = format!("{instance_url}workspaces/{workspace_id}/devices/{device_id}/desired-properties"); let auth_header = format!("Bearer {}", token.secret()); let connector = Arc::new(native_tls::TlsConnector::new().unwrap()); let agent = ureq::AgentBuilder::new().tls_connector(connector).build(); // Arrays are currently not supported by DMS let data = json!({ "a": r"\", "b": "\"", "stuff": "here", "more-stuff": { "number": 4u8, "numberer": 1.2f32, "obj": { "1": 1u8, "2": 2u8, "2,5": 2.5f32, "3": "three" } } }); log::warn!("{}", data); agent .put(&url) .set("Content-Type", "application/json") .set("Authorization", &auth_header) .send_json(data) .unwrap_or_else(|e| { log::error!("{:?}", e); log::error!("{}", e.into_response().unwrap().into_string().unwrap()); panic!("Failed updating device twins"); }); }