Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /** | |||
2 | * @file stored_value_sensor.h | |||
3 | * @brief Base class for a sensor that has its value asynchronously | |||
4 | * set, then later retrieved by a consumer. | |||
5 | * | |||
6 | * @date September 12, 2019 | |||
7 | * @author Matthew Kennedy, (c) 2019-2020 | |||
8 | */ | |||
9 | ||||
10 | #pragma once | |||
11 | ||||
12 | #include "sensor.h" | |||
13 | ||||
14 | #include "efitime.h" | |||
15 | ||||
16 | /** | |||
17 | * @brief Base class for sensors that compute a value on one thread, and want | |||
18 | * to make it available to consumers asynchronously. | |||
19 | * | |||
20 | * Common examples include sensors that have to do heavy lifting to produce | |||
21 | * a reading, and don't want to perform that conversion at the time of | |||
22 | * consumption. | |||
23 | * | |||
24 | * To use this class, create a class for your sensor that inherits StoredValueSensor, | |||
25 | * and call Invalidate() and SetValidValue(float) as appropriate when readings are available | |||
26 | * (or known to be invalid) for your sensor. | |||
27 | * | |||
28 | * Consumers will retrieve the last set (or invalidated) value. | |||
29 | */ | |||
30 | class StoredValueSensor : public Sensor { | |||
31 | public: | |||
32 | 604394 | SensorResult get() const final override { | ||
33 | 604394 | auto result = m_result; | ||
34 | ||||
35 | // Timeouts are disabled, return last value | |||
36 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 604394 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 604394 times.
|
604394 | if (Sensor::s_inhibitSensorTimeouts) { |
37 | ✗ | return result; | ||
38 | } | |||
39 | ||||
40 | // Result is already failed, return that so that we get the real error code instead of a timeout | |||
41 |
2/2✓ Branch 1 taken 252 times.
✓ Branch 2 taken 604142 times.
|
2/2✓ Decision 'true' taken 252 times.
✓ Decision 'false' taken 604142 times.
|
604394 | if (!result) { |
42 | 252 | return result; | ||
43 | } | |||
44 | ||||
45 |
2/2✓ Branch 0 taken 272 times.
✓ Branch 1 taken 603870 times.
|
2/2✓ Decision 'true' taken 272 times.
✓ Decision 'false' taken 603870 times.
|
604142 | if (m_timeoutPeriod != 0) { // zero m_timeoutPeriod means value lasts forever |
46 |
3/3✓ Branch 1 taken 272 times.
✓ Branch 3 taken 208 times.
✓ Branch 4 taken 64 times.
|
2/2✓ Decision 'true' taken 208 times.
✓ Decision 'false' taken 64 times.
|
272 | if (getTimeNowNt() - m_timeoutPeriod > m_lastUpdate) { |
47 | 208 | return UnexpectedCode::Timeout; | ||
48 | } | |||
49 | } | |||
50 | ||||
51 | 603934 | return result; | ||
52 | } | |||
53 | ||||
54 | 808 | StoredValueSensor(SensorType type, efidur_t timeoutNt) | ||
55 | 808 | : Sensor(type) | ||
56 | 808 | , m_result(unexpected) | ||
57 | 808 | , m_timeoutPeriod(timeoutNt) | ||
58 | { | |||
59 | 808 | } | ||
60 | ||||
61 | // Invalidate the stored value. | |||
62 | 8 | void invalidate() { | ||
63 | 8 | m_result = unexpected; | ||
64 | 8 | } | ||
65 | ||||
66 | // Invalidate the stored value with an error code | |||
67 | 9 | void invalidate(UnexpectedCode why) { | ||
68 | 9 | m_result = why; | ||
69 | 9 | } | ||
70 | ||||
71 | // A new reading is available: set and validate a new value for the sensor. | |||
72 | 26875 | void setValidValue(float value, efitick_t timestamp) { | ||
73 | // Set value before valid - so we don't briefly have the valid bit set on an invalid value | |||
74 | 26875 | m_result = value; | ||
75 | 26875 | m_lastUpdate = timestamp; | ||
76 | 26875 | } | ||
77 | ||||
78 | void showInfo(const char* sensorName) const override; | |||
79 | ||||
80 | 1 | virtual void setTimeout(int timeoutMs) { | ||
81 | 1 | m_timeoutPeriod = MS2NT(timeoutMs); | ||
82 | 1 | } | ||
83 | ||||
84 | private: | |||
85 | SensorResult m_result; | |||
86 | ||||
87 | efidur_t m_timeoutPeriod; | |||
88 | efitick_t m_lastUpdate = 0; | |||
89 | }; | |||
90 |