-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBluetoothTPMS.hpp
134 lines (112 loc) · 5.54 KB
/
BluetoothTPMS.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------
#include <BLEAdvertisedDevice.h>
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------
#include <algorithm>
#include <numeric>
#include <vector>
#include <optional>
// -----------------------------------------------------------------------------------------------
struct TpmsData {
enum Alarm : uint8_t {
ZeroPressure = 1 << 7,
Rotating = 1 << 6,
StandingIdleFor15mins = 1 << 5,
BeginRotating = 1 << 4,
DecreasingPressureBelow207Psi = 1 << 3,
RisingPressure = 1 << 2,
DecreasingPressureAbove207Psi = 1 << 1,
Unspecified = 1 << 0,
LowBattery = 0xFF
};
float pressure {};
int temperature {};
float battery {};
uint8_t alarms {};
bool _valid { false };
std::vector<String> alarmStrings () const {
static const std::pair<Alarm, const char *> mappings [] = {
{ Alarm::ZeroPressure, "ZeroPressure" },
{ Alarm::Rotating, "Rotating" },
{ Alarm::StandingIdleFor15mins, "StandingIdleFor15mins" },
{ Alarm::BeginRotating, "BeginRotating" },
{ Alarm::DecreasingPressureBelow207Psi, "DecreasingPressureBelow207Psi" },
{ Alarm::RisingPressure, "RisingPressure" },
{ Alarm::DecreasingPressureAbove207Psi, "DecreasingPressureAbove207Psi" },
{ Alarm::Unspecified, "Unspecified" },
{ Alarm::LowBattery, "LowBattery" }
};
std::vector<String> result;
for (const auto &[alarm, string] : mappings)
if ((alarms & static_cast<uint8_t> (alarm)) == static_cast<uint8_t> (alarm))
result.push_back (string);
return result;
}
String toString (Alarm) const {
const auto join = [] (const std::vector<String> &elements, const String &delimiter) -> String {
return elements.empty () ? String () : std::accumulate (std::next (elements.begin ()), elements.end (), elements [0], [&delimiter] (const String &a, const String &b) {
return a + delimiter + b;
});
};
const auto a = alarmStrings ();
return a.empty () ? String () : String ("(" + join (a, ",") + ")");
}
virtual void dumpDebug (void) const {
const auto toBinaryString = [] (uint8_t value) -> String {
char binStr [8];
for (int i = 7; i >= 0; i--)
binStr [i] = (value & (1 << (7 - i))) ? '1' : '0';
return String (binStr, 8);
};
Serial.printf ("Pressure: %.1f psi\n", pressure);
Serial.printf ("Temperature: %u C°\n", temperature);
Serial.printf ("Battery: %.1f V\n", battery);
Serial.printf ("Alarm: %s %s\n", toBinaryString (alarms).c_str (), toString (static_cast<Alarm> (alarms)).c_str ());
}
void decode (const uint8_t *data, size_t size) {
alarms = data [0];
battery = static_cast<float> (data [1]) / 10.0;
temperature = static_cast <int> (data [2]);
pressure = static_cast<float> (((static_cast<uint16_t> (data [3]) << 8) | static_cast<uint16_t> (data [4])) - 145) / 10.0;
uint16_t checksum = (static_cast<uint16_t> (data [5]) << 8) | static_cast<uint16_t> (data [6]);
(void) checksum;
}
bool valid () const {
return true; // for now
}
TpmsData (const uint8_t *data, size_t size) {
decode (data, size);
}
TpmsData () { }
};
#include <optional>
// -----------------------------------------------------------------------------------------------
struct TpmsDataBluetooth : public TpmsData {
String address;
std::optional<String> name;
std::optional<int> rssi;
std::optional<uint8_t> txpower;
explicit TpmsDataBluetooth () {
}
explicit TpmsDataBluetooth (BLEAdvertisedDevice &device) :
address (device.getAddress ().toString ()),
name (device.haveName () ? std::optional<String> (device.getName ()) : std::nullopt),
rssi (device.haveRSSI () ? std::optional<int> (device.getRSSI ()) : std::nullopt),
txpower (device.haveTXPower () ? std::optional<uint8_t> (device.getTXPower ()) : std::nullopt) {
import (device);
}
void dumpDebug (void) const override {
Serial.printf ("Device: address=%s, name=%s, rssi=%s, txpower=%s\n", address.c_str (), name.has_value () ? name.value ().c_str () : "N/A", rssi.has_value () ? String (*rssi).c_str () : "N/A", txpower.has_value () ? String (*txpower).c_str () : "N/A");
TpmsData::dumpDebug ();
}
static TpmsDataBluetooth fromAdvertisedDevice (BLEAdvertisedDevice &device) {
return TpmsDataBluetooth (device);
}
private:
void import (BLEAdvertisedDevice &device) {
decode (reinterpret_cast<const uint8_t *> (device.getManufacturerData ().c_str ()), device.getManufacturerData ().length ());
}
};
// -----------------------------------------------------------------------------------------------
// -----------------------------------------------------------------------------------------------