GCC Code Coverage Report


Directory: ./
File: firmware/controllers/sensors/core/sensor.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 79.4% 108 0 136
Functions: 86.7% 26 0 30
Branches: 67.7% 42 0 62
Decisions: 61.9% 26 - 42

Line Branch Decision Exec Source
1 #include "pch.h"
2 #include "auto_generated_sensor.h"
3
4 // This struct represents one sensor in the registry.
5 // It stores whether the sensor should use a mock value,
6 // the value to use, and if not a pointer to the sensor that
7 // can provide a real value.
8 class SensorRegistryEntry {
9 public:
10 219 const Sensor* getSensor() {
11 219 return m_sensor;
12 }
13
14 104 void setInvalidMockValue() {
15 104 m_useMock = true;
16 104 m_valid = false;
17 104 }
18
19 2760 void setMockValue(float value, bool mockRedundant) {
20 2760 m_mockValue = value;
21 2760 m_useMock = true;
22 2760 m_valid = true;
23 2760 m_mockRedundant = mockRedundant;
24 2760 }
25
26 63245 void resetMock() {
27 63245 m_useMock = false;
28 63245 m_mockValue = 0.0f;
29 63245 }
30
31 61272 void reset() {
32 61272 m_sensor = nullptr;
33 61272 resetMock();
34 61272 }
35
36 850 bool Register(Sensor* sensor) {
37 // If there's somebody already here - a consumer tried to double-register a sensor
38
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 843 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 6 times.
2/2
✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 849 times.
850 if (m_sensor && m_sensor != sensor) {
39 // This sensor has already been registered. Don't re-register it.
40 1 firmwareError(ObdCode::CUSTOM_OBD_26, "Duplicate registration for sensor \"%s\"", sensor->getSensorName());
41 return false;
42 } else {
43 // Put the sensor in the registry
44 849 m_sensor = sensor;
45 849 return true;
46 }
47 }
48
49 689 void unregister() {
50 689 m_sensor = nullptr;
51 689 }
52
53 35693685 SensorResult get() const {
54 // Check if mock
55
2/2
✓ Branch 0 taken 1068881 times.
✓ Branch 1 taken 34624804 times.
2/2
✓ Decision 'true' taken 1068881 times.
✓ Decision 'false' taken 34624804 times.
35693685 if (m_useMock) {
56
2/2
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 1068575 times.
2/2
✓ Decision 'true' taken 306 times.
✓ Decision 'false' taken 1068575 times.
1068881 if (!m_valid) {
57 306 return unexpected;
58 }
59 1068575 return m_mockValue;
60 }
61
62 // Get the sensor out of the entry
63 34624804 const Sensor *s = m_sensor;
64
2/2
✓ Branch 0 taken 619464 times.
✓ Branch 1 taken 34005340 times.
2/2
✓ Decision 'true' taken 619464 times.
✓ Decision 'false' taken 34005340 times.
34624804 if (s) {
65 // If this sensor says it doesn't exist, return unexpected
66
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 619464 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 619464 times.
619464 if (!s->hasSensor()) {
67 return UnexpectedCode::Configuration;
68 }
69
70 // If we found the sensor, ask it for a result.
71 619464 return s->get();
72 }
73
74 // We've exhausted all valid ways to return something - sensor not found.
75 34005340 return UnexpectedCode::Configuration;
76 }
77
78 void showInfo(const char* sensorName) const {
79 if (m_useMock) {
80 efiPrintf("Sensor \"%s\" mocked with value %.2f", sensorName, m_mockValue);
81 } else {
82 const auto sensor = m_sensor;
83
84 if (sensor) {
85 sensor->showInfo(sensorName);
86 } else {
87 efiPrintf("Sensor \"%s\" is not configured.", sensorName);
88 }
89 }
90 }
91
92 2626172 bool hasSensor() const {
93
6/6
✓ Branch 0 taken 2625892 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 236 times.
✓ Branch 3 taken 2625656 times.
✓ Branch 5 taken 235 times.
✓ Branch 6 taken 1 time.
2626172 return m_useMock || (m_sensor && m_sensor->hasSensor());
94 }
95
96 14119760 float getRaw() const {
97 14119760 const auto sensor = m_sensor;
98
99
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14119758 times.
2/2
✓ Decision 'true' taken 2 times.
✓ Decision 'false' taken 14119758 times.
14119760 if (sensor) {
100 2 return sensor->getRaw();
101 }
102
103 // We've exhausted all valid ways to return something - sensor not found.
104 14119758 return 0;
105 }
106
107 236 bool isRedundant() const {
108 236 const auto sensor = m_sensor;
109
110
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 27 times.
2/2
✓ Decision 'true' taken 209 times.
✓ Decision 'false' taken 27 times.
236 if (sensor) {
111 209 return sensor->isRedundant();
112 }
113
114
1/2
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 27 times.
✗ Decision 'false' not taken.
27 if (m_useMock) {
115 27 return m_mockRedundant;
116 }
117
118 return false;
119 }
120
121 private:
122 bool m_useMock = false;
123 bool m_valid = false;
124 bool m_mockRedundant = false;
125 float m_mockValue;
126 Sensor* m_sensor = nullptr;
127 };
128
129 static SensorRegistryEntry s_sensorRegistry[static_cast<size_t>(SensorType::PlaceholderLast)] = {};
130
131 850 bool Sensor::Register() {
132 850 return s_sensorRegistry[getIndex()].Register(this);
133 }
134
135 689 void Sensor::unregister() {
136 689 s_sensorRegistry[getIndex()].unregister();
137 689 }
138
139 666 /*static*/ void Sensor::resetRegistry() {
140 // Clear all entries
141
2/2
✓ Branch 1 taken 61272 times.
✓ Branch 2 taken 666 times.
2/2
✓ Decision 'true' taken 61272 times.
✓ Decision 'false' taken 666 times.
61938 for (size_t i = 0; i < efi::size(s_sensorRegistry); i++) {
142 61272 auto &entry = s_sensorRegistry[i];
143
144 61272 entry.reset();
145 }
146 666 }
147
148 52442977 /*static*/ SensorRegistryEntry *Sensor::getEntryForType(SensorType type) {
149 52442977 size_t index = getIndex(type);
150 // Check that we didn't get garbage
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 52442977 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 52442977 times.
52442977 if (index >= efi::size(s_sensorRegistry)) {
152 return nullptr;
153 }
154
155 52442977 return &s_sensorRegistry[index];
156 }
157
158 219 /*static*/ const Sensor *Sensor::getSensorOfType(SensorType type) {
159 219 auto entry = getEntryForType(type);
160
1/2
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
219 return entry ? entry->getSensor() : nullptr;
161 }
162
163 /**
164 * @returns NotNull: sensor result or UnexpectedCode::Configuration if sensor is not registered
165 */
166 35693685 /*static*/ SensorResult Sensor::get(SensorType type) {
167 35693685 const auto entry = getEntryForType(type);
168
169 // Check if this is a valid sensor entry
170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35693685 times.
1/2
✗ Decision 'true' not taken.
✓ Decision 'false' taken 35693685 times.
35693685 if (!entry) {
171 return UnexpectedCode::Configuration;
172 }
173
174 35693685 return entry->get();
175 }
176
177 14119760 /*static*/ float Sensor::getRaw(SensorType type) {
178 14119760 const auto entry = getEntryForType(type);
179
180
1/2
✓ Branch 0 taken 14119760 times.
✗ Branch 1 not taken.
14119760 return entry ? entry->getRaw() : 0;
181 }
182
183 236 /*static*/ bool Sensor::isRedundant(SensorType type) {
184 236 const auto entry = getEntryForType(type);
185
186
3/4
✓ Branch 0 taken 236 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 234 times.
✓ Branch 4 taken 2 times.
236 return entry ? entry->isRedundant() : false;
187 }
188
189 2626172 /*static*/ bool Sensor::hasSensor(SensorType type) {
190 2626172 const auto entry = getEntryForType(type);
191
192
3/4
✓ Branch 0 taken 2626172 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 515 times.
✓ Branch 4 taken 2625657 times.
2626172 return entry ? entry->hasSensor() : false;
193 }
194
195 104 void Sensor::setInvalidMockValue(SensorType type) {
196 104 auto entry = getEntryForType(type);
197
198
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 104 times.
✗ Decision 'false' not taken.
104 if (entry) {
199 104 entry->setInvalidMockValue();
200 }
201 104 }
202
203 2760 /*static*/ void Sensor::setMockValue(SensorType type, float value, bool mockRedundant) {
204 2760 auto entry = getEntryForType(type);
205
206
1/2
✓ Branch 0 taken 2760 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 2760 times.
✗ Decision 'false' not taken.
2760 if (entry) {
207 2760 entry->setMockValue(value, mockRedundant);
208 }
209 2760 }
210
211 41 /*static*/ void Sensor::resetMockValue(SensorType type) {
212 41 auto entry = getEntryForType(type);
213
214
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
1/2
✓ Decision 'true' taken 41 times.
✗ Decision 'false' not taken.
41 if (entry) {
215 41 entry->resetMock();
216 }
217 41 }
218
219 21 /*static*/ void Sensor::resetAllMocks() {
220 // Reset all mocks
221
2/2
✓ Branch 1 taken 1932 times.
✓ Branch 2 taken 21 times.
2/2
✓ Decision 'true' taken 1932 times.
✓ Decision 'false' taken 21 times.
1953 for (size_t i = 0; i < efi::size(s_sensorRegistry); i++) {
222 1932 s_sensorRegistry[i].resetMock();
223 }
224 21 }
225
226 122 /*static*/ const char* Sensor::getSensorName(SensorType type) {
227 122 return getSensorType(type);
228 }
229
230 /*static*/ bool Sensor::s_inhibitSensorTimeouts = false;
231
232 /*static*/ void Sensor::inhibitTimeouts(bool inhibit) {
233 Sensor::s_inhibitSensorTimeouts = inhibit;
234 }
235
236 // Print information about all sensors
237 /*static*/ void Sensor::showAllSensorInfo() {
238 for (size_t i = 1; i < efi::size(s_sensorRegistry); i++) {
239 auto& entry = s_sensorRegistry[i];
240 const char* name = getSensorType((SensorType)i);
241
242 entry.showInfo(name);
243 }
244 }
245
246 // Print information about a particular sensor
247 /*static*/ void Sensor::showInfo(SensorType type) {
248 auto entry = getEntryForType(type);
249
250 if (entry) {
251 entry->showInfo(getSensorName(type));
252 }
253 }
254
255 /**
256 * this is definitely not the fastest implementation possible but good enough for now?
257 * todo: some sort of hashmap in the future?
258 */
259 8 SensorType findSensorTypeByName(const char *name) {
260 using namespace rusefi::stringutil;
261
262
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 16 times.
✗ Decision 'false' not taken.
16 for (size_t i = 0;i < efi::size(s_sensorRegistry); i++) {
263 16 SensorType type = (SensorType)i;
264 16 const char *sensorName = getSensorType(type);
265
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
2/2
✓ Decision 'true' taken 8 times.
✓ Decision 'false' taken 8 times.
16 if (strEqualCaseInsensitive(sensorName, name)) {
266 8 return type;
267 }
268 }
269
270 return SensorType::Invalid;
271 }
272