-
Notifications
You must be signed in to change notification settings - Fork 1
/
esp8266-homekit-infrared-remote.ino
182 lines (155 loc) · 5.42 KB
/
esp8266-homekit-infrared-remote.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*
* ESP8266 HomeKit Infrared Remote Blaster
* By Jan Grmela <[email protected]> in 2022
* License: GPL v3 or newer
* Version: 1.1
*
* Based on Arduino-HomeKit-ESP8266 examples by Mixiaoxiao (Wang Bin)
* and IRremoteESP8266 examples by crankyoldgit (David Conran)
*
* Tested successfully on a $2 WEMOS D1 mini clone
* with Arduino 1.8.20 in 2/2022
*
* == Functions ==
* - 1 statefull switch that turn off after a set time after the last turn on event
* - 2 stateless switches that work as buttons - momentary switches
* (turn immediatelly off once triggered)
*
*/
#include <Arduino.h>
#include <arduino_homekit_server.h>
#include "wifi_info.h"
#include <IRremoteESP8266.h>
#include <IRsend.h>
/* USER CONFIG */
// IR module PIN (4 = D2)
#define IR_PIN 4
// LED to blink once transmitted (2 = internal LED)
#define LED_PIN 2
// confirmation LED blink & connected clients log interval
#define BLINK_INTERVAL 1000*10 // 10 seconds
// how long should the stateful switch stay enabled
#define TURN_OFF_AFTER_MILLISECONDS 1000*600 // 10 mins
/* GLOBAL VARS */
#define LOG_D(fmt, ...) printf_P(PSTR(fmt "\n") , ##__VA_ARGS__);
IRsend irsend(IR_PIN);
extern "C" homekit_server_config_t config;
extern "C" homekit_characteristic_t cha_switch_on;
extern "C" homekit_characteristic_t cha_switch_on2;
extern "C" homekit_characteristic_t cha_switch_on3;
static uint32_t next_heap_millis = 0;
static uint32_t next_switch_off_millis = 0;
void setup() {
Serial.begin(115200);
wifi_connect(); // in wifi_info.h
//homekit_storage_reset(); // To remove the previous HomeKit pairing storage when you first run this new HomeKit example
my_homekit_setup();
irsend.begin();
// Set the LED default state to off
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
}
void loop() {
my_homekit_loop();
delay(10);
}
// This is a statefull switch with auto-turn off every X minutes
void cha_switch_on_setter(const homekit_value_t value) {
if(value.bool_value) {
// TURN ON
// reset the timer & do nothing
next_switch_off_millis = millis() + TURN_OFF_AFTER_MILLISECONDS;
LOG_D("Reseting switch timer");
if(cha_switch_on.value.bool_value) {
// Already ON
// Do not need to change the state
homekit_characteristic_notify(&cha_switch_on, cha_switch_on.value);
return;
}
}
else {
// TURN OFF
if(!cha_switch_on.value.bool_value) {
// Switch is already off & we want to turn it off
// Do nothing
homekit_characteristic_notify(&cha_switch_on, cha_switch_on.value);
return;
}
}
// We want to change the state to the other one
// Update the state and trigger the IR
cha_switch_on.value.bool_value = !cha_switch_on.value.bool_value;
irsend.sendNEC(0x807F906F);
switch_triggered(1);
// sync the HK state with our variable
homekit_characteristic_notify(&cha_switch_on, cha_switch_on.value);
}
// These are staless switches (emulated momentary button)
// The setters might be called without the need to send
// the infrared signal - when the setter is called with
// null homekit_value_t, the irsend() is not invoked
void cha_switch_on_setter2(const homekit_value_t value) {
if(!value.is_null) {
irsend.sendNEC(0x4CB38877);
switch_triggered(2);
}
cha_switch_on2.value.bool_value = false;
homekit_characteristic_notify(&cha_switch_on2, cha_switch_on2.value);
}
void cha_switch_on_setter3(const homekit_value_t value) {
if(!value.is_null) {
irsend.sendNEC(0x4CB328D7);
switch_triggered(3);
}
cha_switch_on3.value.bool_value = false;
homekit_characteristic_notify(&cha_switch_on3, cha_switch_on3.value);
}
void my_homekit_setup() {
// Add setters for the switches
// (could be done more elegantly using an array of function pointers in the future)
cha_switch_on.setter = cha_switch_on_setter, cha_switch_on2.setter = cha_switch_on_setter2, cha_switch_on3.setter = cha_switch_on_setter3;
arduino_homekit_setup(&config);
// Now the push buttons default state (which is always false)
const homekit_value_t hn = HOMEKIT_NULL_CPP();
cha_switch_on_setter(hn);
cha_switch_on_setter2(hn);
cha_switch_on_setter3(hn);
}
void my_homekit_loop() {
arduino_homekit_loop();
const uint32_t t = millis();
// periodic LED blink & heap info
if (t > next_heap_millis) {
if(WiFi.status() != WL_CONNECTED) {
// WiFi error: blink 2 times
blink_led();
blink_led();
}
else {
// WiFi OK: blink 1 time
blink_led();
}
next_heap_millis = t + BLINK_INTERVAL;
LOG_D("Free heap: %d, HomeKit clients: %d", ESP.getFreeHeap(), arduino_homekit_connected_clients_count());
if(cha_switch_on.value.bool_value) {
LOG_D("Remaining %d secs before turning off switch 1", (next_switch_off_millis - t)/1000);
}
MDNS.announce(); // fix random connection loss https://github.com/Mixiaoxiao/Arduino-HomeKit-ESP8266/issues/9
}
// automatically turn off the switch after
if(cha_switch_on.value.bool_value && t > next_switch_off_millis) {
const homekit_value_t hn = HOMEKIT_NULL_CPP();
cha_switch_on_setter(hn);
LOG_D("Switch turned off after %d seconds", TURN_OFF_AFTER_MILLISECONDS/1000);
}
}
// Just a console information & LED blink to confirm the switch invocation
void switch_triggered(const int switch_number) {
LOG_D("Switch no %d triggered!", switch_number);
blink_led();
}
void blink_led(void) {
digitalWrite(LED_PIN, LOW);
delay(100);
digitalWrite(LED_PIN, HIGH);
}