Skip to content

Commit

Permalink
Merge branch 'controller/pairing_command_callbacks' into 'main'
Browse files Browse the repository at this point in the history
controller: add APIs to set callbacks for pairing command

Closes CON-1420

See merge request app-frameworks/esp-matter!960
  • Loading branch information
chshu committed Dec 16, 2024
2 parents bd3092a + 22aa659 commit 88a9009
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <credentials/FabricTable.h>
#include <esp_log.h>
#include <esp_matter_controller_client.h>
#include <esp_matter_controller_pairing_command.h>
#include <optional>

static const char *TAG = "pairing_command";

Expand All @@ -24,71 +26,48 @@ using namespace chip::Controller;
namespace esp_matter {
namespace controller {

void pairing_command::OnStatusUpdate(DevicePairingDelegate::Status status)
{
switch (status) {
case DevicePairingDelegate::Status::SecurePairingSuccess:
ESP_LOGI(TAG, "Secure Pairing Success");
break;
case DevicePairingDelegate::Status::SecurePairingFailed:
ESP_LOGI(TAG, "Secure Pairing Failed");
break;
}
}

void pairing_command::OnPairingComplete(CHIP_ERROR err)
{
if (err == CHIP_NO_ERROR) {
ESP_LOGI(TAG, "Pairing Success");
ESP_LOGI(TAG, "PASE session establishment success");
} else {
ESP_LOGI(TAG, "Pairing Failure: Matter-%s", ErrorStr(err));
ESP_LOGI(TAG, "PASE session establishment failure: Matter-%s", ErrorStr(err));
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(nullptr);
}
}

void pairing_command::OnPairingDeleted(CHIP_ERROR err)
{
if (err == CHIP_NO_ERROR) {
ESP_LOGI(TAG, "Pairing Deleted Success");
} else {
ESP_LOGI(TAG, "Pairing Deleted Failure: Matter-%s", ErrorStr(err));
if (m_callbacks.pase_callback) {
m_callbacks.pase_callback(err);
}
}

void pairing_command::OnCommissioningComplete(NodeId nodeId, CHIP_ERROR err)
void pairing_command::OnCommissioningSuccess(chip::PeerId peerId)
{
if (err == CHIP_NO_ERROR) {
ESP_LOGI(TAG, "Device commissioning completed with success - getting OperationalDeviceProxy");
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->GetConnectedDevice(nodeId, &mOnDeviceConnectedCallback,
&mOnDeviceConnectionFailureCallback);
} else {
ESP_LOGI(TAG, "Device commissioning Failure: Matter%s", ErrorStr(err));
ESP_LOGI(TAG, "Commissioning success with node %" PRIX64 "-%" PRIX64, peerId.GetCompressedFabricId(),
peerId.GetNodeId());
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(nullptr);
if (m_callbacks.commissioning_success_callback) {
auto fabric = controller_instance.get_commissioner()->GetFabricTable()->FindFabricWithCompressedId(
peerId.GetCompressedFabricId());
m_callbacks.commissioning_success_callback(ScopedNodeId(fabric->GetFabricIndex(), peerId.GetNodeId()));
}
}

void pairing_command::OnDeviceConnectedFn(void *context, ExchangeManager &exchangeMgr,
const SessionHandle &sessionHandle)
{
ESP_LOGI(TAG, "OnDeviceConnectedFn");
}

void pairing_command::OnDeviceConnectionFailureFn(void *context, const ScopedNodeId &peerId, CHIP_ERROR err)
{
ESP_LOGI(TAG, "OnDeviceConnectionFailureFn - attempt to get OperationalDeviceProxy failed");
}

CommissioningParameters pairing_command::get_commissioning_params()
void pairing_command::OnCommissioningFailure(
chip::PeerId peerId, CHIP_ERROR error, chip::Controller::CommissioningStage stageFailed,
chip::Optional<chip::Credentials::AttestationVerificationResult> additionalErrorInfo)
{
switch (m_pairing_network_type) {
case NETWORK_TYPE_ETHERNET:
case NETWORK_TYPE_NONE:
return CommissioningParameters();
break;
default:
ESP_LOGE(TAG, "Unsuppoted pairing network type");
break;
ESP_LOGI(TAG, "Commissioning failure with node %" PRIX64 "-%" PRIX64, peerId.GetCompressedFabricId(),
peerId.GetNodeId());
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(nullptr);
if (m_callbacks.commissioning_failure_callback) {
auto fabric = controller_instance.get_commissioner()->GetFabricTable()->FindFabricWithCompressedId(
peerId.GetCompressedFabricId());
m_callbacks.commissioning_failure_callback(
ScopedNodeId(fabric->GetFabricIndex(), peerId.GetNodeId()), error, stageFailed,
additionalErrorInfo.HasValue() ? std::make_optional(additionalErrorInfo.Value()) : std::nullopt);
}
return CommissioningParameters();
}

void pairing_command::OnDiscoveredDevice(const Dnssd::CommissionNodeData &nodeData)
Expand All @@ -104,12 +83,11 @@ void pairing_command::OnDiscoveredDevice(const Dnssd::CommissionNodeData &nodeDa
// Stop Mdns discovery. TODO: Check whether it is a right method
controller_instance.get_commissioner()->RegisterDeviceDiscoveryDelegate(nullptr);

Inet::InterfaceId interfaceId = nodeData.ipAddress[0].IsIPv6LinkLocal()
? nodeData.interfaceId
: Inet::InterfaceId::Null();
Inet::InterfaceId interfaceId =
nodeData.ipAddress[0].IsIPv6LinkLocal() ? nodeData.interfaceId : Inet::InterfaceId::Null();
PeerAddress peerAddress = PeerAddress::UDP(nodeData.ipAddress[0], port, interfaceId);
RendezvousParameters params = RendezvousParameters().SetSetupPINCode(m_setup_pincode).SetPeerAddress(peerAddress);
CommissioningParameters commissioning_params = get_commissioning_params();
CommissioningParameters commissioning_params = CommissioningParameters();
controller_instance.get_commissioner()->PairDevice(m_remote_node_id, params, commissioning_params);
}

Expand All @@ -118,10 +96,9 @@ esp_err_t pairing_on_network(NodeId node_id, uint32_t pincode)
Dnssd::DiscoveryFilter filter(Dnssd::DiscoveryFilterType::kNone);
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterDeviceDiscoveryDelegate(&pairing_command::get_instance());
pairing_command::get_instance().m_pairing_mode = PAIRING_MODE_ONNETWORK;
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());
pairing_command::get_instance().m_setup_pincode = pincode;
pairing_command::get_instance().m_remote_node_id = node_id;
pairing_command::get_instance().m_pairing_network_type = NETWORK_TYPE_NONE;
if (CHIP_NO_ERROR != controller_instance.get_commissioner()->DiscoverCommissionableNodes(filter)) {
ESP_LOGE(TAG, "Failed to discover commissionable nodes");
return ESP_FAIL;
Expand All @@ -134,12 +111,13 @@ esp_err_t pairing_ble_wifi(NodeId node_id, uint32_t pincode, uint16_t disc, cons
{
RendezvousParameters params = RendezvousParameters().SetSetupPINCode(pincode).SetDiscriminator(disc).SetPeerAddress(
Transport::PeerAddress::BLE());
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());

ByteSpan nameSpan(reinterpret_cast<const uint8_t *>(ssid), strlen(ssid));
ByteSpan pwdSpan(reinterpret_cast<const uint8_t *>(pwd), strlen(pwd));
CommissioningParameters commissioning_params =
CommissioningParameters().SetWiFiCredentials(Controller::WiFiCredentials(nameSpan, pwdSpan));
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->PairDevice(node_id, params, commissioning_params);
return ESP_OK;
}
Expand All @@ -149,10 +127,11 @@ esp_err_t pairing_ble_thread(NodeId node_id, uint32_t pincode, uint16_t disc, ui
{
RendezvousParameters params = RendezvousParameters().SetSetupPINCode(pincode).SetDiscriminator(disc).SetPeerAddress(
Transport::PeerAddress::BLE());
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());

ByteSpan dataset_span(dataset_tlvs, dataset_len);
CommissioningParameters commissioning_params = CommissioningParameters().SetThreadOperationalDataset(dataset_span);
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->PairDevice(node_id, params, commissioning_params);
return ESP_OK;
}
Expand All @@ -162,7 +141,9 @@ esp_err_t pairing_code(NodeId nodeId, const char *payload)
{
CommissioningParameters commissioning_params = CommissioningParameters();
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->PairDevice(nodeId, payload, commissioning_params, DiscoveryType::kDiscoveryNetworkOnly);
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());
controller_instance.get_commissioner()->PairDevice(nodeId, payload, commissioning_params,
DiscoveryType::kDiscoveryNetworkOnly);
return ESP_OK;
}

Expand All @@ -172,6 +153,7 @@ esp_err_t pairing_code_thread(NodeId nodeId, const char *payload, uint8_t *datas

CommissioningParameters commissioning_params = CommissioningParameters().SetThreadOperationalDataset(dataset_span);
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());
controller_instance.get_commissioner()->PairDevice(nodeId, payload, commissioning_params, DiscoveryType::kAll);

return ESP_OK;
Expand All @@ -185,22 +167,25 @@ esp_err_t pairing_code_wifi(NodeId nodeId, const char *ssid, const char *passwor
CommissioningParameters commissioning_params =
CommissioningParameters().SetWiFiCredentials(Controller::WiFiCredentials(nameSpan, pwdSpan));
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());
controller_instance.get_commissioner()->PairDevice(nodeId, payload, commissioning_params, DiscoveryType::kAll);

return ESP_OK;
}

esp_err_t pairing_code_wifi_thread(NodeId nodeId, const char *ssid, const char *password, const char *payload,
uint8_t *dataset_buf, uint8_t dataset_len)
uint8_t *dataset_buf, uint8_t dataset_len)
{
ByteSpan nameSpan(reinterpret_cast<const uint8_t *>(ssid), strlen(ssid));
ByteSpan pwdSpan(reinterpret_cast<const uint8_t *>(password), strlen(password));
ByteSpan dataset_span(dataset_buf, dataset_len);

CommissioningParameters commissioning_params =
CommissioningParameters().SetWiFiCredentials(Controller::WiFiCredentials(nameSpan, pwdSpan)).SetThreadOperationalDataset(
dataset_span);
CommissioningParameters()
.SetWiFiCredentials(Controller::WiFiCredentials(nameSpan, pwdSpan))
.SetThreadOperationalDataset(dataset_span);
auto &controller_instance = esp_matter::controller::matter_controller_client::get_instance();
controller_instance.get_commissioner()->RegisterPairingDelegate(&pairing_command::get_instance());
controller_instance.get_commissioner()->PairDevice(nodeId, payload, commissioning_params, DiscoveryType::kAll);

return ESP_OK;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,32 @@ using chip::Messaging::ExchangeManager;
namespace esp_matter {
namespace controller {

typedef enum pairing_network_type {
NETWORK_TYPE_NONE,
NETWORK_TYPE_WIFI,
NETWORK_TYPE_THREAD,
NETWORK_TYPE_ETHERNET,
} pairing_network_type_t;

typedef enum pairing_mode {
PAIRING_MODE_NONE,
PAIRING_MODE_CODE,
PAIRING_MODE_BLE,
PAIRING_MODE_SOFTAP,
PAIRING_MODE_ETHERNET,
PAIRING_MODE_ONNETWORK,
} pairing_mode_t;
typedef struct {
// Callback for the success or failure of PASE session establishment. err will be CHIP_NO_ERROR when the commissioner
// establishes PASE session with peer node. Otherwise the commissioner fails to establish PASE session.
void (*pase_callback)(CHIP_ERROR err);
// Callback for the sussess of commisioning
void (*commissioning_success_callback)(ScopedNodeId peer_id);
// Callback for the failure of commissioning
void (*commissioning_failure_callback)(
ScopedNodeId peer_id, CHIP_ERROR error, chip::Controller::CommissioningStage stage,
std::optional<chip::Credentials::AttestationVerificationResult> addtional_err_info);
} pairing_command_callbacks_t;

/** Pairing command class to finish commissioning with Matter end-devices **/
class pairing_command : public chip::Controller::DevicePairingDelegate,
public chip::Controller::DeviceDiscoveryDelegate {
public:
/****************** DevicePairingDelegate Interface *****************/
void OnStatusUpdate(DevicePairingDelegate::Status status) override;
// This function will be called when the PASE session is established or the commisioner fails to establish
// PASE session.
void OnPairingComplete(CHIP_ERROR error) override;
void OnPairingDeleted(CHIP_ERROR error) override;
void OnCommissioningComplete(NodeId deviceId, CHIP_ERROR error) override;
// The two functions are invoked upon the completion of the commissioning process, either successfully or
// failed.
void OnCommissioningSuccess(chip::PeerId peerId) override;
void OnCommissioningFailure(
chip::PeerId peerId, CHIP_ERROR error, chip::Controller::CommissioningStage stageFailed,
chip::Optional<chip::Credentials::AttestationVerificationResult> additionalErrorInfo) override;

/****************** DeviceDiscoveryDelegate Interface ***************/
void OnDiscoveredDevice(const chip::Dnssd::CommissionNodeData &nodeData) override;
Expand All @@ -62,25 +63,16 @@ class pairing_command : public chip::Controller::DevicePairingDelegate,
return s_instance;
}

void set_callbacks(pairing_command_callbacks_t callbacks) { m_callbacks = callbacks; }

NodeId m_remote_node_id;
uint32_t m_setup_pincode;
uint16_t m_discriminator;
pairing_network_type_t m_pairing_network_type;
pairing_mode_t m_pairing_mode;
pairing_command_callbacks_t m_callbacks;

private:
pairing_command()
: mOnDeviceConnectedCallback(OnDeviceConnectedFn, this)
, mOnDeviceConnectionFailureCallback(OnDeviceConnectionFailureFn, this)
{
}
CommissioningParameters get_commissioning_params();

static void OnDeviceConnectedFn(void *context, ExchangeManager &exchangeMgr, const SessionHandle &sessionHandle);
static void OnDeviceConnectionFailureFn(void *context, const ScopedNodeId &peerId, CHIP_ERROR error);

chip::Callback::Callback<chip::OnDeviceConnected> mOnDeviceConnectedCallback;
chip::Callback::Callback<chip::OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback;
: m_remote_node_id(0), m_setup_pincode(0), m_discriminator(0), m_callbacks{nullptr, nullptr, nullptr} {}
};

/**
Expand Down

0 comments on commit 88a9009

Please sign in to comment.