Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial AirPods decoder
Browse files Browse the repository at this point in the history
DigiH committed Oct 31, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent d6fdd20 commit 2e7a319
Showing 6 changed files with 162 additions and 6 deletions.
9 changes: 6 additions & 3 deletions docs/participate/adding-decoders.md
Original file line number Diff line number Diff line change
@@ -53,8 +53,8 @@ Each device should also have an encoded **tag** property to, at the minimum, def
</thead>
<tbody>
<tr>
<td rowspan=21>Byte[0]</td>
<td rowspan=21>Device Type > "type":</td>
<td rowspan=22>Byte[0]</td>
<td rowspan=22>Device Type > "type":</td>
<td rowspan=1>0 - Reserved</td>
</tr>
<tr>
@@ -109,7 +109,10 @@ Each device should also have an encoded **tag** property to, at the minimum, def
<td rowspan=1>17 - BTN - button</td>
</tr>
<tr>
<td rowspan=1>18-253 - Reserved</td>
<td rowspan=1>18 - AUDIO - audio devices</td>
</tr>
<tr>
<td rowspan=1>19-253 - Reserved</td>
</tr>
<tr>
<td rowspan=1>254 - RMAC - known random MAC address devices</td>
3 changes: 3 additions & 0 deletions src/decoder.cpp
Original file line number Diff line number Diff line change
@@ -572,6 +572,9 @@ int TheengsDecoder::decodeBLEJson(JsonObject& jsondata) {
case 17:
doc["type"] = "BTN"; // Button
break;
case 18:
doc["type"] = "AUDIO"; // Button
break;
case 254:
doc["type"] = "RMAC"; // random MAC address devices
break;
1 change: 1 addition & 0 deletions src/decoder.h
Original file line number Diff line number Diff line change
@@ -150,6 +150,7 @@ class TheengsDecoder {
GTAG,
BOSCHNYON,
JAALEE,
APPLEAIRPODS,
APPLEWATCH,
APPLEDEVICE,
IBEACON,
2 changes: 2 additions & 0 deletions src/devices.h
Original file line number Diff line number Diff line change
@@ -102,6 +102,7 @@
#include "devices/BM6_json.h"
#include "devices/TILT_json.h"
#include "devices/JAALEE_json.h"
#include "devices/APPLEAIRPODS_json.h"
#include "devices/APPLEWATCH_json.h"
#include "devices/APPLEDEVICE_json.h"
#include "devices/iBeacon_json.h"
@@ -227,6 +228,7 @@ const char* _devices[][2] = {
{_tracker_json_GTAG, _tracker_json_props},
{_tracker_json_NYON, _tracker_json_props},
{_JAALEE_json, _JAALEE_json_props},
{_APPLEAIRPODS_json, _APPLEAIRPODS_json_props},
{_APPLEWATCH_json, _APPLEWATCH_json_props},
{_APPLEDEVICE_json, _APPLEDEVICE_json_props},
{_ibeacon_json, _ibeacon_json_props},
123 changes: 123 additions & 0 deletions src/devices/APPLEAIRPODS_json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
const char* _APPLEAIRPODS_json = "{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"tag\":\"1208\",\"condition\":[\"manufacturerdata\",\"index\",8,\"01\",\"&\",\"manufacturerdata\",\"=\",58,\"index\",0,\"4c0007\"],\"properties\":{\"version\":{\"decoder\":[\"static_value\",\"thus far unknown - please report your model version\"]},\"_version\":{\"decoder\":[\"string_from_hex_data\",\"manufacturerdata\",10,4],\"lookup\":[\"0220\",\"AirPods\",\"0e20\",\"AirPods Pro\",\"0620\",\"AirPods Pro 1st gen.\",\"1420\",\"AirPods Pro 2nd gen.\",\"0320\",\"Powerbeats3\",\"0520\",\"BeatsX\",\"0620\",\"Beats Solo3\"]},\"color\":{\"decoder\":[\"static_value\",\"thus far unknown - please report your color\"]},\"_color\":{\"decoder\":[\"string_from_hex_data\",\"manufacturerdata\",22,2],\"lookup\":[\"00\",\"white\",\"01\",\"black\",\"02\",\"red\",\"03\",\"blue\",\"04\",\"pink\",\"05\",\"gray\",\"06\",\"silver\",\"07\",\"gold\",\"08\",\"rose gold\",\"09\",\"space gray\",\"0a\",\"dark blue\",\"0b\",\"light blue\",\"0c\",\"yellow\"]},\"status\":{\"decoder\":[\"static_value\",\"thus far unknown - please report your status\"]},\"_status\":{\"decoder\":[\"string_from_hex_data\",\"manufacturerdata\",14,2],\"lookup\":[\"55\",\"Both AirPods in case\",\"75\",\"Both AirPods in case\",\"22\",\"Both AirPods not in case ??\"]},\"batt_r\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",16,1],\"post_proc\":[\"*\",10,\"max\",100]},\"batt_l\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",17,1],\"post_proc\":[\"*\",10,\"max\",100]},\"batt_case\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",19,1],\"post_proc\":[\"*\",10,\"max\",100]},\"lid_open\":{\"decoder\":[\"value_from_hex_data\",\"manufacturerdata\",20,2,false,false]},\"charging_r\":{\"decoder\":[\"bit_static_value\",\"manufacturerdata\",18,1,false,true]},\"charging_l\":{\"decoder\":[\"bit_static_value\",\"manufacturerdata\",18,0,false,true]},\"charging_case\":{\"decoder\":[\"bit_static_value\",\"manufacturerdata\",18,2,false,true]}}}";
/*R""""(
{
"brand":"Apple/Beats",
"model":"AirPods (Pro)/Solo|Studio Buds",
"model_id":"APPLEAIRPODS",
"tag":"1208",
"condition":["manufacturerdata", "index", 8, "01", "&", "manufacturerdata","=", 58, "index", 0, "4c0007"],
"properties":{
"version":{
"decoder":["static_value", "thus far unknown - please report your model version"]
},
"_version":{
"decoder":["string_from_hex_data", "manufacturerdata", 10, 4],
"lookup":["0220", "AirPods",
"0e20", "AirPods Pro",
"0620", "AirPods Pro 1st gen.",
"1420", "AirPods Pro 2nd gen.",
"0320", "Powerbeats3",
"0520", "BeatsX",
"0620", "Beats Solo3"]
},
"color":{
"decoder":["static_value", "thus far unknown - please report your color"]
},
"_color":{
"decoder":["string_from_hex_data", "manufacturerdata", 22, 2],
"lookup":["00", "white",
"01", "black",
"02", "red",
"03", "blue",
"04", "pink",
"05", "gray",
"06", "silver",
"07", "gold",
"08", "rose gold",
"09", "space gray",
"0a", "dark blue",
"0b", "light blue",
"0c", "yellow"]
},
"status":{
"decoder":["static_value", "thus far unknown - please report your status"]
},
"_status":{
"decoder":["string_from_hex_data", "manufacturerdata", 14, 2],
"lookup":["55", "Both AirPods in case",
"75", "Both AirPods in case",
"22", "Both AirPods not in case ??"]
},
"batt_r":{
"decoder":["value_from_hex_data", "manufacturerdata", 16, 1],
"post_proc":["*", 10, "max", 100]
},
"batt_l":{
"decoder":["value_from_hex_data", "manufacturerdata", 17, 1],
"post_proc":["*", 10, "max", 100]
},
"batt_case":{
"decoder":["value_from_hex_data", "manufacturerdata", 19, 1],
"post_proc":["*", 10, "max", 100]
},
"lid_open":{
"decoder":["value_from_hex_data", "manufacturerdata", 20, 2, false, false]
},
"charging_r":{
"decoder":["bit_static_value", "manufacturerdata", 18, 1, false, true]
},
"charging_l":{
"decoder":["bit_static_value", "manufacturerdata", 18, 0, false, true]
},
"charging_case":{
"decoder":["bit_static_value", "manufacturerdata", 18, 2, false, true]
}
}
})"""";*/

const char* _APPLEAIRPODS_json_props = "{\"properties\":{\"version\":{\"unit\":\"string\",\"name\":\"model version\"},\"color\":{\"unit\":\"string\",\"name\":\"color\"},\"status\":{\"unit\":\"string\",\"name\":\"status\"},\"batt_r\":{\"unit\":\"%\",\"name\":\"batt\"},\"batt_l\":{\"unit\":\"%\",\"name\":\"batt\"},\"batt_case\":{\"unit\":\"%\",\"name\":\"batt\"},\"lid_open\":{\"unit\":\"int\",\"name\":\"lid open counter\"},\"charging_r\":{\"unit\":\"status\",\"name\":\"battery_charging\"},\"charging_l\":{\"unit\":\"status\",\"name\":\"battery_charging\"},\"charging_case\":{\"unit\":\"status\",\"name\":\"battery_charging\"}}}";
/*R""""(
{
"properties":{
"version":{
"unit":"string",
"name":"model version"
},
"color":{
"unit":"string",
"name":"color"
},
"status":{
"unit":"string",
"name":"status"
},
"batt_r":{
"unit":"%",
"name":"batt"
},
"batt_l":{
"unit":"%",
"name":"batt"
},
"batt_case":{
"unit":"%",
"name":"batt"
},
"lid_open":{
"unit":"int",
"name":"lid open counter"
},
"charging_r":{
"unit":"status",
"name":"battery_charging"
},
"charging_l":{
"unit":"status",
"name":"battery_charging"
},
"charging_case":{
"unit":"status",
"name":"battery_charging"
}
}
})"""";*/
30 changes: 27 additions & 3 deletions tests/BLE/test_ble.cpp
Original file line number Diff line number Diff line change
@@ -107,7 +107,6 @@ const char* expected_mfg[] = {
"{\"brand\":\"Apple\",\"model\":\"Apple Continuity\",\"model_id\":\"APPLE_CONT\",\"type\":\"RMAC\",\"device\":\"Apple device\"}",
"{\"brand\":\"Apple\",\"model\":\"Apple Continuity\",\"model_id\":\"APPLE_CONTAT\",\"type\":\"RMAC\",\"device\":\"Apple device\"}",
"{\"brand\":\"Apple\",\"model\":\"Apple Continuity\",\"model_id\":\"APPLE_CONTAT\",\"type\":\"RMAC\",\"device\":\"Apple device\"}",
"{\"brand\":\"Apple\",\"model\":\"Apple Continuity\",\"model_id\":\"APPLE_CONTAT\",\"type\":\"RMAC\",\"device\":\"Apple device\"}",
"{\"brand\":\"iTAG\",\"model\":\"Smart Tracker\",\"model_id\":\"ITAG\",\"type\":\"TRACK\",\"cidc\":false,\"acts\":true,\"track\":true,\"device\":\"iTAG Tracker\"}",
"{\"brand\":\"Tile\",\"model\":\"Smart Tracker\",\"model_id\":\"TILE\",\"type\":\"TRACK\",\"cidc\":false,\"acts\":true,\"track\":true,\"device\":\"Tile Tracker\"}",
"{\"brand\":\"Govee\",\"model\":\"Smart Air Quality Monitor\",\"model_id\":\"H5106\",\"type\":\"AIR\",\"cidc\":false,\"acts\":true,\"tempc\":22.7,\"tempf\":72.86,\"hum\":63.1,\"pm25\":2}",
@@ -168,6 +167,15 @@ const char* expected_mfg[] = {
"{\"brand\":\"Onset\",\"model\":\"Hobo Water Level Sensor\",\"model_id\":\"HOBOMX2001\",\"type\":\"UNIQ\",\"lvl_cm\":8.46760273,\"lvl_in\":3.333701862}",
"{\"brand\":\"Onset\",\"model\":\"Hobo Water Level Sensor\",\"model_id\":\"HOBOMX2001\",\"type\":\"UNIQ\",\"lvl_cm\":9.514185786,\"lvl_in\":3.745742436}",
"{\"brand\":\"SwitchBot\",\"model\":\"Outdoor Meter\",\"model_id\":\"W340001X\",\"type\":\"THB\",\"tempc\":25.5,\"tempf\":77.9,\"hum\":50,\"mac\":\"AA:BB:CC:DD:EE:FF\"}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro\",\"color\":\"white\",\"status\":\"Both AirPods not in case ??\",\"batt_r\":100,\"batt_l\":50,\"batt_case\":100,\"lid_open\":0,\"charging_r\":false,\"charging_l\":false,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":90,\"batt_case\":100,\"lid_open\":0,\"charging_r\":false,\"charging_l\":false,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":30,\"lid_open\":17,\"charging_r\":true,\"charging_l\":false,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"Both AirPods in case\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":30,\"lid_open\":50,\"charging_r\":true,\"charging_l\":true,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":30,\"lid_open\":18,\"charging_r\":true,\"charging_l\":false,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":100,\"lid_open\":18,\"charging_r\":false,\"charging_l\":false,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":90,\"batt_l\":90,\"batt_case\":70,\"lid_open\":50,\"charging_r\":false,\"charging_l\":true,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":90,\"batt_case\":70,\"lid_open\":17,\"charging_r\":true,\"charging_l\":false,\"charging_case\":false}",
"{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"type\":\"AUDIO\",\"track\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"Both AirPods in case\",\"batt_r\":100,\"batt_l\":90,\"batt_case\":70,\"lid_open\":50,\"charging_r\":true,\"charging_l\":true,\"charging_case\":false}",
};

const char* expected_name_uuid_mfgsvcdata[] = {
@@ -604,7 +612,6 @@ const char* test_mfgdata[][3] = {
{"Apple", "Continuity", "4c0009060304c0a87b1e130c1adefc915b9ef8010401030c"},
{"Apple", "Continuity", "4c00130100"},
{"Apple", "Continuity", "4c001219003d9967e0d67bf55617939043e48fd6762144da3e35160300"},
{"Apple", "Continuity", "4c000719010e2022f58f00000a7d9fff27234873d4305e0fed1b39e2b8"},
{"Apple", "Continuity", "4c000c0e00a7582cd64fff2fe83046c99f5b10065a19e96670d8"},
{"Tracker iTAG", "iTAG", "8afc23eb"},
{"Tile name", "Tile", "xxxx"},
@@ -666,6 +673,15 @@ const char* test_mfgdata[][3] = {
{"Hobo Water Level", "", "c500073fd54f0106240000000800529501a0a06aad3d"},
{"Hobo Water Level", "", "c500073fd54f010624000000080092a901a0bcd9c23d"},
{"SwitchBot Outdoor Meter Manufacturerdata", "WoIOSensorTH", "6909aabbccddeeff8b0305993200"},
{"Apple", "AirPods", "4c000719010e2022f58f00000a7d9fff27234873d4305e0fed1b39e2b8"},
{"Apple?", "AirPods", "4c000719010e2002f98f0000058de7929a3aa09ed6fbb010db935b056c"},
{"Apple?", "AirPods", "4c00071901142011aaa3110004254f0c5375c903064e61be2590411d53"},
{"Apple?", "AirPods", "4c00071901142075aab3320004336834816d0f667558352a4e211589aa"},
{"Apple?", "AirPods", "4c00071901142031aaa3120004a1156f4a5481160b323df3f8d892bfc8"},
{"Apple?", "AirPods", "4c00071901142021aa8f12000471436c43b098ff4365eb784afd30c09e"},
{"Apple?", "AirPods", "4c0007190114207199973200080c1b53c3031aa10c5da3847e3690f7db"},
{"Apple?", "AirPods", "4c00071901142031a9a7110004e9d97f8a064c7f4fcc0df5e7aa48708f"},
{"Apple?", "AirPods", "4c00071901142075a9b732000882b97530ec03edd806dced9d00e6a14f"},
};

TheengsDecoder::BLE_ID_NUM test_mfgdata_id_num[]{
@@ -756,7 +772,6 @@ TheengsDecoder::BLE_ID_NUM test_mfgdata_id_num[]{
TheengsDecoder::BLE_ID_NUM::APPLE_CONT,
TheengsDecoder::BLE_ID_NUM::APPLE_CONTAT,
TheengsDecoder::BLE_ID_NUM::APPLE_CONTAT,
TheengsDecoder::BLE_ID_NUM::APPLE_CONTAT,
TheengsDecoder::BLE_ID_NUM::ITAG,
TheengsDecoder::BLE_ID_NUM::TILEN,
TheengsDecoder::BLE_ID_NUM::H5106,
@@ -817,6 +832,15 @@ TheengsDecoder::BLE_ID_NUM test_mfgdata_id_num[]{
TheengsDecoder::BLE_ID_NUM::HOBOMX2001,
TheengsDecoder::BLE_ID_NUM::HOBOMX2001,
TheengsDecoder::BLE_ID_NUM::SBOT_M,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
TheengsDecoder::BLE_ID_NUM::APPLEAIRPODS,
};

// uuid test input [test name] [device name] [uuid] [manufacturer data] [service data]

0 comments on commit 2e7a319

Please sign in to comment.