mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 05:24:53 +01:00
Add exposure notifications (#1135)
This commit is contained in:
parent
412351fd1e
commit
465cd3d1f9
4 changed files with 109 additions and 0 deletions
|
@ -28,6 +28,7 @@ class ESPBTUUID {
|
|||
bool contains(uint8_t data1, uint8_t data2) const;
|
||||
|
||||
bool operator==(const ESPBTUUID &uuid) const;
|
||||
bool operator!=(const ESPBTUUID &uuid) const { return !(*this == uuid); }
|
||||
|
||||
esp_bt_uuid_t get_uuid();
|
||||
|
||||
|
@ -74,6 +75,8 @@ class ESPBTDevice {
|
|||
|
||||
uint64_t address_uint64() const;
|
||||
|
||||
const uint8_t *address() const { return address_; }
|
||||
|
||||
esp_ble_addr_type_t get_address_type() const { return this->address_type_; }
|
||||
int get_rssi() const { return rssi_; }
|
||||
const std::string &get_name() const { return this->name_; }
|
||||
|
|
28
esphome/components/exposure_notifications/__init__.py
Normal file
28
esphome/components/exposure_notifications/__init__.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
import esphome.codegen as cg
|
||||
from esphome import automation
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import esp32_ble_tracker
|
||||
from esphome.const import CONF_TRIGGER_ID
|
||||
|
||||
DEPENDENCIES = ['esp32_ble_tracker']
|
||||
|
||||
exposure_notifications_ns = cg.esphome_ns.namespace('exposure_notifications')
|
||||
ExposureNotification = exposure_notifications_ns.struct('ExposureNotification')
|
||||
ExposureNotificationTrigger = exposure_notifications_ns.class_(
|
||||
'ExposureNotificationTrigger', esp32_ble_tracker.ESPBTDeviceListener,
|
||||
automation.Trigger.template(ExposureNotification))
|
||||
|
||||
CONF_ON_EXPOSURE_NOTIFICATION = 'on_exposure_notification'
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.Required(CONF_ON_EXPOSURE_NOTIFICATION): automation.validate_automation(cv.Schema({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ExposureNotificationTrigger),
|
||||
}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)),
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
for conf in config.get(CONF_ON_EXPOSURE_NOTIFICATION, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
|
||||
yield automation.build_automation(trigger, [(ExposureNotification, 'x')], conf)
|
||||
yield esp32_ble_tracker.register_ble_device(trigger, conf)
|
|
@ -0,0 +1,49 @@
|
|||
#include "exposure_notifications.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
namespace esphome {
|
||||
namespace exposure_notifications {
|
||||
|
||||
using namespace esp32_ble_tracker;
|
||||
|
||||
static const char *TAG = "exposure_notifications";
|
||||
|
||||
bool ExposureNotificationTrigger::parse_device(const ESPBTDevice &device) {
|
||||
// See also https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf
|
||||
if (device.get_service_uuids().size() != 1)
|
||||
return false;
|
||||
|
||||
// Exposure notifications have Service UUID FD 6F
|
||||
ESPBTUUID uuid = device.get_service_uuids()[0];
|
||||
// constant service identifier
|
||||
const ESPBTUUID expected_uuid = ESPBTUUID::from_uint16(0xFD6F);
|
||||
if (uuid != expected_uuid)
|
||||
return false;
|
||||
if (device.get_service_datas().size() != 1)
|
||||
return false;
|
||||
|
||||
// The service data should be 20 bytes
|
||||
// First 16 bytes are the rolling proximity identifier (RPI)
|
||||
// Then 4 bytes of encrypted metadata follow which can be used to get the transmit power level.
|
||||
ServiceData service_data = device.get_service_datas()[0];
|
||||
if (service_data.uuid != expected_uuid)
|
||||
return false;
|
||||
auto data = service_data.data;
|
||||
if (data.size() != 20)
|
||||
return false;
|
||||
ExposureNotification notification{};
|
||||
memcpy(¬ification.address[0], device.address(), 6);
|
||||
memcpy(¬ification.rolling_proximity_identifier[0], &data[0], 16);
|
||||
memcpy(¬ification.associated_encrypted_metadata[0], &data[16], 4);
|
||||
notification.rssi = device.get_rssi();
|
||||
this->trigger(notification);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace exposure_notifications
|
||||
} // namespace esphome
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
||||
#include <array>
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
namespace esphome {
|
||||
namespace exposure_notifications {
|
||||
|
||||
struct ExposureNotification {
|
||||
std::array<uint8_t, 6> address;
|
||||
int rssi;
|
||||
std::array<uint8_t, 16> rolling_proximity_identifier;
|
||||
std::array<uint8_t, 4> associated_encrypted_metadata;
|
||||
};
|
||||
|
||||
class ExposureNotificationTrigger : public Trigger<ExposureNotification>,
|
||||
public esp32_ble_tracker::ESPBTDeviceListener {
|
||||
public:
|
||||
bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override;
|
||||
};
|
||||
|
||||
} // namespace exposure_notifications
|
||||
} // namespace esphome
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue