From 6a175e7dbc7f793e0ae2a97b51e38ced5462f6ff Mon Sep 17 00:00:00 2001 From: sieren Date: Thu, 30 May 2019 17:51:22 +0200 Subject: [PATCH 1/7] Add HomeKit Submodules --- .gitmodules | 12 ++++++++++++ components/cJSON | 1 + components/homekit | 1 + components/http-parser | 1 + components/wolfssl | 1 + sdkconfig | 8 +++++++- 6 files changed, 23 insertions(+), 1 deletion(-) create mode 160000 components/cJSON create mode 160000 components/homekit create mode 160000 components/http-parser create mode 160000 components/wolfssl diff --git a/.gitmodules b/.gitmodules index d3d8014..dfaaa35 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,15 @@ [submodule "main/libraries/variant"] path = main/libraries/variant url = https://github.com/mpark/variant.git +[submodule "components/homekit"] + path = components/homekit + url = https://github.com/sieren/esp-homekit.git +[submodule "components/http-parser"] + path = components/http-parser + url = https://github.com/sieren/esp-http-parser.git +[submodule "components/wolfssl"] + path = components/wolfssl + url = https://github.com/sieren/esp-wolfssl.git +[submodule "components/cJSON"] + path = components/cJSON + url = https://github.com/sieren/esp-cjson.git diff --git a/components/cJSON b/components/cJSON new file mode 160000 index 0000000..784e97f --- /dev/null +++ b/components/cJSON @@ -0,0 +1 @@ +Subproject commit 784e97f378243df16eb6e9301f43ab522aa2706f diff --git a/components/homekit b/components/homekit new file mode 160000 index 0000000..439e2e7 --- /dev/null +++ b/components/homekit @@ -0,0 +1 @@ +Subproject commit 439e2e77c61fad277354ae193e86e33983d50592 diff --git a/components/http-parser b/components/http-parser new file mode 160000 index 0000000..a0f9c3b --- /dev/null +++ b/components/http-parser @@ -0,0 +1 @@ +Subproject commit a0f9c3b986112cb62eaf58c68d1b3315b4d9687f diff --git a/components/wolfssl b/components/wolfssl new file mode 160000 index 0000000..04de416 --- /dev/null +++ b/components/wolfssl @@ -0,0 +1 @@ +Subproject commit 04de416bd7642c1f9053caa3e3022c84053e892a diff --git a/sdkconfig b/sdkconfig index 01b7f3c..76e2655 100644 --- a/sdkconfig +++ b/sdkconfig @@ -516,7 +516,9 @@ CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y # CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1 is not set CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" -# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +CONFIG_SPI_FLASH_VERIFY_WRITE=y +CONFIG_SPI_FLASH_LOG_FAILED_WRITE=y +# CONFIG_SPI_FLASH_WARN_SETTING_ZERO_TO_ONE is not set # CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y CONFIG_SPIFFS_MAX_PARTITIONS=3 @@ -552,6 +554,10 @@ CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128 # CONFIG_WL_SECTOR_SIZE_512 is not set CONFIG_WL_SECTOR_SIZE_4096=y CONFIG_WL_SECTOR_SIZE=4096 +CONFIG_HOMEKIT_SPI_FLASH_BASE_ADDR="0x200000" +CONFIG_HOMEKIT_MAX_CLIENTS=16 +# CONFIG_HOMEKIT_SMALL is not set +# CONFIG_HOMEKIT_DEBUG is not set # CONFIG_LEGACY_INCLUDE_COMMON_HEADERS is not set # Deprecated options for backward compatibility From 02202256276097a45c4569ec6151cd0305ab5976 Mon Sep 17 00:00:00 2001 From: sieren Date: Fri, 31 May 2019 16:39:38 +0200 Subject: [PATCH 2/7] Add First iteration HK C API First iteration of HomeKit C API --- CMakeLists.txt | 6 ++++ main/CMakeLists.txt | 8 +++++ main/homekit/hkapi.c | 80 ++++++++++++++++++++++++++++++++++++++++++++ main/homekit/hkapi.h | 4 +++ 4 files changed, 98 insertions(+) create mode 100644 main/homekit/hkapi.c create mode 100644 main/homekit/hkapi.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fa9a478..8824391 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,4 +11,10 @@ list(APPEND compile_definitions "ARDUINO=202000") # pending PR: https://github.com/VSChina/ESP32_AzureIoT_Arduino/pull/15 list(APPEND compile_options "-Wno-maybe-uninitialized") +set(EXTRA_COMPONENT_DIRS +"components/esp-wolfssl/" +"components/http-parser" +) + + project(homepoint) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 2cde7c5..dc19f16 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -17,6 +17,13 @@ file(GLOB FS_SRC "${FS_SRC_PATH}/Filesystem.cpp" ) + +set(HOMEKIT_SRC_PATH "homekit") +file(GLOB HOMEKIT_SRC + "${HOMEKIT_SRC_PATH}/hkapi.c" +) + + set(MQTT_SRC_PATH "mqtt") file(GLOB MQTT_SRC "${MQTT_SRC_PATH}/MQTTConnection.cpp" @@ -72,6 +79,7 @@ set(COMPONENT_SRCS "AppContext.cpp" "main.cpp" ${FS_SRC} + ${HOMEKIT_SRC} ${UI_SRC} ${MQTT_SRC} ${NTP_SRC} diff --git a/main/homekit/hkapi.c b/main/homekit/hkapi.c new file mode 100644 index 0000000..fef49ab --- /dev/null +++ b/main/homekit/hkapi.c @@ -0,0 +1,80 @@ + #define SPIFLASH_BASE_ADDR 0x8c000 + #include + #include + #include + #include + #include + #include + + #include + #include + + #include + #include + +homekit_server_config_t config; +homekit_service_t* services[10 + 1]; +homekit_service_t** s = services; +homekit_accessory_t *accessories[10]; + +static int currentPos = 0; + +void switch_identify(homekit_value_t _value) { + // DO NOTHING FOR NOW +} + +void hkInitService() +{ + *(s++) = + NEW_HOMEKIT_SERVICE( + ACCESSORY_INFORMATION, + .id = 1, + .characteristics=(homekit_characteristic_t*[]) { + NEW_HOMEKIT_CHARACTERISTIC(NAME, "HomePoint"), + NEW_HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Homepoint"), + NEW_HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "131131"), + NEW_HOMEKIT_CHARACTERISTIC(MODEL, "Button"), + NEW_HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"), + NEW_HOMEKIT_CHARACTERISTIC(IDENTIFY, switch_identify), + NULL + }, + ); +} + +void* memdup(void* data, size_t data_size) { + void *result = malloc(data_size); + memcpy(result, data, data_size); + return result; + } + + #define NEW_HOMEKIT_CHARACTERISTIC_CALLBACK(...) \ + memdup(HOMEKIT_CHARACTERISTIC_CALLBACK(__VA_ARGS__), \ + sizeof(homekit_characteristic_change_callback_t)) + +void hkAddDevice(const char* deviceName, homekit_characteristic_t *setterChar) +{ + bool primary = false; + if (currentPos == 0) + { + primary = true; + } + *(s++) = NEW_HOMEKIT_SERVICE( + SWITCH, + .primary = primary, + .characteristics=(homekit_characteristic_t*[]) { + NEW_HOMEKIT_CHARACTERISTIC(NAME, deviceName), + setterChar, + NULL + }); + currentPos += 1; +} + +void hkInit(const char* password) +{ + *(s++) = NULL; + accessories[0] = NEW_HOMEKIT_ACCESSORY(.category=homekit_accessory_category_switch, .services=services); + accessories[1] = NULL; + config.accessories = accessories; + config.password = password; + homekit_server_init(&config); +} diff --git a/main/homekit/hkapi.h b/main/homekit/hkapi.h new file mode 100644 index 0000000..1d25ca7 --- /dev/null +++ b/main/homekit/hkapi.h @@ -0,0 +1,4 @@ + +void hkInitService(); +void hkInit(const char* password); +void hkAddDevice(const char* deviceName, homekit_characteristic_t *setterChar); From e401bbd3ee233d665a61caf619a11b97c13ffd7b Mon Sep 17 00:00:00 2001 From: sieren Date: Fri, 31 May 2019 16:40:19 +0200 Subject: [PATCH 3/7] Add HomeKit API to Homepoint --- main/CMakeLists.txt | 1 + main/fs/ConfigReader.hpp | 17 +++++- main/homekit/HKConfig.hpp | 12 ++++ main/homekit/HKConnection.cpp | 37 ++++++++++++ main/homekit/HKConnection.h | 21 +++++++ main/homekit/HKDevice.hpp | 106 ++++++++++++++++++++++++++++++++++ 6 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 main/homekit/HKConfig.hpp create mode 100644 main/homekit/HKConnection.cpp create mode 100644 main/homekit/HKConnection.h create mode 100644 main/homekit/HKDevice.hpp diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index dc19f16..a4879a0 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -21,6 +21,7 @@ file(GLOB FS_SRC set(HOMEKIT_SRC_PATH "homekit") file(GLOB HOMEKIT_SRC "${HOMEKIT_SRC_PATH}/hkapi.c" + "${HOMEKIT_SRC_PATH}/HKConnection.cpp" ) diff --git a/main/fs/ConfigReader.hpp b/main/fs/ConfigReader.hpp index 64acdbb..054c17a 100644 --- a/main/fs/ConfigReader.hpp +++ b/main/fs/ConfigReader.hpp @@ -67,7 +67,22 @@ namespace fs return conf; } - static std::vector getMQTTGroups() + static const homekit::HKConfig getHKConfig() + { + mqtt::MQTTConfig conf; + using namespace rapidjson; + auto config = fs::FileSystem::getInstance().readJsonConfig("/spiffs/config.json"); + const char* configChar = config.c_str(); + Document document; + document.Parse<0>(configChar); + + if (document.HasMember("homekitpin")) + { + Value& hkPin = document["homekitpin"]; + return homekit::HKConfig{hkPin.GetString(), true};; + } + return homekit::HKConfig{std::string(""), false}; + } { using namespace rapidjson; using namespace mqtt; diff --git a/main/homekit/HKConfig.hpp b/main/homekit/HKConfig.hpp new file mode 100644 index 0000000..cd4dfe7 --- /dev/null +++ b/main/homekit/HKConfig.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace homekit +{ + struct HKConfig + { + std::string password; + bool isEnabled = false; + }; +} // namespace homekit diff --git a/main/homekit/HKConnection.cpp b/main/homekit/HKConnection.cpp new file mode 100644 index 0000000..97866a3 --- /dev/null +++ b/main/homekit/HKConnection.cpp @@ -0,0 +1,37 @@ +#include +#include +#include "HKConnection.h" +#include "HKDevice.hpp" + +extern "C" +{ + #include + #include + #include + #include "hkapi.h" +} + +namespace homekit +{ + + HKConnection::HKConnection(const HKConfig& config, const std::vector devices) : + mDevices(devices), + mConfig(config) + { + hkInitService(); + for (auto& device : mDevices) + { + mpark::visit(::util::overloaded( + [&](HKDevicePtr& ptr) + { + hkAddDevice(ptr->sceneName.c_str(), ptr->characteristic); + }, + [](auto&& i) {}), device); + } + } + + void HKConnection::start() + { + hkInit(mConfig.password.c_str()); + } +} // namespace homekit diff --git a/main/homekit/HKConnection.h b/main/homekit/HKConnection.h new file mode 100644 index 0000000..abed39a --- /dev/null +++ b/main/homekit/HKConnection.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include "HKConfig.hpp" +#include "HKDevice.hpp" +#include + +namespace homekit +{ + class HKConnection + { + public: + HKConnection() = delete; + HKConnection(const HKConfig& config, const std::vector devices); + void start(); + + private: + std::vector mDevices; + const HKConfig mConfig; + }; +} \ No newline at end of file diff --git a/main/homekit/HKDevice.hpp b/main/homekit/HKDevice.hpp new file mode 100644 index 0000000..f0af4bb --- /dev/null +++ b/main/homekit/HKDevice.hpp @@ -0,0 +1,106 @@ +#pragma once + +#include +#include + +extern "C" +{ + #include + #include + #include + #include +} +namespace homekit +{ + struct HKDevice; +} // namespace homekit + +using HKDevicePtr = std::shared_ptr; +namespace homekit +{ + struct HKDevice + { + + static void switch_on_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) + { + printf("Switch On Callback\r\n"); + printf("With ID: %i\r\n", _ch->id); + if (_ch->value.bool_value != on.bool_value) + { + _ch->value.bool_value = on.bool_value; + homekit_characteristic_notify(_ch, _ch->value); + } + (*static_cast(context)).setDeviceState(on.bool_value); + } + + static void deviceSetCallback(homekit_characteristic_t *ch, const homekit_value_t value) + { + (*static_cast(ch->context)).setDeviceState(value.bool_value); + printf("Device has been set!"); + } + + void setDeviceState(bool on) + { + if (on != mIsActive) + { + homekit_value_t newValue; + newValue.format = homekit_format_bool; + newValue.bool_value = on; + characteristic->value = newValue; + mIsActive = on; + homekit_characteristic_notify(characteristic, characteristic->value); + if (mSetNeedsUpdateCB) + { + mSetNeedsUpdateCB(on); + } + } + printf("Updated with new value"); + printf(sceneName.c_str()); + printf("\r\n"); + } + + HKDevice(const HKDevice&) =delete; + HKDevice& operator=(const HKDevice&) =delete; + + HKDevice& operator=(HKDevice&& other) + { + characteristic = other.characteristic; + sceneName = other.sceneName; + characteristic->context = this; + return *this; + } + + HKDevice(const HKDevice&& other) + { + characteristic = other.characteristic; + sceneName = other.sceneName; + characteristic->context = this; + } + + HKDevice() + { + characteristic = new homekit_characteristic_t{}; + characteristic->setter_ex = deviceSetCallback; + characteristic->context = this; + characteristic->type = HOMEKIT_CHARACTERISTIC_ON; + characteristic->description = "On"; + characteristic->format = homekit_format_bool; + characteristic->permissions = static_cast(homekit_permissions_paired_read | + homekit_permissions_paired_write | homekit_permissions_notify); + homekit_value_t val; + val.bool_value = true; + characteristic->value = val; + } + + bool isActive() const + { + return mIsActive; + } + std::string sceneName = ""; + std::string iconName = ""; + uint16_t groupId; + bool mIsActive = false; + std::function mSetNeedsUpdateCB; + homekit_characteristic_t* characteristic; + }; +} // namespace homekit \ No newline at end of file From d4c0ba8654046c876be2c6dbf35592075388d7a4 Mon Sep 17 00:00:00 2001 From: sieren Date: Fri, 31 May 2019 16:40:59 +0200 Subject: [PATCH 4/7] Use generic Device Types --- main/devices/DeviceTypes.hpp | 7 +++++++ main/fs/ConfigReader.hpp | 19 ++++++++++++++++--- main/mqtt/MQTTConnection.cpp | 14 +++++++++++--- main/mqtt/MQTTConnection.h | 6 +++--- main/mqtt/MQTTGroup.hpp | 1 - 5 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 main/devices/DeviceTypes.hpp diff --git a/main/devices/DeviceTypes.hpp b/main/devices/DeviceTypes.hpp new file mode 100644 index 0000000..89266fd --- /dev/null +++ b/main/devices/DeviceTypes.hpp @@ -0,0 +1,7 @@ +#pragma once + +#include +#include +#include "mpark/variant.hpp" + +using DeviceVariants = mpark::variant; diff --git a/main/fs/ConfigReader.hpp b/main/fs/ConfigReader.hpp index 054c17a..714147b 100644 --- a/main/fs/ConfigReader.hpp +++ b/main/fs/ConfigReader.hpp @@ -83,6 +83,8 @@ namespace fs } return homekit::HKConfig{std::string(""), false}; } + + static std::vector getDeviceGroups() { using namespace rapidjson; using namespace mqtt; @@ -93,7 +95,7 @@ namespace fs uint16_t tagId = 0; const auto& scenes = document["scenes"].GetArray(); - std::vector vecScenes; + std::vector vecScenes; for (const auto& scene : scenes) { if (std::string(scene["type"].GetString()) == "Light" || @@ -118,9 +120,10 @@ namespace fs } aScene->mDevices = devices; aScene->groupId = tagId; - MQTTVariants variant = aScene; + DeviceVariants variant = aScene; vecScenes.push_back(aScene); } + else if (std::string(scene["type"].GetString()) == "Sensor") { auto aScene = std::make_shared(); @@ -177,7 +180,17 @@ namespace fs } aScene->mSensorDevices = devices; aScene->groupId = tagId; - MQTTVariants variant = aScene; + DeviceVariants variant = aScene; + vecScenes.push_back(aScene); + } + + else if (std::string(scene["type"].GetString()) == "HomeKitSwitch") + { + auto aScene = std::make_shared(); + aScene->sceneName = scene["name"].GetString(); + aScene->iconName = scene["icon"].GetString(); + aScene->groupId = tagId; + DeviceVariants variant = aScene; vecScenes.push_back(aScene); } tagId += 1; diff --git a/main/mqtt/MQTTConnection.cpp b/main/mqtt/MQTTConnection.cpp index a25d79a..025443e 100644 --- a/main/mqtt/MQTTConnection.cpp +++ b/main/mqtt/MQTTConnection.cpp @@ -20,7 +20,7 @@ static const char* TAG = "MQTT"; namespace mqtt { - MQTTConnection::MQTTConnection(MQTTConfig config, std::vector mqttscenes) : + MQTTConnection::MQTTConnection(MQTTConfig config, std::vector mqttscenes) : mConfig(config), mMQTTScenes(mqttscenes) { @@ -107,7 +107,11 @@ namespace mqtt { auto scene = std::find_if(mMQTTScenes.begin(), mMQTTScenes.end(), [&id](auto& ele) { - return mpark::visit([&id](auto&& elem) { return elem->groupId == id; }, ele); + return mpark::visit(::util::overloaded([&id](MQTTSwitchGroupPtr&& elem) + { + return elem->groupId == id; + }, + [](auto&& i) { return false; }), ele); }); if (scene != mMQTTScenes.end()) { @@ -133,7 +137,11 @@ namespace mqtt ESP_LOGI(TAG, "Switching, grp=%d, dev=%d", groupid, deviceid); auto scene = std::find_if(mMQTTScenes.begin(), mMQTTScenes.end(), [&groupid](auto& ele) { - return mpark::visit([&groupid](auto&& elem) { return elem->groupId == groupid; }, ele); + return mpark::visit(::util::overloaded([&groupid](MQTTSwitchGroupPtr&& elem) + { + return elem->groupId == groupid; + }, + [](auto&& i) { return false; }), ele); }); if (scene != mMQTTScenes.end()) diff --git a/main/mqtt/MQTTConnection.h b/main/mqtt/MQTTConnection.h index c9b41e6..42dbb3e 100644 --- a/main/mqtt/MQTTConnection.h +++ b/main/mqtt/MQTTConnection.h @@ -1,6 +1,6 @@ #pragma once -#include "MQTTGroup.hpp" +#include #include #include @@ -35,7 +35,7 @@ namespace mqtt class MQTTConnection { public: - MQTTConnection(MQTTConfig config, std::vector mqttscenes); + MQTTConnection(MQTTConfig config, std::vector mqttscenes); void connect(); void bindScenes(); void switchScene(const uint16_t id, bool on); @@ -48,7 +48,7 @@ namespace mqtt void updateScenes(esp_mqtt_event_handle_t event); MQTTConfig mConfig; esp_mqtt_client_handle_t client; - std::vector mMQTTScenes; + std::vector mMQTTScenes; MQTTConnectionStatus mLastState; Dispatcher mConnectionStatusNotifier; }; diff --git a/main/mqtt/MQTTGroup.hpp b/main/mqtt/MQTTGroup.hpp index cc704ea..657ae14 100644 --- a/main/mqtt/MQTTGroup.hpp +++ b/main/mqtt/MQTTGroup.hpp @@ -16,7 +16,6 @@ namespace mqtt { struct MQTTSwitchGroup; struct MQTTGroup; struct MQTTSensorGrou using MQTTSwitchGroupPtr = std::shared_ptr; using MQTTSensorGroupPtr = std::shared_ptr; using MQTTGroupBasePtr = std::shared_ptr; -using MQTTVariants = mpark::variant; using MQTTGroupsPtr = std::shared_ptr>; namespace mqtt From 70525017a25e4ae340bd694e4f70bedbd2666960 Mon Sep 17 00:00:00 2001 From: sieren Date: Fri, 31 May 2019 16:42:40 +0200 Subject: [PATCH 5/7] Add first version of HomeKit Support --- data/config.json | 6 ++++++ main/AppContext.cpp | 17 +++++++++++++---- main/AppContext.h | 6 ++++-- main/AppScreen.ipp | 4 ++-- main/fs/ConfigReader.hpp | 2 ++ main/homekit/HKDevice.hpp | 18 +----------------- main/ui/UIWidgetBuilder.hpp | 35 ++++++++++++++++++++++++++++++++++- 7 files changed, 62 insertions(+), 26 deletions(-) diff --git a/data/config.json b/data/config.json index f0e3863..f241979 100644 --- a/data/config.json +++ b/data/config.json @@ -4,8 +4,14 @@ "mqttbroker": "mqtt://192.168.1.1", "mqttusername": "myusername", "mqttpasswd": "mypassword", + "homekitpin": "111-11-111", "timezone": "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", "scenes": [ + { + "name": "Entrance", + "type": "HomeKitSwitch", + "icon": "door" + }, { "name": "Entrance", "type": "Light", diff --git a/main/AppContext.cpp b/main/AppContext.cpp index da22234..cd8b81d 100644 --- a/main/AppContext.cpp +++ b/main/AppContext.cpp @@ -12,8 +12,13 @@ namespace ctx void AppContext::setup() { fs::FileSystem::getInstance().loadPartitions(); - mMQTTGroups = fs::ConfigReader::getMQTTGroups(); - mpMQTTConnection = std::make_shared(fs::ConfigReader::getMQTTConfig(), mMQTTGroups); + mDeviceGroups = fs::ConfigReader::getDeviceGroups(); + const auto hkConfig = fs::ConfigReader::getHKConfig(); + if (hkConfig.isEnabled) + { + mpHKConnection = std::make_shared(hkConfig, mDeviceGroups); + } + mpMQTTConnection = std::make_shared(fs::ConfigReader::getMQTTConfig(), mDeviceGroups); const auto timeZone = fs::ConfigReader::getTimeZone(); if (timeZone != "") { @@ -34,12 +39,16 @@ namespace ctx if (cb == mqtt::MQTTConnectionStatus::CONNECTED) { mpMQTTConnection->bindScenes(); + if (mpHKConnection) + { + mpHKConnection->start(); + } } }); } - std::vector &AppContext::getMQTTGroups() + std::vector &AppContext::getDeviceGroups() { - return mMQTTGroups; + return mDeviceGroups; } } // namespace ctx diff --git a/main/AppContext.h b/main/AppContext.h index f8b4c7b..3e2c1b6 100644 --- a/main/AppContext.h +++ b/main/AppContext.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -21,13 +22,14 @@ namespace ctx WifiContext& getWifiContext() { return mWifiContext; }; std::shared_ptr getMQTTConnection() { return mpMQTTConnection; }; - std::vector &getMQTTGroups(); + std::vector &getDeviceGroups(); private: std::shared_ptr mpMQTTConnection; + std::shared_ptr mpHKConnection = nullptr; std::shared_ptr mNTPSync; WifiContext mWifiContext; - std::vector mMQTTGroups; + std::vector mDeviceGroups; rapidjson::Document mConfigDocument; }; } // namespace ctx diff --git a/main/AppScreen.ipp b/main/AppScreen.ipp index 53b16b3..9e7b092 100644 --- a/main/AppScreen.ipp +++ b/main/AppScreen.ipp @@ -42,7 +42,7 @@ namespace gfx template void AppScreen::presentScreen(const uint16_t sceneId) { - auto& scenes = mpAppContext->getMQTTGroups(); + auto& scenes = mpAppContext->getDeviceGroups(); auto widgets = std::vector(); auto mqttScene = std::find_if(scenes.begin(), scenes.end(), [&](auto& scene) @@ -110,7 +110,7 @@ namespace gfx void AppScreen::presentMenu() { auto screenNavigator = std::make_shared>(&mTft, menuFrame, 1000); - auto& scenes = mpAppContext->getMQTTGroups(); + auto& scenes = mpAppContext->getDeviceGroups(); auto widgets = std::vector(); for (auto& scene : scenes) { diff --git a/main/fs/ConfigReader.hpp b/main/fs/ConfigReader.hpp index 714147b..1f61cfd 100644 --- a/main/fs/ConfigReader.hpp +++ b/main/fs/ConfigReader.hpp @@ -3,6 +3,8 @@ #include #include "rapidjson/document.h" #include "Filesystem.h" +#include +#include #include #include #include diff --git a/main/homekit/HKDevice.hpp b/main/homekit/HKDevice.hpp index f0af4bb..99a9275 100644 --- a/main/homekit/HKDevice.hpp +++ b/main/homekit/HKDevice.hpp @@ -20,23 +20,9 @@ namespace homekit { struct HKDevice { - - static void switch_on_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) - { - printf("Switch On Callback\r\n"); - printf("With ID: %i\r\n", _ch->id); - if (_ch->value.bool_value != on.bool_value) - { - _ch->value.bool_value = on.bool_value; - homekit_characteristic_notify(_ch, _ch->value); - } - (*static_cast(context)).setDeviceState(on.bool_value); - } - static void deviceSetCallback(homekit_characteristic_t *ch, const homekit_value_t value) { (*static_cast(ch->context)).setDeviceState(value.bool_value); - printf("Device has been set!"); } void setDeviceState(bool on) @@ -54,9 +40,6 @@ namespace homekit mSetNeedsUpdateCB(on); } } - printf("Updated with new value"); - printf(sceneName.c_str()); - printf("\r\n"); } HKDevice(const HKDevice&) =delete; @@ -96,6 +79,7 @@ namespace homekit { return mIsActive; } + std::string sceneName = ""; std::string iconName = ""; uint16_t groupId; diff --git a/main/ui/UIWidgetBuilder.hpp b/main/ui/UIWidgetBuilder.hpp index 97e266d..3b5fa3b 100644 --- a/main/ui/UIWidgetBuilder.hpp +++ b/main/ui/UIWidgetBuilder.hpp @@ -59,6 +59,39 @@ namespace util return button; }; + auto operator()(HKDevicePtr ptr, ScreenType screen) -> std::shared_ptr + { + auto button = std::make_shared(&(screen->mTft), Frame(), ptr->groupId); + button->setBackgroundColor(Color::InactiveBgColor()); + button->setLabel(ptr->sceneName); + + const auto icons = GetIconFileNames(ptr->iconName); + const auto textColor = ptr->isActive() ? Color::ActiveBgColor() : Color::InactiveTextColor(); + const auto imagePath = ptr->isActive() ? icons.first : icons.second; + button->setImage(imagePath); + button->setTextColor(textColor); + auto& context = screen->mpAppContext; + button->addTargetAction([ptr, context](const uint16_t id) { + const bool isActive = ptr->isActive(); + ptr->setDeviceState(!isActive); + }); + + auto& screenSaver = screen->mScreenSaver; + ptr->mSetNeedsUpdateCB = [ptr, weakBtn = std::weak_ptr(button), &screenSaver, icons](const bool state) { + const auto textColor = state ? Color::ActiveBgColor() : Color::InactiveTextColor(); + const auto imagePath = state ? icons.first : icons.second; + auto button = weakBtn.lock(); + if (!button) + { + return; + } + button->setTextColor(textColor); + button->setImage(imagePath); + screenSaver.activate(); + }; + return button; + }; + auto operator()(MQTTSensorGroupPtr ptr, ScreenType screen) -> std::shared_ptr { auto button = std::make_shared(&(screen->mTft), Frame(), ptr->groupId); @@ -137,4 +170,4 @@ namespace util } }; } // namespace util -} // namespace gfx \ No newline at end of file +} // namespace gfx From 9e2bc650da792c0c1c83b1ed4a771d037e842dbd Mon Sep 17 00:00:00 2001 From: sieren Date: Fri, 31 May 2019 21:47:57 +0200 Subject: [PATCH 6/7] Update README --- README.md | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 437d1bc..9f942c0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Homepoint ============= -#### An ESP32 based Smarthome Controller for MQTT +#### An ESP32 based Smarthome Controller for MQTT & HomeKit ![Travis CI](https://travis-ci.org/sieren/Homepoint.svg?branch=master "Travis CI Status") @@ -8,8 +8,11 @@ Status") "Issues")](https://github.com/sieren/Homepoint/issues) Homepoint is a screen-based interface for MQTT-connected Smarthome devices that runs -on the cheaply available ESP32 Chipset. -This project requires a MQTT-Broker to be running in your smarthome. +on the cheaply available ESP32 Chipset. +It can also provide *Switches* to *HomeKit*. These can be used inside the Home App on iOS +to trigger other HomeKit Devices. + +For MQTT this project requires a MQTT-Broker to be running in your smarthome. [![HomePoint Youtube demo](https://raw.githubusercontent.com/sieren/Homepoint/master/media/youtube.png)](https://www.youtube.com/watch?v=bqzpkvtQSvY "HomePoint Youtube demo") @@ -21,14 +24,17 @@ This project requires a MQTT-Broker to be running in your smarthome. + Trigger individual devices by diving into scenes (by tapping the indicator or long pressing a button). + See partially switched on scenes with multiple devices at a glance. + Support for temperature, humidity and air quality sensors. ++ HomeKit Switch Support (Setup Automations in Home App to toggle from Homepoint) + Supports both Touch Screen or Button based navigation. + Screen updates automatically when devices are triggered from elsewhere. + Easy configuration through a JSON files. + Screensaver saves power by switching off screen after 10 minutes. + Statusbar shows connectivity for WiFi and MQTT as well as time. + #### Planned -+ HomeKit Button/Switch Support (for users without MQTT to setup Automations they can toggle from Homepoint) + ++ Improve HomeKit Support + Improved documentation Is there a feature missing? Open an issue, send me an [email](mailto:info@s-r-n.de) or fork this project and add it yourself. @@ -134,3 +140,28 @@ Homepoint gets its time from an NTP Server. In order to set the correct timezone ``` Switches can have custom icons, the icons of sensors are currently fixed and not customizable. See the `data` folder for available icons or add your own following the naming scheme visible there. + +### HomeKit +To active *HomeKit*, simply set a PIN in the configuration file. +Beware that the PIN has to follow the scheme of `xxx-xx-xxx`. +A single HomeKit Switch is of `type: "HomeKitSwitch"`. +It may not contain any devices. + +``` +{ + "wifi": "MyWifiSSID", + "password": "My Wifi Password", + "mqttbroker": "mqtt://192.168.1.2", + "mqttusername": "mqttusername", + "mqttpasswd": "mymqttpassword", + "homekitpin": "111-11-111", + "timezone": "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", + "scenes": [ + { + "name": "Living Room", + "type": "HomeKitSwitch", + "icon": "livingroom" + }] +} +``` + From 1287c8d269b16c7051b62b9eaac7cdd06f5edee5 Mon Sep 17 00:00:00 2001 From: sieren Date: Sat, 1 Jun 2019 09:57:57 +0200 Subject: [PATCH 7/7] fixup! Add HomeKit Submodules --- components/cJSON | 2 +- components/homekit | 2 +- components/http-parser | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/cJSON b/components/cJSON index 784e97f..2b93171 160000 --- a/components/cJSON +++ b/components/cJSON @@ -1 +1 @@ -Subproject commit 784e97f378243df16eb6e9301f43ab522aa2706f +Subproject commit 2b9317101a7ffbcf834eaebf7ef92b6d52d10ff4 diff --git a/components/homekit b/components/homekit index 439e2e7..6cde4f9 160000 --- a/components/homekit +++ b/components/homekit @@ -1 +1 @@ -Subproject commit 439e2e77c61fad277354ae193e86e33983d50592 +Subproject commit 6cde4f96d647fce1baf5e0e81902da0ce0fdcfb7 diff --git a/components/http-parser b/components/http-parser index a0f9c3b..dc9b2cb 160000 --- a/components/http-parser +++ b/components/http-parser @@ -1 +1 @@ -Subproject commit a0f9c3b986112cb62eaf58c68d1b3315b4d9687f +Subproject commit dc9b2cb0c8d397dc3bbad20f398828cefb45e8b5