RF24Ethernet - TCP/IP over RF24Network v2.1.4
TMRh20 - Pushing the practical limits of RF24 modules
Loading...
Searching...
No Matches
RF24Client.cpp
Go to the documentation of this file.
1/*
2 RF24Client.cpp - Arduino implementation of a uIP wrapper class.
3 Copyright (c) 2014 tmrh20@gmail.com, github.com/TMRh20
4 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
5 All rights reserved.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17#include "RF24Ethernet.h"
18
19#if USE_LWIP < 1
20
21 #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN
22uip_userdata_t RF24Client::all_data[UIP_CONNS];
23
24#else
25// #define LWIP_ERR_T uint32_t
26
27 //
28 #if !defined ETHERNET_USING_LWIP_ARDUINO
29 #include <lwip/tcp.h>
30 #include "lwip/tcpip.h"
31 #include "lwip/timeouts.h"
32 #else
33 #include "lwip/include/lwip/tcp.h"
34 #include "lwip/include/lwip/tcpip.h"
35 #endif
36
37 #include "RF24Ethernet.h"
38/** \cond */
40char* RF24Client::incomingData[2];
41uint16_t RF24Client::dataSize[2];
42struct tcp_pcb* RF24Client::myPcb;
43uint32_t RF24Client::clientConnectionTimeout;
44uint32_t RF24Client::serverConnectionTimeout;
45uint32_t RF24Client::simpleCounter;
47int32_t RF24Client::accepts;
48
49/***************************************************************************************************/
50
51// Called when the remote host acknowledges receipt of data
52err_t RF24Client::sent_callback(void* arg, struct tcp_pcb* tpcb, u16_t len)
53{
54
55 ConnectState* state = (ConnectState*)arg;
56 if (state != nullptr) {
57 state->serverTimer = millis();
58 state->clientTimer = millis();
59 IF_ETH_DEBUG_L1(Serial.println("Client: Sent cb"););
60
61 state->waiting_for_ack = false; // Data is successfully out
62 state->finished = true;
63 }
64
65 return ERR_OK;
66}
67
68/***************************************************************************************************/
69
70err_t RF24Client::blocking_write(struct tcp_pcb* fpcb, ConnectState* fstate, const char* data, size_t len)
71{
72
73 if (fpcb == nullptr) {
74 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: Tx with no fpcb"););
75 return ERR_CLSD;
76 }
77
78 if (!fstate->connected) {
79 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: Tx with no connection"););
80 return ERR_CLSD;
81 }
82
83 const uint32_t timeoutStart = millis();
84 while (len > tcp_sndbuf(fpcb)) {
85 Ethernet.update();
86 if (millis() - timeoutStart > serverConnectionTimeout) {
87 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: TCP Send Buffer full"););
88 return ERR_BUF;
89 }
90 }
91
92 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
93 if (Ethernet.useCoreLocking) {
94 ETHERNET_APPLY_LOCK();
95 }
96 #endif
97
98 err_t err = ERR_CLSD;
99 if (fpcb != nullptr) {
100 err = tcp_write(fpcb, data, len, TCP_WRITE_FLAG_COPY);
101 }
102
103 //Ethernet.update();
104 if (err != ERR_OK) {
105 if (fstate != nullptr) {
106 fstate->waiting_for_ack = false;
107 fstate->finished = true;
108 }
109 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: BLK Write fail 2: "); Serial.println((int)err););
110
111 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
112 if (Ethernet.useCoreLocking) {
113 ETHERNET_REMOVE_LOCK();
114 }
115 #endif
116 return err;
117 }
118
119 if (fpcb != nullptr && fpcb->state != CLOSED && fstate->connected) {
120 tcp_sent(fpcb, sent_callback);
121 }
122 else {
123 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: TCP OUT FAIL"););
124
125 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
126 if (Ethernet.useCoreLocking) {
127 ETHERNET_REMOVE_LOCK();
128 }
129 #endif
130 return ERR_BUF;
131 }
132 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
133 if (Ethernet.useCoreLocking) {
134 ETHERNET_REMOVE_LOCK();
135 }
136 #endif
137
138 const uint32_t timerStart = millis();
139 while (fstate != nullptr && fstate->waiting_for_ack && !fstate->finished) {
140 if (millis() - timerStart > 5000) {
141 if (fstate != nullptr) {
142 fstate->finished = true;
143 return ERR_CLSD;
144 }
145 break;
146 }
147 Ethernet.update();
148 }
149
150 return ERR_OK;
151}
152
153/***************************************************************************************************/
154
155void RF24Client::error_callback(void* arg, err_t err)
156{
157
158 ConnectState* state = (ConnectState*)arg;
159 if (state != nullptr) {
160 state->result = err;
161 state->connected = false;
162 state->finished = true; // Break the blocking loop
163 state->waiting_for_ack = false;
164 dataSize[state->stateActiveID] = 0;
165 if (state->stateActiveID == activeState) {
166 myPcb = nullptr;
167 }
168 }
169 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Client: Err cb: "); Serial.println((int)err););
170}
171
172/***************************************************************************************************/
173
174err_t RF24Client::srecv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err)
175{
176
177 ConnectState* state = (ConnectState*)arg;
178
179 if (state != nullptr) {
180 state->serverTimer = millis();
181 }
182
183 if (p == nullptr) {
184 if (state != nullptr) {
185 state->connected = false;
186 state->finished = true; // Break the loop
187 }
188 if (tpcb != nullptr) {
189 if (tcp_close(tpcb) != ERR_OK) {
190 tcp_abort(tpcb);
191 tpcb = nullptr;
192 if (state->stateActiveID == activeState) {
193 myPcb = nullptr;
194 }
195 return ERR_ABRT;
196 }
197 tpcb = nullptr;
198 if (state->stateActiveID == activeState) {
199 myPcb = nullptr;
200 }
201 }
202 return ERR_OK;
203 }
204 if (err != ERR_OK || state == nullptr) {
205 if (p)
206 pbuf_free(p);
207 return ERR_OK;
208 }
209
210 bool id = state->stateActiveID;
211 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Copy data to "); Serial.println(state->stateActiveID););
212
213 struct pbuf* q = p;
214 while (q != nullptr) {
215 const uint8_t* data = static_cast<const uint8_t*>(q->payload);
216 if (dataSize[id] + q->len < INCOMING_DATA_SIZE) {
217 memcpy(&incomingData[id][dataSize[id]], data, q->len);
218 dataSize[id] += q->len;
219 }
220 else {
221 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: srecv - Out of incoming buffer space"););
222 }
223 q = q->next;
224 }
225
226 if (tpcb != nullptr) {
227 tcp_recved(tpcb, p->tot_len);
228 }
229 if (p) {
230 pbuf_free(p);
231 }
232 return ERR_OK;
233}
234
235/***************************************************************************************************/
236
237err_t RF24Client::recv_callback(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err)
238{
239
240 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Recv cb"););
241
242 ConnectState* state = (ConnectState*)arg;
243 if (p == nullptr) {
244 if (state != nullptr) {
245 state->connected = false;
246 state->finished = true; // Break the loop
247 }
248 if (tpcb != nullptr) {
249 if (tcp_close(tpcb) != ERR_OK) {
250 tcp_abort(tpcb);
251 tpcb = nullptr;
252 if (state->stateActiveID == activeState) {
253 myPcb = nullptr;
254 }
255 return ERR_ABRT;
256 }
257 tpcb = nullptr;
258 if (state->stateActiveID == activeState) {
259 myPcb = nullptr;
260 }
261 }
262 return err;
263 }
264 if (err != ERR_OK || state == nullptr) {
265 if (p)
266 pbuf_free(p);
267 return err;
268 }
269
270 if (state != nullptr) {
271 state->clientTimer = millis();
272 }
273
274 bool id = state->stateActiveID;
275 struct pbuf* q = p;
276 while (q != nullptr) {
277 const uint8_t* data = static_cast<const uint8_t*>(q->payload);
278 if (dataSize[id] + q->len < INCOMING_DATA_SIZE) {
279 memcpy(&incomingData[id][dataSize[id]], data, q->len);
280 dataSize[id] += q->len;
281 }
282 else {
283 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: recv - Out of incoming buffer space"););
284 }
285 q = q->next;
286 }
287
288 if (tpcb != nullptr) {
289 tcp_recved(tpcb, p->tot_len);
290 }
291 if (p) {
292 pbuf_free(p);
293 }
294 return ERR_OK;
295}
296
297/***************************************************************************************************/
298
299//void RF24Client::setConnectionTimeout(uint32_t timeout)
300//{
301
302// clientConnectionTimeout = timeout;
303//}
304
305/***************************************************************************************************/
306
307err_t RF24Client::clientTimeouts(void* arg, struct tcp_pcb* tpcb)
308{
309
310 ConnectState* state = (ConnectState*)arg;
311
312 if (state != nullptr) {
313 if (millis() - state->clientTimer > state->cConnectionTimeout) {
314 if (tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD) {
315 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Closed Client PCB TIMEOUT"););
316 err_t err = tcp_close(tpcb);
317 state->result = err;
318 state->connected = false;
319 state->finished = true; // Break the blocking loop
320 state->waiting_for_ack = false;
321 }
322 }
323 }
324 return ERR_OK;
325}
326
327/***************************************************************************************************/
328
329err_t RF24Client::serverTimeouts(void* arg, struct tcp_pcb* tpcb)
330{
331
332 ConnectState* state = (ConnectState*)arg;
333
334 if (state != nullptr && tpcb != nullptr) {
335 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Stimeout cb "); Serial.println(millis() - state->serverTimer););
336
337 state->result = ERR_OK;
338
339 if (millis() - state->serverTimer > state->sConnectionTimeout && state->backlogWasClosed == false) {
340 //if (tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD) {
341 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: Closed Server PCB TIMEOUT "););
342
343 state->result = tcp_close(tpcb);
344 state->closeTimer = millis();
345 state->backlogWasClosed = true;
346 dataSize[activeState] = 0;
347 state->connected = false;
348 state->finished = true;
349 if (state->result != ERR_OK) {
350 tcp_arg(tpcb, nullptr);
351 tcp_abort(tpcb);
352 tpcb = nullptr;
353 return ERR_ABRT;
354 }
355 return state->result;
356
357 // }
358 }
359 if (state->backlogWasClosed == true) {
360 if (millis() - state->closeTimer > 5000) {
361 tcp_arg(tpcb, nullptr);
362 tcp_abort(tpcb);
363 tpcb = nullptr;
364 return ERR_ABRT;
365 }
366 }
367 return state->result;
368 }
369 return ERR_CLSD;
370}
371
372/***************************************************************************************************/
373
374err_t RF24Client::closed_port(void* arg, struct tcp_pcb* tpcb)
375{
376
377 ConnectState* state = (ConnectState*)arg;
378
379 if (state != nullptr) {
380 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Client Poll Cb ID: "); Serial.println(state->identifier));
381 }
382
383 if (myPcb == nullptr) {
384 if (state != nullptr && tpcb != nullptr) {
385
386 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
387 if (state->backlogWasAccepted == false && state->backlogWasClosed == false) {
388
389 state->backlogWasAccepted = true;
390 state->connectTimestamp = millis();
391 state->connected = true;
392 state->finished = false;
393 accepts--;
394 myPcb = tpcb;
395 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: ACCEPT delayed PCB "); Serial.println(state->identifier););
396
397 tcp_backlog_accepted(tpcb);
398 activeState = state->stateActiveID;
399 return ERR_OK;
400 }
401 }
402 }
403 }
404
405 if (tpcb != nullptr) {
406 if (state != nullptr) {
407 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
408
409 if ((tpcb->state == ESTABLISHED || tpcb->state == SYN_SENT || tpcb->state == SYN_RCVD)) {
410 if (state->backlogWasClosed == false) {
411
412 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Close off delayed PCB function 1, ID: "); Serial.println(state->identifier););
413
414 if (state->backlogWasAccepted == false) {
415 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: With backlog accepted"););
416 tcp_backlog_accepted(tpcb);
417 state->backlogWasAccepted = true;
418 accepts--;
419 }
420
421 state->result = tcp_close(tpcb);
422 state->backlogWasClosed = true;
423 if (state->result == ERR_OK) {
424 state->closeTimer = millis();
425 state->finished = true;
426 }
427 else {
428 tcp_abort(tpcb);
429 tpcb = nullptr;
430 return ERR_ABRT;
431 }
432
433 return state->result;
434 }
435 else {
436 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Killing off TPCB already closed function 1, ID: "););
437
438 if (state != nullptr) {
439 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(state->identifier););
440 }
441 if (millis() - state->closeTimer > 5000) {
442 tcp_abort(tpcb);
443 tpcb = nullptr;
444 return ERR_ABRT;
445 }
446 }
447 }
448 }
449 }
450 }
451 if (tpcb != nullptr) {
452 if (state != nullptr) {
453 if (millis() - state->connectTimestamp > state->sConnectionTimeout) {
454 if (state->backlogWasClosed == false) {
455 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Close off delayed PCB function 2, ID "); Serial.println(state->identifier););
456 if (state->backlogWasAccepted == false) {
457 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Server: With backlog accepted"););
458 tcp_backlog_accepted(tpcb);
459 state->backlogWasAccepted = true;
460 accepts--;
461 }
462 state->result = tcp_close(tpcb);
463 state->backlogWasClosed = true;
464 if (state->result == ERR_OK) {
465 state->closeTimer = millis();
466 state->finished = true;
467 }
468 else {
469 tcp_abort(tpcb);
470 tpcb = nullptr;
471 return ERR_ABRT;
472 }
473 return state->result;
474 }
475 else {
476 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Killing off TPCB already closed function 2, ID: "););
477 if (state != nullptr) {
478 Serial.println(state->identifier);
479 if (millis() - state->closeTimer > 5000) {
480 tcp_abort(tpcb);
481 tpcb = nullptr;
482 return ERR_ABRT;
483 }
484 }
485 }
486 }
487 }
488 }
489
490 return ERR_OK;
491}
492
493/**************************************************************************************************/
494
495err_t RF24Client::accept(void* arg, struct tcp_pcb* tpcb, err_t err)
496{
497 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Accept cb, ID: "); Serial.println(simpleCounter + 1););
498
499 if (tpcb == nullptr) {
500 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Accepted conn, but no tpcb from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
501 return ERR_CLSD;
502 }
503
504 if (tpcb != nullptr) {
505 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Client connect from: "); Serial.println(ip4addr_ntoa(ip_2_ip4(&tpcb->remote_ip))););
506 }
507 bool actState = activeState;
508
509 if (myPcb != nullptr) {
510
511 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print("Server: Accept w/already connected: Accepted_Conns - Delayed_Conns == "); Serial.println(accepts););
512 tcp_backlog_delayed(tpcb);
513 accepts++;
514 tcp_poll(tpcb, closed_port, 5);
515 actState = !activeState;
516 gState[actState]->connected = false;
517 gState[actState]->backlogWasAccepted = false;
518 }
519 else {
520 myPcb = tpcb;
521 tcp_poll(tpcb, serverTimeouts, 8);
523 actState = activeState;
524 gState[actState]->connected = true;
525 gState[actState]->backlogWasAccepted = true;
526 }
527
528 dataSize[actState] = 0;
529
530 simpleCounter += 1;
531 gState[actState]->stateActiveID = actState;
532 gState[actState]->identifier = simpleCounter;
533 gState[actState]->finished = false;
534 gState[actState]->sConnectionTimeout = serverConnectionTimeout;
535 gState[actState]->waiting_for_ack = false;
536 gState[actState]->backlogWasClosed = false;
537 gState[actState]->connectTimestamp = millis();
538 gState[actState]->serverTimer = millis();
539
540 tcp_arg(tpcb, RF24Client::gState[actState]);
541 tcp_recv(tpcb, srecv_callback);
542 tcp_sent(tpcb, sent_callback);
543 tcp_err(tpcb, error_callback);
544
545 return ERR_OK;
546}
547
548/***************************************************************************************************/
549err_t RF24Client::closeConn(void* arg, struct tcp_pcb* tpcb)
550{
551 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Immediate close"););
552 if (tpcb != nullptr) {
553 tcp_close(tpcb);
554 }
555
556 return ERR_OK;
557}
558
559/***************************************************************************************************/
560
561// Callback triggered by lwIP when handshake completes
562
563err_t RF24Client::on_connected(void* arg, struct tcp_pcb* tpcb, err_t err)
564{
565 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println("Client: Conn cb"););
566
567 ConnectState* state = (ConnectState*)arg;
568
569 if (state != nullptr) {
570 /*if (state->cConnectionTimeout > 0) {
571 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
572 if(Ethernet.useCoreLocking){if(Ethernet.useCoreLocking){ ETHERNET_APPLY_LOCK(); } }
573 #endif
574 tcp_poll(tpcb, clientTimeouts, 30);
575 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
576 if(Ethernet.useCoreLocking){ ETHERNET_REMOVE_LOCK(); }
577 #endif
578 }*/
579
580 state->cConnectionTimeout = clientConnectionTimeout;
581 state->clientTimer = millis();
582 state->result = err;
583 state->finished = true;
584 if (err == ERR_OK) {
585 state->connected = true;
586 }
587 else {
588 state->connected = false;
589 }
590 state->waiting_for_ack = false;
591 }
592 return err;
593}
594/** \endcond */
595#endif // USE_LWIP > 1
596
597/***************************************************************************************************/
598
599#if USE_LWIP < 1
600RF24Client::RF24Client() : data(NULL)
601{
602}
603#else
605{
606}
607
608#endif
609/*************************************************************/
610
611#if USE_LWIP < 1
612RF24Client::RF24Client(uip_userdata_t* conn_data) : data(conn_data)
613{
614}
615#else
616/** \cond */
617RF24Client::RF24Client(uint32_t data) : data(0)
618{
619}
620/** \endcond */
621#endif
622/*************************************************************/
623
625{
626#if USE_LWIP < 1
627 return (data && (data->packets_in != 0 || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
628#else
629 if (gState[activeState] != nullptr) {
630 return gState[activeState]->connected;
631 }
632 return 0;
633#endif
634}
635
636/*************************************************************/
637
638int RF24Client::connect(IPAddress ip, uint16_t port)
639{
640
641#if USE_LWIP < 1
642 #if UIP_ACTIVE_OPEN > 0
643
644 // do{
645
646 stop();
647 uip_ipaddr_t ipaddr;
648 uip_ip_addr(ipaddr, ip);
649
650 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
651
652 if (conn)
653 {
654 #if UIP_CONNECTION_TIMEOUT > 0
655 uint32_t timeout = millis();
656 #endif
657
658 while ((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
659 {
660 Ethernet.update();
661
662 if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
663 {
664 data = (uip_userdata_t*)conn->appstate;
665 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(millis()); Serial.print(F(" connected, state: ")); Serial.print(data->state); Serial.print(F(", first packet in: ")); Serial.println(data->packets_in););
666 return 1;
667 }
668
669 #if UIP_CONNECTION_TIMEOUT > 0
670 if ((millis() - timeout) > UIP_CONNECTION_TIMEOUT)
671 {
672 conn->tcpstateflags = UIP_CLOSED;
673 break;
674 }
675 #endif
676 }
677 }
678 // delay(25);
679 // }while(millis()-timer < 175);
680
681 #endif // Active open enabled
682#else
683
684 if (myPcb != nullptr) {
685 _stop();
686 return ERR_CLSD;
687 }
688
689 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
690 if (Ethernet.useCoreLocking) {
691 ETHERNET_APPLY_LOCK();
692 }
693 #endif
694
695 if (myPcb == nullptr) {
696 myPcb = tcp_new();
697 }
698
699 if (!myPcb) {
700 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
701 if (Ethernet.useCoreLocking) {
702 ETHERNET_REMOVE_LOCK();
703 }
704 #endif
705 return 0;
706 }
707
708 dataSize[activeState] = 0;
709 memset(incomingData[activeState], 0, INCOMING_DATA_SIZE);
710
711 gState[activeState]->finished = false;
712 gState[activeState]->connected = false;
713 gState[activeState]->result = 0;
714 gState[activeState]->waiting_for_ack = false;
715
716 tcp_arg(myPcb, gState[activeState]);
717 tcp_err(myPcb, error_callback);
718 tcp_recv(myPcb, recv_callback);
719 //tcp_poll(myPcb, clientTimeouts, 30);
720
721 err_t err = ERR_OK;
722
723 ip_addr_t myIp;
724 IP_ADDR4(&myIp, ip[0], ip[1], ip[2], ip[3]);
725
726 err = tcp_connect(myPcb, &myIp, port, on_connected);
727
728 if (err != ERR_OK || gState[activeState]->result != ERR_OK) {
729 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
730 if (Ethernet.useCoreLocking) {
731 ETHERNET_REMOVE_LOCK();
732 }
733 #endif
734
735 stop();
736 return ERR_CLSD;
737 }
738
739 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
740 if (Ethernet.useCoreLocking) {
741 ETHERNET_REMOVE_LOCK();
742 }
743 #endif
744
745 const uint32_t timeoutStart = millis();
746 // Simulate blocking by looping until the callback sets 'finished'
747 while (!gState[activeState]->finished && millis() - timeoutStart < 5000) {
748 Ethernet.update();
749 }
750
751 if (clientConnectionTimeout > 0) {
752 gState[activeState]->clientPollingSetup = 1;
753 }
754
755 return gState[activeState]->connected;
756
757#endif
758 return 0;
759}
760
761/*************************************************************/
762
763#if USE_LWIP > 1
764void dnsCallback(const char* name, const ip_addr_t* ipaddr, void* callback_arg)
765{
766}
767#endif
768/*************************************************************/
769
770int RF24Client::connect(const char* host, uint16_t port)
771{
772 // Look up the host first
773 int ret = 0;
774
775#if UIP_UDP
776 DNSClient dns;
777 IPAddress remote_addr;
778
779 dns.begin(RF24EthernetClass::_dnsServerAddress);
780 ret = dns.getHostByName(host, remote_addr);
781
782 if (ret == 1)
783 {
784 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
785 Serial.println(F("*UIP Got DNS*"));
786 #endif
787 return connect(remote_addr, port);
788 }
789#elif RF24ETHERNET_USE_UDP
790
791 DNSClient dns;
792 IPAddress remote_addr;
793
794 dns.begin(RF24EthernetClass::_dnsServerAddress);
795 ret = dns.getHostByName(host, remote_addr);
796
797 if (ret == 1)
798 {
799 #if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
800 Serial.println(F("*lwIP Got DNS*"));
801 #endif
802 return connect(remote_addr, port);
803 }
804
805#else // ! UIP_UDP
806 // Do something with the input parameters to prevent compile time warnings
807 if (host) {
808 };
809 if (port) {
810 };
811#endif // ! UIP_UDP
812
813#if defined(ETH_DEBUG_L1) || defined(RF24ETHERNET_DEBUG_DNS)
814 Serial.println(F("* DNS fail*"));
815#endif
816
817 return ret;
818}
819
820/*************************************************************/
821
823{
824#if USE_LWIP < 1
825 if (data && data->state)
826 {
827
828 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(millis()); Serial.println(F(" before stop(), with data")););
829
830 data->packets_in = 0;
831 data->dataCnt = 0;
832
833 if (data->state & UIP_CLIENT_REMOTECLOSED)
834 {
835 data->state = 0;
836 }
837 else
838 {
839 data->state |= UIP_CLIENT_CLOSE;
840 }
841
842 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("after stop()")););
843 }
844 else
845 {
846 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(millis()); Serial.println(F(" stop(), data: NULL")););
847 }
848
849 data = NULL;
850 RF24Ethernet.update();
851#else
852
853 _stop();
854
855#endif
856}
857
858/***************************************************************************************************/
859#if USE_LWIP > 0
860void RF24Client::_stop()
861{
862 tcp_pcb* pcb = myPcb;
863 myPcb = nullptr;
864
865 if (pcb != nullptr) {
866 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
867 if (Ethernet.useCoreLocking) {
868 ETHERNET_APPLY_LOCK();
869 }
870 #endif
871 if (pcb->state != CLOSED) {
872 tcp_arg(pcb, NULL);
873 tcp_recv(pcb, NULL);
874 tcp_sent(pcb, NULL);
875 tcp_err(pcb, NULL);
876
877 err_t err = tcp_close(pcb);
878 if (err != ERR_OK) {
879 tcp_abort(pcb);
880 }
881 }
882 #if defined RF24ETHERNET_CORE_REQUIRES_LOCKING
883 if (Ethernet.useCoreLocking) {
884 ETHERNET_REMOVE_LOCK();
885 }
886 #endif
887 }
888
889 gState[activeState]->connected = false;
890 gState[activeState]->finished = true;
891 dataSize[activeState] = 0;
892}
893#endif
894/*************************************************************/
895
896// the next function allows us to use the client returned by
897// EthernetServer::available() as the condition in an if-statement.
899{
900#if USE_LWIP < 1
901 return data && rhs.data && (data == rhs.data);
902#else
903 return dataSize[activeState] > 0 ? true : false;
904#endif
905}
906
907/*************************************************************/
908
909RF24Client::operator bool()
910{
911 Ethernet.update();
912#if USE_LWIP < 1
913 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in != 0);
914#else
915 return dataSize[activeState] > 0 ? true : false;
916#endif
917}
918
919/*************************************************************/
920
921size_t RF24Client::write(uint8_t c)
922{
923 return _write(data, &c, 1);
924}
925
926/*************************************************************/
927
928size_t RF24Client::write(const uint8_t* buf, size_t size)
929{
930 return _write(data, buf, size);
931}
932
933/*************************************************************/
934#if USE_LWIP < 1
935size_t RF24Client::_write(uip_userdata_t* u, const uint8_t* buf, size_t size)
936#else
937size_t RF24Client::_write(uint8_t* data, const uint8_t* buf, size_t size)
938
939#endif
940
941{
942
943#if USE_LWIP < 1
944 size_t total_written = 0;
945 size_t payloadSize = rf24_min(size, UIP_TCP_MSS);
946 uint32_t start = millis();
947
948test2:
949
950 Ethernet.update();
951
952 if (millis() - start > 5000)
953 {
954 if (u) {
955 u->hold = false;
956 }
957 return total_written;
958 }
959
960 if (u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)) && (u->state & UIP_CLIENT_CONNECTED))
961 {
962 if (u->out_pos + payloadSize > UIP_TCP_MSS || u->hold)
963 {
964 goto test2;
965 }
966
968 Serial.println();
969 Serial.print(millis());
970 Serial.print(F(" UIPClient.write: writePacket("));
971 Serial.print(u->packets_out);
972 Serial.print(F(") pos: "));
973 Serial.print(u->out_pos);
974 Serial.print(F(", buf["));
975 Serial.print(size - total_written);
976 Serial.print(F("]: '"));
977 Serial.write((uint8_t*)buf + total_written, payloadSize);
978 Serial.println(F("'")););
979
980 memcpy(u->myData + u->out_pos, buf + total_written, payloadSize);
981 u->packets_out = 1;
982 u->out_pos += payloadSize;
983 total_written += payloadSize;
984
985 if (total_written < size)
986 {
987 size_t remain = size - total_written;
988 payloadSize = rf24_min(remain, UIP_TCP_MSS);
989 goto test2;
990 }
991
992 u->hold = false;
993 return u->out_pos;
994 }
995
996 if (u) {
997 u->hold = false;
998 }
999 return 0;
1000#else
1001
1002 bool initialActiveState = activeState;
1003 size_t chunk = MAX_PAYLOAD_SIZE - 14; // 14 = Ethernet/link-layer header bytes reserved per frame
1004 size_t position = 0;
1005
1006 while (size > chunk) {
1007 if (myPcb == nullptr)
1008 return 0;
1009 gState[initialActiveState]->waiting_for_ack = true;
1010 err_t write_err = blocking_write(myPcb, gState[initialActiveState], reinterpret_cast<const char*>(&buf[position]), chunk);
1011 if (write_err != ERR_OK) {
1012 gState[initialActiveState]->result = write_err;
1013 gState[initialActiveState]->connected = false;
1014 _stop();
1015 return 0;
1016 }
1017 position += chunk;
1018 size -= chunk;
1019 Ethernet.update();
1020 }
1021
1022 if (myPcb == nullptr)
1023 return 0;
1024 gState[initialActiveState]->waiting_for_ack = true;
1025 err_t write_err = blocking_write(myPcb, gState[initialActiveState], reinterpret_cast<const char*>(&buf[position]), size);
1026
1027 if (write_err != ERR_OK) {
1028 gState[initialActiveState]->result = write_err;
1029 gState[initialActiveState]->connected = false;
1030 _stop();
1031 return 0;
1032 }
1033
1034 return position + size;
1035#endif
1036}
1037
1038/*************************************************************/
1039
1040void uip_log(char* msg)
1041{
1042 // Serial.println();
1043 // Serial.println("** UIP LOG **");
1044 // Serial.println(msg);
1045 if (msg)
1046 {
1047 };
1048}
1049
1050/*************************************************************/
1051#if USE_LWIP < 1
1052void serialip_appcall(void)
1053{
1054 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
1055
1056 /*******Connected**********/
1057 if (!u && uip_connected())
1058 {
1059 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient uip_connected")););
1060
1061 u = (uip_userdata_t*)EthernetClient::_allocateData();
1062
1063 if (u)
1064 {
1065 uip_conn->appstate = u;
1066 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(F("UIPClient allocated state: ")); Serial.println(u->state, BIN););
1067 }
1068 else
1069 {
1070 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("UIPClient allocation failed")););
1071 }
1072 }
1073
1074 #if UIP_CONNECTION_TIMEOUT > 0
1075 if (u && u->connectTimeout > 0) {
1076 if (millis() - u->connectTimer > u->connectTimeout) {
1077 u->state |= UIP_CLIENT_CLOSE;
1078 u->connectTimer = millis();
1079 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println("UIP Client close(timeout)"););
1080 }
1081 }
1082 #endif
1083
1084 /*******User Data RX**********/
1085 if (u)
1086 {
1087 if (uip_newdata())
1088 {
1089 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.print(F(" UIPClient uip_newdata, uip_len:")); Serial.println(uip_len););
1090 #if UIP_CONNECTION_TIMEOUT > 0
1091 u->connectTimer = millis();
1092 #endif
1093 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out = false)));
1094
1095 if (uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1096 {
1097 uip_stop();
1098 u->state &= ~UIP_CLIENT_RESTART;
1099 u->windowOpened = false;
1100 u->restartTime = millis();
1101
1102 uint16_t writePos = u->in_pos + u->dataCnt;
1103 uint16_t incomingLen = uip_datalen();
1104
1105 if (writePos <= OUTPUT_BUFFER_SIZE && incomingLen <= (OUTPUT_BUFFER_SIZE - writePos))
1106 {
1107 memcpy(&u->myData[writePos], uip_appdata, incomingLen);
1108 u->dataCnt += incomingLen;
1109 u->packets_in = 1;
1110 }
1111 else
1112 {
1114 Serial.println(F("UIPClient RX overflow, closing connection")););
1115 u->state |= UIP_CLIENT_CLOSE;
1116 }
1117 }
1118 goto finish;
1119 }
1120
1121 /*******Closed/Timed-out/Aborted**********/
1122 // If the connection has been closed, save received but unread data.
1123 if (uip_closed() || uip_timedout() || uip_aborted())
1124 {
1125 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient uip_closed")););
1126 // drop outgoing packets not sent yet:
1127 u->packets_out = 0;
1128
1129 if (u->packets_in)
1130 {
1131 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
1132 u->state |= UIP_CLIENT_REMOTECLOSED;
1133 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("UIPClient close 1")););
1134 }
1135 else
1136 {
1137 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("UIPClient close 2")););
1138 u->state = 0;
1139 }
1140
1141 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("after UIPClient uip_closed")););
1142 uip_conn->appstate = NULL;
1143 goto finish;
1144 }
1145
1146 /*******ACKED**********/
1147 if (uip_acked())
1148 {
1149 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient uip_acked")););
1150 u->state &= ~UIP_CLIENT_RESTART;
1151 u->hold = (u->out_pos = (u->windowOpened = (u->packets_out = false)));
1152 u->restartTime = millis();
1153 #if UIP_CONNECTION_TIMEOUT > 0
1154 u->connectTimer = millis();
1155 #endif
1156 }
1157
1158 /*******Polling**********/
1159 if (uip_poll() || uip_rexmit())
1160 {
1161 if (uip_rexmit()) {
1162 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.print(F("ReXmit, Len: ")););
1163 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(u->out_pos));
1164 uip_len = u->out_pos;
1165 uip_send(u->myData, u->out_pos);
1166 u->hold = true;
1167 goto finish;
1168 }
1169 // IF_RF24ETHERNET_DEBUG_CLIENT( Serial.println(); Serial.println(F("UIPClient uip_poll")); );
1170
1171 if (u->packets_out != 0 && !u->hold)
1172 {
1173 uip_len = u->out_pos;
1174 uip_send(u->myData, u->out_pos);
1175 u->hold = true;
1176 goto finish;
1177 }
1178
1179 // Restart mechanism to keep connections going
1180 // Only call this if the TCP window has already been re-opened, the connection is being polled, but no data
1181 // has been acked
1182 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1183 {
1184
1185 if (u->windowOpened == true && u->state & UIP_CLIENT_RESTART && millis() - u->restartTime > u->restartInterval)
1186 {
1187 u->restartTime = millis();
1188 #if defined RF24ETHERNET_DEBUG_CLIENT || defined ETH_DEBUG_L1
1189 Serial.println();
1190 Serial.print(millis());
1191 #if UIP_CONNECTION_TIMEOUT > 0
1192 Serial.print(F(" UIPClient Re-Open TCP Window, time remaining before abort: "));
1193 Serial.println(UIP_CONNECTION_TIMEOUT - (millis() - u->connectTimer));
1194 #endif
1195 #endif
1196 u->restartInterval += 500;
1197 u->restartInterval = rf24_min(u->restartInterval, 7000);
1198 uip_restart();
1199 }
1200 }
1201 }
1202
1203 /*******Close**********/
1204 if (u->state & UIP_CLIENT_CLOSE)
1205 {
1206 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(); Serial.print(millis()); Serial.println(F(" UIPClient state UIP_CLIENT_CLOSE")););
1207
1208 if (u->packets_out == 0)
1209 {
1210 u->state = 0;
1211 uip_conn->appstate = NULL;
1212 uip_close();
1213 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("no blocks out -> free userdata")););
1214 }
1215 else
1216 {
1217 uip_stop();
1218 IF_RF24ETHERNET_DEBUG_CLIENT(Serial.println(F("blocks outstanding transfer -> uip_stop()")););
1219 }
1220 }
1221finish:;
1222
1223 if (u->state & UIP_CLIENT_RESTART && !u->windowOpened)
1224 {
1225 if (!(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1226 {
1227 uip_restart();
1228 #if defined ETH_DEBUG_L1
1229 Serial.println();
1230 Serial.print(millis());
1231 Serial.println(F(" UIPClient Re-Open TCP Window"));
1232 #endif
1233 u->windowOpened = true;
1234 u->restartInterval = UIP_WINDOW_REOPEN_DELAY; //.75 seconds
1235 u->restartTime = millis();
1236 }
1237 }
1238 }
1239}
1240#endif
1241/*******************************************************/
1242#if USE_LWIP < 1
1243uip_userdata_t* RF24Client::_allocateData()
1244{
1245 for (uint8_t sock = 0; sock < UIP_CONNS; sock++)
1246 {
1247 uip_userdata_t* data = &RF24Client::all_data[sock];
1248 if (!data->state)
1249 {
1250 data->state = sock | UIP_CLIENT_CONNECTED;
1251 data->packets_in = 0;
1252 data->packets_out = 0;
1253 data->dataCnt = 0;
1254 data->in_pos = 0;
1255 data->out_pos = 0;
1256 data->hold = 0;
1257 data->restartTime = millis();
1258 data->restartInterval = 5000;
1259 #if (UIP_CONNECTION_TIMEOUT > 0)
1260 data->connectTimer = millis();
1261 data->connectTimeout = UIP_CONNECTION_TIMEOUT;
1262 #endif
1263 return data;
1264 }
1265 }
1266 return NULL;
1267}
1268#endif
1269
1270int RF24Client::waitAvailable(uint32_t timeout)
1271{
1272 uint32_t start = millis();
1273 while (available() < 1)
1274 {
1275 if (millis() - start > timeout)
1276 {
1277 return 0;
1278 }
1279 RF24Ethernet.update();
1280 }
1281 return available();
1282}
1283
1284/*************************************************************/
1285
1287{
1288 RF24Ethernet.update();
1289#if USE_LWIP < 1
1290 if (*this)
1291 {
1292 return _available(data);
1293 }
1294#else
1295 return _available(data);
1296#endif
1297 return 0;
1298}
1299
1300/*************************************************************/
1301#if USE_LWIP < 1
1302int RF24Client::_available(uip_userdata_t* u)
1303#else
1304int RF24Client::_available(uint8_t* data)
1305#endif
1306{
1307#if USE_LWIP < 1
1308 if (u->packets_in)
1309 {
1310 return u->dataCnt;
1311 }
1312#else
1313 return dataSize[activeState];
1314#endif
1315 return 0;
1316}
1317
1318/*************************************************************/
1319
1320int RF24Client::read(uint8_t* buf, size_t size)
1321{
1322#if USE_LWIP < 1
1323 if (*this)
1324 {
1325 if (!data->packets_in)
1326 {
1327 return -1;
1328 }
1329 if (data->in_pos > OUTPUT_BUFFER_SIZE || data->dataCnt > OUTPUT_BUFFER_SIZE || (data->in_pos + data->dataCnt) > OUTPUT_BUFFER_SIZE)
1330 {
1331 data->state |= UIP_CLIENT_CLOSE;
1332 data->in_pos = 0;
1333 data->dataCnt = 0;
1334 return -1;
1335 }
1336 size = rf24_min(data->dataCnt, size);
1337 memcpy(buf, &data->myData[data->in_pos], size);
1338 data->dataCnt -= size;
1339
1340 data->in_pos += size;
1341
1342 if (!data->dataCnt)
1343 {
1344 data->packets_in = 0;
1345 data->in_pos = 0;
1346
1347 if (uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS]) && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED)))
1348 {
1349 data->state |= UIP_CLIENT_RESTART;
1350 data->restartTime = 0;
1351
1352 IF_ETH_DEBUG_L2(Serial.print(F("UIPClient set restart ")); Serial.println(data->state & UIP_CLIENT_SOCKETS); Serial.println(F("**")); Serial.println(data->state, BIN); Serial.println(F("**")); Serial.println(UIP_CLIENT_SOCKETS, BIN); Serial.println(F("**")););
1353 }
1354 else
1355 {
1356 IF_ETH_DEBUG_L2(Serial.print(F("UIPClient stop?????? ")); Serial.println(data->state & UIP_CLIENT_SOCKETS); Serial.println(F("**")); Serial.println(data->state, BIN); Serial.println(F("**")); Serial.println(UIP_CLIENT_SOCKETS, BIN); Serial.println(F("**")););
1357 }
1358
1359 if (data->packets_in == 0)
1360 {
1361 if (data->state & UIP_CLIENT_REMOTECLOSED)
1362 {
1363 data->state = 0;
1364 data = NULL;
1365 }
1366 }
1367 }
1368 return size;
1369 }
1370
1371 return -1;
1372#else
1373
1374 if (available()) {
1375
1376 if (size >= dataSize[activeState]) {
1377 memcpy(&buf[0], &incomingData[activeState][0], dataSize[activeState]);
1378 memmove(&incomingData[activeState][0], &incomingData[activeState][dataSize[activeState]], dataSize[activeState]);
1379 size = dataSize[activeState];
1380 dataSize[activeState] = 0;
1381 return size;
1382 }
1383 else {
1384 memcpy(&buf[0], &incomingData[activeState][0], size);
1385 memmove(&incomingData[activeState][0], &incomingData[activeState][size], dataSize[activeState] - size);
1386 dataSize[activeState] -= size;
1387 return size;
1388 }
1389 }
1390 return -1;
1391#endif
1392}
1393
1394/*************************************************************/
1395
1397{
1398 uint8_t c;
1399 if (read(&c, 1) < 0)
1400 return -1;
1401 return c;
1402}
1403
1404/*************************************************************/
1405
1407{
1408 if (available())
1409 {
1410#if USE_LWIP < 1
1411 return data->myData[data->in_pos];
1412#else
1413 return incomingData[activeState][0];
1414#endif
1415 }
1416 return -1;
1417}
1418
1419/*************************************************************/
1420
1422{
1423#if USE_LWIP < 1
1424 if (*this)
1425 {
1426 #if USE_LWIP < 1
1427 data->packets_in = 0;
1428 data->dataCnt = 0;
1429 #else
1430 data = 0;
1431 #endif
1432 }
1433#else
1434 dataSize[activeState] = 0;
1435#endif
1436}
void uip_log(char *msg)
volatile err_t result
Definition RF24Client.h:8
#define INCOMING_DATA_SIZE
Definition RF24Client.h:78
volatile bool finished
Definition RF24Client.h:0
RF24EthernetClass RF24Ethernet
void begin(const IPAddress &aDNSServer)
Definition Dns.cpp:45
int getHostByName(const char *aHostname, IPAddress &aResult)
Definition Dns.cpp:110
virtual bool operator==(const EthernetClient &)
size_t write(uint8_t)
int connect(IPAddress ip, uint16_t port)
static void error_callback(void *arg, err_t err)
static err_t srecv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
int waitAvailable(uint32_t timeout=750)
static ConnectState * gState[2]
Definition RF24Client.h:218
static bool activeState
Definition RF24Client.h:233
static err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
static err_t sent_callback(void *arg, struct tcp_pcb *tpcb, uint16_t len)
uint8_t connected()
#define Ethernet
#define IF_ETH_DEBUG_L2(x)
#define IF_RF24ETHERNET_DEBUG_CLIENT(x)
#define IF_ETH_DEBUG_L1(x)
#define UIP_CONNECTION_TIMEOUT
Optional: Uncomment to disable
Definition uip-conf.h:90
#define OUTPUT_BUFFER_SIZE
Definition uip-conf.h:153
#define UIP_WINDOW_REOPEN_DELAY
Optional: Used with UIP_CONNECTION_TIMEOUT
Definition uip-conf.h:167
volatile bool stateActiveID
Definition RF24Client.h:205
uint16_t u16_t
16 bit datatype
Definition uip-conf.h:245
void serialip_appcall(void)