From 53e02a483b9051cf54815b606bb5e642d7d37ad4 Mon Sep 17 00:00:00 2001 From: DigiH Date: Sat, 20 Jan 2024 17:45:30 +0100 Subject: [PATCH] Initial Apple AirPods / Beats Buds decoder Co-Authored-By: jum0n <7494877+jum0n@users.noreply.github.com> --- docs/devices/AppleAirPods.md | 21 +++++ docs/devices/BeatsBuds.md | 21 +++++ docs/participate/adding-decoders.md | 9 ++- src/decoder.cpp | 3 + src/decoder.h | 1 + src/devices.h | 2 + src/devices/APPLEAIRPODS_json.h | 116 ++++++++++++++++++++++++++++ tests/BLE/test_ble.cpp | 45 ++++++++++- 8 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 docs/devices/AppleAirPods.md create mode 100644 docs/devices/BeatsBuds.md create mode 100644 src/devices/APPLEAIRPODS_json.h diff --git a/docs/devices/AppleAirPods.md b/docs/devices/AppleAirPods.md new file mode 100644 index 000000000..21c8acedd --- /dev/null +++ b/docs/devices/AppleAirPods.md @@ -0,0 +1,21 @@ +# Apple AirPods (Pro) + +|Model Id|[APPLEAIRPODS](https://github.com/theengs/decoder/blob/development/src/devices/APPLEAIRPODS_json.h)| +|-|-| +|Brand|Apple| +|Model|AirPods (Pro)| +|Short Description|Various Apple AirPods (Pro) models| +|Communication|BLE broadcast| +|Frequency|2.4Ghz| +|Power Source|Rechargeable battery| +|Exchanged Data|model version, color, status, (left, right, case) battery level*, (left, right, case) charging state| +|Encrypted|No| +|Device Tracker|✅| + +Currently only usefully working with the [Theengs Gateway](https://gateway.theengs.io/use/use.html#details-options) **Identity Address** and **IRK** functionality, to be able to decrypt the randomly changing Bluetooth MAC address to the static identity MAC address. + +Instructions on how to get the [Identity Address and IRK for an Apple Watch, iPhone or iPad](https://gateway.theengs.io/use/use.html#getting-identity-resolving-key-irk-for-apple-watch-iphone-and-ipad) + +\* battery levels are only reported in 10% steps by the BLE broadcasts. + +Some model versions and statuses are not decoded correctly yet, due to the various models and generations. In such a case please report your device's MQTT message with the [PUBLISH_ADVDATA option](https://gateway.theengs.io/use/use.html#details-options) set to **true**. diff --git a/docs/devices/BeatsBuds.md b/docs/devices/BeatsBuds.md new file mode 100644 index 000000000..1cd4c403d --- /dev/null +++ b/docs/devices/BeatsBuds.md @@ -0,0 +1,21 @@ +# Beats Solo/Studio Buds + +|Model Id|[APPLEAIRPODS](https://github.com/theengs/decoder/blob/development/src/devices/APPLEAIRPODS_json.h)| +|-|-| +|Brand|Beats| +|Model|Solo/Studio Buds| +|Short Description|Various Beats Solo/Studio Buds models| +|Communication|BLE broadcast| +|Frequency|2.4Ghz| +|Power Source|Rechargeable battery| +|Exchanged Data|model version, color, status, (left, right, case) battery level*, (left, right, case) charging state| +|Encrypted|No| +|Device Tracker|✅| + +Currently only usefully working with the [Theengs Gateway](https://gateway.theengs.io/use/use.html#details-options) **Identity Address** and **IRK** functionality, to be able to decrypt the randomly changing Bluetooth MAC address to the static identity MAC address. + +Instructions on how to get the [Identity Address and IRK for an Apple Watch, iPhone or iPad](https://gateway.theengs.io/use/use.html#getting-identity-resolving-key-irk-for-apple-watch-iphone-and-ipad) + +\* battery levels are only reported in 10% steps by the BLE broadcasts. + +Some model versions, colors and statuses are not decoded correctly yet, due to the various models, colors and generations. In such a case please report your device's MQTT message with the [PUBLISH_ADVDATA option](https://gateway.theengs.io/use/use.html#details-options) set to **true**. diff --git a/docs/participate/adding-decoders.md b/docs/participate/adding-decoders.md index 7867f6116..997d53b03 100644 --- a/docs/participate/adding-decoders.md +++ b/docs/participate/adding-decoders.md @@ -53,8 +53,8 @@ Each device should also have an encoded **tag** property to, at the minimum, def - Byte[0] - Device Type > "type": + Byte[0] + Device Type > "type": 0 - Reserved @@ -109,7 +109,10 @@ Each device should also have an encoded **tag** property to, at the minimum, def 17 - BTN - button - 18-253 - Reserved + 18 - AUDIO - audio devices + + + 19-253 - Reserved 254 - RMAC - known random MAC address devices diff --git a/src/decoder.cpp b/src/decoder.cpp index 808c23d98..19e3dbd35 100644 --- a/src/decoder.cpp +++ b/src/decoder.cpp @@ -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; diff --git a/src/decoder.h b/src/decoder.h index 2ebd9f32c..d5b09a487 100644 --- a/src/decoder.h +++ b/src/decoder.h @@ -150,6 +150,7 @@ class TheengsDecoder { GTAG, BOSCHNYON, JAALEE, + APPLEAIRPODS, APPLEWATCH, APPLEDEVICE, IBEACON, diff --git a/src/devices.h b/src/devices.h index 15b26624c..d9934f6fb 100644 --- a/src/devices.h +++ b/src/devices.h @@ -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}, diff --git a/src/devices/APPLEAIRPODS_json.h b/src/devices/APPLEAIRPODS_json.h new file mode 100644 index 000000000..f9f6d26fd --- /dev/null +++ b/src/devices/APPLEAIRPODS_json.h @@ -0,0 +1,116 @@ +const char* _APPLEAIRPODS_json = "{\"brand\":\"Apple/Beats\",\"model\":\"AirPods (Pro)/Solo|Studio Buds\",\"model_id\":\"APPLEAIRPODS\",\"tag\":\"1218\",\"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 1st gen.\",\"0e20\",\"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\",15,1],\"lookup\":[\"5\",\"in case\",\"1\",\"out of case\",\"3\",\"in ears\",\"b\",\"in ears\"]},\"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]},\"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":"1218", + "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 1st gen.", + "0e20", "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", 15, 1], + "lookup":["5", "in case", + "1", "out of case", + "3", "in ears", + "b", "in ears"] + }, + "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] + }, + "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\"},\"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" + }, + "charging_r":{ + "unit":"status", + "name":"battery_charging" + }, + "charging_l":{ + "unit":"status", + "name":"battery_charging" + }, + "charging_case":{ + "unit":"status", + "name":"battery_charging" + } + } +})"""";*/ diff --git a/tests/BLE/test_ble.cpp b/tests/BLE/test_ble.cpp index 350092eb3..8e459a005 100644 --- a/tests/BLE/test_ble.cpp +++ b/tests/BLE/test_ble.cpp @@ -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,20 @@ 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,\"prmac\":true,\"version\":\"AirPods Pro 1st gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":50,\"batt_case\":100,\"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,\"prmac\":true,\"version\":\"AirPods Pro 1st gen.\",\"color\":\"white\",\"status\":\"thus far unknown - please report your status\",\"batt_r\":100,\"batt_l\":90,\"batt_case\":100,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"out of case\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":30,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in case\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":30,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"out of case\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":30,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"out of case\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":100,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"out of case\",\"batt_r\":90,\"batt_l\":90,\"batt_case\":70,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"out of case\",\"batt_r\":100,\"batt_l\":90,\"batt_case\":70,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in case\",\"batt_r\":100,\"batt_l\":90,\"batt_case\":70,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in case\",\"batt_r\":90,\"batt_l\":90,\"batt_case\":70,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in case\",\"batt_r\":90,\"batt_l\":90,\"batt_case\":60,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in ears\",\"batt_r\":80,\"batt_l\":90,\"batt_case\":100,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in ears\",\"batt_r\":100,\"batt_l\":100,\"batt_case\":100,\"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,\"prmac\":true,\"version\":\"AirPods Pro 2nd gen.\",\"color\":\"white\",\"status\":\"in ears\",\"batt_r\":90,\"batt_l\":100,\"batt_case\":100,\"charging_r\":false,\"charging_l\":false,\"charging_case\":false}", }; const char* expected_name_uuid_mfgsvcdata[] = { @@ -604,7 +617,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 +678,20 @@ 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"}, + {"Apple", "AirPods", "4c0007190114203599b751000444a7139966d773e3e1b642a3be823d75"}, + {"Apple", "AirPods", "4c0007190114205599b65100082b939c385b205372f32501b289b844a8"}, + {"Apple", "AirPods", "4c00071901142003898f100008cc74d502b12d6d72e0f4f6eabf826972"}, + {"Apple", "AirPods", "4c00071901142023aa8f1100085925754da1d6ab3f80c398447e652875"}, + {"Apple", "AirPods", "4c0007190114200b9a8f110004fa242ea8abb9e8f5e57cefb13a3077eb"}, }; TheengsDecoder::BLE_ID_NUM test_mfgdata_id_num[]{ @@ -756,7 +782,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 +842,20 @@ 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, + 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]