Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI Test: HomeKit Integration #10

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
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")
[![Issues](https://img.shields.io/github/issues/sieren/Homepoint.svg
"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.

<img src="https://raw.githubusercontent.com/sieren/Homepoint/master/media/img1.jpg" width="400"><img src="https://raw.githubusercontent.com/sieren/Homepoint/master/media/img2.gif" width="400">
[![HomePoint Youtube demo](https://raw.githubusercontent.com/sieren/Homepoint/master/media/youtube.png)](https://www.youtube.com/watch?v=bqzpkvtQSvY "HomePoint Youtube demo")
Expand All @@ -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.
Expand Down Expand Up @@ -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"
}]
}
```

1 change: 1 addition & 0 deletions components/cJSON
Submodule cJSON added at 2b9317
1 change: 1 addition & 0 deletions components/homekit
Submodule homekit added at 6cde4f
1 change: 1 addition & 0 deletions components/http-parser
Submodule http-parser added at dc9b2c
1 change: 1 addition & 0 deletions components/wolfssl
Submodule wolfssl added at 04de41
6 changes: 6 additions & 0 deletions data/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
17 changes: 13 additions & 4 deletions main/AppContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ namespace ctx
void AppContext::setup()
{
fs::FileSystem::getInstance().loadPartitions();
mMQTTGroups = fs::ConfigReader::getMQTTGroups();
mpMQTTConnection = std::make_shared<mqtt::MQTTConnection>(fs::ConfigReader::getMQTTConfig(), mMQTTGroups);
mDeviceGroups = fs::ConfigReader::getDeviceGroups();
const auto hkConfig = fs::ConfigReader::getHKConfig();
if (hkConfig.isEnabled)
{
mpHKConnection = std::make_shared<homekit::HKConnection>(hkConfig, mDeviceGroups);
}
mpMQTTConnection = std::make_shared<mqtt::MQTTConnection>(fs::ConfigReader::getMQTTConfig(), mDeviceGroups);
const auto timeZone = fs::ConfigReader::getTimeZone();
if (timeZone != "")
{
Expand All @@ -34,12 +39,16 @@ namespace ctx
if (cb == mqtt::MQTTConnectionStatus::CONNECTED)
{
mpMQTTConnection->bindScenes();
if (mpHKConnection)
{
mpHKConnection->start();
}
}
});
}

std::vector<MQTTVariants> &AppContext::getMQTTGroups()
std::vector<DeviceVariants> &AppContext::getDeviceGroups()
{
return mMQTTGroups;
return mDeviceGroups;
}
} // namespace ctx
6 changes: 4 additions & 2 deletions main/AppContext.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <homekit/HKConnection.h>
#include <mqtt/MQTTConnection.h>
#include <mqtt/MQTTGroup.hpp>
#include <ntp/NTPSync.h>
Expand All @@ -21,13 +22,14 @@ namespace ctx

WifiContext& getWifiContext() { return mWifiContext; };
std::shared_ptr<mqtt::MQTTConnection> getMQTTConnection() { return mpMQTTConnection; };
std::vector<MQTTVariants> &getMQTTGroups();
std::vector<DeviceVariants> &getDeviceGroups();

private:
std::shared_ptr<mqtt::MQTTConnection> mpMQTTConnection;
std::shared_ptr<homekit::HKConnection> mpHKConnection = nullptr;
std::shared_ptr<ntp::NTPSync> mNTPSync;
WifiContext mWifiContext;
std::vector<MQTTVariants> mMQTTGroups;
std::vector<DeviceVariants> mDeviceGroups;
rapidjson::Document mConfigDocument;
};
} // namespace ctx
4 changes: 2 additions & 2 deletions main/AppScreen.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace gfx
template<class ScreenDriver, class NavigationDriver>
void AppScreen<ScreenDriver, NavigationDriver>::presentScreen(const uint16_t sceneId)
{
auto& scenes = mpAppContext->getMQTTGroups();
auto& scenes = mpAppContext->getDeviceGroups();
auto widgets = std::vector<WidgetPtr>();

auto mqttScene = std::find_if(scenes.begin(), scenes.end(), [&](auto& scene)
Expand Down Expand Up @@ -110,7 +110,7 @@ namespace gfx
void AppScreen<ScreenDriver, NavigationDriver>::presentMenu()
{
auto screenNavigator = std::make_shared<ScreenNavigator<NavigationDriver>>(&mTft, menuFrame, 1000);
auto& scenes = mpAppContext->getMQTTGroups();
auto& scenes = mpAppContext->getDeviceGroups();
auto widgets = std::vector<WidgetPtr>();
for (auto& scene : scenes)
{
Expand Down
9 changes: 9 additions & 0 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ file(GLOB FS_SRC
"${FS_SRC_PATH}/Filesystem.cpp"
)


set(HOMEKIT_SRC_PATH "homekit")
file(GLOB HOMEKIT_SRC
"${HOMEKIT_SRC_PATH}/hkapi.c"
"${HOMEKIT_SRC_PATH}/HKConnection.cpp"
)


set(MQTT_SRC_PATH "mqtt")
file(GLOB MQTT_SRC
"${MQTT_SRC_PATH}/MQTTConnection.cpp"
Expand Down Expand Up @@ -72,6 +80,7 @@ set(COMPONENT_SRCS
"AppContext.cpp"
"main.cpp"
${FS_SRC}
${HOMEKIT_SRC}
${UI_SRC}
${MQTT_SRC}
${NTP_SRC}
Expand Down
7 changes: 7 additions & 0 deletions main/devices/DeviceTypes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#include <mqtt/MQTTGroup.hpp>
#include <homekit/HKDevice.hpp>
#include "mpark/variant.hpp"

using DeviceVariants = mpark::variant<MQTTSwitchGroupPtr, MQTTSensorGroupPtr, HKDevicePtr, MQTTGroupBasePtr>;
38 changes: 34 additions & 4 deletions main/fs/ConfigReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <util/warnings.h>
#include "rapidjson/document.h"
#include "Filesystem.h"
#include <homekit/HKConfig.hpp>
#include <homekit/HKDevice.hpp>
#include <mqtt/MQTTConnection.h>
#include <mqtt/MQTTGroup.hpp>
#include <mqtt/MQTTSensorGroup.hpp>
Expand Down Expand Up @@ -67,7 +69,24 @@ namespace fs
return conf;
}

static std::vector<MQTTVariants> 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};
}

static std::vector<DeviceVariants> getDeviceGroups()
{
using namespace rapidjson;
using namespace mqtt;
Expand All @@ -78,7 +97,7 @@ namespace fs

uint16_t tagId = 0;
const auto& scenes = document["scenes"].GetArray();
std::vector<MQTTVariants> vecScenes;
std::vector<DeviceVariants> vecScenes;
for (const auto& scene : scenes)
{
if (std::string(scene["type"].GetString()) == "Light" ||
Expand All @@ -103,9 +122,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<MQTTSensorGroup>();
Expand Down Expand Up @@ -162,7 +182,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<homekit::HKDevice>();
aScene->sceneName = scene["name"].GetString();
aScene->iconName = scene["icon"].GetString();
aScene->groupId = tagId;
DeviceVariants variant = aScene;
vecScenes.push_back(aScene);
}
tagId += 1;
Expand Down
12 changes: 12 additions & 0 deletions main/homekit/HKConfig.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include <string>

namespace homekit
{
struct HKConfig
{
std::string password;
bool isEnabled = false;
};
} // namespace homekit
37 changes: 37 additions & 0 deletions main/homekit/HKConnection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <devices/DeviceTypes.hpp>
#include <util/varianthelper.hpp>
#include "HKConnection.h"
#include "HKDevice.hpp"

extern "C"
{
#include <cstdio>
#include <cstddef>
#include <homekit/types.h>
#include "hkapi.h"
}

namespace homekit
{

HKConnection::HKConnection(const HKConfig& config, const std::vector<DeviceVariants> 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
21 changes: 21 additions & 0 deletions main/homekit/HKConnection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <devices/DeviceTypes.hpp>
#include "HKConfig.hpp"
#include "HKDevice.hpp"
#include <vector>

namespace homekit
{
class HKConnection
{
public:
HKConnection() = delete;
HKConnection(const HKConfig& config, const std::vector<DeviceVariants> devices);
void start();

private:
std::vector<DeviceVariants> mDevices;
const HKConfig mConfig;
};
}
Loading