src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
44 / 44
100.0%
Branches:
59 / 60
98.3%
Functions:
17 / 17
100.0%

Utils.h
Line Branch Exec Source
1 #ifndef utils_h
2 #define utils_h
3 #include <Arduino.h>
4 #include <atomic>
5
6
7 #define DEBUG_SOMFY Serial
8
9
10
11
12 3 [[maybe_unused]] static void SETCHARPROP(char *prop, const char *value, size_t size) {strncpy(prop, value, size); prop[size - 1] = '\0';}
13 /*
14 namespace util {
15 // Createa a custom to_string function. C++ can be annoying
16 // with all the trailing 0s on number formats.
17 template <typename T> std::string to_string(const T& t) {
18 std::string str{std::to_string (t)};
19 int offset{1};
20 if (str.find_last_not_of('0') == str.find('.')) {
21 offset = 0;
22 }
23 str.erase ( str.find_last_not_of('0') + 1, std::string::npos );
24 str.erase ( str.find_last_not_of('.') + 1, std::string::npos );
25 return str;
26 }
27 }
28 */
29
30 4 static void _ltrim(char *str) {
31 4 int s = 0, j, k = 0;
32 4 int e = strlen(str);
33
12/12
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 2 times.
13 while(s < e && (str[s] == ' ' || str[s] == '\n' || str[s] == '\r' || str[s] == '\t' || str[s] == '"')) s++;
34
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if(s > 0) {
35
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 for(j = s; j < e; j++) {
36 14 str[k] = str[j];
37 14 k++;
38 }
39 2 str[k] = '\0';
40 }
41 //if(s > 0) strcpy(str, &str[s]);
42 4 }
43 619 static void _rtrim(char *str) {
44 619 int e = strlen(str) - 1;
45
11/12
✓ Branch 0 taken 912 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 298 times.
✓ Branch 3 taken 614 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 613 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 612 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 612 times.
✓ Branch 10 taken 1 time.
✓ Branch 11 taken 611 times.
920 while(e >= 0 && (str[e] == ' ' || str[e] == '\n' || str[e] == '\r' || str[e] == '\t' || str[e] == '"')) {str[e] = '\0'; e--;}
46 619 }
47 4 [[maybe_unused]] static void _trim(char *str) { _ltrim(str); _rtrim(str); }
48 struct rebootDelay_t {
49 bool reboot = false;
50 int rebootTime = 0;
51 bool closed = false;
52 };
53 12 [[maybe_unused]] static bool toBoolean(const char *str, bool def) {
54
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
12 if(!str) return def;
55
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if(strlen(str) == 0) return def;
56
6/6
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 5 times.
8 else if(str[0] == 't' || str[0] == 'T' || str[0] == '1') return true;
57
6/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 2 times.
5 else if(str[0] == 'f' || str[0] == 'F' || str[0] == '0') return false;
58 2 return def;
59 }
60 // Whether a wifi broadcast is worth sending: always on a channel change,
61 // otherwise only for an RSSI change of at least minDelta dBm.
62 bool rssiNeedsEmit(int rssi, int lastRssi, int channel, int lastChannel, int minDelta);
63 // What the last wifi broadcast told every client. A client that connects gets
64 // the signal in its sync, which tells the others nothing, so it isn't moved.
65 struct RssiBroadcast {
66 int rssi = 0;
67 int channel = 0;
68 bool due(int rssi, int channel, int minDelta) const;
69 void sent(int rssi, int channel);
70 };
71 // Whether an AP a scan found for our SSID is worth connecting to. While
72 // connected it has to be at least minGain dBm stronger than the current AP so
73 // a small swing doesn't make the device hop between APs.
74 bool worthRoaming(bool connected, int currentRssi, int apRssi, int minGain);
75 // Whether the calling task may send socket events. They are all formatted
76 // into one shared buffer, so only loop()'s task may. owner is that task, or
77 // null before ProtoSocket::begin() has recorded it (setup() runs there too).
78 bool emitAllowed(const void *current, const void *owner);
79 // A short name for a wifi_auth_mode_t value, for the logs. The values up to
80 // WAPI are the same in ESP-IDF 4.4 and 5.x.
81 const char *wifiAuthModeName(uint8_t authMode);
82 // Whether a firmware the bootloader is holding for verification after an
83 // update has proven itself: it has run for minUptimeMs and the network is
84 // up. Until then a reset rolls back to the previous firmware.
85 bool otaProven(bool networkUp, unsigned long uptimeMs, unsigned long minUptimeMs);
86 // A release asset's name: "SomfyController.<kind>.esp32<chipModel>.bin", kind
87 // "ino" for the firmware or "littlefs" for the web UI image, chipModel as in
88 // ConfigSettings ("" for the ESP32, "s3", "c3", "c5", "c6", "p4", "p4es").
89 void releaseAssetName(char *buf, size_t size, const char *kind, const char *chipModel);
90 // A coredump backtrace as " 0x%08x" per frame. bt holds maxFrames entries and
91 // depth is how many the dump claims are valid.
92 void formatBacktrace(char *buf, size_t size, const uint32_t *bt, size_t maxFrames, uint32_t depth);
93 // How well loop() keeps up: the passes it made per second and its longest
94 // pass, over the window since the last memory broadcast. Only the loop
95 // task calls record(), rate(), maxUs() and publish(). publish() closes the
96 // window and keeps its figures for the memory event and a client's sync.
97 class LoopStats {
98 uint32_t _passes = 0;
99 uint32_t _maxUs = 0;
100 uint32_t _startMs = 0;
101 std::atomic<uint32_t> _publishedRate{0};
102 std::atomic<uint32_t> _publishedMaxUs{0};
103 public:
104 void record(uint32_t passUs);
105 // Passes per second since the window started, 0 for an empty window.
106 uint32_t rate(uint32_t nowMs) const;
107 5 uint32_t maxUs() const { return _maxUs; }
108 void publish(uint32_t nowMs);
109 6 uint32_t publishedRate() const { return _publishedRate.load(std::memory_order_relaxed); }
110 4 uint32_t publishedMaxUs() const { return _publishedMaxUs.load(std::memory_order_relaxed); }
111 };
112
113 class Timestamp {
114 char _timeBuffer[128];
115 public:
116 time_t getUTC();
117 time_t getUTC(time_t epoch);
118 char * getISOTime();
119 char * getISOTime(time_t epoch);
120 char * formatISO(struct tm *dt, int tz);
121 int tzOffset();
122 static time_t parseUTCTime(const char *buff);
123 static time_t mkUTCTime(struct tm *dt);
124 static int calcTZOffset(time_t *dt);
125 static time_t now();
126 static unsigned long epoch();
127 };
128 // Sort an array
129 template<typename AnyType> void sortArray(AnyType array[], size_t sizeOfArray);
130 // Sort in reverse
131 template<typename AnyType> void sortArrayReverse(AnyType array[], size_t sizeOfArray);
132 // Sort an array with custom comparison function
133 template<typename AnyType> void sortArray(AnyType array[], size_t sizeOfArray, bool (*largerThan)(AnyType, AnyType));
134 // Sort in reverse with custom comparison function
135 template<typename AnyType> void sortArrayReverse(AnyType array[], size_t sizeOfArray, bool (*largerThan)(AnyType, AnyType));
136 namespace ArduinoSort {
137 25 template<typename AnyType> bool builtinLargerThan(AnyType first, AnyType second) { return first > second; }
138 //template<> bool builtinLargerThan(char* first, char* second) { return strcmp(first, second) > 0; }
139
4/4
void ArduinoSort::insertionSort<int>(int*, unsigned long, bool, bool (*)(int, int)):
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 6 times.
void ArduinoSort::insertionSort<unsigned char>(unsigned char*, unsigned long, bool, bool (*)(unsigned char, unsigned char)):
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
25 template<typename AnyType> void insertionSort(AnyType array[], size_t sizeOfArray, bool reverse, bool (*largerThan)(AnyType, AnyType)) { for (size_t i = 1; i < sizeOfArray; i++) {
140
12/12
void ArduinoSort::insertionSort<int>(int*, unsigned long, bool, bool (*)(int, int)):
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 9 times.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 14 times.
void ArduinoSort::insertionSort<unsigned char>(unsigned char*, unsigned long, bool, bool (*)(unsigned char, unsigned char)):
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 4 times.
43 for (size_t j = i; j > 0 && (largerThan(array[j-1], array[j]) != reverse); j--) {
141 25 AnyType tmp = array[j-1];
142 25 array[j-1] = array[j];
143 25 array[j] = tmp;
144 }
145 }
146 7 }
147 }
148 4 template<typename AnyType> void sortArray(AnyType array[], size_t sizeOfArray) { ArduinoSort::insertionSort(array, sizeOfArray, false, ArduinoSort::builtinLargerThan); }
149 1 template<typename AnyType> void sortArrayReverse(AnyType array[], size_t sizeOfArray) { ArduinoSort::insertionSort(array, sizeOfArray, true, ArduinoSort::builtinLargerThan); }
150 1 template<typename AnyType> void sortArray(AnyType array[], size_t sizeOfArray, bool (*largerThan)(AnyType, AnyType)) { ArduinoSort::insertionSort(array, sizeOfArray, false, largerThan); }
151 1 template<typename AnyType> void sortArrayReverse(AnyType array[], size_t sizeOfArray, bool (*largerThan)(AnyType, AnyType)) { ArduinoSort::insertionSort(array, sizeOfArray, true, largerThan); }
152 #endif
153