Remove heapless::String from QR API

This commit is contained in:
ivmarkov 2023-04-29 17:20:55 +00:00
parent 2a2bdab9c5
commit 5fc3d2d510
5 changed files with 70 additions and 42 deletions

View file

@ -54,8 +54,8 @@ fn main() -> Result<(), impl Error> {
device_name: "OnOff Light", device_name: "OnOff Light",
}; };
let mut mdns = matter::mdns::astro::AstroMdns::new()?; //let mut mdns = matter::mdns::astro::AstroMdns::new()?;
//let mut mdns = matter::mdns::libmdns::LibMdns::new()?; let mut mdns = matter::mdns::libmdns::LibMdns::new()?;
//let mut mdns = matter::mdns::DummyMdns {}; //let mut mdns = matter::mdns::DummyMdns {};
let matter = Matter::new_default(&dev_info, &mut mdns, matter::transport::udp::MATTER_PORT); let matter = Matter::new_default(&dev_info, &mut mdns, matter::transport::udp::MATTER_PORT);
@ -77,7 +77,7 @@ fn main() -> Result<(), impl Error> {
matter.load_fabrics(data)?; matter.load_fabrics(data)?;
} }
matter.start::<4096>( matter.start(
CommissioningData { CommissioningData {
// TODO: Hard-coded for now // TODO: Hard-coded for now
verifier: VerifierData::new_with_pw(123456, *matter.borrow()), verifier: VerifierData::new_with_pw(123456, *matter.borrow()),

View file

@ -116,19 +116,15 @@ impl<'a> Matter<'a> {
self.acl_mgr.borrow_mut().store(buf) self.acl_mgr.borrow_mut().store(buf)
} }
pub fn start<const N: usize>( pub fn start(&self, dev_comm: CommissioningData, buf: &mut [u8]) -> Result<(), Error> {
&self,
dev_comm: CommissioningData,
buf: &mut [u8],
) -> Result<(), Error> {
let open_comm_window = self.fabric_mgr.borrow().is_empty(); let open_comm_window = self.fabric_mgr.borrow().is_empty();
if open_comm_window { if open_comm_window {
print_pairing_code_and_qr::<N>( print_pairing_code_and_qr(
self.dev_det, self.dev_det,
&dev_comm, &dev_comm,
DiscoveryCapabilities::default(), DiscoveryCapabilities::default(),
buf, buf,
); )?;
self.pase_mgr.borrow_mut().enable_pase_session( self.pase_mgr.borrow_mut().enable_pase_session(
dev_comm.verifier, dev_comm.verifier,

View file

@ -19,7 +19,7 @@ use core::fmt::Write;
use super::*; use super::*;
pub(super) fn compute_pairing_code(comm_data: &CommissioningData) -> heapless::String<32> { pub fn compute_pairing_code(comm_data: &CommissioningData) -> heapless::String<32> {
// 0: no Vendor ID and Product ID present in Manual Pairing Code // 0: no Vendor ID and Product ID present in Manual Pairing Code
const VID_PID_PRESENT: u8 = 0; const VID_PID_PRESENT: u8 = 0;

View file

@ -31,7 +31,7 @@ use crate::{
use self::{ use self::{
code::{compute_pairing_code, pretty_print_pairing_code}, code::{compute_pairing_code, pretty_print_pairing_code},
qr::{payload_base38_representation, print_qr_code, QrSetupPayload}, qr::{compute_qr_code, print_qr_code},
}; };
pub struct DiscoveryCapabilities { pub struct DiscoveryCapabilities {
@ -81,19 +81,19 @@ impl DiscoveryCapabilities {
} }
/// Prepares and prints the pairing code and the QR code for easy pairing. /// Prepares and prints the pairing code and the QR code for easy pairing.
pub fn print_pairing_code_and_qr<const N: usize>( pub fn print_pairing_code_and_qr(
dev_det: &BasicInfoConfig, dev_det: &BasicInfoConfig,
comm_data: &CommissioningData, comm_data: &CommissioningData,
discovery_capabilities: DiscoveryCapabilities, discovery_capabilities: DiscoveryCapabilities,
buf: &mut [u8], buf: &mut [u8],
) { ) -> Result<(), Error> {
let pairing_code = compute_pairing_code(comm_data); let pairing_code = compute_pairing_code(comm_data);
let qr_code_data = QrSetupPayload::new(dev_det, comm_data, discovery_capabilities); let qr_code = compute_qr_code(dev_det, comm_data, discovery_capabilities, buf)?;
let data_str =
payload_base38_representation::<N>(&qr_code_data, buf).expect("Failed to encode");
pretty_print_pairing_code(&pairing_code); pretty_print_pairing_code(&pairing_code);
print_qr_code(&data_str); print_qr_code(&qr_code);
Ok(())
} }
pub(self) fn passwd_from_comm_data(comm_data: &CommissioningData) -> u32 { pub(self) fn passwd_from_comm_data(comm_data: &CommissioningData) -> u32 {

View file

@ -253,20 +253,24 @@ pub enum CommissionningFlowType {
Custom = 2, Custom = 2,
} }
pub(super) fn payload_base38_representation<const N: usize>( pub(super) fn payload_base38_representation<'a>(
payload: &QrSetupPayload, payload: &QrSetupPayload,
buf: &mut [u8], buf: &'a mut [u8],
) -> Result<heapless::String<N>, Error> { ) -> Result<&'a str, Error> {
if payload.is_valid() { if payload.is_valid() {
let (bits_buf, tlv_buf) = if payload.has_tlv() { let (str_buf, bits_buf, tlv_buf) = if payload.has_tlv() {
let (bits_buf, tlv_buf) = buf.split_at_mut(buf.len() / 2); let (str_buf, buf) = buf.split_at_mut(buf.len() / 3 * 2);
(bits_buf, Some(tlv_buf)) let (bits_buf, tlv_buf) = buf.split_at_mut(buf.len() / 3);
(str_buf, bits_buf, Some(tlv_buf))
} else { } else {
(buf, None) let (str_buf, buf) = buf.split_at_mut(buf.len() / 3 * 2);
(str_buf, buf, None)
}; };
payload_base38_representation_with_tlv(payload, bits_buf, tlv_buf) payload_base38_representation_with_tlv(payload, str_buf, bits_buf, tlv_buf)
} else { } else {
Err(ErrorCode::InvalidArgument.into()) Err(ErrorCode::InvalidArgument.into())
} }
@ -315,16 +319,16 @@ fn estimate_struct_overhead(first_field_size: usize) -> usize {
first_field_size + 4 + 2 first_field_size + 4 + 2
} }
pub(super) fn print_qr_code(qr_data: &str) { pub(super) fn print_qr_code(qr_code: &str) {
info!("QR Code: {}", qr_data); info!("QR Code: {}", qr_code);
#[cfg(feature = "std")] #[cfg(feature = "std")]
{ {
use qrcode::{render::unicode, QrCode, Version}; use qrcode::{render::unicode, QrCode, Version};
let needed_version = compute_qr_version(qr_data); let needed_version = compute_qr_version(qr_code);
let code = let code =
QrCode::with_version(qr_data, Version::Normal(needed_version), qrcode::EcLevel::M) QrCode::with_version(qr_code, Version::Normal(needed_version), qrcode::EcLevel::M)
.unwrap(); .unwrap();
let image = code let image = code
.render::<unicode::Dense1x2>() .render::<unicode::Dense1x2>()
@ -336,6 +340,16 @@ pub(super) fn print_qr_code(qr_data: &str) {
} }
} }
pub fn compute_qr_code<'a>(
dev_det: &BasicInfoConfig,
comm_data: &CommissioningData,
discovery_capabilities: DiscoveryCapabilities,
buf: &'a mut [u8],
) -> Result<&'a str, Error> {
let qr_code_data = QrSetupPayload::new(dev_det, comm_data, discovery_capabilities);
payload_base38_representation(&qr_code_data, buf)
}
fn compute_qr_version(qr_data: &str) -> i16 { fn compute_qr_version(qr_data: &str) -> i16 {
match qr_data.len() { match qr_data.len() {
0..=38 => 2, 0..=38 => 2,
@ -375,11 +389,12 @@ fn populate_bits(
Ok(()) Ok(())
} }
fn payload_base38_representation_with_tlv<const N: usize>( fn payload_base38_representation_with_tlv<'a>(
payload: &QrSetupPayload, payload: &QrSetupPayload,
str_buf: &'a mut [u8],
bits_buf: &mut [u8], bits_buf: &mut [u8],
tlv_buf: Option<&mut [u8]>, tlv_buf: Option<&mut [u8]>,
) -> Result<heapless::String<N>, Error> { ) -> Result<&'a str, Error> {
let tlv_data = if let Some(tlv_buf) = tlv_buf { let tlv_data = if let Some(tlv_buf) = tlv_buf {
Some(generate_tlv_from_optional_data(payload, tlv_buf)?) Some(generate_tlv_from_optional_data(payload, tlv_buf)?)
} else { } else {
@ -388,13 +403,30 @@ fn payload_base38_representation_with_tlv<const N: usize>(
let bits = generate_bit_set(payload, bits_buf, tlv_data)?; let bits = generate_bit_set(payload, bits_buf, tlv_data)?;
let mut base38_encoded: heapless::String<N> = "MT:".into(); let prefix = "MT:";
for c in base38::encode(bits) { if str_buf.len() < prefix.as_bytes().len() {
base38_encoded.push(c).map_err(|_| ErrorCode::NoSpace)?; Err(ErrorCode::NoSpace)?;
} }
Ok(base38_encoded) str_buf[..prefix.as_bytes().len()].copy_from_slice(prefix.as_bytes());
let mut offset = prefix.len();
for c in base38::encode(bits) {
let mut char_buf = [0; 4];
let str = c.encode_utf8(&mut char_buf);
if str_buf.len() - offset < str.as_bytes().len() {
Err(ErrorCode::NoSpace)?;
}
str_buf[offset..offset + str.as_bytes().len()].copy_from_slice(str.as_bytes());
offset += str.as_bytes().len();
}
Ok(core::str::from_utf8(&str_buf[..offset])?)
} }
fn generate_tlv_from_optional_data<'a>( fn generate_tlv_from_optional_data<'a>(
@ -557,8 +589,8 @@ mod tests {
let disc_cap = DiscoveryCapabilities::new(false, true, false); let disc_cap = DiscoveryCapabilities::new(false, true, false);
let qr_code_data = QrSetupPayload::new(&dev_det, &comm_data, disc_cap); let qr_code_data = QrSetupPayload::new(&dev_det, &comm_data, disc_cap);
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let data_str = payload_base38_representation::<128>(&qr_code_data, &mut buf) let data_str =
.expect("Failed to encode"); payload_base38_representation(&qr_code_data, &mut buf).expect("Failed to encode");
assert_eq!(data_str, QR_CODE) assert_eq!(data_str, QR_CODE)
} }
@ -580,8 +612,8 @@ mod tests {
let disc_cap = DiscoveryCapabilities::new(true, false, false); let disc_cap = DiscoveryCapabilities::new(true, false, false);
let qr_code_data = QrSetupPayload::new(&dev_det, &comm_data, disc_cap); let qr_code_data = QrSetupPayload::new(&dev_det, &comm_data, disc_cap);
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let data_str = payload_base38_representation::<128>(&qr_code_data, &mut buf) let data_str =
.expect("Failed to encode"); payload_base38_representation(&qr_code_data, &mut buf).expect("Failed to encode");
assert_eq!(data_str, QR_CODE) assert_eq!(data_str, QR_CODE)
} }
@ -626,8 +658,8 @@ mod tests {
.expect("Failed to add optional data"); .expect("Failed to add optional data");
let mut buf = [0; 1024]; let mut buf = [0; 1024];
let data_str = payload_base38_representation::<{ QR_CODE.len() }>(&qr_code_data, &mut buf) let data_str =
.expect("Failed to encode"); payload_base38_representation(&qr_code_data, &mut buf).expect("Failed to encode");
assert_eq!(data_str, QR_CODE) assert_eq!(data_str, QR_CODE)
} }
} }