mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
example: Add light example with RainMaker-WiFi-Provisioning
This commit is contained in:
@@ -337,6 +337,13 @@ build_esp_matter_examples:
|
||||
- cp sdkconfig.defaults sdkconfig.defaults.backup
|
||||
- cp sdkconfig.defaults.ext_plat_ci sdkconfig.defaults
|
||||
|
||||
# steps for external platform build for light_wifi_prov app
|
||||
- cd ${ESP_MATTER_PATH}/examples/light_wifi_prov
|
||||
- cp sdkconfig.defaults.esp32s3 sdkconfig.defaults.esp32s3.backup
|
||||
- cp sdkconfig.defaults.esp32s3.ext_plat_ci sdkconfig.defaults.esp32s3
|
||||
- cp sdkconfig.defaults.esp32c3 sdkconfig.defaults.esp32c3.backup
|
||||
- cp sdkconfig.defaults.esp32c3.ext_plat_ci sdkconfig.defaults.esp32c3
|
||||
|
||||
- cd ${ESP_MATTER_PATH}
|
||||
- pip install -r tools/ci/requirements-build.txt
|
||||
- python tools/ci/build_apps.py ./examples --no_pytest
|
||||
|
||||
@@ -104,3 +104,9 @@ examples/ota_provider:
|
||||
- if: IDF_TARGET in ["esp32s3"]
|
||||
temporary: true
|
||||
reason: the other targets are not tested yet
|
||||
|
||||
examples/light_wifi_prov:
|
||||
enable:
|
||||
- if: IDF_TARGET in ["esp32s3", "esp32c3"]
|
||||
temporary: true
|
||||
reason: the other targets are not tested yet
|
||||
|
||||
@@ -0,0 +1,493 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2020-2021 Project CHIP Authors
|
||||
* Copyright (c) 2018 Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides an implementation of the BLEManager singleton object
|
||||
* for the ESP32 platform.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <lib/core/Optional.h>
|
||||
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
|
||||
#include "esp_bt.h"
|
||||
#include "esp_gap_ble_api.h"
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#include "esp_gattc_api.h"
|
||||
#endif
|
||||
#include "esp_gatts_api.h"
|
||||
#include <lib/core/CHIPCallback.h>
|
||||
|
||||
#elif defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
|
||||
/* min max macros in NimBLE can cause build issues with generic min max
|
||||
* functions defined in CHIP.*/
|
||||
#define min
|
||||
#define max
|
||||
#include "host/ble_hs.h"
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
/* GATT context */
|
||||
struct ble_gatt_char_context
|
||||
{
|
||||
uint16_t conn_handle;
|
||||
uint16_t attr_handle;
|
||||
struct ble_gatt_access_ctxt * ctxt;
|
||||
void * arg;
|
||||
};
|
||||
|
||||
#define MAX_ADV_DATA_LEN 31
|
||||
#define MAX_DEVICE_NAME_LEN 29
|
||||
|
||||
#endif // CONFIG_BT_BLUEDROID_ENABLED
|
||||
|
||||
#include <ble/Ble.h>
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#include <platform/ESP32/ChipDeviceScanner.h>
|
||||
#ifdef CONFIG_BT_NIMBLE_ENABLED
|
||||
#include "nimble/blecent.h"
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
|
||||
#define MAX_SCAN_RSP_DATA_LEN 31
|
||||
|
||||
namespace chip {
|
||||
namespace DeviceLayer {
|
||||
namespace Internal {
|
||||
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
enum class BleScanState : uint8_t
|
||||
{
|
||||
kNotScanning,
|
||||
kScanForDiscriminator,
|
||||
kScanForAddress,
|
||||
kConnecting,
|
||||
};
|
||||
|
||||
struct BLEAdvConfig
|
||||
{
|
||||
char * mpBleName;
|
||||
uint32_t mAdapterId;
|
||||
uint8_t mMajor;
|
||||
uint8_t mMinor;
|
||||
uint16_t mVendorId;
|
||||
uint16_t mProductId;
|
||||
uint64_t mDeviceId;
|
||||
uint8_t mPairingStatus;
|
||||
uint8_t mType;
|
||||
uint16_t mDuration;
|
||||
const char * mpAdvertisingUUID;
|
||||
};
|
||||
|
||||
struct BLEScanConfig
|
||||
{
|
||||
// If an active scan for connection is being performed
|
||||
BleScanState mBleScanState = BleScanState::kNotScanning;
|
||||
|
||||
// If scanning by discriminator, what are we scanning for
|
||||
SetupDiscriminator mDiscriminator;
|
||||
|
||||
// If scanning by address, what address are we searching for
|
||||
std::string mAddress;
|
||||
|
||||
// Optional argument to be passed to callback functions provided by the BLE scan/connect requestor
|
||||
void * mAppState = nullptr;
|
||||
};
|
||||
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
/**
|
||||
* Concrete implementation of the BLEManager singleton object for the ESP32 platform.
|
||||
*/
|
||||
class BLEManagerImpl final : public BLEManager,
|
||||
private Ble::BleLayer,
|
||||
private Ble::BlePlatformDelegate,
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
private Ble::BleApplicationDelegate,
|
||||
private Ble::BleConnectionDelegate,
|
||||
private ChipDeviceScannerDelegate
|
||||
#else
|
||||
private Ble::BleApplicationDelegate
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
{
|
||||
public:
|
||||
uint8_t scanResponseBuffer[MAX_SCAN_RSP_DATA_LEN];
|
||||
BLEManagerImpl() {}
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
CHIP_ERROR ConfigureBle(uint32_t aAdapterId, bool aIsCentral);
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
static void gattc_profile_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t * param);
|
||||
#endif // CONFIG_BT_BLUEDROID_ENABLED
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
|
||||
CHIP_ERROR ConfigureScanResponseData(ByteSpan data);
|
||||
void ClearScanResponseData(void);
|
||||
|
||||
CHIP_ERROR SetSecondaryGATTService(struct ble_gatt_svc_def *gatt_svc, size_t gattSvcIndex)
|
||||
{
|
||||
if (!gatt_svc || gattSvcIndex > 1)
|
||||
{
|
||||
return CHIP_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
mSecondGATTServiceIndex = gattSvcIndex;
|
||||
memcpy(&mGATTServices[gattSvcIndex], gatt_svc, sizeof(struct ble_gatt_svc_def));
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
using BleGapEventHandler = int(*)(struct ble_gap_event * event, void * arg);
|
||||
|
||||
void SetSecondaryAdvGapEventHandler(BleGapEventHandler handler) { mSecondaryBleGapEventHandler = handler; }
|
||||
|
||||
CHIP_ERROR SetSecondaryAdvDeviceName(const char *deviceName)
|
||||
{
|
||||
strncpy(mSecondaryAdvDeviceName, deviceName, MAX_DEVICE_NAME_LEN);
|
||||
mSecondaryAdvDeviceName[MAX_DEVICE_NAME_LEN] = 0;
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR SetSecondaryAdvUuid(const ByteSpan &uuid)
|
||||
{
|
||||
if (uuid.size() != 16)
|
||||
{
|
||||
return CHIP_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
mSecondaryAdvUuid.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(mSecondaryAdvUuid.value, uuid.data(), uuid.size());
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
void SetSecondaryBleSmConfig(bool bleBonding, bool bleSmSc)
|
||||
{
|
||||
mSecondaryBleBonding = bleBonding;
|
||||
mSecondaryBleSmSc = bleSmSc;
|
||||
}
|
||||
|
||||
private:
|
||||
chip::Optional<chip::ByteSpan> mScanResponse;
|
||||
|
||||
// Allow the BLEManager interface class to delegate method calls to
|
||||
// the implementation methods provided by this class.
|
||||
friend BLEManager;
|
||||
|
||||
// ===== Members that implement the BLEManager internal interface.
|
||||
|
||||
CHIP_ERROR _Init(void);
|
||||
void _Shutdown();
|
||||
bool _IsAdvertisingEnabled(void);
|
||||
CHIP_ERROR _SetAdvertisingEnabled(bool val);
|
||||
bool _IsAdvertising(void);
|
||||
CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode);
|
||||
CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize);
|
||||
CHIP_ERROR _SetDeviceName(const char * deviceName);
|
||||
uint16_t _NumConnections(void);
|
||||
void _OnPlatformEvent(const ChipDeviceEvent * event);
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
void HandlePlatformSpecificBLEEvent(const ChipDeviceEvent * event);
|
||||
CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val);
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
::chip::Ble::BleLayer * _GetBleLayer(void);
|
||||
|
||||
// ===== Members that implement virtual methods on BlePlatformDelegate.
|
||||
|
||||
CHIP_ERROR SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
|
||||
const Ble::ChipBleUUID * charId) override;
|
||||
CHIP_ERROR UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
|
||||
const Ble::ChipBleUUID * charId) override;
|
||||
CHIP_ERROR CloseConnection(BLE_CONNECTION_OBJECT conId) override;
|
||||
uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override;
|
||||
CHIP_ERROR SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
|
||||
System::PacketBufferHandle pBuf) override;
|
||||
CHIP_ERROR SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
|
||||
System::PacketBufferHandle pBuf) override;
|
||||
|
||||
// ===== Members that implement virtual methods on BleApplicationDelegate.
|
||||
|
||||
void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override;
|
||||
// ===== Members that implement virtual methods on BleConnectionDelegate.
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
|
||||
void NewConnection(chip::Ble::BleLayer * bleLayer, void * appState, const SetupDiscriminator & connDiscriminator) override;
|
||||
void NewConnection(chip::Ble::BleLayer * bleLayer, void * appState, BLE_CONNECTION_OBJECT connObj) override{};
|
||||
CHIP_ERROR CancelConnection() override;
|
||||
|
||||
// ===== Members that implement virtual methods on ChipDeviceScannerDelegate
|
||||
#ifdef CONFIG_BT_NIMBLE_ENABLED
|
||||
virtual void OnDeviceScanned(const struct ble_hs_adv_fields & fields, const ble_addr_t & addr,
|
||||
const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override;
|
||||
#elif defined(CONFIG_BT_BLUEDROID_ENABLED)
|
||||
virtual void OnDeviceScanned(esp_ble_addr_type_t & addr_type, esp_bd_addr_t & addr,
|
||||
const chip::Ble::ChipBLEDeviceIdentificationInfo & info) override;
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
void OnScanComplete() override;
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
// ===== Members for internal use by the following friends.
|
||||
|
||||
friend BLEManager & BLEMgr(void);
|
||||
friend BLEManagerImpl & BLEMgrImpl(void);
|
||||
|
||||
static BLEManagerImpl sInstance;
|
||||
|
||||
// ===== Private members reserved for use by this class only.
|
||||
|
||||
enum class Flags : uint16_t
|
||||
{
|
||||
kAsyncInitCompleted = 0x0001, /**< One-time asynchronous initialization actions have been performed. */
|
||||
kESPBLELayerInitialized = 0x0002, /**< The ESP BLE layer has been initialized. */
|
||||
kAppRegistered = 0x0004, /**< The CHIPoBLE application has been registered with the ESP BLE layer. */
|
||||
kAttrsRegistered = 0x0008, /**< The CHIPoBLE GATT attributes have been registered with the ESP BLE layer. */
|
||||
kGATTServiceStarted = 0x0010, /**< The CHIPoBLE GATT service has been started. */
|
||||
kAdvertisingConfigured = 0x0020, /**< CHIPoBLE advertising has been configured in the ESP BLE layer. */
|
||||
kAdvertising = 0x0040, /**< The system is currently CHIPoBLE advertising. */
|
||||
kControlOpInProgress = 0x0080, /**< An async control operation has been issued to the ESP BLE layer. */
|
||||
kAdvertisingEnabled = 0x0100, /**< The application has enabled CHIPoBLE advertising. */
|
||||
kFastAdvertisingEnabled = 0x0200, /**< The application has enabled fast advertising. */
|
||||
kUseCustomDeviceName = 0x0400, /**< The application has configured a custom BLE device name. */
|
||||
kAdvertisingRefreshNeeded = 0x0800, /**< The advertising configuration/state in ESP BLE layer needs to be updated. */
|
||||
kExtAdvertisingEnabled = 0x1000, /**< The application has enabled Extended BLE announcement. */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxConnections = BLE_LAYER_NUM_BLE_ENDPOINTS,
|
||||
kMaxDeviceNameLength = 16
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
BLEAdvConfig mBLEAdvConfig;
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#ifdef CONFIG_BT_NIMBLE_ENABLED
|
||||
uint16_t mSubscribedConIds[kMaxConnections];
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
|
||||
struct CHIPoBLEConState
|
||||
{
|
||||
System::PacketBufferHandle PendingIndBuf;
|
||||
uint16_t ConId;
|
||||
uint16_t MTU : 10;
|
||||
uint16_t Allocated : 1;
|
||||
uint16_t Subscribed : 1;
|
||||
uint16_t Unused : 4;
|
||||
|
||||
void Set(uint16_t conId)
|
||||
{
|
||||
PendingIndBuf = nullptr;
|
||||
ConId = conId;
|
||||
MTU = 0;
|
||||
Allocated = 1;
|
||||
Subscribed = 0;
|
||||
Unused = 0;
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
PendingIndBuf = nullptr;
|
||||
ConId = BLE_CONNECTION_UNINITIALIZED;
|
||||
MTU = 0;
|
||||
Allocated = 0;
|
||||
Subscribed = 0;
|
||||
Unused = 0;
|
||||
}
|
||||
};
|
||||
|
||||
CHIPoBLEConState mCons[kMaxConnections];
|
||||
CHIPoBLEServiceMode mServiceMode;
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
esp_gatt_if_t mAppIf;
|
||||
#elif defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
uint16_t mNumGAPCons;
|
||||
#endif // CONFIG_BT_BLUEDROID_ENABLED
|
||||
uint16_t mServiceAttrHandle;
|
||||
uint16_t mRXCharAttrHandle;
|
||||
uint16_t mTXCharAttrHandle;
|
||||
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
|
||||
uint16_t mC3CharAttrHandle;
|
||||
#endif
|
||||
uint16_t mTXCharCCCDAttrHandle;
|
||||
BitFlags<Flags> mFlags;
|
||||
char mDeviceName[kMaxDeviceNameLength + 1];
|
||||
CHIP_ERROR MapBLEError(int bleErr);
|
||||
|
||||
void DriveBLEState(void);
|
||||
CHIP_ERROR InitESPBleLayer(void);
|
||||
void DeinitESPBleLayer(void);
|
||||
CHIP_ERROR ConfigureAdvertisingData(void);
|
||||
CHIP_ERROR StartAdvertising(void);
|
||||
void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs);
|
||||
void CancelBleAdvTimeoutTimer(void);
|
||||
static void BleAdvTimeoutHandler(System::Layer *, void *);
|
||||
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
void HandleGATTControlEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
|
||||
void HandleGATTCommEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
|
||||
void HandleRXCharWrite(esp_ble_gatts_cb_param_t * param);
|
||||
void HandleTXCharRead(esp_ble_gatts_cb_param_t * param);
|
||||
void HandleTXCharCCCDRead(esp_ble_gatts_cb_param_t * param);
|
||||
void HandleTXCharCCCDWrite(esp_ble_gatts_cb_param_t * param);
|
||||
void HandleTXCharConfirm(CHIPoBLEConState * conState, esp_ble_gatts_cb_param_t * param);
|
||||
void HandleDisconnect(esp_ble_gatts_cb_param_t * param);
|
||||
CHIPoBLEConState * GetConnectionState(uint16_t conId, bool allocate = false);
|
||||
bool ReleaseConnectionState(uint16_t conId);
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
CHIP_ERROR HandleGAPConnect(esp_ble_gattc_cb_param_t p_data);
|
||||
CHIP_ERROR HandleGAPCentralConnect(esp_ble_gattc_cb_param_t p_data);
|
||||
|
||||
static void HandleConnectFailed(CHIP_ERROR error);
|
||||
static void ConnectDevice(esp_bd_addr_t & addr, esp_ble_addr_type_t addr_type, uint16_t timeout);
|
||||
void HandleGAPConnectionFailed();
|
||||
CHIP_ERROR HandleRXNotify(esp_ble_gattc_cb_param_t p_data);
|
||||
#endif
|
||||
static void HandleGATTEvent(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t * param);
|
||||
static void HandleGAPEvent(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t * param);
|
||||
|
||||
#elif defined(CONFIG_BT_NIMBLE_ENABLED)
|
||||
CHIP_ERROR DeinitBLE();
|
||||
static void ClaimBLEMemory(System::Layer *, void *);
|
||||
|
||||
void HandleRXCharRead(struct ble_gatt_char_context * param);
|
||||
void HandleRXCharWrite(struct ble_gatt_char_context * param);
|
||||
void HandleTXCharWrite(struct ble_gatt_char_context * param);
|
||||
void HandleTXCharRead(struct ble_gatt_char_context * param);
|
||||
void HandleTXCharCCCDRead(void * param);
|
||||
void HandleTXCharCCCDWrite(struct ble_gap_event * gapEvent);
|
||||
CHIP_ERROR HandleTXComplete(struct ble_gap_event * gapEvent);
|
||||
CHIP_ERROR HandleGAPConnect(struct ble_gap_event * gapEvent);
|
||||
CHIP_ERROR HandleGAPPeripheralConnect(struct ble_gap_event * gapEvent);
|
||||
CHIP_ERROR HandleGAPDisconnect(struct ble_gap_event * gapEvent);
|
||||
CHIP_ERROR SetSubscribed(uint16_t conId);
|
||||
bool UnsetSubscribed(uint16_t conId);
|
||||
bool IsSubscribed(uint16_t conId);
|
||||
static void ConnectDevice(const ble_addr_t & addr, uint16_t timeout);
|
||||
CHIP_ERROR HandleGAPCentralConnect(struct ble_gap_event * gapEvent);
|
||||
void HandleGAPConnectionFailed(struct ble_gap_event * gapEvent, CHIP_ERROR error);
|
||||
|
||||
static CHIP_ERROR bleprph_set_random_addr(void);
|
||||
static void bleprph_host_task(void * param);
|
||||
static void bleprph_on_sync(void);
|
||||
static void bleprph_on_reset(int);
|
||||
static const struct ble_gatt_svc_def CHIPoBLEGATTService;
|
||||
static int ble_svr_gap_event(struct ble_gap_event * event, void * arg);
|
||||
|
||||
static int gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg);
|
||||
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
|
||||
static int gatt_svr_chr_access_additional_data(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt,
|
||||
void * arg);
|
||||
void HandleC3CharRead(struct ble_gatt_char_context * param);
|
||||
#endif /* CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING */
|
||||
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
static int btshell_on_mtu(uint16_t conn_handle, const struct ble_gatt_error * error, uint16_t mtu, void * arg);
|
||||
|
||||
bool SubOrUnsubChar(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
|
||||
bool subscribe);
|
||||
|
||||
static void OnGattDiscComplete(const struct peer * peer, int status, void * arg);
|
||||
static void HandleConnectFailed(CHIP_ERROR error);
|
||||
CHIP_ERROR HandleRXNotify(struct ble_gap_event * event);
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
static void CancelConnect(void);
|
||||
static void HandleConnectTimeout(chip::System::Layer *, void * context);
|
||||
void InitiateScan(BleScanState scanType);
|
||||
static void InitiateScan(intptr_t arg);
|
||||
void HandleAdvertisementTimer(System::Layer * systemLayer, void * context);
|
||||
void HandleAdvertisementTimer();
|
||||
void CleanScanConfig();
|
||||
BLEScanConfig mBLEScanConfig;
|
||||
bool mIsCentral;
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
|
||||
static void DriveBLEState(intptr_t arg);
|
||||
|
||||
uint8_t mAdvData[MAX_ADV_DATA_LEN];
|
||||
uint16_t mAdvDataLen;
|
||||
static constexpr uint8_t kChipAdvInstance = 0;
|
||||
// Three GATT service
|
||||
// mGATTServices[0] is for Matter-over-BLE
|
||||
// mGATTServices[1] is for wifi_provisioning over BLE
|
||||
// mGATTServices[2] is NULL
|
||||
struct ble_gatt_svc_def mGATTServices[3];
|
||||
|
||||
// Secondary Advertisement
|
||||
static int secondary_ble_svr_gap_event(struct ble_gap_event * event, void * arg);
|
||||
CHIP_ERROR ConfigureSecondaryAdvertisingData(void);
|
||||
CHIP_ERROR StartSecondaryAdvertising(void);
|
||||
char mSecondaryAdvDeviceName[MAX_DEVICE_NAME_LEN + 1];
|
||||
size_t mSecondGATTServiceIndex = 1;
|
||||
ble_uuid128_t mSecondaryAdvUuid;
|
||||
bool mSecondaryBleBonding;
|
||||
bool mSecondaryBleSmSc;
|
||||
ble_hs_adv_fields mSecondaryAdvFields;
|
||||
ble_hs_adv_fields mSecondaryRespFields;
|
||||
uint8_t *mSecondaryMfgData;
|
||||
size_t mSecondaryMfgDataLen;
|
||||
BleGapEventHandler mSecondaryBleGapEventHandler = nullptr;
|
||||
static constexpr uint8_t kSecondaryAdvInstance = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a reference to the public interface of the BLEManager singleton object.
|
||||
*
|
||||
* Internal components should use this to access features of the BLEManager object
|
||||
* that are common to all platforms.
|
||||
*/
|
||||
inline BLEManager & BLEMgr(void)
|
||||
{
|
||||
return BLEManagerImpl::sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform-specific implementation of the BLEManager singleton object.
|
||||
*
|
||||
* Internal components can use this to gain access to features of the BLEManager
|
||||
* that are specific to the ESP32 platform.
|
||||
*/
|
||||
inline BLEManagerImpl & BLEMgrImpl(void)
|
||||
{
|
||||
return BLEManagerImpl::sInstance;
|
||||
}
|
||||
|
||||
inline ::chip::Ble::BleLayer * BLEManagerImpl::_GetBleLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
inline bool BLEManagerImpl::_IsAdvertisingEnabled(void)
|
||||
{
|
||||
return mFlags.Has(Flags::kAdvertisingEnabled);
|
||||
}
|
||||
|
||||
inline bool BLEManagerImpl::_IsAdvertising(void)
|
||||
{
|
||||
return mFlags.Has(Flags::kAdvertising);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace DeviceLayer
|
||||
} // namespace chip
|
||||
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
|
||||
@@ -0,0 +1,242 @@
|
||||
# Copyright (c) 2023 Project CHIP Authors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//build_overrides/chip.gni")
|
||||
|
||||
import("${chip_root}/build/chip/buildconfig_header.gni")
|
||||
import("${chip_root}/src/platform/device.gni")
|
||||
|
||||
declare_args() {
|
||||
# By default use default/example implementation of CommissionableDataProvider,
|
||||
# DeviceAttestationCredentialsProvider and DeviceInstanceInfoProvider
|
||||
chip_use_transitional_commissionable_data_provider = true
|
||||
chip_use_transitional_device_instance_info_provider = true
|
||||
chip_use_factory_data_provider = false
|
||||
chip_use_device_info_provider = false
|
||||
chip_config_software_version_number = 0
|
||||
chip_enable_chipoble = true
|
||||
chip_bt_nimble_enabled = true
|
||||
chip_bt_bluedroid_enabled = false
|
||||
chip_enable_ble_controller = false
|
||||
chip_use_secure_cert_dac_provider = false
|
||||
chip_use_esp32_ecdsa_peripheral = false
|
||||
chip_enable_ethernet = false
|
||||
chip_max_discovered_ip_addresses = 5
|
||||
chip_enable_route_hook = false
|
||||
}
|
||||
|
||||
buildconfig_header("custom_buildconfig") {
|
||||
header = "CHIPDeviceBuildConfig.h"
|
||||
header_dir = "platform"
|
||||
|
||||
defines = [
|
||||
"CHIP_DEVICE_CONFIG_ENABLE_WPA=false",
|
||||
"CHIP_ENABLE_OPENTHREAD=${chip_enable_openthread}",
|
||||
"CHIP_DEVICE_CONFIG_THREAD_FTD=${chip_openthread_ftd}",
|
||||
"OPENTHREAD_CONFIG_ENABLE_TOBLE=false",
|
||||
"CHIP_BYPASS_RENDEZVOUS=false",
|
||||
"CHIP_STACK_LOCK_TRACKING_ENABLED=true",
|
||||
"CHIP_STACK_LOCK_TRACKING_ERROR_FATAL=false",
|
||||
"CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING=false",
|
||||
"CHIP_DEVICE_CONFIG_RUN_AS_ROOT=false",
|
||||
"CHIP_DEVICE_LAYER_TARGET_ESP32=1",
|
||||
"CHIP_DEVICE_LAYER_TARGET=ESP32_custom",
|
||||
"CHIP_USE_TRANSITIONAL_COMMISSIONABLE_DATA_PROVIDER=${chip_use_transitional_commissionable_data_provider}",
|
||||
"CHIP_USE_TRANSITIONAL_DEVICE_INSTANCE_INFO_PROVIDER=${chip_use_transitional_device_instance_info_provider}",
|
||||
"BLE_PLATFORM_CONFIG_INCLUDE=<platform/ESP32_custom/BlePlatformConfig.h>",
|
||||
"CHIP_DEVICE_PLATFORM_CONFIG_INCLUDE=<platform/ESP32_custom/CHIPDevicePlatformConfig.h>",
|
||||
"CHIP_PLATFORM_CONFIG_INCLUDE=<platform/ESP32_custom/CHIPPlatformConfig.h>",
|
||||
"INET_CONFIG_INCLUDE=<platform/ESP32_custom/InetPlatformConfig.h>",
|
||||
"SYSTEM_PLATFORM_CONFIG_INCLUDE=<platform/ESP32_custom/SystemPlatformConfig.h>",
|
||||
"EXTERNAL_CONFIGURATIONMANAGERIMPL_HEADER=<platform/ESP32_custom/ConfigurationManagerImpl.h>",
|
||||
"EXTERNAL_CHIPDEVICEPLATFORMEVENT_HEADER=<platform/ESP32_custom/CHIPDevicePlatformEvent.h>",
|
||||
"EXTERNAL_CONNECTIVITYMANAGERIMPL_HEADER=<platform/ESP32_custom/ConnectivityManagerImpl.h>",
|
||||
"EXTERNAL_BLEMANAGERIMPL_HEADER=<platform/ESP32_custom/BLEManagerImpl.h>",
|
||||
"EXTERNAL_KEYVALUESTOREMANAGERIMPL_HEADER=<platform/ESP32_custom/KeyValueStoreManagerImpl.h>",
|
||||
"EXTERNAL_PLATFORMMANAGERIMPL_HEADER=<platform/ESP32_custom/PlatformManagerImpl.h>",
|
||||
"CHIP_CONFIG_SOFTWARE_VERSION_NUMBER=${chip_config_software_version_number}",
|
||||
"CHIP_DEVICE_CONFIG_MAX_DISCOVERED_IP_ADDRESSES=${chip_max_discovered_ip_addresses}",
|
||||
]
|
||||
|
||||
if (chip_enable_ota_requestor) {
|
||||
defines += [ "CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR=1" ]
|
||||
}
|
||||
}
|
||||
|
||||
group("platform_buildconfig") {
|
||||
public_deps = [ ":custom_buildconfig" ]
|
||||
}
|
||||
|
||||
static_library("ESP32_custom") {
|
||||
sources = [
|
||||
"${chip_root}/src/platform/SingletonConfigurationManager.cpp",
|
||||
"CHIPDevicePlatformConfig.h",
|
||||
"CHIPDevicePlatformEvent.h",
|
||||
"ConfigurationManagerImpl.cpp",
|
||||
"ConfigurationManagerImpl.h",
|
||||
"ConnectivityManagerImpl.cpp",
|
||||
"ConnectivityManagerImpl.h",
|
||||
"DiagnosticDataProviderImpl.cpp",
|
||||
"DiagnosticDataProviderImpl.h",
|
||||
"ESP32Config.cpp",
|
||||
"ESP32Config.h",
|
||||
"ESP32Utils.cpp",
|
||||
"ESP32Utils.h",
|
||||
"KeyValueStoreManagerImpl.cpp",
|
||||
"KeyValueStoreManagerImpl.h",
|
||||
"Logging.cpp",
|
||||
"LwIPCoreLock.cpp",
|
||||
"PlatformManagerImpl.cpp",
|
||||
"PlatformManagerImpl.h",
|
||||
"SystemTimeSupport.cpp",
|
||||
"SystemTimeSupport.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"${chip_root}/src/lib/dnssd:platform_header",
|
||||
"${chip_root}/src/platform/logging:headers",
|
||||
"${chip_root}/src/setup_payload",
|
||||
]
|
||||
|
||||
public = [
|
||||
"${chip_root}/src/credentials/CHIPCert.h",
|
||||
"${chip_root}/src/credentials/DeviceAttestationCredsProvider.h",
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":platform_buildconfig",
|
||||
"${chip_root}/src/crypto",
|
||||
"${chip_root}/src/platform:platform_base",
|
||||
]
|
||||
|
||||
if (chip_enable_ota_requestor) {
|
||||
sources += [
|
||||
"OTAImageProcessorImpl.cpp",
|
||||
"OTAImageProcessorImpl.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (chip_enable_chipoble) {
|
||||
sources += [
|
||||
"BLEManagerImpl.h",
|
||||
"ChipDeviceScanner.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (chip_enable_ble_controller) {
|
||||
sources += [ "ChipDeviceScanner.h" ]
|
||||
}
|
||||
|
||||
if (chip_bt_nimble_enabled) {
|
||||
sources += [ "nimble/BLEManagerImpl.cpp" ]
|
||||
if (chip_enable_ble_controller) {
|
||||
sources += [
|
||||
"nimble/ChipDeviceScanner.cpp",
|
||||
"nimble/blecent.h",
|
||||
"nimble/misc.c",
|
||||
"nimble/peer.c",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (chip_bt_bluedroid_enabled) {
|
||||
sources += [ "bluedroid/BLEManagerImpl.cpp" ]
|
||||
if (chip_enable_ble_controller) {
|
||||
sources += [ "bluedroid/ChipDeviceScanner.cpp" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (chip_enable_wifi) {
|
||||
sources += [
|
||||
"ConnectivityManagerImpl_WiFi.cpp",
|
||||
"NetworkCommissioningDriver.cpp",
|
||||
"NetworkCommissioningDriver.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (chip_mdns == "platform") {
|
||||
sources += [ "DnssdImpl.cpp" ]
|
||||
}
|
||||
|
||||
if (chip_enable_ethernet) {
|
||||
sources += [
|
||||
"ConnectivityManagerImpl_Ethernet.cpp",
|
||||
"NetworkCommissioningDriver_Ethernet.cpp",
|
||||
]
|
||||
}
|
||||
|
||||
if (chip_enable_ethernet || chip_enable_wifi) {
|
||||
if (chip_mdns == "platform") {
|
||||
sources += [
|
||||
"ESP32DnssdImpl.cpp",
|
||||
"ESP32DnssdImpl.h",
|
||||
]
|
||||
}
|
||||
if (chip_mdns == "minimal") {
|
||||
sources += [ "ESP32EndpointQueueFilter.h" ]
|
||||
}
|
||||
if (chip_enable_route_hook) {
|
||||
sources += [
|
||||
"route_hook/ESP32RouteHook.c",
|
||||
"route_hook/ESP32RouteHook.h",
|
||||
"route_hook/ESP32RouteTable.c",
|
||||
"route_hook/ESP32RouteTable.h",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (chip_enable_openthread) {
|
||||
sources += [
|
||||
"../OpenThread/GenericNetworkCommissioningThreadDriver.cpp",
|
||||
"../OpenThread/GenericNetworkCommissioningThreadDriver.h",
|
||||
"../OpenThread/OpenThreadUtils.cpp",
|
||||
"OpenthreadLauncher.cpp",
|
||||
"OpenthreadLauncher.h",
|
||||
"ThreadStackManagerImpl.cpp",
|
||||
"ThreadStackManagerImpl.h",
|
||||
]
|
||||
if (chip_mdns == "platform") {
|
||||
sources += [
|
||||
"../OpenThread/OpenThreadDnssdImpl.cpp",
|
||||
"../OpenThread/OpenThreadDnssdImpl.h",
|
||||
]
|
||||
}
|
||||
configs -= [ "${chip_root}/build/config/compiler:warnings_default" ]
|
||||
}
|
||||
|
||||
if (chip_use_factory_data_provider) {
|
||||
sources += [
|
||||
"ESP32FactoryDataProvider.cpp",
|
||||
"ESP32FactoryDataProvider.h",
|
||||
"StaticESP32DeviceInfoProvider.cpp",
|
||||
"StaticESP32DeviceInfoProvider.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (chip_use_secure_cert_dac_provider) {
|
||||
sources += [
|
||||
"ESP32SecureCertDACProvider.cpp",
|
||||
"ESP32SecureCertDACProvider.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (chip_use_device_info_provider) {
|
||||
sources += [
|
||||
"ESP32DeviceInfoProvider.cpp",
|
||||
"ESP32DeviceInfoProvider.h",
|
||||
]
|
||||
}
|
||||
|
||||
cflags = [ "-Wconversion" ]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/BlePlatformConfig.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/CHIPDevicePlatformConfig.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/CHIPDevicePlatformEvent.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/CHIPPlatformConfig.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ChipDeviceScanner.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ConfigurationManagerImpl.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ConfigurationManagerImpl.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ConnectivityManagerImpl.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ConnectivityManagerImpl.h
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ConnectivityManagerImpl_Ethernet.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ConnectivityManagerImpl_WiFi.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/DiagnosticDataProviderImpl.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/DiagnosticDataProviderImpl.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/DnssdImpl.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32CHIPCryptoPAL.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32CHIPCryptoPAL.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32Config.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32Config.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32DeviceInfoProvider.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32DeviceInfoProvider.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32DnssdImpl.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32DnssdImpl.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32EndpointQueueFilter.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32FactoryDataProvider.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32FactoryDataProvider.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32SecureCertDACProvider.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32SecureCertDACProvider.h
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2020 Project CHIP Authors
|
||||
* Copyright (c) 2018 Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* General utility methods for the ESP32 platform.
|
||||
*/
|
||||
/* this file behaves like a config.h, comes first */
|
||||
#include <platform/internal/CHIPDeviceLayerInternal.h>
|
||||
|
||||
#include <lib/core/ErrorStr.h>
|
||||
#include <lib/support/CodeUtils.h>
|
||||
#include <lib/support/logging/CHIPLogging.h>
|
||||
#include <platform/ESP32/ESP32Utils.h>
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_netif_net_stack.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs.h"
|
||||
|
||||
using namespace ::chip::DeviceLayer::Internal;
|
||||
using chip::DeviceLayer::Internal::DeviceNetworkInfo;
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
CHIP_ERROR ESP32Utils::IsAPEnabled(bool & apEnabled)
|
||||
{
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
wifi_mode_t curWiFiMode;
|
||||
|
||||
esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
apEnabled = (curWiFiMode == WIFI_MODE_AP || curWiFiMode == WIFI_MODE_APSTA);
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
#else
|
||||
return CHIP_ERROR_NOT_IMPLEMENTED;
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::IsStationEnabled(bool & staEnabled)
|
||||
{
|
||||
wifi_mode_t curWiFiMode;
|
||||
esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
staEnabled = (curWiFiMode == WIFI_MODE_STA || curWiFiMode == WIFI_MODE_APSTA);
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
bool ESP32Utils::IsStationProvisioned(void)
|
||||
{
|
||||
wifi_config_t stationConfig;
|
||||
return (esp_wifi_get_config(WIFI_IF_STA, &stationConfig) == ERR_OK && stationConfig.sta.ssid[0] != 0);
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::IsStationConnected(bool & connected)
|
||||
{
|
||||
wifi_ap_record_t apInfo;
|
||||
connected = (esp_wifi_sta_get_ap_info(&apInfo) == ESP_OK && apInfo.ssid[0] != 0);
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::StartWiFiLayer(void)
|
||||
{
|
||||
int8_t ignored;
|
||||
bool wifiStarted;
|
||||
|
||||
// There appears to be no direct way to ask the ESP WiFi layer if esp_wifi_start()
|
||||
// has been called. So use the ESP_ERR_WIFI_NOT_STARTED error returned by
|
||||
// esp_wifi_get_max_tx_power() to detect this.
|
||||
esp_err_t err = esp_wifi_get_max_tx_power(&ignored);
|
||||
switch (err)
|
||||
{
|
||||
case ESP_OK:
|
||||
wifiStarted = true;
|
||||
break;
|
||||
case ESP_ERR_WIFI_NOT_STARTED:
|
||||
wifiStarted = false;
|
||||
break;
|
||||
default:
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
if (!wifiStarted)
|
||||
{
|
||||
ChipLogProgress(DeviceLayer, "Starting ESP WiFi layer");
|
||||
|
||||
err = esp_wifi_start();
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_start() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
}
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::EnableStationMode(void)
|
||||
{
|
||||
wifi_mode_t curWiFiMode;
|
||||
|
||||
// Get the current ESP WiFI mode.
|
||||
esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
// If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change
|
||||
// the mode to WIFI_MODE_APSTA.
|
||||
if (curWiFiMode == WIFI_MODE_AP)
|
||||
{
|
||||
ChipLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(WIFI_MODE_AP),
|
||||
WiFiModeToStr(WIFI_MODE_APSTA));
|
||||
|
||||
err = esp_wifi_set_mode(WIFI_MODE_APSTA);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
}
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::SetAPMode(bool enabled)
|
||||
{
|
||||
wifi_mode_t curWiFiMode;
|
||||
wifi_mode_t targetWiFiMode = WIFI_MODE_STA;
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
targetWiFiMode = (enabled) ? WIFI_MODE_APSTA : WIFI_MODE_STA;
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
|
||||
// Get the current ESP WiFI mode.
|
||||
esp_err_t err = esp_wifi_get_mode(&curWiFiMode);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_get_mode() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
// If station mode is not already enabled (implying the current mode is WIFI_MODE_AP), change
|
||||
// the mode to WIFI_MODE_APSTA.
|
||||
if (curWiFiMode != targetWiFiMode)
|
||||
{
|
||||
ChipLogProgress(DeviceLayer, "Changing ESP WiFi mode: %s -> %s", WiFiModeToStr(curWiFiMode), WiFiModeToStr(targetWiFiMode));
|
||||
|
||||
err = esp_wifi_set_mode(targetWiFiMode);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_set_mode() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
}
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
int ESP32Utils::OrderScanResultsByRSSI(const void * _res1, const void * _res2)
|
||||
{
|
||||
const wifi_ap_record_t * res1 = (const wifi_ap_record_t *) _res1;
|
||||
const wifi_ap_record_t * res2 = (const wifi_ap_record_t *) _res2;
|
||||
|
||||
if (res1->rssi > res2->rssi)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (res1->rssi < res2->rssi)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char * ESP32Utils::WiFiModeToStr(wifi_mode_t wifiMode)
|
||||
{
|
||||
switch (wifiMode)
|
||||
{
|
||||
case WIFI_MODE_NULL:
|
||||
return "NULL";
|
||||
case WIFI_MODE_STA:
|
||||
return "STA";
|
||||
case WIFI_MODE_AP:
|
||||
return "AP";
|
||||
case WIFI_MODE_APSTA:
|
||||
return "STA+AP";
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
struct netif * ESP32Utils::GetStationNetif(void)
|
||||
{
|
||||
return GetNetif(kDefaultWiFiStationNetifKey);
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::GetWiFiStationProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials)
|
||||
{
|
||||
wifi_config_t stationConfig;
|
||||
|
||||
esp_err_t err = esp_wifi_get_config(WIFI_IF_STA, &stationConfig);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
VerifyOrReturnError(stationConfig.sta.ssid[0] != 0, CHIP_ERROR_INCORRECT_STATE);
|
||||
|
||||
netInfo.NetworkId = kWiFiStationNetworkId;
|
||||
netInfo.FieldPresent.NetworkId = true;
|
||||
memcpy(netInfo.WiFiSSID, stationConfig.sta.ssid,
|
||||
min(strlen(reinterpret_cast<char *>(stationConfig.sta.ssid)) + 1, sizeof(netInfo.WiFiSSID)));
|
||||
|
||||
// Enforce that netInfo wifiSSID is null terminated
|
||||
netInfo.WiFiSSID[kMaxWiFiSSIDLength] = '\0';
|
||||
|
||||
if (includeCredentials)
|
||||
{
|
||||
static_assert(sizeof(netInfo.WiFiKey) < 255, "Our min might not fit in netInfo.WiFiKeyLen");
|
||||
netInfo.WiFiKeyLen = static_cast<uint8_t>(min(strlen((char *) stationConfig.sta.password), sizeof(netInfo.WiFiKey)));
|
||||
memcpy(netInfo.WiFiKey, stationConfig.sta.password, netInfo.WiFiKeyLen);
|
||||
}
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::SetWiFiStationProvision(const Internal::DeviceNetworkInfo & netInfo)
|
||||
{
|
||||
wifi_config_t wifiConfig;
|
||||
|
||||
char wifiSSID[kMaxWiFiSSIDLength + 1];
|
||||
size_t netInfoSSIDLen = strlen(netInfo.WiFiSSID);
|
||||
|
||||
// Ensure that ESP station mode is enabled. This is required before esp_wifi_set_config(ESP_IF_WIFI_STA,...)
|
||||
// can be called.
|
||||
ReturnErrorOnFailure(ESP32Utils::EnableStationMode());
|
||||
|
||||
// Enforce that wifiSSID is null terminated before copying it
|
||||
memcpy(wifiSSID, netInfo.WiFiSSID, min(netInfoSSIDLen + 1, sizeof(wifiSSID)));
|
||||
if (netInfoSSIDLen + 1 < sizeof(wifiSSID))
|
||||
{
|
||||
wifiSSID[netInfoSSIDLen] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
wifiSSID[kMaxWiFiSSIDLength] = '\0';
|
||||
}
|
||||
|
||||
// Initialize an ESP wifi_config_t structure based on the new provision information.
|
||||
memset(&wifiConfig, 0, sizeof(wifiConfig));
|
||||
memcpy(wifiConfig.sta.ssid, wifiSSID, min(strlen(wifiSSID) + 1, sizeof(wifiConfig.sta.ssid)));
|
||||
memcpy(wifiConfig.sta.password, netInfo.WiFiKey, min((size_t) netInfo.WiFiKeyLen, sizeof(wifiConfig.sta.password)));
|
||||
wifiConfig.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
|
||||
wifiConfig.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;
|
||||
|
||||
// Configure the ESP WiFi interface.
|
||||
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifiConfig);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "esp_wifi_set_config() failed: %s", esp_err_to_name(err));
|
||||
return ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
ChipLogProgress(DeviceLayer, "WiFi station provision set (SSID: %s)", netInfo.WiFiSSID);
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::ClearWiFiStationProvision(void)
|
||||
{
|
||||
wifi_config_t stationConfig;
|
||||
|
||||
// Clear the ESP WiFi station configuration.
|
||||
memset(&stationConfig, 0, sizeof(stationConfig));
|
||||
esp_wifi_set_config(WIFI_IF_STA, &stationConfig);
|
||||
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::InitWiFiStack(void)
|
||||
{
|
||||
// Intentionally make this function empty so that we can setup wifi stack in the example
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
|
||||
struct netif * ESP32Utils::GetNetif(const char * ifKey)
|
||||
{
|
||||
struct netif * netif = NULL;
|
||||
esp_netif_t * netif_handle = NULL;
|
||||
netif_handle = esp_netif_get_handle_from_ifkey(ifKey);
|
||||
netif = (struct netif *) esp_netif_get_netif_impl(netif_handle);
|
||||
return netif;
|
||||
}
|
||||
|
||||
bool ESP32Utils::IsInterfaceUp(const char * ifKey)
|
||||
{
|
||||
struct netif * netif = GetNetif(ifKey);
|
||||
return netif != NULL && netif_is_up(netif);
|
||||
}
|
||||
|
||||
bool ESP32Utils::HasIPv6LinkLocalAddress(const char * ifKey)
|
||||
{
|
||||
struct esp_ip6_addr if_ip6_unused;
|
||||
return esp_netif_get_ip6_linklocal(esp_netif_get_handle_from_ifkey(ifKey), &if_ip6_unused) == ESP_OK;
|
||||
}
|
||||
|
||||
CHIP_ERROR ESP32Utils::MapError(esp_err_t error)
|
||||
{
|
||||
if (error == ESP_OK)
|
||||
{
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
if (error == ESP_ERR_NVS_NOT_FOUND)
|
||||
{
|
||||
return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
|
||||
}
|
||||
if (error == ESP_ERR_NVS_INVALID_LENGTH)
|
||||
{
|
||||
return CHIP_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
return CHIP_ERROR(ChipError::Range::kPlatform, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a CHIP error value that represents an ESP32 error, returns a
|
||||
* human-readable NULL-terminated C string describing the error.
|
||||
*
|
||||
* @param[in] buf Buffer into which the error string will be placed.
|
||||
* @param[in] bufSize Size of the supplied buffer in bytes.
|
||||
* @param[in] err The error to be described.
|
||||
*
|
||||
* @return true If a description string was written into the supplied buffer.
|
||||
* @return false If the supplied error was not an ESP32 error.
|
||||
*
|
||||
*/
|
||||
bool ESP32Utils::FormatError(char * buf, uint16_t bufSize, CHIP_ERROR err)
|
||||
{
|
||||
if (!err.IsRange(ChipError::Range::kPlatform))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if CHIP_CONFIG_SHORT_ERROR_STR
|
||||
const char * desc = NULL;
|
||||
#else // CHIP_CONFIG_SHORT_ERROR_STR
|
||||
const char * desc = esp_err_to_name((esp_err_t) err.GetValue());
|
||||
#endif // CHIP_CONFIG_SHORT_ERROR_STR
|
||||
|
||||
chip::FormatError(buf, bufSize, "ESP32", err, desc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a text error formatter for ESP32 errors.
|
||||
*/
|
||||
void ESP32Utils::RegisterESP32ErrorFormatter()
|
||||
{
|
||||
static ErrorFormatter sErrorFormatter = { ESP32Utils::FormatError, NULL };
|
||||
|
||||
RegisterErrorFormatter(&sErrorFormatter);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ESP32Utils.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/InetPlatformConfig.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/KeyValueStoreManagerImpl.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/KeyValueStoreManagerImpl.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/Logging.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/LwIPCoreLock.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/NetworkCommissioningDriver.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/NetworkCommissioningDriver.h
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/NetworkCommissioningDriver_Ethernet.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/OTAImageProcessorImpl.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/OTAImageProcessorImpl.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/OpenthreadLauncher.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/OpenthreadLauncher.h
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2020 Project CHIP Authors
|
||||
* Copyright (c) 2018 Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides an implementation of the PlatformManager object
|
||||
* for the ESP32 platform.
|
||||
*/
|
||||
/* this file behaves like a config.h, comes first */
|
||||
#include <platform/internal/CHIPDeviceLayerInternal.h>
|
||||
|
||||
#include <crypto/CHIPCryptoPAL.h>
|
||||
#include <platform/ESP32/DiagnosticDataProviderImpl.h>
|
||||
#include <platform/ESP32/ESP32Utils.h>
|
||||
#include <platform/ESP32/SystemTimeSupport.h>
|
||||
#include <platform/PlatformManager.h>
|
||||
#include <platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp>
|
||||
|
||||
#include "esp_event.h"
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_netif.h"
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
#include "spi_flash_mmap.h"
|
||||
#else
|
||||
#include "esp_spi_flash.h"
|
||||
#endif
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
namespace chip {
|
||||
namespace DeviceLayer {
|
||||
|
||||
namespace Internal {
|
||||
extern CHIP_ERROR InitLwIPCoreLock();
|
||||
}
|
||||
|
||||
PlatformManagerImpl PlatformManagerImpl::sInstance;
|
||||
|
||||
static int app_entropy_source(void * data, unsigned char * output, size_t len, size_t * olen)
|
||||
{
|
||||
esp_fill_random(output, len);
|
||||
*olen = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CHIP_ERROR PlatformManagerImpl::DisableESPEventDispatch()
|
||||
{
|
||||
esp_err_t err = esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent);
|
||||
if (err != ESP_OK)
|
||||
{
|
||||
return Internal::ESP32Utils::MapError(err);
|
||||
}
|
||||
err = esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent);
|
||||
return Internal::ESP32Utils::MapError(err);
|
||||
}
|
||||
|
||||
CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
|
||||
{
|
||||
// Arrange for CHIP-encapsulated ESP32 errors to be translated to text
|
||||
Internal::ESP32Utils::RegisterESP32ErrorFormatter();
|
||||
// Make sure the LwIP core lock has been initialized
|
||||
ReturnErrorOnFailure(Internal::InitLwIPCoreLock());
|
||||
|
||||
// Initialize TCP/IP network interface, which internally initializes LwIP stack. We have to
|
||||
// call this before the usage of PacketBufferHandle::New() because in case of LwIP-based pool
|
||||
// allocator, the LwIP pool allocator uses the LwIP stack.
|
||||
esp_err_t err = esp_netif_init();
|
||||
VerifyOrReturnError(err == ESP_OK, Internal::ESP32Utils::MapError(err));
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent, nullptr);
|
||||
VerifyOrReturnError(err == ESP_OK, Internal::ESP32Utils::MapError(err));
|
||||
#endif
|
||||
// Arrange for the ESP event loop to deliver events into the CHIP Device layer.
|
||||
err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent, nullptr);
|
||||
VerifyOrReturnError(err == ESP_OK, Internal::ESP32Utils::MapError(err));
|
||||
|
||||
mStartTime = System::SystemClock().GetMonotonicTimestamp();
|
||||
ReturnErrorOnFailure(chip::Crypto::add_entropy_source(app_entropy_source, nullptr, 16));
|
||||
|
||||
// Call _InitChipStack() on the generic implementation base class
|
||||
// to finish the initialization process.
|
||||
ReturnErrorOnFailure(Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_InitChipStack());
|
||||
|
||||
ReturnErrorOnFailure(System::Clock::InitClock_RealTime());
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
|
||||
void PlatformManagerImpl::_Shutdown()
|
||||
{
|
||||
uint64_t upTime = 0;
|
||||
|
||||
if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR)
|
||||
{
|
||||
uint32_t totalOperationalHours = 0;
|
||||
|
||||
if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR)
|
||||
{
|
||||
ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast<uint32_t>(upTime / 3600));
|
||||
}
|
||||
else
|
||||
{
|
||||
ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot");
|
||||
}
|
||||
|
||||
Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_Shutdown();
|
||||
|
||||
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent);
|
||||
esp_netif_deinit();
|
||||
}
|
||||
|
||||
void PlatformManagerImpl::HandleESPSystemEvent(void * arg, esp_event_base_t eventBase, int32_t eventId, void * eventData)
|
||||
{
|
||||
ChipDeviceEvent event;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.Type = DeviceEventType::kESPSystemEvent;
|
||||
event.Platform.ESPSystemEvent.Base = eventBase;
|
||||
event.Platform.ESPSystemEvent.Id = eventId;
|
||||
if (eventBase == IP_EVENT)
|
||||
{
|
||||
ChipLogProgress(DeviceLayer, "Posting ESPSystemEvent: IP Event with eventId : %ld", eventId);
|
||||
switch (eventId)
|
||||
{
|
||||
case IP_EVENT_STA_GOT_IP:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.IpGotIp, eventData, sizeof(event.Platform.ESPSystemEvent.Data.IpGotIp));
|
||||
break;
|
||||
case IP_EVENT_GOT_IP6:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.IpGotIp6, eventData, sizeof(event.Platform.ESPSystemEvent.Data.IpGotIp6));
|
||||
break;
|
||||
case IP_EVENT_AP_STAIPASSIGNED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.IpApStaIpAssigned, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.IpApStaIpAssigned));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
else if (eventBase == WIFI_EVENT)
|
||||
{
|
||||
ChipLogProgress(DeviceLayer, "Posting ESPSystemEvent: Wifi Event with eventId : %ld", eventId);
|
||||
switch (eventId)
|
||||
{
|
||||
case WIFI_EVENT_SCAN_DONE:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiStaScanDone, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiStaScanDone));
|
||||
break;
|
||||
case WIFI_EVENT_STA_CONNECTED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiStaConnected, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiStaConnected));
|
||||
break;
|
||||
case WIFI_EVENT_STA_DISCONNECTED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiStaDisconnected, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiStaDisconnected));
|
||||
break;
|
||||
case WIFI_EVENT_STA_AUTHMODE_CHANGE:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiStaAuthModeChange, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiStaAuthModeChange));
|
||||
break;
|
||||
case WIFI_EVENT_STA_WPS_ER_PIN:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiStaWpsErPin, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiStaWpsErPin));
|
||||
break;
|
||||
case WIFI_EVENT_STA_WPS_ER_FAILED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiStaWpsErFailed, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiStaWpsErFailed));
|
||||
break;
|
||||
case WIFI_EVENT_AP_STACONNECTED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiApStaConnected, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiApStaConnected));
|
||||
break;
|
||||
case WIFI_EVENT_AP_STADISCONNECTED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiApStaDisconnected, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiApStaDisconnected));
|
||||
break;
|
||||
case WIFI_EVENT_AP_PROBEREQRECVED:
|
||||
memcpy(&event.Platform.ESPSystemEvent.Data.WiFiApProbeReqRecved, eventData,
|
||||
sizeof(event.Platform.ESPSystemEvent.Data.WiFiApProbeReqRecved));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
else
|
||||
{
|
||||
ChipLogProgress(DeviceLayer, "Posting ESPSystemEvent with eventId : %ld", eventId);
|
||||
}
|
||||
sInstance.PostEventOrDie(&event);
|
||||
}
|
||||
|
||||
} // namespace DeviceLayer
|
||||
} // namespace chip
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) 2020 Project CHIP Authors
|
||||
* Copyright (c) 2018 Nest Labs, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides an implementation of the PlatformManager object
|
||||
* for the ESP32 platform.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <platform/internal/GenericPlatformManagerImpl_FreeRTOS.h>
|
||||
#include <system/SystemClock.h>
|
||||
|
||||
namespace chip {
|
||||
namespace DeviceLayer {
|
||||
|
||||
/**
|
||||
* Concrete implementation of the PlatformManager singleton object for the ESP32 platform.
|
||||
*/
|
||||
class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>
|
||||
{
|
||||
// Allow the PlatformManager interface class to delegate method calls to
|
||||
// the implementation methods provided by this class.
|
||||
friend PlatformManager;
|
||||
|
||||
// Allow the generic implementation base class to call helper methods on
|
||||
// this class.
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
friend Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// ===== Platform-specific members that may be accessed directly by the application.
|
||||
|
||||
CHIP_ERROR InitLwIPCoreLock(void);
|
||||
static void HandleESPSystemEvent(void * arg, esp_event_base_t eventBase, int32_t eventId, void * eventData);
|
||||
System::Clock::Timestamp GetStartTime() { return mStartTime; }
|
||||
static CHIP_ERROR DisableESPEventDispatch();
|
||||
|
||||
private:
|
||||
// ===== Methods that implement the PlatformManager abstract interface.
|
||||
|
||||
CHIP_ERROR _InitChipStack(void);
|
||||
void _Shutdown();
|
||||
|
||||
// ===== Members for internal use by the following friends.
|
||||
|
||||
friend PlatformManager & PlatformMgr(void);
|
||||
friend PlatformManagerImpl & PlatformMgrImpl(void);
|
||||
|
||||
System::Clock::Timestamp mStartTime = System::Clock::kZero;
|
||||
|
||||
static PlatformManagerImpl sInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the public interface of the PlatformManager singleton object.
|
||||
*
|
||||
* Chip applications should use this to access features of the PlatformManager object
|
||||
* that are common to all platforms.
|
||||
*/
|
||||
inline PlatformManager & PlatformMgr(void)
|
||||
{
|
||||
return PlatformManagerImpl::sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform-specific implementation of the PlatformManager singleton object.
|
||||
*
|
||||
* Chip applications can use this to gain access to features of the PlatformManager
|
||||
* that are specific to the ESP32 platform.
|
||||
*/
|
||||
inline PlatformManagerImpl & PlatformMgrImpl(void)
|
||||
{
|
||||
return PlatformManagerImpl::sInstance;
|
||||
}
|
||||
|
||||
} // namespace DeviceLayer
|
||||
} // namespace chip
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ScopedNvsHandle.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/StaticESP32DeviceInfoProvider.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/StaticESP32DeviceInfoProvider.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/SystemPlatformConfig.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/SystemTimeSupport.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/SystemTimeSupport.h
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ThreadStackManagerImpl.cpp
|
||||
+1
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/ThreadStackManagerImpl.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/WarmPlatformConfig.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/bluedroid
|
||||
File diff suppressed because it is too large
Load Diff
+1
@@ -0,0 +1 @@
|
||||
../../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/nimble/ChipDeviceScanner.cpp
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/nimble/blecent.h
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/nimble/misc.c
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/nimble/peer.c
|
||||
@@ -0,0 +1,639 @@
|
||||
diff --git a/src/platform/ESP32/BLEManagerImpl.h b/src/platform/ESP32/BLEManagerImpl.h
|
||||
index eeed125012..e5480505c5 100644
|
||||
--- a/src/platform/ESP32/BLEManagerImpl.h
|
||||
+++ b/src/platform/ESP32/BLEManagerImpl.h
|
||||
@@ -61,6 +61,9 @@ struct ble_gatt_char_context
|
||||
void * arg;
|
||||
};
|
||||
|
||||
+#define MAX_ADV_DATA_LEN 31
|
||||
+#define MAX_DEVICE_NAME_LEN 29
|
||||
+
|
||||
#endif // CONFIG_BT_BLUEDROID_ENABLED
|
||||
|
||||
#include <ble/Ble.h>
|
||||
@@ -144,6 +147,45 @@ public:
|
||||
CHIP_ERROR ConfigureScanResponseData(ByteSpan data);
|
||||
void ClearScanResponseData(void);
|
||||
|
||||
+ CHIP_ERROR SetSecondaryGATTService(struct ble_gatt_svc_def *gatt_svc, size_t gattSvcIndex)
|
||||
+ {
|
||||
+ if (!gatt_svc || gattSvcIndex > 1)
|
||||
+ {
|
||||
+ return CHIP_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ mSecondGATTServiceIndex = gattSvcIndex;
|
||||
+ memcpy(&mGATTServices[gattSvcIndex], gatt_svc, sizeof(struct ble_gatt_svc_def));
|
||||
+ return CHIP_NO_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ using BleGapEventHandler = int(*)(struct ble_gap_event * event, void * arg);
|
||||
+
|
||||
+ void SetSecondaryAdvGapEventHandler(BleGapEventHandler handler) { mSecondaryBleGapEventHandler = handler; }
|
||||
+
|
||||
+ CHIP_ERROR SetSecondaryAdvDeviceName(const char *deviceName)
|
||||
+ {
|
||||
+ strncpy(mSecondaryAdvDeviceName, deviceName, MAX_DEVICE_NAME_LEN);
|
||||
+ mSecondaryAdvDeviceName[MAX_DEVICE_NAME_LEN] = 0;
|
||||
+ return CHIP_NO_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ CHIP_ERROR SetSecondaryAdvUuid(const ByteSpan &uuid)
|
||||
+ {
|
||||
+ if (uuid.size() != 16)
|
||||
+ {
|
||||
+ return CHIP_ERROR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ mSecondaryAdvUuid.u.type = BLE_UUID_TYPE_128;
|
||||
+ memcpy(mSecondaryAdvUuid.value, uuid.data(), uuid.size());
|
||||
+ return CHIP_NO_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ void SetSecondaryBleSmConfig(bool bleBonding, bool bleSmSc)
|
||||
+ {
|
||||
+ mSecondaryBleBonding = bleBonding;
|
||||
+ mSecondaryBleSmSc = bleSmSc;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
chip::Optional<chip::ByteSpan> mScanResponse;
|
||||
|
||||
@@ -346,7 +388,7 @@ private:
|
||||
static void bleprph_host_task(void * param);
|
||||
static void bleprph_on_sync(void);
|
||||
static void bleprph_on_reset(int);
|
||||
- static const struct ble_gatt_svc_def CHIPoBLEGATTAttrs[];
|
||||
+ static const struct ble_gatt_svc_def CHIPoBLEGATTService;
|
||||
static int ble_svr_gap_event(struct ble_gap_event * event, void * arg);
|
||||
|
||||
static int gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt * ctxt, void * arg);
|
||||
@@ -380,6 +422,31 @@ private:
|
||||
#endif // CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
|
||||
static void DriveBLEState(intptr_t arg);
|
||||
+
|
||||
+ uint8_t mAdvData[MAX_ADV_DATA_LEN];
|
||||
+ uint16_t mAdvDataLen;
|
||||
+ static constexpr uint8_t kChipAdvInstance = 0;
|
||||
+ // Three GATT service
|
||||
+ // mGATTServices[0] is for Matter-over-BLE
|
||||
+ // mGATTServices[1] is for wifi_provisioning over BLE
|
||||
+ // mGATTServices[2] is NULL
|
||||
+ struct ble_gatt_svc_def mGATTServices[3];
|
||||
+
|
||||
+ // Secondary Advertisement
|
||||
+ static int secondary_ble_svr_gap_event(struct ble_gap_event * event, void * arg);
|
||||
+ CHIP_ERROR ConfigureSecondaryAdvertisingData(void);
|
||||
+ CHIP_ERROR StartSecondaryAdvertising(void);
|
||||
+ char mSecondaryAdvDeviceName[MAX_DEVICE_NAME_LEN + 1];
|
||||
+ size_t mSecondGATTServiceIndex = 1;
|
||||
+ ble_uuid128_t mSecondaryAdvUuid;
|
||||
+ bool mSecondaryBleBonding;
|
||||
+ bool mSecondaryBleSmSc;
|
||||
+ ble_hs_adv_fields mSecondaryAdvFields;
|
||||
+ ble_hs_adv_fields mSecondaryRespFields;
|
||||
+ uint8_t *mSecondaryMfgData;
|
||||
+ size_t mSecondaryMfgDataLen;
|
||||
+ BleGapEventHandler mSecondaryBleGapEventHandler = nullptr;
|
||||
+ static constexpr uint8_t kSecondaryAdvInstance = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
diff --git a/src/platform/ESP32/ESP32Utils.cpp b/src/platform/ESP32/ESP32Utils.cpp
|
||||
index ffa45ee722..7a7fcad299 100644
|
||||
--- a/src/platform/ESP32/ESP32Utils.cpp
|
||||
+++ b/src/platform/ESP32/ESP32Utils.cpp
|
||||
@@ -311,62 +311,7 @@ CHIP_ERROR ESP32Utils::ClearWiFiStationProvision(void)
|
||||
|
||||
CHIP_ERROR ESP32Utils::InitWiFiStack(void)
|
||||
{
|
||||
- wifi_init_config_t cfg;
|
||||
- uint8_t ap_mac[6];
|
||||
- wifi_mode_t mode;
|
||||
- esp_err_t err = esp_netif_init();
|
||||
- if (err != ESP_OK)
|
||||
- {
|
||||
- return ESP32Utils::MapError(err);
|
||||
- }
|
||||
-
|
||||
-#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
- // Lets not create a default AP interface if already present
|
||||
- if (!esp_netif_get_handle_from_ifkey(kDefaultWiFiAPNetifKey))
|
||||
- {
|
||||
- if (!esp_netif_create_default_wifi_ap())
|
||||
- {
|
||||
- ChipLogError(DeviceLayer, "Failed to create the WiFi AP netif");
|
||||
- return CHIP_ERROR_INTERNAL;
|
||||
- }
|
||||
- }
|
||||
-#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_AP
|
||||
-
|
||||
- // Lets not create a default station interface if already present
|
||||
- if (!esp_netif_get_handle_from_ifkey(kDefaultWiFiStationNetifKey))
|
||||
- {
|
||||
- if (!esp_netif_create_default_wifi_sta())
|
||||
- {
|
||||
- ChipLogError(DeviceLayer, "Failed to create the WiFi STA netif");
|
||||
- return CHIP_ERROR_INTERNAL;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Initialize the ESP WiFi layer.
|
||||
- cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
- err = esp_wifi_init(&cfg);
|
||||
- if (err != ESP_OK)
|
||||
- {
|
||||
- return ESP32Utils::MapError(err);
|
||||
- }
|
||||
-
|
||||
- esp_wifi_get_mode(&mode);
|
||||
- if ((mode == WIFI_MODE_AP) || (mode == WIFI_MODE_APSTA))
|
||||
- {
|
||||
- esp_fill_random(ap_mac, sizeof(ap_mac));
|
||||
- /* Bit 0 of the first octet of MAC Address should always be 0 */
|
||||
- ap_mac[0] &= (uint8_t) ~0x01;
|
||||
- err = esp_wifi_set_mac(WIFI_IF_AP, ap_mac);
|
||||
- if (err != ESP_OK)
|
||||
- {
|
||||
- return ESP32Utils::MapError(err);
|
||||
- }
|
||||
- }
|
||||
- err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent, NULL);
|
||||
- if (err != ESP_OK)
|
||||
- {
|
||||
- return ESP32Utils::MapError(err);
|
||||
- }
|
||||
+ // Intentionally make this function empty so that we can setup wifi stack in the example
|
||||
return CHIP_NO_ERROR;
|
||||
}
|
||||
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
diff --git a/src/platform/ESP32/PlatformManagerImpl.cpp b/src/platform/ESP32/PlatformManagerImpl.cpp
|
||||
index 2c73019933..35ff83c2df 100644
|
||||
--- a/src/platform/ESP32/PlatformManagerImpl.cpp
|
||||
+++ b/src/platform/ESP32/PlatformManagerImpl.cpp
|
||||
@@ -60,7 +60,18 @@ static int app_entropy_source(void * data, unsigned char * output, size_t len, s
|
||||
return 0;
|
||||
}
|
||||
|
||||
-CHIP_ERROR PlatformManagerImpl::_InitChipStack()
|
||||
+CHIP_ERROR PlatformManagerImpl::DisableESPEventDispatch()
|
||||
+{
|
||||
+ esp_err_t err = esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent);
|
||||
+ if (err != ESP_OK)
|
||||
+ {
|
||||
+ return Internal::ESP32Utils::MapError(err);
|
||||
+ }
|
||||
+ err = esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent);
|
||||
+ return Internal::ESP32Utils::MapError(err);
|
||||
+}
|
||||
+
|
||||
+CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
|
||||
{
|
||||
// Arrange for CHIP-encapsulated ESP32 errors to be translated to text
|
||||
Internal::ESP32Utils::RegisterESP32ErrorFormatter();
|
||||
@@ -73,6 +84,10 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack()
|
||||
esp_err_t err = esp_netif_init();
|
||||
VerifyOrReturnError(err == ESP_OK, Internal::ESP32Utils::MapError(err));
|
||||
|
||||
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
+ err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent, nullptr);
|
||||
+ VerifyOrReturnError(err == ESP_OK, Internal::ESP32Utils::MapError(err));
|
||||
+#endif
|
||||
// Arrange for the ESP event loop to deliver events into the CHIP Device layer.
|
||||
err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, PlatformManagerImpl::HandleESPSystemEvent, nullptr);
|
||||
VerifyOrReturnError(err == ESP_OK, Internal::ESP32Utils::MapError(err));
|
||||
diff --git a/src/platform/ESP32/PlatformManagerImpl.h b/src/platform/ESP32/PlatformManagerImpl.h
|
||||
index cc2b0eefe9..0d99857ef8 100644
|
||||
--- a/src/platform/ESP32/PlatformManagerImpl.h
|
||||
+++ b/src/platform/ESP32/PlatformManagerImpl.h
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
CHIP_ERROR InitLwIPCoreLock(void);
|
||||
static void HandleESPSystemEvent(void * arg, esp_event_base_t eventBase, int32_t eventId, void * eventData);
|
||||
System::Clock::Timestamp GetStartTime() { return mStartTime; }
|
||||
+ static CHIP_ERROR DisableESPEventDispatch();
|
||||
|
||||
private:
|
||||
// ===== Methods that implement the PlatformManager abstract interface.
|
||||
diff --git a/src/platform/ESP32/nimble/BLEManagerImpl.cpp b/src/platform/ESP32/nimble/BLEManagerImpl.cpp
|
||||
index d4d90f4536..75328ddb3c 100644
|
||||
--- a/src/platform/ESP32/nimble/BLEManagerImpl.cpp
|
||||
+++ b/src/platform/ESP32/nimble/BLEManagerImpl.cpp
|
||||
@@ -125,39 +125,35 @@ uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
|
||||
ChipDeviceScanner & mDeviceScanner = Internal::ChipDeviceScanner::GetInstance();
|
||||
#endif
|
||||
BLEManagerImpl BLEManagerImpl::sInstance;
|
||||
-const struct ble_gatt_svc_def BLEManagerImpl::CHIPoBLEGATTAttrs[] = {
|
||||
- { .type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
- .uuid = (ble_uuid_t *) (&ShortUUID_CHIPoBLEService),
|
||||
- .characteristics =
|
||||
- (struct ble_gatt_chr_def[]){
|
||||
- {
|
||||
- .uuid = (ble_uuid_t *) (&UUID128_CHIPoBLEChar_RX),
|
||||
- .access_cb = gatt_svr_chr_access,
|
||||
- .flags = BLE_GATT_CHR_F_WRITE,
|
||||
- .val_handle = &sInstance.mRXCharAttrHandle,
|
||||
- },
|
||||
- {
|
||||
- .uuid = (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX),
|
||||
- .access_cb = gatt_svr_chr_access,
|
||||
- .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_INDICATE,
|
||||
- .val_handle = &sInstance.mTXCharCCCDAttrHandle,
|
||||
- },
|
||||
+const struct ble_gatt_svc_def BLEManagerImpl::CHIPoBLEGATTService = {
|
||||
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||
+ .uuid = (ble_uuid_t *) (&ShortUUID_CHIPoBLEService),
|
||||
+ .characteristics = (struct ble_gatt_chr_def[]){
|
||||
+ {
|
||||
+ .uuid = (ble_uuid_t *) (&UUID128_CHIPoBLEChar_RX),
|
||||
+ .access_cb = gatt_svr_chr_access,
|
||||
+ .flags = BLE_GATT_CHR_F_WRITE,
|
||||
+ .val_handle = &sInstance.mRXCharAttrHandle,
|
||||
+ },
|
||||
+ {
|
||||
+ .uuid = (ble_uuid_t *) (&UUID_CHIPoBLEChar_TX),
|
||||
+ .access_cb = gatt_svr_chr_access,
|
||||
+ .flags =
|
||||
+ BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_INDICATE,
|
||||
+ .val_handle = &sInstance.mTXCharCCCDAttrHandle,
|
||||
+ },
|
||||
#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
|
||||
- {
|
||||
- .uuid = (ble_uuid_t *) (&UUID_CHIPoBLEChar_C3),
|
||||
- .access_cb = gatt_svr_chr_access_additional_data,
|
||||
- .flags = BLE_GATT_CHR_F_READ,
|
||||
- .val_handle = &sInstance.mC3CharAttrHandle,
|
||||
- },
|
||||
+ {
|
||||
+ .uuid = (ble_uuid_t *) (&UUID_CHIPoBLEChar_C3),
|
||||
+ .access_cb = gatt_svr_chr_access_additional_data,
|
||||
+ .flags = BLE_GATT_CHR_F_READ,
|
||||
+ .val_handle = &sInstance.mC3CharAttrHandle,
|
||||
+ },
|
||||
#endif
|
||||
- {
|
||||
- 0, /* No more characteristics in this service */
|
||||
- },
|
||||
- } },
|
||||
-
|
||||
- {
|
||||
- 0, /* No more services. */
|
||||
- },
|
||||
+ {
|
||||
+ 0, /* No more characteristics in this service */
|
||||
+ },
|
||||
+ }
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ENABLE_ESP32_BLE_CONTROLLER
|
||||
@@ -773,6 +769,12 @@ void BLEManagerImpl::DriveBLEState(void)
|
||||
ChipLogError(DeviceLayer, "Configure Adv Data failed: %s", ErrorStr(err));
|
||||
ExitNow();
|
||||
}
|
||||
+ err = ConfigureSecondaryAdvertisingData();
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "Configure secondary Adv Data failed: %s", ErrorStr(err));
|
||||
+ ExitNow();
|
||||
+ }
|
||||
}
|
||||
|
||||
// Start advertising. This is also an asynchronous step.
|
||||
@@ -783,6 +785,12 @@ void BLEManagerImpl::DriveBLEState(void)
|
||||
ChipLogError(DeviceLayer, "Start advertising failed: %s", ErrorStr(err));
|
||||
ExitNow();
|
||||
}
|
||||
+ err = StartSecondaryAdvertising();
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "Start secondary advertising failed: %s", ErrorStr(err));
|
||||
+ ExitNow();
|
||||
+ }
|
||||
|
||||
mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
|
||||
// Transition to the Advertising state...
|
||||
@@ -808,12 +816,12 @@ void BLEManagerImpl::DriveBLEState(void)
|
||||
{
|
||||
if (mFlags.Has(Flags::kAdvertising))
|
||||
{
|
||||
- if (ble_gap_adv_active())
|
||||
+ if (ble_gap_ext_adv_active(kChipAdvInstance))
|
||||
{
|
||||
- err = MapBLEError(ble_gap_adv_stop());
|
||||
+ err = MapBLEError(ble_gap_ext_adv_stop(kChipAdvInstance));
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %s", ErrorStr(err));
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_stop() failed: %s", ErrorStr(err));
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
@@ -939,14 +947,15 @@ CHIP_ERROR BLEManagerImpl::InitESPBleLayer(void)
|
||||
ble_svc_gap_init();
|
||||
ble_svc_gatt_init();
|
||||
|
||||
- err = MapBLEError(ble_gatts_count_cfg(CHIPoBLEGATTAttrs));
|
||||
+ mGATTServices[1 - mSecondGATTServiceIndex] = CHIPoBLEGATTService;
|
||||
+ err = MapBLEError(ble_gatts_count_cfg(mGATTServices));
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "ble_gatts_count_cfg failed: %s", ErrorStr(err));
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
- err = MapBLEError(ble_gatts_add_svcs(CHIPoBLEGATTAttrs));
|
||||
+ err = MapBLEError(ble_gatts_add_svcs(mGATTServices));
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
ChipLogError(DeviceLayer, "ble_gatts_add_svcs failed: %s", ErrorStr(err));
|
||||
@@ -992,7 +1001,7 @@ void BLEManagerImpl::ClaimBLEMemory(System::Layer *, void *)
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
err = esp_bt_mem_release(ESP_BT_MODE_BTDM);
|
||||
-#elif defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || \
|
||||
+#elif defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || \
|
||||
defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
err = esp_bt_mem_release(ESP_BT_MODE_BLE);
|
||||
#endif
|
||||
@@ -1024,7 +1033,6 @@ CHIP_ERROR BLEManagerImpl::DeinitBLE()
|
||||
CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
|
||||
{
|
||||
CHIP_ERROR err;
|
||||
- uint8_t advData[MAX_ADV_DATA_LEN];
|
||||
uint8_t index = 0;
|
||||
|
||||
constexpr uint8_t kServiceDataTypeSize = 1;
|
||||
@@ -1050,14 +1058,14 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
- memset(advData, 0, sizeof(advData));
|
||||
- advData[index++] = 0x02; // length
|
||||
- advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
|
||||
- advData[index++] = CHIP_ADV_DATA_FLAGS; // AD value
|
||||
- advData[index++] = kServiceDataTypeSize + sizeof(ESP32ChipServiceData); // length
|
||||
- advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type: (Service Data - 16-bit UUID)
|
||||
- advData[index++] = static_cast<uint8_t>(ShortUUID_CHIPoBLEService.value & 0xFF); // AD value
|
||||
- advData[index++] = static_cast<uint8_t>((ShortUUID_CHIPoBLEService.value >> 8) & 0xFF); // AD value
|
||||
+ memset(mAdvData, 0, sizeof(mAdvData));
|
||||
+ mAdvData[index++] = 0x02; // length
|
||||
+ mAdvData[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
|
||||
+ mAdvData[index++] = CHIP_ADV_DATA_FLAGS; // AD value
|
||||
+ mAdvData[index++] = kServiceDataTypeSize + sizeof(ESP32ChipServiceData); // length
|
||||
+ mAdvData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type: (Service Data - 16-bit UUID)
|
||||
+ mAdvData[index++] = static_cast<uint8_t>(ShortUUID_CHIPoBLEService.value & 0xFF); // AD value
|
||||
+ mAdvData[index++] = static_cast<uint8_t>((ShortUUID_CHIPoBLEService.value >> 8) & 0xFF); // AD value
|
||||
|
||||
err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(deviceIdInfo);
|
||||
if (err != CHIP_NO_ERROR)
|
||||
@@ -1087,18 +1095,11 @@ CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
- VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(advData), err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG);
|
||||
- memcpy(&advData[index], &deviceIdInfo, sizeof(deviceIdInfo));
|
||||
+ VerifyOrExit(index + sizeof(deviceIdInfo) <= sizeof(mAdvData), err = CHIP_ERROR_OUTBOUND_MESSAGE_TOO_BIG);
|
||||
+ memcpy(&mAdvData[index], &deviceIdInfo, sizeof(deviceIdInfo));
|
||||
index = static_cast<uint8_t>(index + sizeof(deviceIdInfo));
|
||||
|
||||
- // Construct the Chip BLE Service Data to be sent in the scan response packet.
|
||||
- err = MapBLEError(ble_gap_adv_set_data(advData, sizeof(advData)));
|
||||
- if (err != CHIP_NO_ERROR)
|
||||
- {
|
||||
- ChipLogError(DeviceLayer, "ble_gap_adv_set_data failed: %s %d", ErrorStr(err), discriminator);
|
||||
- ExitNow();
|
||||
- }
|
||||
-
|
||||
+ mAdvDataLen = index;
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
@@ -1651,16 +1652,18 @@ int BLEManagerImpl::gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_hand
|
||||
CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
|
||||
{
|
||||
CHIP_ERROR err;
|
||||
- ble_gap_adv_params adv_params;
|
||||
+ ble_gap_ext_adv_params adv_params;
|
||||
memset(&adv_params, 0, sizeof(adv_params));
|
||||
- adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||
+ adv_params.scannable = 1;
|
||||
+ adv_params.own_addr_type = own_addr_type;
|
||||
+ adv_params.legacy_pdu = 1;
|
||||
|
||||
mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
|
||||
|
||||
// Advertise connectable if we haven't reached the maximum number of connections.
|
||||
- size_t numCons = _NumConnections();
|
||||
- bool connectable = (numCons < kMaxConnections);
|
||||
- adv_params.conn_mode = connectable ? BLE_GAP_CONN_MODE_UND : BLE_GAP_CONN_MODE_NON;
|
||||
+ size_t numCons = _NumConnections();
|
||||
+ bool connectable = (numCons < kMaxConnections);
|
||||
+ adv_params.connectable = connectable;
|
||||
|
||||
// Advertise in fast mode if it is connectable advertisement and
|
||||
// the application has expressly requested fast advertising.
|
||||
@@ -1694,48 +1697,187 @@ CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
|
||||
(((uint32_t) adv_params.itvl_min) * 10) / 16, (connectable) ? "" : "non-");
|
||||
|
||||
{
|
||||
- if (ble_gap_adv_active())
|
||||
+ if (ble_gap_ext_adv_active(kChipAdvInstance))
|
||||
{
|
||||
/* Advertising is already active. Stop and restart with the new parameters */
|
||||
ChipLogProgress(DeviceLayer, "Device already advertising, stop active advertisement and restart");
|
||||
- err = MapBLEError(ble_gap_adv_stop());
|
||||
+ err = MapBLEError(ble_gap_ext_adv_stop(kChipAdvInstance));
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- ChipLogError(DeviceLayer, "ble_gap_adv_stop() failed: %s, cannot restart", ErrorStr(err));
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_stop() failed: %s, cannot restart", ErrorStr(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
-#ifdef CONFIG_BT_NIMBLE_HOST_BASED_PRIVACY
|
||||
- else
|
||||
+ err = MapBLEError(ble_gap_ext_adv_configure(kChipAdvInstance, &adv_params, NULL, ble_svr_gap_event, NULL));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- err = MapBLEError(ble_hs_pvcy_rpa_config(NIMBLE_HOST_ENABLE_RPA));
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_configure failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ ble_addr_t addr;
|
||||
+
|
||||
+ /* generate new non-resolvable private address */
|
||||
+ err = MapBLEError(ble_hs_id_gen_rnd(1, &addr));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_hs_id_gen_rnd failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Set generated address */
|
||||
+ err = MapBLEError(ble_gap_ext_adv_set_addr(kChipAdvInstance, &addr));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_set_addr failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ struct os_mbuf * data = os_msys_get_pkthdr(mAdvDataLen, 0);
|
||||
+ assert(data);
|
||||
+ err = MapBLEError(os_mbuf_append(data, mAdvData, mAdvDataLen));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "os_mbuf_append failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = MapBLEError(ble_gap_ext_adv_set_data(kChipAdvInstance, data));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "os_mbuf_append failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (mScanResponse.HasValue())
|
||||
+ {
|
||||
+ uint16_t resp_size = static_cast<uint16_t>(mScanResponse.Value().size());
|
||||
+ struct os_mbuf * resp_data = os_msys_get_pkthdr(resp_size, 0);
|
||||
+ assert(resp_data);
|
||||
+ err = MapBLEError(os_mbuf_append(resp_data, mScanResponse.Value().data(), resp_size));
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- ChipLogError(DeviceLayer, "RPA not set: %s", ErrorStr(err));
|
||||
+ ChipLogError(DeviceLayer, "os_mbuf_append failed: %s", ErrorStr(err));
|
||||
return err;
|
||||
}
|
||||
- }
|
||||
-#endif
|
||||
- if (mScanResponse.HasValue())
|
||||
- {
|
||||
- err = MapBLEError(ble_gap_adv_rsp_set_data(mScanResponse.Value().data(), mScanResponse.Value().size()));
|
||||
+ err = MapBLEError(ble_gap_ext_adv_rsp_set_data(kChipAdvInstance, resp_data));
|
||||
if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- ChipLogError(DeviceLayer, "ble_gap_adv_rsp_set_data failed: %s", ErrorStr(err));
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_rsp_set_data failed: %s", ErrorStr(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
- err = MapBLEError(ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, ble_svr_gap_event, NULL));
|
||||
- if (err == CHIP_NO_ERROR)
|
||||
+ err = MapBLEError(ble_gap_ext_adv_start(kChipAdvInstance, 0, 0));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- return CHIP_NO_ERROR;
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_start() failed: %s", ErrorStr(err));
|
||||
}
|
||||
- else
|
||||
+ }
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int BLEManagerImpl::secondary_ble_svr_gap_event(struct ble_gap_event * event, void * arg)
|
||||
+{
|
||||
+ if (chip::DeviceLayer::Internal::BLEMgrImpl().mSecondaryBleGapEventHandler) {
|
||||
+ return chip::DeviceLayer::Internal::BLEMgrImpl().mSecondaryBleGapEventHandler(event, arg);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+CHIP_ERROR BLEManagerImpl::ConfigureSecondaryAdvertisingData(void)
|
||||
+{
|
||||
+ memset(&mSecondaryAdvFields, 0, sizeof(mSecondaryAdvFields));
|
||||
+ mSecondaryAdvFields.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
|
||||
+ mSecondaryAdvFields.num_uuids128 = 1;
|
||||
+ mSecondaryAdvFields.uuids128_is_complete = 1;
|
||||
+ mSecondaryAdvFields.uuids128 = &mSecondaryAdvUuid;
|
||||
+
|
||||
+ memset(&mSecondaryRespFields, 0, sizeof(mSecondaryRespFields));
|
||||
+ mSecondaryRespFields.name = (const uint8_t *)mSecondaryAdvDeviceName;
|
||||
+ mSecondaryRespFields.name_len = (uint8_t)strlen(mSecondaryAdvDeviceName);
|
||||
+ mSecondaryRespFields.name_is_complete = 1;
|
||||
+ return CHIP_NO_ERROR;
|
||||
+}
|
||||
+
|
||||
+CHIP_ERROR BLEManagerImpl::StartSecondaryAdvertising(void)
|
||||
+{
|
||||
+ CHIP_ERROR err;
|
||||
+ uint8_t secondary_own_addr_type;
|
||||
+ err = MapBLEError(ble_hs_util_ensure_addr(0));
|
||||
+ if (err != CHIP_NO_ERROR) {
|
||||
+ ESP_LOGE(TAG, "Error loading address");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Figure out address to use while advertising (no privacy for now) */
|
||||
+ err = MapBLEError(ble_hs_id_infer_auto(0, &secondary_own_addr_type));
|
||||
+ if (err != CHIP_NO_ERROR) {
|
||||
+ ChipLogError(DeviceLayer, "ble_hs_id_infer_auto() failed: %s, cannot restart", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+ ble_gap_ext_adv_params adv_params;
|
||||
+ memset(&adv_params, 0, sizeof(adv_params));
|
||||
+ adv_params.scannable = 1;
|
||||
+ adv_params.own_addr_type = secondary_own_addr_type;
|
||||
+ adv_params.legacy_pdu = 1;
|
||||
+ adv_params.connectable = 1;
|
||||
+ adv_params.itvl_min = 0x100;
|
||||
+ adv_params.itvl_max = 0x100;
|
||||
+
|
||||
+ if (ble_gap_ext_adv_active(kSecondaryAdvInstance))
|
||||
+ {
|
||||
+ /* Advertising is already active. Stop and restart with the new parameters */
|
||||
+ ChipLogProgress(DeviceLayer, "Device already advertising, stop active advertisement and restart");
|
||||
+ err = MapBLEError(ble_gap_ext_adv_stop(kSecondaryAdvInstance));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
{
|
||||
- ChipLogError(DeviceLayer, "ble_gap_adv_start() failed: %s", ErrorStr(err));
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_stop() failed: %s, cannot restart", ErrorStr(err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
+ err = MapBLEError(ble_gap_ext_adv_configure(kSecondaryAdvInstance, &adv_params, NULL, secondary_ble_svr_gap_event, NULL));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_configure failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ struct os_mbuf * data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0);
|
||||
+ assert(data);
|
||||
+ err = MapBLEError(ble_hs_adv_set_fields_mbuf(&mSecondaryAdvFields, data));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_hs_adv_set_fields_mbuf failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = MapBLEError(ble_gap_ext_adv_set_data(kSecondaryAdvInstance, data));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_set_data failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ struct os_mbuf * resp_data = os_msys_get_pkthdr(BLE_HCI_MAX_ADV_DATA_LEN, 0);
|
||||
+ assert(resp_data);
|
||||
+ err = MapBLEError(ble_hs_adv_set_fields_mbuf(&mSecondaryRespFields, resp_data));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_hs_adv_set_fields_mbuf failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = MapBLEError(ble_gap_ext_adv_rsp_set_data(kSecondaryAdvInstance, resp_data));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_set_data failed: %s", ErrorStr(err));
|
||||
+ return err;
|
||||
+ }
|
||||
+ err = MapBLEError(ble_gap_ext_adv_start(kSecondaryAdvInstance, 0, 0));
|
||||
+ if (err != CHIP_NO_ERROR)
|
||||
+ {
|
||||
+ ChipLogError(DeviceLayer, "ble_gap_ext_adv_start() failed: %s", ErrorStr(err));
|
||||
+ }
|
||||
+ return err;
|
||||
}
|
||||
|
||||
void BLEManagerImpl::DriveBLEState(intptr_t arg)
|
||||
@@ -0,0 +1 @@
|
||||
../../../../../connectedhomeip/connectedhomeip/src/platform/ESP32/route_hook
|
||||
@@ -0,0 +1,41 @@
|
||||
# The following lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
if(NOT DEFINED ENV{ESP_MATTER_PATH})
|
||||
message(FATAL_ERROR "Please set ESP_MATTER_PATH to the path of esp-matter repo")
|
||||
endif(NOT DEFINED ENV{ESP_MATTER_PATH})
|
||||
|
||||
set(PROJECT_VER "1.0")
|
||||
set(PROJECT_VER_NUMBER 1)
|
||||
|
||||
set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH})
|
||||
set(MATTER_SDK_PATH ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip)
|
||||
|
||||
# This should be done before using the IDF_TARGET variable.
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
include(${ESP_MATTER_PATH}/examples/common/cmake_common/components_include.cmake)
|
||||
|
||||
set(EXTRA_COMPONENT_DIRS
|
||||
"${ESP_MATTER_PATH}/examples/common"
|
||||
"${MATTER_SDK_PATH}/config/esp32/components"
|
||||
"${ESP_MATTER_PATH}/components"
|
||||
${extra_components_dirs_append})
|
||||
|
||||
project(light-wifi-prov)
|
||||
|
||||
# WARNING: This is just an example for using key for decrypting the encrypted OTA image
|
||||
# Please do not use it as is.
|
||||
if(CONFIG_ENABLE_ENCRYPTED_OTA)
|
||||
target_add_binary_data(light.elf "esp_image_encryption_key.pem" TEXT)
|
||||
endif()
|
||||
|
||||
if(CONFIG_IDF_TARGET_ESP32C2)
|
||||
include(relinker)
|
||||
endif()
|
||||
|
||||
idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_H;-Wno-overloaded-virtual" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
|
||||
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
|
||||
# flags that depend on -Wformat
|
||||
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security" APPEND)
|
||||
@@ -0,0 +1,143 @@
|
||||
# Light with RainMaker-WiFi-Provisioning
|
||||
|
||||
This example creates a Color Temperature Light device using the ESP Matter data model and is integrated with ESP-RainMaker and wifi_provisioning.
|
||||
|
||||
See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html) for more information about building and flashing the firmware.
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
- ESP32-S3-DevKitM / ESP32-C3-DevKitM
|
||||
- chip-tool (For Matter commissioning)
|
||||
- Android RainMaker APP of version 3.4.1 or iOS RainMaker APP of version 3.2.0 (For RainMaker Provisioning)
|
||||
- [ESP-IDF](https://github.com/espressif/esp-idf) on tag v5.2.2
|
||||
- [ESP RainMaker](https://github.com/espressif/esp-rainmaker/tree/fd781295) on commit fd78129500aa1a8b2eee9e0dcc0720d7b14cd3dc
|
||||
- [ESP Secure Cert Manager](https://github.com/espressif/esp_secure_cert_mgr)
|
||||
|
||||
## 2. Additional Environment Setup
|
||||
|
||||
### 2.1 Claiming device certificates
|
||||
|
||||
This example will use [host driven claiming](https://rainmaker.espressif.com/docs/claiming/#host-driven-claiming) via the RainMaker CLI.
|
||||
|
||||
Make sure your device is connected to the host machine, login into the CLI and execute this:
|
||||
```
|
||||
$ cd $RMAKER_PATH/cli
|
||||
$ ./rainmaker.py claim --matter <port>
|
||||
```
|
||||
The CLI will fetch the device certificates and flash them into the secure cert partition of your device. The certificates will be used for both the Matter device attestation verification and RainMaker MQTT connection.
|
||||
|
||||
### 2.2 Generating the factory nvs binary
|
||||
|
||||
The factory nvs (fctry partition) needs to be generated using the mfg_tool of esp-matter. It is released on pypi as [esp-matter-mfg-tool](https://pypi.org/project/esp-matter-mfg-tool) and can be installed by running `pip install esp-matter-mfg-tool`
|
||||
|
||||
```
|
||||
$ export ESP_SECURE_CERT_PATH=/path/to/esp_secure_cert_mgr
|
||||
$ esp-matter-mfg-tool -v 0x131B -p 0x2 -cd $RMAKER_PATH/examples/matter/mfg/cd_131B_0002.der --csv $RMAKER_PATH/examples/matter/mfg/keys.csv --mcsv $RMAKER_PATH/examples/matter/mfg/master.csv
|
||||
```
|
||||
This not only generates the factory nvs binary required for matter, but also embeds the RainMaker MQTT Host url into it via the master.csv file. Optionally, you can embed the MQTT host into the firmware itself by using idf.py menuconfig -> ESP RainMaker Config -> ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG and then skipping the --csv and --mcsv options to mfg_tool
|
||||
|
||||
The factory binary generated above should be flashed onto the fctry partition (default : 0x3e0000 for ESP32-S3 and ESP32-C3. Do check your partition table for exact address).
|
||||
|
||||
```
|
||||
$ esptool.py write_flash 0x3e0000 out/131b_2/<node-id>/<node-id>-partition.bin
|
||||
```
|
||||
|
||||
### 2.3 Build the example
|
||||
|
||||
Once the environment and required files are set up, we can now proceed to build and flash the example
|
||||
|
||||
```
|
||||
$ idf.py set-target <target>
|
||||
$ idf.py build
|
||||
$ idf.py flash monitor
|
||||
```
|
||||
|
||||
## 3. Post Commissioning Setup
|
||||
|
||||
See the [docs](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#commissioning-and-control) for the information about Matter commissioning with chip-tool. Note that you need to specific the PAA path to the `paa_cert` under the directory of this example when you use the chip-tool to commisioning the device.
|
||||
|
||||
```
|
||||
$ ./chip-tool pairing ble-wifi <node-id> <ssid> <passcode> <setup-pincode> <discriminator> --paa-trust-store-path <PAA-path>
|
||||
```
|
||||
|
||||
**Note**: The `setup-picode` and `discriminator` is generated with the factory partition binary. You can find it in the `out/131b_2/<node-id>/<node-id>-onb_codes.csv`.
|
||||
|
||||
## 4. External platform
|
||||
|
||||
This example uses [external platform](../common/secondary_ble_adv/).
|
||||
|
||||
In the external platform, `SetSecondaryXX()` APIs are added in the `BLEManagerImpl` class for setting up the secondary BLE advertisement and services. After you call these APIs of `BLEManagerImpl`, there will be an additional BLE advertisement and corresponding service for wifi_provisioning after you initialize the Matter stack.
|
||||
|
||||
There are also some WiFi stack initialization changes to avoid duplicated Wi-Fi stack initialization of wifi_provisioning and Matter stack.
|
||||
|
||||
## 5. RainMaker Provisioning
|
||||
|
||||
After you flash the example to the DevKit board, the console will print the QR code for RainMaker Provisioning. After you scan the QR code with the RainMaker Phone App, the RainMaker provisioning will be done and the device will be added to your RainMaker home.
|
||||
|
||||
## 6. Manufacturing Considerations
|
||||
|
||||
This step is only suggested for Privately deployed Production and not required for test set up.
|
||||
|
||||
### 6.1 RainMaker MQTT Host
|
||||
|
||||
Find your private deployment's mqtt hostname (if applicable) by sending a GET request at `https://<Rainmaker-API-endpoint>/mqtt_host`. You should replace the mqtt host in master.csv (As described in the section above) with this to generate the factory nvs binary.
|
||||
|
||||
### 6.2 Matter VID/PID
|
||||
|
||||
For production devices which may have a different matter vid and pid, please set the values of DEVICE_VENDOR_ID and DEVICE_PRODUCT_ID by using `idf.py menuconfig` -> `Component config` -> `CHIP Device Layer` -> `Device Identification Options`. These same should also be used in the `mfg_tool`.
|
||||
|
||||
**Note**: The CD used by `mfg_tool` should also be changed when VID/PID is changed. Please refer to [this](https://docs.espressif.com/projects/esp-matter/en/latest/esp32/certification.html#certification-declaration) about how to generate a test CD file.
|
||||
|
||||
### 6.3 Matter DAC
|
||||
|
||||
For public RainMaker, some test DACs are provided via claiming. For private deployments, test DACs can be generated using `mfg_tool`.
|
||||
|
||||
```
|
||||
export ESP_SECURE_CERT_PATH=/path/to/esp_secure_cert_mgr
|
||||
esp-matter-mfg-tool -v <vendor-id> -p <product-id> --pai -k <pai-key> -c <pai-cert> -cd <cert-dclrn> --csv /path/to/keys.csv --mcsv /path/to/master.csv
|
||||
```
|
||||
|
||||
Samples of keys.csv and master.csv can be found in $RMAKER_PATH/examples/matter/mfg/.
|
||||
|
||||
For testing, you can use the test VID, PID, PAI and CD as shown below.
|
||||
```
|
||||
$ esp-matter-mfg-tool --dac-in-secure-cert -v 0xFFF2 -p 0x8001 --pai -k $ESP_MATTER_PATH/connectedhomeip/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Key.pem -c $ESP_MATTER_PATH/connectedhomeip/connectedhomeip/credentials/test/attestation/Chip-Test-PAI-FFF2-8001-Cert.pem -cd $ESP_MATTER_PATH/connectedhomeip/connectedhomeip/credentials/test/certification-declaration/Chip-Test-CD-FFF2-8001.der --csv $RMAKER_PATH/examples/matter/mfg/keys.csv --mcsv $RMAKER_PATH/examples/matter/mfg/master.csv
|
||||
```
|
||||
|
||||
Note the path where the files are generated after running the above command since it will be required later.
|
||||
|
||||
### 6.4 Configure your app
|
||||
|
||||
Open the project configuration menu using
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
|
||||
In the configuration menu, set the following additional configuration to use custom factory partition and different values for Data and Device Info Providers.
|
||||
|
||||
1. Enable ESP32 Factory Data Provider [Component config → CHIP Device Layer → Commissioning options → Use ESP32 Factory Data Provider]
|
||||
|
||||
Enable config option CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER to use ESP32 specific implementation of CommissionableDataProvider and DeviceAttestationCredentialsProvider.
|
||||
|
||||
2. Enable ESP32 Device Instance Info Provider [Component config → CHIP Device Layer → Commissioning options → Use ESP32 Device Instance Info Provider]
|
||||
|
||||
Enable config option ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER to get device instance info from factory partition.
|
||||
|
||||
3. Enable Attestation - Secure Cert [ Component config → ESP Matter → DAC Provider options → Attestation - Secure Cert]
|
||||
|
||||
Enable config option CONFIG_FACTORY_PARTITION_DAC_PROVIDER to use DAC certificates from the secure_cert partition during Attestation.
|
||||
|
||||
4. Set chip-factory namespace partition label [Component config → CHIP Device Layer → Matter Manufacturing Options → chip-factory namespace partition label]
|
||||
|
||||
Set config option CHIP_FACTORY_NAMESPACE_PARTITION_LABEL to choose the label of the partition to store key-values in the "chip-factory" namespace. The default chosen partition label is nvs, change it to fctry.
|
||||
|
||||
|
||||
Connect your esp32 device to your computer. Enter the below command to flash certificates and factory partition
|
||||
|
||||
```
|
||||
$ esptool.py write_flash 0xd000 /out/<vendor-id>_<product-id>/<node-id>/<node-id>_esp_secure_cert.bin 0x3e0000 ./out/<vendor-id>_<product-id>/<node-id>/<node-id>-partition.bin
|
||||
```
|
||||
|
||||
The csv file generate at `/out/<vendor-id>_<product-id>/cn_dacs-<date>-<time>.csv` should be registered to your private RainMaker deployment (if applicable) using the steps mentioned here.
|
||||
|
||||
> **In production use case, the DACs will be pre-provisioned in the modules and a csv file will be provided by the Espressif factory directly. Optionally, even the fctry partitions can be pre programmed. If not, use the mfg_tool to generate these nvs binaries**
|
||||
@@ -0,0 +1,5 @@
|
||||
idf_component_register(SRC_DIRS "." "./wifi_prov_scheme"
|
||||
PRIV_INCLUDE_DIRS "." "${ESP_MATTER_PATH}/examples/common/utils" "./wifi_prov_scheme")
|
||||
|
||||
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <esp_matter.h>
|
||||
#include "bsp/esp-bsp.h"
|
||||
|
||||
#include <app_priv.h>
|
||||
|
||||
using namespace chip::app::Clusters;
|
||||
using namespace esp_matter;
|
||||
|
||||
static const char *TAG = "app_driver";
|
||||
extern uint16_t light_endpoint_id;
|
||||
|
||||
/* Do any conversions/remapping for the actual value here */
|
||||
static esp_err_t app_driver_light_set_power(led_indicator_handle_t handle, esp_matter_attr_val_t *val)
|
||||
{
|
||||
#if CONFIG_BSP_LEDS_NUM > 0
|
||||
esp_err_t err = ESP_OK;
|
||||
if (val->val.b) {
|
||||
err = led_indicator_start(handle, BSP_LED_ON);
|
||||
} else {
|
||||
err = led_indicator_start(handle, BSP_LED_OFF);
|
||||
}
|
||||
return err;
|
||||
#else
|
||||
ESP_LOGI(TAG, "LED set power: %d", val->val.b);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t app_driver_light_set_brightness(led_indicator_handle_t handle, esp_matter_attr_val_t *val)
|
||||
{
|
||||
int value = REMAP_TO_RANGE(val->val.u8, MATTER_BRIGHTNESS, STANDARD_BRIGHTNESS);
|
||||
#if CONFIG_BSP_LEDS_NUM > 0
|
||||
return led_indicator_set_brightness(handle, value);
|
||||
#else
|
||||
ESP_LOGI(TAG, "LED set brightness: %d", value);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t app_driver_light_set_hue(led_indicator_handle_t handle, esp_matter_attr_val_t *val)
|
||||
{
|
||||
int value = REMAP_TO_RANGE(val->val.u8, MATTER_HUE, STANDARD_HUE);
|
||||
#if CONFIG_BSP_LEDS_NUM > 0
|
||||
led_indicator_ihsv_t hsv;
|
||||
hsv.value = led_indicator_get_hsv(handle);
|
||||
hsv.h = value;
|
||||
return led_indicator_set_hsv(handle, hsv.value);
|
||||
#else
|
||||
ESP_LOGI(TAG, "LED set hue: %d", value);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t app_driver_light_set_saturation(led_indicator_handle_t handle, esp_matter_attr_val_t *val)
|
||||
{
|
||||
int value = REMAP_TO_RANGE(val->val.u8, MATTER_SATURATION, STANDARD_SATURATION);
|
||||
#if CONFIG_BSP_LEDS_NUM > 0
|
||||
led_indicator_ihsv_t hsv;
|
||||
hsv.value = led_indicator_get_hsv(handle);
|
||||
hsv.s = value;
|
||||
return led_indicator_set_hsv(handle, hsv.value);
|
||||
#else
|
||||
ESP_LOGI(TAG, "LED set saturation: %d", value);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t app_driver_light_set_temperature(led_indicator_handle_t handle, esp_matter_attr_val_t *val)
|
||||
{
|
||||
uint32_t value = REMAP_TO_RANGE_INVERSE(val->val.u16, STANDARD_TEMPERATURE_FACTOR);
|
||||
#if CONFIG_BSP_LEDS_NUM > 0
|
||||
return led_indicator_set_color_temperature(handle, value);
|
||||
#else
|
||||
ESP_LOGI(TAG, "LED set temperature: %ld", value);
|
||||
return ESP_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void app_driver_button_toggle_cb(void *arg, void *data)
|
||||
{
|
||||
ESP_LOGI(TAG, "Toggle button pressed");
|
||||
uint16_t endpoint_id = light_endpoint_id;
|
||||
uint32_t cluster_id = OnOff::Id;
|
||||
uint32_t attribute_id = OnOff::Attributes::OnOff::Id;
|
||||
|
||||
node_t *node = node::get();
|
||||
endpoint_t *endpoint = endpoint::get(node, endpoint_id);
|
||||
cluster_t *cluster = cluster::get(endpoint, cluster_id);
|
||||
attribute_t *attribute = attribute::get(cluster, attribute_id);
|
||||
|
||||
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
|
||||
attribute::get_val(attribute, &val);
|
||||
val.val.b = !val.val.b;
|
||||
attribute::update(endpoint_id, cluster_id, attribute_id, &val);
|
||||
}
|
||||
|
||||
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t attribute_id, esp_matter_attr_val_t *val)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
if (endpoint_id == light_endpoint_id) {
|
||||
led_indicator_handle_t handle = (led_indicator_handle_t)driver_handle;
|
||||
if (cluster_id == OnOff::Id) {
|
||||
if (attribute_id == OnOff::Attributes::OnOff::Id) {
|
||||
err = app_driver_light_set_power(handle, val);
|
||||
}
|
||||
} else if (cluster_id == LevelControl::Id) {
|
||||
if (attribute_id == LevelControl::Attributes::CurrentLevel::Id) {
|
||||
err = app_driver_light_set_brightness(handle, val);
|
||||
}
|
||||
} else if (cluster_id == ColorControl::Id) {
|
||||
if (attribute_id == ColorControl::Attributes::CurrentHue::Id) {
|
||||
err = app_driver_light_set_hue(handle, val);
|
||||
} else if (attribute_id == ColorControl::Attributes::CurrentSaturation::Id) {
|
||||
err = app_driver_light_set_saturation(handle, val);
|
||||
} else if (attribute_id == ColorControl::Attributes::ColorTemperatureMireds::Id) {
|
||||
err = app_driver_light_set_temperature(handle, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
void *priv_data = endpoint::get_priv_data(endpoint_id);
|
||||
led_indicator_handle_t handle = (led_indicator_handle_t)priv_data;
|
||||
node_t *node = node::get();
|
||||
endpoint_t *endpoint = endpoint::get(node, endpoint_id);
|
||||
cluster_t *cluster = NULL;
|
||||
attribute_t *attribute = NULL;
|
||||
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
|
||||
|
||||
/* Setting brightness */
|
||||
cluster = cluster::get(endpoint, LevelControl::Id);
|
||||
attribute = attribute::get(cluster, LevelControl::Attributes::CurrentLevel::Id);
|
||||
attribute::get_val(attribute, &val);
|
||||
err |= app_driver_light_set_brightness(handle, &val);
|
||||
|
||||
/* Setting color */
|
||||
cluster = cluster::get(endpoint, ColorControl::Id);
|
||||
attribute = attribute::get(cluster, ColorControl::Attributes::ColorMode::Id);
|
||||
attribute::get_val(attribute, &val);
|
||||
if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kCurrentHueAndCurrentSaturation) {
|
||||
/* Setting hue */
|
||||
attribute = attribute::get(cluster, ColorControl::Attributes::CurrentHue::Id);
|
||||
attribute::get_val(attribute, &val);
|
||||
err |= app_driver_light_set_hue(handle, &val);
|
||||
/* Setting saturation */
|
||||
attribute = attribute::get(cluster, ColorControl::Attributes::CurrentSaturation::Id);
|
||||
attribute::get_val(attribute, &val);
|
||||
err |= app_driver_light_set_saturation(handle, &val);
|
||||
} else if (val.val.u8 == (uint8_t)ColorControl::ColorMode::kColorTemperature) {
|
||||
/* Setting temperature */
|
||||
attribute = attribute::get(cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
|
||||
attribute::get_val(attribute, &val);
|
||||
err |= app_driver_light_set_temperature(handle, &val);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Color mode not supported");
|
||||
}
|
||||
|
||||
/* Setting power */
|
||||
cluster = cluster::get(endpoint, OnOff::Id);
|
||||
attribute = attribute::get(cluster, OnOff::Attributes::OnOff::Id);
|
||||
attribute::get_val(attribute, &val);
|
||||
err |= app_driver_light_set_power(handle, &val);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
app_driver_handle_t app_driver_light_init()
|
||||
{
|
||||
#if CONFIG_BSP_LEDS_NUM > 0
|
||||
/* Initialize led */
|
||||
led_indicator_handle_t leds[CONFIG_BSP_LEDS_NUM];
|
||||
ESP_ERROR_CHECK(bsp_led_indicator_create(leds, NULL, CONFIG_BSP_LEDS_NUM));
|
||||
led_indicator_set_hsv(leds[0], SET_HSV(DEFAULT_HUE, DEFAULT_SATURATION, DEFAULT_BRIGHTNESS));
|
||||
|
||||
return (app_driver_handle_t)leds[0];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
app_driver_handle_t app_driver_button_init()
|
||||
{
|
||||
/* Initialize button */
|
||||
button_handle_t btns[BSP_BUTTON_NUM];
|
||||
ESP_ERROR_CHECK(bsp_iot_button_create(btns, NULL, BSP_BUTTON_NUM));
|
||||
ESP_ERROR_CHECK(iot_button_register_cb(btns[0], BUTTON_PRESS_DOWN, app_driver_button_toggle_cb, NULL));
|
||||
|
||||
return (app_driver_handle_t)btns[0];
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "esp_matter_attribute_utils.h"
|
||||
#include "esp_rmaker_user_mapping.h"
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
#include <esp_matter.h>
|
||||
#include <esp_matter_console.h>
|
||||
#include <esp_matter_ota.h>
|
||||
|
||||
#include <esp_rmaker_console.h>
|
||||
#include <esp_rmaker_core.h>
|
||||
#include <esp_rmaker_scenes.h>
|
||||
#include <esp_rmaker_schedule.h>
|
||||
#include <esp_rmaker_standard_devices.h>
|
||||
#include <esp_rmaker_standard_params.h>
|
||||
|
||||
#include <app_priv.h>
|
||||
#include <app_reset.h>
|
||||
#include <app_wifi.h>
|
||||
#include <common_macros.h>
|
||||
#include "app-common/zap-generated/ids/Attributes.h"
|
||||
#include "app-common/zap-generated/ids/Clusters.h"
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
||||
#include <platform/ESP32/OpenthreadLauncher.h>
|
||||
#endif
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
|
||||
#include <platform/ESP32/ESP32Utils.h>
|
||||
#endif
|
||||
|
||||
#include <app/server/CommissioningWindowManager.h>
|
||||
#include <app/server/Server.h>
|
||||
|
||||
static const char *TAG = "app_main";
|
||||
uint16_t light_endpoint_id = 0;
|
||||
|
||||
using namespace esp_matter;
|
||||
using namespace esp_matter::attribute;
|
||||
using namespace esp_matter::endpoint;
|
||||
using namespace chip::app::Clusters;
|
||||
|
||||
constexpr auto k_timeout_seconds = 300;
|
||||
|
||||
#if CONFIG_ENABLE_ENCRYPTED_OTA
|
||||
extern const char decryption_key_start[] asm("_binary_esp_image_encryption_key_pem_start");
|
||||
extern const char decryption_key_end[] asm("_binary_esp_image_encryption_key_pem_end");
|
||||
|
||||
static const char *s_decryption_key = decryption_key_start;
|
||||
static const uint16_t s_decryption_key_len = decryption_key_end - decryption_key_start;
|
||||
#endif // CONFIG_ENABLE_ENCRYPTED_OTA
|
||||
|
||||
static esp_rmaker_device_t *light_device;
|
||||
|
||||
static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg)
|
||||
{
|
||||
switch (event->Type) {
|
||||
case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged:
|
||||
ESP_LOGI(TAG, "Interface IP Address changed");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningComplete:
|
||||
ESP_LOGI(TAG, "Commissioning complete");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired:
|
||||
ESP_LOGI(TAG, "Commissioning failed, fail safe timer expired");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted:
|
||||
ESP_LOGI(TAG, "Commissioning session started");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped:
|
||||
ESP_LOGI(TAG, "Commissioning session stopped");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened:
|
||||
ESP_LOGI(TAG, "Commissioning window opened");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed:
|
||||
ESP_LOGI(TAG, "Commissioning window closed");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricRemoved: {
|
||||
ESP_LOGI(TAG, "Fabric removed successfully");
|
||||
if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) {
|
||||
chip::CommissioningWindowManager &commissionMgr =
|
||||
chip::Server::GetInstance().GetCommissioningWindowManager();
|
||||
constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds);
|
||||
if (!commissionMgr.IsCommissioningWindowOpen()) {
|
||||
/* After removing last fabric, this example does not remove the Wi-Fi credentials
|
||||
* and still has IP connectivity so, only advertising on DNS-SD.
|
||||
*/
|
||||
CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(
|
||||
kTimeoutSeconds, chip::CommissioningWindowAdvertisement::kDnssdOnly);
|
||||
if (err != CHIP_NO_ERROR) {
|
||||
ESP_LOGE(TAG, "Failed to open commissioning window, err:%" CHIP_ERROR_FORMAT, err.Format());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved:
|
||||
ESP_LOGI(TAG, "Fabric will be removed");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricUpdated:
|
||||
ESP_LOGI(TAG, "Fabric is updated");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kFabricCommitted:
|
||||
ESP_LOGI(TAG, "Fabric is committed");
|
||||
break;
|
||||
|
||||
case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized:
|
||||
ESP_LOGI(TAG, "BLE deinitialized and memory reclaimed");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[],
|
||||
uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src));
|
||||
}
|
||||
ESP_LOGI(TAG, "Light received %d params in write", count);
|
||||
app_driver_handle_t light_handle = (app_driver_handle_t)priv_data;
|
||||
esp_matter_attr_val_t matter_val;
|
||||
for (int i = 0; i < count; i++) {
|
||||
const esp_rmaker_param_t *param = write_req[i].param;
|
||||
esp_rmaker_param_val_t val = write_req[i].val;
|
||||
const char *device_name = esp_rmaker_device_get_name(device);
|
||||
const char *param_name = esp_rmaker_param_get_name(param);
|
||||
if (strcmp(param_name, ESP_RMAKER_DEF_POWER_NAME) == 0) {
|
||||
ESP_LOGI(TAG, "Received value = %s for %s - %s", val.val.b ? "true" : "false", device_name, param_name);
|
||||
matter_val.type = ESP_MATTER_VAL_TYPE_BOOLEAN;
|
||||
matter_val.val.b = val.val.b;
|
||||
app_driver_attribute_update(light_handle, light_endpoint_id, OnOff::Id, OnOff::Attributes::OnOff::Id,
|
||||
&matter_val);
|
||||
} else if (strcmp(param_name, ESP_RMAKER_DEF_BRIGHTNESS_NAME) == 0) {
|
||||
ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name);
|
||||
matter_val.type = ESP_MATTER_VAL_TYPE_UINT8;
|
||||
matter_val.val.u8 = (uint8_t)(val.val.i * 254 / 100);
|
||||
app_driver_attribute_update(light_handle, light_endpoint_id, LevelControl::Id,
|
||||
LevelControl::Attributes::CurrentLevel::Id, &matter_val);
|
||||
} else if (strcmp(param_name, ESP_RMAKER_DEF_HUE_NAME) == 0) {
|
||||
ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name);
|
||||
matter_val.type = ESP_MATTER_VAL_TYPE_UINT16;
|
||||
matter_val.val.u16 = (uint16_t)(val.val.i * 254 / 360);
|
||||
app_driver_attribute_update(light_handle, light_endpoint_id, ColorControl::Id,
|
||||
ColorControl::Attributes::CurrentHue::Id, &matter_val);
|
||||
} else if (strcmp(param_name, ESP_RMAKER_DEF_SATURATION_NAME) == 0) {
|
||||
ESP_LOGI(TAG, "Received value = %d for %s - %s", val.val.i, device_name, param_name);
|
||||
matter_val.type = ESP_MATTER_VAL_TYPE_UINT16;
|
||||
matter_val.val.u16 = (uint16_t)(val.val.i * 254 / 100);
|
||||
app_driver_attribute_update(light_handle, light_endpoint_id, ColorControl::Id,
|
||||
ColorControl::Attributes::CurrentSaturation::Id, &matter_val);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Updating for %s", param_name);
|
||||
}
|
||||
esp_rmaker_param_update(param, val);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// This callback is invoked when clients interact with the Identify Cluster.
|
||||
// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light).
|
||||
static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id,
|
||||
uint8_t effect_variant, void *priv_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// This callback is called for every attribute update. The callback implementation shall
|
||||
// handle the desired attributes and return an appropriate error code. If the attribute
|
||||
// is not of your interest, please do not return an error code and strictly return ESP_OK.
|
||||
static esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
if (type == PRE_UPDATE) {
|
||||
/* Driver update */
|
||||
app_driver_handle_t driver_handle = (app_driver_handle_t)priv_data;
|
||||
err = app_driver_attribute_update(driver_handle, endpoint_id, cluster_id, attribute_id, val);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
extern "C" void app_main()
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
/* Initialize the ESP NVS layer */
|
||||
nvs_flash_init();
|
||||
|
||||
/* Initialize driver */
|
||||
app_driver_handle_t light_handle = app_driver_light_init();
|
||||
app_driver_handle_t button_handle = app_driver_button_init();
|
||||
app_reset_button_register(button_handle);
|
||||
|
||||
/* Create a Matter node and add the mandatory Root Node device type on endpoint 0 */
|
||||
node::config_t node_config;
|
||||
|
||||
// node handle can be used to add/modify other endpoints.
|
||||
node_t *node = node::create(&node_config, app_attribute_update_cb, app_identification_cb);
|
||||
ABORT_APP_ON_FAILURE(node != nullptr, ESP_LOGE(TAG, "Failed to create Matter node"));
|
||||
|
||||
extended_color_light::config_t light_config;
|
||||
light_config.on_off.on_off = DEFAULT_POWER;
|
||||
light_config.on_off.lighting.start_up_on_off = nullptr;
|
||||
light_config.level_control.current_level = DEFAULT_BRIGHTNESS;
|
||||
light_config.level_control.on_level = DEFAULT_BRIGHTNESS;
|
||||
light_config.level_control.lighting.start_up_current_level = DEFAULT_BRIGHTNESS;
|
||||
light_config.color_control.color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;
|
||||
light_config.color_control.enhanced_color_mode = (uint8_t)ColorControl::ColorMode::kColorTemperature;
|
||||
light_config.color_control.color_temperature.startup_color_temperature_mireds = nullptr;
|
||||
|
||||
// endpoint handles can be used to add/modify clusters.
|
||||
endpoint_t *endpoint = extended_color_light::create(node, &light_config, ENDPOINT_FLAG_NONE, light_handle);
|
||||
ABORT_APP_ON_FAILURE(endpoint != nullptr, ESP_LOGE(TAG, "Failed to create extended color light endpoint"));
|
||||
|
||||
light_endpoint_id = endpoint::get_id(endpoint);
|
||||
ESP_LOGI(TAG, "Light created with endpoint_id %d", light_endpoint_id);
|
||||
|
||||
/* Mark deferred persistence for some attributes that might be changed rapidly */
|
||||
cluster_t *level_control_cluster = cluster::get(endpoint, LevelControl::Id);
|
||||
attribute_t *current_level_attribute =
|
||||
attribute::get(level_control_cluster, LevelControl::Attributes::CurrentLevel::Id);
|
||||
attribute::set_deferred_persistence(current_level_attribute);
|
||||
|
||||
cluster_t *color_control_cluster = cluster::get(endpoint, ColorControl::Id);
|
||||
attribute_t *current_x_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentX::Id);
|
||||
attribute::set_deferred_persistence(current_x_attribute);
|
||||
attribute_t *current_y_attribute = attribute::get(color_control_cluster, ColorControl::Attributes::CurrentY::Id);
|
||||
attribute::set_deferred_persistence(current_y_attribute);
|
||||
attribute_t *color_temp_attribute =
|
||||
attribute::get(color_control_cluster, ColorControl::Attributes::ColorTemperatureMireds::Id);
|
||||
attribute::set_deferred_persistence(color_temp_attribute);
|
||||
|
||||
err = esp_event_loop_create_default();
|
||||
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error create default event loop");
|
||||
return;
|
||||
}
|
||||
app_wifi_init();
|
||||
esp_rmaker_config_t rainmaker_cfg = {
|
||||
.enable_time_sync = false,
|
||||
};
|
||||
esp_rmaker_node_t *rmaker_node = esp_rmaker_node_init(&rainmaker_cfg, "ESP RainMaker Device", "Lightbulb");
|
||||
if (!rmaker_node) {
|
||||
ESP_LOGE(TAG, "Could not initialise node. Aborting!!!");
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
abort();
|
||||
}
|
||||
|
||||
light_device = esp_rmaker_lightbulb_device_create("Light", light_handle, DEFAULT_POWER);
|
||||
esp_rmaker_device_add_bulk_cb(light_device, bulk_write_cb, NULL);
|
||||
|
||||
esp_rmaker_device_add_param(light_device,
|
||||
esp_rmaker_brightness_param_create(ESP_RMAKER_DEF_BRIGHTNESS_NAME, DEFAULT_BRIGHTNESS));
|
||||
esp_rmaker_device_add_param(light_device, esp_rmaker_hue_param_create(ESP_RMAKER_DEF_HUE_NAME, DEFAULT_HUE));
|
||||
esp_rmaker_device_add_param(light_device,
|
||||
esp_rmaker_saturation_param_create(ESP_RMAKER_DEF_SATURATION_NAME, DEFAULT_SATURATION));
|
||||
|
||||
esp_rmaker_node_add_device(rmaker_node, light_device);
|
||||
|
||||
esp_rmaker_ota_enable_default();
|
||||
|
||||
esp_rmaker_timezone_service_enable();
|
||||
|
||||
esp_rmaker_schedule_enable();
|
||||
|
||||
err = app_wifi_set_custom_mfg_data(MGF_DATA_DEVICE_TYPE_LIGHT, MFG_DATA_DEVICE_SUBTYPE_LIGHT);
|
||||
|
||||
err = app_wifi_start(POP_TYPE_MAC);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not start Wifi. Aborting!!!");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Matter start */
|
||||
err = esp_matter::start(app_event_cb);
|
||||
ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to start Matter, err:%d", err));
|
||||
|
||||
/* Starting driver with default values */
|
||||
app_driver_light_set_defaults(light_endpoint_id);
|
||||
|
||||
#if CONFIG_ENABLE_ENCRYPTED_OTA
|
||||
err = esp_matter_ota_requestor_encrypted_init(s_decryption_key, s_decryption_key_len);
|
||||
ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to initialized the encrypted OTA, err: %d", err));
|
||||
#endif // CONFIG_ENABLE_ENCRYPTED_OTA
|
||||
if (esp_rmaker_user_node_mapping_get_state() == ESP_RMAKER_USER_MAPPING_DONE) {
|
||||
chip::DeviceLayer::Internal::BLEMgr().Shutdown();
|
||||
}
|
||||
|
||||
#if CONFIG_ENABLE_CHIP_SHELL
|
||||
esp_matter::console::diagnostics_register_commands();
|
||||
esp_matter::console::wifi_register_commands();
|
||||
esp_matter::console::init();
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <esp_matter.h>
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
||||
#include "esp_openthread_types.h"
|
||||
#endif
|
||||
|
||||
/** Standard max values (used for remapping attributes) */
|
||||
#define STANDARD_BRIGHTNESS 255
|
||||
#define STANDARD_HUE 360
|
||||
#define STANDARD_SATURATION 255
|
||||
#define STANDARD_TEMPERATURE_FACTOR 1000000
|
||||
|
||||
/** Matter max values (used for remapping attributes) */
|
||||
#define MATTER_BRIGHTNESS 254
|
||||
#define MATTER_HUE 254
|
||||
#define MATTER_SATURATION 254
|
||||
#define MATTER_TEMPERATURE_FACTOR 1000000
|
||||
|
||||
/** Default attribute values used during initialization */
|
||||
#define DEFAULT_POWER true
|
||||
#define DEFAULT_BRIGHTNESS 64
|
||||
#define DEFAULT_HUE 128
|
||||
#define DEFAULT_SATURATION 254
|
||||
|
||||
typedef void *app_driver_handle_t;
|
||||
|
||||
/** Initialize the light driver
|
||||
*
|
||||
* This initializes the light driver associated with the selected board.
|
||||
*
|
||||
* @return Handle on success.
|
||||
* @return NULL in case of failure.
|
||||
*/
|
||||
app_driver_handle_t app_driver_light_init();
|
||||
|
||||
/** Initialize the button driver
|
||||
*
|
||||
* This initializes the button driver associated with the selected board.
|
||||
*
|
||||
* @return Handle on success.
|
||||
* @return NULL in case of failure.
|
||||
*/
|
||||
app_driver_handle_t app_driver_button_init();
|
||||
|
||||
/** Driver Update
|
||||
*
|
||||
* This API should be called to update the driver for the attribute being updated.
|
||||
* This is usually called from the common `app_attribute_update_cb()`.
|
||||
*
|
||||
* @param[in] endpoint_id Endpoint ID of the attribute.
|
||||
* @param[in] cluster_id Cluster ID of the attribute.
|
||||
* @param[in] attribute_id Attribute ID of the attribute.
|
||||
* @param[in] val Pointer to `esp_matter_attr_val_t`. Use appropriate elements as per the value type.
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
|
||||
uint32_t attribute_id, esp_matter_attr_val_t *val);
|
||||
|
||||
/** Set defaults for light driver
|
||||
*
|
||||
* Set the attribute drivers to their default values from the created data model.
|
||||
*
|
||||
* @param[in] endpoint_id Endpoint ID of the driver.
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t app_driver_light_set_defaults(uint16_t endpoint_id);
|
||||
|
||||
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
|
||||
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
|
||||
{ \
|
||||
.radio_mode = RADIO_MODE_NATIVE, \
|
||||
}
|
||||
|
||||
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
|
||||
{ \
|
||||
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
|
||||
}
|
||||
|
||||
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
|
||||
{ \
|
||||
.storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <esp_event.h>
|
||||
#include <esp_idf_version.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_rmaker_utils.h>
|
||||
#include <esp_wifi.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/event_groups.h>
|
||||
#include <freertos/task.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <esp_netif.h>
|
||||
#include <wifi_prov_scheme_matter_ble.h>
|
||||
#include <wifi_provisioning/manager.h>
|
||||
|
||||
#include <app_wifi.h>
|
||||
#include <esp_rmaker_core.h>
|
||||
#include <esp_timer.h>
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <platform/CHIPDeviceLayer.h>
|
||||
#include <platform/ESP32_custom/PlatformManagerImpl.h>
|
||||
#include <platform/PlatformManager.h>
|
||||
#include <qrcode.h>
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(APP_WIFI_EVENT);
|
||||
|
||||
static const char *TAG = "app_wifi";
|
||||
|
||||
#define PROV_QR_VERSION "v1"
|
||||
|
||||
#define PROV_TRANSPORT_BLE "ble"
|
||||
#define QRCODE_BASE_URL "https://rainmaker.espressif.com/qrcode.html"
|
||||
|
||||
#define CREDENTIALS_NAMESPACE "rmaker_creds"
|
||||
#define RANDOM_NVS_KEY "random"
|
||||
|
||||
#define POP_STR_SIZE 9
|
||||
static esp_timer_handle_t prov_stop_timer;
|
||||
/* Timeout period in minutes */
|
||||
#define APP_WIFI_PROV_TIMEOUT_PERIOD 30
|
||||
/* Autofetch period in micro-seconds */
|
||||
static uint64_t prov_timeout_period = (APP_WIFI_PROV_TIMEOUT_PERIOD * 60 * 1000000LL);
|
||||
|
||||
#define APP_PROV_STOP_ON_CREDS_MISMATCH
|
||||
|
||||
#define ESP_RAINMAKER_GITHUB_EXAMPLES_PATH "https://github.com/espressif/esp-rainmaker/blob/master/examples"
|
||||
#define ESP_RAINMAKER_INTRO_LINK "https://rainmaker.espressif.com"
|
||||
#define ESP_RMAKER_PHONE_APP_LINK "http://bit.ly/esp-rmaker"
|
||||
char esp_rainmaker_ascii_art[] =
|
||||
" ______ _____ _____ _____ _____ _ _ __ __ _ ________ _____\n"
|
||||
" | ____|/ ____| __ \\ | __ \\ /\\ |_ _| \\ | | \\/ | /\\ | |/ / ____| __ \\\n"
|
||||
" | |__ | (___ | |__) | | |__) | / \\ | | | \\| | \\ / | / \\ | ' /| |__ | |__) |\n"
|
||||
" | __| \\___ \\| ___/ | _ / / /\\ \\ | | | . ` | |\\/| | / /\\ \\ | < | __| | _ /\n"
|
||||
" | |____ ____) | | | | \\ \\ / ____ \\ _| |_| |\\ | | | |/ ____ \\| . \\| |____| | \\ \\\n"
|
||||
" |______|_____/|_| |_| \\_\\/_/ \\_\\_____|_| \\_|_| |_/_/ \\_\\_|\\_\\______|_| \\_\\\n";
|
||||
|
||||
static uint8_t *custom_mfg_data = NULL;
|
||||
static size_t custom_mfg_data_len = 0;
|
||||
|
||||
esp_err_t app_wifi_set_custom_mfg_data(uint16_t device_type, uint8_t device_subtype)
|
||||
{
|
||||
int8_t mfg_data[] = {(int8_t)MFG_DATA_HEADER, MGF_DATA_APP_ID, MFG_DATA_VERSION, MFG_DATA_CUSTOMER_ID};
|
||||
size_t mfg_data_len = sizeof(mfg_data) + 4; // 4 bytes of device type, subtype, and extra-code
|
||||
custom_mfg_data = (uint8_t *)MEM_ALLOC_EXTRAM(mfg_data_len);
|
||||
if (custom_mfg_data == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory to custom mfg data");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(custom_mfg_data, mfg_data, sizeof(mfg_data));
|
||||
custom_mfg_data[8] = 0xff & (device_type >> 8);
|
||||
custom_mfg_data[9] = 0xff & device_type;
|
||||
custom_mfg_data[10] = device_subtype;
|
||||
custom_mfg_data[11] = 0;
|
||||
custom_mfg_data_len = mfg_data_len;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t qrcode_display(const char *text)
|
||||
{
|
||||
#define MAX_QRCODE_VERSION 5
|
||||
esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT();
|
||||
cfg.max_qrcode_version = MAX_QRCODE_VERSION;
|
||||
return esp_qrcode_generate(&cfg, text);
|
||||
}
|
||||
|
||||
static void app_wifi_print_qr(const char *name, const char *pop, const char *transport)
|
||||
{
|
||||
if (!name || !transport) {
|
||||
ESP_LOGW(TAG, "Cannot generate QR code payload. Data missing.");
|
||||
return;
|
||||
}
|
||||
char payload[150];
|
||||
if (pop) {
|
||||
snprintf(payload, sizeof(payload),
|
||||
"{\"ver\":\"%s\",\"name\":\"%s\""
|
||||
",\"pop\":\"%s\",\"transport\":\"%s\"}",
|
||||
PROV_QR_VERSION, name, pop, transport);
|
||||
} else {
|
||||
snprintf(payload, sizeof(payload),
|
||||
"{\"ver\":\"%s\",\"name\":\"%s\""
|
||||
",\"transport\":\"%s\"}",
|
||||
PROV_QR_VERSION, name, transport);
|
||||
}
|
||||
ESP_LOGI(TAG, "Scan this QR code from the ESP RainMaker phone app for Provisioning.");
|
||||
qrcode_display(payload);
|
||||
ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL,
|
||||
payload);
|
||||
esp_event_post(APP_WIFI_EVENT, APP_WIFI_EVENT_QR_DISPLAY, payload, strlen(payload) + 1, portMAX_DELAY);
|
||||
}
|
||||
|
||||
/* Event handler for catching system events */
|
||||
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
|
||||
{
|
||||
static int retries = 0;
|
||||
static int failed_cnt = 0;
|
||||
|
||||
if (event_base == WIFI_PROV_EVENT) {
|
||||
switch (event_id) {
|
||||
case WIFI_PROV_START:
|
||||
ESP_LOGI(TAG, "Provisioning started");
|
||||
break;
|
||||
case WIFI_PROV_CRED_RECV: {
|
||||
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data;
|
||||
ESP_LOGI(TAG,
|
||||
"Received Wi-Fi credentials"
|
||||
"\n\tSSID : %s\n\tPassword : %s",
|
||||
(const char *)wifi_sta_cfg->ssid, (const char *)wifi_sta_cfg->password);
|
||||
break;
|
||||
}
|
||||
case WIFI_PROV_CRED_FAIL: {
|
||||
wifi_prov_sta_fail_reason_t *reason = (wifi_prov_sta_fail_reason_t *)event_data;
|
||||
ESP_LOGE(TAG,
|
||||
"Provisioning failed!\n\tReason : %s"
|
||||
"\n\tPlease reset to factory and retry provisioning",
|
||||
(*reason == WIFI_PROV_STA_AUTH_ERROR) ? "Wi-Fi station authentication failed"
|
||||
: "Wi-Fi access-point not found");
|
||||
retries++;
|
||||
if (retries >= 5) {
|
||||
ESP_LOGI(TAG, "Failed to connect with provisioned AP, reseting provisioned credentials");
|
||||
wifi_prov_mgr_reset_sm_state_on_failure();
|
||||
esp_event_post(APP_WIFI_EVENT, APP_WIFI_EVENT_PROV_RESTART, NULL, 0, portMAX_DELAY);
|
||||
ESP_LOGW(TAG, "Failed to connect with provisioned AP, please reset to provisioning manually");
|
||||
retries = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WIFI_PROV_CRED_SUCCESS:
|
||||
ESP_LOGI(TAG, "Provisioning successful");
|
||||
retries = 0;
|
||||
break;
|
||||
case WIFI_PROV_END:
|
||||
if (prov_stop_timer) {
|
||||
esp_timer_stop(prov_stop_timer);
|
||||
esp_timer_delete(prov_stop_timer);
|
||||
prov_stop_timer = NULL;
|
||||
}
|
||||
/* De-initialize manager once provisioning is finished */
|
||||
wifi_prov_mgr_deinit();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (event_base == PROTOCOMM_SECURITY_SESSION_EVENT) {
|
||||
switch (event_id) {
|
||||
case PROTOCOMM_SECURITY_SESSION_SETUP_OK:
|
||||
ESP_LOGI(TAG, "Secured session established!");
|
||||
esp_rmaker_start();
|
||||
break;
|
||||
case PROTOCOMM_SECURITY_SESSION_INVALID_SECURITY_PARAMS:
|
||||
/* fall-through */
|
||||
case PROTOCOMM_SECURITY_SESSION_CREDENTIALS_MISMATCH:
|
||||
ESP_LOGE(TAG, "Received incorrect PoP or invalid security params! event: %d", (int)event_id);
|
||||
if (++failed_cnt >= 5) {
|
||||
/* stop provisioning for security reasons */
|
||||
wifi_prov_mgr_stop_provisioning();
|
||||
ESP_LOGW(TAG,
|
||||
"Max PoP attempts reached! Provisioning disabled for security reasons. Please reboot device "
|
||||
"to restart provisioning");
|
||||
esp_event_post(APP_WIFI_EVENT, APP_WIFI_EVENT_PROV_CRED_MISMATCH, NULL, 0, portMAX_DELAY);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
ESP_LOGI(TAG, "Disconnected. Connecting to the AP again...");
|
||||
esp_wifi_connect();
|
||||
}
|
||||
}
|
||||
|
||||
/* Free random_bytes after use only if function returns ESP_OK */
|
||||
static esp_err_t read_random_bytes_from_nvs(uint8_t **random_bytes, size_t *len)
|
||||
{
|
||||
nvs_handle handle;
|
||||
esp_err_t err;
|
||||
*len = 0;
|
||||
|
||||
if ((err = nvs_open_from_partition(CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME, CREDENTIALS_NAMESPACE, NVS_READONLY,
|
||||
&handle)) != ESP_OK) {
|
||||
ESP_LOGD(TAG, "NVS open for %s %s %s failed with error %d", CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME,
|
||||
CREDENTIALS_NAMESPACE, RANDOM_NVS_KEY, err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if ((err = nvs_get_blob(handle, RANDOM_NVS_KEY, NULL, len)) != ESP_OK) {
|
||||
ESP_LOGD(TAG, "Error %d. Failed to read key %s.", err, RANDOM_NVS_KEY);
|
||||
nvs_close(handle);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
*random_bytes = (uint8_t *)calloc(*len, 1);
|
||||
if (*random_bytes) {
|
||||
nvs_get_blob(handle, RANDOM_NVS_KEY, *random_bytes, len);
|
||||
nvs_close(handle);
|
||||
return ESP_OK;
|
||||
}
|
||||
nvs_close(handle);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
static char *custom_pop;
|
||||
esp_err_t app_wifi_set_custom_pop(const char *pop)
|
||||
{
|
||||
/* NULL PoP is not allowed here. Use POP_TYPE_NONE instead. */
|
||||
if (!pop) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Freeing up the PoP in case it is already allocated */
|
||||
if (custom_pop) {
|
||||
free(custom_pop);
|
||||
custom_pop = NULL;
|
||||
}
|
||||
|
||||
custom_pop = strdup(pop);
|
||||
if (!custom_pop) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t get_device_service_name(char *service_name, size_t max)
|
||||
{
|
||||
uint8_t *nvs_random = NULL;
|
||||
const char *ssid_prefix = "PROV";
|
||||
size_t nvs_random_size = 0;
|
||||
if ((read_random_bytes_from_nvs(&nvs_random, &nvs_random_size) != ESP_OK) || nvs_random_size < 3) {
|
||||
uint8_t eth_mac[6];
|
||||
esp_wifi_get_mac(WIFI_IF_STA, eth_mac);
|
||||
snprintf(service_name, max, "%s_%02x%02x%02x", ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]);
|
||||
} else {
|
||||
snprintf(service_name, max, "%s_%02x%02x%02x", ssid_prefix, nvs_random[nvs_random_size - 3],
|
||||
nvs_random[nvs_random_size - 2], nvs_random[nvs_random_size - 1]);
|
||||
}
|
||||
if (nvs_random) {
|
||||
free(nvs_random);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static char *get_device_pop(app_wifi_pop_type_t pop_type)
|
||||
{
|
||||
if (pop_type == POP_TYPE_NONE) {
|
||||
return NULL;
|
||||
} else if (pop_type == POP_TYPE_CUSTOM) {
|
||||
if (!custom_pop) {
|
||||
ESP_LOGE(TAG, "Custom PoP not set. Please use app_wifi_set_custom_pop().");
|
||||
return NULL;
|
||||
}
|
||||
return strdup(custom_pop);
|
||||
}
|
||||
char *pop = (char *)calloc(1, POP_STR_SIZE);
|
||||
if (!pop) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for PoP.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pop_type == POP_TYPE_MAC) {
|
||||
uint8_t eth_mac[6];
|
||||
esp_err_t err = esp_wifi_get_mac(WIFI_IF_STA, eth_mac);
|
||||
if (err == ESP_OK) {
|
||||
snprintf(pop, POP_STR_SIZE, "%02x%02x%02x%02x", eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]);
|
||||
return pop;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to get MAC address to generate PoP.");
|
||||
goto pop_err;
|
||||
}
|
||||
} else if (pop_type == POP_TYPE_RANDOM) {
|
||||
uint8_t *nvs_random = NULL;
|
||||
size_t nvs_random_size = 0;
|
||||
if ((read_random_bytes_from_nvs(&nvs_random, &nvs_random_size) != ESP_OK) || nvs_random_size < 4) {
|
||||
ESP_LOGE(TAG, "Failed to read random bytes from NVS to generate PoP.");
|
||||
if (nvs_random) {
|
||||
free(nvs_random);
|
||||
}
|
||||
goto pop_err;
|
||||
} else {
|
||||
snprintf(pop, POP_STR_SIZE, "%02x%02x%02x%02x", nvs_random[0], nvs_random[1], nvs_random[2], nvs_random[3]);
|
||||
free(nvs_random);
|
||||
return pop;
|
||||
}
|
||||
}
|
||||
pop_err:
|
||||
free(pop);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void app_wifi_init(void)
|
||||
{
|
||||
wifi_init_config_t cfg;
|
||||
esp_err_t err = esp_netif_init();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize esp_netif");
|
||||
return;
|
||||
}
|
||||
|
||||
// Lets not create a default station interface if already present
|
||||
if (!esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")) {
|
||||
if (!esp_netif_create_default_wifi_sta()) {
|
||||
ESP_LOGE(TAG, "Failed to create the WiFi STA netif");
|
||||
return;
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the ESP WiFi layer.
|
||||
cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
err = esp_wifi_init(&cfg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize esp_wifi");
|
||||
return;
|
||||
}
|
||||
/* Register our event handler for Wi-Fi, IP and Provisioning related events */
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||
#ifdef APP_PROV_STOP_ON_CREDS_MISMATCH
|
||||
ESP_ERROR_CHECK(
|
||||
esp_event_handler_register(PROTOCOMM_SECURITY_SESSION_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||
#endif
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
|
||||
}
|
||||
|
||||
static void app_wifi_prov_stop(void *priv)
|
||||
{
|
||||
ESP_LOGW(TAG, "Provisioning timed out. Please reboot device to restart provisioning.");
|
||||
wifi_prov_mgr_stop_provisioning();
|
||||
esp_event_post(APP_WIFI_EVENT, APP_WIFI_EVENT_PROV_TIMEOUT, NULL, 0, portMAX_DELAY);
|
||||
}
|
||||
|
||||
esp_err_t app_wifi_start_timer(void)
|
||||
{
|
||||
if (prov_timeout_period == 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
esp_timer_create_args_t prov_stop_timer_conf = {.callback = app_wifi_prov_stop,
|
||||
.arg = NULL,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "app_wifi_prov_stop_tm"};
|
||||
if (esp_timer_create(&prov_stop_timer_conf, &prov_stop_timer) == ESP_OK) {
|
||||
esp_timer_start_once(prov_stop_timer, prov_timeout_period);
|
||||
ESP_LOGI(TAG, "Provisioning will auto stop after %d minute(s).", APP_WIFI_PROV_TIMEOUT_PERIOD);
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to create Provisioning auto stop timer.");
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t app_wifi_start(app_wifi_pop_type_t pop_type)
|
||||
{
|
||||
/* Configuration for the provisioning manager */
|
||||
wifi_prov_mgr_config_t config = {
|
||||
.scheme = wifi_prov_scheme_matter_ble,
|
||||
|
||||
/* Any default scheme specific event handler that you would
|
||||
* like to choose. Since our example application requires
|
||||
* neither BT nor BLE, we can choose to release the associated
|
||||
* memory once provisioning is complete, or not needed
|
||||
* (in case when device is already provisioned). Choosing
|
||||
* appropriate scheme specific event handler allows the manager
|
||||
* to take care of this automatically. This can be set to
|
||||
* WIFI_PROV_EVENT_HANDLER_NONE when using wifi_prov_scheme_softap*/
|
||||
.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE,
|
||||
};
|
||||
|
||||
/* Initialize provisioning manager with the
|
||||
* configuration parameters set above */
|
||||
ESP_ERROR_CHECK(wifi_prov_mgr_init(config));
|
||||
|
||||
bool provisioned = false;
|
||||
/* Let's find out if the device is provisioned */
|
||||
wifi_prov_mgr_is_provisioned(&provisioned);
|
||||
/* If device is not yet provisioned start provisioning service */
|
||||
if (!provisioned) {
|
||||
ESP_LOGI(TAG, "Starting provisioning");
|
||||
|
||||
/* What is the Device Service Name that we want
|
||||
* This translates to :
|
||||
* - Wi-Fi SSID when scheme is wifi_prov_scheme_softap
|
||||
* - device name when scheme is wifi_prov_scheme_ble
|
||||
*/
|
||||
char service_name[12];
|
||||
get_device_service_name(service_name, sizeof(service_name));
|
||||
|
||||
/* What is the service key (Wi-Fi password)
|
||||
* NULL = Open network
|
||||
* This is ignored when scheme is wifi_prov_scheme_ble
|
||||
*/
|
||||
const char *service_key = NULL;
|
||||
|
||||
/* What is the security level that we want (0 or 1):
|
||||
* - WIFI_PROV_SECURITY_0 is simply plain text communication.
|
||||
* - WIFI_PROV_SECURITY_1 is secure communication which consists of secure handshake
|
||||
* using X25519 key exchange and proof of possession (pop) and AES-CTR
|
||||
* for encryption/decryption of messages.
|
||||
*/
|
||||
wifi_prov_security_t security = WIFI_PROV_SECURITY_1;
|
||||
|
||||
/* Do we want a proof-of-possession (ignored if Security 0 is selected):
|
||||
* - this should be a string with length > 0
|
||||
* - NULL if not used
|
||||
*/
|
||||
char *pop = get_device_pop(pop_type);
|
||||
if ((pop_type != POP_TYPE_NONE) && (pop == NULL)) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
/* This step is only useful when scheme is wifi_prov_scheme_ble. This will
|
||||
* set a custom 128 bit UUID which will be included in the BLE advertisement
|
||||
* and will correspond to the primary GATT service that provides provisioning
|
||||
* endpoints as GATT characteristics. Each GATT characteristic will be
|
||||
* formed using the primary service UUID as base, with different auto assigned
|
||||
* 12th and 13th bytes (assume counting starts from 0th byte). The client side
|
||||
* applications must identify the endpoints by reading the User Characteristic
|
||||
* Description descriptor (0x2901) for each characteristic, which contains the
|
||||
* endpoint name of the characteristic */
|
||||
uint8_t custom_service_uuid[] = {
|
||||
/* This is a random uuid. This can be modified if you want to change the BLE uuid. */
|
||||
/* 12th and 13th bit will be replaced by internal bits. */
|
||||
0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02,
|
||||
};
|
||||
esp_err_t err = wifi_prov_scheme_matter_ble_set_service_uuid(custom_service_uuid, sizeof(custom_service_uuid));
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "wifi_prov_scheme_ble_set_service_uuid failed %d", err);
|
||||
return err;
|
||||
}
|
||||
if (custom_mfg_data) {
|
||||
err = wifi_prov_scheme_matter_ble_set_mfg_data(custom_mfg_data, custom_mfg_data_len);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set mfg data, err=0x%x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Start provisioning service */
|
||||
ESP_ERROR_CHECK(wifi_prov_mgr_start_provisioning(security, pop, service_name, service_key));
|
||||
/* Print QR code for provisioning */
|
||||
app_wifi_print_qr(service_name, pop, PROV_TRANSPORT_BLE);
|
||||
ESP_LOGI(TAG, "Provisioning Started. Name : %s, POP : %s", service_name, pop ? pop : "<null>");
|
||||
if (pop) {
|
||||
free(pop);
|
||||
}
|
||||
app_wifi_start_timer();
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Already provisioned, starting Wi-Fi STA");
|
||||
/* We don't need the manager as device is already provisioned,
|
||||
* so let's release it's resources */
|
||||
wifi_prov_mgr_deinit();
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
esp_wifi_connect();
|
||||
esp_rmaker_start();
|
||||
}
|
||||
if (custom_mfg_data) {
|
||||
free(custom_mfg_data);
|
||||
custom_mfg_data = NULL;
|
||||
custom_mfg_data_len = 0;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#pragma once
|
||||
#include <esp_err.h>
|
||||
#include <esp_event.h>
|
||||
|
||||
|
||||
#define MFG_DATA_HEADER 0xe5, 0x02
|
||||
#define MGF_DATA_APP_ID 'N', 'o', 'v'
|
||||
#define MFG_DATA_VERSION 'a'
|
||||
#define MFG_DATA_CUSTOMER_ID 0x00, 0x01
|
||||
|
||||
#define MGF_DATA_DEVICE_TYPE_LIGHT 0x0005
|
||||
#define MGF_DATA_DEVICE_TYPE_SWITCH 0x0080
|
||||
|
||||
#define MFG_DATA_DEVICE_SUBTYPE_SWITCH 0x01
|
||||
#define MFG_DATA_DEVICE_SUBTYPE_LIGHT 0x01
|
||||
|
||||
#define MFG_DATA_DEVICE_EXTRA_CODE 0x00
|
||||
|
||||
/** ESP RainMaker Event Base */
|
||||
ESP_EVENT_DECLARE_BASE(APP_WIFI_EVENT);
|
||||
|
||||
/** App Wi-Fir Events */
|
||||
typedef enum {
|
||||
/** QR code available for display. Associated data is the NULL terminated QR payload. */
|
||||
APP_WIFI_EVENT_QR_DISPLAY = 1,
|
||||
/** Provisioning timed out */
|
||||
APP_WIFI_EVENT_PROV_TIMEOUT,
|
||||
/** Provisioning has restarted due to failures (Invalid SSID/Passphrase) */
|
||||
APP_WIFI_EVENT_PROV_RESTART,
|
||||
/** Provisioning closed due to invalid credentials */
|
||||
APP_WIFI_EVENT_PROV_CRED_MISMATCH,
|
||||
} app_wifi_event_t;
|
||||
|
||||
/** Types of Proof of Possession */
|
||||
typedef enum {
|
||||
/** Use MAC address to generate PoP */
|
||||
POP_TYPE_MAC,
|
||||
/** Use random stream generated and stored in fctry partition during claiming process as PoP */
|
||||
POP_TYPE_RANDOM,
|
||||
/** Do not use any PoP.
|
||||
* Use this option with caution. Consider using `CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD` with this.
|
||||
*/
|
||||
POP_TYPE_NONE,
|
||||
/** Use a custom PoP.
|
||||
* Set a custom PoP using app_wifi_set_custom_pop() first.
|
||||
*/
|
||||
POP_TYPE_CUSTOM
|
||||
} app_wifi_pop_type_t;
|
||||
|
||||
/** Initialize Wi-Fi
|
||||
*
|
||||
* This initializes Wi-Fi and the Wi-Fi provisioning manager
|
||||
*/
|
||||
void app_wifi_init();
|
||||
|
||||
/** Start Wi-Fi
|
||||
*
|
||||
* This will start provisioning if the node is not provisioned and will connect to Wi-Fi
|
||||
* if node is provisioned. Function will return successfully only after Wi-Fi is connect
|
||||
*
|
||||
* @param[in] pop_type The type for Proof of Possession (PoP) pin
|
||||
*
|
||||
* @return ESP_OK on success (Wi-Fi connected).
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t app_wifi_start(app_wifi_pop_type_t pop_type);
|
||||
|
||||
/** Set custom manufacturing data
|
||||
*
|
||||
* This can be used to add some custom manufacturing data in BLE advertisements during
|
||||
* provisioning. This can be used by apps to filter the scanned BLE devices and show
|
||||
* only the relevant one. Supported by Nova Home app for light and switch
|
||||
*
|
||||
* @param[in] device_type Type of the device, like light or switch
|
||||
* @param[in] device_subtype Sub Type of the device (application specific)
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t app_wifi_set_custom_mfg_data(uint16_t device_type, uint8_t device_subtype);
|
||||
|
||||
/** Set custom PoP
|
||||
*
|
||||
* This can be used to set a custom Proof of Possession (PoP) pin for provisioning.
|
||||
* Applicable only if POP_TYPE_CUSTOM is used for app_wifi_start().
|
||||
*
|
||||
* @param[in] pop A NULL terminated PoP string (typically 8 characters alphanumeric)
|
||||
*
|
||||
* @return ESP_OK on success.
|
||||
* @return error in case of failure.
|
||||
*/
|
||||
esp_err_t app_wifi_set_custom_pop(const char *pop);
|
||||
@@ -0,0 +1,7 @@
|
||||
dependencies:
|
||||
esp_bsp_generic:
|
||||
version: "^1.1.0"
|
||||
espressif/esp_rainmaker:
|
||||
version: "1.3.0"
|
||||
espressif/qrcode:
|
||||
version: "^0.1.0~2"
|
||||
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <platform/internal/CHIPDeviceLayerInternal.h>
|
||||
#include <platform/CHIPDeviceConfig.h>
|
||||
#include <ble/CHIPBleServiceData.h>
|
||||
#include <platform/internal/BLEManager.h>
|
||||
#include <esp_err.h>
|
||||
#include <host/ble_gap.h>
|
||||
#include <host/ble_gatt.h>
|
||||
#include <host/ble_uuid.h>
|
||||
#include <protocomm.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "protocomm_matter_ble.h"
|
||||
#include "esp_cpu.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT);
|
||||
|
||||
int ble_uuid_flat(const ble_uuid_t *, void *);
|
||||
|
||||
typedef struct {
|
||||
protocomm_t *pc_matter_ble;
|
||||
uint8_t ble_uuid_base[BLE_UUID128_VAL_LENGTH];
|
||||
protocomm_matter_ble_name_uuid_t *g_name_uuid_array;
|
||||
ssize_t g_name_uuid_array_len;
|
||||
uint16_t gatt_mtu;
|
||||
unsigned ble_link_encryption:1;
|
||||
} _protocomm_matter_ble_internal_t;
|
||||
|
||||
static _protocomm_matter_ble_internal_t *protoble_internal = nullptr;
|
||||
struct ble_gatt_svc_def *s_gatt_db = nullptr;
|
||||
|
||||
#define BLE_GATT_UUID_CHAR_DSC 0x2901
|
||||
#define TAG "protocomm_matter_ble"
|
||||
|
||||
struct data_mbuf {
|
||||
SLIST_ENTRY(data_mbuf) node;
|
||||
uint8_t *outbuf;
|
||||
ssize_t outlen;
|
||||
uint16_t attr_handle;
|
||||
};
|
||||
|
||||
static SLIST_HEAD(data_mbuf_head, data_mbuf) data_mbuf_list =
|
||||
SLIST_HEAD_INITIALIZER(data_mbuf_list);
|
||||
|
||||
static struct data_mbuf *find_attr_with_handle(uint16_t attr_handle)
|
||||
{
|
||||
struct data_mbuf *cur;
|
||||
SLIST_FOREACH(cur, &data_mbuf_list, node) {
|
||||
if (cur->attr_handle == attr_handle) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void free_gatt_ble_misc_memory(struct ble_gatt_svc_def * svc_def)
|
||||
{
|
||||
if (svc_def) {
|
||||
if (svc_def->characteristics) {
|
||||
for (int i = 0; i < protoble_internal->g_name_uuid_array_len; ++i) {
|
||||
if (svc_def->characteristics[i].descriptors) {
|
||||
free((void *)svc_def->characteristics[i].descriptors->uuid);
|
||||
free(svc_def->characteristics[i].descriptors);
|
||||
}
|
||||
free((void *)svc_def->characteristics[i].uuid);
|
||||
}
|
||||
free((void *)svc_def->characteristics);
|
||||
}
|
||||
if (svc_def->uuid) {
|
||||
free((void *)svc_def->uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void protocomm_matter_ble_cleanup()
|
||||
{
|
||||
if (protoble_internal) {
|
||||
if (protoble_internal->g_name_uuid_array) {
|
||||
for (unsigned i = 0; i < protoble_internal->g_name_uuid_array_len; ++i) {
|
||||
if (protoble_internal->g_name_uuid_array[i].name) {
|
||||
free((void *)protoble_internal->g_name_uuid_array[i].name);
|
||||
}
|
||||
}
|
||||
free(protoble_internal->g_name_uuid_array);
|
||||
}
|
||||
free(protoble_internal);
|
||||
protoble_internal = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ble_gatt_add_primary_svcs(struct ble_gatt_svc_def *gatt_db_svc, int char_count)
|
||||
{
|
||||
gatt_db_svc->type = BLE_GATT_SVC_TYPE_PRIMARY;
|
||||
gatt_db_svc->characteristics =
|
||||
(struct ble_gatt_chr_def *) calloc((char_count + 1), sizeof(struct ble_gatt_chr_def));
|
||||
if (!gatt_db_svc->characteristics) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const char *uuid128_to_handler(uint8_t *uuid)
|
||||
{
|
||||
uint8_t *uuid16 = uuid + 12;
|
||||
for (int i = 0; i < protoble_internal->g_name_uuid_array_len; i++) {
|
||||
if (protoble_internal->g_name_uuid_array[i].uuid == *(uint16_t *)uuid16) {
|
||||
ESP_LOGD(TAG, "UUID (0x%x) matched with proto-name = %s", *uuid16, protoble_internal->g_name_uuid_array[i].name);
|
||||
return protoble_internal->g_name_uuid_array[i].name;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int matter_ble_gatts_get_attr_value(uint16_t attr_handle, ssize_t *outlen, uint8_t **outbuf)
|
||||
{
|
||||
struct data_mbuf *attr_mbuf = find_attr_with_handle(attr_handle);
|
||||
if (!attr_mbuf) {
|
||||
ESP_LOGE(TAG, "Outbuf with handle %d not found", attr_handle);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
*outbuf = attr_mbuf->outbuf;
|
||||
*outlen = attr_mbuf->outlen;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int matter_ble_gatts_set_attr_value(uint16_t attr_handle, ssize_t outlen, uint8_t *outbuf)
|
||||
{
|
||||
struct data_mbuf *attr_mbuf = find_attr_with_handle(attr_handle);
|
||||
if (!attr_mbuf) {
|
||||
attr_mbuf = (struct data_mbuf *)calloc(1, sizeof(struct data_mbuf));
|
||||
if (!attr_mbuf) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for storing outbuf and outlen");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
SLIST_INSERT_HEAD(&data_mbuf_list, attr_mbuf, node);
|
||||
attr_mbuf->attr_handle = attr_handle;
|
||||
} else {
|
||||
free(attr_mbuf->outbuf);
|
||||
}
|
||||
attr_mbuf->outbuf = outbuf;
|
||||
attr_mbuf->outlen = outlen;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static int matter_ble_gatt_svr_chr_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
int rc = 0;
|
||||
esp_err_t err;
|
||||
char buf[BLE_UUID_STR_LEN] = { 0 };
|
||||
ssize_t temp_outlen = 0;
|
||||
uint8_t *temp_outbuf = nullptr;
|
||||
uint8_t *uuid = nullptr;
|
||||
uint8_t *data_buf = nullptr;
|
||||
uint16_t data_len = 0;
|
||||
uint16_t data_buf_len = 0;
|
||||
switch (ctxt->op) {
|
||||
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||
ESP_LOGD(TAG, "Read attempted for characteristic UUID = %s, attr_handle = %d",
|
||||
ble_uuid_to_str(ctxt->chr->uuid, buf), attr_handle);
|
||||
rc = matter_ble_gatts_get_attr_value(attr_handle, &temp_outlen, &temp_outbuf);
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "Characteristic with attr_handle = %d is not added to the list", attr_handle);
|
||||
return 0;
|
||||
}
|
||||
if (os_mbuf_append(ctxt->om, temp_outbuf, static_cast<uint16_t>(temp_outlen)) != 0) {
|
||||
rc = BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
break;
|
||||
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
||||
if (ctxt->om->om_len == 0) {
|
||||
ESP_LOGD(TAG,"Empty packet");
|
||||
return 0;
|
||||
}
|
||||
uuid = (uint8_t *) calloc(BLE_UUID128_VAL_LENGTH, sizeof(uint8_t));
|
||||
if (!uuid) {
|
||||
ESP_LOGE(TAG, "Error allocating memory for 128 bit UUID");
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
assert(ctxt->chr->uuid->type == BLE_UUID_TYPE_128);
|
||||
{
|
||||
const ble_uuid128_t *uuid128 = (const ble_uuid128_t *)ctxt->chr->uuid;
|
||||
memcpy(uuid, uuid128->value, BLE_UUID128_VAL_LENGTH);
|
||||
}
|
||||
if (rc != 0) {
|
||||
free(uuid);
|
||||
ESP_LOGE(TAG, "Error fetching Characteristic UUID128");
|
||||
return rc;
|
||||
}
|
||||
data_len = OS_MBUF_PKTLEN(ctxt->om);
|
||||
ESP_LOGD(TAG, "Write attempt for uuid = %s, attr_handle = %d, data_len = %d",
|
||||
ble_uuid_to_str(ctxt->chr->uuid, buf), attr_handle, data_len);
|
||||
data_buf = (uint8_t *)calloc(1, data_len);
|
||||
if (!data_buf) {
|
||||
ESP_LOGE(TAG, "Error allocating memory for characteristic value");
|
||||
free(uuid);
|
||||
return BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
rc = ble_hs_mbuf_to_flat(ctxt->om, data_buf, data_len, &data_buf_len);
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "Error getting data from memory buffers");
|
||||
free(uuid);
|
||||
free(data_buf);
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
err = protocomm_req_handle(protoble_internal->pc_matter_ble, uuid128_to_handler(uuid), conn_handle, data_buf,
|
||||
data_buf_len, &temp_outbuf, &temp_outlen);
|
||||
free(uuid);
|
||||
free(data_buf);
|
||||
if (err == ESP_OK) {
|
||||
rc = matter_ble_gatts_set_attr_value(attr_handle, temp_outlen, temp_outbuf);
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "Failed to set outbuf for characteristic with attr_handle = %d", attr_handle);
|
||||
free(temp_outbuf);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Invalid content received, killing connection");
|
||||
rc = BLE_ATT_ERR_INVALID_PDU;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int matter_ble_gatt_svr_dsc_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt,
|
||||
void *arg)
|
||||
{
|
||||
if (ctxt->op != BLE_GATT_ACCESS_OP_READ_DSC) {
|
||||
return BLE_ATT_ERR_UNLIKELY;
|
||||
}
|
||||
int rc;
|
||||
size_t temp_outlen = strlen((const char *)ctxt->dsc->arg);
|
||||
rc = os_mbuf_append(ctxt->om, ctxt->dsc->arg, (uint16_t)temp_outlen);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
static esp_err_t ble_gatt_add_characteristics(void *character, int idx)
|
||||
{
|
||||
struct ble_gatt_chr_def *characteristics = (struct ble_gatt_chr_def *)character;
|
||||
ble_uuid128_t temp_uuid128 = { 0 };
|
||||
temp_uuid128.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(temp_uuid128.value, protoble_internal->ble_uuid_base, BLE_UUID128_VAL_LENGTH);
|
||||
memcpy(&temp_uuid128.value[12], &protoble_internal->g_name_uuid_array[idx].uuid, 2);
|
||||
|
||||
(characteristics + idx)->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE;
|
||||
if (protoble_internal->ble_link_encryption) {
|
||||
(characteristics + idx)->flags |= BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_WRITE_ENC;
|
||||
}
|
||||
|
||||
(characteristics + idx)->access_cb = matter_ble_gatt_svr_chr_access;
|
||||
|
||||
(characteristics + idx)->uuid = (ble_uuid_t *)calloc(1, sizeof(ble_uuid128_t));
|
||||
if (!(characteristics + idx)->uuid) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy((void *)(characteristics + idx)->uuid, &temp_uuid128, sizeof(ble_uuid128_t));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ble_gatt_add_char_dsc(void *ch, int idx, uint16_t dsc_uuid)
|
||||
{
|
||||
struct ble_gatt_chr_def *characteristics = (struct ble_gatt_chr_def *)ch;
|
||||
ble_uuid16_t uuid16;
|
||||
uuid16.u.type = BLE_UUID_TYPE_16;
|
||||
uuid16.value = dsc_uuid;
|
||||
(characteristics + idx)->descriptors =
|
||||
(struct ble_gatt_dsc_def *) calloc(2, sizeof(struct ble_gatt_dsc_def));
|
||||
if (!(characteristics + idx)->descriptors) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
(characteristics + idx)->descriptors[0].uuid = (ble_uuid_t *) calloc(1, sizeof(ble_uuid16_t));
|
||||
if (!(characteristics + idx)->descriptors[0].uuid) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy((void *)(characteristics + idx)->descriptors[0].uuid, &uuid16,
|
||||
sizeof(ble_uuid16_t));
|
||||
(characteristics + idx)->descriptors[0].att_flags = BLE_ATT_F_READ;
|
||||
(characteristics + idx)->descriptors[0].access_cb = matter_ble_gatt_svr_dsc_access;
|
||||
(characteristics + idx)->descriptors[0].arg = (void *)protoble_internal->g_name_uuid_array[idx].name;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t populate_gatt_db(struct ble_gatt_svc_def **gatt_db_svc_ptr, const protocomm_matter_ble_config_t *config)
|
||||
{
|
||||
if (*gatt_db_svc_ptr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
*gatt_db_svc_ptr = (struct ble_gatt_svc_def *) calloc(1, sizeof(struct ble_gatt_svc_def));
|
||||
if (!*gatt_db_svc_ptr) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
(*gatt_db_svc_ptr)->uuid = (ble_uuid_t *) calloc(1, sizeof(ble_uuid128_t));
|
||||
if (!(*gatt_db_svc_ptr)->uuid) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
ble_uuid128_t uuid128 = { 0 };
|
||||
uuid128.u.type = BLE_UUID_TYPE_128;
|
||||
memcpy(uuid128.value, config->service_uuid, BLE_UUID128_VAL_LENGTH);
|
||||
memcpy((void *) (*gatt_db_svc_ptr)->uuid, &uuid128, sizeof(ble_uuid128_t));
|
||||
// Add primary service
|
||||
esp_err_t err = ble_gatt_add_primary_svcs(*gatt_db_svc_ptr, config->name_uuid_array_len);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
for (int i = 0; i < config->name_uuid_array_len; ++i) {
|
||||
err = ble_gatt_add_characteristics((void *)(*gatt_db_svc_ptr)->characteristics, i);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
err = ble_gatt_add_char_dsc((void *) (*gatt_db_svc_ptr)->characteristics,
|
||||
i, BLE_GATT_UUID_CHAR_DSC);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void transport_matter_ble_connect(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGD(TAG, "Inside BLE connect w/ conn_id - %d", event->connect.conn_handle);
|
||||
|
||||
if (!protoble_internal) {
|
||||
ESP_LOGI(TAG,"Protocomm layer has already stopped");
|
||||
return;
|
||||
}
|
||||
|
||||
err = protocomm_open_session(protoble_internal->pc_matter_ble, event->connect.conn_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error creating the session");
|
||||
} else {
|
||||
protocomm_matter_ble_event_t ble_event = {};
|
||||
ble_event.evt_type = PROTOCOMM_TRANSPORT_MATTER_BLE_CONNECTED;
|
||||
ble_event.conn_handle = event->connect.conn_handle;
|
||||
ble_event.conn_status = event->connect.status;
|
||||
if (esp_event_post(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT, PROTOCOMM_TRANSPORT_MATTER_BLE_CONNECTED, &ble_event,
|
||||
sizeof(protocomm_matter_ble_event_t), portMAX_DELAY) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to post transport pairing event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void transport_matter_ble_disconnect(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
ESP_LOGD(TAG, "Inside disconnect w/ session - %d", event->disconnect.conn.conn_handle);
|
||||
if (!protoble_internal) {
|
||||
ESP_LOGI(TAG,"Protocomm layer has already stopped");
|
||||
return;
|
||||
}
|
||||
|
||||
if (protoble_internal->pc_matter_ble) {
|
||||
err = protocomm_close_session(protoble_internal->pc_matter_ble, event->disconnect.conn.conn_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error closing the session after disconnect");
|
||||
} else {
|
||||
protocomm_matter_ble_event_t ble_event = {};
|
||||
ble_event.evt_type = PROTOCOMM_TRANSPORT_MATTER_BLE_DISCONNECTED;
|
||||
ble_event.conn_handle = event->disconnect.conn.conn_handle;
|
||||
ble_event.disconnect_reason = event->disconnect.reason;
|
||||
if (esp_event_post(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT, PROTOCOMM_TRANSPORT_MATTER_BLE_DISCONNECTED, &ble_event,
|
||||
sizeof(protocomm_matter_ble_event_t), portMAX_DELAY) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to post transport disconnection event");
|
||||
}
|
||||
}
|
||||
}
|
||||
protoble_internal->gatt_mtu = BLE_ATT_MTU_DFLT;
|
||||
}
|
||||
|
||||
static void transport_matter_ble_set_mtu(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
protoble_internal->gatt_mtu = event->mtu.value;
|
||||
}
|
||||
|
||||
static int protocomm_matter_ble_gap_event(struct ble_gap_event *event, void *arg)
|
||||
{
|
||||
struct ble_gap_conn_desc desc;
|
||||
int rc;
|
||||
|
||||
switch (event->type) {
|
||||
case BLE_GAP_EVENT_CONNECT:
|
||||
if (event->connect.status == 0) {
|
||||
transport_matter_ble_connect(event, arg);
|
||||
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
|
||||
if (rc != 0) {
|
||||
ESP_LOGE(TAG, "No open connection with the specified handle");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BLE_GAP_EVENT_DISCONNECT:
|
||||
transport_matter_ble_disconnect(event, arg);
|
||||
break;
|
||||
case BLE_GAP_EVENT_MTU:
|
||||
transport_matter_ble_set_mtu(event, arg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_err_t protocomm_matter_ble_start(protocomm_t *pc, const protocomm_matter_ble_config_t *config)
|
||||
{
|
||||
if (!pc || !config || !config->name_uuid_array_len || !config->name_uuid_array) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (protoble_internal) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
protoble_internal = (_protocomm_matter_ble_internal_t *) calloc(1, sizeof(_protocomm_matter_ble_internal_t));
|
||||
if (!protoble_internal) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memcpy(protoble_internal->ble_uuid_base, config->service_uuid, BLE_UUID128_VAL_LENGTH);
|
||||
protoble_internal->g_name_uuid_array_len = config->name_uuid_array_len;
|
||||
protoble_internal->g_name_uuid_array = (protocomm_matter_ble_name_uuid_t *)malloc(config->name_uuid_array_len * sizeof(protocomm_matter_ble_name_uuid_t));
|
||||
if (!protoble_internal->g_name_uuid_array) {
|
||||
protocomm_matter_ble_cleanup();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < protoble_internal->g_name_uuid_array_len; i++) {
|
||||
protoble_internal->g_name_uuid_array[i].uuid = config->name_uuid_array[i].uuid;
|
||||
protoble_internal->g_name_uuid_array[i].name = strdup(config->name_uuid_array[i].name);
|
||||
if (!protoble_internal->g_name_uuid_array[i].name) {
|
||||
ESP_LOGE(TAG, "Error allocating internal name UUID entry");
|
||||
protocomm_matter_ble_cleanup();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
protoble_internal->pc_matter_ble = pc;
|
||||
protoble_internal->gatt_mtu = BLE_ATT_MTU_DFLT;
|
||||
protoble_internal->ble_link_encryption = config->ble_link_encryption;
|
||||
|
||||
if (populate_gatt_db(&s_gatt_db, config) != ESP_OK) {
|
||||
free_gatt_ble_misc_memory(s_gatt_db);
|
||||
}
|
||||
|
||||
chip::DeviceLayer::Internal::BLEMgrImpl().SetSecondaryAdvDeviceName(config->device_name);
|
||||
chip::DeviceLayer::Internal::BLEMgrImpl().SetSecondaryAdvUuid(chip::ByteSpan(config->service_uuid));
|
||||
chip::DeviceLayer::Internal::BLEMgrImpl().SetSecondaryGATTService(s_gatt_db, 0);
|
||||
chip::DeviceLayer::Internal::BLEMgrImpl().SetSecondaryBleSmConfig(config->ble_bonding, config->ble_sm_sc);
|
||||
chip::DeviceLayer::Internal::BLEMgrImpl().SetSecondaryAdvGapEventHandler(protocomm_matter_ble_gap_event);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t protocomm_matter_ble_stop(protocomm_t *pc)
|
||||
{
|
||||
ESP_LOGD(TAG, "protocomm_ble_stop called here...");
|
||||
|
||||
if ((pc != NULL) && (protoble_internal != NULL ) && (pc == protoble_internal->pc_matter_ble)) {
|
||||
protoble_internal->pc_matter_ble = nullptr;
|
||||
}
|
||||
chip::DeviceLayer::Internal::BLEMgr().Shutdown();
|
||||
free_gatt_ble_misc_memory(s_gatt_db);
|
||||
protocomm_matter_ble_cleanup();
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <esp_event.h>
|
||||
#include <protocomm.h>
|
||||
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(PROTOCOMM_TRANSPORT_MATTER_BLE_EVENT);
|
||||
|
||||
typedef enum {
|
||||
PROTOCOMM_TRANSPORT_MATTER_BLE_CONNECTED,
|
||||
PROTOCOMM_TRANSPORT_MATTER_BLE_DISCONNECTED,
|
||||
} protocomm_transport_matter_ble_event_t;
|
||||
|
||||
#define BLE_UUID128_VAL_LENGTH 16
|
||||
|
||||
#define MAX_BLE_MANUFACTURER_DATA_LEN 29
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
uint16_t uuid;
|
||||
} protocomm_matter_ble_name_uuid_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t evt_type;
|
||||
uint16_t conn_handle;
|
||||
union {
|
||||
int conn_status;
|
||||
int disconnect_reason;
|
||||
};
|
||||
} protocomm_matter_ble_event_t;
|
||||
|
||||
typedef struct protocomm_matter_ble_config {
|
||||
char device_name[30];
|
||||
uint8_t service_uuid[BLE_UUID128_VAL_LENGTH];
|
||||
uint8_t *manufacturer_data;
|
||||
ssize_t manufacturer_data_len;
|
||||
ssize_t name_uuid_array_len;
|
||||
protocomm_matter_ble_name_uuid_t *name_uuid_array;
|
||||
unsigned ble_bonding:1;
|
||||
unsigned ble_sm_sc:1;
|
||||
unsigned ble_link_encryption:1;
|
||||
} protocomm_matter_ble_config_t;
|
||||
|
||||
esp_err_t protocomm_matter_ble_start(protocomm_t *pc, const protocomm_matter_ble_config_t *config);
|
||||
|
||||
esp_err_t protocomm_matter_ble_stop(protocomm_t *pc);
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "wifi_prov_scheme_matter_ble.h"
|
||||
#include "protocomm_matter_ble.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_wifi_types.h>
|
||||
#include <protocomm.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "WIFI_PROV"
|
||||
|
||||
static uint8_t custom_service_uuid[BLE_UUID128_VAL_LENGTH];
|
||||
static bool custom_service_uuid_set = false;
|
||||
static uint8_t *custom_manufacturer_data = nullptr;
|
||||
static size_t custom_manufacturer_data_len = 0;
|
||||
|
||||
static esp_err_t prov_start(protocomm_t *pc, void *config)
|
||||
{
|
||||
if (!pc) {
|
||||
ESP_LOGE(TAG, "Protocomm handle cannot be null");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!config) {
|
||||
ESP_LOGE(TAG, "Cannot start with null configuration");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
||||
|
||||
#if defined(CONFIG_WIFI_PROV_BLE_BONDING)
|
||||
ble_config->ble_bonding = 1;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_WIFI_PROV_BLE_SEC_CONN)
|
||||
ble_config->ble_sm_sc = 1;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION)
|
||||
ble_config->ble_link_encryption = 1;
|
||||
#endif
|
||||
|
||||
if (protocomm_matter_ble_start(pc, ble_config) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start protocomm BLE service");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t prov_stop(protocomm_t *pc)
|
||||
{
|
||||
return protocomm_matter_ble_stop(pc);
|
||||
}
|
||||
|
||||
esp_err_t wifi_prov_scheme_matter_ble_set_service_uuid(uint8_t *uuid, size_t uuid_size)
|
||||
{
|
||||
if (uuid_size != sizeof(custom_service_uuid)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
memcpy(custom_service_uuid, uuid, sizeof(custom_service_uuid));
|
||||
custom_service_uuid_set = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t wifi_prov_scheme_matter_ble_set_mfg_data(uint8_t *mfg_data, size_t mfg_data_len)
|
||||
{
|
||||
if (custom_manufacturer_data) {
|
||||
free(custom_manufacturer_data);
|
||||
}
|
||||
custom_manufacturer_data = (uint8_t *)malloc(mfg_data_len);
|
||||
if (!custom_manufacturer_data) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
custom_manufacturer_data_len = mfg_data_len;
|
||||
memcpy(custom_manufacturer_data, mfg_data, mfg_data_len);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void *new_config()
|
||||
{
|
||||
protocomm_matter_ble_config_t *ble_config =
|
||||
(protocomm_matter_ble_config_t *)calloc(1, sizeof(protocomm_matter_ble_config_t));
|
||||
if (!ble_config) {
|
||||
ESP_LOGE(TAG, "Error allocating memory for new configuration");
|
||||
return nullptr;
|
||||
}
|
||||
const uint8_t service_uuid[16] = {
|
||||
0x07, 0xed, 0x9b, 0x2d, 0x0f, 0x06, 0x7c, 0x87, 0x9b, 0x43, 0x43, 0x6b, 0x4d, 0x24, 0x75, 0x17,
|
||||
};
|
||||
memcpy(ble_config->service_uuid, service_uuid, sizeof(ble_config->service_uuid));
|
||||
return ble_config;
|
||||
}
|
||||
|
||||
static void delete_config(void *config)
|
||||
{
|
||||
if (!config) {
|
||||
ESP_LOGE(TAG, "Cannot delete null configuration");
|
||||
return;
|
||||
}
|
||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
||||
for (size_t i = 0; i < ble_config->name_uuid_array_len; i++) {
|
||||
free((void *)ble_config->name_uuid_array[i].name);
|
||||
}
|
||||
free(ble_config->name_uuid_array);
|
||||
free(ble_config);
|
||||
}
|
||||
|
||||
static esp_err_t set_config_service(void *config, const char *service_name, const char *service_key)
|
||||
{
|
||||
if (!config) {
|
||||
ESP_LOGE(TAG, "Cannot set null configuration");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!service_name) {
|
||||
ESP_LOGE(TAG, "Service name cannot be NULL");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
||||
strlcpy(ble_config->device_name, service_name, sizeof(ble_config->device_name));
|
||||
if (custom_service_uuid_set) {
|
||||
memcpy(ble_config->service_uuid, custom_service_uuid, sizeof(ble_config->service_uuid));
|
||||
}
|
||||
if (custom_manufacturer_data && custom_manufacturer_data_len) {
|
||||
size_t mfg_data_len = custom_manufacturer_data_len;
|
||||
if (mfg_data_len > (MAX_BLE_MANUFACTURER_DATA_LEN - sizeof(ble_config->device_name) - 2)) {
|
||||
ESP_LOGE(TAG, "Manufacturer data length is more than the max allowed size; expect truncated mfg_data ");
|
||||
mfg_data_len = MAX_BLE_MANUFACTURER_DATA_LEN - sizeof(ble_config->device_name) - 2;
|
||||
}
|
||||
ble_config->manufacturer_data = custom_manufacturer_data;
|
||||
ble_config->manufacturer_data_len = mfg_data_len;
|
||||
} else {
|
||||
ble_config->manufacturer_data = nullptr;
|
||||
ble_config->manufacturer_data_len = 0;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t set_config_endpoint(void *config, const char *endpoint_name, uint16_t uuid)
|
||||
{
|
||||
if (!config) {
|
||||
ESP_LOGE(TAG, "Cannot set null configuration");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!endpoint_name) {
|
||||
ESP_LOGE(TAG, "EP name cannot be null");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
protocomm_matter_ble_config_t *ble_config = (protocomm_matter_ble_config_t *)config;
|
||||
|
||||
char *copy_ep_name = strdup(endpoint_name);
|
||||
if (!copy_ep_name) {
|
||||
ESP_LOGE(TAG, "Error allocating memory for EP name");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
protocomm_matter_ble_name_uuid_t *name_uuid_array = (protocomm_matter_ble_name_uuid_t *)realloc(
|
||||
ble_config->name_uuid_array, (ble_config->name_uuid_array_len + 1) * sizeof(protocomm_matter_ble_name_uuid_t));
|
||||
if (!name_uuid_array) {
|
||||
ESP_LOGE(TAG, "Error allocating memory for EP-UUID lookup table");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
name_uuid_array[ble_config->name_uuid_array_len].name = copy_ep_name;
|
||||
name_uuid_array[ble_config->name_uuid_array_len].uuid = uuid;
|
||||
ble_config->name_uuid_array = name_uuid_array;
|
||||
ble_config->name_uuid_array_len += 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
const wifi_prov_scheme_t wifi_prov_scheme_matter_ble = {.prov_start = prov_start,
|
||||
.prov_stop = prov_stop,
|
||||
.new_config = new_config,
|
||||
.delete_config = delete_config,
|
||||
.set_config_service = set_config_service,
|
||||
.set_config_endpoint = set_config_endpoint,
|
||||
.wifi_mode = WIFI_MODE_STA};
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <protocomm.h>
|
||||
#include <protocomm_ble.h>
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
|
||||
#include <wifi_provisioning/manager.h>
|
||||
|
||||
extern const wifi_prov_scheme_t wifi_prov_scheme_matter_ble;
|
||||
|
||||
#define WIFI_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM { \
|
||||
.event_cb = wifi_prov_scheme_ble_event_cb_free_btdm, \
|
||||
.user_data = NULL \
|
||||
}
|
||||
|
||||
void wifi_prov_scheme_matter_ble_event_cb_free_btdm(void *user_data, wifi_prov_cb_event_t event, void *event_data);
|
||||
|
||||
esp_err_t wifi_prov_scheme_matter_ble_set_service_uuid(uint8_t *uuid, size_t uuid_size);
|
||||
|
||||
esp_err_t wifi_prov_scheme_matter_ble_set_mfg_data(uint8_t *mfg_data, size_t mfg_data_len);
|
||||
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
# Note: Firmware partition offset needs to be 64K aligned, initial 36K (9 sectors) are reserved for bootloader and partition table
|
||||
esp_secure_cert, 0x3F, ,0xd000, 0x2000, encrypted
|
||||
nvs, data, nvs, 0x10000, 0xC000,
|
||||
nvs_keys, data, nvs_keys,, 0x1000, encrypted
|
||||
otadata, data, ota, , 0x2000
|
||||
phy_init, data, phy, , 0x1000,
|
||||
ota_0, app, ota_0, 0x20000, 0x1E0000,
|
||||
ota_1, app, ota_1, , 0x1E0000,
|
||||
fctry, data, nvs, 0x3E0000, 0x6000
|
||||
|
@@ -0,0 +1,76 @@
|
||||
# Default to 921600 baud when flashing and monitoring device
|
||||
CONFIG_ESPTOOLPY_BAUD_921600B=y
|
||||
CONFIG_ESPTOOLPY_BAUD=921600
|
||||
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
# Enable Extended advertisement of NIMBLE
|
||||
CONFIG_BT_NIMBLE_EXT_ADV=y
|
||||
CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
|
||||
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
# Use a custom partition table
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
|
||||
# Enable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=y
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# Button
|
||||
CONFIG_BUTTON_PERIOD_TIME_MS=20
|
||||
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
|
||||
|
||||
# disable softap by default
|
||||
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
|
||||
# Disable DS Peripheral
|
||||
CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
# Increase LwIP IPv6 address number to 6 (MAX_FABRIC + 1)
|
||||
# unique local addresses for fabrics(MAX_FABRIC), a link local address(1)
|
||||
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
|
||||
|
||||
# mbedtls
|
||||
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
||||
|
||||
# Fix for Timer Overflows
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
|
||||
|
||||
# External Platform
|
||||
CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM=y
|
||||
CONFIG_CHIP_EXTERNAL_PLATFORM_DIR="../../../../examples/common/secondary_ble_adv/platform/ESP32_custom"
|
||||
CONFIG_CHIP_EXTERNAL_PLATFORM_INCLUDE_DIR="../../../../examples/common/secondary_ble_adv"
|
||||
|
||||
# Additional configurations
|
||||
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
|
||||
CONFIG_ESP_RMAKER_NO_CLAIM=y
|
||||
CONFIG_ESP_RMAKER_USE_ESP_SECURE_CERT_MGR=y
|
||||
CONFIG_ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN=y
|
||||
|
||||
CONFIG_CHIP_FACTORY_NAMESPACE_PARTITION_LABEL="fctry"
|
||||
CONFIG_ENABLE_ESP32_FACTORY_DATA_PROVIDER=y
|
||||
CONFIG_ENABLE_ESP32_DEVICE_INSTANCE_INFO_PROVIDER=y
|
||||
CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER=y
|
||||
CONFIG_SEC_CERT_DAC_PROVIDER=y
|
||||
@@ -0,0 +1,25 @@
|
||||
# ESP32-C3-DevKitC-02 Settings
|
||||
# Buttons
|
||||
CONFIG_BSP_BUTTONS_NUM=1
|
||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
||||
CONFIG_BSP_BUTTON_1_GPIO=9
|
||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
||||
# LEDs
|
||||
CONFIG_BSP_LEDS_NUM=1
|
||||
CONFIG_BSP_LED_TYPE_RGB=y
|
||||
CONFIG_BSP_LED_RGB_GPIO=8
|
||||
CONFIG_BSP_LED_RGB_BACKEND_RMT=y
|
||||
|
||||
# Memory Optimization
|
||||
CONFIG_ESP_WIFI_IRAM_OPT=n
|
||||
CONFIG_ESP_WIFI_RX_IRAM_OPT=n
|
||||
CONFIG_ESP_MATTER_MAX_DEVICE_TYPE_COUNT=2
|
||||
CONFIG_ESP_MATTER_BINDING_TABLE_SIZE=1
|
||||
CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=512
|
||||
CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE=256
|
||||
CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE=256
|
||||
CONFIG_MAX_EXCHANGE_CONTEXTS=5
|
||||
CONFIG_MAX_BINDINGS=2
|
||||
CONFIG_MAX_PEER_NODES=8
|
||||
CONFIG_NUM_TCP_ENDPOINTS=1
|
||||
CONFIG_NUM_UDP_ENDPOINTS=6
|
||||
@@ -0,0 +1,70 @@
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
# Enable Extended advertisement of NIMBLE
|
||||
CONFIG_BT_NIMBLE_EXT_ADV=y
|
||||
CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
|
||||
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
# Use a custom partition table
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
|
||||
# Enable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=y
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# Button
|
||||
CONFIG_BUTTON_PERIOD_TIME_MS=20
|
||||
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
# ESP32-S3-DevKitC-1 Settings
|
||||
# Buttons
|
||||
CONFIG_BSP_BUTTONS_NUM=1
|
||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
||||
CONFIG_BSP_BUTTON_1_GPIO=0
|
||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
||||
|
||||
# mbedtls
|
||||
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
||||
|
||||
# For additional security on reset to factory
|
||||
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
|
||||
|
||||
# Fix for Timer Overflows
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
|
||||
|
||||
# External Platform
|
||||
CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM=y
|
||||
CONFIG_CHIP_EXTERNAL_PLATFORM_DIR="../../../../../builds/app-frameworks/esp-matter/examples/common/secondary_ble_adv/platform/ESP32_custom"
|
||||
CONFIG_CHIP_EXTERNAL_PLATFORM_INCLUDE_DIR="../../../../../builds/app-frameworks/esp-matter/examples/common/secondary_ble_adv"
|
||||
|
||||
# Memory Optimization
|
||||
CONFIG_ESP_WIFI_IRAM_OPT=n
|
||||
CONFIG_ESP_WIFI_RX_IRAM_OPT=n
|
||||
CONFIG_ESP_MATTER_MAX_DEVICE_TYPE_COUNT=2
|
||||
CONFIG_ESP_MATTER_BINDING_TABLE_SIZE=1
|
||||
CONFIG_EVENT_LOGGING_CRIT_BUFFER_SIZE=512
|
||||
CONFIG_EVENT_LOGGING_INFO_BUFFER_SIZE=256
|
||||
CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE=256
|
||||
CONFIG_MAX_EXCHANGE_CONTEXTS=5
|
||||
CONFIG_MAX_BINDINGS=2
|
||||
CONFIG_MAX_PEER_NODES=8
|
||||
CONFIG_NUM_TCP_ENDPOINTS=1
|
||||
CONFIG_NUM_UDP_ENDPOINTS=6
|
||||
@@ -0,0 +1,6 @@
|
||||
# ESP32-S3-DevKitC-1 Settings
|
||||
# Buttons
|
||||
CONFIG_BSP_BUTTONS_NUM=1
|
||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
||||
CONFIG_BSP_BUTTON_1_GPIO=0
|
||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
||||
@@ -0,0 +1,56 @@
|
||||
#enable BT
|
||||
CONFIG_BT_ENABLED=y
|
||||
CONFIG_BT_NIMBLE_ENABLED=y
|
||||
|
||||
# Enable Extended advertisement of NIMBLE
|
||||
CONFIG_BT_NIMBLE_EXT_ADV=y
|
||||
CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES=2
|
||||
|
||||
#disable BT connection reattempt
|
||||
CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=n
|
||||
|
||||
#enable lwip ipv6 autoconfig
|
||||
CONFIG_LWIP_IPV6_AUTOCONFIG=y
|
||||
|
||||
# Use a custom partition table
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0xC000
|
||||
|
||||
# Enable chip shell
|
||||
CONFIG_ENABLE_CHIP_SHELL=y
|
||||
|
||||
#enable lwIP route hooks
|
||||
CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT=y
|
||||
CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT=y
|
||||
|
||||
# Button
|
||||
CONFIG_BUTTON_PERIOD_TIME_MS=20
|
||||
CONFIG_BUTTON_LONG_PRESS_TIME_MS=5000
|
||||
|
||||
# Enable HKDF in mbedtls
|
||||
CONFIG_MBEDTLS_HKDF_C=y
|
||||
|
||||
# ESP32-S3-DevKitC-1 Settings
|
||||
# Buttons
|
||||
CONFIG_BSP_BUTTONS_NUM=1
|
||||
CONFIG_BSP_BUTTON_1_TYPE_GPIO=y
|
||||
CONFIG_BSP_BUTTON_1_GPIO=0
|
||||
CONFIG_BSP_BUTTON_1_LEVEL=0
|
||||
|
||||
# mbedtls
|
||||
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_PEER_CERT=y
|
||||
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
|
||||
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y
|
||||
|
||||
# For additional security on reset to factory
|
||||
CONFIG_ESP_RMAKER_USER_ID_CHECK=y
|
||||
|
||||
# Fix for Timer Overflows
|
||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120
|
||||
|
||||
# External Platform
|
||||
CONFIG_CHIP_ENABLE_EXTERNAL_PLATFORM=y
|
||||
CONFIG_CHIP_EXTERNAL_PLATFORM_DIR="../../../../../builds/app-frameworks/esp-matter/examples/common/secondary_ble_adv/platform/ESP32_custom"
|
||||
CONFIG_CHIP_EXTERNAL_PLATFORM_INCLUDE_DIR="../../../../../builds/app-frameworks/esp-matter/examples/common/secondary_ble_adv"
|
||||
Reference in New Issue
Block a user