Skip to content

Commit ccbdb56

Browse files
committed
Improve auto connection
1 parent fabfa4c commit ccbdb56

File tree

9 files changed

+554
-378
lines changed

9 files changed

+554
-378
lines changed

arduino-altherma-controller/01-interfaces.ino

Lines changed: 118 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,9 @@
1-
/* *******************************************************************
2-
Ethernet interface functions
3-
4-
startEthernet()
5-
- initiates ethernet interface
6-
- if enabled, gets IP from DHCP
7-
- starts all servers (Modbus TCP, UDP, web server)
8-
9-
resetFunc()
10-
- well... resets Arduino
11-
12-
maintainDhcp()
13-
- maintain DHCP lease
14-
15-
maintainUptime()
16-
- maintains up time in case of millis() overflow
17-
18-
maintainCounters(), rollover()
19-
- synchronizes roll-over of data counters to zero
20-
21-
resetStats(), resetEepromStats()
22-
- resets P1P2 stats and Daikin EEPROM stats
23-
24-
generateMac()
25-
- generate random MAC using pseudo random generator (faster and than build-in random())
26-
27-
manageSockets()
28-
- closes sockets which are waiting to be closed or which refuse to close
29-
- forwards sockets with data available for further processing by the webserver
30-
- disconnects (closes) sockets which are too old / idle for too long
31-
- opens new sockets if needed (and if available)
32-
33-
CreateTrulyRandomSeed()
34-
- seed pseudorandom generator using watch dog timer interrupt (works only on AVR)
35-
- see https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library/arduino-random-seed
36-
37-
38-
+ preprocessor code for identifying microcontroller board
39-
40-
***************************************************************** */
41-
42-
1+
/**************************************************************************/
2+
/*!
3+
@brief Initiates ethernet interface, if DHCP enabled, gets IP from DHCP,
4+
starts all servers (UDP, web server).
5+
*/
6+
/**************************************************************************/
437
void startEthernet() {
448
if (ETH_RESET_PIN != 0) {
459
pinMode(ETH_RESET_PIN, OUTPUT);
@@ -68,8 +32,18 @@ void startEthernet() {
6832
#endif
6933
}
7034

35+
/**************************************************************************/
36+
/*!
37+
@brief Resets Arduino (works only on AVR chips).
38+
*/
39+
/**************************************************************************/
7140
void (*resetFunc)(void) = 0; //declare reset function at address 0
7241

42+
/**************************************************************************/
43+
/*!
44+
@brief Maintains DHCP lease.
45+
*/
46+
/**************************************************************************/
7347
#ifdef ENABLE_DHCP
7448
void maintainDhcp() {
7549
if (data.config.enableDhcp && dhcpSuccess == true) { // only call maintain if initial DHCP request by startEthernet was successfull
@@ -78,6 +52,11 @@ void maintainDhcp() {
7852
}
7953
#endif /* ENABLE_DHCP */
8054

55+
/**************************************************************************/
56+
/*!
57+
@brief Maintains uptime in case of millis() overflow.
58+
*/
59+
/**************************************************************************/
8160
#ifdef ENABLE_EXTENDED_WEBUI
8261
void maintainUptime() {
8362
uint32_t milliseconds = millis();
@@ -94,9 +73,13 @@ void maintainUptime() {
9473
}
9574
#endif /* ENABLE_EXTENDED_WEBUI */
9675

97-
const uint32_t ROLLOVER = 0xFFFFFF00;
76+
/**************************************************************************/
77+
/*!
78+
@brief Synchronizes roll-over of data counters to zero.
79+
*/
80+
/**************************************************************************/
9881
bool rollover() {
99-
// synchronize roll-over of run time, data counters and modbus stats to zero, at 0xFFFFFF00
82+
const uint32_t ROLLOVER = 0xFFFFFF00;
10083
for (byte i = 0; i < P1P2_LAST; i++) {
10184
if (data.p1p2Cnt[i] > ROLLOVER) {
10285
return true;
@@ -115,7 +98,11 @@ bool rollover() {
11598
return false;
11699
}
117100

118-
// resets counters to 0: data.p1p2Cnt, data.udpCnt
101+
/**************************************************************************/
102+
/*!
103+
@brief Resets P1P2 stats, date and UDP stats.
104+
*/
105+
/**************************************************************************/
119106
void resetStats() {
120107
memset(data.statsDate, 0, sizeof(data.statsDate));
121108
memset(data.p1p2Cnt, 0, sizeof(data.p1p2Cnt));
@@ -125,11 +112,21 @@ void resetStats() {
125112
#endif /* ENABLE_EXTENDED_WEBUI */
126113
}
127114

115+
/**************************************************************************/
116+
/*!
117+
@brief Resets Daikin EEPROM stats.
118+
*/
119+
/**************************************************************************/
128120
void resetEepromStats() {
129121
memset(&data.eepromDaikin, 0, sizeof(eeprom_t));
130122
}
131123

132-
// generate new MAC (bytes 0, 1 and 2 are static, bytes 3, 4 and 5 are generated randomly)
124+
/**************************************************************************/
125+
/*!
126+
@brief Generate random MAC using pseudo random generator,
127+
bytes 0, 1 and 2 are static (MAC_START), bytes 3, 4 and 5 are generated randomly
128+
*/
129+
/**************************************************************************/
133130
void generateMac() {
134131
// Marsaglia algorithm from https://github.com/RobTillaart/randomHelpers
135132
seed1 = 36969L * (seed1 & 65535L) + (seed1 >> 16);
@@ -142,19 +139,28 @@ void generateMac() {
142139
}
143140
}
144141

142+
/**************************************************************************/
143+
/*!
144+
@brief Write (update) data to Arduino EEPROM.
145+
*/
146+
/**************************************************************************/
145147
void updateEeprom() {
146148
eepromTimer.sleep(EEPROM_INTERVAL * 60UL * 60UL * 1000UL); // EEPROM_INTERVAL is in hours, sleep is in milliseconds!
147149
data.eepromWrites++; // we assume that at least some bytes are written to EEPROM during EEPROM.update or EEPROM.put
148150
EEPROM.put(DATA_START, data);
149151
}
150152

151-
#if MAX_SOCK_NUM == 8
152-
uint32_t lastSocketUse[MAX_SOCK_NUM] = { 0, 0, 0, 0, 0, 0, 0, 0 };
153-
#elif MAX_SOCK_NUM == 4
154-
uint32_t lastSocketUse[MAX_SOCK_NUM] = { 0, 0, 0, 0 };
155-
#endif
156153

157-
// from https://github.com/SapientHetero/Ethernet/blob/master/src/socket.cpp
154+
uint32_t lastSocketUse[MAX_SOCK_NUM];
155+
/**************************************************************************/
156+
/*!
157+
@brief Closes sockets which are waiting to be closed or which refuse to close,
158+
forwards sockets with data available for further processing by the webserver,
159+
disconnects (closes) sockets which are too old (idle for too long), opens
160+
new sockets if needed (and if available).
161+
From https://github.com/SapientHetero/Ethernet/blob/master/src/socket.cpp
162+
*/
163+
/**************************************************************************/
158164
void manageSockets() {
159165
uint32_t maxAge = 0; // the 'age' of the socket in a 'disconnectable' state that was last used the longest time ago
160166
byte oldest = MAX_SOCK_NUM; // the socket number of the 'oldest' disconnectable socket
@@ -231,9 +237,14 @@ void manageSockets() {
231237
}
232238

233239
SPI.endTransaction(); // Serves to o release the bus for other devices to access it. Since the ethernet chip is the only device
234-
// we do not need SPI.beginTransaction(SPI_ETHERNET_SETTINGS) or SPI.endTransaction()
235240
}
236241

242+
/**************************************************************************/
243+
/*!
244+
@brief Disconnect or close a socket.
245+
@param s Socket number.
246+
*/
247+
/**************************************************************************/
237248
void disconSocket(byte s) {
238249
if (W5100.readSnSR(s) == SnSR::ESTABLISHED) {
239250
W5100.execCmdSn(s, Sock_DISCON); // Sock_DISCON does not close LISTEN sockets
@@ -243,65 +254,67 @@ void disconSocket(byte s) {
243254
}
244255
}
245256

257+
/**************************************************************************/
258+
/*!
259+
@brief Maintains connection to the P1P2 bus.
260+
*/
261+
/**************************************************************************/
246262
void manageController() {
247-
if ((controllerState == NOT_SUPPORTED) != data.config.notSupported) {
248-
data.config.notSupported = (controllerState == NOT_SUPPORTED);
249-
updateEeprom();
263+
if (p1p2Timer.isOver()) {
264+
memset(FxRequests, 0, sizeof(FxRequests));
250265
}
251-
switch (controllerState) {
252-
case DISABLED:
253-
case DISCONNECTED:
254-
case NOT_SUPPORTED:
255-
connectionTimer.sleep(data.config.connectTimeout * 1000UL);
256-
controllerId = 0x00;
257-
FxAbsentCnt[0] = -1;
258-
FxAbsentCnt[1] = -1;
259-
cmdQueue.clear();
260-
indoorInQueue = false;
261-
outdoorInQueue = false;
262-
if (data.config.controllerMode == CONTROL_AUTO && controllerState == DISCONNECTED) {
263-
controllerState = CONNECTING;
264-
}
265-
break;
266-
case CONNECTING:
267-
case CONNECTED:
268-
if (connectionTimer.isOver()) {
269-
if (FxAbsentCnt[0] == 0 || FxAbsentCnt[1] == 0) {
270-
controllerState = NOT_SUPPORTED;
271-
} else {
272-
controllerState = DISCONNECTED;
273-
}
274-
}
275-
if (counterRequestTimer.isOver()) {
276-
counterRequestTimer.sleep(data.config.counterPeriod * 60UL * 1000UL);
277-
cmdQueue.push(2);
278-
cmdQueue.push(PACKET_TYPE_COUNTER);
279-
cmdQueue.push(0);
280-
if (data.config.sendDataPackets == DATA_CHANGE_AND_REQUEST) {
281-
memset(savedPackets, 0xFF, sizeof(savedPackets)); // reset saved packets
282-
}
283-
}
284-
if (daikinIndoor[0] == '\0' && indoorInQueue == false) {
285-
cmdQueue.push(2);
286-
cmdQueue.push(PACKET_TYPE_INDOOR_NAME);
287-
cmdQueue.push(0);
288-
indoorInQueue = true;
266+
if (controllerAddr == DISCONNECTED || controllerAddr == CONNECTING) {
267+
cmdQueue.clear();
268+
indoorInQueue = false;
269+
outdoorInQueue = false;
270+
}
271+
if (controllerAddr == DISCONNECTED || (controllerAddr == CONNECTING && data.config.controllerMode == CONTROL_AUTO)) {
272+
connectionTimer.sleep(data.config.connectTimeout * 1000UL);
273+
if (data.config.controllerMode == CONTROL_AUTO) {
274+
controllerAddr = CONNECTING;
275+
}
276+
}
277+
if (connectionTimer.isOver()) {
278+
if (data.config.controllerMode == CONTROL_AUTO) {
279+
controllerAddr = CONNECTING;
280+
} else {
281+
controllerAddr = DISCONNECTED;
282+
}
283+
}
284+
if (controllerAddr > CONNECTING // Send counter requests only if controller in Write mode (after 00Fx30 request + 40Fx30 reply)
285+
|| data.config.controllerMode == CONTROL_AUTO) { // Or if Write to P1P2 is set to Automatically
286+
if (counterRequestTimer.isOver()) {
287+
counterRequestTimer.sleep(data.config.counterPeriod * 60UL * 1000UL);
288+
cmdQueue.push(2);
289+
cmdQueue.push(PACKET_TYPE_COUNTER);
290+
cmdQueue.push(0);
291+
if (data.config.sendDataPackets == DATA_CHANGE_AND_REQUEST) {
292+
memset(savedPackets, 0xFF, sizeof(savedPackets)); // reset saved packets
289293
}
294+
}
295+
if (daikinIndoor[0] == '\0' && indoorInQueue == false) {
296+
cmdQueue.push(2);
297+
cmdQueue.push(PACKET_TYPE_INDOOR_NAME);
298+
cmdQueue.push(0);
299+
indoorInQueue = true;
300+
}
290301
#ifdef ENABLE_EXTENDED_WEBUI
291-
if (daikinOutdoor[0] == '\0' && outdoorInQueue == false) {
292-
cmdQueue.push(2);
293-
cmdQueue.push(PACKET_TYPE_OUTDOOR_NAME);
294-
cmdQueue.push(0);
295-
outdoorInQueue = true;
296-
}
302+
if (daikinOutdoor[0] == '\0' && outdoorInQueue == false) {
303+
cmdQueue.push(2);
304+
cmdQueue.push(PACKET_TYPE_OUTDOOR_NAME);
305+
cmdQueue.push(0);
306+
outdoorInQueue = true;
307+
}
297308
#endif /* ENABLE_EXTENDED_WEBUI */
298-
break;
299-
default:
300-
break;
301309
}
302310
}
303311

304-
// https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library/arduino-random-seed
312+
/**************************************************************************/
313+
/*!
314+
@brief Seed pseudorandom generator using watch dog timer interrupt (works only on AVR).
315+
See https://sites.google.com/site/astudyofentropy/project-definition/timer-jitter-entropy-sources/entropy-library/arduino-random-seed
316+
*/
317+
/**************************************************************************/
305318
void CreateTrulyRandomSeed() {
306319
seed1 = 0;
307320
nrot = 32; // Must be at least 4, but more increased the uniformity of the produced seeds entropy.
@@ -328,11 +341,9 @@ ISR(WDT_vect) {
328341
seed1 = seed1 ^ TCNT1L;
329342
}
330343

331-
// Board definitions
344+
// Preprocessor code for identifying microcontroller board
332345
#if defined(TEENSYDUINO)
333-
334346
// --------------- Teensy -----------------
335-
336347
#if defined(__AVR_ATmega32U4__)
337348
#define BOARD F("Teensy 2.0")
338349
#elif defined(__AVR_AT90USB1286__)
@@ -350,9 +361,7 @@ ISR(WDT_vect) {
350361
#else
351362
#define BOARD F("Unknown Board")
352363
#endif
353-
354364
#else // --------------- Arduino ------------------
355-
356365
#if defined(ARDUINO_AVR_ADK)
357366
#define BOARD F("Arduino Mega Adk")
358367
#elif defined(ARDUINO_AVR_BT) // Bluetooth
@@ -406,5 +415,4 @@ ISR(WDT_vect) {
406415
#else
407416
#define BOARD F("Unknown Board")
408417
#endif
409-
410418
#endif

0 commit comments

Comments
 (0)