1
- /*
2
- Program written by JelleWho
3
- Board: https://dl.espressif.com/dl/package_esp32_index.json
4
- Sketch from: https://github.com/jellewie/Arduino-smart-home-switch
1
+ /* Written by JelleWho https://github.com/jellewie
2
+ TODO: https://github.com/jellewie/Arduino-smart-home-switch/issues
5
3
*/
6
4
#if !defined(ESP32)
7
5
#error "Please check if the 'DOIT ESP32 DEVKIT V1' board is selected, which can be downloaded at https://dl.espressif.com/dl/package_esp32_index.json"
11
9
12
10
#ifdef SerialEnabled
13
11
#include < rom/rtc.h> // This is for rtc_get_reset_reason
12
+ #define OTA_EnabledOnBoot
14
13
#define WiFiManager_SerialEnabled
15
14
// #define Button_SerialEnabled
16
15
// #define SerialEnabled_Speed //SP:
17
16
// #define SerialEnabled_Convert //CV:
17
+ #define SerialEnabled_CheckButton
18
18
#endif // SerialEnabled
19
19
20
20
#include " WiFiManagerBefore.h" // Define what options to use/include or to hook into WiFiManager
25
25
char Hub_IP[16 ] = " 192.168.255.255" ; // The url to connect to
26
26
int Hub_Port = 80 ;
27
27
const byte AB = 4 ; // Amount_Buttons
28
- Button ButtonA[AB] = {{34 , INPUT_PULLUP, 21 }, {35 , INPUT_PULLUP, 19 }, {32 , INPUT_PULLUP, 18 }, {33 , INPUT_PULLUP, 5 }}; // Bunch up the 4 buttons to be 1 switch set (Only used for reference pin pares, not which command is connected to which pin)
29
- Button ButtonB[AB] = {{26 , INPUT_PULLUP, 23 }, {27 , INPUT_PULLUP, 22 }, {14 , INPUT_PULLUP, 4 }, {12 , INPUT_PULLUP, 15 }}; // ^
28
+ Button ButtonA[AB] = {{32 , INPUT_PULLUP, 21 }, {33 , INPUT_PULLUP, 19 }, {25 , INPUT_PULLUP, 18 }, {26 , INPUT_PULLUP, 5 }}; // Bunch up the 4 buttons to be 1 switch set (Only used for reference pin pares, not which command is connected to which pin)
29
+ Button ButtonB[AB] = {{27 , INPUT_PULLUP, 23 }, {14 , INPUT_PULLUP, 22 }, {12 , INPUT_PULLUP, 4 }, {13 , INPUT_PULLUP, 15 }}; // ^
30
30
String Path_A[AB] = {" " , " " , " " , " " }; // SOFT_SETTING
31
31
String Path_B[AB] = {" " , " " , " " , " " }; // ^
32
32
String Json_A[AB] = {" " , " " , " " , " " }; // SOFT_SETTING
33
33
String Json_B[AB] = {" " , " " , " " , " " }; // ^
34
34
byte RotationA = NORMAL; // SOFT_SETTING Rotation of the PCB seen from the case
35
35
byte RotationB = UNUSED; // ^ RIGHT=PCB 90° clockwise to case
36
+ const byte BootButtonsWaitMs = 100 ; // Wait for a period of this length on boot for the buttons to be NOT pressed
36
37
37
38
#include " WiFiManagerLater.h" // Define options of WiFiManager (can also be done before), but WiFiManager can also be called here (example for DoRequest)
38
39
@@ -62,39 +63,41 @@ void setup() {
62
63
// ===========================================================================
63
64
// Wait for all buttons to be NOT pressed
64
65
// ===========================================================================
65
- byte ButtonPressedID = 1 ;
66
- while (ButtonPressedID > 0 ) {
67
- #ifdef SerialEnabled
68
- Serial.println (" Waiting on a button(s) " + String (ButtonPressedID, BIN) + " before starting up" );
69
- #endif // SerialEnabled
70
- ButtonPressedID = 0 ; // Set to NOT pressed by default, will be overwritten
66
+ unsigned long WaitUntil = millis () + BootButtonsWaitMs;
67
+ while (WaitUntil > millis ()) {
68
+ byte ButtonStatesA = 0 , ButtonStatesB = 0 ;
69
+ for (byte i = 0 ; i < AB; i++) {
70
+ if (ButtonA[i].CheckButton ().Pressed ) {
71
+ bitSet (ButtonStatesA, i);
72
+ WaitUntil = millis () + BootButtonsWaitMs;
73
+ }
74
+ if (RotationB != UNUSED) {
75
+ if (ButtonB[i].CheckButton ().Pressed ) {
76
+ bitSet (ButtonStatesB, i);
77
+ WaitUntil = millis () + BootButtonsWaitMs;
78
+ }
79
+ }
80
+ }
71
81
static unsigned long LastTimeA = 0 ; // Set to 0, so the first call is FALSE
72
- if (TickEveryXms (&LastTimeA, 50 )) { // Wait here for 50ms (so an error blink would look nice)
73
- // Returns the button states in bits; Like 0000<button1><b2><b3><b4> where 1 is HIGH and 0 is LOW
74
- // Example '00001001' = Buttons 1 and 4 are HIGH (Note we count from LSB)
75
- byte ButtonID = 0 ;
82
+ if (TickEveryXms (&LastTimeA, 50 )) { // Execute every 50ms (so an error blink would look nice)
76
83
for (byte i = 0 ; i < AB; i++) {
77
- ButtonID = ButtonID << 1 ; // Move bits 1 to the left (it’s like *2)
78
- Button_Time Value = ButtonA[i].CheckButton ();
79
- if (Value.Pressed ) {
80
- ButtonID += 1 ; // Flag this button as on
84
+ if (bitRead (ButtonStatesA, i)) {
85
+ bitClear (ButtonStatesA, i);
81
86
if (ButtonA[i].PIN_LED > 0 ) digitalWrite (ButtonA[i].PIN_LED , !digitalRead (ButtonA[i].PIN_LED ));
82
- } else if (ButtonA[i].PIN_LED > 0 )
83
- digitalWrite (ButtonA[i].PIN_LED , LOW);
84
- }
85
- if (RotationB != UNUSED) {
86
- for (byte i = 0 ; i < AB; i++) {
87
- ButtonID = ButtonID << 1 ; // Move bits 1 to the left (it’s like *2)
88
- Button_Time Value = ButtonB[i].CheckButton ();
89
- if (Value.Pressed ) {
90
- ButtonID += 1 ; // Flag this button as on
91
- if (ButtonA[i].PIN_LED > 0 ) digitalWrite (ButtonB[i].PIN_LED , !digitalRead (ButtonB[i].PIN_LED ));
92
- } else if (ButtonB[i].PIN_LED > 0 )
93
- digitalWrite (ButtonB[i].PIN_LED , LOW);
87
+ } else {
88
+ if (ButtonA[i].PIN_LED > 0 ) digitalWrite (ButtonA[i].PIN_LED , LOW);
89
+ }
90
+ if (bitRead (ButtonStatesB, i)) {
91
+ bitClear (ButtonStatesB, i);
92
+ if (ButtonB[i].PIN_LED > 0 ) digitalWrite (ButtonB[i].PIN_LED , !digitalRead (ButtonB[i].PIN_LED ));
93
+ } else {
94
+ if (ButtonB[i].PIN_LED > 0 ) digitalWrite (ButtonB[i].PIN_LED , LOW);
94
95
}
95
96
}
96
- ButtonPressedID = ButtonID; // Get the button state, here 1 is HIGH in the form of '0000<Button 1><2><3><4> '
97
97
}
98
+ #ifdef SerialEnabled
99
+ Serial.println (" Waiting on a button(s) " + String (ButtonStatesA, BIN) + " _" + String (ButtonStatesB, BIN) + " before starting up, wait ms=" + String (WaitUntil - millis ()));
100
+ #endif // SerialEnabled
98
101
}
99
102
for (byte i = 0 ; i < AB; i++) {
100
103
digitalWrite (ButtonA[i].PIN_LED , LOW); // Make sure all LED's are off
@@ -104,6 +107,7 @@ void setup() {
104
107
// ===========================================================================
105
108
// Start WIFI
106
109
// ===========================================================================
110
+ server.on (" /test" , handle_Test); // Declair the TEST urls
107
111
byte Answer = WiFiManager.Start ();
108
112
if (Answer != 1 ) {
109
113
#ifdef SerialEnabled
@@ -114,8 +118,14 @@ void setup() {
114
118
WiFiManager.OTA_Enabled = false ;
115
119
WiFiManager.EnableSetup (true ); // Start the server (if you also need it for other stuff)
116
120
// ===========================================================================
117
- // Get Reset reason (This could be/is useful for power outage)
121
+ // Get Reset reason (This could be/is useful for power outage? )
118
122
// ===========================================================================
123
+ #ifdef OTA_EnabledOnBoot
124
+ // WiFiManager.OTA_Enabled = true;
125
+ # ifdef SerialEnabled
126
+ Serial.println (" Due to 'OTA_EnabledOnBoot' debug mode, OTA is enabled after boot by default" );
127
+ # endif // SerialEnabled
128
+ #endif // OtaEnabledOnBoot
119
129
#ifdef SerialEnabled
120
130
Serial.println (" Done with boot, resetted due to " + ResetReasonToString (GetResetReason ()) + " boottime=" + String (millis ()));
121
131
#endif // SerialEnabled
@@ -139,21 +149,31 @@ void loop() {
139
149
140
150
for (byte i = 0 ; i < AB; i++) {
141
151
Check (ButtonA[i].CheckButton (), // The button state (contains info like if its just pressed and such)
142
- Path_A[i ] == " " ? Path_A[1 ] : Path_A[RotatedButtonID (RotationA, i)] , // The URL, if(non given){default to first given path}
143
- Json_A[RotatedButtonID (RotationA, i)], // The command to execute
152
+ Path_A[RotatedButtonID (RotationA, i) ] == " " ? Path_A[0 ] : Path_A[RotatedButtonID (RotationA, i)] , // The URL, if(non given){default to first given path}
153
+ Json_A[RotatedButtonID (RotationA, i)], // The command to execute
144
154
ButtonA[i].PIN_LED ); // The LED corospanding to this button
145
155
if (RotationB != UNUSED)
146
156
Check (ButtonB[i].CheckButton (),
147
- Path_B[i ] == " " ? Path_B[1 ] : Path_A [RotatedButtonID (RotationB, i)] ,
157
+ Path_B[RotatedButtonID (RotationB, i) ] == " " ? Path_B[0 ] : Path_B [RotatedButtonID (RotationB, i)] ,
148
158
Json_B[RotatedButtonID (RotationB, i)],
149
159
ButtonB[i].PIN_LED );
150
160
}
151
161
}
152
162
// ===========================================================================
153
- void Check (Button_Time Value, String Path, String Json, byte LEDpin) {
154
- #ifdef SerialEnabled
155
- Serial.println (String (Value.Pressed ) + " S=" + String (Value.StartPress ) + " L=" + String (Value.PressedLong ) + " SL=" + String (Value.StartLongPress ) + " LEDpin=" + String (LEDpin) + " Path=" + String (Path) + " Json=" + String (Json));
156
- #endif // SerialEnabled
163
+ byte Check (Button_Time Value, String Path, String Json, byte LEDpin) {
164
+ byte Answer = 0 ;
165
+ #ifdef SerialEnabled_CheckButton
166
+ if (Value.StartPress or Value.Pressed or
167
+ Value.StartLongPress or Value.PressedLong or
168
+ Value.StartDoublePress or Value.DoublePress or
169
+ Value.StartRelease ) // If there was an update
170
+ Serial.println (" CB: S" + String (Value.StartPress ) + " _" + String (Value.Pressed ) + " "
171
+ " L" + String (Value.StartLongPress ) + " _" + String (Value.PressedLong ) + " "
172
+ " D" + String (Value.StartDoublePress ) + " _" + String (Value.DoublePress ) + " "
173
+ " R" + String (Value.StartRelease ) + " _" + String (Value.PressEnded ) + " "
174
+ " T" + String (Value.PressedTime ) + " "
175
+ " LEDpin=" + String (LEDpin) + " Path=" + String (Path) + " Json=" + String (Json));
176
+ #endif // SerialEnabled_CheckButton
157
177
158
178
if (Value.StartPress ) { // If button is just pressed in
159
179
@@ -162,10 +182,9 @@ void Check(Button_Time Value, String Path, String Json, byte LEDpin) {
162
182
#endif // SerialEnabled_Speed
163
183
164
184
if (LEDpin > 0 ) digitalWrite (LEDpin, HIGH); // If a LED pin was given; Set that buttons LED on
165
- byte Answer = WiFiManager.DoRequest (Hub_IP, Hub_Port, Path, Json);
185
+ Answer = WiFiManager.DoRequest (Hub_IP, Hub_Port, Path, Json);
166
186
if (LEDpin > 0 ) digitalWrite (LEDpin, LOW); // If a LED pin was given; Set that buttons LED off
167
187
168
- Answer = Answer + 0 ; // mask compiler warning if 'SerialEnabled' is not defined
169
188
#ifdef SerialEnabled
170
189
Serial.println (" DoRequest executed with responce code '" + DoRequestReasonToString (Answer) + " '" ); // The return codes can be found in "WiFiManager.cpp" in "CWiFiManager::DoRequest("
171
190
# ifdef SerialEnabled_Speed
@@ -176,10 +195,13 @@ void Check(Button_Time Value, String Path, String Json, byte LEDpin) {
176
195
} else if (Value.StartLongPress ) {
177
196
WiFiManager.OTA_Enabled = !WiFiManager.OTA_Enabled ; // Toggle OTA on/off
178
197
if (LEDpin > 0 ) digitalWrite (LEDpin, LOW); // If a LED pin was given; Set that buttons LED off
198
+ #ifdef SerialEnabled
199
+ Serial.println (" Toggled OTA " + String (WiFiManager.OTA_Enabled ? " ON" : " OFF" ));
200
+ #endif // SerialEnabled
179
201
}
180
202
if (Value.PressedLong ) { // If it is/was a long press
181
203
if (Value.Pressed ) { // If we are still pressing
182
- if (Value.PressedTime > Time_ESPrestartMS - 1000 ) {
204
+ if (Value.PressedTime > Time_ESPrestartMS - 2000 ) {
183
205
if (LEDpin > 0 ) BlinkEveryMs (LEDpin, 10 ); // If a LED pin was given; Blink that button LED
184
206
} else
185
207
digitalWrite (LED_BUILTIN, HIGH);
@@ -188,6 +210,7 @@ void Check(Button_Time Value, String Path, String Json, byte LEDpin) {
188
210
if (LEDpin > 0 ) digitalWrite (LEDpin, LOW); // If a LED pin was given; Blink that button LED
189
211
}
190
212
}
213
+ return Answer;
191
214
}
192
215
byte RotatedButtonID (byte Rotation, byte i) {
193
216
switch (Rotation) {
@@ -217,6 +240,35 @@ byte RotatedButtonID(byte Rotation, byte i) {
217
240
}
218
241
return 0 ;
219
242
}
243
+ void handle_Test () {
244
+ byte i = 0 ;
245
+ char m = ' A' ;
246
+ if (server.args ()) {
247
+ String ArguName = server.argName (i);
248
+ ArguName.toUpperCase ();
249
+ ArguName.substring (0 , 1 );
250
+ if (ArguName == " B" ) m = ' B' ;
251
+ i = server.arg (i).toInt ();
252
+ if (i > 4 ) i = 3 ;
253
+ if (i < 1 ) i = 1 ;
254
+ }
255
+ String Path = Path_A[RotatedButtonID (RotationA, i - 1 )] == " " ? Path_A[0 ] : Path_A[RotatedButtonID (RotationA, i - 1 )];
256
+ String Json = Json_A[RotatedButtonID (RotationA, i - 1 )];
257
+ byte LEDpin = ButtonA[i].PIN_LED ;
258
+ if (m == ' B' ) {
259
+ Path = Path_B[RotatedButtonID (RotationB, i - 1 )] == " " ? Path_B[0 ] : Path_B[RotatedButtonID (RotationB, i - 1 )];
260
+ Json = Json_B[RotatedButtonID (RotationB, i - 1 )];
261
+ LEDpin = ButtonB[i].PIN_LED ;
262
+ }
263
+
264
+ Button_Time Dummy;
265
+ Dummy.StartPress = true ;
266
+ byte Answer = Check (Dummy, Path, Json, LEDpin);
267
+
268
+ server.send (200 , " text/plain" , " DoRequest " + String (m) + String (i) + " with result " + String (Answer) + " \n\n "
269
+ " " + String (Hub_IP) + " :" + String (Hub_Port) + String (Path) + " \n "
270
+ " " + String (Json));
271
+ }
220
272
// ===========================================================================
221
273
void ISR_A0 () {
222
274
ButtonA[0 ].Pinchange ();
0 commit comments