blob: a7f6478b1af9f7b9769dcc802fc19017e51cd2f1 [file] [log] [blame]
/*
*
* Copyright (c) 2020 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.
*/
//#include "FreeRTOS.h"
//#include "task.h"
#include <lib/shell/Engine.h>
#include <app/server/OnboardingCodesUtil.h>
#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/SetupPayload.h>
#include <lib/core/CHIPCore.h>
#include <lib/support/Base64.h>
#include <lib/support/CHIPArgParser.hpp>
#include <lib/support/CodeUtils.h>
//#include <lib/support/RandUtils.h> //==> rm from TE7.5
#include <app-common/zap-generated/attribute-id.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/server/Dnssd.h>
#include <app/server/Server.h>
#include <app/util/af-types.h>
#include <app/util/attribute-storage.h>
#include <app/util/attribute-table.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <setup_payload/QRCodeSetupPayloadGenerator.h>
#include <app/InteractionModelEngine.h>
#include <ChipShellCollection.h>
// cr++
#if (defined(CONFIG_CHIP_MW320_REAL_FACTORY_DATA) && (CONFIG_CHIP_MW320_REAL_FACTORY_DATA == 1))
#include "FactoryDataProvider.h"
#else
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#endif // if CONFIG_CHIP_MW320_REAL_FACTORY_DATA
// cr--
// ota++
#include "app/clusters/ota-requestor/BDXDownloader.h"
#include "app/clusters/ota-requestor/DefaultOTARequestor.h"
#include "app/clusters/ota-requestor/DefaultOTARequestorDriver.h"
#include "app/clusters/ota-requestor/DefaultOTARequestorStorage.h"
//#include <app/clusters/ota-requestor/DefaultOTARequestorUserConsent.h>
#include "platform/nxp/mw320/OTAImageProcessorImpl.h"
//#include "app/clusters/ota-requestor/OTARequestorDriver.h"
// for ota module test
#include "mw320_ota.h"
// ota--
#include "app/clusters/bindings/BindingManager.h"
#include "binding-handler.h"
/* platform specific */
#include "board.h"
#include "clock_config.h"
#include "fsl_debug_console.h"
#include "fsl_gpio.h"
#include "pin_mux.h"
#include <wm_os.h>
extern "C" {
#include "boot_flags.h"
#include "cli.h"
#include "dhcp-server.h"
#include "iperf.h"
#include "mflash_drv.h"
#include "network_flash_storage.h"
#include "partition.h"
#include "ping.h"
#include "wlan.h"
#include "wm_net.h"
}
#include "fsl_aes.h"
#include "lpm.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define APP_AES AES
#define CONNECTION_INFO_FILENAME "connection_info.dat"
#define SSID_FNAME "ssid_fname"
#define PSK_FNAME "psk_fname"
#define VERSION_STR "mw320-2.9.10-005"
enum
{
MCUXPRESSO_WIFI_CLI,
MATTER_SHELL,
MAX_SELECTION,
};
static int Matter_Selection = MAX_SELECTION;
#define RUN_RST_LT_DELAY 10
static const char * TAG = "mw320";
/*******************************************************************************
* Variables
******************************************************************************/
static SemaphoreHandle_t aesLock;
static struct wlan_network sta_network;
static struct wlan_network uap_network;
const int TASK_MAIN_PRIO = OS_PRIO_3;
const int TASK_MAIN_STACK_SIZE = 800;
portSTACK_TYPE * task_main_stack = NULL;
TaskHandle_t task_main_task_handler;
uint8_t * __FACTORY_DATA_START;
uint32_t __FACTORY_DATA_SIZE;
#if CHIP_ENABLE_OPENTHREAD
extern "C" {
#include <openthread/platform/platform-softdevice.h>
}
#endif // CHIP_ENABLE_OPENTHREAD
using namespace chip;
using namespace chip::Credentials;
using namespace ::chip::app;
using namespace chip::Shell;
using namespace chip::DeviceLayer;
// ota ++
using chip::BDXDownloader;
using chip::DefaultOTARequestor;
using chip::OTADownloader;
using chip::OTAImageProcessorImpl;
using chip::OTAImageProgress;
DefaultOTARequestor gRequestorCore;
DefaultOTARequestorStorage gRequestorStorage;
chip::DeviceLayer::DefaultOTARequestorDriver gRequestorUser;
BDXDownloader gDownloader;
OTAImageProcessorImpl gImageProcessor;
// chip::ota::DefaultOTARequestorUserConsent gUserConsentProvider;
// static chip::ota::UserConsentState gUserConsentState = chip::ota::UserConsentState::kGranted;
void InitOTARequestor(void)
{
// Initialize and interconnect the Requestor and Image Processor objects -- START
SetRequestorInstance(&gRequestorCore);
gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage());
// Set server instance used for session establishment
gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader);
// WARNING: this is probably not realistic to know such details of the image or to even have an OTADownloader instantiated at
// the beginning of program execution. We're using hardcoded values here for now since this is a reference application.
// TODO: instatiate and initialize these values when QueryImageResponse tells us an image is available
// TODO: add API for OTARequestor to pass QueryImageResponse info to the application to use for OTADownloader init
// OTAImageProcessor ipParams;
// ipParams.imageFile = CharSpan("dnld_img.txt");
// gImageProcessor.SetOTAImageProcessorParams(ipParams);
gImageProcessor.SetOTADownloader(&gDownloader);
// Connect the Downloader and Image Processor objects
gDownloader.SetImageProcessorDelegate(&gImageProcessor);
gRequestorUser.Init(&gRequestorCore, &gImageProcessor);
/*
if (gUserConsentState != chip::ota::UserConsentState::kUnknown)
{
gUserConsentProvider.SetUserConsentState(gUserConsentState);
gRequestorUser.SetUserConsentDelegate(&gUserConsentProvider);
}
*/
// Initialize and interconnect the Requestor and Image Processor objects -- END
}
const char * mw320_get_verstr(void)
{
return VERSION_STR;
}
void save_network(char * ssid, char * pwd);
void save_network(char * ssid, char * pwd)
{
int ret;
ret = save_wifi_network((char *) SSID_FNAME, (uint8_t *) ssid, strlen(ssid) + 1);
if (ret != WM_SUCCESS)
{
PRINTF("Error: write ssid to flash failed\r\n");
}
ret = save_wifi_network((char *) PSK_FNAME, (uint8_t *) pwd, strlen(pwd) + 1);
if (ret != WM_SUCCESS)
{
PRINTF("Error: write psk to flash failed\r\n");
}
return;
}
// ota --
namespace {
static void rst_args_lt(System::Layer * aSystemLayer, void * aAppState);
}
#if defined(__cplusplus)
extern "C" {
#endif /* __cplusplus */
volatile int g_ButtonPress = 0;
bool need2sync_sw_attr = false;
void sw2_handle(bool frm_clk)
{
static uint8_t click_cnt = 0;
static uint8_t run_times = 0;
if (frm_clk == true)
{
// Called while user clicks the button
click_cnt++;
PRINTF(" (%d times) \r\n", click_cnt);
return;
}
// Called regularlly from a thread every 500ms
run_times++;
if (click_cnt > 4)
{
// More than 4 clicks within the last second => erase the saved parameters
PRINTF("--> enough clicks (%d times) => resetting the saved parameters \r\n", click_cnt);
::erase_all_params();
DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(RUN_RST_LT_DELAY), rst_args_lt, nullptr);
click_cnt = 0;
}
if (run_times >= 2)
{
// Called twice with gap==500ms
click_cnt = 0;
run_times = 0;
}
return;
}
void GPIO_IRQHandler(void)
{
uint32_t intrval = GPIO_PortGetInterruptFlags(GPIO, GPIO_PORT(BOARD_SW1_GPIO_PIN));
// Clear the interrupt
GPIO_PortClearInterruptFlags(GPIO, GPIO_PORT(BOARD_SW1_GPIO_PIN), intrval);
// Check which sw tiggers the interrupt
if (intrval & 1UL << GPIO_PORT_PIN(BOARD_SW1_GPIO_PIN))
{
PRINTF("SW_1 click => do switch handler\r\n");
/* Change state of button. */
g_ButtonPress++;
need2sync_sw_attr = true;
}
else if (intrval & 1UL << GPIO_PORT_PIN(BOARD_SW2_GPIO_PIN))
{
PRINTF("SW_2 click \r\n");
sw2_handle(true);
}
SDK_ISR_EXIT_BARRIER;
}
#if defined(__cplusplus)
}
#endif /* __cplusplus */
/*
EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
EmberAfAttributeMetadata * attributeMetadata, uint16_t manufacturerCode,
uint8_t * buffer, uint16_t maxReadLength, int32_t index)
{
PRINTF("====> emberAfExternalAttributeReadCallback\r\n");
if(clusterId == Clusters::Switch::Id) {
*buffer = g_ButtonPress;
}
return EMBER_ZCL_STATUS_SUCCESS;
}
*/
namespace {
typedef enum
{
chip_srv_all,
dns_srv,
srv_type_max
} srv_type_t;
typedef enum
{
led_yellow,
led_amber,
led_max
} led_id_t;
static void run_chip_srv(System::Layer * aSystemLayer, void * aAppState);
static void run_dnssrv(System::Layer * aSystemLayer, void * aAppState);
static void run_update_chipsrv(srv_type_t srv_type);
static void led_on_off(led_id_t lt_id, bool is_on);
bool is_connected = false;
/*******************************************************************************
* Prototypes
******************************************************************************/
static void load_network(char * ssid, char * pwd);
/*
static void saveProfile(int argc, char **argv);
static void loadProfile(int argc, char **argv);
static void resetProfile(int argc, char **argv);
static void wlanIeeePowerSave(int argc, char **argv);
static void wlanDeepSleep(int argc, char **argv);
static void mcuPowerMode(int argc, char **argv);
static struct cli_command saveload[] = {
{"save-profile", "<profile_name>", saveProfile},
{"load-profile", NULL, loadProfile},
{"reset-profile", NULL, resetProfile},
};
static struct cli_command wlanPower[] = {
{"wlan-ieee-power-save", "<on/off> <wakeup condition>", wlanIeeePowerSave},
{"wlan-deepsleep", "<on/off>", wlanDeepSleep},
};
static struct cli_command mcuPower[] = {
{"mcu-power-mode", "<pm0/pm1/pm2/pm4> [<pm2_io_exclude_mask>]", mcuPowerMode},
};
*/
TaskHandle_t sShellTaskHandle;
/*******************************************************************************
* Code
******************************************************************************/
static status_t APP_AES_Lock(void)
{
if (pdTRUE == xSemaphoreTakeRecursive(aesLock, portMAX_DELAY))
{
return kStatus_Success;
}
else
{
return kStatus_Fail;
}
}
static void APP_AES_Unlock(void)
{
xSemaphoreGiveRecursive(aesLock);
}
static void load_network(char * ssid, char * pwd)
{
int ret;
unsigned char ssid_buf[IEEEtypes_SSID_SIZE + 1];
unsigned char psk_buf[WLAN_PSK_MAX_LENGTH];
uint32_t len;
len = IEEEtypes_SSID_SIZE + 1;
ret = get_saved_wifi_network((char *) SSID_FNAME, ssid_buf, &len);
if (ret != WM_SUCCESS)
{
PRINTF("Error: Read saved SSID\r\n");
strcpy(ssid, "");
}
else
{
PRINTF("saved_ssid: [%s]\r\n", ssid_buf);
strcpy(ssid, (const char *) ssid_buf);
}
len = WLAN_PSK_MAX_LENGTH;
ret = get_saved_wifi_network((char *) PSK_FNAME, psk_buf, &len);
if (ret != WM_SUCCESS)
{
PRINTF("Error: Read saved PSK\r\n");
strcpy(pwd, "");
}
else
{
PRINTF("saved_psk: [%s]\r\n", psk_buf);
strcpy(pwd, (const char *) psk_buf);
}
}
/*
static void saveProfile(int argc, char **argv)
{
int ret;
struct wlan_network network;
if (argc < 2)
{
PRINTF("Usage: %s <profile_name>\r\n", argv[0]);
PRINTF("Error: specify network to save\r\n");
return;
}
ret = wlan_get_network_byname(argv[1], &network);
if (ret != WM_SUCCESS)
{
PRINTF("Error: network not found\r\n");
}
else
{
ret = save_wifi_network((char *)CONNECTION_INFO_FILENAME, (uint8_t *)&network, sizeof(network));
if (ret != WM_SUCCESS)
{
PRINTF("Error: write network to flash failed\r\n");
}
}
}
static void loadProfile(int argc, char **argv)
{
int ret;
struct wlan_network network;
uint32_t len = sizeof(network);
ret = get_saved_wifi_network((char *)CONNECTION_INFO_FILENAME, (uint8_t *)&network, &len);
if (ret != WM_SUCCESS || len != sizeof(network))
{
PRINTF("Error: No network saved\r\n");
}
else
{
ret = wlan_add_network(&network);
if (ret != WM_SUCCESS)
{
PRINTF("Error: network data corrupted or network already added\r\n");
}
}
}
static void resetProfile(int argc, char **argv)
{
int ret;
ret = reset_saved_wifi_network((char *)CONNECTION_INFO_FILENAME);
if (ret != WM_SUCCESS)
{
PRINTF("Error: Reset profile failed\r\n");
}
}
static void wlanIeeePowerSave(int argc, char **argv)
{
bool on = false;
bool off = false;
uint32_t cond;
int ret;
if (argc >= 2)
{
on = (strcmp(argv[1], "on") == 0);
off = (strcmp(argv[1], "off") == 0);
}
if ((argc < 2) || (!on && !off) || (on && argc < 3))
{
PRINTF("Usage: %s <on/off> [<wakeup condition>]\r\n", argv[0]);
PRINTF(" wakeup condictions needed by \"on\" command:\r\n");
PRINTF(" bit0=1: broadcast data\r\n");
PRINTF(" bit1=1: unicast data\r\n");
PRINTF(" bit2=1: mac events\r\n");
PRINTF(" bit3=1: multicast data\r\n");
PRINTF(" bit4=1: arp broadcast data\r\n");
PRINTF(" bit6=1: management frame\r\n");
return;
}
if (on)
{
cond = strtoul(argv[2], NULL, 0);
ret = wlan_ieeeps_on(cond);
}
else
{
ret = wlan_ieeeps_off();
}
if (ret != WM_SUCCESS)
{
PRINTF("Cannot request IEEE power save mode change!\r\n");
}
else
{
PRINTF("IEEE power save mode change requested!\r\n");
}
}
static void wlanDeepSleep(int argc, char **argv)
{
bool on;
int ret;
if ((argc < 2) || ((strcmp(argv[1], "on") != 0) && (strcmp(argv[1], "off") != 0)))
{
PRINTF("Usage: %s <on/off>\r\n", argv[0]);
PRINTF("Error: specify deep sleep on or off.\r\n");
return;
}
on = (strcmp(argv[1], "on") == 0);
if (on)
{
ret = wlan_deepsleepps_on();
}
else
{
ret = wlan_deepsleepps_off();
}
if (ret != WM_SUCCESS)
{
PRINTF("Cannot request deep sleep mode change!\r\n");
}
else
{
PRINTF("Deep sleep mode change requested!\r\n");
}
}
static void mcuPowerMode(int argc, char **argv)
{
uint32_t excludeIo = 0U;
if ((argc < 2) || (strlen(argv[1]) != 3) || (argv[1][0] != 'p') || (argv[1][1] != 'm') || (argv[1][2] < '0') ||
(argv[1][2] > '4') || (argv[1][2] == '3'))
{
PRINTF("Usage: %s <pm0/pm1/pm2/pm4> [<pm2_io_exclude_mask>]\r\n", argv[0]);
PRINTF(" pm2_io_exclude_mask: bitmask of io domains to keep on in PM2.\r\n");
PRINTF(" e.g. 0x5 means VDDIO0 and VDDIO2 will not be powered off in PM2\r\n");
PRINTF("Error: specify power mode to enter.\r\n");
return;
}
if (argv[1][2] - '0' == 2U)
{
if (argc < 3)
{
PRINTF("Error: PM2 need 3rd parameter.\r\n");
return;
}
else
{
excludeIo = strtoul(argv[2], NULL, 0);
}
}
LPM_SetPowerMode(argv[1][2] - '0', excludeIo);
}
*/
static void mcuInitPower(void)
{
lpm_config_t config = {
/* System PM2/PM3 less than 50 ms will be skipped. */
.threshold = 50U,
/* SFLL config and RC32M setup takes approx 14 ms. */
.latency = 15U,
.enableWakeupPin0 = true,
.enableWakeupPin1 = true,
.handler = NULL,
};
LPM_Init(&config);
}
/* Callback Function passed to WLAN Connection Manager. The callback function
* gets called when there are WLAN Events that need to be handled by the
* application.
*/
int wlan_event_callback(enum wlan_event_reason reason, void * data)
{
int ret;
struct wlan_ip_config addr;
char ip[16];
static int auth_fail = 0;
// PRINTF("[%s] WLAN: received event %d\r\n", __FUNCTION__, reason);
switch (reason)
{
case WLAN_REASON_INITIALIZED:
// PRINTF("app_cb: WLAN initialized\r\n");
#ifdef MCUXPRESSO_WIFI_CLI
ret = wlan_basic_cli_init();
if (ret != WM_SUCCESS)
{
PRINTF("Failed to initialize BASIC WLAN CLIs\r\n");
return 0;
}
ret = wlan_cli_init();
if (ret != WM_SUCCESS)
{
PRINTF("Failed to initialize WLAN CLIs\r\n");
return 0;
}
PRINTF("WLAN CLIs are initialized\r\n");
ret = ping_cli_init();
if (ret != WM_SUCCESS)
{
PRINTF("Failed to initialize PING CLI\r\n");
return 0;
}
ret = iperf_cli_init();
if (ret != WM_SUCCESS)
{
PRINTF("Failed to initialize IPERF CLI\r\n");
return 0;
}
#endif
ret = dhcpd_cli_init();
if (ret != WM_SUCCESS)
{
// PRINTF("Failed to initialize DHCP Server CLI\r\n");
return 0;
}
#ifdef MCUXPRESSO_WIFI_CLI
if (cli_register_commands(saveload, sizeof(saveload) / sizeof(struct cli_command)))
{
return -WM_FAIL;
}
if (cli_register_commands(wlanPower, sizeof(wlanPower) / sizeof(struct cli_command)))
{
return -WM_FAIL;
}
if (cli_register_commands(mcuPower, sizeof(mcuPower) / sizeof(struct cli_command)))
{
return -WM_FAIL;
}
PRINTF("CLIs Available:\r\n");
if (Matter_Selection == MCUXPRESSO_WIFI_CLI)
help_command(0, NULL);
#endif
break;
case WLAN_REASON_INITIALIZATION_FAILED:
// PRINTF("app_cb: WLAN: initialization failed\r\n");
break;
case WLAN_REASON_SUCCESS:
// PRINTF("app_cb: WLAN: connected to network\r\n");
ret = wlan_get_address(&addr);
if (ret != WM_SUCCESS)
{
// PRINTF("failed to get IP address\r\n");
return 0;
}
net_inet_ntoa(addr.ipv4.address, ip);
ret = wlan_get_current_network(&sta_network);
if (ret != WM_SUCCESS)
{
// PRINTF("Failed to get External AP network\r\n");
return 0;
}
PRINTF("Connected to following BSS:\r\n");
PRINTF("SSID = [%s], IP = [%s]\r\n", sta_network.ssid, ip);
save_network(sta_network.ssid, sta_network.security.psk);
#ifdef CONFIG_IPV6
{
int i;
(void) PRINTF("\r\n\tIPv6 Addresses\r\n");
for (i = 0; i < MAX_IPV6_ADDRESSES; i++)
{
if (sta_network.ip.ipv6[i].addr_state != IP6_ADDR_INVALID)
{
(void) PRINTF("\t%-13s:\t%s (%s)\r\n", ipv6_addr_type_to_desc(&(sta_network.ip.ipv6[i])),
inet6_ntoa(sta_network.ip.ipv6[i].address),
ipv6_addr_state_to_desc(sta_network.ip.ipv6[i].addr_state));
}
}
(void) PRINTF("\r\n");
}
#endif
auth_fail = 0;
is_connected = true;
run_update_chipsrv(dns_srv);
if (is_uap_started())
{
wlan_get_current_uap_network(&uap_network);
ret = wlan_stop_network(uap_network.name);
/* if (ret != WM_SUCCESS)
PRINTF("Error: unable to stop network\r\n");
else
PRINTF("stop uAP, SSID = [%s]\r\n", uap_network.ssid);
*/
}
break;
case WLAN_REASON_CONNECT_FAILED:
// PRINTF("app_cb: WLAN: connect failed\r\n");
break;
case WLAN_REASON_NETWORK_NOT_FOUND:
// PRINTF("app_cb: WLAN: network not found\r\n");
break;
case WLAN_REASON_NETWORK_AUTH_FAILED:
// PRINTF("app_cb: WLAN: network authentication failed\r\n");
auth_fail++;
if (auth_fail >= 3)
{
// PRINTF("Authentication Failed. Disconnecting ... \r\n");
wlan_disconnect();
auth_fail = 0;
}
break;
case WLAN_REASON_ADDRESS_SUCCESS:
// PRINTF("network mgr: DHCP new lease\r\n");
break;
case WLAN_REASON_ADDRESS_FAILED:
// PRINTF("app_cb: failed to obtain an IP address\r\n");
break;
case WLAN_REASON_USER_DISCONNECT:
// PRINTF("app_cb: disconnected\r\n");
auth_fail = 0;
break;
case WLAN_REASON_LINK_LOST:
is_connected = false;
run_update_chipsrv(dns_srv);
// PRINTF("app_cb: WLAN: link lost\r\n");
break;
case WLAN_REASON_CHAN_SWITCH:
// PRINTF("app_cb: WLAN: channel switch\r\n");
break;
case WLAN_REASON_UAP_SUCCESS:
// PRINTF("app_cb: WLAN: UAP Started\r\n");
ret = wlan_get_current_uap_network(&uap_network);
if (ret != WM_SUCCESS)
{
PRINTF("Failed to get Soft AP network\r\n");
return 0;
}
// PRINTF("Soft AP \"%s\" started successfully\r\n", uap_network.ssid);
if (dhcp_server_start(net_get_uap_handle()))
PRINTF("Error in starting dhcp server\r\n");
// PRINTF("DHCP Server started successfully\r\n");
break;
case WLAN_REASON_UAP_CLIENT_ASSOC:
PRINTF("app_cb: WLAN: UAP a Client Associated\r\n");
// PRINTF("Client => ");
// print_mac((const char *)data);
// PRINTF("Associated with Soft AP\r\n");
break;
case WLAN_REASON_UAP_CLIENT_DISSOC:
// PRINTF("app_cb: WLAN: UAP a Client Dissociated\r\n");
// PRINTF("Client => ");
// print_mac((const char *)data);
// PRINTF("Dis-Associated from Soft AP\r\n");
break;
case WLAN_REASON_UAP_STOPPED:
// PRINTF("app_cb: WLAN: UAP Stopped\r\n");
// PRINTF("Soft AP \"%s\" stopped successfully\r\n", uap_network.ssid);
dhcp_server_stop();
// PRINTF("DHCP Server stopped successfully\r\n");
break;
case WLAN_REASON_PS_ENTER:
// PRINTF("app_cb: WLAN: PS_ENTER\r\n");
break;
case WLAN_REASON_PS_EXIT:
// PRINTF("app_cb: WLAN: PS EXIT\r\n");
break;
default:
PRINTF("app_cb: WLAN: Unknown Event: %d\r\n", reason);
}
return 0;
}
#if 0
char profile[8] = "mw320";
char ssid[32] = "matter_mw320";
char psk[64] = "12345678";
char network_ip[15] = "192.168.2.1";
char network_netmask[15] = "255.255.255.0";
const uint8_t kOptionalDefaultStringTag1 = 1;
const uint8_t kOptionalDefaultStringTag2 = 2;
const uint8_t kOptionalDefaultStringTag3 = 3;
std::string createSetupPayload()
{
CHIP_ERROR err = CHIP_NO_ERROR;
std::string result;
std::string kOptionalDefaultStringValue1 = "IP:";
std::string kOptionalDefaultStringValue2 = "SSID:";
std::string kOptionalDefaultStringValue3 = "Key:";
uint16_t discriminator;
kOptionalDefaultStringValue1.append( network_ip, sizeof(network_ip) );
kOptionalDefaultStringValue2.append( ssid, sizeof(ssid) );
kOptionalDefaultStringValue3.append( psk, sizeof(psk) );
err = ConfigurationMgr().GetSetupDiscriminator(discriminator);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't get discriminator: %s\r\n", __FUNCTION__, ErrorStr(err));
return result;
}
uint32_t setupPINCode;
err = ConfigurationMgr().GetSetupPinCode(setupPINCode);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't get setupPINCode: %s\r\n", __FUNCTION__, ErrorStr(err));
return result;
}
uint16_t vendorId;
err = ConfigurationMgr().GetVendorId(vendorId);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't get vendorId: %s\r\n", __FUNCTION__, ErrorStr(err));
return result;
}
uint16_t productId;
err = ConfigurationMgr().GetProductId(productId);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't get productId: %s\r\n", __FUNCTION__, ErrorStr(err));
return result;
}
SetupPayload payload;
payload.version = 0;
payload.discriminator = discriminator;
payload.setUpPINCode = setupPINCode;
payload.rendezvousInformation.SetValue(chip::RendezvousInformationFlag::kBLE);
payload.vendorID = vendorId;
payload.productID = productId;
err = payload.addOptionalVendorData(kOptionalDefaultStringTag1, kOptionalDefaultStringValue1);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't add payload Vnedor string %d \r\n", __FUNCTION__, kOptionalDefaultStringTag1);
}
err = payload.addOptionalVendorData(kOptionalDefaultStringTag2, kOptionalDefaultStringValue2);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't add payload Vnedor string %d \r\n", __FUNCTION__, kOptionalDefaultStringTag2);
}
err = payload.addOptionalVendorData(kOptionalDefaultStringTag3, kOptionalDefaultStringValue3);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't add payload Vnedor string %d \r\n", __FUNCTION__, kOptionalDefaultStringTag3);
}
QRCodeSetupPayloadGenerator generator(payload);
size_t tlvDataLen = sizeof(kOptionalDefaultStringValue1)+sizeof(kOptionalDefaultStringValue2)+sizeof(kOptionalDefaultStringValue3);
uint8_t tlvDataStart[tlvDataLen];
err = generator.payloadBase38Representation(result, tlvDataStart, tlvDataLen);
if (err != CHIP_NO_ERROR)
{
PRINTF("[%s]: Couldn't get payload string %d \r\n", __FUNCTION__, err);
}
return result;
}
#endif // 0
#if 0
void demo_init(void)
{
struct wlan_network network;
int ret = 0;
// add uAP profile
memset(&network, 0, sizeof(struct wlan_network));
memcpy(network.name, profile, strlen(profile));
memcpy(network.ssid, ssid, strlen(ssid));
network.channel = 1;
network.ip.ipv4.address = net_inet_aton(network_ip);
network.ip.ipv4.gw = net_inet_aton(network_ip);
network.ip.ipv4.netmask = net_inet_aton(network_netmask);
network.ip.ipv4.addr_type = ADDR_TYPE_STATIC;
network.security.psk_len = strlen(psk);
strcpy(network.security.psk, psk);
network.security.type = WLAN_SECURITY_WPA2;
network.role = WLAN_BSS_ROLE_UAP;
ret = wlan_add_network(&network);
switch (ret)
{
case WM_SUCCESS:
PRINTF("Added \"%s\"\r\n", network.name);
break;
case -WM_E_INVAL:
PRINTF("Error: network already exists or invalid arguments\r\n");
break;
case -WM_E_NOMEM:
PRINTF("Error: network list is full\r\n");
break;
case WLAN_ERROR_STATE:
PRINTF("Error: can't add networks in this state\r\n");
break;
default:
PRINTF(
"Error: unable to add network for unknown"
" reason\r\n");
break;
}
// start uAP
ret = wlan_start_network(profile);
if (ret != WM_SUCCESS)
PRINTF("Error: unable to start network\r\n");
else
PRINTF("start uAP ssid: %s\r\n", network.ssid);
}
#endif // 0
void task_main(void * param)
{
#if 0
int32_t result = 0;
flash_desc_t fl;
struct partition_entry *p, *f1, *f2;
short history = 0;
uint32_t *wififw;
#ifdef CONFIG_USE_PSM
struct partition_entry *psm;
#endif
mcuInitPower();
boot_init();
mflash_drv_init();
PRINTF("[%s]: Initialize CLI\r\n", __FUNCTION__);
result = cli_init();
if (WM_SUCCESS != result)
{
assert(false);
}
PRINTF("[%s]: Initialize WLAN Driver\r\n", __FUNCTION__);
result = part_init();
if (WM_SUCCESS != result)
{
assert(false);
}
#ifdef CONFIG_USE_PSM
psm = part_get_layout_by_id(FC_COMP_PSM, NULL);
part_to_flash_desc(psm, &fl);
#else
fl.fl_dev = 0U;
fl.fl_start = MFLASH_FILE_BASEADDR;
fl.fl_size = MFLASH_FILE_SIZE;
#endif
init_flash_storage((char *)CONNECTION_INFO_FILENAME, &fl);
f1 = part_get_layout_by_id(FC_COMP_WLAN_FW, &history);
f2 = part_get_layout_by_id(FC_COMP_WLAN_FW, &history);
if (f1 && f2)
{
p = part_get_active_partition(f1, f2);
}
else if (!f1 && f2)
{
p = f2;
}
else if (!f2 && f1)
{
p = f1;
}
else
{
PRINTF("[%s]: Wi-Fi Firmware not detected\r\n", __FUNCTION__);
p = NULL;
}
if (p != NULL)
{
part_to_flash_desc(p, &fl);
wififw = (uint32_t *)mflash_drv_phys2log(fl.fl_start, fl.fl_size);
assert(wififw != NULL);
/* First word in WIFI firmware is magic number. */
assert(*wififw == (('W' << 0) | ('L' << 8) | ('F' << 16) | ('W' << 24)));
/* Initialize WIFI Driver */
/* Second word in WIFI firmware is WIFI firmware length in bytes. */
/* Real WIFI binary starts from 3rd word. */
result = wlan_init((const uint8_t *)(wififw + 2U), *(wififw + 1U));
if (WM_SUCCESS != result)
{
assert(false);
}
PRINTF("[%s]: wlan_init success \r\n", __FUNCTION__);
result = wlan_start(wlan_event_callback);
if (WM_SUCCESS != result)
{
assert(false);
}
}
while (true)
{
/* wait for interface up */
os_thread_sleep(os_msec_to_ticks(5000));
PRINTF("[%s]: looping\r\n", __FUNCTION__);
}
#endif // 0
}
static void run_chip_srv(System::Layer * aSystemLayer, void * aAppState)
{
// Init ZCL Data Model and CHIP App Server
{
// Initialize device attestation config
#if (defined(CONFIG_CHIP_MW320_REAL_FACTORY_DATA) && (CONFIG_CHIP_MW320_REAL_FACTORY_DATA == 1))
FactoryDataProvider::GetDefaultInstance().Init();
#if (CHIP_DEVICE_CONFIG_ENABLE_DEVICE_INSTANCE_INFO_PROVIDER == 1)
SetDeviceInstanceInfoProvider(&FactoryDataProvider::GetDefaultInstance());
#endif // USE_LOCAL_DEVICEINSTANCEINFOPROVIDER
SetDeviceAttestationCredentialsProvider(&FactoryDataProvider::GetDefaultInstance());
SetCommissionableDataProvider(&FactoryDataProvider::GetDefaultInstance());
#else
SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
#endif // CONFIG_CHIP_MW320_REAL_FACTORY_DATA
}
{
// chip::Server::GetInstance().Init();
// uint16_t securePort = CHIP_PORT;
// uint16_t unsecurePort = CHIP_UDC_PORT;
// PRINTF("==> call chip::Server() \r\n");
// chip::Server::GetInstance().Init(nullptr, securePort, unsecurePort);
static chip::CommonCaseDeviceServerInitParams initParams;
(void) initParams.InitializeStaticResourcesBeforeServerInit();
chip::Server::GetInstance().Init(initParams);
PRINTF("Done to call chip::Server() \r\n");
}
// ota ++
{
InitOTARequestor();
#if (MW320_OTA_TEST == 1)
// for ota module test
mw320_fw_update_test();
#endif // MW320_OTA_TEST
}
// ota --
// binding ++
InitBindingHandlers();
// binding --
return;
}
static void run_dnssrv(System::Layer * aSystemLayer, void * aAppState)
{
chip::app::DnssdServer::Instance().StartServer();
if (is_connected == true)
{
led_on_off(led_amber, true);
}
else
{
led_on_off(led_amber, false);
}
return;
}
#define RUN_CHIPSRV_DELAY 1
static void run_update_chipsrv(srv_type_t srv_type)
{
switch (srv_type)
{
case chip_srv_all:
DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(RUN_CHIPSRV_DELAY), run_chip_srv, nullptr);
break;
case dns_srv:
DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(RUN_CHIPSRV_DELAY), run_dnssrv, nullptr);
break;
default:
return;
}
return;
}
//=============================================================================
// Light behaior while resetting the saved arguments
//
static void rst_args_lt(System::Layer * aSystemLayer, void * aAppState)
{
// PRINTF("%s(), Turn on lights \r\n", __FUNCTION__);
led_on_off(led_amber, true);
led_on_off(led_yellow, true);
// sleep 3 second
// PRINTF("%s(), sleep 3 seconds \r\n", __FUNCTION__);
os_thread_sleep(os_msec_to_ticks(3000));
// PRINTF("%s(), Turn off lights \r\n", __FUNCTION__);
led_on_off(led_amber, false);
led_on_off(led_yellow, false);
return;
}
void task_test_main(void * param)
{
while (true)
{
/* wait for interface up */
os_thread_sleep(os_msec_to_ticks(500));
/*PRINTF("[%s]: looping\r\n", __FUNCTION__);*/
if (need2sync_sw_attr == true)
{
static bool is_on = false;
uint16_t value = g_ButtonPress & 0x1;
is_on = !is_on;
value = (uint16_t) is_on;
// sync-up the switch attribute:
PRINTF("--> update ZCL_CURRENT_POSITION_ATTRIBUTE_ID [%d] \r\n", value);
emAfWriteAttribute(1, Clusters::Switch::Id, ZCL_CURRENT_POSITION_ATTRIBUTE_ID, (uint8_t *) &value, sizeof(value), true,
false);
#ifdef SUPPORT_MANUAL_CTRL
// sync-up the Light attribute (for test event, OO.M.ManuallyControlled)
PRINTF("--> update [Clusters::Switch::Id]: ZCL_ON_OFF_ATTRIBUTE_ID [%d] \r\n", value);
emAfWriteAttribute(1, Clusters::Switch::Id, ZCL_ON_OFF_ATTRIBUTE_ID, (uint8_t *) &value, sizeof(value), true, false);
#endif // SUPPORT_MANUAL_CTRL
need2sync_sw_attr = false;
}
// =============================
// Call sw2_handle to clear click_count if needed
sw2_handle(false);
// =============================
}
return;
}
void init_mw320_sdk()
{
flash_desc_t fl;
struct partition_entry *p, *f1, *f2;
short history = 0;
uint32_t * wififw;
struct partition_entry * psm;
struct partition_entry * manu_dat;
uint8_t * pmfdat;
PRINTF("=> init mw320 sdk \r\n");
PRINTF("call mcuInitPower() \r\n");
mcuInitPower();
boot_init();
mflash_drv_init();
cli_init();
part_init();
psm = part_get_layout_by_id(FC_COMP_PSM, NULL);
part_to_flash_desc(psm, &fl);
init_flash_storage((char *) CONNECTION_INFO_FILENAME, &fl);
PRINTF("[PSM]: (start, len)=(0x%x, 0x%x)\r\n", fl.fl_start, fl.fl_size);
manu_dat = part_get_layout_by_id(FC_COMP_USER_APP, NULL);
part_to_flash_desc(manu_dat, &fl);
PRINTF("[Manufacture_Data]: (start, len)=(0x%x, 0x%x)\r\n", fl.fl_start, fl.fl_size);
pmfdat = (uint8_t *) mflash_drv_phys2log(fl.fl_start, fl.fl_size);
__FACTORY_DATA_START = pmfdat;
__FACTORY_DATA_SIZE = (uint32_t) fl.fl_size;
f1 = part_get_layout_by_id(FC_COMP_WLAN_FW, &history);
f2 = part_get_layout_by_id(FC_COMP_WLAN_FW, &history);
if (f1 && f2)
{
p = part_get_active_partition(f1, f2);
}
else if (!f1 && f2)
{
p = f2;
}
else if (!f2 && f1)
{
p = f1;
}
else
{
// PRINTF("[%s]: Wi-Fi Firmware not detected\r\n", __FUNCTION__);
p = NULL;
}
if (p != NULL)
{
part_to_flash_desc(p, &fl);
wififw = (uint32_t *) mflash_drv_phys2log(fl.fl_start, fl.fl_size);
// assert(wififw != NULL);
/* First word in WIFI firmware is magic number. */
assert(*wififw == (('W' << 0) | ('L' << 8) | ('F' << 16) | ('W' << 24)));
wlan_init((const uint8_t *) (wififw + 2U), *(wififw + 1U));
// PRINTF("[%s]: wlan_init success \r\n", __FUNCTION__);
wlan_start(wlan_event_callback);
// demo_init();
os_thread_sleep(os_msec_to_ticks(5000));
}
PRINTF(" mw320 init complete! \r\n");
return;
}
void ShellCLIMain(void * pvParameter)
{
const int rc = streamer_init(streamer_get());
if (rc != 0)
{
ChipLogError(Shell, "Streamer initialization failed: %d", rc);
return;
}
PRINTF("version: [%s] \r\n", VERSION_STR);
// Initialize the SDK components
init_mw320_sdk();
ChipLogDetail(Shell, "Initializing CHIP shell commands: %d", rc);
chip::Platform::MemoryInit();
chip::DeviceLayer::PlatformMgr().InitChipStack();
ConfigurationMgr().LogDeviceConfig();
PrintOnboardingCodes(chip::RendezvousInformationFlag::kOnNetwork);
chip::DeviceLayer::PlatformMgr().StartEventLoopTask();
#if CHIP_DEVICE_CONFIG_ENABLE_WPA
chip::DeviceLayer::ConnectivityManagerImpl().StartWiFiManagement();
#endif
cmd_misc_init();
// cmd_otcli_init();
ChipLogDetail(Shell, "Run CHIP shell Task: %d", rc);
// std::string qrCodeText = createSetupPayload();
// PRINTF("SetupQRCode: [%s]\r\n", qrCodeText.c_str());
{
char def_ssid[IEEEtypes_SSID_SIZE + 1];
char def_psk[WLAN_PSK_MAX_LENGTH];
load_network(def_ssid, def_psk);
if ((strlen(def_ssid) <= 0) || (strlen(def_psk) <= 0))
{
// No saved connected_ap_info => Using the default ssid/password
strcpy(def_ssid, "nxp_matter");
strcpy(def_psk, "nxp12345");
}
PRINTF("Connecting to [%s, %s] \r\n", def_ssid, def_psk);
// TODO: ConnectivityMgrImpl is the platform implementation of ConnectivityMgr layer.
// Application should use the APIs defined src/include/platform to talk to the Matter
// platfrom layer, instead of calling into the functions defined in the platform implemenation.
// ConnectivityMgrImpl().ProvisionWiFiNetwork(def_ssid, def_psk);
}
// Run CHIP servers
run_update_chipsrv(chip_srv_all);
Engine::Root().RunMainLoop();
}
static void led_on_off(led_id_t lt_id, bool is_on)
{
GPIO_Type * pgpio;
uint32_t gpio_pin;
// Configure the GPIO / PIN
switch (lt_id)
{
case led_amber:
pgpio = BOARD_LED_AMBER_GPIO;
gpio_pin = BOARD_LED_AMBER_GPIO_PIN;
break;
case led_yellow:
default: // Note: led_yellow as default
pgpio = BOARD_LED_YELLOW_GPIO;
gpio_pin = BOARD_LED_YELLOW_GPIO_PIN;
}
// Do on/off the LED
if (is_on == true)
{
// PRINTF("led on\r\n");
GPIO_PortClear(pgpio, GPIO_PORT(gpio_pin), 1u << GPIO_PORT_PIN(gpio_pin));
}
else
{
// PRINTF("led off\r\n");
GPIO_PortSet(pgpio, GPIO_PORT(gpio_pin), 1u << GPIO_PORT_PIN(gpio_pin));
}
return;
}
} // namespace
int StartShellTask(void)
{
int ret = 0;
// Start Shell task.
switch (Matter_Selection)
{
case MCUXPRESSO_WIFI_CLI:
#ifdef MCUXPRESSO_WIFI_CLI
if (xTaskCreate(task_main, "main", TASK_MAIN_STACK_SIZE, task_main_stack, TASK_MAIN_PRIO, &task_main_task_handler) !=
pdPASS)
{
ret = -1;
}
break;
#endif
case MATTER_SHELL:
default:
if (xTaskCreate(ShellCLIMain, "SHELL", TASK_MAIN_STACK_SIZE, NULL, TASK_MAIN_PRIO, &sShellTaskHandle) != pdPASS)
{
ret = -1;
}
if (xTaskCreate(task_test_main, "testmain", TASK_MAIN_STACK_SIZE, task_main_stack, TASK_MAIN_PRIO,
&task_main_task_handler) != pdPASS)
{
PRINTF("Failed to crete task_test_main() \r\n");
ret = -1;
}
break;
}
return ret;
}
#define gpio_led_cfg(base, pin, cfg) \
{ \
GPIO_PinInit(base, pin, cfg); \
GPIO_PortSet(base, GPIO_PORT(pin), 1u << GPIO_PORT_PIN(pin)); \
}
#define gpio_sw_cfg(base, pin, cfg, irq, trig) \
{ \
GPIO_PinInit(base, pin, cfg); \
GPIO_PinSetInterruptConfig(base, pin, trig); \
GPIO_PortEnableInterrupts(base, GPIO_PORT(pin), 1UL << GPIO_PORT_PIN(pin)); \
EnableIRQ(irq); \
}
void gpio_init(void)
{
gpio_pin_config_t led_config = {
kGPIO_DigitalOutput,
0,
};
gpio_pin_config_t sw_config = {
kGPIO_DigitalInput,
0,
};
/* Init output amber led gpio off */
gpio_led_cfg(BOARD_LED_AMBER_GPIO, BOARD_LED_AMBER_GPIO_PIN, &led_config);
/* Init output yellow led gpio off */
gpio_led_cfg(BOARD_LED_YELLOW_GPIO, BOARD_LED_YELLOW_GPIO_PIN, &led_config);
/* Init/config input sw_1 GPIO. */
gpio_sw_cfg(BOARD_SW1_GPIO, BOARD_SW1_GPIO_PIN, &sw_config, BOARD_SW1_IRQ, kGPIO_InterruptFallingEdge);
/* Init/config input sw_2 GPIO. */
gpio_sw_cfg(BOARD_SW2_GPIO, BOARD_SW2_GPIO_PIN, &sw_config, BOARD_SW2_IRQ, kGPIO_InterruptFallingEdge);
return;
}
int main(void)
{
// char ch;
// unsigned int bp;
// unsigned int mw320_sec = 9000000;
// unsigned int default_ch;
// unsigned int default_1= 0;
// unsigned int default_2= 0;
/* Initialize platform */
// BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
#ifdef MCUXPRESSO_WIFI_CLI
PRINTF("\nPlease Select [1/2] => 1. MCUXpress format 2. Matter format. \r\n");
do
{
ch = GETCHAR();
PUTCHAR(ch);
if (ch == '1')
Matter_Selection = MCUXPRESSO_WIFI_CLI;
else if (ch == '2')
Matter_Selection = MATTER_SHELL;
} while (ch != '\r');
if (Matter_Selection == MAX_SELECTION)
Matter_Selection = MATTER_SHELL;
PRINTF("\n\n[%s]: MW320 %s .\r\n", __FUNCTION__,
(Matter_Selection == MCUXPRESSO_WIFI_CLI) ? "MCUXPresso WiFi CLI" : "Matter Shell");
#else
#ifdef CONFIGURE_UAP
PRINTF("\nDo you want to use the default SSID and key for mw320 uAP? [y/n]\r\n");
do
{
ch = GETCHAR();
PUTCHAR(ch);
if (ch == 'n')
{
PRINTF("\nPlease input your SSID: [ 1 ~ 32 characters]\r\n");
bp = 0;
do
{
ssid[bp] = GETCHAR();
PUTCHAR(ssid[bp]);
bp++;
if (bp > sizeof(ssid))
{
PRINTF("\n ERROR: your SSID length=%d is larger than %d \r\n", bp, sizeof(ssid));
return 0;
}
} while (ssid[bp - 1] != '\r');
ssid[bp - 1] = '\0';
PRINTF("\nPlease input your KEY: [ 8 ~ 63 characters]\r\n");
bp = 0;
do
{
psk[bp] = GETCHAR();
PUTCHAR(psk[bp]);
bp++;
if (bp > sizeof(psk))
{
PRINTF("\n ERROR: your KEY length=%d is larger than %d \r\n", bp, sizeof(psk));
return 0;
}
} while (psk[bp - 1] != '\r');
psk[bp - 1] = '\0';
if ((bp - 1) < 8)
{
PRINTF("\n ERROR: KEY length=%d is less than 8 \r\n", (bp - 1));
return 0;
}
break;
}
if (ch == '\r')
{
break;
}
} while (ch != 'y');
#endif
#endif
// PRINTF("\nMW320 uAP SSID=%s key=%s ip=%s \r\n", ssid, psk, network_ip);
CLOCK_EnableXtal32K(kCLOCK_Osc32k_External);
CLOCK_AttachClk(kXTAL32K_to_RTC);
aesLock = xSemaphoreCreateRecursiveMutex();
assert(aesLock != NULL);
AES_Init(APP_AES);
AES_SetLockFunc(APP_AES_Lock, APP_AES_Unlock);
gpio_init();
StartShellTask();
/* Start FreeRTOS */
vTaskStartScheduler();
return 0;
}
bool lowPowerClusterSleep()
{
return true;
}
static void OnOnOffPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value)
{
VerifyOrExit(attributeId == ZCL_ON_OFF_ATTRIBUTE_ID,
ChipLogError(DeviceLayer, "Unhandled Attribute ID: '0x%04lx", attributeId));
VerifyOrExit(endpointId == 1 || endpointId == 2, ChipLogError(DeviceLayer, "Unexpected EndPoint ID: `0x%02x'", endpointId));
// At this point we can assume that value points to a bool value.
led_on_off(led_yellow, (*value != 0) ? true : false);
exit:
return;
}
static void OnSwitchAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value)
{
// auto * pimEngine = chip::app::InteractionModelEngine::GetInstance();
// bool do_sendrpt = false;
VerifyOrExit(attributeId == ZCL_CURRENT_POSITION_ATTRIBUTE_ID,
ChipLogError(DeviceLayer, "Unhandled Attribute ID: '0x%04lx", attributeId));
// Send the switch status report now
/*
for (uint32_t i = 0 ; i<pimEngine->GetNumActiveReadHandlers() ; i++) {
ReadHandler * phandler = pimEngine->ActiveHandlerAt(i);
if (phandler->IsType(chip::app::ReadHandler::InteractionType::Subscribe) &&
(phandler->IsGeneratingReports() || phandler->IsAwaitingReportResponse())) {
phandler->UnblockUrgentEventDelivery();
do_sendrpt = true;
break;
}
}
if (do_sendrpt == true) {
ConcreteEventPath event_path(endpointId, Clusters::Switch::Id, 0);
pimEngine->GetReportingEngine().ScheduleEventDelivery(event_path, chip::app::EventOptions::Type::kUrgent,
sizeof(uint16_t));
}
*/
exit:
return;
}
uint32_t identifyTimerCount;
constexpr uint32_t kIdentifyTimerDelayMS = 250;
typedef struct _Identify_Timer
{
EndpointId ep;
uint32_t identifyTimerCount;
} Identify_Time_t;
Identify_Time_t id_time[MAX_ENDPOINT_COUNT];
void IdentifyTimerHandler(System::Layer * systemLayer, void * appState)
{
Identify_Time_t * pidt = (Identify_Time_t *) appState;
PRINTF(" -> %s(%u, %u) \r\n", __FUNCTION__, pidt->ep, pidt->identifyTimerCount);
if (pidt->identifyTimerCount)
{
pidt->identifyTimerCount--;
emAfWriteAttribute(pidt->ep, Clusters::Identify::Id, ZCL_IDENTIFY_TIME_ATTRIBUTE_ID, (uint8_t *) &pidt->identifyTimerCount,
sizeof(identifyTimerCount), true, false);
DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(1), IdentifyTimerHandler, pidt);
}
}
static void OnIdentifyPostAttributeChangeCallback(EndpointId endpointId, AttributeId attributeId, uint8_t * value)
{
VerifyOrExit(attributeId == ZCL_IDENTIFY_TIME_ATTRIBUTE_ID,
ChipLogError(DeviceLayer, "[%s] Unhandled Attribute ID: '0x%04lx", TAG, attributeId));
VerifyOrExit((endpointId < MAX_ENDPOINT_COUNT),
ChipLogError(DeviceLayer, "[%s] EndPoint > max: [%u, %u]", TAG, endpointId, MAX_ENDPOINT_COUNT));
if (id_time[endpointId].identifyTimerCount != *value)
{
id_time[endpointId].ep = endpointId;
id_time[endpointId].identifyTimerCount = *value;
PRINTF("-> Identify: %u \r\n", id_time[endpointId].identifyTimerCount);
DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(1), IdentifyTimerHandler, &id_time[endpointId]);
}
exit:
return;
}
/*
Callback to receive the cluster modification event
*/
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & path, uint8_t type, uint16_t size, uint8_t * value)
{
PRINTF("==> MatterPostAttributeChangeCallback, cluster: %x, attr: %x, size: %d \r\n", path.mClusterId, path.mAttributeId, size);
// path.mEndpointId, path.mClusterId, path.mAttributeId, mask, type, size, value
switch (path.mClusterId)
{
case Clusters::OnOff::Id:
OnOnOffPostAttributeChangeCallback(path.mEndpointId, path.mAttributeId, value);
break;
case Clusters::Switch::Id:
OnSwitchAttributeChangeCallback(path.mEndpointId, path.mAttributeId, value);
// SwitchToggleOnOff();
// Trigger to send on/off/toggle command to the bound devices
chip::BindingManager::GetInstance().NotifyBoundClusterChanged(1, chip::app::Clusters::OnOff::Id, nullptr);
break;
case Clusters::Identify::Id:
OnIdentifyPostAttributeChangeCallback(path.mEndpointId, path.mAttributeId, value);
break;
default:
break;
}
return;
}
EmberAfStatus emberAfExternalAttributeWriteCallback(EndpointId endpoint, ClusterId clusterId,
const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer)
{
PRINTF("====> %s() \r\n", __FUNCTION__);
return EMBER_ZCL_STATUS_SUCCESS;
}
EmberAfStatus emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
const EmberAfAttributeMetadata * attributeMetadata, uint8_t * buffer,
uint16_t maxReadLength)
{
// Added for the pairing of TE9 to report the commission_info
// default function (in callback-stub.cpp)
//
PRINTF("-> %s()\n\r", __FUNCTION__);
return EMBER_ZCL_STATUS_SUCCESS;
}