Skip to content

Commit 620f5ad

Browse files
authored
feat: switch to using PlatformIO scripting to build SDK from source
* chore: set to cleanup build by default * refactor: remove static libaries * feat: begin to use PlatfomIO's extra script for build * feat: finalise building library from source * docs: include basic fan example * docs: update README
1 parent d025451 commit 620f5ad

21 files changed

+279
-4728
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
.tmp
22
.DS_Store
3-
*.tar*
3+
*.tar*
4+
lib/*
5+
!lib/esp_hap_config.h

ESP32HomeKit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include <ESP32HomeKit.h>

ESP32HomeKit.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "lib/hap.h"
2+
#include "lib/hap_apple_chars.h"
3+
#include "lib/hap_apple_servs.h"

README.md

Lines changed: 4 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,7 @@
22

33
This library provides the official [ESP-IDF HomeKit SDK](https://github.com/espressif/esp-homekit-sdk) for ESP32 devices running the Arduino framework.
44

5-
**Note:** This wrapper uses a version of the SDK which can't be used in commercial products due to it not being MFi certified. Other changes would also mean the library would fail HomeKit certifications. Feel free to use it in your hobby projects though!
6-
7-
## Building Process
8-
9-
Since Arduino for the ESP32 currently supports version 3.3 of the ESP-IDF framework, this library uses a version of the HomeKit SDK that has been ported to ESP-IDF v3.3. An example project is built using the same `sdkconfig` that the Arduino framework to build itself, with the outputted static libraries being extracted. You can view the `build.sh` script to see this process.
10-
11-
Below is a list of modified entries in `sdkconfig` that are used to build the example project:
12-
13-
- `CONFIG_HAP_HTTP_MAX_OPEN_SOCKETS=8` => 6
14-
- `CONFIG_HAP_HTTP_SERVER_PORT=80` => 8080
15-
16-
The adapted version be found here: [esp-idf3-homekit-sdk](https://github.com/Brawrdon/esp-idf3-homekit-sdk).
5+
**Note:** This wrapper uses a version of the SDK which can't be used in commercial products due to it not being MFi certified, feel free to use it in your hobby projects though!
176

187
## Installation
198

@@ -23,202 +12,17 @@ If you're using [PlatformIO](https://docs.platformio.org/en/latest/librarymanage
2312
pio lib install 'ESP32 HomeKit SDK for Arduino'
2413
```
2514

26-
You can also use the Arduino IDE to install the library via Library Manager or ZIP file.
15+
You can use the Arduino IDE to install the library by downloading the prebuilt ZIP file in the Releases section.
2716

2817
## Usage
2918

30-
This is based on the fan example of the original ESP-IDF SDK.
31-
32-
```cpp
33-
#include <Arduino.h>
34-
#include <Wifi.h>
35-
#include <hap.h>
36-
#include <hap_apple_servs.h>
37-
#include <hap_apple_chars.h>
38-
39-
const char* ssid = "yourNetworkName";
40-
const char* password = "yourNetworkPassword";
41-
42-
43-
/* Mandatory identify routine for the accessory.
44-
* In a real accessory, something like LED blink should be implemented
45-
* got visual identification
46-
*/
47-
static int identify(hap_acc_t *ha)
48-
{
49-
ESP_LOGI(TAG, "Accessory identified");
50-
return HAP_SUCCESS;
51-
}
52-
53-
/* A dummy callback for handling a read on the "Direction" characteristic of Fan.
54-
* In an actual accessory, this should read from hardware.
55-
* Read routines are generally not required as the value is available with th HAP core
56-
* when it is updated from write routines. For external triggers (like fan switched on/off
57-
* using physical button), accessories should explicitly call hap_char_update_val()
58-
* instead of waiting for a read request.
59-
*/
60-
static int fan_read(hap_char_t *hc, hap_status_t *status_code, void *serv_priv, void *read_priv)
61-
{
62-
if (hap_req_get_ctrl_id(read_priv)) {
63-
ESP_LOGI(TAG, "Received read from %s", hap_req_get_ctrl_id(read_priv));
64-
}
65-
if (!strcmp(hap_char_get_type_uuid(hc), HAP_CHAR_UUID_ROTATION_DIRECTION)) {
66-
/* Read the current value, toggle it and set the new value.
67-
* A separate variable should be used for the new value, as the hap_char_get_val()
68-
* API returns a const pointer
69-
*/
70-
const hap_val_t *cur_val = hap_char_get_val(hc);
71-
72-
hap_val_t new_val;
73-
if (cur_val->i == 1) {
74-
new_val.i = 0;
75-
} else {
76-
new_val.i = 1;
77-
}
78-
hap_char_update_val(hc, &new_val);
79-
*status_code = HAP_STATUS_SUCCESS;
80-
}
81-
return HAP_SUCCESS;
82-
}
83-
84-
85-
/* A dummy callback for handling a write on the "On" characteristic of Fan.
86-
* In an actual accessory, this should control the hardware
87-
*/
88-
static int fan_write(hap_write_data_t write_data[], int count, void *serv_priv, void *write_priv)
89-
{
90-
if (hap_req_get_ctrl_id(write_priv))
91-
{
92-
ESP_LOGI(TAG, "Received write from %s", hap_req_get_ctrl_id(write_priv));
93-
}
94-
95-
ESP_LOGI(TAG, "Fan Write called with %d chars", count);
96-
int i, ret = HAP_SUCCESS;
97-
hap_write_data_t *write;
98-
for (i = 0; i < count; i++)
99-
{
100-
write = &write_data[i];
101-
if (!strcmp(hap_char_get_type_uuid(write->hc), HAP_CHAR_UUID_ON))
102-
{
103-
ESP_LOGI(TAG, "Received Write. Fan %s", write->val.b ? "On" : "Off");
104-
105-
/* TODO: Control Actual Hardware */
106-
hap_char_update_val(write->hc, &(write->val));
107-
*(write->status) = HAP_STATUS_SUCCESS;
108-
}
109-
else if (!strcmp(hap_char_get_type_uuid(write->hc), HAP_CHAR_UUID_ROTATION_DIRECTION))
110-
{
111-
if (write->val.i > 1)
112-
{
113-
*(write->status) = HAP_STATUS_VAL_INVALID;
114-
ret = HAP_FAIL;
115-
}
116-
else
117-
{
118-
ESP_LOGI(TAG, "Received Write. Fan %s", write->val.i ? "AntiClockwise" : "Clockwise");
119-
hap_char_update_val(write->hc, &(write->val));
120-
*(write->status) = HAP_STATUS_SUCCESS;
121-
}
122-
}
123-
else
124-
{
125-
*(write->status) = HAP_STATUS_RES_ABSENT;
126-
}
127-
}
128-
return ret;
129-
}
130-
131-
void setup(){
132-
Serial.begin(115200);
133-
134-
WiFi.begin(ssid, password);
135-
136-
while (WiFi.status() != WL_CONNECTED)
137-
{
138-
delay(1000);
139-
Serial.println("Establishing connection to WiFi..");
140-
}
19+
An example of implementing a basic fan accessory can be found in the examples folder. It's based off of the fan example from the origin ESP-IDF SDK.
14120

142-
Serial.println("Connected to network.");
143-
144-
hap_acc_t *accessory;
145-
hap_serv_t *service;
146-
147-
/* Configure HomeKit core to make the Accessory name (and thus the WAC SSID) unique,
148-
* instead of the default configuration wherein only the WAC SSID is made unique.
149-
*/
150-
hap_cfg_t hap_cfg;
151-
hap_get_config(&hap_cfg);
152-
hap_cfg.unique_param = UNIQUE_NAME;
153-
hap_set_config(&hap_cfg);
154-
155-
/* Initialize the HAP core */
156-
hap_init(HAP_TRANSPORT_WIFI);
157-
158-
/* Initialise the mandatory parameters for Accessory which will be added as
159-
* the mandatory services internally
160-
*/
161-
hap_acc_cfg_t cfg = {
162-
.name = "Esp-Fan",
163-
.model = "Espressif",
164-
.manufacturer = "EspFan01",
165-
.serial_num = "001122334455",
166-
.fw_rev = "0.0.1",
167-
.hw_rev = NULL,
168-
.pv = "1.1.0",
169-
.cid = HAP_CID_FAN,
170-
.identify_routine = identify,
171-
};
172-
173-
/* Create accessory object */
174-
accessory = hap_acc_create(&cfg);
175-
176-
/* Add a dummy Product Data */
177-
uint8_t product_data[] = {'P', 'L', 'A', 'N', 'T', 'K', 'I', 'T'};
178-
hap_acc_add_product_data(accessory, product_data, sizeof(product_data));
179-
180-
/* Create the Fan Service. Include the "name" since this is a user visible service */
181-
service = hap_serv_fan_create(false);
182-
hap_serv_add_char(service, hap_char_name_create("My Fan"));
183-
hap_serv_add_char(service, hap_char_rotation_direction_create(0));
184-
185-
/* Set the write callback for the service */
186-
hap_serv_set_write_cb(service, fan_write);
187-
188-
/* Set the read callback for the service (optional) */
189-
hap_serv_set_read_cb(service, fan_read);
190-
191-
/* Add the Fan Service to the Accessory Object */
192-
hap_acc_add_serv(accessory, service);
193-
194-
/* Add the Accessory to the HomeKit Database */
195-
hap_add_accessory(accessory);
196-
197-
/* Query the controller count (just for information) */
198-
ESP_LOGI(TAG, "Accessory is paired with %d controllers",
199-
hap_get_paired_controller_count());
200-
201-
/* TODO: Do the actual hardware initialization here */
202-
203-
/* Unique Setup code of the format xxx-xx-xxx. Default: 111-22-333 */
204-
hap_set_setup_code("111-22-333");
205-
/* Unique four character Setup Id. Default: ES32 */
206-
hap_set_setup_id("ES32");
207-
208-
/* After all the initializations are done, start the HAP core */
209-
hap_start();
210-
}
211-
212-
void loop() {
213-
/* Main loop code */
214-
}
215-
```
21+
As the Arduino style API wrappers haven't been implemented yet, if you have any questions or issues it's best that you visit the ESP-IDF HomeKit SDK repository for additional help.
21622

21723
## To Do
21824

21925
- [ ] Add Arduino API wrappers to make it easier to use.
220-
- [ ] Break down and explain usage example.
221-
- [ ] Currently unified provisioning is enabled but I haven't tested if it actually works.
22226

22327
## License
22428
[MIT](https://choosealicense.com/licenses/mit/)

build.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import subprocess
2+
import os
3+
import glob
4+
import shutil
5+
from distutils.dir_util import copy_tree
6+
from pathlib import Path
7+
import sys
8+
9+
idf_homekit_directory = "lib/esp-homekit-sdk/"
10+
arduino_homekit_directory = "lib/homekit"
11+
12+
priv_includes = "lib/priv_includes"
13+
14+
if len(glob.glob("lib/*.c")) == 0:
15+
# Create the directory path for the ESP-IDF SDK
16+
Path(idf_homekit_directory).mkdir(parents=True, exist_ok=True)
17+
18+
# Check if a .git folder exists, if so assume the project's been cloned.
19+
git_folder = Path(idf_homekit_directory + ".git")
20+
if not git_folder.exists() and not Path(arduino_homekit_directory).exists(): # Add and lib/homekit so i can delete it
21+
commit = "040b0f301223ebc6995597328e5a5cc9f9739a02"
22+
process = subprocess.call(["git", "clone", "--recursive", "https://github.com/espressif/esp-homekit-sdk.git", idf_homekit_directory], stdout=open(os.devnull, 'wb'))
23+
process = subprocess.call(["git", "--git-dir", str(git_folder), "checkout", commit], stdout=open(os.devnull, 'wb'))
24+
shutil.copytree(idf_homekit_directory + "components/homekit", arduino_homekit_directory)
25+
shutil.rmtree(idf_homekit_directory)
26+
27+
for (dirpath, dirnames, filenames) in os.walk(Path(arduino_homekit_directory)):
28+
# 1. Ignore example and test(s)
29+
if "example" in dirpath or "test" in dirpath or "tests" in dirpath:
30+
continue
31+
for file in filenames:
32+
if file.endswith(".c") or file.endswith(".h") and file[:-2] not in mfi_source:
33+
shutil.move(dirpath + "/" + file, "lib/")
34+
35+
#
36+
shutil.rmtree(arduino_homekit_directory)
37+
38+
replacements = {"<jsmn/jsmn.h>": "\"jsmn.h\"", "\"esp32/rom/ets_sys.h\"": "\"rom/ets_sys.h\""}
39+
esp_hap_config = "#include \"esp_hap_config.h\"\n"
40+
for (dirpath, dirnames, filenames) in os.walk("lib"):
41+
for file in filenames:
42+
if file.endswith(".h"):
43+
replacements["<" + file + ">"] = "\"" + file + "\""
44+
45+
for file in filenames:
46+
lines = []
47+
with open("lib/" + file) as infile:
48+
for line in infile:
49+
for src, target in replacements.items():
50+
line = line.replace(src, target)
51+
52+
# Messy manual additions / changes for specific files and lines
53+
if file == "esp_hap_main.c" and "hap_platform_os.h" in line:
54+
line += esp_hap_config
55+
if file == "hap_platform_httpd.c" and "<esp_http_server.h>" in line:
56+
line += esp_hap_config
57+
if file == "esp_mfi_i2c.c" and "esp_mfi_i2c.h" in line:
58+
line += esp_hap_config
59+
60+
lines.append(line)
61+
62+
with open("lib/" + file, 'w') as outfile:
63+
for line in lines:
64+
outfile.write(line)

build.sh

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)