From 2351713f8136f2d8f644c13380e552be2466f8fa Mon Sep 17 00:00:00 2001 From: Martin Turon Date: Thu, 10 Feb 2022 15:36:13 -0800 Subject: [PATCH] [esp] Add status screen to all-clusters-app on M5Stack (#14986) * [m5] Add status screen to M5Stack. * [m5] Add status screen to esp for FabricId/Idx, NodeId, and IP addresses. * [m5] Correct some comments. * [m5] Use lib defined Inet::IPAddress::kMaxStringLength. * [m5] Update comment on what screen displays. * [m5] Reference issue #15049 deferral. * Apply suggestions from code review Use simplified call to `IPAddress::ToString()`. Co-authored-by: Boris Zbarsky Co-authored-by: Boris Zbarsky --- .../esp32/main/StatusScreen.cpp | 189 ++++++++++++++++++ .../esp32/main/include/StatusScreen.h | 45 +++++ examples/all-clusters-app/esp32/main/main.cpp | 6 + src/credentials/FabricTable.h | 2 + 4 files changed, 242 insertions(+) create mode 100644 examples/all-clusters-app/esp32/main/StatusScreen.cpp create mode 100644 examples/all-clusters-app/esp32/main/include/StatusScreen.h diff --git a/examples/all-clusters-app/esp32/main/StatusScreen.cpp b/examples/all-clusters-app/esp32/main/StatusScreen.cpp new file mode 100644 index 00000000000000..55f42a32723823 --- /dev/null +++ b/examples/all-clusters-app/esp32/main/StatusScreen.cpp @@ -0,0 +1,189 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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 StatusScreen.cpp + * + * Screen which displays device state and status: + * - Fabric Index : none | # + * - Fabric ID : none | # + * - Node ID : none | # + * - UDP Port : # + * - IPv4 : none | addr + * - IPv6 LL : none | addr + * - IPv6 ULA : none | addr + */ + +#include "StatusScreen.h" + +#if CONFIG_HAVE_DISPLAY + +#include "esp_log.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include +#include + +#include +#include + +#define MAX_LENGTH_SMALL_FONT 30 + +using namespace chip; + +class StatusListModel : public ListScreen::Model +{ +public: + enum + { + kStatusItemFabricIndex, + kStatusItemFabricId, + kStatusItemNodeId, + kStatusItemPort, + kStatusItemIp4, + kStatusItemIp6LinkLocal, + kStatusItemIp6Ula, + }; + + StatusListModel() + { + options.emplace_back("FabricIndex : none"); + options.emplace_back("FabricID : none"); + options.emplace_back("NodeID : none"); + options.emplace_back("UDP port : " + std::to_string(CHIP_PORT)); + options.emplace_back("IPv4 : none"); + options.emplace_back("IPv6 LL : none"); + options.emplace_back("IPv6 ULA : none"); + } + + virtual std::string GetTitle() { return "Status"; } + + virtual int GetItemCount() { return options.size(); } + virtual std::string GetItemText(int i) + { + std::string itemString = options.at(i); + switch (i) + { + case kStatusItemFabricIndex: { + for (const auto & fb : Server::GetInstance().GetFabricTable()) + { + FabricIndex fabricIndex = fb.GetFabricIndex(); + itemString = "FabricIdx : " + std::to_string(fabricIndex); + break; // Only print first fabric for now + } + break; + } + + case kStatusItemFabricId: { + for (const auto & fb : Server::GetInstance().GetFabricTable()) + { + FabricId fabricId = fb.GetFabricId(); + itemString = "FabricID : " + std::to_string(fabricId); + break; // Only print first fabric for now + } + break; + } + + case kStatusItemNodeId: { + for (const auto & fb : Server::GetInstance().GetFabricTable()) + { + NodeId nodeId = fb.GetNodeId(); + itemString = "NodeID : " + std::to_string(nodeId); + break; // Only print first fabric for now + } + break; + } + + case kStatusItemIp4: { + chip::Inet::IPAddress addr; + for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next()) + { + if ((it.GetAddress(addr) == CHIP_NO_ERROR) && addr.IsIPv4()) + { + char buf[Inet::IPAddress::kMaxStringLength]; + addr.ToString(buf); + itemString = std::string(buf); + break; // Only print first IPv4 address for now + } + } + break; + } + + case kStatusItemIp6LinkLocal: { + chip::Inet::IPAddress addr; + for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next()) + { + if ((it.GetAddress(addr) == CHIP_NO_ERROR) && addr.IsIPv6LinkLocal()) + { + char buf[Inet::IPAddress::kMaxStringLength]; + addr.ToString(buf); + itemString = std::string(buf); + if (itemString.length() < MAX_LENGTH_SMALL_FONT) + { + TFT_setFont(SMALL_FONT, nullptr); + } + else + { + TFT_setFont(DEF_SMALL_FONT, nullptr); + } + break; // Only print first IPv6 LL for now + } + } + break; + } + + case kStatusItemIp6Ula: { + chip::Inet::IPAddress addr; + for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next()) + { + if ((it.GetAddress(addr) == CHIP_NO_ERROR) && addr.IsIPv6ULA()) + { + char buf[Inet::IPAddress::kMaxStringLength]; + addr.ToString(buf); + itemString = std::string(buf); + if (itemString.length() < MAX_LENGTH_SMALL_FONT) + { + TFT_setFont(SMALL_FONT, nullptr); + } + else + { + TFT_setFont(DEF_SMALL_FONT, nullptr); + } + break; // Only print first IPv6 ULA for now + } + } + break; + } + } + ESP_LOGI("M5 UI", "Display status %d: %s", i, itemString.c_str()); + + return itemString; + } + + virtual void ItemAction(int i) {} + +private: + std::vector options; +}; + +StatusScreen::StatusScreen() : ListScreen(chip::Platform::New()) {} + +#endif // CONFIG_HAVE_DISPLAY diff --git a/examples/all-clusters-app/esp32/main/include/StatusScreen.h b/examples/all-clusters-app/esp32/main/include/StatusScreen.h new file mode 100644 index 00000000000000..621604804aa923 --- /dev/null +++ b/examples/all-clusters-app/esp32/main/include/StatusScreen.h @@ -0,0 +1,45 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * 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 StatusScreen.h + * + * Screen which displays a QR code. + * + */ + +#pragma once + +#include "ListScreen.h" +#include "ScreenManager.h" + +#if CONFIG_HAVE_DISPLAY + +#include +#include + +class StatusScreen : public ListScreen +{ + +public: + StatusScreen(); + + virtual ~StatusScreen() {} +}; + +#endif // CONFIG_HAVE_DISPLAY diff --git a/examples/all-clusters-app/esp32/main/main.cpp b/examples/all-clusters-app/esp32/main/main.cpp index 0bc91a2c23c9cd..025d208b89fdb1 100644 --- a/examples/all-clusters-app/esp32/main/main.cpp +++ b/examples/all-clusters-app/esp32/main/main.cpp @@ -27,6 +27,7 @@ #include "QRCodeScreen.h" #include "ScreenManager.h" #include "ShellCommands.h" +#include "StatusScreen.h" #include "WiFiWidget.h" #include "esp_heap_caps_init.h" #include "esp_log.h" @@ -706,6 +707,11 @@ extern "C" void app_main() ESP_LOGI(TAG, "Opening Setup list"); ScreenManager::PushScreen(chip::Platform::New(chip::Platform::New())); }) + ->Item("Status", + [=]() { + ESP_LOGI(TAG, "Opening Status screen"); + ScreenManager::PushScreen(chip::Platform::New()); + }) ->Item("Custom", []() { ESP_LOGI(TAG, "Opening custom screen"); diff --git a/src/credentials/FabricTable.h b/src/credentials/FabricTable.h index 631f3cf5dc2ffc..e394f3e9563a79 100644 --- a/src/credentials/FabricTable.h +++ b/src/credentials/FabricTable.h @@ -142,6 +142,8 @@ class DLL_EXPORT FabricInfo ReleaseOperationalCerts(); } + NodeId GetNodeId() const { return mOperationalId.GetNodeId(); } + // TODO(#15049): Refactor/rename PeerId to OperationalId or OpId throughout source PeerId GetPeerId() const { return mOperationalId; } PeerId GetPeerIdForNode(const NodeId node) const {