blob: 5177bc393dffc96a310772fe62fd965128fc0117 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdio.h> // snprintf
#include "beacons.h"
namespace ble = fuchsia::bluetooth::le;
namespace bt_beacon_reader {
std::unique_ptr<IBeaconDetection> IBeaconDetection::Create(
const ble::RemoteDevice& device) {
if (!device.advertising_data ||
device.advertising_data->manufacturer_specific_data->size() != 1) {
return nullptr;
}
const std::vector<uint8_t>& data =
*(*device.advertising_data->manufacturer_specific_data)[0].data;
if (data[0] != 0x02) {
return nullptr;
}
if (data[1] != data.size() - 2 || data.size() < 21) {
return nullptr;
}
std::unique_ptr<IBeaconDetection> beacon(new IBeaconDetection);
beacon->Read(data);
return beacon;
}
void IBeaconDetection::Read(const std::vector<uint8_t>& data) {
char temp[3];
power_lvl_ = 0;
uuid_.clear();
for (int i = 2; i < 18; ++i) {
snprintf(temp, 3, "%02x", data[i]);
uuid_.append(temp, 2);
}
major_ = (data[18] << 8) + data[19];
minor_ = (data[20] << 8) + data[21];
// The power level field seems to be optional...
if (data.size() > 22) {
power_lvl_ = data[22];
}
}
std::unique_ptr<TiltDetection> TiltDetection::Create(
const ble::RemoteDevice& device) {
std::unique_ptr<IBeaconDetection> beacon = IBeaconDetection::Create(device);
if (!beacon) {
return nullptr;
}
// All Tilt Hydrometers have uuids of the form:
// a495bb-0c5b14b44b5121370f02d74de where the dash is 0-8,
// corresponding to the 8 colors.
if (beacon->uuid_.compare(0, 6, "a495bb") ||
beacon->uuid_.compare(8, 24, "c5b14b44b5121370f02d74de")) {
return nullptr;
}
// OK, it is a tilt!
std::unique_ptr<TiltDetection> tilt(new TiltDetection);
tilt->Read(beacon);
tilt->identifier_ = *device.identifier;
return tilt;
}
void TiltDetection::Print() {
printf("Tilt %s: Temp: %dF, Gravity: %1.3f\n", color_string_.c_str(),
temperature_F_, gravity_);
}
void TiltDetection::Read(const std::unique_ptr<IBeaconDetection>& beacon) {
temperature_F_ = beacon->major_;
color_ = beacon->uuid_[6] - '0';
std::string colors[] = {"Invalid", "Red", "Green", "Black", "Purple",
"Orange", "Blue", "Yellow", "Pink"};
color_string_ = colors[color_ % 9];
// negative gravities are just expressed as their value % 1000.
// Since a specific gravity of beer at 1.5 is crazy, we'll draw the line
// there.
gravity_ = beacon->minor_ / 1000.0;
if (beacon->minor_ < 500) {
gravity_ += 1.0;
}
}
} // namespace bt_beacon_reader