Yacubane / esp32-arduino-matter

Matter IoT protocol library for ESP32 working on Arduino framework
Apache License 2.0
323 stars 34 forks source link

Generating a QR code string #35

Closed smeisner closed 1 year ago

smeisner commented 1 year ago

First of all, thank you for your work!

I am working on a device that has a touchscreen and want to generate a QR code myself to display (allowing the user to merely scan that to provision it).

I understand calling PrintOnboardingCodes() will show the text of the QR code, but I want to retrieve the data string, generate the QR code and display it. When I call chip::GetQRCode() with a std::string as the first arg, I am met with an incompatible type:

lib/esp32-arduino-matter/src/app/server/OnboardingCodesUtil.h:33:12: note: candidate: 'CHIP_ERROR GetQRCode(chip::MutableCharSpan&, chip::RendezvousInformationFlags)'
 CHIP_ERROR GetQRCode(chip::MutableCharSpan & aQRCode, chip::RendezvousInformationFlags aRendezvousFlags);
            ^~~~~~~~~
lib/esp32-arduino-matter/src/app/server/OnboardingCodesUtil.h:33:12: note:   no known conversion for argument 1 from 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'chip::MutableCharSpan&' {aka 'chip::Span<char>&'}
lib/esp32-arduino-matter/src/app/server/OnboardingCodesUtil.h:40:12: note: candidate: 'CHIP_ERROR GetQRCode(chip::MutableCharSpan&, const chip::PayloadContents&)'
 CHIP_ERROR GetQRCode(chip::MutableCharSpan & aQRCode, const chip::PayloadContents & payload);
            ^~~~~~~~~
lib/esp32-arduino-matter/src/app/server/OnboardingCodesUtil.h:40:12: note:   no known conversion for argument 1 from 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'chip::MutableCharSpan&' {aka 'chip::Span<char>&'}

The code snippet is:

#include "Matter.h"
#include <app/server/OnboardingCodesUtil.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>

using namespace chip;
using namespace chip::app::Clusters;
using namespace esp_matter;
using namespace esp_matter::endpoint;

...

**[In Matter init func]**

// Start Matter device
  esp_matter::start(on_device_event);

  // Get QR Code 
  std::string QRCode;

  ESP_LOGE(TAG, "Calling PrintOnboardingCodes()\n");
  // Print codes needed to setup Matter device
  #if 0
    PrintOnboardingCodes(RendezvousInformationFlags(RendezvousInformationFlag::kOnNetwork));
  #else
    if (GetQRCode(QRCode, RendezvousInformationFlag::kOnNetwork) == CHIP_NO_ERROR)
    {
      strcpy (OperatingParameters.MatterQR, QRCode.c_str());
      ESP_LOGE(TAG, "QR Pairing Code: '%s'\n", OperatingParameters.MatterQR);
    } else {
      ESP_LOGE(TAG, "Failed to GetQRCode()!!\n");
    }
  #endif

What is the right way to fetch the QR code string?

smeisner commented 1 year ago

A few more details...

I did try changing the data type of the QRCode to MutableCharSpan and copying the returned string as QRCode.data(), which compiles. The problem I am seeing now is when calling GetQRCode() it returns CHIP_ERROR_BUFFER_TOO_SMALL (0x19).

I am assuming this is due to declaring QRCode simply as MutableCharSpan QRCode;. How do you provide storage when declaring the variable? ...or after?

smeisner commented 1 year ago

ok, it wasn't easy/obvious, but I got it working. Here's the code

.
.
.

  ESP_LOGE(TAG, "Calling esp_matter::start()\n");
  // Start Matter device
  esp_matter::start(on_device_event);

  // Get QR Code 
  std::string QRCode = "                                 ";  // 33 chars
  CHIP_ERROR err;

  ESP_LOGE(TAG, "Calling PrintOnboardingCodes()\n");
  // Print codes needed to setup Matter device
  #if 0
    PrintOnboardingCodes(RendezvousInformationFlags(RendezvousInformationFlag::kOnNetwork));
  #else
    err = GetQRCode((MutableCharSpan &)QRCode, RendezvousInformationFlag::kOnNetwork);
    if (err == CHIP_NO_ERROR)
    {
      // strcpy (OperatingParameters.MatterQR, QRCode.data());
      strcpy (OperatingParameters.MatterQR, QRCode.c_str());
      ESP_LOGE(TAG, "QR Pairing Code: '%s'\n", OperatingParameters.MatterQR);
    } else {
      ESP_LOGE(TAG, "Failed to GetQRCode() -- Error: %d\n", err.AsInteger());
    }
  #endif
Yacubane commented 1 year ago

Thanks for sharing it ;)

Btw. there should be possibility to set these codes, however I haven't tested it: https://github.com/espressif/esp-matter/blob/4707b88ceb5e6328f7b571b652487507429c1891/docs/en/developing.rst (2.5 Factory Data Providers section)