mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-27 04:36:31 +00:00
Add Support for Avago Tech Bluetooth Buttons (#20088)
This commit is contained in:
parent
1c60527099
commit
3568b559e4
@ -24,6 +24,8 @@
|
|||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
Version yyyymmdd Action Description
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
|
0.9.2.2 20231123 changed - added support for Avago Tech Bluetooth buttons
|
||||||
|
-------
|
||||||
0.9.2.1 20210217 changed - make features alos depend on received data - i.e. 'unknown' devices will show what they send.
|
0.9.2.1 20210217 changed - make features alos depend on received data - i.e. 'unknown' devices will show what they send.
|
||||||
Add MI32Option6 1 to switch to tele/tasmota_ble/<somename> style MQTT independent of HASS discovery.
|
Add MI32Option6 1 to switch to tele/tasmota_ble/<somename> style MQTT independent of HASS discovery.
|
||||||
-------
|
-------
|
||||||
@ -483,8 +485,9 @@ void (*const MI32_Commands[])(void) PROGMEM = {
|
|||||||
#define MI_SCALE_V1 15
|
#define MI_SCALE_V1 15
|
||||||
#define MI_SCALE_V2 16
|
#define MI_SCALE_V2 16
|
||||||
#define MI_CGDK2 17
|
#define MI_CGDK2 17
|
||||||
|
#define AT_BTN 18
|
||||||
|
|
||||||
#define MI_MI32_TYPES 17 //count this manually
|
#define MI_MI32_TYPES 18 //count this manually
|
||||||
|
|
||||||
const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
|
const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
|
||||||
0x0000, // Unkown
|
0x0000, // Unkown
|
||||||
@ -504,6 +507,7 @@ const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
|
|||||||
0x181d, // Mi Scale V1
|
0x181d, // Mi Scale V1
|
||||||
0x181b, // Mi Scale V2
|
0x181b, // Mi Scale V2
|
||||||
0x066f, // CGDK2
|
0x066f, // CGDK2
|
||||||
|
0x004e // Avago Tech Bluetooth Buttons (Company Id)
|
||||||
};
|
};
|
||||||
|
|
||||||
const char kMI32DeviceType0[] PROGMEM = "Unknown";
|
const char kMI32DeviceType0[] PROGMEM = "Unknown";
|
||||||
@ -523,7 +527,8 @@ const char kMI32DeviceType13[] PROGMEM ="DOOR";
|
|||||||
const char kMI32DeviceType14[] PROGMEM ="MISCALEV1";
|
const char kMI32DeviceType14[] PROGMEM ="MISCALEV1";
|
||||||
const char kMI32DeviceType15[] PROGMEM ="MISCALEV2";
|
const char kMI32DeviceType15[] PROGMEM ="MISCALEV2";
|
||||||
const char kMI32DeviceType16[] PROGMEM ="CGDK2";
|
const char kMI32DeviceType16[] PROGMEM ="CGDK2";
|
||||||
const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15,kMI32DeviceType16};
|
const char kMI32DeviceType17[] PROGMEM ="ATBTN";
|
||||||
|
const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15,kMI32DeviceType16,kMI32DeviceType17};
|
||||||
|
|
||||||
typedef int BATREAD_FUNCTION(int slot);
|
typedef int BATREAD_FUNCTION(int slot);
|
||||||
typedef int UNITWRITE_FUNCTION(int slot, int unit);
|
typedef int UNITWRITE_FUNCTION(int slot, int unit);
|
||||||
@ -558,6 +563,7 @@ const char FLORA_Svc[] PROGMEM = "00001204-0000-1000-8000-00805F9
|
|||||||
const char FLORA_BattChar[] PROGMEM = "00001A02-0000-1000-8000-00805F9B34FB";
|
const char FLORA_BattChar[] PROGMEM = "00001A02-0000-1000-8000-00805F9B34FB";
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t ATBTN_Addr[] = { 0xc1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6 }; // All Avago Buttons seem to use same source address
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* enumerations
|
* enumerations
|
||||||
@ -1057,6 +1063,14 @@ int MI32advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ATBTN uses manufacturer data and not a service - bit more like an IBeacon
|
||||||
|
if (memcmp(ATBTN_Addr, addr, 6) == 0)
|
||||||
|
{
|
||||||
|
//AddLog(LOG_LEVEL_INFO, PSTR("M32: AvagoBtn: %s"), advertisedDevice->toString().c_str());
|
||||||
|
MI32ParseATBtn((uint8_t*)advertisedDevice->getManufacturerData().data(), advertisedDevice->getManufacturerData().length(), addr, RSSI);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int svcdataCount = advertisedDevice->getServiceDataCount();
|
int svcdataCount = advertisedDevice->getServiceDataCount();
|
||||||
|
|
||||||
if (svcdataCount == 0) {
|
if (svcdataCount == 0) {
|
||||||
@ -1463,9 +1477,11 @@ int MIParsePacket(const uint8_t* slotmac, struct mi_beacon_data_t *parsed, const
|
|||||||
*
|
*
|
||||||
* @param _MAC BLE address of the sensor
|
* @param _MAC BLE address of the sensor
|
||||||
* @param _type Type number of the sensor
|
* @param _type Type number of the sensor
|
||||||
|
* @param counter sequence number of broadcast - same for duplicates
|
||||||
|
* @paramm ignoreDulicates ignore if counter matches lastCnt and previous broardcasts
|
||||||
* @return uint32_t Known or new slot in the sensors-vector
|
* @return uint32_t Known or new slot in the sensors-vector
|
||||||
*/
|
*/
|
||||||
uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter){
|
uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter, bool ignoreDuplicate = false){
|
||||||
|
|
||||||
//AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: will test ID-type: %x"),D_CMND_MI32, _type);
|
//AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: will test ID-type: %x"),D_CMND_MI32, _type);
|
||||||
bool _success = false;
|
bool _success = false;
|
||||||
@ -1490,7 +1506,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
|||||||
if(MIBLEsensors[i].lastCnt==counter) {
|
if(MIBLEsensors[i].lastCnt==counter) {
|
||||||
// AddLog(LOG_LEVEL_DEBUG,PSTR("Old packet"));
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("Old packet"));
|
||||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: slot: %u/%u - ign repeat"),D_CMND_MI32, i, MIBLEsensors.size());
|
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG_MORE,PSTR("M32: %s: slot: %u/%u - ign repeat"),D_CMND_MI32, i, MIBLEsensors.size());
|
||||||
//return 0xff; // packet received before, stop here
|
if(ignoreDuplicate) return 0xff; // packet received before, stop here
|
||||||
}
|
}
|
||||||
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Frame %d, last %d"), counter, MIBLEsensors[i].lastCnt);
|
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Frame %d, last %d"), counter, MIBLEsensors[i].lastCnt);
|
||||||
MIBLEsensors[i].lastCnt = counter;
|
MIBLEsensors[i].lastCnt = counter;
|
||||||
@ -1523,7 +1539,7 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
|||||||
_newSensor.lux = 0x00ffffff;
|
_newSensor.lux = 0x00ffffff;
|
||||||
_newSensor.light = -1;
|
_newSensor.light = -1;
|
||||||
_newSensor.Btn = -1;
|
_newSensor.Btn = -1;
|
||||||
|
_newSensor.lastCnt = counter;
|
||||||
switch (_type)
|
switch (_type)
|
||||||
{
|
{
|
||||||
case MI_FLORA:
|
case MI_FLORA:
|
||||||
@ -1566,6 +1582,11 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
|
|||||||
_newSensor.feature.scale=1;
|
_newSensor.feature.scale=1;
|
||||||
_newSensor.feature.impedance=1;
|
_newSensor.feature.impedance=1;
|
||||||
break;
|
break;
|
||||||
|
case AT_BTN:
|
||||||
|
_newSensor.feature.Btn=1;
|
||||||
|
_newSensor.needkey = KEY_NOT_REQUIRED;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_newSensor.hum=NAN;
|
_newSensor.hum=NAN;
|
||||||
_newSensor.feature.temp=1;
|
_newSensor.feature.temp=1;
|
||||||
@ -2134,6 +2155,61 @@ int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
AT Button Manufacturer Data
|
||||||
|
0 Company ID = 2 bytes
|
||||||
|
2 Unknown = 4 bytes 7fffffff
|
||||||
|
6 Counter = 1 byte
|
||||||
|
7 Unknown = 1 byte 05
|
||||||
|
8 Switch = 2 bytes
|
||||||
|
10 Unknown = 1 byte 00
|
||||||
|
11 Button = 1 bytes 0x (x = 1 to 3)
|
||||||
|
12 Unknown = 4 bytes 50000100
|
||||||
|
*/
|
||||||
|
struct __attribute__ ((packed)) ATBtn_data
|
||||||
|
{
|
||||||
|
uint16_t company_id;
|
||||||
|
uint32_t unknown1;
|
||||||
|
uint8_t counter;
|
||||||
|
uint8_t unknown2;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uint8_t switch1;
|
||||||
|
uint8_t switch2;
|
||||||
|
};
|
||||||
|
uint16_t switch_id;
|
||||||
|
};
|
||||||
|
uint8_t unknown3;
|
||||||
|
uint8_t button_id;
|
||||||
|
uint32_t unknown4;
|
||||||
|
};
|
||||||
|
|
||||||
|
void MI32ParseATBtn(uint8_t *buf, uint16_t bufsize, const uint8_t* addr, int RSSI) {
|
||||||
|
|
||||||
|
ATBtn_data* data = (ATBtn_data*)buf;
|
||||||
|
// AddLog(LOG_LEVEL_INFO,PSTR("ATBTN %04x, %d, Counter(%u) Switch(%04x), Button(%x) %x"), data->company_id, bufsize, data->counter, data->switch_id, data->button_id, kMI32DeviceID[AT_BTN-1]);
|
||||||
|
if (bufsize != sizeof(ATBtn_data) || data->company_id != kMI32DeviceID[AT_BTN-1])
|
||||||
|
return;
|
||||||
|
// since all have same address, we'll move the "switch Id" into the last two addr fields to give each switch a unique MAC address
|
||||||
|
uint8_t _addr[6];
|
||||||
|
memcpy(_addr,addr,6);
|
||||||
|
_addr[4] = data->switch1;
|
||||||
|
_addr[5] = data->switch2;
|
||||||
|
uint32_t _slot = MIBLEgetSensorSlot(_addr, kMI32DeviceID[AT_BTN-1], data->counter, true);
|
||||||
|
if(_slot==0xff) return;
|
||||||
|
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG,PSTR("%s at slot %u"), MI32getDeviceName(_slot),_slot);
|
||||||
|
MIBLEsensors[_slot].RSSI=RSSI;
|
||||||
|
MIBLEsensors[_slot].lastTime = millis();
|
||||||
|
MIBLEsensors[_slot].eventType.Btn = 1;
|
||||||
|
MI32.mode.shallTriggerTele = 1;
|
||||||
|
MIBLEsensors[_slot].shallSendMQTT = 1;
|
||||||
|
MIBLEsensors[_slot].feature.Btn = 1;
|
||||||
|
MIBLEsensors[_slot].Btn = data->button_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// this SHOULD parse any MI packet, including encrypted.
|
// this SHOULD parse any MI packet, including encrypted.
|
||||||
void MI32ParseResponse(const uint8_t *buf, uint16_t bufsize, const uint8_t* addr, int RSSI) {
|
void MI32ParseResponse(const uint8_t *buf, uint16_t bufsize, const uint8_t* addr, int RSSI) {
|
||||||
@ -2745,6 +2821,9 @@ void MI32TimeoutSensors(){
|
|||||||
// remove devices for which the adverts have timed out
|
// remove devices for which the adverts have timed out
|
||||||
for (int i = MIBLEsensors.size()-1; i >= 0 ; i--) {
|
for (int i = MIBLEsensors.size()-1; i >= 0 ; i--) {
|
||||||
//if (MIBLEsensors[i].MAC[2] || MIBLEsensors[i].MAC[3] || MIBLEsensors[i].MAC[4] || MIBLEsensors[i].MAC[5]){
|
//if (MIBLEsensors[i].MAC[2] || MIBLEsensors[i].MAC[3] || MIBLEsensors[i].MAC[4] || MIBLEsensors[i].MAC[5]){
|
||||||
|
// Since we use a pseudo MAC for the ATBTN slots we need to ignore these warnings
|
||||||
|
if (memcmp(MIBLEsensors[i].MAC, ATBTN_Addr, 4) == 0) // Skip pseudo AT BTN addresses
|
||||||
|
continue;
|
||||||
if (!BLE_ESP32::devicePresent(MIBLEsensors[i].MAC)){
|
if (!BLE_ESP32::devicePresent(MIBLEsensors[i].MAC)){
|
||||||
uint8_t *mac = MIBLEsensors[i].MAC;
|
uint8_t *mac = MIBLEsensors[i].MAC;
|
||||||
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Dev no longer present MAC: %02x%02x%02x%02x%02x%02x"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
AddLog(LOG_LEVEL_DEBUG,PSTR("M32: Dev no longer present MAC: %02x%02x%02x%02x%02x%02x"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user