Clean-up
This commit is contained in:
parent
76997c1a3c
commit
82ae21309c
3 changed files with 62 additions and 54 deletions
|
@ -1,16 +1,7 @@
|
||||||
|
//! Base38 encoding functions.
|
||||||
const BASE38_CHARS: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-.";
|
const BASE38_CHARS: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-.";
|
||||||
|
|
||||||
fn encode_base38(mut value: u32, char_count: u8) -> String {
|
/// Encodes a byte array into a base38 string.
|
||||||
let mut result = String::new();
|
|
||||||
for _ in 0..char_count {
|
|
||||||
let mut chars = BASE38_CHARS.chars();
|
|
||||||
let remainder = value % 38;
|
|
||||||
result.push(chars.nth(remainder as usize).unwrap());
|
|
||||||
value = (value - remainder) / 38;
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encode(bytes: &[u8]) -> String {
|
pub fn encode(bytes: &[u8]) -> String {
|
||||||
let length = bytes.len();
|
let length = bytes.len();
|
||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
|
@ -45,6 +36,17 @@ pub fn encode(bytes: &[u8]) -> String {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn encode_base38(mut value: u32, char_count: u8) -> String {
|
||||||
|
let mut result = String::new();
|
||||||
|
for _ in 0..char_count {
|
||||||
|
let mut chars = BASE38_CHARS.chars();
|
||||||
|
let remainder = value % 38;
|
||||||
|
result.push(chars.nth(remainder as usize).unwrap());
|
||||||
|
value = (value - remainder) / 38;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::{
|
||||||
fabric::FabricMgr,
|
fabric::FabricMgr,
|
||||||
interaction_model::InteractionModel,
|
interaction_model::InteractionModel,
|
||||||
mdns::Mdns,
|
mdns::Mdns,
|
||||||
pairing::compute_and_print_pairing_code,
|
pairing::print_pairing_code_and_qr,
|
||||||
secure_channel::core::SecureChannel,
|
secure_channel::core::SecureChannel,
|
||||||
transport,
|
transport,
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,7 @@ impl Matter {
|
||||||
&dev_det.device_name,
|
&dev_det.device_name,
|
||||||
);
|
);
|
||||||
|
|
||||||
compute_and_print_pairing_code(dev_det, dev_comm);
|
print_pairing_code_and_qr(dev_det, dev_comm);
|
||||||
|
|
||||||
let fabric_mgr = Arc::new(FabricMgr::new()?);
|
let fabric_mgr = Arc::new(FabricMgr::new()?);
|
||||||
let acl_mgr = Arc::new(AclMgr::new()?);
|
let acl_mgr = Arc::new(AclMgr::new()?);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! This module contains the logic for generating the pairing code and the QR code for easy pairing.
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use qrcode::{render::unicode, QrCode, Version};
|
use qrcode::{render::unicode, QrCode, Version};
|
||||||
use verhoeff::Verhoeff;
|
use verhoeff::Verhoeff;
|
||||||
|
@ -7,6 +9,25 @@ use crate::{
|
||||||
CommissioningData,
|
CommissioningData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const LONG_BITS: usize = 12;
|
||||||
|
const VERSION_FIELD_LENGTH_IN_BITS: usize = 3;
|
||||||
|
const VENDOR_IDFIELD_LENGTH_IN_BITS: usize = 16;
|
||||||
|
const PRODUCT_IDFIELD_LENGTH_IN_BITS: usize = 16;
|
||||||
|
const COMMISSIONING_FLOW_FIELD_LENGTH_IN_BITS: usize = 2;
|
||||||
|
const RENDEZVOUS_INFO_FIELD_LENGTH_IN_BITS: usize = 8;
|
||||||
|
const PAYLOAD_DISCRIMINATOR_FIELD_LENGTH_IN_BITS: usize = LONG_BITS;
|
||||||
|
const SETUP_PINCODE_FIELD_LENGTH_IN_BITS: usize = 27;
|
||||||
|
const PADDING_FIELD_LENGTH_IN_BITS: usize = 4;
|
||||||
|
const TOTAL_PAYLOAD_DATA_SIZE_IN_BITS: usize = VERSION_FIELD_LENGTH_IN_BITS
|
||||||
|
+ VENDOR_IDFIELD_LENGTH_IN_BITS
|
||||||
|
+ PRODUCT_IDFIELD_LENGTH_IN_BITS
|
||||||
|
+ COMMISSIONING_FLOW_FIELD_LENGTH_IN_BITS
|
||||||
|
+ RENDEZVOUS_INFO_FIELD_LENGTH_IN_BITS
|
||||||
|
+ PAYLOAD_DISCRIMINATOR_FIELD_LENGTH_IN_BITS
|
||||||
|
+ SETUP_PINCODE_FIELD_LENGTH_IN_BITS
|
||||||
|
+ PADDING_FIELD_LENGTH_IN_BITS;
|
||||||
|
const TOTAL_PAYLOAD_DATA_SIZE_IN_BYTES: usize = TOTAL_PAYLOAD_DATA_SIZE_IN_BITS / 8;
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum CommissionningFlowType {
|
pub enum CommissionningFlowType {
|
||||||
|
@ -21,6 +42,16 @@ pub struct DiscoveryCapabilitiesSchema {
|
||||||
soft_access_point: bool,
|
soft_access_point: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DiscoveryCapabilitiesSchema {
|
||||||
|
pub fn new(on_ip_network: bool, ble: bool, soft_access_point: bool) -> Self {
|
||||||
|
DiscoveryCapabilitiesSchema {
|
||||||
|
on_ip_network,
|
||||||
|
ble,
|
||||||
|
soft_access_point,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DiscoveryCapabilitiesSchema {
|
impl DiscoveryCapabilitiesSchema {
|
||||||
fn as_bits(&self) -> u8 {
|
fn as_bits(&self) -> u8 {
|
||||||
let mut bits = 0;
|
let mut bits = 0;
|
||||||
|
@ -59,18 +90,20 @@ impl<'data> QrCodeData<'data> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_and_print_pairing_code(dev_det: &BasicInfoConfig, comm_data: &CommissioningData) {
|
struct TlvData {
|
||||||
|
data_length_in_bytes: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prepares and prints the pairing code and the QR code for easy pairing.
|
||||||
|
pub fn print_pairing_code_and_qr(dev_det: &BasicInfoConfig, comm_data: &CommissioningData) {
|
||||||
let pairing_code = compute_pairing_code(comm_data);
|
let pairing_code = compute_pairing_code(comm_data);
|
||||||
pretty_print_pairing_code(&pairing_code);
|
|
||||||
|
|
||||||
let disc_cap = DiscoveryCapabilitiesSchema {
|
|
||||||
on_ip_network: true,
|
|
||||||
ble: false,
|
|
||||||
soft_access_point: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// todo: allow the discovery capabilities to be passed in
|
||||||
|
let disc_cap = DiscoveryCapabilitiesSchema::new(true, false, false);
|
||||||
let qr_code_data = QrCodeData::new(dev_det, comm_data, disc_cap);
|
let qr_code_data = QrCodeData::new(dev_det, comm_data, disc_cap);
|
||||||
let data_str = payload_base38_representation(&qr_code_data).expect("Failed to encode");
|
let data_str = payload_base38_representation(&qr_code_data).expect("Failed to encode");
|
||||||
|
|
||||||
|
pretty_print_pairing_code(&pairing_code);
|
||||||
print_qr_code(&data_str);
|
print_qr_code(&data_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +131,7 @@ fn compute_pairing_code(comm_data: &CommissioningData) -> String {
|
||||||
digits
|
digits
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pretty_print_pairing_code(pairing_code: &str) {
|
fn pretty_print_pairing_code(pairing_code: &str) {
|
||||||
assert!(pairing_code.len() == 11);
|
assert!(pairing_code.len() == 11);
|
||||||
let mut pretty = String::new();
|
let mut pretty = String::new();
|
||||||
pretty.push_str(&pairing_code[..4]);
|
pretty.push_str(&pairing_code[..4]);
|
||||||
|
@ -116,7 +149,7 @@ fn print_qr_code(qr_data: &str) {
|
||||||
.dark_color(unicode::Dense1x2::Light)
|
.dark_color(unicode::Dense1x2::Light)
|
||||||
.light_color(unicode::Dense1x2::Dark)
|
.light_color(unicode::Dense1x2::Dark)
|
||||||
.build();
|
.build();
|
||||||
println!("{}", image);
|
info!("\n{}", image);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_bits(
|
fn populate_bits(
|
||||||
|
@ -148,34 +181,11 @@ fn populate_bits(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
const LONG_BITS: usize = 12;
|
|
||||||
const VERSION_FIELD_LENGTH_IN_BITS: usize = 3;
|
|
||||||
const VENDOR_IDFIELD_LENGTH_IN_BITS: usize = 16;
|
|
||||||
const PRODUCT_IDFIELD_LENGTH_IN_BITS: usize = 16;
|
|
||||||
const COMMISSIONING_FLOW_FIELD_LENGTH_IN_BITS: usize = 2;
|
|
||||||
const RENDEZVOUS_INFO_FIELD_LENGTH_IN_BITS: usize = 8;
|
|
||||||
const PAYLOAD_DISCRIMINATOR_FIELD_LENGTH_IN_BITS: usize = LONG_BITS;
|
|
||||||
const SETUP_PINCODE_FIELD_LENGTH_IN_BITS: usize = 27;
|
|
||||||
const PADDING_FIELD_LENGTH_IN_BITS: usize = 4;
|
|
||||||
const RAW_VENDOR_TAG_LENGTH_IN_BITS: usize = 7;
|
|
||||||
const TOTAL_PAYLOAD_DATA_SIZE_IN_BITS: usize = VERSION_FIELD_LENGTH_IN_BITS
|
|
||||||
+ VENDOR_IDFIELD_LENGTH_IN_BITS
|
|
||||||
+ PRODUCT_IDFIELD_LENGTH_IN_BITS
|
|
||||||
+ COMMISSIONING_FLOW_FIELD_LENGTH_IN_BITS
|
|
||||||
+ RENDEZVOUS_INFO_FIELD_LENGTH_IN_BITS
|
|
||||||
+ PAYLOAD_DISCRIMINATOR_FIELD_LENGTH_IN_BITS
|
|
||||||
+ SETUP_PINCODE_FIELD_LENGTH_IN_BITS
|
|
||||||
+ PADDING_FIELD_LENGTH_IN_BITS;
|
|
||||||
const TOTAL_PAYLOAD_DATA_SIZE_IN_BYTES: usize = TOTAL_PAYLOAD_DATA_SIZE_IN_BITS / 8;
|
|
||||||
|
|
||||||
struct TlvData {
|
|
||||||
data_length_in_bytes: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn payload_base38_representation_with_tlv(
|
fn payload_base38_representation_with_tlv(
|
||||||
payload: &QrCodeData,
|
payload: &QrCodeData,
|
||||||
bits: &mut [u8; TOTAL_PAYLOAD_DATA_SIZE_IN_BYTES],
|
bits: &mut [u8; TOTAL_PAYLOAD_DATA_SIZE_IN_BYTES],
|
||||||
tlv_data: Option<TlvData>,
|
tlv_data: Option<&TlvData>,
|
||||||
) -> Result<String, Error> {
|
) -> Result<String, Error> {
|
||||||
generate_bit_set(payload, bits, tlv_data)?;
|
generate_bit_set(payload, bits, tlv_data)?;
|
||||||
let base38_encoded = base38::encode(&*bits);
|
let base38_encoded = base38::encode(&*bits);
|
||||||
|
@ -193,10 +203,10 @@ fn payload_base38_representation(payload: &QrCodeData) -> Result<String, Error>
|
||||||
fn generate_bit_set(
|
fn generate_bit_set(
|
||||||
payload: &QrCodeData,
|
payload: &QrCodeData,
|
||||||
bits: &mut [u8; TOTAL_PAYLOAD_DATA_SIZE_IN_BYTES],
|
bits: &mut [u8; TOTAL_PAYLOAD_DATA_SIZE_IN_BYTES],
|
||||||
tlv_data: Option<TlvData>,
|
tlv_data: Option<&TlvData>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut offset: usize = 0;
|
let mut offset: usize = 0;
|
||||||
let total_payload_size_in_bits = if let Some(tlv_data) = &tlv_data {
|
let total_payload_size_in_bits = if let Some(tlv_data) = tlv_data {
|
||||||
TOTAL_PAYLOAD_DATA_SIZE_IN_BITS + (tlv_data.data_length_in_bytes * 8) as usize
|
TOTAL_PAYLOAD_DATA_SIZE_IN_BITS + (tlv_data.data_length_in_bytes * 8) as usize
|
||||||
} else {
|
} else {
|
||||||
TOTAL_PAYLOAD_DATA_SIZE_IN_BITS
|
TOTAL_PAYLOAD_DATA_SIZE_IN_BITS
|
||||||
|
@ -314,12 +324,8 @@ mod tests {
|
||||||
pid: 65279,
|
pid: 65279,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let disc_cap = DiscoveryCapabilitiesSchema {
|
|
||||||
on_ip_network: false,
|
|
||||||
ble: true,
|
|
||||||
soft_access_point: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let disc_cap = DiscoveryCapabilitiesSchema::new(false, true, false);
|
||||||
let qr_code_data = QrCodeData::new(&dev_det, &comm_data, disc_cap);
|
let qr_code_data = QrCodeData::new(&dev_det, &comm_data, disc_cap);
|
||||||
let data_str = payload_base38_representation(&qr_code_data).expect("Failed to encode");
|
let data_str = payload_base38_representation(&qr_code_data).expect("Failed to encode");
|
||||||
assert_eq!(data_str, QR_CODE)
|
assert_eq!(data_str, QR_CODE)
|
||||||
|
|
Loading…
Add table
Reference in a new issue