Skip to content

Commit 1fd2497

Browse files
committed
Add TimedAttempt
1 parent 0d100c3 commit 1fd2497

File tree

5 files changed

+299
-0
lines changed

5 files changed

+299
-0
lines changed

extras/test/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ set(TEST_SRCS
2727
src/crc16/test_crc16.cpp
2828
src/sha256/test_sha256.cpp
2929
src/hex/test_hex.cpp
30+
src/time/test_TimedAttempt.cpp
3031
)
3132

3233
set(TEST_DUT_SRCS
3334
../../src/crc/crc32.cpp
3435
../../src/crc/crc16.cpp
3536
../../src/sha256/sha2.c
3637
../../src/hex/chex.h
38+
../../src/time/TimedAttempt.cpp
3739
)
3840

3941
##########################################################################
+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
This file is part of the Arduino_CloudUtils library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
#include <catch2/catch_test_macros.hpp>
12+
13+
#include <time/TimedAttempt.h>
14+
15+
SCENARIO("Test broker connection retries") {
16+
TimedAttempt _connection_attempt(0,0);
17+
18+
_connection_attempt.begin(1000UL, 32000UL);
19+
20+
/* 100000 retries are more or less 37 days without connection */
21+
while(_connection_attempt.getRetryCount() < 100000) {
22+
_connection_attempt.retry();
23+
24+
switch(_connection_attempt.getRetryCount()) {
25+
case 1:
26+
REQUIRE(_connection_attempt.getWaitTime() == 2000);
27+
break;
28+
case 2:
29+
REQUIRE(_connection_attempt.getWaitTime() == 4000);
30+
break;
31+
case 3:
32+
REQUIRE(_connection_attempt.getWaitTime() == 8000);
33+
break;
34+
case 4:
35+
REQUIRE(_connection_attempt.getWaitTime() == 16000);
36+
break;
37+
default:
38+
REQUIRE(_connection_attempt.getWaitTime() == 32000);
39+
break;
40+
}
41+
}
42+
}
43+
44+
SCENARIO("Test thing id request with no answer from the cloud") {
45+
TimedAttempt _attachAttempt(0,0);
46+
47+
_attachAttempt.begin(2000UL, 32000UL);
48+
49+
/* 100000 retries are more or less 37 days of requests */
50+
while(_attachAttempt.getRetryCount() < 100000) {
51+
_attachAttempt.retry();
52+
53+
switch(_attachAttempt.getRetryCount()) {
54+
case 1:
55+
REQUIRE(_attachAttempt.getWaitTime() == 4000);
56+
break;
57+
case 2:
58+
REQUIRE(_attachAttempt.getWaitTime() == 8000);
59+
break;
60+
case 3:
61+
REQUIRE(_attachAttempt.getWaitTime() == 16000);
62+
break;
63+
default:
64+
REQUIRE(_attachAttempt.getWaitTime() == 32000);
65+
break;
66+
}
67+
}
68+
}
69+
70+
SCENARIO("Test thing id request of a detached device") {
71+
TimedAttempt _attachAttempt(0,0);
72+
73+
_attachAttempt.begin(2000UL, 32000UL);
74+
75+
while(_attachAttempt.getRetryCount() < 100000) {
76+
_attachAttempt.retry();
77+
78+
switch(_attachAttempt.getRetryCount()) {
79+
case 1:
80+
REQUIRE(_attachAttempt.getWaitTime() == 4000);
81+
_attachAttempt.reconfigure(2000UL * 10UL, 32000UL * 40UL);
82+
break;
83+
case 2:
84+
REQUIRE(_attachAttempt.getWaitTime() == 80000);
85+
break;
86+
case 3:
87+
REQUIRE(_attachAttempt.getWaitTime() == 160000);
88+
break;
89+
case 4:
90+
REQUIRE(_attachAttempt.getWaitTime() == 320000);
91+
break;
92+
case 5:
93+
REQUIRE(_attachAttempt.getWaitTime() == 640000);
94+
break;
95+
default:
96+
REQUIRE(_attachAttempt.getWaitTime() == 1280000);
97+
break;
98+
}
99+
}
100+
}
101+
102+
SCENARIO("Test last value request") {
103+
TimedAttempt _syncAttempt(0,0);
104+
105+
_syncAttempt.begin(30000UL);
106+
107+
/* 100000 retries are more or less 37 days of requests */
108+
while(_syncAttempt.getRetryCount() < 100000) {
109+
_syncAttempt.retry();
110+
111+
switch(_syncAttempt.getRetryCount()) {
112+
default:
113+
REQUIRE(_syncAttempt.getWaitTime() == 30000);
114+
break;
115+
}
116+
}
117+
}
118+
119+
SCENARIO("Test isExpired() and isRetry()") {
120+
TimedAttempt attempt(0,0);
121+
122+
attempt.begin(1000UL, 32000UL);
123+
124+
/* Initial condition */
125+
set_millis(0);
126+
REQUIRE(attempt.isExpired() == false);
127+
REQUIRE(attempt.isRetry() == false);
128+
129+
/* Normal retry 2000ms */
130+
attempt.retry();
131+
REQUIRE(attempt.isRetry() == true);
132+
set_millis(1000);
133+
REQUIRE(attempt.isExpired() == false);
134+
set_millis(1999);
135+
REQUIRE(attempt.isExpired() == false);
136+
set_millis(2000);
137+
REQUIRE(attempt.isExpired() == false);
138+
set_millis(2001);
139+
REQUIRE(attempt.isExpired() == true);
140+
141+
/* Retry with rollover 4000ms */
142+
set_millis(ULONG_MAX - 1999);
143+
attempt.retry();
144+
REQUIRE(attempt.isRetry() == true);
145+
set_millis(0);
146+
REQUIRE(attempt.isExpired() == false);
147+
set_millis(1999);
148+
REQUIRE(attempt.isExpired() == false);
149+
set_millis(2000);
150+
REQUIRE(attempt.isExpired() == false);
151+
set_millis(2001);
152+
REQUIRE(attempt.isExpired() == true);
153+
154+
/* Normal retry 8000ms */
155+
set_millis(4000);
156+
attempt.retry();
157+
REQUIRE(attempt.isRetry() == true);
158+
set_millis(4000);
159+
REQUIRE(attempt.isExpired() == false);
160+
set_millis(11999);
161+
REQUIRE(attempt.isExpired() == false);
162+
set_millis(12000);
163+
REQUIRE(attempt.isExpired() == false);
164+
set_millis(12001);
165+
REQUIRE(attempt.isExpired() == true);
166+
167+
attempt.reset();
168+
REQUIRE(attempt.isRetry() == false);
169+
}

src/Arduino_TimedAttempt.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
This file is part of the Arduino_CloudUtils library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
#pragma once
11+
12+
#include "./TimedAttempt.h"

src/time/TimedAttempt.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
This file is part of the Arduino_CloudUtils library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
12+
#include <Arduino.h>
13+
#include "TimedAttempt.h"
14+
15+
namespace arduino { namespace time {
16+
17+
TimedAttempt::TimedAttempt(unsigned long minDelay, unsigned long maxDelay)
18+
: _minDelay(minDelay)
19+
, _maxDelay(maxDelay) {
20+
}
21+
22+
void TimedAttempt::begin(unsigned long delay) {
23+
_retryCount = 0;
24+
_retryDelay = 0;
25+
_retryTick = 0;
26+
_minDelay = delay;
27+
_maxDelay = delay;
28+
}
29+
30+
void TimedAttempt::begin(unsigned long minDelay, unsigned long maxDelay) {
31+
_retryCount = 0;
32+
_retryDelay = 0;
33+
_retryTick = 0;
34+
_minDelay = minDelay;
35+
_maxDelay = maxDelay;
36+
}
37+
38+
unsigned long TimedAttempt::reconfigure(unsigned long minDelay, unsigned long maxDelay) {
39+
_minDelay = minDelay;
40+
_maxDelay = maxDelay;
41+
return reload();
42+
}
43+
44+
unsigned long TimedAttempt::retry() {
45+
_retryCount++;
46+
return reload();
47+
}
48+
49+
unsigned long TimedAttempt::reload() {
50+
unsigned long shift = _retryCount > 31 ? 31 : _retryCount;
51+
unsigned long delay = (1UL << shift) * _minDelay;
52+
_retryDelay = min(delay, _maxDelay);
53+
_retryTick = millis();
54+
return _retryDelay;
55+
}
56+
57+
void TimedAttempt::reset() {
58+
_retryCount = 0;
59+
}
60+
61+
bool TimedAttempt::isRetry() {
62+
return _retryCount > 0;
63+
}
64+
65+
bool TimedAttempt::isExpired() {
66+
return millis() - _retryTick > _retryDelay;
67+
}
68+
69+
unsigned int TimedAttempt::getRetryCount() {
70+
return _retryCount;
71+
}
72+
73+
unsigned int TimedAttempt::getWaitTime() {
74+
return _retryDelay;
75+
}
76+
77+
}} // arduino::time

src/time/TimedAttempt.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
This file is part of the Arduino_CloudUtils library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
11+
#pragma once
12+
13+
namespace arduino { namespace time {
14+
15+
class TimedAttempt {
16+
17+
public:
18+
TimedAttempt(unsigned long minDelay, unsigned long maxDelay);
19+
20+
void begin(unsigned long delay);
21+
void begin(unsigned long minDelay, unsigned long maxDelay);
22+
unsigned long reconfigure(unsigned long minDelay, unsigned long maxDelay);
23+
unsigned long retry();
24+
unsigned long reload();
25+
void reset();
26+
bool isRetry();
27+
bool isExpired();
28+
unsigned int getRetryCount();
29+
unsigned int getWaitTime();
30+
31+
private:
32+
unsigned long _minDelay;
33+
unsigned long _maxDelay;
34+
unsigned long _retryTick;
35+
unsigned long _retryDelay;
36+
unsigned int _retryCount;
37+
};
38+
39+
}} // arduino::time

0 commit comments

Comments
 (0)