Add exposure notifications (#1135)

This commit is contained in:
Otto Winter 2020-07-14 18:47:17 +02:00 committed by GitHub
parent 412351fd1e
commit 465cd3d1f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 109 additions and 0 deletions

View file

@ -28,6 +28,7 @@ class ESPBTUUID {
bool contains(uint8_t data1, uint8_t data2) const; bool contains(uint8_t data1, uint8_t data2) const;
bool operator==(const ESPBTUUID &uuid) const; bool operator==(const ESPBTUUID &uuid) const;
bool operator!=(const ESPBTUUID &uuid) const { return !(*this == uuid); }
esp_bt_uuid_t get_uuid(); esp_bt_uuid_t get_uuid();
@ -74,6 +75,8 @@ class ESPBTDevice {
uint64_t address_uint64() const; 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_; } esp_ble_addr_type_t get_address_type() const { return this->address_type_; }
int get_rssi() const { return rssi_; } int get_rssi() const { return rssi_; }
const std::string &get_name() const { return this->name_; } const std::string &get_name() const { return this->name_; }

View 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)

View file

@ -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(&notification.address[0], device.address(), 6);
memcpy(&notification.rolling_proximity_identifier[0], &data[0], 16);
memcpy(&notification.associated_encrypted_metadata[0], &data[16], 4);
notification.rssi = device.get_rssi();
this->trigger(notification);
return true;
}
} // namespace exposure_notifications
} // namespace esphome
#endif

View file

@ -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