Skip to content

Commit 50d5e21

Browse files
committed
chore: update README.md
1 parent b1ff466 commit 50d5e21

File tree

1 file changed

+224
-2
lines changed

1 file changed

+224
-2
lines changed

README.md

Lines changed: 224 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,224 @@
1-
# esp-homekit-arduino-sdk
2-
Arduino wrapper for ESP32 Espressif IDF HomeKit Library
1+
# ESP32 HomeKit Accessory Protocol SDK for Arduino
2+
3+
This library provides the official [ESP-IDF HomeKit SDK](https://github.com/espressif/esp-homekit-sdk) for ESP32 devices running the Arduino framework.
4+
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).
17+
18+
## Installation
19+
20+
If you're using [PlatformIO](https://docs.platformio.org/en/latest/librarymanager/quickstart.html), update your `platformio.ini` file's dependancies or use the `pio` command in the directory containing your `platformio.ini` file:
21+
22+
```bash
23+
pio lib install 'ESP32 HomeKit SDK for Arduino'
24+
```
25+
26+
You can also use the Arduino IDE to install the library via Library Manager or ZIP file.
27+
28+
## Usage
29+
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+
}
141+
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+
```
216+
217+
## To Do
218+
219+
- [ ] 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.
222+
223+
## License
224+
[MIT](https://choosealicense.com/licenses/mit/)

0 commit comments

Comments
 (0)