Added Android UWB code
This commit is contained in:
164
Manager.cpp
164
Manager.cpp
@@ -9,37 +9,56 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <thread>>
|
||||||
|
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QTextStream>
|
||||||
|
|
||||||
|
|
||||||
|
#include "uwb.h"
|
||||||
|
|
||||||
const std::string NUC1 = "38:de:ad:6d:77:25";
|
const std::string NUC1 = "38:de:ad:6d:77:25";
|
||||||
const std::string NUC2 = "38:de:ad:6d:60:ff";
|
const std::string NUC2 = "38:de:ad:6d:60:ff";
|
||||||
const std::string NUC3 = "1c:1b:b5:ef:a2:9a";
|
const std::string NUC3 = "1c:1b:b5:ef:a2:9a";
|
||||||
const std::string NUC4 = "1c:1b:b5:ec:d1:82";
|
const std::string NUC4 = "1c:1b:b5:ec:d1:82";
|
||||||
|
|
||||||
|
static long long startTime = 0;
|
||||||
|
|
||||||
static QString GetCurrentTimeForFileName()
|
static QString GetCurrentTimeForFileName()
|
||||||
{
|
{
|
||||||
auto time = std::time(nullptr);
|
auto time = std::time(nullptr);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::put_time(std::localtime(&time), "%F_%T"); // ISO 8601 without timezone information.
|
ss << std::put_time(std::localtime(&time), "%Y%m%d_%H%M%S");
|
||||||
auto s = ss.str();
|
auto s = ss.str();
|
||||||
std::replace(s.begin(), s.end(), ':', '-');
|
std::replace(s.begin(), s.end(), ':', '-');
|
||||||
return QString::fromStdString(s);
|
return QString::fromStdString(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long long nowInMsec()
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto duration = now.time_since_epoch();
|
||||||
|
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
|
||||||
|
return millis;
|
||||||
|
}
|
||||||
|
|
||||||
Manager::Manager() {
|
Manager::Manager() {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Manager::trigger() {
|
void Manager::trigger() {
|
||||||
|
|
||||||
QString folder = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + "/ftm/";
|
QString folder = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + "/ftm/";
|
||||||
|
|
||||||
dataLogger = std::make_shared<QFile>(folder+"/ftm_"+GetCurrentTimeForFileName()+".txt");
|
QString prefix = GetCurrentTimeForFileName();
|
||||||
|
|
||||||
|
dataLogger = std::make_shared<QFile>(folder+"/"+prefix+"_ftm.txt");
|
||||||
|
uwbLogger = std::make_shared<QFile>(folder+"/"+prefix+"_uwb.txt");
|
||||||
|
gtLogger = std::make_shared<QFile>(folder+"/"+prefix+"_gt.txt");
|
||||||
|
|
||||||
if (!dataLogger->exists()) {
|
if (!dataLogger->exists()) {
|
||||||
// create the folder, if necessary
|
// create the folder, if necessary
|
||||||
@@ -57,10 +76,24 @@ void Manager::trigger() {
|
|||||||
dataLogger = nullptr;
|
dataLogger = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!uwbLogger->open(QIODevice::ReadWrite)) {
|
||||||
|
qWarning() << "Failed to create uwb data logger file" << uwbLogger->fileName();
|
||||||
|
uwbLogger = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gtLogger->open(QIODevice::ReadWrite)) {
|
||||||
|
qWarning() << "Failed to create gt data logger file" << gtLogger->fileName();
|
||||||
|
gtLogger = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime = nowInMsec();
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
|
||||||
|
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/UWB", "start", "()I");
|
||||||
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/RTT", "start", "()I");
|
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/RTT", "start", "()I");
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
//onData("38:de:ad:6d:77:25;FAILED");
|
//onData("38:de:ad:6d:77:25;FAILED");
|
||||||
@@ -75,21 +108,39 @@ void Manager::trigger() {
|
|||||||
void Manager::stop() {
|
void Manager::stop() {
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/RTT", "stop", "()I");
|
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/RTT", "stop", "()I");
|
||||||
|
QAndroidJniObject::callStaticMethod<int>("android/net/wifi/UWB", "stop", "()I");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dataLogger->flush();
|
dataLogger->flush();
|
||||||
dataLogger->close();
|
dataLogger->close();
|
||||||
|
|
||||||
|
uwbLogger->flush();
|
||||||
|
uwbLogger->close();
|
||||||
|
|
||||||
|
gtLogger->flush();
|
||||||
|
gtLogger->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Manager::manualCheckpoint() {
|
||||||
|
qDebug() << "Manual checkpoint";
|
||||||
|
|
||||||
|
long long timestamp = nowInMsec();
|
||||||
|
timestamp -= startTime;
|
||||||
|
|
||||||
|
QTextStream out(gtLogger.get());
|
||||||
|
|
||||||
|
out << timestamp << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::onData(std::string str) {
|
void Manager::onData(std::string str) {
|
||||||
|
|
||||||
qDebug() << QString(str.c_str());
|
qDebug() << QString(str.c_str());
|
||||||
|
|
||||||
if (dataLogger) {
|
long long timestamp = nowInMsec();
|
||||||
dataLogger->write(str.c_str());
|
timestamp -= startTime;
|
||||||
dataLogger->write("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bool successfullMeas = true;
|
||||||
std::stringstream lineStream(str);
|
std::stringstream lineStream(str);
|
||||||
std::string cell;
|
std::string cell;
|
||||||
|
|
||||||
@@ -99,47 +150,111 @@ void Manager::onData(std::string str) {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
const float alpha = 0.7f;
|
const float alpha = 0.7f;
|
||||||
|
|
||||||
|
QTextStream out(dataLogger.get());
|
||||||
|
|
||||||
|
out << timestamp << ";";
|
||||||
|
|
||||||
while (std::getline(lineStream, cell, ';')) {
|
while (std::getline(lineStream, cell, ';')) {
|
||||||
|
|
||||||
switch(i) {
|
switch(i) {
|
||||||
|
|
||||||
case 0: {
|
case 0: {
|
||||||
|
// success flag
|
||||||
|
successfullMeas = (cell == "1");
|
||||||
|
|
||||||
|
out << (successfullMeas ? 1 : 0) << ";";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
// timestamp; ignore;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 2: {
|
||||||
if(NUC1 == cell) {distIndex = 0;}
|
if(NUC1 == cell) {distIndex = 0;}
|
||||||
if(NUC2 == cell) {distIndex = 1;}
|
if(NUC2 == cell) {distIndex = 1;}
|
||||||
if(NUC3 == cell) {distIndex = 2;}
|
if(NUC3 == cell) {distIndex = 2;}
|
||||||
if(NUC4 == cell) {distIndex = 3;}
|
if(NUC4 == cell) {distIndex = 3;}
|
||||||
|
|
||||||
|
out << QString(cell.c_str()) << ";";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: {
|
case 3: {
|
||||||
if ("FAILED" == cell) {
|
if (successfullMeas) {
|
||||||
_dist[distIndex] = 0;
|
_dist[distIndex] = std::stoi(cell) + _offset;
|
||||||
|
//_dist[distIndex] = _dist[distIndex] * alpha + atoi(cell.c_str()) * (1-alpha);
|
||||||
} else {
|
} else {
|
||||||
//_dist[distIndex] = std::stoi(cell);
|
_dist[distIndex] = 0;
|
||||||
_dist[distIndex] = _dist[distIndex] * alpha + atoi(cell.c_str()) * (1-alpha);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out << _dist[distIndex] << ";";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: {
|
case 4: {
|
||||||
_stdDev[distIndex] = atoi(cell.c_str());
|
if (successfullMeas) {
|
||||||
|
_stdDev[distIndex] = atoi(cell.c_str());
|
||||||
|
} else {
|
||||||
|
_stdDev[distIndex] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out << _stdDev[distIndex] << ";";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: {
|
case 5: {
|
||||||
// RSSI
|
// RSSI
|
||||||
}
|
|
||||||
|
|
||||||
|
out << cell.c_str() << ";";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit distChanged();
|
out << endl;
|
||||||
|
|
||||||
|
|
||||||
|
// if (dataLogger && successfullMeas) {
|
||||||
|
// dataLogger->write(str.c_str());
|
||||||
|
// dataLogger->write("\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
emit distChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::onUWBData(std::vector<uchar> data) {
|
||||||
|
qDebug() << "Received uwb data " << data;
|
||||||
|
|
||||||
|
long long timestamp = nowInMsec();
|
||||||
|
timestamp -= startTime;
|
||||||
|
|
||||||
|
UwbResult uwbResult = uwb_parse(data.data());
|
||||||
|
|
||||||
|
_uwbDist[0] = 0;
|
||||||
|
_uwbDist[1] = 0;
|
||||||
|
_uwbDist[2] = 0;
|
||||||
|
_uwbDist[3] = 0;
|
||||||
|
|
||||||
|
for (UwbDistance& dist : uwbResult.distances) {
|
||||||
|
qDebug() << dist.nodeID;
|
||||||
|
|
||||||
|
switch (dist.nodeID) {
|
||||||
|
case 0x1D8C: _uwbDist[0] = static_cast<float>(dist.distance); break;
|
||||||
|
case 0x47A7: _uwbDist[1] = static_cast<float>(dist.distance); break;
|
||||||
|
case 0x863B: _uwbDist[2] = static_cast<float>(dist.distance); break;
|
||||||
|
case 0x58B4: _uwbDist[3] = static_cast<float>(dist.distance); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uwbLogger) {
|
||||||
|
|
||||||
|
QTextStream out(uwbLogger.get());
|
||||||
|
|
||||||
|
out << timestamp << ";" << "1;" << "DW" << hex << dist.nodeID << dec << ";" << dist.distance << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit distChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
Manager mgmt;
|
Manager mgmt;
|
||||||
@@ -156,5 +271,16 @@ extern "C" {
|
|||||||
mgmt.onData(str);
|
mgmt.onData(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_android_net_wifi_UWB_onUWBComplete(JNIEnv* env, jobject jobj, jbyteArray arrayID) {
|
||||||
|
(void) env; (void) jobj;
|
||||||
|
jsize length = env->GetArrayLength(arrayID);
|
||||||
|
jbyte* data = env->GetByteArrayElements(arrayID, 0);
|
||||||
|
std::vector<uchar> c_data;
|
||||||
|
c_data.assign(reinterpret_cast<char*>(data), reinterpret_cast<char*>(data)+length);
|
||||||
|
env->ReleaseByteArrayElements(arrayID, data, JNI_ABORT);
|
||||||
|
|
||||||
|
mgmt.onUWBData(c_data);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
25
Manager.h
25
Manager.h
@@ -12,8 +12,13 @@ private:
|
|||||||
|
|
||||||
float _dist[4];
|
float _dist[4];
|
||||||
float _stdDev[4];
|
float _stdDev[4];
|
||||||
|
float _offset = 500;
|
||||||
|
|
||||||
|
float _uwbDist[4];
|
||||||
|
|
||||||
std::shared_ptr<QFile> dataLogger;
|
std::shared_ptr<QFile> dataLogger;
|
||||||
|
std::shared_ptr<QFile> uwbLogger;
|
||||||
|
std::shared_ptr<QFile> gtLogger;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -27,11 +32,22 @@ public:
|
|||||||
Q_PROPERTY(float stdDev3 READ getStdDev3() NOTIFY distChanged)
|
Q_PROPERTY(float stdDev3 READ getStdDev3() NOTIFY distChanged)
|
||||||
Q_PROPERTY(float stdDev4 READ getStdDev4() NOTIFY distChanged)
|
Q_PROPERTY(float stdDev4 READ getStdDev4() NOTIFY distChanged)
|
||||||
|
|
||||||
|
// FTM offset
|
||||||
|
Q_PROPERTY(float offset READ getOffset() WRITE setOffset() NOTIFY offsetChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(float uwbDist1 READ getUwbDist1() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float uwbDist2 READ getUwbDist2() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float uwbDist3 READ getUwbDist3() NOTIFY distChanged)
|
||||||
|
Q_PROPERTY(float uwbDist4 READ getUwbDist4() NOTIFY distChanged)
|
||||||
|
|
||||||
|
|
||||||
Q_INVOKABLE void trigger();
|
Q_INVOKABLE void trigger();
|
||||||
Q_INVOKABLE void stop();
|
Q_INVOKABLE void stop();
|
||||||
|
|
||||||
|
Q_INVOKABLE void manualCheckpoint();
|
||||||
|
|
||||||
void onData(std::string str);
|
void onData(std::string str);
|
||||||
|
void onUWBData(std::vector<uchar> data);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -45,9 +61,18 @@ public:
|
|||||||
float getStdDev3() {return _stdDev[2];}
|
float getStdDev3() {return _stdDev[2];}
|
||||||
float getStdDev4() {return _stdDev[3];}
|
float getStdDev4() {return _stdDev[3];}
|
||||||
|
|
||||||
|
float getOffset() {return _offset;}
|
||||||
|
void setOffset(float value) { _offset = value; emit offsetChanged(); }
|
||||||
|
|
||||||
|
float getUwbDist1() {return _uwbDist[0];}
|
||||||
|
float getUwbDist2() {return _uwbDist[1];}
|
||||||
|
float getUwbDist3() {return _uwbDist[2];}
|
||||||
|
float getUwbDist4() {return _uwbDist[3];}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void distChanged();
|
void distChanged();
|
||||||
|
void offsetChanged();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
80
RTT.pro
80
RTT.pro
@@ -46,4 +46,82 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
|
|||||||
!isEmpty(target.path): INSTALLS += target
|
!isEmpty(target.path): INSTALLS += target
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
Manager.h
|
Manager.h \
|
||||||
|
uwb.h
|
||||||
|
|
||||||
|
DISTFILES += \
|
||||||
|
_android/src/UWB.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/annotation/ConnectionPriority.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/annotation/ConnectionState.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/annotation/PhyMask.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/annotation/PhyOption.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/annotation/PhyValue.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/annotation/WriteType.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/profile/ProfileDataCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/profile/ProfileReadResponse.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/BeforeCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/ConnectionPriorityCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/DataReceivedCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/DataSentCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/FailCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/InvalidRequestCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/MtuCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/PhyCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/ReadProgressCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/RssiCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/SuccessCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/callback/WriteProgressCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/Data.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/DataFilter.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/DataMerger.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/DataSplitter.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/DataStream.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/DefaultMtuSplitter.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/data/MutableData.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/error/GattError.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/exception/BluetoothDisabledException.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/exception/ConnectionException.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/exception/DeviceDisconnectedException.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/exception/InvalidDataException.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/exception/InvalidRequestException.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/exception/RequestFailedException.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/response/ConnectionPriorityResponse.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/response/MtuResult.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/response/PhyResult.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/response/ReadResponse.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/response/RssiResult.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/response/WriteResponse.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/utils/ILogger.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/utils/ParserUtils.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/BleManager.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/BleManagerCallbacks.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/ConnectionPriorityRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/ConnectRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/DisconnectRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/MainThreadBluetoothGattCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/MtuRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/Operation.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/PhyRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/ReadRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/ReadRssiRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/ReliableWriteRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/Request.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/RequestQueue.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/SimpleRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/SimpleValueRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/SleepRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/TimeoutableRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/TimeoutableValueRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/TimeoutHandler.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/ValueChangedCallback.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/WaitForValueChangedRequest.java \
|
||||||
|
_android/src/no/nordicsemi/android/ble/WriteRequest.java \
|
||||||
|
_android/src/DecaManager.java \
|
||||||
|
_android/src/DecaManagerCallbacks.java \
|
||||||
|
_android/AndroidManifest.xml \
|
||||||
|
_android/gradle/wrapper/gradle-wrapper.jar \
|
||||||
|
_android/gradlew \
|
||||||
|
_android/res/values/libs.xml \
|
||||||
|
_android/build.gradle \
|
||||||
|
_android/gradle/wrapper/gradle-wrapper.properties \
|
||||||
|
_android/gradlew.bat
|
||||||
|
|||||||
@@ -1,49 +1,49 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<manifest package="indoor.java" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
|
<manifest package="indoor.java" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" android:versionCode="1" android:installLocation="auto">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="26"/>
|
<uses-sdk android:minSdkVersion="28"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
<uses-permission android:name="android.permission.BODY_SENSORS"/>
|
<uses-permission android:name="android.permission.BODY_SENSORS"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
|
|
||||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
|
|
||||||
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name">
|
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/app_name">
|
||||||
|
|
||||||
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="indoor.java.MyActivity" android:label="TEST" android:screenOrientation="unspecified">
|
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="indoor.java.MyActivity" android:label="TEST" android:screenOrientation="unspecified">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
|
<meta-data android:name="android.app.lib_name" android:value="-- %%INSERT_APP_LIB_NAME%% --"/>
|
||||||
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
||||||
<meta-data android:name="android.app.repository" android:value="default"/>
|
<meta-data android:name="android.app.repository" android:value="default"/>
|
||||||
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||||
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||||
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
||||||
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||||
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||||
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
||||||
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
||||||
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
||||||
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||||
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||||
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
||||||
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
||||||
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
65
_android/build.gradle
Normal file
65
_android/build.gradle
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:3.2.0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||||
|
implementation 'androidx.annotation:annotation:1.0.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
/*******************************************************
|
||||||
|
* The following variables:
|
||||||
|
* - androidBuildToolsVersion,
|
||||||
|
* - androidCompileSdkVersion
|
||||||
|
* - qt5AndroidDir - holds the path to qt android files
|
||||||
|
* needed to build any Qt application
|
||||||
|
* on Android.
|
||||||
|
*
|
||||||
|
* are defined in gradle.properties file. This file is
|
||||||
|
* updated by QtCreator and androiddeployqt tools.
|
||||||
|
* Changing them manually might break the compilation!
|
||||||
|
*******************************************************/
|
||||||
|
|
||||||
|
compileSdkVersion androidCompileSdkVersion.toInteger()
|
||||||
|
|
||||||
|
buildToolsVersion androidBuildToolsVersion
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
manifest.srcFile 'AndroidManifest.xml'
|
||||||
|
java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java']
|
||||||
|
aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl']
|
||||||
|
res.srcDirs = [qt5AndroidDir + '/res', 'res']
|
||||||
|
resources.srcDirs = ['src']
|
||||||
|
renderscript.srcDirs = ['src']
|
||||||
|
assets.srcDirs = ['assets']
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
}
|
||||||
18
_android/gradle.properties
Normal file
18
_android/gradle.properties
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
android.enableJetifier=true
|
||||||
|
android.useAndroidX=true
|
||||||
BIN
_android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
_android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
_android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
_android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
172
_android/gradlew
vendored
Normal file
172
_android/gradlew
vendored
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
84
_android/gradlew.bat
vendored
Normal file
84
_android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
25
_android/res/values/libs.xml
Normal file
25
_android/res/values/libs.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<array name="qt_sources">
|
||||||
|
<item>https://download.qt.io/ministro/android/qt5/qt-5.9</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- The following is handled automatically by the deployment tool. It should
|
||||||
|
not be edited manually. -->
|
||||||
|
|
||||||
|
<array name="bundled_libs">
|
||||||
|
<!-- %%INSERT_EXTRA_LIBS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="qt_libs">
|
||||||
|
<!-- %%INSERT_QT_LIBS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="bundled_in_lib">
|
||||||
|
<!-- %%INSERT_BUNDLED_IN_LIB%% -->
|
||||||
|
</array>
|
||||||
|
<array name="bundled_in_assets">
|
||||||
|
<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
</resources>
|
||||||
107
_android/src/DecaManager.java
Normal file
107
_android/src/DecaManager.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package com.example.nrftest;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattService;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.BleManager;
|
||||||
|
import no.nordicsemi.android.ble.callback.profile.ProfileDataCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
|
||||||
|
public class DecaManager extends BleManager<DecaManagerCallbacks> {
|
||||||
|
private static final String TAG = "DecaManager";
|
||||||
|
|
||||||
|
/** Decawave Service UUID. */
|
||||||
|
public final static UUID LBS_UUID_SERVICE = UUID.fromString("680c21d9-c946-4c1f-9c11-baa1c21329e7");
|
||||||
|
/** */
|
||||||
|
public final static UUID LBS_UUID_LOCATION_DATA_CHAR = UUID.fromString("003bbdf2-c634-4b3d-ab56-7ec889b89a37");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private BluetoothGattCharacteristic _locationDataCharacteristic;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public DecaManager(@NonNull final Context context)
|
||||||
|
{
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
protected BleManagerGattCallback getGattCallback() {
|
||||||
|
return mGattCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BluetoothGatt callbacks object.
|
||||||
|
*/
|
||||||
|
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
|
||||||
|
@Override
|
||||||
|
protected void initialize() {
|
||||||
|
|
||||||
|
requestMtu(512).enqueue();
|
||||||
|
|
||||||
|
setNotificationCallback(_locationDataCharacteristic).with(mButtonCallback);
|
||||||
|
// readCharacteristic(mLedCharacteristic).with(mLedCallback).enqueue();
|
||||||
|
// readCharacteristic(mButtonCharacteristic).with(mButtonCallback).enqueue();
|
||||||
|
enableNotifications(_locationDataCharacteristic).enqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) {
|
||||||
|
final BluetoothGattService service = gatt.getService(LBS_UUID_SERVICE);
|
||||||
|
if (service != null) {
|
||||||
|
_locationDataCharacteristic = service.getCharacteristic(LBS_UUID_LOCATION_DATA_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// boolean writeRequest = false;
|
||||||
|
// if (mLedCharacteristic != null) {
|
||||||
|
// final int rxProperties = mLedCharacteristic.getProperties();
|
||||||
|
// writeRequest = (rxProperties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// mSupported = mButtonCharacteristic != null && mLedCharacteristic != null && writeRequest;
|
||||||
|
// return mSupported;
|
||||||
|
|
||||||
|
return _locationDataCharacteristic != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDeviceDisconnected() {
|
||||||
|
_locationDataCharacteristic = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final ProfileDataCallback mButtonCallback = new ProfileDataCallback() {
|
||||||
|
@Override
|
||||||
|
public void onDataReceived(@NonNull BluetoothDevice device, @NonNull Data data) {
|
||||||
|
Log.d(TAG, "onDataReceived: length=" + data.size() + " data=" + data);
|
||||||
|
|
||||||
|
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
for (int i = 0; i < data.size(); i++) {
|
||||||
|
stream.write(data.getByte(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
mCallbacks.onTagLocationData(stream.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidDataReceived(@NonNull final BluetoothDevice device,
|
||||||
|
@NonNull final Data data) {
|
||||||
|
Log.w(TAG, "Invalid data received: " + data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
8
_android/src/DecaManagerCallbacks.java
Normal file
8
_android/src/DecaManagerCallbacks.java
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package com.example.nrftest;
|
||||||
|
|
||||||
|
import no.nordicsemi.android.ble.BleManagerCallbacks;
|
||||||
|
|
||||||
|
public interface DecaManagerCallbacks extends BleManagerCallbacks {
|
||||||
|
|
||||||
|
void onTagLocationData(byte[] dataStr);
|
||||||
|
}
|
||||||
@@ -62,10 +62,8 @@ public class RTT {
|
|||||||
Log.d("RTT", mac.toString() + " FAILED");
|
Log.d("RTT", mac.toString() + " FAILED");
|
||||||
}
|
}
|
||||||
|
|
||||||
RTT.onRTTComplete(serialize(res));
|
RTT.onRTTComplete(serialize(res));
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,28 +73,31 @@ public class RTT {
|
|||||||
char delim = ';';
|
char delim = ';';
|
||||||
boolean success = res.getStatus() == RangingResult.STATUS_SUCCESS;
|
boolean success = res.getStatus() == RangingResult.STATUS_SUCCESS;
|
||||||
|
|
||||||
if (success) {
|
baos.write(success ? '1' : '0');
|
||||||
baos.write(("" + res.getRangingTimestampMillis()).getBytes());
|
baos.write(delim);
|
||||||
baos.write(delim);
|
|
||||||
} else {
|
baos.write(("" + System.currentTimeMillis()).getBytes());
|
||||||
baos.write(("" + System.currentTimeMillis()).getBytes());
|
baos.write(delim);
|
||||||
baos.write(delim);
|
|
||||||
}
|
|
||||||
|
|
||||||
baos.write(res.getMacAddress().toString().getBytes());
|
baos.write(res.getMacAddress().toString().getBytes());
|
||||||
baos.write(delim);
|
baos.write(delim);
|
||||||
|
|
||||||
if (success) {
|
int distValue = 0;
|
||||||
baos.write( ("" + res.getDistanceMm()).getBytes() );
|
int distStdDev = 0;
|
||||||
baos.write(delim);
|
int rssi = 0;
|
||||||
baos.write( ("" + res.getDistanceStdDevMm()).getBytes() );
|
|
||||||
baos.write(delim);
|
|
||||||
baos.write( ("" + res.getRssi()).getBytes() );
|
|
||||||
|
|
||||||
} else {
|
if (success) {
|
||||||
baos.write( "FAILED".getBytes() );
|
distValue = res.getDistanceMm();
|
||||||
|
distStdDev = res.getDistanceStdDevMm();
|
||||||
|
rssi = res.getRssi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
baos.write( ("" + distValue).getBytes() );
|
||||||
|
baos.write(delim);
|
||||||
|
baos.write( ("" + distStdDev).getBytes() );
|
||||||
|
baos.write(delim);
|
||||||
|
baos.write( ("" + rssi).getBytes() );
|
||||||
|
|
||||||
} catch (final Exception e) {;}
|
} catch (final Exception e) {;}
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|||||||
174
_android/src/UWB.java
Normal file
174
_android/src/UWB.java
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
package android.net.wifi;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.lang.System;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothManager;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import android.net.MacAddress;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
|
||||||
|
import indoor.java.MyActivity;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
import com.example.nrftest.*;
|
||||||
|
|
||||||
|
public class UWB {
|
||||||
|
|
||||||
|
private static Activity act;
|
||||||
|
private static Executor mainExecutor;
|
||||||
|
private static Thread uwbThread;
|
||||||
|
private static boolean uwbRunning;
|
||||||
|
|
||||||
|
private static BluetoothManager bluetoothManager;
|
||||||
|
private static BluetoothAdapter bluetoothAdapter;
|
||||||
|
private static BluetoothDevice bluetoothDevice;
|
||||||
|
|
||||||
|
private static DecaManager uwbManager;
|
||||||
|
|
||||||
|
// called when a UWB is completed successfully
|
||||||
|
public static native void onUWBComplete(final byte[] result);
|
||||||
|
|
||||||
|
|
||||||
|
public static int start() {
|
||||||
|
|
||||||
|
if (uwbRunning)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Log.d("UWB", "start()");
|
||||||
|
|
||||||
|
MyActivity act = MyActivity.act;
|
||||||
|
mainExecutor = act.getMainExecutor();
|
||||||
|
|
||||||
|
bluetoothManager = (BluetoothManager) act.getSystemService(Context.BLUETOOTH_SERVICE);
|
||||||
|
bluetoothAdapter = bluetoothManager.getAdapter();
|
||||||
|
|
||||||
|
bluetoothDevice = bluetoothAdapter.getRemoteDevice("D1:6C:7A:99:57:71");
|
||||||
|
|
||||||
|
if (bluetoothDevice == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uwbManager = new DecaManager(act.getApplicationContext());
|
||||||
|
uwbManager.setGattCallbacks(decaCallbacks);
|
||||||
|
|
||||||
|
uwbManager.connect(bluetoothDevice)
|
||||||
|
.retry(3, 100)
|
||||||
|
.useAutoConnect(false)
|
||||||
|
.enqueue();
|
||||||
|
|
||||||
|
uwbRunning = true;
|
||||||
|
|
||||||
|
// uwbThread = new Thread() {
|
||||||
|
// public void run() {
|
||||||
|
// while(uwbRunning) {
|
||||||
|
// try {
|
||||||
|
// Thread.sleep(200);
|
||||||
|
// } catch (Exception e) {;}
|
||||||
|
|
||||||
|
// startRangingOnMacs(macs);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
// uwbThread.start();
|
||||||
|
|
||||||
|
return 1337;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int stop() {
|
||||||
|
Log.d("UWB", "stop()");
|
||||||
|
|
||||||
|
if (uwbRunning) {
|
||||||
|
uwbManager.disconnect().enqueue();
|
||||||
|
|
||||||
|
uwbRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1337*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static final DecaManagerCallbacks decaCallbacks = new DecaManagerCallbacks(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTagLocationData(byte[] data) {
|
||||||
|
onUWBComplete(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceConnecting(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onDeviceConnecting");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceConnected(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onDeviceConnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceDisconnecting(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onDeviceDisconnecting");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceDisconnected(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onDeviceDisconnected");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLinkLossOccurred(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onLinkLossOccurred");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServicesDiscovered(@NonNull BluetoothDevice device, boolean optionalServicesFound) {
|
||||||
|
Log.d("DecaCallbacks", "onServicesDiscovered");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceReady(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onDeviceReady");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBondingRequired(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onBondingRequired");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBonded(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onBonded");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBondingFailed(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onBondingFailed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull BluetoothDevice device, @NonNull String message, int errorCode) {
|
||||||
|
Log.d("DecaCallbacks", "onError: " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeviceNotSupported(@NonNull BluetoothDevice device) {
|
||||||
|
Log.d("DecaCallbacks", "onDeviceNotSupported");
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
3650
_android/src/no/nordicsemi/android/ble/BleManager.java
Normal file
3650
_android/src/no/nordicsemi/android/ble/BleManager.java
Normal file
File diff suppressed because it is too large
Load Diff
206
_android/src/no/nordicsemi/android/ble/BleManagerCallbacks.java
Normal file
206
_android/src/no/nordicsemi/android/ble/BleManagerCallbacks.java
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCallback;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
// DO NOT EDIT THIS FILE UNLESS NECESSARY!
|
||||||
|
/**
|
||||||
|
* The BleManagerCallbacks should be overridden in your app and all the 'high level' callbacks
|
||||||
|
* should be added there. See examples in Android nRF Blinky or Android nRF Toolbox.
|
||||||
|
* <p>
|
||||||
|
* Keeping this file as is (and {@link BleManager} as well) will allow to quickly update it when
|
||||||
|
* an update is posted here.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"DeprecatedIsStillUsed", "unused"})
|
||||||
|
public interface BleManagerCallbacks {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the Android device started connecting to given device.
|
||||||
|
* The {@link #onDeviceConnected(BluetoothDevice)} will be called when the device is connected,
|
||||||
|
* or {@link #onError(BluetoothDevice, String, int)} in case of error.
|
||||||
|
*
|
||||||
|
* @param device the device that got connected.
|
||||||
|
*/
|
||||||
|
void onDeviceConnecting(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the device has been connected. This does not mean that the application may start
|
||||||
|
* communication.
|
||||||
|
* A service discovery will be handled automatically after this call. Service discovery
|
||||||
|
* may ends up with calling {@link #onServicesDiscovered(BluetoothDevice, boolean)} or
|
||||||
|
* {@link #onDeviceNotSupported(BluetoothDevice)} if required services have not been found.
|
||||||
|
*
|
||||||
|
* @param device the device that got connected.
|
||||||
|
*/
|
||||||
|
void onDeviceConnected(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when user initialized disconnection.
|
||||||
|
*
|
||||||
|
* @param device the device that gets disconnecting.
|
||||||
|
*/
|
||||||
|
void onDeviceDisconnecting(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the device has disconnected (when the callback returned
|
||||||
|
* {@link BluetoothGattCallback#onConnectionStateChange(BluetoothGatt, int, int)} with state
|
||||||
|
* DISCONNECTED), but ONLY if the {@link BleManager#shouldAutoConnect()} method returned false
|
||||||
|
* for this device when it was connecting.
|
||||||
|
* Otherwise the {@link #onLinkLossOccurred(BluetoothDevice)} method will be called instead.
|
||||||
|
*
|
||||||
|
* @param device the device that got disconnected.
|
||||||
|
*/
|
||||||
|
void onDeviceDisconnected(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback is invoked when the Ble Manager lost connection to a device that has been
|
||||||
|
* connected with autoConnect option (see {@link BleManager#shouldAutoConnect()}.
|
||||||
|
* Otherwise a {@link #onDeviceDisconnected(BluetoothDevice)} method will be called on such
|
||||||
|
* event.
|
||||||
|
*
|
||||||
|
* @param device the device that got disconnected due to a link loss.
|
||||||
|
*/
|
||||||
|
void onLinkLossOccurred(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when service discovery has finished and primary services has been found.
|
||||||
|
* This method is not called if the primary, mandatory services were not found during service
|
||||||
|
* discovery. For example in the Blood Pressure Monitor, a Blood Pressure service is a
|
||||||
|
* primary service and Intermediate Cuff Pressure service is a optional secondary service.
|
||||||
|
* Existence of battery service is not notified by this call.
|
||||||
|
* <p>
|
||||||
|
* After successful service discovery the service will initialize all services.
|
||||||
|
* The {@link #onDeviceReady(BluetoothDevice)} method will be called when the initialization
|
||||||
|
* is complete.
|
||||||
|
*
|
||||||
|
* @param device the device which services got disconnected.
|
||||||
|
* @param optionalServicesFound if <code>true</code> the secondary services were also found
|
||||||
|
* on the device.
|
||||||
|
*/
|
||||||
|
void onServicesDiscovered(@NonNull final BluetoothDevice device, final boolean optionalServicesFound);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when all initialization requests has been completed.
|
||||||
|
*
|
||||||
|
* @param device the device that get ready.
|
||||||
|
*/
|
||||||
|
void onDeviceReady(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should return true if Battery Level notifications should be enabled on the
|
||||||
|
* target device. If there is no Battery Service, or the Battery Level characteristic does
|
||||||
|
* not have NOTIFY property, this method will not be called for this device.
|
||||||
|
* <p>
|
||||||
|
* This method may return true only if an activity is bound to the service (to display the
|
||||||
|
* information to the user), always (e.g. if critical battery level is reported using
|
||||||
|
* notifications) or never, if such information is not important or the manager wants to
|
||||||
|
* control Battery Level notifications on its own.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @return True to enabled battery level notifications after connecting to the device,
|
||||||
|
* false otherwise.
|
||||||
|
* @deprecated Use
|
||||||
|
* <pre>{@code
|
||||||
|
* setNotificationCallback(batteryLevelCharacteristic)
|
||||||
|
* .with(new BatteryLevelDataCallback() {
|
||||||
|
* onBatteryLevelChanged(int batteryLevel) {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
|
* in the {@link BleManager.BleManagerGattCallback#initialize() initialize(BluetoothDevice)}
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default boolean shouldEnableBatteryLevelNotifications(@NonNull final BluetoothDevice device) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when battery value has been received from the device.
|
||||||
|
*
|
||||||
|
* @param device the device from which the battery value has changed.
|
||||||
|
* @param value the battery value in percent.
|
||||||
|
* @deprecated Use
|
||||||
|
* <pre>{@code
|
||||||
|
* setNotificationCallback(batteryLevelCharacteristic)
|
||||||
|
* .with(new BatteryLevelDataCallback() {
|
||||||
|
* onBatteryLevelChanged(int batteryLevel) {
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
|
* in the {@link BleManager.BleManagerGattCallback#initialize() initialize(BluetoothDevice)}
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default void onBatteryValueReceived(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 0, to = 100) final int value) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when an {@link BluetoothGatt#GATT_INSUFFICIENT_AUTHENTICATION} error occurred and the
|
||||||
|
* device bond state is {@link BluetoothDevice#BOND_NONE}.
|
||||||
|
*
|
||||||
|
* @param device the device that requires bonding.
|
||||||
|
*/
|
||||||
|
void onBondingRequired(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the device has been successfully bonded.
|
||||||
|
*
|
||||||
|
* @param device the device that got bonded.
|
||||||
|
*/
|
||||||
|
void onBonded(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the bond state has changed from {@link BluetoothDevice#BOND_BONDING} to
|
||||||
|
* {@link BluetoothDevice#BOND_NONE}.
|
||||||
|
*
|
||||||
|
* @param device the device that failed to bond.
|
||||||
|
*/
|
||||||
|
void onBondingFailed(@NonNull final BluetoothDevice device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a BLE error has occurred
|
||||||
|
*
|
||||||
|
* @param message the error message.
|
||||||
|
* @param errorCode the error code.
|
||||||
|
* @param device the device that caused an error.
|
||||||
|
*/
|
||||||
|
void onError(@NonNull final BluetoothDevice device,
|
||||||
|
@NonNull final String message, final int errorCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when service discovery has finished but the main services were not found on the device.
|
||||||
|
*
|
||||||
|
* @param device the device that failed to connect due to lack of required services.
|
||||||
|
*/
|
||||||
|
void onDeviceNotSupported(@NonNull final BluetoothDevice device);
|
||||||
|
}
|
||||||
246
_android/src/no/nordicsemi/android/ble/ConnectRequest.java
Normal file
246
_android/src/no/nordicsemi/android/ble/ConnectRequest.java
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCallback;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyMask;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connect request is used to connect to a Bluetooth LE device. The request will end when
|
||||||
|
* the device gets connected, the connection timeouts, or an error occurs.
|
||||||
|
* <p>
|
||||||
|
* The {@link #done(SuccessCallback)} callback will be called after the device is ready, that is
|
||||||
|
* when it is connected, the services were discovered, the required services were found and the
|
||||||
|
* initialization queue set in {@link BleManager.BleManagerGattCallback#initialize()} is complete
|
||||||
|
* (without or with errors).
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused", "deprecation"})
|
||||||
|
public class ConnectRequest extends TimeoutableRequest {
|
||||||
|
@NonNull
|
||||||
|
private BluetoothDevice device;
|
||||||
|
@PhyMask
|
||||||
|
private int preferredPhy;
|
||||||
|
@IntRange(from = 0)
|
||||||
|
private int attempt = 0, retries = 0;
|
||||||
|
@IntRange(from = 0)
|
||||||
|
private int delay = 0;
|
||||||
|
private boolean autoConnect = false;
|
||||||
|
|
||||||
|
ConnectRequest(@NonNull final Type type, @NonNull final BluetoothDevice device) {
|
||||||
|
super(type);
|
||||||
|
this.device = device;
|
||||||
|
this.preferredPhy = PhyRequest.PHY_LE_1M_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
ConnectRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ConnectRequest timeout(@IntRange(from = 0) final long timeout) {
|
||||||
|
super.timeout(timeout);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to set a completion callback. The callback will be invoked when the operation has
|
||||||
|
* finished successfully unless {@link #await()} or its variant was used, in which case this
|
||||||
|
* callback will be ignored.
|
||||||
|
* <p>
|
||||||
|
* The done callback will also be called when one or more of initialization requests has
|
||||||
|
* failed due to a reason other than disconnect event. This is because
|
||||||
|
* {@link BleManagerCallbacks#onDeviceReady(BluetoothDevice)} is called no matter
|
||||||
|
* if the requests succeeded, or not. Set failure callbacks to initialization requests
|
||||||
|
* to get information about failures.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ConnectRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ConnectRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ConnectRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ConnectRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an optional retry count. The BleManager will do that many attempts to connect to the
|
||||||
|
* device in case of an error. The library will NOT retry if the device is not reachable,
|
||||||
|
* that is when the 30 sec. timeout occurs. In that case the app should scan before
|
||||||
|
* connecting, to make sure the target is in range.
|
||||||
|
*
|
||||||
|
* @param count how many times should the BleManager retry to connect.
|
||||||
|
* @return The request.
|
||||||
|
* @see #retry(int, int)
|
||||||
|
*/
|
||||||
|
public ConnectRequest retry(@IntRange(from = 0) final int count) {
|
||||||
|
this.retries = count;
|
||||||
|
this.delay = 0;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an optional retry count and a delay that the process will wait before each connection
|
||||||
|
* attempt. The library will NOT retry if the device is not reachable, that is when the 30 sec.
|
||||||
|
* timeout occurs. In that case the app should scan before connecting, to make sure the
|
||||||
|
* target is in range.
|
||||||
|
*
|
||||||
|
* @param count how many times should the BleManager retry to connect.
|
||||||
|
* @param delay the delay between each connection attempt, in milliseconds.
|
||||||
|
* The real delay will be 200 ms longer than specified, as
|
||||||
|
* {@link BluetoothGatt#clone()} is estimated to last
|
||||||
|
* {@link BleManager#internalConnect(BluetoothDevice, ConnectRequest) 200 ms}.
|
||||||
|
* @return The request.
|
||||||
|
* @see #retry(int)
|
||||||
|
*/
|
||||||
|
public ConnectRequest retry(@IntRange(from = 0) final int count,
|
||||||
|
@IntRange(from = 0) final int delay) {
|
||||||
|
this.retries = count;
|
||||||
|
this.delay = delay;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method replaces the {@link BleManager#shouldAutoConnect()} method.
|
||||||
|
* <p>
|
||||||
|
* Sets whether to connect to the remote device just once (false) or to add the address to
|
||||||
|
* white list of devices that will be automatically connect as soon as they become available
|
||||||
|
* (true). In the latter case, if Bluetooth adapter is enabled, Android scans periodically
|
||||||
|
* for devices from the white list and, if an advertising packet is received from such, it tries
|
||||||
|
* to connect to it. When the connection is lost, the system will keep trying to reconnect to
|
||||||
|
* it. If method is called with parameter set to true, and the connection to the device is
|
||||||
|
* lost, the {@link BleManagerCallbacks#onLinkLossOccurred(BluetoothDevice)} callback is
|
||||||
|
* called instead of {@link BleManagerCallbacks#onDeviceDisconnected(BluetoothDevice)}.
|
||||||
|
* <p>
|
||||||
|
* This feature works much better on newer Android phone models and may have issues on older
|
||||||
|
* phones.
|
||||||
|
* <p>
|
||||||
|
* This method should only be used with bonded devices, as otherwise the device may change
|
||||||
|
* it's address. It will however work also with non-bonded devices with private static address.
|
||||||
|
* A connection attempt to a non-bonded device with private resolvable address will fail.
|
||||||
|
* <p>
|
||||||
|
* The first connection to a device will always be created with autoConnect flag to false
|
||||||
|
* (see {@link BluetoothDevice#connectGatt(Context, boolean, BluetoothGattCallback)}). This is
|
||||||
|
* to make it quick as the user most probably waits for a quick response. If autoConnect is
|
||||||
|
* used (true), the following connections will be done using {@link BluetoothGatt#connect()},
|
||||||
|
* which forces the autoConnect parameter to true.
|
||||||
|
*
|
||||||
|
* @param autoConnect true to use autoConnect feature on the second and following connections.
|
||||||
|
* The first connection is always done with autoConnect parameter equal to
|
||||||
|
* false, to make it faster and allow to timeout it the device is unreachable.
|
||||||
|
* Default value is false.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
public ConnectRequest useAutoConnect(final boolean autoConnect) {
|
||||||
|
this.autoConnect = autoConnect;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the preferred PHY used for connection. Th value should be a bitmask composed of
|
||||||
|
* {@link PhyRequest#PHY_LE_1M_MASK}, {@link PhyRequest#PHY_LE_2M_MASK} or
|
||||||
|
* {@link PhyRequest#PHY_LE_CODED_MASK}.
|
||||||
|
* <p>
|
||||||
|
* Different PHYs are available only on more recent devices with Android 8+.
|
||||||
|
* Check {@link BluetoothAdapter#isLe2MPhySupported()} and
|
||||||
|
* {@link BluetoothAdapter#isLeCodedPhySupported()} if required PHYs are supported by this
|
||||||
|
* Android device. The default PHY is {@link PhyRequest#PHY_LE_1M_MASK}.
|
||||||
|
*
|
||||||
|
* @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of
|
||||||
|
* {@link PhyRequest#PHY_LE_1M_MASK}, {@link PhyRequest#PHY_LE_2M_MASK},
|
||||||
|
* and {@link PhyRequest#PHY_LE_CODED_MASK}. This option does not take effect
|
||||||
|
* if {@code autoConnect} is set to true.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
public ConnectRequest usePreferredPhy(@PhyMask final int phy) {
|
||||||
|
this.preferredPhy = phy;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public BluetoothDevice getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhyMask
|
||||||
|
int getPreferredPhy() {
|
||||||
|
return preferredPhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean canRetry() {
|
||||||
|
if (retries > 0) {
|
||||||
|
retries -= 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isFirstAttempt() {
|
||||||
|
return attempt++ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntRange(from = 0)
|
||||||
|
int getRetryDelay() {
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean shouldAutoConnect() {
|
||||||
|
return autoConnect;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import no.nordicsemi.android.ble.annotation.ConnectionPriority;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.ConnectionPriorityCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public final class ConnectionPriorityRequest extends SimpleValueRequest<ConnectionPriorityCallback>
|
||||||
|
implements Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection parameter update - Use the connection parameters recommended by the
|
||||||
|
* Bluetooth SIG. This is the default value if no connection parameter update
|
||||||
|
* is requested.
|
||||||
|
* <p>
|
||||||
|
* Interval: 30 - 50 ms, latency: 0, supervision timeout: 20 sec.
|
||||||
|
*/
|
||||||
|
public static final int CONNECTION_PRIORITY_BALANCED = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection parameter update - Request a high priority, low latency connection.
|
||||||
|
* An application should only request high priority connection parameters to transfer
|
||||||
|
* large amounts of data over LE quickly. Once the transfer is complete, the application
|
||||||
|
* should request {@link #CONNECTION_PRIORITY_BALANCED} connection parameters
|
||||||
|
* to reduce energy use.
|
||||||
|
* <p>
|
||||||
|
* Interval: 11.25 - 15 ms (Android 6+) or 7.5 - 10 ms (Android 4.3 - 5.1),
|
||||||
|
* latency: 0, supervision timeout: 20 sec.
|
||||||
|
*/
|
||||||
|
public static final int CONNECTION_PRIORITY_HIGH = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connection parameter update - Request low power, reduced data rate connection parameters.
|
||||||
|
* <p>
|
||||||
|
* Interval: 100 - 125 ms, latency: 2, supervision timeout: 20 sec.
|
||||||
|
*/
|
||||||
|
public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
ConnectionPriorityRequest(@NonNull final Type type, @ConnectionPriority int priority) {
|
||||||
|
super(type);
|
||||||
|
if (priority < 0 || priority > 2)
|
||||||
|
priority = CONNECTION_PRIORITY_BALANCED;
|
||||||
|
this.value = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
ConnectionPriorityRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ConnectionPriorityRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ConnectionPriorityRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ConnectionPriorityRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ConnectionPriorityRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(value = Build.VERSION_CODES.O)
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ConnectionPriorityRequest with(@NonNull final ConnectionPriorityCallback callback) {
|
||||||
|
// The BluetoothGattCallback#onConnectionUpdated callback was introduced in Android Oreo.
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(value = Build.VERSION_CODES.O)
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public <E extends ConnectionPriorityCallback> E await(@NonNull final Class<E> responseClass)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException {
|
||||||
|
// The BluetoothGattCallback#onConnectionUpdated callback was introduced in Android Oreo.
|
||||||
|
return super.await(responseClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(value = Build.VERSION_CODES.O)
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public <E extends ConnectionPriorityCallback> E await(@NonNull final E response)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException {
|
||||||
|
// The BluetoothGattCallback#onConnectionUpdated callback was introduced in Android Oreo.
|
||||||
|
return super.await(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
void notifyConnectionPriorityChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 6, to = 3200) final int interval,
|
||||||
|
@IntRange(from = 0, to = 499) final int latency,
|
||||||
|
@IntRange(from = 10, to = 3200) final int timeout) {
|
||||||
|
if (valueCallback != null)
|
||||||
|
valueCallback.onConnectionUpdated(device, interval, latency, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConnectionPriority
|
||||||
|
int getRequiredPriority() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused", "deprecation"})
|
||||||
|
public class DisconnectRequest extends TimeoutableRequest {
|
||||||
|
|
||||||
|
DisconnectRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
DisconnectRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DisconnectRequest timeout(@IntRange(from = 0) final long timeout) {
|
||||||
|
super.timeout(timeout);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DisconnectRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DisconnectRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public DisconnectRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public DisconnectRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCallback;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import no.nordicsemi.android.ble.annotation.ConnectionState;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class ensures that the BLE callbacks will be called on the main (UI) thread.
|
||||||
|
* Handler parameter was added to {@link android.bluetooth.BluetoothDevice
|
||||||
|
* #connectGatt(Context, boolean, BluetoothGattCallback, int, int, Handler)}
|
||||||
|
* in Android Oreo, before that the behavior was undefined.
|
||||||
|
*/
|
||||||
|
abstract class MainThreadBluetoothGattCallback extends BluetoothGattCallback {
|
||||||
|
private Handler mHandler;
|
||||||
|
|
||||||
|
void setHandler(@NonNull final Handler handler) {
|
||||||
|
mHandler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runOnUiThread(@NonNull final Runnable runnable) {
|
||||||
|
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||||
|
mHandler.post(runnable);
|
||||||
|
} else {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void onConnectionStateChangeSafe(@NonNull final BluetoothGatt gatt, final int status,
|
||||||
|
final int newState);
|
||||||
|
abstract void onServicesDiscoveredSafe(@NonNull final BluetoothGatt gatt, final int status);
|
||||||
|
abstract void onCharacteristicReadSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] data,
|
||||||
|
final int status);
|
||||||
|
abstract void onCharacteristicWriteSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] data,
|
||||||
|
final int status);
|
||||||
|
abstract void onCharacteristicChangedSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] data);
|
||||||
|
abstract void onDescriptorReadSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattDescriptor descriptor,
|
||||||
|
@Nullable final byte[] data,
|
||||||
|
final int status);
|
||||||
|
abstract void onDescriptorWriteSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattDescriptor descriptor,
|
||||||
|
@Nullable final byte[] data,
|
||||||
|
final int status);
|
||||||
|
abstract void onReadRemoteRssiSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@IntRange(from = -128, to = 20) final int rssi,
|
||||||
|
final int status);
|
||||||
|
abstract void onReliableWriteCompletedSafe(@NonNull final BluetoothGatt gatt, final int status);
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
abstract void onMtuChangedSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@IntRange(from = 23, to = 517) final int mtu, final int status);
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
abstract void onPhyReadSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy, final int status);
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
abstract void onPhyUpdateSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy, final int status);
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
abstract void onConnectionUpdatedSafe(@NonNull final BluetoothGatt gatt,
|
||||||
|
@IntRange(from = 6, to = 3200) final int interval,
|
||||||
|
@IntRange(from = 0, to = 499) final int latency,
|
||||||
|
@IntRange(from = 10, to = 3200) final int timeout,
|
||||||
|
final int status);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onConnectionStateChange(@NonNull final BluetoothGatt gatt, final int status,
|
||||||
|
@ConnectionState final int newState) {
|
||||||
|
runOnUiThread(() -> onConnectionStateChangeSafe(gatt, status, newState));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onServicesDiscovered(@NonNull final BluetoothGatt gatt, final int status) {
|
||||||
|
runOnUiThread(() -> onServicesDiscoveredSafe(gatt, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onCharacteristicRead(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattCharacteristic characteristic,
|
||||||
|
final int status) {
|
||||||
|
final byte[] data = characteristic.getValue();
|
||||||
|
runOnUiThread(() -> onCharacteristicReadSafe(gatt, characteristic, data, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onCharacteristicWrite(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattCharacteristic characteristic,
|
||||||
|
final int status) {
|
||||||
|
final byte[] data = characteristic.getValue();
|
||||||
|
runOnUiThread(() -> onCharacteristicWriteSafe(gatt, characteristic, data, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onCharacteristicChanged(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattCharacteristic characteristic) {
|
||||||
|
final byte[] data = characteristic.getValue();
|
||||||
|
runOnUiThread(() -> onCharacteristicChangedSafe(gatt, characteristic, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onDescriptorRead(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattDescriptor descriptor,
|
||||||
|
final int status) {
|
||||||
|
final byte[] data = descriptor.getValue();
|
||||||
|
runOnUiThread(() -> onDescriptorReadSafe(gatt, descriptor, data, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onDescriptorWrite(@NonNull final BluetoothGatt gatt,
|
||||||
|
@NonNull final BluetoothGattDescriptor descriptor,
|
||||||
|
final int status) {
|
||||||
|
final byte[] data = descriptor.getValue();
|
||||||
|
runOnUiThread(() -> onDescriptorWriteSafe(gatt, descriptor, data, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onReadRemoteRssi(@NonNull final BluetoothGatt gatt,
|
||||||
|
@IntRange(from = -128, to = 20) final int rssi,
|
||||||
|
final int status) {
|
||||||
|
runOnUiThread(() -> onReadRemoteRssiSafe(gatt, rssi, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void onReliableWriteCompleted(@NonNull final BluetoothGatt gatt, final int status) {
|
||||||
|
runOnUiThread(() -> onReliableWriteCompletedSafe(gatt, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
@Override
|
||||||
|
public final void onMtuChanged(@NonNull final BluetoothGatt gatt,
|
||||||
|
@IntRange(from = 23, to = 517) final int mtu, final int status) {
|
||||||
|
runOnUiThread(() -> onMtuChangedSafe(gatt, mtu, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
@Override
|
||||||
|
public final void onPhyRead(@NonNull final BluetoothGatt gatt,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy,
|
||||||
|
final int status) {
|
||||||
|
runOnUiThread(() -> onPhyReadSafe(gatt, txPhy, rxPhy, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
@Override
|
||||||
|
public final void onPhyUpdate(@NonNull final BluetoothGatt gatt,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy,
|
||||||
|
final int status) {
|
||||||
|
runOnUiThread(() -> onPhyUpdateSafe(gatt, txPhy, rxPhy, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is hidden in Android Oreo and Pie
|
||||||
|
// @Override
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||||
|
@Keep
|
||||||
|
public final void onConnectionUpdated(@NonNull final BluetoothGatt gatt,
|
||||||
|
@IntRange(from = 6, to = 3200) final int interval,
|
||||||
|
@IntRange(from = 0, to = 499) final int latency,
|
||||||
|
@IntRange(from = 10, to = 3200) final int timeout,
|
||||||
|
final int status) {
|
||||||
|
runOnUiThread(() -> onConnectionUpdatedSafe(gatt, interval, latency, timeout, status));
|
||||||
|
}
|
||||||
|
}
|
||||||
98
_android/src/no/nordicsemi/android/ble/MtuRequest.java
Normal file
98
_android/src/no/nordicsemi/android/ble/MtuRequest.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.MtuCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
public final class MtuRequest extends SimpleValueRequest<MtuCallback>implements Operation {
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
MtuRequest(@NonNull final Type type, @IntRange(from = 23, to = 517) int mtu) {
|
||||||
|
super(type);
|
||||||
|
if (mtu < 23)
|
||||||
|
mtu = 23;
|
||||||
|
if (mtu > 517)
|
||||||
|
mtu = 517;
|
||||||
|
this.value = mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
MtuRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public MtuRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public MtuRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public MtuRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public MtuRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public MtuRequest with(@NonNull final MtuCallback callback) {
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyMtuChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 23, to = 517) final int mtu) {
|
||||||
|
if (valueCallback != null)
|
||||||
|
valueCallback.onMtuChanged(device, mtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getRequiredMtu() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
32
_android/src/no/nordicsemi/android/ble/Operation.java
Normal file
32
_android/src/no/nordicsemi/android/ble/Operation.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An operation is a request that can be executed during a pending connection without
|
||||||
|
* changing connection state. Such requests may be added to {@link RequestQueue}.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public interface Operation {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
165
_android/src/no/nordicsemi/android/ble/PhyRequest.java
Normal file
165
_android/src/no/nordicsemi/android/ble/PhyRequest.java
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyMask;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyOption;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyValue;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.PhyCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public final class PhyRequest extends SimpleValueRequest<PhyCallback> implements Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
|
||||||
|
* options in a bitmask.
|
||||||
|
*/
|
||||||
|
public static final int PHY_LE_1M_MASK = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
|
||||||
|
* options in a bitmask.
|
||||||
|
*/
|
||||||
|
public static final int PHY_LE_2M_MASK = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
|
||||||
|
* available options in a bitmask.
|
||||||
|
*/
|
||||||
|
public static final int PHY_LE_CODED_MASK = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No preferred coding when transmitting on the LE Coded PHY.
|
||||||
|
*/
|
||||||
|
public static final int PHY_OPTION_NO_PREFERRED = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefer the S=2 coding to be used when transmitting on the LE Coded PHY.
|
||||||
|
*/
|
||||||
|
public static final int PHY_OPTION_S2 = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefer the S=8 coding to be used when transmitting on the LE Coded PHY.
|
||||||
|
*/
|
||||||
|
public static final int PHY_OPTION_S8 = 2;
|
||||||
|
|
||||||
|
private final int txPhy;
|
||||||
|
private final int rxPhy;
|
||||||
|
private final int phyOptions;
|
||||||
|
|
||||||
|
PhyRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
this.txPhy = 0;
|
||||||
|
this.rxPhy = 0;
|
||||||
|
this.phyOptions = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhyRequest(@NonNull final Type type,
|
||||||
|
@PhyMask int txPhy, @PhyMask int rxPhy, @PhyOption int phyOptions) {
|
||||||
|
super(type);
|
||||||
|
if ((txPhy & ~(PHY_LE_1M_MASK | PHY_LE_2M_MASK | PHY_LE_CODED_MASK)) > 0)
|
||||||
|
txPhy = PHY_LE_1M_MASK;
|
||||||
|
if ((rxPhy & ~(PHY_LE_1M_MASK | PHY_LE_2M_MASK | PHY_LE_CODED_MASK)) > 0)
|
||||||
|
rxPhy = PHY_LE_1M_MASK;
|
||||||
|
if (phyOptions < PHY_OPTION_NO_PREFERRED || phyOptions > PHY_OPTION_S8)
|
||||||
|
phyOptions = PHY_OPTION_NO_PREFERRED;
|
||||||
|
this.txPhy = txPhy;
|
||||||
|
this.rxPhy = rxPhy;
|
||||||
|
this.phyOptions = phyOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
PhyRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public PhyRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public PhyRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public PhyRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public PhyRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public PhyRequest with(@NonNull final PhyCallback callback) {
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyPhyChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy) {
|
||||||
|
if (valueCallback != null)
|
||||||
|
valueCallback.onPhyChanged(device, txPhy, rxPhy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyLegacyPhy(@NonNull final BluetoothDevice device) {
|
||||||
|
if (valueCallback != null)
|
||||||
|
valueCallback.onPhyChanged(device, PhyCallback.PHY_LE_1M, PhyCallback.PHY_LE_1M);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhyMask
|
||||||
|
int getPreferredTxPhy() {
|
||||||
|
return txPhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhyMask
|
||||||
|
int getPreferredRxPhy() {
|
||||||
|
return rxPhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhyOption
|
||||||
|
int getPreferredPhyOptions() {
|
||||||
|
return phyOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
249
_android/src/no/nordicsemi/android/ble/ReadRequest.java
Normal file
249
_android/src/no/nordicsemi/android/ble/ReadRequest.java
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataReceivedCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.ReadProgressCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.profile.ProfileReadResponse;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataFilter;
|
||||||
|
import no.nordicsemi.android.ble.data.DataMerger;
|
||||||
|
import no.nordicsemi.android.ble.data.DataStream;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidDataException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public final class ReadRequest extends SimpleValueRequest<DataReceivedCallback> implements Operation {
|
||||||
|
private ReadProgressCallback progressCallback;
|
||||||
|
private DataMerger dataMerger;
|
||||||
|
private DataStream buffer;
|
||||||
|
private DataFilter filter;
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
|
ReadRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadRequest(@NonNull final Type type, @Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadRequest(@NonNull final Type type, @Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
super(type, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
ReadRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ReadRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest with(@NonNull final DataReceivedCallback callback) {
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a filter which allows to skip some incoming data.
|
||||||
|
*
|
||||||
|
* @param filter the data filter.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest filter(@NonNull final DataFilter filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a merger that will be used to merge multiple packets into a single Data.
|
||||||
|
* The merger may modify each packet if necessary.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest merge(@NonNull final DataMerger merger) {
|
||||||
|
this.dataMerger = merger;
|
||||||
|
this.progressCallback = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a merger that will be used to merge multiple packets into a single Data.
|
||||||
|
* The merger may modify each packet if necessary.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ReadRequest merge(@NonNull final DataMerger merger,
|
||||||
|
@NonNull final ReadProgressCallback callback) {
|
||||||
|
this.dataMerger = merger;
|
||||||
|
this.progressCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #await(Class)}, but if the response class extends
|
||||||
|
* {@link ProfileReadResponse} and the received response is not valid
|
||||||
|
* ({@link ProfileReadResponse#isValid()} returns false), this method will
|
||||||
|
* throw an exception.
|
||||||
|
*
|
||||||
|
* @param responseClass the response class. This class will be instantiate, therefore it
|
||||||
|
* has to have a default constructor.
|
||||||
|
* @return The object with the response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws IllegalArgumentException thrown when the response class could not be instantiated.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidDataException thrown when the received data were not valid (that is when
|
||||||
|
* {@link ProfileReadResponse#onDataReceived(BluetoothDevice, Data)}
|
||||||
|
* failed to parse the data correctly and called
|
||||||
|
* {@link ProfileReadResponse#onInvalidDataReceived(BluetoothDevice, Data)}).
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public <E extends ProfileReadResponse> E awaitValid(@NonNull final Class<E> responseClass)
|
||||||
|
throws RequestFailedException, InvalidDataException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException {
|
||||||
|
final E response = await(responseClass);
|
||||||
|
if (!response.isValid()) {
|
||||||
|
throw new InvalidDataException(response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #await(Object)}, but if the response class extends
|
||||||
|
* {@link ProfileReadResponse} and the received response is not valid
|
||||||
|
* ({@link ProfileReadResponse#isValid()} returns false), this method will
|
||||||
|
* throw an exception.
|
||||||
|
*
|
||||||
|
* @param response the response object.
|
||||||
|
* @return The object with the response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidDataException thrown when the received data were not valid (that is when
|
||||||
|
* {@link ProfileReadResponse#onDataReceived(BluetoothDevice, Data)}
|
||||||
|
* failed to parse the data correctly and called
|
||||||
|
* {@link ProfileReadResponse#onInvalidDataReceived(BluetoothDevice, Data)}).
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public <E extends ProfileReadResponse> E awaitValid(@NonNull final E response)
|
||||||
|
throws RequestFailedException, InvalidDataException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException {
|
||||||
|
await(response);
|
||||||
|
if (!response.isValid()) {
|
||||||
|
throw new InvalidDataException(response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean matches(final byte[] packet) {
|
||||||
|
return filter == null || filter.filter(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyValueChanged(@NonNull final BluetoothDevice device, @Nullable final byte[] value) {
|
||||||
|
// Keep a reference to the value callback, as it may change during execution
|
||||||
|
final DataReceivedCallback valueCallback = this.valueCallback;
|
||||||
|
|
||||||
|
// With no value callback there is no need for any merging
|
||||||
|
if (valueCallback == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dataMerger == null) {
|
||||||
|
valueCallback.onDataReceived(device, new Data(value));
|
||||||
|
} else {
|
||||||
|
if (progressCallback != null)
|
||||||
|
progressCallback.onPacketReceived(device, value, count);
|
||||||
|
if (buffer == null)
|
||||||
|
buffer = new DataStream();
|
||||||
|
if (dataMerger.merge(buffer, value, count++)) {
|
||||||
|
valueCallback.onDataReceived(device, buffer.toData());
|
||||||
|
buffer = null;
|
||||||
|
count = 0;
|
||||||
|
} // else
|
||||||
|
// wait for more packets to be merged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasMore() {
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
88
_android/src/no/nordicsemi/android/ble/ReadRssiRequest.java
Normal file
88
_android/src/no/nordicsemi/android/ble/ReadRssiRequest.java
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.RssiCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
public final class ReadRssiRequest extends SimpleValueRequest<RssiCallback> implements Operation {
|
||||||
|
|
||||||
|
ReadRssiRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
ReadRssiRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRssiRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRssiRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ReadRssiRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRssiRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReadRssiRequest with(@NonNull final RssiCallback callback) {
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyRssiRead(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = -128, to = 20) final int rssi) {
|
||||||
|
if (valueCallback != null)
|
||||||
|
valueCallback.onRssiRead(device, rssi);
|
||||||
|
}
|
||||||
|
}
|
||||||
134
_android/src/no/nordicsemi/android/ble/ReliableWriteRequest.java
Normal file
134
_android/src/no/nordicsemi/android/ble/ReliableWriteRequest.java
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ReliableWriteRequest extends RequestQueue {
|
||||||
|
private boolean initialized;
|
||||||
|
private boolean closed;
|
||||||
|
private boolean cancelled;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
ReliableWriteRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReliableWriteRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReliableWriteRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ReliableWriteRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public ReliableWriteRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ReliableWriteRequest add(@NonNull final Operation operation) {
|
||||||
|
super.add(operation);
|
||||||
|
// Make sure the write request uses splitting, as Long Write is not supported
|
||||||
|
// in Reliable Write sub-procedure.
|
||||||
|
if (operation instanceof WriteRequest) {
|
||||||
|
((WriteRequest) operation).forceSplit();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelQueue() {
|
||||||
|
cancelled = true;
|
||||||
|
super.cancelQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link #cancelQueue()}.
|
||||||
|
*/
|
||||||
|
public void abort() {
|
||||||
|
cancelQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
int size = super.size();
|
||||||
|
|
||||||
|
// Add Begin Reliable Write
|
||||||
|
if (!initialized)
|
||||||
|
size += 1;
|
||||||
|
|
||||||
|
// Add Execute or Abort Reliable Write
|
||||||
|
if (!closed)
|
||||||
|
size += 1;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Request getNext() {
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = true;
|
||||||
|
return newBeginReliableWriteRequest();
|
||||||
|
}
|
||||||
|
if (super.isEmpty()) {
|
||||||
|
closed = true;
|
||||||
|
|
||||||
|
if (cancelled)
|
||||||
|
return newAbortReliableWriteRequest();
|
||||||
|
return newExecuteReliableWriteRequest();
|
||||||
|
}
|
||||||
|
return super.getNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean hasMore() {
|
||||||
|
// If no operations were added, consider the RW request empty, no requests will be executed.
|
||||||
|
if (!initialized)
|
||||||
|
return super.hasMore();
|
||||||
|
return !closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
896
_android/src/no/nordicsemi/android/ble/Request.java
Normal file
896
_android/src/no/nordicsemi/android/ble/Request.java
Normal file
@@ -0,0 +1,896 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCallback;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
import android.os.ConditionVariable;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.annotation.ConnectionPriority;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyMask;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyOption;
|
||||||
|
import no.nordicsemi.android.ble.annotation.WriteType;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Android, when multiple BLE operations needs to be done, it is required to wait for a proper
|
||||||
|
* {@link BluetoothGattCallback} callback before calling another operation.
|
||||||
|
* In order to make BLE operations easier the BleManager allows to enqueue a request containing all
|
||||||
|
* data necessary for a given operation. Requests are performed one after another until the queue
|
||||||
|
* is empty.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess", "deprecation", "DeprecatedIsStillUsed"})
|
||||||
|
public abstract class Request {
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
SET,
|
||||||
|
CONNECT,
|
||||||
|
DISCONNECT,
|
||||||
|
CREATE_BOND,
|
||||||
|
REMOVE_BOND,
|
||||||
|
WRITE,
|
||||||
|
READ,
|
||||||
|
WRITE_DESCRIPTOR,
|
||||||
|
READ_DESCRIPTOR,
|
||||||
|
BEGIN_RELIABLE_WRITE,
|
||||||
|
EXECUTE_RELIABLE_WRITE,
|
||||||
|
ABORT_RELIABLE_WRITE,
|
||||||
|
ENABLE_NOTIFICATIONS,
|
||||||
|
ENABLE_INDICATIONS,
|
||||||
|
DISABLE_NOTIFICATIONS,
|
||||||
|
DISABLE_INDICATIONS,
|
||||||
|
WAIT_FOR_NOTIFICATION,
|
||||||
|
WAIT_FOR_INDICATION,
|
||||||
|
@Deprecated
|
||||||
|
READ_BATTERY_LEVEL,
|
||||||
|
@Deprecated
|
||||||
|
ENABLE_BATTERY_LEVEL_NOTIFICATIONS,
|
||||||
|
@Deprecated
|
||||||
|
DISABLE_BATTERY_LEVEL_NOTIFICATIONS,
|
||||||
|
ENABLE_SERVICE_CHANGED_INDICATIONS,
|
||||||
|
REQUEST_MTU,
|
||||||
|
REQUEST_CONNECTION_PRIORITY,
|
||||||
|
SET_PREFERRED_PHY,
|
||||||
|
READ_PHY,
|
||||||
|
READ_RSSI,
|
||||||
|
REFRESH_CACHE,
|
||||||
|
SLEEP,
|
||||||
|
}
|
||||||
|
|
||||||
|
private BleManager manager;
|
||||||
|
|
||||||
|
final ConditionVariable syncLock;
|
||||||
|
final Type type;
|
||||||
|
final BluetoothGattCharacteristic characteristic;
|
||||||
|
final BluetoothGattDescriptor descriptor;
|
||||||
|
BeforeCallback beforeCallback;
|
||||||
|
SuccessCallback successCallback;
|
||||||
|
FailCallback failCallback;
|
||||||
|
InvalidRequestCallback invalidRequestCallback;
|
||||||
|
BeforeCallback internalBeforeCallback;
|
||||||
|
SuccessCallback internalSuccessCallback;
|
||||||
|
FailCallback internalFailCallback;
|
||||||
|
boolean enqueued;
|
||||||
|
boolean finished;
|
||||||
|
|
||||||
|
Request(@NonNull final Type type) {
|
||||||
|
this.type = type;
|
||||||
|
this.characteristic = null;
|
||||||
|
this.descriptor = null;
|
||||||
|
this.syncLock = new ConditionVariable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request(@NonNull final Type type, @Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
this.type = type;
|
||||||
|
this.characteristic = characteristic;
|
||||||
|
this.descriptor = null;
|
||||||
|
this.syncLock = new ConditionVariable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request(@NonNull final Type type, @Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
this.type = type;
|
||||||
|
this.characteristic = null;
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
this.syncLock = new ConditionVariable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link BleManager} instance.
|
||||||
|
*
|
||||||
|
* @param manager the manager in which the request will be executed.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
Request setManager(@NonNull final BleManager manager) {
|
||||||
|
this.manager = manager;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new connect request. This allows to set a callback to the connect event,
|
||||||
|
* just like any other request.
|
||||||
|
*
|
||||||
|
* @param device the device to connect to.
|
||||||
|
* @return The new connect request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static ConnectRequest connect(@NonNull final BluetoothDevice device) {
|
||||||
|
return new ConnectRequest(Type.CONNECT, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new disconnect request. This allows to set a callback to a disconnect event,
|
||||||
|
* just like any other request.
|
||||||
|
*
|
||||||
|
* @return The new disconnect request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static DisconnectRequest disconnect() {
|
||||||
|
return new DisconnectRequest(Type.DISCONNECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new request that will start pairing with the device.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#createBond()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static SimpleRequest createBond() {
|
||||||
|
return new SimpleRequest(Type.CREATE_BOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new request that will remove the bonding information from the Android device.
|
||||||
|
* This is done using reflections and may not work on all devices.
|
||||||
|
* <p>
|
||||||
|
* The device will disconnect after calling this method. The success callback will be called
|
||||||
|
* after the device got disconnected, when the {@link BluetoothDevice#getBondState()} changes
|
||||||
|
* to {@link BluetoothDevice#BOND_NONE}.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#removeBond()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static SimpleRequest removeBond() {
|
||||||
|
return new SimpleRequest(Type.REMOVE_BOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Read Characteristic request. The request will not be executed if given
|
||||||
|
* characteristic is null or does not have READ property.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to be read.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#readCharacteristic(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static ReadRequest newReadRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new ReadRequest(Type.READ, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Write Characteristic request. The request will not be executed if given
|
||||||
|
* characteristic is null or does not have WRITE property.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to be written.
|
||||||
|
* @param value value to be written. The array is copied into another buffer so it's
|
||||||
|
* safe to reuse the array again.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#writeCharacteristic(BluetoothGattCharacteristic, byte[])} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newWriteRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] value) {
|
||||||
|
return new WriteRequest(Type.WRITE, characteristic, value, 0,
|
||||||
|
value != null ? value.length : 0,
|
||||||
|
characteristic != null ?
|
||||||
|
characteristic.getWriteType() :
|
||||||
|
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Write Characteristic request. The request will not be executed if given
|
||||||
|
* characteristic is null or does not have WRITE property.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to be written.
|
||||||
|
* @param value value to be written. The array is copied into another buffer so it's
|
||||||
|
* safe to reuse the array again.
|
||||||
|
* @param writeType write type to be used, one of
|
||||||
|
* {@link BluetoothGattCharacteristic#WRITE_TYPE_DEFAULT},
|
||||||
|
* {@link BluetoothGattCharacteristic#WRITE_TYPE_NO_RESPONSE}.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#writeCharacteristic(BluetoothGattCharacteristic, Data)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newWriteRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] value, @WriteType final int writeType) {
|
||||||
|
return new WriteRequest(Type.WRITE, characteristic, value, 0,
|
||||||
|
value != null ? value.length : 0, writeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Write Characteristic request. The request will not be executed if given
|
||||||
|
* characteristic is null or does not have WRITE property.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to be written.
|
||||||
|
* @param value value to be written. The array is copied into another buffer so it's
|
||||||
|
* safe to reuse the array again.
|
||||||
|
* @param offset the offset from which value has to be copied.
|
||||||
|
* @param length number of bytes to be copied from the value buffer.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#writeCharacteristic(BluetoothGattCharacteristic, byte[], int, int)}
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newWriteRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] value,
|
||||||
|
@IntRange(from = 0) final int offset, @IntRange(from = 0) final int length) {
|
||||||
|
return new WriteRequest(Type.WRITE, characteristic, value, offset, length,
|
||||||
|
characteristic != null ?
|
||||||
|
characteristic.getWriteType() :
|
||||||
|
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Write Characteristic request. The request will not be executed if given
|
||||||
|
* characteristic is null or does not have WRITE property.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to be written.
|
||||||
|
* @param value value to be written. The array is copied into another buffer so it's
|
||||||
|
* safe to reuse the array again.
|
||||||
|
* @param offset the offset from which value has to be copied.
|
||||||
|
* @param length number of bytes to be copied from the value buffer.
|
||||||
|
* @param writeType write type to be used, one of
|
||||||
|
* {@link BluetoothGattCharacteristic#WRITE_TYPE_DEFAULT},
|
||||||
|
* {@link BluetoothGattCharacteristic#WRITE_TYPE_NO_RESPONSE} or
|
||||||
|
* {@link BluetoothGattCharacteristic#WRITE_TYPE_SIGNED}.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#writeCharacteristic(BluetoothGattCharacteristic, byte[], int, int)}
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newWriteRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] value,
|
||||||
|
@IntRange(from = 0) final int offset, @IntRange(from = 0) final int length,
|
||||||
|
@WriteType final int writeType) {
|
||||||
|
return new WriteRequest(Type.WRITE, characteristic, value, offset, length, writeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Read Descriptor request. The request will not be executed if given descriptor
|
||||||
|
* is null. After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param descriptor descriptor to be read.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#readDescriptor(BluetoothGattDescriptor)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static ReadRequest newReadRequest(@Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
return new ReadRequest(Type.READ_DESCRIPTOR, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Write Descriptor request. The request will not be executed if given descriptor
|
||||||
|
* is null. After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param descriptor descriptor to be written.
|
||||||
|
* @param value value to be written. The array is copied into another buffer so it's safe
|
||||||
|
* to reuse the array again.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#writeDescriptor(BluetoothGattDescriptor, byte[])} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newWriteRequest(@Nullable final BluetoothGattDescriptor descriptor,
|
||||||
|
@Nullable final byte[] value) {
|
||||||
|
return new WriteRequest(Type.WRITE_DESCRIPTOR, descriptor, value, 0,
|
||||||
|
value != null ? value.length : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Write Descriptor request. The request will not be executed if given descriptor
|
||||||
|
* is null. After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param descriptor descriptor to be written.
|
||||||
|
* @param value value to be written. The array is copied into another buffer so it's safe
|
||||||
|
* to reuse the array again.
|
||||||
|
* @param offset the offset from which value has to be copied.
|
||||||
|
* @param length number of bytes to be copied from the value buffer.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#writeDescriptor(BluetoothGattDescriptor, byte[], int, int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newWriteRequest(
|
||||||
|
@Nullable final BluetoothGattDescriptor descriptor,
|
||||||
|
@Nullable final byte[] value,
|
||||||
|
@IntRange(from = 0) final int offset, @IntRange(from = 0) final int length) {
|
||||||
|
return new WriteRequest(Type.WRITE_DESCRIPTOR, descriptor, value, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Reliable Write request. All operations that need to be executed
|
||||||
|
* reliably should be enqueued inside the returned request before enqueuing it in the
|
||||||
|
* BleManager. The library will automatically verify the data sent
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static ReliableWriteRequest newReliableWriteRequest() {
|
||||||
|
return new ReliableWriteRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Begin Reliable Write request.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static SimpleRequest newBeginReliableWriteRequest() {
|
||||||
|
return new SimpleRequest(Type.BEGIN_RELIABLE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes Reliable Write sub-procedure. At lease one Write Request must be performed
|
||||||
|
* before the Reliable Write is to be executed, otherwise error
|
||||||
|
* {@link no.nordicsemi.android.ble.error.GattError#GATT_INVALID_OFFSET} will be returned.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static SimpleRequest newExecuteReliableWriteRequest() {
|
||||||
|
return new SimpleRequest(Type.EXECUTE_RELIABLE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aborts Reliable Write sub-procedure. All write requests performed during Reliable Write will
|
||||||
|
* be cancelled. At lease one Write Request must be performed before the Reliable Write
|
||||||
|
* is to be executed, otherwise error
|
||||||
|
* {@link no.nordicsemi.android.ble.error.GattError#GATT_INVALID_OFFSET} will be returned.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static SimpleRequest newAbortReliableWriteRequest() {
|
||||||
|
return new SimpleRequest(Type.ABORT_RELIABLE_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Enable Notification request. The request will not be executed if given
|
||||||
|
* characteristic is null, does not have NOTIFY property or the CCCD.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to have notifications enabled.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#enableNotifications(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newEnableNotificationsRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new WriteRequest(Type.ENABLE_NOTIFICATIONS, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Disable Notification request. The request will not be executed if given
|
||||||
|
* characteristic is null, does not have NOTIFY property or the CCCD.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to have notifications disabled.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#disableNotifications(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newDisableNotificationsRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new WriteRequest(Type.DISABLE_NOTIFICATIONS, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Enable Indications request. The request will not be executed if given
|
||||||
|
* characteristic is null, does not have INDICATE property or the CCCD.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to have indications enabled.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#enableIndications(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newEnableIndicationsRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new WriteRequest(Type.ENABLE_INDICATIONS, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Disable Indications request. The request will not be executed if given
|
||||||
|
* characteristic is null, does not have INDICATE property or the CCCD.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic to have indications disabled.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#disableNotifications(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WriteRequest newDisableIndicationsRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new WriteRequest(Type.DISABLE_INDICATIONS, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Wait For Notification request. The request will not be executed if given
|
||||||
|
* characteristic is null, does not have NOTIFY property or the CCCD.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
* <p>
|
||||||
|
* If the notification should be triggered by another operation (for example writing an
|
||||||
|
* op code), set it with {@link WaitForValueChangedRequest#trigger(Operation)}.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic from which a notification should be received.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#waitForNotification(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WaitForValueChangedRequest newWaitForNotificationRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new WaitForValueChangedRequest(Type.WAIT_FOR_NOTIFICATION, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Wait For Indication request. The request will not be executed if given
|
||||||
|
* characteristic is null, does not have INDICATE property or the CCCD.
|
||||||
|
* After the operation is complete a proper callback will be invoked.
|
||||||
|
* <p>
|
||||||
|
* If the indication should be triggered by another operation (for example writing an
|
||||||
|
* op code), set it with {@link WaitForValueChangedRequest#trigger(Operation)}.
|
||||||
|
*
|
||||||
|
* @param characteristic characteristic from which a notification should be received.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#waitForIndication(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static WaitForValueChangedRequest newWaitForIndicationRequest(
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new WaitForValueChangedRequest(Type.WAIT_FOR_INDICATION, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Read Battery Level request. The first found Battery Level characteristic value
|
||||||
|
* from the first found Battery Service. If any of them is not found, or the characteristic
|
||||||
|
* does not have the READ property this operation will not execute.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Use {@link #newReadRequest(BluetoothGattCharacteristic)} with
|
||||||
|
* BatteryLevelDataCallback from Android BLE Common Library instead.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public static ReadRequest newReadBatteryLevelRequest() {
|
||||||
|
return new ReadRequest(Type.READ_BATTERY_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Enable Notifications on the first found Battery Level characteristic from the
|
||||||
|
* first found Battery Service. If any of them is not found, or the characteristic does not
|
||||||
|
* have the NOTIFY property this operation will not execute.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Use {@link #newEnableNotificationsRequest(BluetoothGattCharacteristic)} with
|
||||||
|
* BatteryLevelDataCallback from Android BLE Common Library instead.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public static WriteRequest newEnableBatteryLevelNotificationsRequest() {
|
||||||
|
return new WriteRequest(Type.ENABLE_BATTERY_LEVEL_NOTIFICATIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Disable Notifications on the first found Battery Level characteristic from the
|
||||||
|
* first found Battery Service. If any of them is not found, or the characteristic does not
|
||||||
|
* have the NOTIFY property this operation will not execute.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Use {@link #newDisableNotificationsRequest(BluetoothGattCharacteristic)} instead.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public static WriteRequest newDisableBatteryLevelNotificationsRequest() {
|
||||||
|
return new WriteRequest(Type.DISABLE_BATTERY_LEVEL_NOTIFICATIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Enable Indications on Service Changed characteristic. It is a NOOP if such
|
||||||
|
* characteristic does not exist in the Generic Attribute service.
|
||||||
|
* It is required to enable those notifications on bonded devices on older Android versions to
|
||||||
|
* be informed about attributes changes.
|
||||||
|
* Android 7+ (or 6+) handles this automatically and no action is required.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
static WriteRequest newEnableServiceChangedIndicationsRequest() {
|
||||||
|
return new WriteRequest(Type.ENABLE_SERVICE_CHANGED_INDICATIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests new MTU (Maximum Transfer Unit). This is only supported on Android Lollipop or newer.
|
||||||
|
* On older platforms the request will enqueue, but will fail to execute and
|
||||||
|
* {@link #fail(FailCallback)} callback will be called.
|
||||||
|
* The target device may reject requested value and set a smaller MTU.
|
||||||
|
*
|
||||||
|
* @param mtu the new MTU. Acceptable values are <23, 517>.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#requestMtu(int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static MtuRequest newMtuRequest(@IntRange(from = 23, to = 517) final int mtu) {
|
||||||
|
return new MtuRequest(Type.REQUEST_MTU, mtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the new connection priority. Acceptable values are:
|
||||||
|
* <ol>
|
||||||
|
* <li>{@link ConnectionPriorityRequest#CONNECTION_PRIORITY_HIGH}
|
||||||
|
* - Interval: 11.25 -15 ms (Android 6+) and 7.5 - 10 ms (older), latency: 0,
|
||||||
|
* supervision timeout: 20 sec,</li>
|
||||||
|
* <li>{@link ConnectionPriorityRequest#CONNECTION_PRIORITY_BALANCED}
|
||||||
|
* - Interval: 30 - 50 ms, latency: 0, supervision timeout: 20 sec,</li>
|
||||||
|
* <li>{@link ConnectionPriorityRequest#CONNECTION_PRIORITY_LOW_POWER}
|
||||||
|
* - Interval: 100 - 125 ms, latency: 2, supervision timeout: 20 sec.</li>
|
||||||
|
* </ol>
|
||||||
|
* Requesting connection priority is available on Android Lollipop or newer. On older
|
||||||
|
* platforms the request will enqueue, but will fail to execute and {@link #fail(FailCallback)}
|
||||||
|
* callback will be called.
|
||||||
|
*
|
||||||
|
* @param priority one of: {@link ConnectionPriorityRequest#CONNECTION_PRIORITY_HIGH},
|
||||||
|
* {@link ConnectionPriorityRequest#CONNECTION_PRIORITY_BALANCED},
|
||||||
|
* {@link ConnectionPriorityRequest#CONNECTION_PRIORITY_LOW_POWER}.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#requestConnectionPriority(int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static ConnectionPriorityRequest newConnectionPriorityRequest(
|
||||||
|
@ConnectionPriority final int priority) {
|
||||||
|
return new ConnectionPriorityRequest(Type.REQUEST_CONNECTION_PRIORITY, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the change of preferred PHY for this connections.
|
||||||
|
* <p>
|
||||||
|
* PHY LE 2M and PHY LE Coded are supported only on Android Oreo or newer.
|
||||||
|
* You may safely request other PHYs on older platforms, but the request will not be executed
|
||||||
|
* and you will get PHY LE 1M as TX and RX PHY in the callback.
|
||||||
|
*
|
||||||
|
* @param txPhy preferred transmitter PHY. Bitwise OR of any of
|
||||||
|
* {@link PhyRequest#PHY_LE_1M_MASK}, {@link PhyRequest#PHY_LE_2M_MASK},
|
||||||
|
* and {@link PhyRequest#PHY_LE_CODED_MASK}.
|
||||||
|
* @param rxPhy preferred receiver PHY. Bitwise OR of any of
|
||||||
|
* {@link PhyRequest#PHY_LE_1M_MASK}, {@link PhyRequest#PHY_LE_2M_MASK},
|
||||||
|
* and {@link PhyRequest#PHY_LE_CODED_MASK}.
|
||||||
|
* @param phyOptions preferred coding to use when transmitting on the LE Coded PHY. Can be one
|
||||||
|
* of {@link PhyRequest#PHY_OPTION_NO_PREFERRED},
|
||||||
|
* {@link PhyRequest#PHY_OPTION_S2} or {@link PhyRequest#PHY_OPTION_S8}.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#setPreferredPhy(int, int, int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static PhyRequest newSetPreferredPhyRequest(@PhyMask final int txPhy,
|
||||||
|
@PhyMask final int rxPhy,
|
||||||
|
@PhyOption final int phyOptions) {
|
||||||
|
return new PhyRequest(Type.SET_PREFERRED_PHY, txPhy, rxPhy, phyOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the current PHY for this connections.
|
||||||
|
* <p>
|
||||||
|
* PHY LE 2M and PHY LE Coded are supported only on Android Oreo or newer.
|
||||||
|
* You may safely read PHY on older platforms, but the request will not be executed
|
||||||
|
* and you will get PHY LE 1M as TX and RX PHY in the callback.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#readPhy()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static PhyRequest newReadPhyRequest() {
|
||||||
|
return new PhyRequest(Type.READ_PHY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the current RSSI (Received Signal Strength Indication).
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#readRssi()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static ReadRssiRequest newReadRssiRequest() {
|
||||||
|
return new ReadRssiRequest(Type.READ_RSSI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the device cache. As the {@link BluetoothGatt#refresh()} method is not in the
|
||||||
|
* public API (it's hidden, and on Android P it is on a light gray list) it is called
|
||||||
|
* using reflections and may be removed in some future Android release or on some devices.
|
||||||
|
* <p>
|
||||||
|
* There is no callback indicating when the cache has been cleared. This library assumes
|
||||||
|
* some time and waits. After the delay, it will start service discovery and clear the
|
||||||
|
* task queue. When the service discovery finishes, the
|
||||||
|
* {@link BleManager.BleManagerGattCallback#isRequiredServiceSupported(BluetoothGatt)} and
|
||||||
|
* {@link BleManager.BleManagerGattCallback#isOptionalServiceSupported(BluetoothGatt)} will
|
||||||
|
* be called and the initialization will be performed as if the device has just connected.
|
||||||
|
*
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#refreshDeviceCache()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@SuppressWarnings("JavadocReference")
|
||||||
|
@NonNull
|
||||||
|
public static SimpleRequest newRefreshCacheRequest() {
|
||||||
|
return new SimpleRequest(Type.REFRESH_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new Sleep request that will postpone next request for given number of milliseconds.
|
||||||
|
*
|
||||||
|
* @param delay the delay in milliseconds.
|
||||||
|
* @return The new request.
|
||||||
|
* @deprecated Access to this method will change to package-only.
|
||||||
|
* Use {@link BleManager#sleep(long)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@NonNull
|
||||||
|
public static SleepRequest newSleepRequest(@IntRange(from = 0) final long delay) {
|
||||||
|
return new SleepRequest(Type.SLEEP, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to set a completion callback. The callback will be invoked when the operation has
|
||||||
|
* finished successfully unless the request was executed synchronously, in which case this
|
||||||
|
* callback will be ignored.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Request done(@NonNull final SuccessCallback callback) {
|
||||||
|
this.successCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to set a callback that will be called in case the request has failed.
|
||||||
|
* If the target device wasn't set before executing this request
|
||||||
|
* ({@link BleManager#connect(BluetoothDevice)} was never called), the
|
||||||
|
* {@link #invalid(InvalidRequestCallback)} will be used instead, as the
|
||||||
|
* {@link BluetoothDevice} is not known.
|
||||||
|
* <p>
|
||||||
|
* This callback will be ignored if request was executed synchronously, in which case
|
||||||
|
* the error will be returned as an exception.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Request fail(@NonNull final FailCallback callback) {
|
||||||
|
this.failCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set internal callback what will be executed before the request is executed.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
*/
|
||||||
|
void internalBefore(@NonNull final BeforeCallback callback) {
|
||||||
|
this.internalBeforeCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set internal success callback. The callback will be notified in case the request
|
||||||
|
* has completed.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
*/
|
||||||
|
void internalSuccess(@NonNull final SuccessCallback callback) {
|
||||||
|
this.internalSuccessCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set internal fail callback. The callback will be notified in case the request
|
||||||
|
* has failed.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
*/
|
||||||
|
void internalFail(@NonNull final FailCallback callback) {
|
||||||
|
this.internalFailCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use to set a callback that will be called in case the request was invalid, for example
|
||||||
|
* called before the device was connected.
|
||||||
|
* This callback will be ignored if request was executed synchronously, in which case
|
||||||
|
* the error will be returned as an exception.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Request invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
this.invalidRequestCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a callback that will be executed before the execution of this operation starts.
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Request before(@NonNull final BeforeCallback callback) {
|
||||||
|
this.beforeCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues the request for asynchronous execution.
|
||||||
|
*/
|
||||||
|
public void enqueue() {
|
||||||
|
manager.enqueue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyStarted(@NonNull final BluetoothDevice device) {
|
||||||
|
if (beforeCallback != null)
|
||||||
|
beforeCallback.onRequestStarted(device);
|
||||||
|
if (internalBeforeCallback != null)
|
||||||
|
internalBeforeCallback.onRequestStarted(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifySuccess(@NonNull final BluetoothDevice device) {
|
||||||
|
if (!finished) {
|
||||||
|
finished = true;
|
||||||
|
|
||||||
|
if (successCallback != null)
|
||||||
|
successCallback.onRequestCompleted(device);
|
||||||
|
if (internalSuccessCallback != null)
|
||||||
|
internalSuccessCallback.onRequestCompleted(device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyFail(@NonNull final BluetoothDevice device, final int status) {
|
||||||
|
if (!finished) {
|
||||||
|
finished = true;
|
||||||
|
|
||||||
|
if (failCallback != null)
|
||||||
|
failCallback.onRequestFailed(device, status);
|
||||||
|
if (internalFailCallback != null)
|
||||||
|
internalFailCallback.onRequestFailed(device, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyInvalidRequest() {
|
||||||
|
if (!finished) {
|
||||||
|
finished = true;
|
||||||
|
|
||||||
|
if (invalidRequestCallback != null)
|
||||||
|
invalidRequestCallback.onInvalidRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that the synchronous method was not called from the UI thread.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException when called from a UI thread.
|
||||||
|
*/
|
||||||
|
static void assertNotMainThread() throws IllegalStateException {
|
||||||
|
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||||
|
throw new IllegalStateException("Cannot execute synchronous operation from the UI thread.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class RequestCallback implements SuccessCallback, FailCallback, InvalidRequestCallback {
|
||||||
|
final static int REASON_REQUEST_INVALID = -1000000;
|
||||||
|
int status = BluetoothGatt.GATT_SUCCESS;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestCompleted(@NonNull final BluetoothDevice device) {
|
||||||
|
syncLock.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestFailed(@NonNull final BluetoothDevice device, final int status) {
|
||||||
|
this.status = status;
|
||||||
|
syncLock.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidRequest() {
|
||||||
|
this.status = REASON_REQUEST_INVALID;
|
||||||
|
syncLock.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
|
boolean isSuccess() {
|
||||||
|
return this.status == BluetoothGatt.GATT_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
164
_android/src/no/nordicsemi/android/ble/RequestQueue.java
Normal file
164
_android/src/no/nordicsemi/android/ble/RequestQueue.java
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class RequestQueue extends SimpleRequest {
|
||||||
|
/**
|
||||||
|
* A list of operations that will be executed together.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private final Queue<Request> requests;
|
||||||
|
|
||||||
|
RequestQueue() {
|
||||||
|
super(Type.SET);
|
||||||
|
requests = new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
RequestQueue setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public RequestQueue done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public RequestQueue fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public RequestQueue invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public RequestQueue before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues a new operation. All operations will be executed sequentially in order they were
|
||||||
|
* added.
|
||||||
|
*
|
||||||
|
* @param operation the new operation to be enqueued.
|
||||||
|
* @throws IllegalStateException if the operation was enqueued before.
|
||||||
|
* @throws IllegalArgumentException if the operation is not a {@link Request}.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public RequestQueue add(@NonNull final Operation operation) {
|
||||||
|
if (operation instanceof Request) {
|
||||||
|
final Request request = (Request) operation;
|
||||||
|
// Validate
|
||||||
|
if (request.enqueued)
|
||||||
|
throw new IllegalStateException("Request already enqueued");
|
||||||
|
// Add
|
||||||
|
requests.add(request);
|
||||||
|
// Mark
|
||||||
|
request.enqueued = true;
|
||||||
|
return this;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Operation does not extend Request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of enqueued operations.
|
||||||
|
*
|
||||||
|
* @return the size of the internal operations list.
|
||||||
|
*/
|
||||||
|
@IntRange(from = 0)
|
||||||
|
public int size() {
|
||||||
|
return requests.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the set is empty, or not.
|
||||||
|
*
|
||||||
|
* @return true if the set is empty. Set gets emptied while it all enqueued operations
|
||||||
|
* are being executed.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return requests.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels all the enqueued operations that were not executed yet.
|
||||||
|
* The one currently executed will be finished.
|
||||||
|
* <p>
|
||||||
|
* It is safe to call this method in {@link Request#done(SuccessCallback)} or
|
||||||
|
* {@link Request#fail(FailCallback)} callback;
|
||||||
|
*/
|
||||||
|
public void cancelQueue() {
|
||||||
|
requests.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next {@link Request} to be enqueued.
|
||||||
|
*
|
||||||
|
* @return the next request.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Request getNext() {
|
||||||
|
try {
|
||||||
|
return requests.remove();
|
||||||
|
// poll() may also throw an exception
|
||||||
|
// See: https://github.com/NordicSemiconductor/Android-BLE-Library/issues/37
|
||||||
|
} catch (final Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether there are more operations to be executed.
|
||||||
|
*
|
||||||
|
* @return true, if not all operations were completed.
|
||||||
|
*/
|
||||||
|
boolean hasMore() {
|
||||||
|
return !requests.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
106
_android/src/no/nordicsemi/android/ble/SimpleRequest.java
Normal file
106
_android/src/no/nordicsemi/android/ble/SimpleRequest.java
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A request that requires a {@link android.bluetooth.BluetoothGattCallback callback} or can't
|
||||||
|
* have timeout for any other reason. This class defines the {@link #await()} method.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class SimpleRequest extends Request {
|
||||||
|
|
||||||
|
SimpleRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
super(type, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)}
|
||||||
|
* will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
*/
|
||||||
|
public final void await() throws RequestFailedException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
final SuccessCallback sc = successCallback;
|
||||||
|
final FailCallback fc = failCallback;
|
||||||
|
try {
|
||||||
|
syncLock.close();
|
||||||
|
final RequestCallback callback = new RequestCallback();
|
||||||
|
done(callback).fail(callback).invalid(callback).enqueue();
|
||||||
|
|
||||||
|
syncLock.block();
|
||||||
|
if (!callback.isSuccess()) {
|
||||||
|
if (callback.status == FailCallback.REASON_DEVICE_DISCONNECTED) {
|
||||||
|
throw new DeviceDisconnectedException();
|
||||||
|
}
|
||||||
|
if (callback.status == FailCallback.REASON_BLUETOOTH_DISABLED) {
|
||||||
|
throw new BluetoothDisabledException();
|
||||||
|
}
|
||||||
|
if (callback.status == RequestCallback.REASON_REQUEST_INVALID) {
|
||||||
|
throw new InvalidRequestException(this);
|
||||||
|
}
|
||||||
|
throw new RequestFailedException(this, callback.status);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
successCallback = sc;
|
||||||
|
failCallback = fc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
152
_android/src/no/nordicsemi/android/ble/SimpleValueRequest.java
Normal file
152
_android/src/no/nordicsemi/android/ble/SimpleValueRequest.java
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value request that requires a {@link android.bluetooth.BluetoothGattCallback callback} or
|
||||||
|
* can't have timeout for any other reason. This class defines the {@link #await()} methods.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public abstract class SimpleValueRequest<T> extends SimpleRequest {
|
||||||
|
T valueCallback;
|
||||||
|
|
||||||
|
SimpleValueRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleValueRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleValueRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
super(type, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value callback. When the request is invoked synchronously, this callback will
|
||||||
|
* be ignored and the received value will be returned by the <code>await(...)</code> method;
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public SimpleValueRequest<T> with(@NonNull final T callback) {
|
||||||
|
this.valueCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done. The given response object will be filled
|
||||||
|
* with the request response.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)} and
|
||||||
|
* {@link #with(T)} will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param response the response object.
|
||||||
|
* @param <E> a response class.
|
||||||
|
* @return The response with a response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter is disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @see #await(Class)
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public <E extends T> E await(@NonNull final E response)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
final T vc = valueCallback;
|
||||||
|
try {
|
||||||
|
with(response).await();
|
||||||
|
return response;
|
||||||
|
} finally {
|
||||||
|
valueCallback = vc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)} and
|
||||||
|
* {@link #with(T)} will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param responseClass the response class. This class will be instantiate, therefore it has
|
||||||
|
* to have a default constructor.
|
||||||
|
* @return The response with a response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws IllegalArgumentException thrown when the response class could not be instantiated.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter is disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @see #await(Object)
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public <E extends T> E await(@NonNull final Class<E> responseClass)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final E response = responseClass.newInstance();
|
||||||
|
return await(response);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException("Couldn't instantiate "
|
||||||
|
+ responseClass.getCanonicalName()
|
||||||
|
+ " class. Is the default constructor accessible?");
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalArgumentException("Couldn't instantiate "
|
||||||
|
+ responseClass.getCanonicalName()
|
||||||
|
+ " class. Does it have a default constructor with no arguments?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
79
_android/src/no/nordicsemi/android/ble/SleepRequest.java
Normal file
79
_android/src/no/nordicsemi/android/ble/SleepRequest.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public final class SleepRequest extends SimpleRequest implements Operation {
|
||||||
|
private long delay;
|
||||||
|
|
||||||
|
SleepRequest(@NonNull final Type type, @IntRange(from = 0) final long delay) {
|
||||||
|
super(type);
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
SleepRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public SleepRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public SleepRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public SleepRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public SleepRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getDelay() {
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
_android/src/no/nordicsemi/android/ble/TimeoutHandler.java
Normal file
13
_android/src/no/nordicsemi/android/ble/TimeoutHandler.java
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
abstract class TimeoutHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when the request timed out.
|
||||||
|
*
|
||||||
|
* @param request the request that timed out.
|
||||||
|
*/
|
||||||
|
abstract void onRequestTimeout(@NonNull final TimeoutableRequest request);
|
||||||
|
}
|
||||||
222
_android/src/no/nordicsemi/android/ble/TimeoutableRequest.java
Normal file
222
_android/src/no/nordicsemi/android/ble/TimeoutableRequest.java
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
import android.os.Handler;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public abstract class TimeoutableRequest extends Request {
|
||||||
|
private TimeoutHandler timeoutHandler;
|
||||||
|
private Runnable timeoutCallback;
|
||||||
|
private Handler handler;
|
||||||
|
protected long timeout;
|
||||||
|
|
||||||
|
TimeoutableRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeoutableRequest(@NonNull final Type type, @Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeoutableRequest(@NonNull final Type type, @Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
super(type, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
TimeoutableRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
this.handler = manager.mHandler;
|
||||||
|
this.timeoutHandler = manager;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the operation timeout.
|
||||||
|
* When the timeout occurs, the request will fail with {@link FailCallback#REASON_TIMEOUT}.
|
||||||
|
*
|
||||||
|
* @param timeout the request timeout in milliseconds, 0 to disable timeout.
|
||||||
|
* @return the callback.
|
||||||
|
* @throws IllegalStateException thrown when the request has already been started.
|
||||||
|
* @throws UnsupportedOperationException thrown when the timeout is not allowed for this request,
|
||||||
|
* as the callback from the system is required.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public TimeoutableRequest timeout(@IntRange(from = 0) final long timeout) {
|
||||||
|
if (timeoutCallback != null)
|
||||||
|
throw new IllegalStateException("Request already started");
|
||||||
|
this.timeout = timeout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues the request for asynchronous execution.
|
||||||
|
* <p>
|
||||||
|
* Use {@link #timeout(long)} to set the maximum time the manager should wait until the device
|
||||||
|
* is ready. When the timeout occurs, the request will fail with
|
||||||
|
* {@link FailCallback#REASON_TIMEOUT} and the device will get disconnected.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final void enqueue() {
|
||||||
|
super.enqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues the request for asynchronous execution.
|
||||||
|
* <p>
|
||||||
|
* When the timeout occurs, the request will fail with {@link FailCallback#REASON_TIMEOUT}
|
||||||
|
* and the device will get disconnected.
|
||||||
|
*
|
||||||
|
* @param timeout the request timeout in milliseconds, 0 to disable timeout. This value will
|
||||||
|
* override one set in {@link #timeout(long)}.
|
||||||
|
* @deprecated Use {@link #timeout(long)} and {@link #enqueue()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public final void enqueue(@IntRange(from = 0) final long timeout) {
|
||||||
|
timeout(timeout).enqueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done.
|
||||||
|
* <p>
|
||||||
|
* Use {@link #timeout(long)} to set the maximum time the manager should wait until the request
|
||||||
|
* is ready. When the timeout occurs, the {@link InterruptedException} will be thrown.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)}
|
||||||
|
* will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws InterruptedException thrown if the timeout occurred before the request has
|
||||||
|
* finished.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @see #enqueue()
|
||||||
|
*/
|
||||||
|
public final void await() throws RequestFailedException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException, InterruptedException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
final SuccessCallback sc = successCallback;
|
||||||
|
final FailCallback fc = failCallback;
|
||||||
|
try {
|
||||||
|
syncLock.close();
|
||||||
|
final RequestCallback callback = new RequestCallback();
|
||||||
|
done(callback).fail(callback).invalid(callback).enqueue();
|
||||||
|
|
||||||
|
if (!syncLock.block(timeout)) {
|
||||||
|
throw new InterruptedException();
|
||||||
|
}
|
||||||
|
if (!callback.isSuccess()) {
|
||||||
|
if (callback.status == FailCallback.REASON_DEVICE_DISCONNECTED) {
|
||||||
|
throw new DeviceDisconnectedException();
|
||||||
|
}
|
||||||
|
if (callback.status == FailCallback.REASON_BLUETOOTH_DISABLED) {
|
||||||
|
throw new BluetoothDisabledException();
|
||||||
|
}
|
||||||
|
if (callback.status == RequestCallback.REASON_REQUEST_INVALID) {
|
||||||
|
throw new InvalidRequestException(this);
|
||||||
|
}
|
||||||
|
throw new RequestFailedException(this, callback.status);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
successCallback = sc;
|
||||||
|
failCallback = fc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits, for as most as the given number of milliseconds, until the request
|
||||||
|
* is ready.
|
||||||
|
* <p>
|
||||||
|
* When the timeout occurs, the {@link InterruptedException} will be thrown.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)}
|
||||||
|
* will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param timeout optional timeout in milliseconds, 0 to disable timeout. This will
|
||||||
|
* override the timeout set using {@link #timeout(long)}.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws InterruptedException thrown if the timeout occurred before the request has
|
||||||
|
* finished.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @deprecated Use {@link #timeout(long)} and {@link #await()} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public final void await(@IntRange(from = 0) final long timeout) throws RequestFailedException,
|
||||||
|
InterruptedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException {
|
||||||
|
timeout(timeout).await();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void notifyStarted(@NonNull final BluetoothDevice device) {
|
||||||
|
if (timeout > 0L) {
|
||||||
|
timeoutCallback = () -> {
|
||||||
|
timeoutCallback = null;
|
||||||
|
if (!finished) {
|
||||||
|
notifyFail(device, FailCallback.REASON_TIMEOUT);
|
||||||
|
timeoutHandler.onRequestTimeout(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
handler.postDelayed(timeoutCallback, timeout);
|
||||||
|
}
|
||||||
|
super.notifyStarted(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void notifySuccess(@NonNull final BluetoothDevice device) {
|
||||||
|
if (!finished) {
|
||||||
|
handler.removeCallbacks(timeoutCallback);
|
||||||
|
timeoutCallback = null;
|
||||||
|
}
|
||||||
|
super.notifySuccess(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void notifyFail(@NonNull final BluetoothDevice device, final int status) {
|
||||||
|
if (!finished) {
|
||||||
|
handler.removeCallbacks(timeoutCallback);
|
||||||
|
timeoutCallback = null;
|
||||||
|
}
|
||||||
|
super.notifyFail(device, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void notifyInvalidRequest() {
|
||||||
|
if (!finished) {
|
||||||
|
handler.removeCallbacks(timeoutCallback);
|
||||||
|
timeoutCallback = null;
|
||||||
|
}
|
||||||
|
super.notifyInvalidRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A value request that requires a {@link android.bluetooth.BluetoothGattCallback callback} or
|
||||||
|
* can't have timeout for any other reason. This class defines the {@link #await()} methods.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public abstract class TimeoutableValueRequest<T> extends TimeoutableRequest {
|
||||||
|
T valueCallback;
|
||||||
|
|
||||||
|
TimeoutableValueRequest(@NonNull final Type type) {
|
||||||
|
super(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeoutableValueRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeoutableValueRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattDescriptor descriptor) {
|
||||||
|
super(type, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public TimeoutableValueRequest<T> timeout(@IntRange(from = 0) final long timeout) {
|
||||||
|
super.timeout(timeout);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value callback. When the request is invoked synchronously, this callback will
|
||||||
|
* be ignored and the received value will be returned by the <code>await(...)</code> method;
|
||||||
|
*
|
||||||
|
* @param callback the callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public TimeoutableValueRequest<T> with(@NonNull final T callback) {
|
||||||
|
this.valueCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done.
|
||||||
|
* <p>
|
||||||
|
* When the timeout, set with {@link #timeout(long)} occurs, the {@link InterruptedException}
|
||||||
|
* will be thrown.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)} and
|
||||||
|
* {@link #with(E)} will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param response the response object.
|
||||||
|
* @param <E> a response class.
|
||||||
|
* @return The response with a response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws InterruptedException thrown if the timeout occurred before the request has
|
||||||
|
* finished.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread, or when the trigger was already enqueued.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter is disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public <E extends T> E await(@NonNull final E response)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException, InterruptedException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
final T vc = valueCallback;
|
||||||
|
try {
|
||||||
|
with(response).await();
|
||||||
|
return response;
|
||||||
|
} finally {
|
||||||
|
valueCallback = vc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)} and {@link #fail(FailCallback)} and
|
||||||
|
* {@link #with(T)} will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param responseClass the response class. This class will be instantiate, therefore it has
|
||||||
|
* to have a default constructor.
|
||||||
|
* @return The response with a response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws InterruptedException thrown if the timeout occurred before the request has
|
||||||
|
* finished.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws IllegalArgumentException thrown when the response class could not be instantiated.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter is disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @see #await(Object)
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public <E extends T> E await(@NonNull final Class<E> responseClass)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException, InterruptedException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
try {
|
||||||
|
final E response = responseClass.newInstance();
|
||||||
|
return await(response);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalArgumentException("Couldn't instantiate "
|
||||||
|
+ responseClass.getCanonicalName()
|
||||||
|
+ " class. Is the default constructor accessible?");
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new IllegalArgumentException("Couldn't instantiate "
|
||||||
|
+ responseClass.getCanonicalName()
|
||||||
|
+ " class. Does it have a default constructor with no arguments?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done, for at most given number of milliseconds
|
||||||
|
* after which the {@link InterruptedException} will be thrown.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)}, {@link #fail(FailCallback)} and
|
||||||
|
* {@link #with(E)} will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param responseClass the response class. This class will be instantiate, therefore it has
|
||||||
|
* to have a default constructor.
|
||||||
|
* @param timeout optional timeout in milliseconds. This value will override one set
|
||||||
|
* in {@link #timeout(long)}.
|
||||||
|
* @param <E> a response class that extends {@link T}.
|
||||||
|
* @return The object with a response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws InterruptedException thrown if the timeout occurred before the request has
|
||||||
|
* finished.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws IllegalArgumentException thrown when the response class could not be instantiated.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter is disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @deprecated Use {@link #timeout(long)} and {@link #await(Class)} instead.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public <E extends T> E await(@NonNull final Class<E> responseClass,
|
||||||
|
@IntRange(from = 0) final long timeout)
|
||||||
|
throws RequestFailedException, InterruptedException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException {
|
||||||
|
return timeout(timeout).await(responseClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously waits until the request is done, for at most given number of milliseconds
|
||||||
|
* after which the {@link InterruptedException} will be thrown.
|
||||||
|
* <p>
|
||||||
|
* Callbacks set using {@link #done(SuccessCallback)}, {@link #fail(FailCallback)} and
|
||||||
|
* {@link #with(E)} will be ignored.
|
||||||
|
* <p>
|
||||||
|
* This method may not be called from the main (UI) thread.
|
||||||
|
*
|
||||||
|
* @param response the response object.
|
||||||
|
* @param timeout optional timeout in milliseconds.
|
||||||
|
* @param <E> a response class that extends {@link T}.
|
||||||
|
* @return The object with a response.
|
||||||
|
* @throws RequestFailedException thrown when the BLE request finished with status other
|
||||||
|
* than {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
* @throws InterruptedException thrown if the timeout occurred before the request has
|
||||||
|
* finished.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from the main
|
||||||
|
* (UI) thread.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the request
|
||||||
|
* was completed.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter is disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @deprecated Use {@link #timeout(long)} and {@link #await(E)} instead.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public <E extends T> E await(@NonNull final E response,
|
||||||
|
@IntRange(from = 0) final long timeout)
|
||||||
|
throws RequestFailedException, InterruptedException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException {
|
||||||
|
return timeout(timeout).await(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
137
_android/src/no/nordicsemi/android/ble/ValueChangedCallback.java
Normal file
137
_android/src/no/nordicsemi/android/ble/ValueChangedCallback.java
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataReceivedCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.ReadProgressCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataFilter;
|
||||||
|
import no.nordicsemi.android.ble.data.DataMerger;
|
||||||
|
import no.nordicsemi.android.ble.data.DataStream;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess", "UnusedReturnValue"})
|
||||||
|
public class ValueChangedCallback {
|
||||||
|
private ReadProgressCallback progressCallback;
|
||||||
|
private DataReceivedCallback valueCallback;
|
||||||
|
private DataMerger dataMerger;
|
||||||
|
private DataStream buffer;
|
||||||
|
private DataFilter filter;
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
|
ValueChangedCallback() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the asynchronous data callback that will be called whenever a notification or
|
||||||
|
* an indication is received on given characteristic.
|
||||||
|
*
|
||||||
|
* @param callback the data callback.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ValueChangedCallback with(@NonNull final DataReceivedCallback callback) {
|
||||||
|
this.valueCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a filter which allows to skip some incoming data.
|
||||||
|
*
|
||||||
|
* @param filter the data filter.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ValueChangedCallback filter(@NonNull final DataFilter filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a merger that will be used to merge multiple packets into a single Data.
|
||||||
|
* The merger may modify each packet if necessary.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ValueChangedCallback merge(@NonNull final DataMerger merger) {
|
||||||
|
this.dataMerger = merger;
|
||||||
|
this.progressCallback = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a merger that will be used to merge multiple packets into a single Data.
|
||||||
|
* The merger may modify each packet if necessary.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public ValueChangedCallback merge(@NonNull final DataMerger merger,
|
||||||
|
@NonNull final ReadProgressCallback callback) {
|
||||||
|
this.dataMerger = merger;
|
||||||
|
this.progressCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueChangedCallback free() {
|
||||||
|
valueCallback = null;
|
||||||
|
dataMerger = null;
|
||||||
|
progressCallback = null;
|
||||||
|
buffer = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean matches(final byte[] packet) {
|
||||||
|
return filter == null || filter.filter(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyValueChanged(@NonNull final BluetoothDevice device, @Nullable final byte[] value) {
|
||||||
|
// Keep a reference to the value callback, as it may change during execution
|
||||||
|
final DataReceivedCallback valueCallback = this.valueCallback;
|
||||||
|
|
||||||
|
// With no value callback there is no need for any merging
|
||||||
|
if (valueCallback == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataMerger == null) {
|
||||||
|
valueCallback.onDataReceived(device, new Data(value));
|
||||||
|
} else {
|
||||||
|
if (progressCallback != null)
|
||||||
|
progressCallback.onPacketReceived(device, value, count);
|
||||||
|
if (buffer == null)
|
||||||
|
buffer = new DataStream();
|
||||||
|
if (dataMerger.merge(buffer, value, count++)) {
|
||||||
|
valueCallback.onDataReceived(device, buffer.toData());
|
||||||
|
buffer = null;
|
||||||
|
count = 0;
|
||||||
|
} // else
|
||||||
|
// wait for more packets to be merged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,400 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataReceivedCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.ReadProgressCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.profile.ProfileReadResponse;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataFilter;
|
||||||
|
import no.nordicsemi.android.ble.data.DataMerger;
|
||||||
|
import no.nordicsemi.android.ble.data.DataStream;
|
||||||
|
import no.nordicsemi.android.ble.exception.BluetoothDisabledException;
|
||||||
|
import no.nordicsemi.android.ble.exception.DeviceDisconnectedException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidDataException;
|
||||||
|
import no.nordicsemi.android.ble.exception.InvalidRequestException;
|
||||||
|
import no.nordicsemi.android.ble.exception.RequestFailedException;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public final class WaitForValueChangedRequest extends TimeoutableValueRequest<DataReceivedCallback>
|
||||||
|
implements Operation {
|
||||||
|
static final int NOT_STARTED = -123456;
|
||||||
|
static final int STARTED = NOT_STARTED + 1;
|
||||||
|
|
||||||
|
private ReadProgressCallback progressCallback;
|
||||||
|
private DataMerger dataMerger;
|
||||||
|
private DataStream buffer;
|
||||||
|
private DataFilter filter;
|
||||||
|
private Request trigger;
|
||||||
|
private boolean deviceDisconnected;
|
||||||
|
private boolean bluetoothDisabled;
|
||||||
|
private int triggerStatus = BluetoothGatt.GATT_SUCCESS;
|
||||||
|
private int count = 0;
|
||||||
|
|
||||||
|
WaitForValueChangedRequest(@NonNull final Type type,
|
||||||
|
@Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
WaitForValueChangedRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public WaitForValueChangedRequest timeout(@IntRange(from = 0) final long timeout) {
|
||||||
|
super.timeout(timeout);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public WaitForValueChangedRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public WaitForValueChangedRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public WaitForValueChangedRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public WaitForValueChangedRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public WaitForValueChangedRequest with(@NonNull final DataReceivedCallback callback) {
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a filter which allows to skip some incoming data.
|
||||||
|
*
|
||||||
|
* @param filter the data filter.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WaitForValueChangedRequest filter(@NonNull final DataFilter filter) {
|
||||||
|
this.filter = filter;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a merger that will be used to merge multiple packets into a single Data.
|
||||||
|
* The merger may modify each packet if necessary.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WaitForValueChangedRequest merge(@NonNull final DataMerger merger) {
|
||||||
|
this.dataMerger = merger;
|
||||||
|
this.progressCallback = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a merger that will be used to merge multiple packets into a single Data.
|
||||||
|
* The merger may modify each packet if necessary.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WaitForValueChangedRequest merge(@NonNull final DataMerger merger,
|
||||||
|
@NonNull final ReadProgressCallback callback) {
|
||||||
|
this.dataMerger = merger;
|
||||||
|
this.progressCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an optional request that is suppose to trigger the notification or indication.
|
||||||
|
* This is to ensure that the characteristic value won't change before the callback was set.
|
||||||
|
*
|
||||||
|
* @param trigger the operation that triggers the notification, usually a write characteristic
|
||||||
|
* request that write some OP CODE.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WaitForValueChangedRequest trigger(@NonNull final Operation trigger) {
|
||||||
|
if (trigger instanceof Request) {
|
||||||
|
this.trigger = (Request) trigger;
|
||||||
|
this.triggerStatus = NOT_STARTED;
|
||||||
|
// The trigger will never receive invalid request event.
|
||||||
|
// If the BluetoothDevice wasn't set, the whole WaitForValueChangedRequest would be invalid.
|
||||||
|
/*this.trigger.invalid(() -> {
|
||||||
|
// never called
|
||||||
|
});*/
|
||||||
|
this.trigger.internalBefore(device -> triggerStatus = STARTED);
|
||||||
|
this.trigger.internalSuccess(device -> triggerStatus = BluetoothGatt.GATT_SUCCESS);
|
||||||
|
this.trigger.internalFail((device, status) -> {
|
||||||
|
triggerStatus = status;
|
||||||
|
syncLock.open();
|
||||||
|
notifyFail(device, status);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public <E extends DataReceivedCallback> E await(@NonNull final E response)
|
||||||
|
throws RequestFailedException, DeviceDisconnectedException, BluetoothDisabledException,
|
||||||
|
InvalidRequestException, InterruptedException {
|
||||||
|
assertNotMainThread();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Ensure the trigger request it enqueued after the callback has been set.
|
||||||
|
if (trigger != null && trigger.enqueued) {
|
||||||
|
throw new IllegalStateException("Trigger request already enqueued");
|
||||||
|
}
|
||||||
|
super.await(response);
|
||||||
|
return response;
|
||||||
|
} catch (final RequestFailedException e) {
|
||||||
|
if (triggerStatus != BluetoothGatt.GATT_SUCCESS) {
|
||||||
|
// Trigger will never have invalid request status. The outer request will.
|
||||||
|
/*if (triggerStatus == RequestCallback.REASON_REQUEST_INVALID) {
|
||||||
|
throw new InvalidRequestException(trigger);
|
||||||
|
}*/
|
||||||
|
throw new RequestFailedException(trigger, triggerStatus);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link #await(Class)}, but if the response class extends
|
||||||
|
* {@link ProfileReadResponse} and the received response is invalid, an exception is thrown.
|
||||||
|
* This allows to keep all error handling in one place.
|
||||||
|
*
|
||||||
|
* @param response the result object.
|
||||||
|
* @param <E> a response class that extends {@link ProfileReadResponse}.
|
||||||
|
* @return Object with a valid response.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from
|
||||||
|
* the main (UI) thread.
|
||||||
|
* @throws InterruptedException thrown when the timeout occurred before the
|
||||||
|
* characteristic value has changed.
|
||||||
|
* @throws RequestFailedException thrown when the trigger request has failed.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the
|
||||||
|
* notification or indication was received.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @throws InvalidDataException thrown when the received data were not valid (that is when
|
||||||
|
* {@link ProfileReadResponse#onDataReceived(BluetoothDevice, Data)}
|
||||||
|
* failed to parse the data correctly and called
|
||||||
|
* {@link ProfileReadResponse#onInvalidDataReceived(BluetoothDevice, Data)}).
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@NonNull
|
||||||
|
public <E extends ProfileReadResponse> E awaitValid(@NonNull final E response)
|
||||||
|
throws RequestFailedException, InvalidDataException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException, InterruptedException {
|
||||||
|
final E result = await(response);
|
||||||
|
if (result != null && !result.isValid()) {
|
||||||
|
throw new InvalidDataException(result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to {@link #await(DataReceivedCallback)}, but if the response class extends
|
||||||
|
* {@link ProfileReadResponse} and the received response is invalid, an exception is thrown.
|
||||||
|
* This allows to keep all error handling in one place.
|
||||||
|
*
|
||||||
|
* @param responseClass the result class. This class will be instantiate, therefore it
|
||||||
|
* has to have a default constructor.
|
||||||
|
* @param <E> a response class that extends {@link ProfileReadResponse}.
|
||||||
|
* @return Object with a valid response.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from
|
||||||
|
* the main (UI) thread.
|
||||||
|
* @throws InterruptedException thrown when the timeout occurred before the
|
||||||
|
* characteristic value has changed.
|
||||||
|
* @throws IllegalArgumentException thrown when the response class could not be instantiated.
|
||||||
|
* @throws RequestFailedException thrown when the trigger request has failed.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the
|
||||||
|
* notification or indication was received.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @throws InvalidDataException thrown when the received data were not valid (that is when
|
||||||
|
* {@link ProfileReadResponse#onDataReceived(BluetoothDevice, Data)}
|
||||||
|
* failed to parse the data correctly and called
|
||||||
|
* {@link ProfileReadResponse#onInvalidDataReceived(BluetoothDevice, Data)}).
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@NonNull
|
||||||
|
public <E extends ProfileReadResponse> E awaitValid(@NonNull final Class<E> responseClass)
|
||||||
|
throws RequestFailedException, InvalidDataException, DeviceDisconnectedException,
|
||||||
|
BluetoothDisabledException, InvalidRequestException, InterruptedException {
|
||||||
|
final E response = await(responseClass);
|
||||||
|
if (response != null && !response.isValid()) {
|
||||||
|
throw new InvalidDataException(response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #await(Class, long)}, but if received response is not valid, this method will
|
||||||
|
* thrown an exception.
|
||||||
|
*
|
||||||
|
* @param responseClass the result class. This class will be instantiate, therefore it
|
||||||
|
* has to have a default constructor.
|
||||||
|
* @param timeout optional timeout in milliseconds.
|
||||||
|
* @param <E> a response class that extends {@link ProfileReadResponse}.
|
||||||
|
* @return Object with a valid response.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from
|
||||||
|
* the main (UI) thread.
|
||||||
|
* @throws InterruptedException thrown when the timeout occurred before the
|
||||||
|
* characteristic value has changed.
|
||||||
|
* @throws IllegalArgumentException thrown when the response class could not be instantiated.
|
||||||
|
* @throws RequestFailedException thrown when the trigger request has failed.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the
|
||||||
|
* notification or indication was received.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @throws InvalidDataException thrown when the received data were not valid (that is when
|
||||||
|
* {@link ProfileReadResponse#onDataReceived(BluetoothDevice, Data)}
|
||||||
|
* failed to parse the data correctly and called
|
||||||
|
* {@link ProfileReadResponse#onInvalidDataReceived(BluetoothDevice, Data)}).
|
||||||
|
* @deprecated Use {@link #timeout(long)} and {@link #awaitValid(Class)} instead.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public <E extends ProfileReadResponse> E awaitValid(@NonNull final Class<E> responseClass,
|
||||||
|
@IntRange(from = 0) final long timeout)
|
||||||
|
throws InterruptedException, InvalidDataException, RequestFailedException,
|
||||||
|
DeviceDisconnectedException, BluetoothDisabledException, InvalidRequestException {
|
||||||
|
return timeout(timeout).awaitValid(responseClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #await(Object, long)}, but if received response is not valid,
|
||||||
|
* this method will thrown an exception.
|
||||||
|
*
|
||||||
|
* @param response the result object.
|
||||||
|
* @param timeout optional timeout in milliseconds.
|
||||||
|
* @param <E> a response class that extends {@link ProfileReadResponse}.
|
||||||
|
* @return Object with a valid response.
|
||||||
|
* @throws IllegalStateException thrown when you try to call this method from
|
||||||
|
* the main (UI) thread.
|
||||||
|
* @throws InterruptedException thrown when the timeout occurred before the
|
||||||
|
* characteristic value has changed.
|
||||||
|
* @throws RequestFailedException thrown when the trigger request has failed.
|
||||||
|
* @throws DeviceDisconnectedException thrown when the device disconnected before the
|
||||||
|
* notification or indication was received.
|
||||||
|
* @throws BluetoothDisabledException thrown when the Bluetooth adapter has been disabled.
|
||||||
|
* @throws InvalidRequestException thrown when the request was called before the device was
|
||||||
|
* connected at least once (unknown device).
|
||||||
|
* @throws InvalidDataException thrown when the received data were not valid (that is when
|
||||||
|
* {@link ProfileReadResponse#onDataReceived(BluetoothDevice, Data)}
|
||||||
|
* failed to parse the data correctly and called
|
||||||
|
* {@link ProfileReadResponse#onInvalidDataReceived(BluetoothDevice, Data)}).
|
||||||
|
* @deprecated Use {@link #timeout(long)} and {@link #awaitValid(E)} instead.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@NonNull
|
||||||
|
@Deprecated
|
||||||
|
public <E extends ProfileReadResponse> E awaitValid(@NonNull final E response,
|
||||||
|
@IntRange(from = 0) final long timeout)
|
||||||
|
throws InterruptedException, InvalidDataException, DeviceDisconnectedException,
|
||||||
|
RequestFailedException, BluetoothDisabledException, InvalidRequestException {
|
||||||
|
return timeout(timeout).awaitValid(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean matches(final byte[] packet) {
|
||||||
|
return filter == null || filter.filter(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyValueChanged(final BluetoothDevice device, final byte[] value) {
|
||||||
|
// Keep a reference to the value callback, as it may change during execution
|
||||||
|
final DataReceivedCallback valueCallback = this.valueCallback;
|
||||||
|
|
||||||
|
// With no value callback there is no need for any merging
|
||||||
|
if (valueCallback == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataMerger == null) {
|
||||||
|
valueCallback.onDataReceived(device, new Data(value));
|
||||||
|
} else {
|
||||||
|
if (progressCallback != null)
|
||||||
|
progressCallback.onPacketReceived(device, value, count);
|
||||||
|
if (buffer == null)
|
||||||
|
buffer = new DataStream();
|
||||||
|
if (dataMerger.merge(buffer, value, count++)) {
|
||||||
|
valueCallback.onDataReceived(device, buffer.toData());
|
||||||
|
buffer = null;
|
||||||
|
count = 0;
|
||||||
|
} // else
|
||||||
|
// wait for more packets to be merged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasMore() {
|
||||||
|
return count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
Request getTrigger() {
|
||||||
|
return trigger;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isTriggerPending() {
|
||||||
|
return triggerStatus == NOT_STARTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isTriggerCompleteOrNull() {
|
||||||
|
return triggerStatus != STARTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
282
_android/src/no/nordicsemi/android/ble/WriteRequest.java
Normal file
282
_android/src/no/nordicsemi/android/ble/WriteRequest.java
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.annotation.WriteType;
|
||||||
|
import no.nordicsemi.android.ble.callback.BeforeCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataSentCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.FailCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.InvalidRequestCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback;
|
||||||
|
import no.nordicsemi.android.ble.callback.WriteProgressCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataSplitter;
|
||||||
|
import no.nordicsemi.android.ble.data.DefaultMtuSplitter;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public final class WriteRequest extends SimpleValueRequest<DataSentCallback> implements Operation {
|
||||||
|
private final static DataSplitter MTU_SPLITTER = new DefaultMtuSplitter();
|
||||||
|
|
||||||
|
private WriteProgressCallback progressCallback;
|
||||||
|
private DataSplitter dataSplitter;
|
||||||
|
private final byte[] data;
|
||||||
|
private final int writeType;
|
||||||
|
private byte[] currentChunk;
|
||||||
|
private byte[] nextChunk;
|
||||||
|
private int count = 0;
|
||||||
|
private boolean complete = false;
|
||||||
|
|
||||||
|
WriteRequest(@NonNull final Type type) {
|
||||||
|
this(type, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteRequest(@NonNull final Type type, @Nullable final BluetoothGattCharacteristic characteristic) {
|
||||||
|
super(type, characteristic);
|
||||||
|
// not used:
|
||||||
|
this.data = null;
|
||||||
|
this.writeType = 0;
|
||||||
|
// getData(int) isn't called on enabling and disabling notifications/indications.
|
||||||
|
this.complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteRequest(@NonNull final Type type, @Nullable final BluetoothGattCharacteristic characteristic,
|
||||||
|
@Nullable final byte[] data,
|
||||||
|
@IntRange(from = 0) final int offset, @IntRange(from = 0) final int length,
|
||||||
|
@WriteType final int writeType) {
|
||||||
|
super(type, characteristic);
|
||||||
|
this.data = copy(data, offset, length);
|
||||||
|
this.writeType = writeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteRequest(@NonNull final Type type, @Nullable final BluetoothGattDescriptor descriptor,
|
||||||
|
@Nullable final byte[] data,
|
||||||
|
@IntRange(from = 0) final int offset, @IntRange(from = 0) final int length) {
|
||||||
|
super(type, descriptor);
|
||||||
|
this.data = copy(data, offset, length);
|
||||||
|
this.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
WriteRequest setManager(@NonNull final BleManager manager) {
|
||||||
|
super.setManager(manager);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest done(@NonNull final SuccessCallback callback) {
|
||||||
|
super.done(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest fail(@NonNull final FailCallback callback) {
|
||||||
|
super.fail(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public WriteRequest invalid(@NonNull final InvalidRequestCallback callback) {
|
||||||
|
super.invalid(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest before(@NonNull final BeforeCallback callback) {
|
||||||
|
super.before(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest with(@NonNull final DataSentCallback callback) {
|
||||||
|
super.with(callback);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a splitter that will be used to cut given data into multiple packets.
|
||||||
|
* The splitter may modify each packet if necessary, i.e. add a flag indicating first packet,
|
||||||
|
* continuation or the last packet.
|
||||||
|
*
|
||||||
|
* @param splitter an implementation of a splitter.
|
||||||
|
* @return The request.
|
||||||
|
* @see #split()
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest split(@NonNull final DataSplitter splitter) {
|
||||||
|
this.dataSplitter = splitter;
|
||||||
|
this.progressCallback = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a splitter that will be used to cut given data into multiple packets.
|
||||||
|
* The splitter may modify each packet if necessary, i.e. add a flag indicating first packet,
|
||||||
|
* continuation or the last packet.
|
||||||
|
*
|
||||||
|
* @param splitter an implementation of a splitter.
|
||||||
|
* @param callback the progress callback that will be notified each time a packet was sent.
|
||||||
|
* @return The request.
|
||||||
|
* @see #split()
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest split(@NonNull final DataSplitter splitter,
|
||||||
|
@NonNull final WriteProgressCallback callback) {
|
||||||
|
this.dataSplitter = splitter;
|
||||||
|
this.progressCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a default MTU splitter that will be used to cut given data into at-most MTU-3
|
||||||
|
* bytes long packets.
|
||||||
|
*
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest split() {
|
||||||
|
this.dataSplitter = MTU_SPLITTER;
|
||||||
|
this.progressCallback = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a default MTU splitter that will be used to cut given data into at-most MTU-3
|
||||||
|
* bytes long packets.
|
||||||
|
*
|
||||||
|
* @param callback the progress callback that will be notified each time a packet was sent.
|
||||||
|
* @return The request.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public WriteRequest split(@NonNull final WriteProgressCallback callback) {
|
||||||
|
this.dataSplitter = MTU_SPLITTER;
|
||||||
|
this.progressCallback = callback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method makes sure the data sent will be split to at-most MTU-3 bytes long packets.
|
||||||
|
* This is because Long Write does not work with Reliable Write.
|
||||||
|
*/
|
||||||
|
void forceSplit() {
|
||||||
|
if (dataSplitter == null)
|
||||||
|
split();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next chunk to be sent. If data splitter was not set the date returned may
|
||||||
|
* be longer than MTU. Android will try to send them using Long Write sub-procedure if
|
||||||
|
* write type is {@link BluetoothGattCharacteristic#WRITE_TYPE_DEFAULT}. Other write types
|
||||||
|
* will cause the data to be truncated.
|
||||||
|
*
|
||||||
|
* @param mtu the current MTU.
|
||||||
|
* @return The next bytes to be sent.
|
||||||
|
*/
|
||||||
|
byte[] getData(@IntRange(from = 23, to = 517) final int mtu) {
|
||||||
|
if (dataSplitter == null || data == null) {
|
||||||
|
complete = true;
|
||||||
|
return currentChunk = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write Request and Write Command require 3 bytes for handler and op code.
|
||||||
|
// Write Signed requires 12 bytes, as the signature is sent.
|
||||||
|
final int maxLength = writeType != BluetoothGattCharacteristic.WRITE_TYPE_SIGNED ?
|
||||||
|
mtu - 3 : mtu - 12;
|
||||||
|
|
||||||
|
byte[] chunk = nextChunk;
|
||||||
|
// Get the first chunk.
|
||||||
|
if (chunk == null) {
|
||||||
|
chunk = dataSplitter.chunk(data, count, maxLength);
|
||||||
|
}
|
||||||
|
// If there's something to send, check if there are any more packets to be sent later.
|
||||||
|
if (chunk != null) {
|
||||||
|
nextChunk = dataSplitter.chunk(data, count + 1, maxLength);
|
||||||
|
}
|
||||||
|
// If there's no next packet left, we are done.
|
||||||
|
if (nextChunk == null) {
|
||||||
|
complete = true;
|
||||||
|
}
|
||||||
|
return currentChunk = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when packet has been sent and confirmed (when Write With Response was used),
|
||||||
|
* or added to local outgoing buffer (when Write Without Response was used).
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param data the data received in the
|
||||||
|
* {@link android.bluetooth.BluetoothGattCallback#onCharacteristicWrite(BluetoothGatt, BluetoothGattCharacteristic, int)}.
|
||||||
|
* @return True, if the data received are equal to data sent.
|
||||||
|
*/
|
||||||
|
boolean notifyPacketSent(@NonNull final BluetoothDevice device, @Nullable final byte[] data) {
|
||||||
|
if (progressCallback != null)
|
||||||
|
progressCallback.onPacketSent(device, data, count);
|
||||||
|
count++;
|
||||||
|
if (complete && valueCallback != null)
|
||||||
|
valueCallback.onDataSent(device, new Data(WriteRequest.this.data));
|
||||||
|
return Arrays.equals(data, currentChunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether there are more bytes to be sent from this Write Request.
|
||||||
|
* @return True if not all data were sent, false if the request is complete.
|
||||||
|
*/
|
||||||
|
boolean hasMore() {
|
||||||
|
return !complete;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the write type that should be used to send the data.
|
||||||
|
* @return The write type.
|
||||||
|
*/
|
||||||
|
@WriteType
|
||||||
|
int getWriteType() {
|
||||||
|
return writeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] copy(@Nullable final byte[] value,
|
||||||
|
@IntRange(from = 0) final int offset,
|
||||||
|
@IntRange(from = 0) final int length) {
|
||||||
|
if (value == null || offset > value.length)
|
||||||
|
return null;
|
||||||
|
final int maxLength = Math.min(value.length - offset, length);
|
||||||
|
final byte[] copy = new byte[maxLength];
|
||||||
|
System.arraycopy(value, offset, copy, 0, maxLength);
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import no.nordicsemi.android.ble.ConnectionPriorityRequest;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
ConnectionPriorityRequest.CONNECTION_PRIORITY_BALANCED,
|
||||||
|
ConnectionPriorityRequest.CONNECTION_PRIORITY_HIGH,
|
||||||
|
ConnectionPriorityRequest.CONNECTION_PRIORITY_LOW_POWER
|
||||||
|
})
|
||||||
|
public @interface ConnectionPriority {}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.annotation;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
BluetoothProfile.STATE_DISCONNECTED,
|
||||||
|
BluetoothProfile.STATE_CONNECTING,
|
||||||
|
BluetoothProfile.STATE_CONNECTED,
|
||||||
|
BluetoothProfile.STATE_DISCONNECTING,
|
||||||
|
})
|
||||||
|
public @interface ConnectionState {}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import no.nordicsemi.android.ble.PhyRequest;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(flag = true, value = {
|
||||||
|
PhyRequest.PHY_LE_1M_MASK,
|
||||||
|
PhyRequest.PHY_LE_2M_MASK,
|
||||||
|
PhyRequest.PHY_LE_CODED_MASK
|
||||||
|
})
|
||||||
|
public @interface PhyMask {}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import no.nordicsemi.android.ble.PhyRequest;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
PhyRequest.PHY_OPTION_NO_PREFERRED,
|
||||||
|
PhyRequest.PHY_OPTION_S2,
|
||||||
|
PhyRequest.PHY_OPTION_S8
|
||||||
|
})
|
||||||
|
public @interface PhyOption {}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import no.nordicsemi.android.ble.callback.PhyCallback;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
PhyCallback.PHY_LE_1M,
|
||||||
|
PhyCallback.PHY_LE_2M,
|
||||||
|
PhyCallback.PHY_LE_CODED
|
||||||
|
})
|
||||||
|
public @interface PhyValue {}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.annotation;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT,
|
||||||
|
BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE,
|
||||||
|
BluetoothGattCharacteristic.WRITE_TYPE_SIGNED,
|
||||||
|
})
|
||||||
|
public @interface WriteType {}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface BeforeCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback invoked when the request is about to start.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
*/
|
||||||
|
void onRequestStarted(@NonNull final BluetoothDevice device);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection parameters for a Bluetooth LE connection is a set of parameters that determine
|
||||||
|
* when and how the Central and a Peripheral in a link transmits data.
|
||||||
|
* It is always the Central that actually sets the connection parameters used, but the Peripheral
|
||||||
|
* can send a so-called Connection Parameter Update Request, that the Central can then accept or reject.
|
||||||
|
* <p>
|
||||||
|
* On Android, requesting connection parameters is available since Android Lollipop using
|
||||||
|
* {@link android.bluetooth.BluetoothGatt#requestConnectionPriority(int)}. There are 3 options
|
||||||
|
* available: {@link android.bluetooth.BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER},
|
||||||
|
* {@link android.bluetooth.BluetoothGatt#CONNECTION_PRIORITY_BALANCED} and
|
||||||
|
* {@link android.bluetooth.BluetoothGatt#CONNECTION_PRIORITY_HIGH}. See
|
||||||
|
* {@link no.nordicsemi.android.ble.Request#newConnectionPriorityRequest(int)} for details.
|
||||||
|
* <p>
|
||||||
|
* Until Android 8.0 Oreo, there was no callback indicating whether the change has succeeded,
|
||||||
|
* or not. Also, when a Central or Peripheral requested connection parameters change without
|
||||||
|
* explicit calling of this method, the application was not aware of it.
|
||||||
|
* Android Oreo added a hidden callback to {@link android.bluetooth.BluetoothGattCallback}
|
||||||
|
* notifying about connection parameters change. Those values will be reported with this callback.
|
||||||
|
*/
|
||||||
|
public interface ConnectionPriorityCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback indicating the connection parameters were updated. Works on Android 8.0 Oreo or newer.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param interval Connection interval used on this connection, 1.25ms unit. Valid range is from
|
||||||
|
* 6 (7.5ms) to 3200 (4000ms).
|
||||||
|
* @param latency Slave latency for the connection in number of connection events. Valid range
|
||||||
|
* is from 0 to 499.
|
||||||
|
* @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is from 10
|
||||||
|
* (100 ms = 0.1s) to 3200 (32s).
|
||||||
|
*/
|
||||||
|
void onConnectionUpdated(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 6, to = 3200) final int interval,
|
||||||
|
@IntRange(from = 0, to = 499) final int latency,
|
||||||
|
@IntRange(from = 10, to = 3200) final int timeout);
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataMerger;
|
||||||
|
|
||||||
|
public interface DataReceivedCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback received each time the value was read or has changed using
|
||||||
|
* notifications or indications.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param data the data received. If the {@link DataMerger} was used,
|
||||||
|
* this contains the merged result.
|
||||||
|
*/
|
||||||
|
void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataSplitter;
|
||||||
|
|
||||||
|
public interface DataSentCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback received each time the value was written to a characteristic or descriptor.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param data the data sent. If the {@link DataSplitter} was used, this contains the full data.
|
||||||
|
*/
|
||||||
|
void onDataSent(@NonNull final BluetoothDevice device, @NonNull final Data data);
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface FailCallback {
|
||||||
|
int REASON_DEVICE_DISCONNECTED = -1;
|
||||||
|
int REASON_DEVICE_NOT_SUPPORTED = -2;
|
||||||
|
int REASON_NULL_ATTRIBUTE = -3;
|
||||||
|
int REASON_REQUEST_FAILED = -4;
|
||||||
|
int REASON_TIMEOUT = -5;
|
||||||
|
int REASON_VALIDATION = -6;
|
||||||
|
int REASON_BLUETOOTH_DISABLED = -100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback invoked when the request has failed with status other than
|
||||||
|
* {@link android.bluetooth.BluetoothGatt#GATT_SUCCESS}.
|
||||||
|
*
|
||||||
|
* @param device target device.
|
||||||
|
* @param status error status code, one of BluetoothGatt#GATT_* constants or
|
||||||
|
* {@link #REASON_DEVICE_DISCONNECTED}, {@link #REASON_TIMEOUT},
|
||||||
|
* {@link #REASON_DEVICE_NOT_SUPPORTED} (only for Connect request),
|
||||||
|
* {@link #REASON_BLUETOOTH_DISABLED}, {@link #REASON_NULL_ATTRIBUTE},
|
||||||
|
* {@link #REASON_VALIDATION} or {@link #REASON_REQUEST_FAILED} (for other reason).
|
||||||
|
*/
|
||||||
|
void onRequestFailed(@NonNull final BluetoothDevice device, final int status);
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
public interface InvalidRequestCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback invoked when the request was invalid, for example when was called before the
|
||||||
|
* device was connected.
|
||||||
|
*/
|
||||||
|
void onInvalidRequest();
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface MtuCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when the MTU request has finished with success. The MTU value may
|
||||||
|
* be different than requested one. The maximum packet size is 3 bytes less then MTU.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param mtu the new MTU (Maximum Transfer Unit).
|
||||||
|
*/
|
||||||
|
void onMtuChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 23, to = 517) final int mtu);
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyValue;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface PhyCallback {
|
||||||
|
/**
|
||||||
|
* Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
int PHY_LE_1M = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
int PHY_LE_2M = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
|
||||||
|
* or connection.
|
||||||
|
*/
|
||||||
|
int PHY_LE_CODED = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when the PHY value has changed or was read.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param txPhy the transmitter PHY in use. One of {@link #PHY_LE_1M},
|
||||||
|
* {@link #PHY_LE_2M}, and {@link #PHY_LE_CODED}.
|
||||||
|
* @param rxPhy the receiver PHY in use. One of {@link #PHY_LE_1M},
|
||||||
|
* {@link #PHY_LE_2M}, and {@link #PHY_LE_CODED}.
|
||||||
|
*/
|
||||||
|
void onPhyChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.data.DataMerger;
|
||||||
|
|
||||||
|
public interface ReadProgressCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback received each time the value was read or has changed using notifications or
|
||||||
|
* indications when {@link DataMerger} was used.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param data the last packet received.
|
||||||
|
* @param index the index of a packet that will be merged into a single Data.
|
||||||
|
*/
|
||||||
|
void onPacketReceived(@NonNull final BluetoothDevice device,
|
||||||
|
@Nullable final byte[] data, @IntRange(from = 0) final int index);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface RssiCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when the RSSI value has been read.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param rssi the current RSSI value, in dBm.
|
||||||
|
*/
|
||||||
|
void onRssiRead(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = -128, to = 20) final int rssi);
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface SuccessCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A callback invoked when the request completed successfully.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
*/
|
||||||
|
void onRequestCompleted(@NonNull final BluetoothDevice device);
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.data.DataSplitter;
|
||||||
|
|
||||||
|
public interface WriteProgressCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback called each time a packet has been sent when {@link DataSplitter} was used.
|
||||||
|
*
|
||||||
|
* @param device the target device.
|
||||||
|
* @param data the last packet sent.
|
||||||
|
* @param index the index of a packet that the initial Data was cut into.
|
||||||
|
*/
|
||||||
|
void onPacketSent(@NonNull final BluetoothDevice device,
|
||||||
|
@Nullable final byte[] data, @IntRange(from = 0) final int index);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback.profile;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataReceivedCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.data.DataMerger;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface ProfileDataCallback extends DataReceivedCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback called when the data received do not conform to required scheme.
|
||||||
|
* @param device the target device.
|
||||||
|
* @param data the data received. If the {@link DataMerger} was used, this contains the
|
||||||
|
* merged result.
|
||||||
|
*/
|
||||||
|
default void onInvalidDataReceived(@NonNull final BluetoothDevice device,
|
||||||
|
@NonNull final Data data) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.callback.profile;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
import no.nordicsemi.android.ble.response.ReadResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A response type for read requests with basic validation check.
|
||||||
|
* When read was requested as a synchronous call the {@link #isValid()} can be used to
|
||||||
|
* check if data were parsed successfully. Parsing method must call super methods on
|
||||||
|
* both {@link #onDataReceived(BluetoothDevice, Data)} and
|
||||||
|
* {@link #onInvalidDataReceived(BluetoothDevice, Data)} in order to make getters working properly.
|
||||||
|
* <p>
|
||||||
|
* Check out profile data callbacks in the Android BLE Common Library for example of usage.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class ProfileReadResponse extends ReadResponse implements ProfileDataCallback, Parcelable {
|
||||||
|
private boolean valid = true;
|
||||||
|
|
||||||
|
public ProfileReadResponse() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInvalidDataReceived(@NonNull final BluetoothDevice device,
|
||||||
|
@NonNull final Data data) {
|
||||||
|
this.valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if {@link #onInvalidDataReceived(BluetoothDevice, Data)} wasn't called.
|
||||||
|
*
|
||||||
|
* @return True, if profile data were valid, false if parsing error occurred.
|
||||||
|
*/
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected ProfileReadResponse(final Parcel in) {
|
||||||
|
super(in);
|
||||||
|
valid = in.readByte() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
super.writeToParcel(dest, flags);
|
||||||
|
dest.writeByte((byte) (valid ? 1 : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ProfileReadResponse> CREATOR = new Creator<ProfileReadResponse>() {
|
||||||
|
@Override
|
||||||
|
public ProfileReadResponse createFromParcel(final Parcel in) {
|
||||||
|
return new ProfileReadResponse(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProfileReadResponse[] newArray(final int size) {
|
||||||
|
return new ProfileReadResponse[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
470
_android/src/no/nordicsemi/android/ble/data/Data.java
Normal file
470
_android/src/no/nordicsemi/android/ble/data/Data.java
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused", "UnusedReturnValue"})
|
||||||
|
public class Data implements Parcelable {
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
FORMAT_UINT8,
|
||||||
|
FORMAT_UINT16,
|
||||||
|
FORMAT_UINT24,
|
||||||
|
FORMAT_UINT32,
|
||||||
|
FORMAT_SINT8,
|
||||||
|
FORMAT_SINT16,
|
||||||
|
FORMAT_SINT24,
|
||||||
|
FORMAT_SINT32,
|
||||||
|
FORMAT_FLOAT,
|
||||||
|
FORMAT_SFLOAT
|
||||||
|
})
|
||||||
|
public @interface ValueFormat {}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
FORMAT_UINT8,
|
||||||
|
FORMAT_UINT16,
|
||||||
|
FORMAT_UINT24,
|
||||||
|
FORMAT_UINT32,
|
||||||
|
FORMAT_SINT8,
|
||||||
|
FORMAT_SINT16,
|
||||||
|
FORMAT_SINT24,
|
||||||
|
FORMAT_SINT32
|
||||||
|
})
|
||||||
|
public @interface IntFormat {}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
FORMAT_UINT32,
|
||||||
|
FORMAT_SINT32
|
||||||
|
})
|
||||||
|
public @interface LongFormat {}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(value = {
|
||||||
|
FORMAT_FLOAT,
|
||||||
|
FORMAT_SFLOAT
|
||||||
|
})
|
||||||
|
public @interface FloatFormat {}
|
||||||
|
|
||||||
|
private static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type uint8
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_UINT8 = 0x11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type uint16
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_UINT16 = 0x12;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type uint24
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_UINT24 = 0x13;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type uint32
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_UINT32 = 0x14;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type sint8
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_SINT8 = 0x21;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type sint16
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_SINT16 = 0x22;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type sint24
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_SINT24 = 0x23;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type sint32
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_SINT32 = 0x24;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type sfloat (16-bit float, IEEE-11073)
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_SFLOAT = 0x32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data value format type float (32-bit float, IEEE-11073)
|
||||||
|
*/
|
||||||
|
public final static int FORMAT_FLOAT = 0x34;
|
||||||
|
|
||||||
|
protected byte[] mValue;
|
||||||
|
|
||||||
|
public Data() {
|
||||||
|
this.mValue = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Data(@Nullable final byte[] value) {
|
||||||
|
this.mValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Data from(@NonNull final String value) {
|
||||||
|
return new Data(value.getBytes()); // UTF-8
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Data from(@NonNull final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new Data(characteristic.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Data from(@NonNull final BluetoothGattDescriptor descriptor) {
|
||||||
|
return new Data(descriptor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Data opCode(final byte opCode) {
|
||||||
|
return new Data(new byte[] { opCode });
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Data opCode(final byte opCode, final byte parameter) {
|
||||||
|
return new Data(new byte[] { opCode, parameter });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the underlying byte array.
|
||||||
|
*
|
||||||
|
* @return Data received.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public byte[] getValue() {
|
||||||
|
return mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the stored value of this characteristic.
|
||||||
|
* <p>See {@link #getValue} for details.
|
||||||
|
*
|
||||||
|
* @param offset Offset at which the string value can be found.
|
||||||
|
* @return Cached value of the characteristic
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getStringValue(@IntRange(from = 0) final int offset) {
|
||||||
|
if (mValue == null || offset > mValue.length)
|
||||||
|
return null;
|
||||||
|
final byte[] strBytes = new byte[mValue.length - offset];
|
||||||
|
for (int i = 0; i != (mValue.length - offset); ++i)
|
||||||
|
strBytes[i] = mValue[offset+i];
|
||||||
|
return new String(strBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of underlying byte array.
|
||||||
|
*
|
||||||
|
* @return Length of the data.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return mValue != null ? mValue.length : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (size() == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
final char[] out = new char[mValue.length * 3 - 1];
|
||||||
|
for (int j = 0; j < mValue.length; j++) {
|
||||||
|
int v = mValue[j] & 0xFF;
|
||||||
|
out[j * 3] = HEX_ARRAY[v >>> 4];
|
||||||
|
out[j * 3 + 1] = HEX_ARRAY[v & 0x0F];
|
||||||
|
if (j != mValue.length - 1)
|
||||||
|
out[j * 3 + 2] = '-';
|
||||||
|
}
|
||||||
|
return "(0x) " + new String(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a byte at the given offset from the byte array.
|
||||||
|
*
|
||||||
|
* @param offset Offset at which the byte value can be found.
|
||||||
|
* @return Cached value or null of offset exceeds value size.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Byte getByte(@IntRange(from = 0) final int offset) {
|
||||||
|
if (offset + 1 > size()) return null;
|
||||||
|
|
||||||
|
return mValue[offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an integer value from the byte array.
|
||||||
|
* <p>
|
||||||
|
* <p>The formatType parameter determines how the value
|
||||||
|
* is to be interpreted. For example, setting formatType to
|
||||||
|
* {@link #FORMAT_UINT16} specifies that the first two bytes of the
|
||||||
|
* value at the given offset are interpreted to generate the
|
||||||
|
* return value.
|
||||||
|
*
|
||||||
|
* @param formatType The format type used to interpret the value.
|
||||||
|
* @param offset Offset at which the integer value can be found.
|
||||||
|
* @return Cached value or null of offset exceeds value size.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Integer getIntValue(@IntFormat final int formatType,
|
||||||
|
@IntRange(from = 0) final int offset) {
|
||||||
|
if ((offset + getTypeLen(formatType)) > size()) return null;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_UINT8:
|
||||||
|
return unsignedByteToInt(mValue[offset]);
|
||||||
|
|
||||||
|
case FORMAT_UINT16:
|
||||||
|
return unsignedBytesToInt(mValue[offset], mValue[offset + 1]);
|
||||||
|
|
||||||
|
case FORMAT_UINT24:
|
||||||
|
return unsignedBytesToInt(mValue[offset], mValue[offset + 1],
|
||||||
|
mValue[offset + 2], (byte) 0);
|
||||||
|
|
||||||
|
case FORMAT_UINT32:
|
||||||
|
return unsignedBytesToInt(mValue[offset], mValue[offset + 1],
|
||||||
|
mValue[offset + 2], mValue[offset + 3]);
|
||||||
|
|
||||||
|
case FORMAT_SINT8:
|
||||||
|
return unsignedToSigned(unsignedByteToInt(mValue[offset]), 8);
|
||||||
|
|
||||||
|
case FORMAT_SINT16:
|
||||||
|
return unsignedToSigned(unsignedBytesToInt(mValue[offset],
|
||||||
|
mValue[offset + 1]), 16);
|
||||||
|
|
||||||
|
case FORMAT_SINT24:
|
||||||
|
return unsignedToSigned(unsignedBytesToInt(mValue[offset],
|
||||||
|
mValue[offset + 1], mValue[offset + 2], (byte) 0), 24);
|
||||||
|
|
||||||
|
case FORMAT_SINT32:
|
||||||
|
return unsignedToSigned(unsignedBytesToInt(mValue[offset],
|
||||||
|
mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]), 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a long value from the byte array.
|
||||||
|
* <p>Only {@link #FORMAT_UINT32} and {@link #FORMAT_SINT32} are supported.
|
||||||
|
* <p>The formatType parameter determines how the value
|
||||||
|
* is to be interpreted. For example, setting formatType to
|
||||||
|
* {@link #FORMAT_UINT32} specifies that the first four bytes of the
|
||||||
|
* value at the given offset are interpreted to generate the
|
||||||
|
* return value.
|
||||||
|
*
|
||||||
|
* @param formatType The format type used to interpret the value.
|
||||||
|
* @param offset Offset at which the integer value can be found.
|
||||||
|
* @return Cached value or null of offset exceeds value size.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Long getLongValue(@LongFormat final int formatType,
|
||||||
|
@IntRange(from = 0) final int offset) {
|
||||||
|
if ((offset + getTypeLen(formatType)) > size()) return null;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_SINT32:
|
||||||
|
return unsignedToSigned(unsignedBytesToLong(mValue[offset],
|
||||||
|
mValue[offset + 1], mValue[offset + 2], mValue[offset + 3]), 32);
|
||||||
|
|
||||||
|
case FORMAT_UINT32:
|
||||||
|
return unsignedBytesToLong(mValue[offset], mValue[offset + 1],
|
||||||
|
mValue[offset + 2], mValue[offset + 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an float value from the given byte array.
|
||||||
|
*
|
||||||
|
* @param formatType The format type used to interpret the value.
|
||||||
|
* @param offset Offset at which the float value can be found.
|
||||||
|
* @return Cached value at a given offset or null if the requested offset exceeds the value size.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Float getFloatValue(@FloatFormat final int formatType,
|
||||||
|
@IntRange(from = 0) final int offset) {
|
||||||
|
if ((offset + getTypeLen(formatType)) > size()) return null;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_SFLOAT:
|
||||||
|
if (mValue[offset + 1] == 0x07 && mValue[offset] == (byte) 0xFE)
|
||||||
|
return Float.POSITIVE_INFINITY;
|
||||||
|
if ((mValue[offset + 1] == 0x07 && mValue[offset] == (byte) 0xFF) ||
|
||||||
|
(mValue[offset + 1] == 0x08 && mValue[offset] == 0x00) ||
|
||||||
|
(mValue[offset + 1] == 0x08 && mValue[offset] == 0x01))
|
||||||
|
return Float.NaN;
|
||||||
|
if (mValue[offset + 1] == 0x08 && mValue[offset] == 0x02)
|
||||||
|
return Float.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
|
return bytesToFloat(mValue[offset], mValue[offset + 1]);
|
||||||
|
|
||||||
|
case FORMAT_FLOAT:
|
||||||
|
if (mValue[offset + 3] == 0x00) {
|
||||||
|
if (mValue[offset + 2] == 0x7F && mValue[offset + 1] == (byte) 0xFF) {
|
||||||
|
if (mValue[offset] == (byte) 0xFE)
|
||||||
|
return Float.POSITIVE_INFINITY;
|
||||||
|
if (mValue[offset] == (byte) 0xFF)
|
||||||
|
return Float.NaN;
|
||||||
|
} else if (mValue[offset + 2] == (byte) 0x80 && mValue[offset + 1] == 0x00) {
|
||||||
|
if (mValue[offset] == 0x00 || mValue[offset] == 0x01)
|
||||||
|
return Float.NaN;
|
||||||
|
if (mValue[offset] == 0x02)
|
||||||
|
return Float.NEGATIVE_INFINITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytesToFloat(mValue[offset], mValue[offset + 1],
|
||||||
|
mValue[offset + 2], mValue[offset + 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the size of a give value type.
|
||||||
|
*/
|
||||||
|
public static int getTypeLen(@ValueFormat final int formatType) {
|
||||||
|
return formatType & 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a signed byte to an unsigned int.
|
||||||
|
*/
|
||||||
|
private static int unsignedByteToInt(final byte b) {
|
||||||
|
return b & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a signed byte to an unsigned int.
|
||||||
|
*/
|
||||||
|
private static long unsignedByteToLong(final byte b) {
|
||||||
|
return b & 0xFFL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert signed bytes to a 16-bit unsigned int.
|
||||||
|
*/
|
||||||
|
private static int unsignedBytesToInt(final byte b0, final byte b1) {
|
||||||
|
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert signed bytes to a 32-bit unsigned int.
|
||||||
|
*/
|
||||||
|
private static int unsignedBytesToInt(final byte b0, final byte b1, final byte b2, final byte b3) {
|
||||||
|
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
|
||||||
|
+ (unsignedByteToInt(b2) << 16) + (unsignedByteToInt(b3) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert signed bytes to a 32-bit unsigned long.
|
||||||
|
*/
|
||||||
|
private static long unsignedBytesToLong(final byte b0, final byte b1, final byte b2, final byte b3) {
|
||||||
|
return (unsignedByteToLong(b0) + (unsignedByteToLong(b1) << 8))
|
||||||
|
+ (unsignedByteToLong(b2) << 16) + (unsignedByteToLong(b3) << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert signed bytes to a 16-bit short float value.
|
||||||
|
*/
|
||||||
|
private static float bytesToFloat(final byte b0, final byte b1) {
|
||||||
|
int mantissa = unsignedToSigned(unsignedByteToInt(b0)
|
||||||
|
+ ((unsignedByteToInt(b1) & 0x0F) << 8), 12);
|
||||||
|
int exponent = unsignedToSigned(unsignedByteToInt(b1) >> 4, 4);
|
||||||
|
return (float) (mantissa * Math.pow(10, exponent));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert signed bytes to a 32-bit short float value.
|
||||||
|
*/
|
||||||
|
private static float bytesToFloat(final byte b0, final byte b1, final byte b2, final byte b3) {
|
||||||
|
int mantissa = unsignedToSigned(unsignedByteToInt(b0)
|
||||||
|
+ (unsignedByteToInt(b1) << 8)
|
||||||
|
+ (unsignedByteToInt(b2) << 16), 24);
|
||||||
|
return (float) (mantissa * Math.pow(10, b3));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an unsigned integer value to a two's-complement encoded
|
||||||
|
* signed value.
|
||||||
|
*/
|
||||||
|
private static int unsignedToSigned(int unsigned, final int size) {
|
||||||
|
if ((unsigned & (1 << size - 1)) != 0) {
|
||||||
|
unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1)));
|
||||||
|
}
|
||||||
|
return unsigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an unsigned long value to a two's-complement encoded
|
||||||
|
* signed value.
|
||||||
|
*/
|
||||||
|
private static long unsignedToSigned(long unsigned, final int size) {
|
||||||
|
if ((unsigned & (1 << size - 1)) != 0) {
|
||||||
|
unsigned = -1 * ((1 << size - 1) - (unsigned & ((1 << size - 1) - 1)));
|
||||||
|
}
|
||||||
|
return unsigned;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected Data(final Parcel in) {
|
||||||
|
mValue = in.createByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeByteArray(mValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<Data> CREATOR = new Creator<Data>() {
|
||||||
|
@Override
|
||||||
|
public Data createFromParcel(final Parcel in) {
|
||||||
|
return new Data(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Data[] newArray(final int size) {
|
||||||
|
return new Data[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
37
_android/src/no/nordicsemi/android/ble/data/DataFilter.java
Normal file
37
_android/src/no/nordicsemi/android/ble/data/DataFilter.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface DataFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should return true if the packet matches the filter and should be processed
|
||||||
|
* by the request.
|
||||||
|
*
|
||||||
|
* @param lastPacket the packet received.
|
||||||
|
* @return True, if packet should be processed, false if it should be ignored.
|
||||||
|
*/
|
||||||
|
boolean filter(@Nullable final byte[] lastPacket);
|
||||||
|
}
|
||||||
42
_android/src/no/nordicsemi/android/ble/data/DataMerger.java
Normal file
42
_android/src/no/nordicsemi/android/ble/data/DataMerger.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface DataMerger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should merge the last packet into the output message.
|
||||||
|
*
|
||||||
|
* @param output the stream for the output message, initially empty.
|
||||||
|
* @param lastPacket the data received in the last read/notify/indicate operation.
|
||||||
|
* @param index an index of the packet, 0-based (if you expect 3 packets, they will be
|
||||||
|
* called with indexes 0, 1, 2).
|
||||||
|
* @return True, if the message is complete, false if more data are expected.
|
||||||
|
*/
|
||||||
|
boolean merge(@NonNull final DataStream output,
|
||||||
|
@Nullable final byte[] lastPacket, @IntRange(from = 0) final int index);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface DataSplitter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The implementation should return a index'th byte array from given message,
|
||||||
|
* with at most maxLength size, or null if no bytes are left to be sent.
|
||||||
|
*
|
||||||
|
* @param message the full message to be chunk.
|
||||||
|
* @param index index of a packet, 0-based.
|
||||||
|
* @param maxLength maximum length of the returned packet. Equals to MTU-3.
|
||||||
|
* Use {@link no.nordicsemi.android.ble.BleManager#requestMtu(int)} to request
|
||||||
|
* higher MTU, or {@link no.nordicsemi.android.ble.BleManager#overrideMtu(int)}
|
||||||
|
* If the MTU change was initiated by the target device.
|
||||||
|
* @return The packet to be sent, or null, if the whole message was already split.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
byte[] chunk(@NonNull final byte[] message,
|
||||||
|
@IntRange(from = 0) final int index, @IntRange(from = 20) final int maxLength);
|
||||||
|
}
|
||||||
75
_android/src/no/nordicsemi/android/ble/data/DataStream.java
Normal file
75
_android/src/no/nordicsemi/android/ble/data/DataStream.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class DataStream {
|
||||||
|
private final ByteArrayOutputStream buffer;
|
||||||
|
|
||||||
|
public DataStream() {
|
||||||
|
buffer = new ByteArrayOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SimplifiableIfStatement")
|
||||||
|
public boolean write(@Nullable final byte[] data) {
|
||||||
|
if (data == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return write(data, 0, data.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean write(@Nullable final byte[] data,
|
||||||
|
@IntRange(from = 0) final int offset, @IntRange(from = 0) final int length) {
|
||||||
|
if (data == null || data.length < offset)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
final int len = Math.min(data.length - offset, length);
|
||||||
|
buffer.write(data, offset, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean write(@Nullable final Data data) {
|
||||||
|
return data != null && write(data.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntRange(from = 0)
|
||||||
|
public int size() {
|
||||||
|
return buffer.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Data toData() {
|
||||||
|
return new Data(buffer.toByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the message into at-most MTU-3 size packets.
|
||||||
|
*/
|
||||||
|
public final class DefaultMtuSplitter implements DataSplitter {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public byte[] chunk(@NonNull final byte[] message,
|
||||||
|
@IntRange(from = 0) final int index,
|
||||||
|
@IntRange(from = 20) final int maxLength) {
|
||||||
|
final int offset = index * maxLength;
|
||||||
|
final int length = Math.min(maxLength, message.length - offset);
|
||||||
|
|
||||||
|
if (length <= 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final byte[] data = new byte[length];
|
||||||
|
System.arraycopy(message, offset, data, 0, length);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
409
_android/src/no/nordicsemi/android/ble/data/MutableData.java
Normal file
409
_android/src/no/nordicsemi/android/ble/data/MutableData.java
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.data;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "SameParameterValue", "WeakerAccess", "UnusedReturnValue"})
|
||||||
|
public class MutableData extends Data {
|
||||||
|
// Values required to convert float to IEEE-11073 SFLOAT
|
||||||
|
private final static int SFLOAT_POSITIVE_INFINITY = 0x07FE;
|
||||||
|
private final static int SFLOAT_NAN = 0x07FF;
|
||||||
|
// private final static int SFLOAT_NOT_AT_THIS_RESOLUTION = 0x0800;
|
||||||
|
// private final static int SFLOAT_RESERVED_VALUE = 0x0801;
|
||||||
|
private final static int SFLOAT_NEGATIVE_INFINITY = 0x0802;
|
||||||
|
private final static int SFLOAT_MANTISSA_MAX = 0x07FD;
|
||||||
|
private final static int SFLOAT_EXPONENT_MAX = 7;
|
||||||
|
private final static int SFLOAT_EXPONENT_MIN = -8;
|
||||||
|
private final static float SFLOAT_MAX = 20450000000.0f;
|
||||||
|
private final static float SFLOAT_MIN = -SFLOAT_MAX;
|
||||||
|
private final static int SFLOAT_PRECISION = 10000;
|
||||||
|
// private final static float SFLOAT_EPSILON = 1e-8f;
|
||||||
|
|
||||||
|
// Values required to convert float to IEEE-11073 FLOAT
|
||||||
|
private final static int FLOAT_POSITIVE_INFINITY = 0x007FFFFE;
|
||||||
|
private final static int FLOAT_NAN = 0x007FFFFF;
|
||||||
|
// private final static int FLOAT_NOT_AT_THIS_RESOLUTION = 0x00800000;
|
||||||
|
// private final static int FLOAT_RESERVED_VALUE = 0x00800001;
|
||||||
|
private final static int FLOAT_NEGATIVE_INFINITY = 0x00800002;
|
||||||
|
private final static int FLOAT_MANTISSA_MAX = 0x007FFFFD;
|
||||||
|
private final static int FLOAT_EXPONENT_MAX = 127;
|
||||||
|
private final static int FLOAT_EXPONENT_MIN = -128;
|
||||||
|
private final static int FLOAT_PRECISION = 10000000;
|
||||||
|
// private final static float FLOAT_EPSILON = 1e-128f;
|
||||||
|
|
||||||
|
public MutableData() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableData(@Nullable final byte[] data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MutableData from(@NonNull final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return new MutableData(characteristic.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MutableData from(@NonNull final BluetoothGattDescriptor descriptor) {
|
||||||
|
return new MutableData(descriptor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the locally stored value of this data.
|
||||||
|
*
|
||||||
|
* @param value New value
|
||||||
|
* @return true if the locally stored value has been set, false if the
|
||||||
|
* requested value could not be stored locally.
|
||||||
|
*/
|
||||||
|
public boolean setValue(@Nullable final byte[] value) {
|
||||||
|
mValue = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the byte at offset position.
|
||||||
|
*
|
||||||
|
* @param value Byte to set
|
||||||
|
* @param offset The offset
|
||||||
|
* @return true if the locally stored value has been set, false if the
|
||||||
|
* requested value could not be stored locally.
|
||||||
|
*/
|
||||||
|
public boolean setByte(final int value, @IntRange(from = 0) final int offset) {
|
||||||
|
final int len = offset + 1;
|
||||||
|
if (mValue == null) mValue = new byte[len];
|
||||||
|
if (len > mValue.length) return false;
|
||||||
|
mValue[offset] = (byte) value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locally stored value of this data.
|
||||||
|
* <p>See {@link #setValue(byte[])} for details.
|
||||||
|
*
|
||||||
|
* @param value New value for this data
|
||||||
|
* @param formatType Integer format type used to transform the value parameter
|
||||||
|
* @param offset Offset at which the value should be placed
|
||||||
|
* @return true if the locally stored value has been set
|
||||||
|
*/
|
||||||
|
public boolean setValue(int value, @IntFormat int formatType, @IntRange(from = 0) int offset) {
|
||||||
|
final int len = offset + getTypeLen(formatType);
|
||||||
|
if (mValue == null) mValue = new byte[len];
|
||||||
|
if (len > mValue.length) return false;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_SINT8:
|
||||||
|
value = intToSignedBits(value, 8);
|
||||||
|
// Fall-through intended
|
||||||
|
case FORMAT_UINT8:
|
||||||
|
mValue[offset] = (byte) (value & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FORMAT_SINT16:
|
||||||
|
value = intToSignedBits(value, 16);
|
||||||
|
// Fall-through intended
|
||||||
|
case FORMAT_UINT16:
|
||||||
|
mValue[offset++] = (byte) (value & 0xFF);
|
||||||
|
mValue[offset] = (byte) ((value >> 8) & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FORMAT_SINT24:
|
||||||
|
value = intToSignedBits(value, 24);
|
||||||
|
// Fall-through intended
|
||||||
|
case FORMAT_UINT24:
|
||||||
|
mValue[offset++] = (byte) (value & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((value >> 8) & 0xFF);
|
||||||
|
mValue[offset] = (byte) ((value >> 16) & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FORMAT_SINT32:
|
||||||
|
value = intToSignedBits(value, 32);
|
||||||
|
// Fall-through intended
|
||||||
|
case FORMAT_UINT32:
|
||||||
|
mValue[offset++] = (byte) (value & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((value >> 8) & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((value >> 16) & 0xFF);
|
||||||
|
mValue[offset] = (byte) ((value >> 24) & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locally stored value of this data.
|
||||||
|
* <p>See {@link #setValue(byte[])} for details.
|
||||||
|
*
|
||||||
|
* @param mantissa Mantissa for this data
|
||||||
|
* @param exponent Exponent value for this data
|
||||||
|
* @param formatType Float format type used to transform the value parameter
|
||||||
|
* @param offset Offset at which the value should be placed
|
||||||
|
* @return true if the locally stored value has been set
|
||||||
|
*/
|
||||||
|
public boolean setValue(int mantissa, int exponent,
|
||||||
|
@FloatFormat int formatType, @IntRange(from = 0) int offset) {
|
||||||
|
final int len = offset + getTypeLen(formatType);
|
||||||
|
if (mValue == null) mValue = new byte[len];
|
||||||
|
if (len > mValue.length) return false;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_SFLOAT:
|
||||||
|
mantissa = intToSignedBits(mantissa, 12);
|
||||||
|
exponent = intToSignedBits(exponent, 4);
|
||||||
|
mValue[offset++] = (byte) (mantissa & 0xFF);
|
||||||
|
mValue[offset] = (byte) ((mantissa >> 8) & 0x0F);
|
||||||
|
mValue[offset] += (byte) ((exponent & 0x0F) << 4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FORMAT_FLOAT:
|
||||||
|
mantissa = intToSignedBits(mantissa, 24);
|
||||||
|
exponent = intToSignedBits(exponent, 8);
|
||||||
|
mValue[offset++] = (byte) (mantissa & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((mantissa >> 8) & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((mantissa >> 16) & 0xFF);
|
||||||
|
mValue[offset] += (byte) (exponent & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locally stored value of this data.
|
||||||
|
* <p>See {@link #setValue(byte[])} for details.
|
||||||
|
*
|
||||||
|
* @param value New value for this data. This allows to send {@link #FORMAT_UINT32}.
|
||||||
|
* @param formatType Integer format type used to transform the value parameter
|
||||||
|
* @param offset Offset at which the value should be placed
|
||||||
|
* @return true if the locally stored value has been set
|
||||||
|
*/
|
||||||
|
public boolean setValue(long value, @LongFormat int formatType, @IntRange(from = 0) int offset) {
|
||||||
|
final int len = offset + getTypeLen(formatType);
|
||||||
|
if (mValue == null) mValue = new byte[len];
|
||||||
|
if (len > mValue.length) return false;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_SINT32:
|
||||||
|
value = longToSignedBits(value, 32);
|
||||||
|
// Fall-through intended
|
||||||
|
case FORMAT_UINT32:
|
||||||
|
mValue[offset++] = (byte) (value & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((value >> 8) & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((value >> 16) & 0xFF);
|
||||||
|
mValue[offset] = (byte) ((value >> 24) & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the locally stored value of this data.
|
||||||
|
* <p>See {@link #setValue(byte[])} for details.
|
||||||
|
*
|
||||||
|
* @param value Float value to be written
|
||||||
|
* @param formatType Float format type used to transform the value parameter
|
||||||
|
* @param offset Offset at which the value should be placed
|
||||||
|
* @return true if the locally stored value has been set
|
||||||
|
*/
|
||||||
|
public boolean setValue(float value,
|
||||||
|
@FloatFormat int formatType, @IntRange(from = 0) int offset) {
|
||||||
|
final int len = offset + getTypeLen(formatType);
|
||||||
|
if (mValue == null) mValue = new byte[len];
|
||||||
|
if (len > mValue.length) return false;
|
||||||
|
|
||||||
|
switch (formatType) {
|
||||||
|
case FORMAT_SFLOAT:
|
||||||
|
final int sfloatAsInt = sfloatToInt(value);
|
||||||
|
mValue[offset++] = (byte) (sfloatAsInt & 0xFF);
|
||||||
|
mValue[offset] = (byte) ((sfloatAsInt >> 8) & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FORMAT_FLOAT:
|
||||||
|
final int floatAsInt = floatToInt(value);
|
||||||
|
mValue[offset++] = (byte) (floatAsInt & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((floatAsInt >> 8) & 0xFF);
|
||||||
|
mValue[offset++] = (byte) ((floatAsInt >> 16) & 0xFF);
|
||||||
|
mValue[offset] += (byte) ((floatAsInt >> 24) & 0xFF);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts float to SFLOAT IEEE 11073 format as UINT16, rounding up or down.
|
||||||
|
* See: https://github.com/signove/antidote/blob/master/src/util/bytelib.c
|
||||||
|
*
|
||||||
|
* @param value the value to be converted.
|
||||||
|
* @return given float as UINT16 in IEEE 11073 format.
|
||||||
|
*/
|
||||||
|
private static int sfloatToInt(final float value) {
|
||||||
|
if (Float.isNaN(value)) {
|
||||||
|
return SFLOAT_NAN;
|
||||||
|
} else if (value > SFLOAT_MAX) {
|
||||||
|
return SFLOAT_POSITIVE_INFINITY;
|
||||||
|
} else if (value < SFLOAT_MIN) {
|
||||||
|
return SFLOAT_NEGATIVE_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sign = value >= 0 ? +1 : -1;
|
||||||
|
float mantissa = Math.abs(value);
|
||||||
|
int exponent = 0; // Note: 10**x exponent, not 2**x
|
||||||
|
|
||||||
|
// scale up if number is too big
|
||||||
|
while (mantissa > SFLOAT_MANTISSA_MAX) {
|
||||||
|
mantissa /= 10.0f;
|
||||||
|
++exponent;
|
||||||
|
if (exponent > SFLOAT_EXPONENT_MAX) {
|
||||||
|
// argh, should not happen
|
||||||
|
if (sign > 0) {
|
||||||
|
return SFLOAT_POSITIVE_INFINITY;
|
||||||
|
} else {
|
||||||
|
return SFLOAT_NEGATIVE_INFINITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale down if number is too small
|
||||||
|
while (mantissa < 1) {
|
||||||
|
mantissa *= 10;
|
||||||
|
--exponent;
|
||||||
|
if (exponent < SFLOAT_EXPONENT_MIN) {
|
||||||
|
// argh, should not happen
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale down if number needs more precision
|
||||||
|
double smantissa = Math.round(mantissa * SFLOAT_PRECISION);
|
||||||
|
double rmantissa = Math.round(mantissa) * SFLOAT_PRECISION;
|
||||||
|
double mdiff = Math.abs(smantissa - rmantissa);
|
||||||
|
while (mdiff > 0.5 && exponent > SFLOAT_EXPONENT_MIN &&
|
||||||
|
(mantissa * 10) <= SFLOAT_MANTISSA_MAX) {
|
||||||
|
mantissa *= 10;
|
||||||
|
--exponent;
|
||||||
|
smantissa = Math.round(mantissa * SFLOAT_PRECISION);
|
||||||
|
rmantissa = Math.round(mantissa) * SFLOAT_PRECISION;
|
||||||
|
mdiff = Math.abs(smantissa - rmantissa);
|
||||||
|
}
|
||||||
|
|
||||||
|
int int_mantissa = Math.round(sign * mantissa);
|
||||||
|
return ((exponent & 0xF) << 12) | (int_mantissa & 0xFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts float to FLOAT IEEE 11073 format as UINT32, rounding up or down.
|
||||||
|
* See: https://github.com/signove/antidote/blob/master/src/util/bytelib.c
|
||||||
|
*
|
||||||
|
* @param value the value to be converted.
|
||||||
|
* @return given float as UINT32 in IEEE 11073 format.
|
||||||
|
*/
|
||||||
|
private static int floatToInt(final float value) {
|
||||||
|
if (Float.isNaN(value)) {
|
||||||
|
return FLOAT_NAN;
|
||||||
|
} else if (value == Float.POSITIVE_INFINITY) {
|
||||||
|
return FLOAT_POSITIVE_INFINITY;
|
||||||
|
} else if (value == Float.NEGATIVE_INFINITY) {
|
||||||
|
return FLOAT_NEGATIVE_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sign = value >= 0 ? +1 : -1;
|
||||||
|
float mantissa = Math.abs(value);
|
||||||
|
int exponent = 0; // Note: 10**x exponent, not 2**x
|
||||||
|
|
||||||
|
// scale up if number is too big
|
||||||
|
while (mantissa > FLOAT_MANTISSA_MAX) {
|
||||||
|
mantissa /= 10.0f;
|
||||||
|
++exponent;
|
||||||
|
if (exponent > FLOAT_EXPONENT_MAX) {
|
||||||
|
// argh, should not happen
|
||||||
|
if (sign > 0) {
|
||||||
|
return FLOAT_POSITIVE_INFINITY;
|
||||||
|
} else {
|
||||||
|
return FLOAT_NEGATIVE_INFINITY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale down if number is too small
|
||||||
|
while (mantissa < 1) {
|
||||||
|
mantissa *= 10;
|
||||||
|
--exponent;
|
||||||
|
if (exponent < FLOAT_EXPONENT_MIN) {
|
||||||
|
// argh, should not happen
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// scale down if number needs more precision
|
||||||
|
double smantissa = Math.round(mantissa * FLOAT_PRECISION);
|
||||||
|
double rmantissa = Math.round(mantissa) * FLOAT_PRECISION;
|
||||||
|
double mdiff = Math.abs(smantissa - rmantissa);
|
||||||
|
while (mdiff > 0.5 && exponent > FLOAT_EXPONENT_MIN &&
|
||||||
|
(mantissa * 10) <= FLOAT_MANTISSA_MAX) {
|
||||||
|
mantissa *= 10;
|
||||||
|
--exponent;
|
||||||
|
smantissa = Math.round(mantissa * FLOAT_PRECISION);
|
||||||
|
rmantissa = Math.round(mantissa) * FLOAT_PRECISION;
|
||||||
|
mdiff = Math.abs(smantissa - rmantissa);
|
||||||
|
}
|
||||||
|
|
||||||
|
int int_mantissa = Math.round(sign * mantissa);
|
||||||
|
return (exponent << 24) | (int_mantissa & 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an integer into the signed bits of a given length.
|
||||||
|
*/
|
||||||
|
private static int intToSignedBits(int i, int size) {
|
||||||
|
if (i < 0) {
|
||||||
|
i = (1 << size - 1) + (i & ((1 << size - 1) - 1));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a long into the signed bits of a given length.
|
||||||
|
*/
|
||||||
|
private static long longToSignedBits(long i, int size) {
|
||||||
|
if (i < 0) {
|
||||||
|
i = (1L << size - 1) + (i & ((1L << size - 1) - 1));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
209
_android/src/no/nordicsemi/android/ble/error/GattError.java
Normal file
209
_android/src/no/nordicsemi/android/ble/error/GattError.java
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package no.nordicsemi.android.ble.error;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGatt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the GATT and HCI errors to human readable strings.
|
||||||
|
* <p>
|
||||||
|
* See: <a href="https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/stack/include/gatt_api.h">gatt_api.h</a> for details.<br>
|
||||||
|
* See also: <a href="https://android.googlesource.com/platform/external/libnfc-nci/+/master/src/include/hcidefs.h#447">hcidefs.h</a> for other possible HCI errors.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class GattError {
|
||||||
|
public static final int GATT_SUCCESS = BluetoothGatt.GATT_SUCCESS;
|
||||||
|
public static final int GATT_CONN_L2C_FAILURE = 0x01;
|
||||||
|
public static final int GATT_CONN_TIMEOUT = 0x08;
|
||||||
|
public static final int GATT_CONN_TERMINATE_PEER_USER = 0x13;
|
||||||
|
public static final int GATT_CONN_TERMINATE_LOCAL_HOST = 0x16;
|
||||||
|
public static final int GATT_CONN_FAIL_ESTABLISH = 0x3E;
|
||||||
|
public static final int GATT_CONN_LMP_TIMEOUT = 0x22;
|
||||||
|
public static final int GATT_CONN_CANCEL = 0x0100;
|
||||||
|
public static final int GATT_ERROR = 0x0085; // Device not reachable
|
||||||
|
|
||||||
|
public static final int GATT_INVALID_HANDLE = 0x0001;
|
||||||
|
public static final int GATT_READ_NOT_PERMIT = 0x0002;
|
||||||
|
public static final int GATT_WRITE_NOT_PERMIT = 0x0003;
|
||||||
|
public static final int GATT_INVALID_PDU = 0x0004;
|
||||||
|
public static final int GATT_INSUF_AUTHENTICATION = 0x0005;
|
||||||
|
public static final int GATT_REQ_NOT_SUPPORTED = 0x0006;
|
||||||
|
public static final int GATT_INVALID_OFFSET = 0x0007;
|
||||||
|
public static final int GATT_INSUF_AUTHORIZATION = 0x0008;
|
||||||
|
public static final int GATT_PREPARE_Q_FULL = 0x0009;
|
||||||
|
public static final int GATT_NOT_FOUND = 0x000a;
|
||||||
|
public static final int GATT_NOT_LONG = 0x000b;
|
||||||
|
public static final int GATT_INSUF_KEY_SIZE = 0x000c;
|
||||||
|
public static final int GATT_INVALID_ATTR_LEN = 0x000d;
|
||||||
|
public static final int GATT_ERR_UNLIKELY = 0x000e;
|
||||||
|
public static final int GATT_INSUF_ENCRYPTION = 0x000f;
|
||||||
|
public static final int GATT_UNSUPPORT_GRP_TYPE = 0x0010;
|
||||||
|
public static final int GATT_INSUF_RESOURCE = 0x0011;
|
||||||
|
public static final int GATT_CONTROLLER_BUSY = 0x003A;
|
||||||
|
public static final int GATT_UNACCEPT_CONN_INTERVAL = 0x003B;
|
||||||
|
public static final int GATT_ILLEGAL_PARAMETER = 0x0087;
|
||||||
|
public static final int GATT_NO_RESOURCES = 0x0080;
|
||||||
|
public static final int GATT_INTERNAL_ERROR = 0x0081;
|
||||||
|
public static final int GATT_WRONG_STATE = 0x0082;
|
||||||
|
public static final int GATT_DB_FULL = 0x0083;
|
||||||
|
public static final int GATT_BUSY = 0x0084;
|
||||||
|
public static final int GATT_CMD_STARTED = 0x0086;
|
||||||
|
public static final int GATT_PENDING = 0x0088;
|
||||||
|
public static final int GATT_AUTH_FAIL = 0x0089;
|
||||||
|
public static final int GATT_MORE = 0x008a;
|
||||||
|
public static final int GATT_INVALID_CFG = 0x008b;
|
||||||
|
public static final int GATT_SERVICE_STARTED = 0x008c;
|
||||||
|
public static final int GATT_ENCRYPTED_NO_MITM = 0x008d;
|
||||||
|
public static final int GATT_NOT_ENCRYPTED = 0x008e;
|
||||||
|
public static final int GATT_CONGESTED = 0x008f;
|
||||||
|
public static final int GATT_CCCD_CFG_ERROR = 0x00FD;
|
||||||
|
public static final int GATT_PROCEDURE_IN_PROGRESS = 0x00FE;
|
||||||
|
public static final int GATT_VALUE_OUT_OF_RANGE = 0x00FF;
|
||||||
|
public static final int TOO_MANY_OPEN_CONNECTIONS = 0x0101;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the connection status given by the
|
||||||
|
* {@link android.bluetooth.BluetoothGattCallback#onConnectionStateChange(BluetoothGatt, int, int)}
|
||||||
|
* to error name.
|
||||||
|
*
|
||||||
|
* @param error the status number.
|
||||||
|
* @return The error name as stated in the links in {@link GattError} documentation.
|
||||||
|
*/
|
||||||
|
public static String parseConnectionError(final int error) {
|
||||||
|
switch (error) {
|
||||||
|
case GATT_SUCCESS:
|
||||||
|
return "SUCCESS";
|
||||||
|
case GATT_CONN_L2C_FAILURE:
|
||||||
|
return "GATT CONN L2C FAILURE";
|
||||||
|
case GATT_CONN_TIMEOUT:
|
||||||
|
return "GATT CONN TIMEOUT";
|
||||||
|
case GATT_CONN_TERMINATE_PEER_USER:
|
||||||
|
return "GATT CONN TERMINATE PEER USER";
|
||||||
|
case GATT_CONN_TERMINATE_LOCAL_HOST:
|
||||||
|
return "GATT CONN TERMINATE LOCAL HOST";
|
||||||
|
case GATT_CONN_FAIL_ESTABLISH:
|
||||||
|
return "GATT CONN FAIL ESTABLISH";
|
||||||
|
case GATT_CONN_LMP_TIMEOUT:
|
||||||
|
return "GATT CONN LMP TIMEOUT";
|
||||||
|
case GATT_CONN_CANCEL:
|
||||||
|
return "GATT CONN CANCEL ";
|
||||||
|
case GATT_ERROR:
|
||||||
|
return "GATT ERROR"; // Device not reachable
|
||||||
|
default:
|
||||||
|
return "UNKNOWN (" + error + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the Bluetooth communication status given by other BluetoothGattCallbacks to error
|
||||||
|
* name. It also parses the DFU errors.
|
||||||
|
*
|
||||||
|
* @param error the status number.
|
||||||
|
* @return The error name as stated in the links in {@link GattError} documentation.
|
||||||
|
*/
|
||||||
|
public static String parse(final int error) {
|
||||||
|
switch (error) {
|
||||||
|
case GATT_INVALID_HANDLE:
|
||||||
|
return "GATT INVALID HANDLE";
|
||||||
|
case GATT_READ_NOT_PERMIT:
|
||||||
|
return "GATT READ NOT PERMIT";
|
||||||
|
case GATT_WRITE_NOT_PERMIT:
|
||||||
|
return "GATT WRITE NOT PERMIT";
|
||||||
|
case GATT_INVALID_PDU:
|
||||||
|
return "GATT INVALID PDU";
|
||||||
|
case GATT_INSUF_AUTHENTICATION:
|
||||||
|
return "GATT INSUF AUTHENTICATION";
|
||||||
|
case GATT_REQ_NOT_SUPPORTED:
|
||||||
|
return "GATT REQ NOT SUPPORTED";
|
||||||
|
case GATT_INVALID_OFFSET:
|
||||||
|
return "GATT INVALID OFFSET";
|
||||||
|
case GATT_INSUF_AUTHORIZATION:
|
||||||
|
return "GATT INSUF AUTHORIZATION";
|
||||||
|
case GATT_PREPARE_Q_FULL:
|
||||||
|
return "GATT PREPARE Q FULL";
|
||||||
|
case GATT_NOT_FOUND:
|
||||||
|
return "GATT NOT FOUND";
|
||||||
|
case GATT_NOT_LONG:
|
||||||
|
return "GATT NOT LONG";
|
||||||
|
case GATT_INSUF_KEY_SIZE:
|
||||||
|
return "GATT INSUF KEY SIZE";
|
||||||
|
case GATT_INVALID_ATTR_LEN:
|
||||||
|
return "GATT INVALID ATTR LEN";
|
||||||
|
case GATT_ERR_UNLIKELY:
|
||||||
|
return "GATT ERR UNLIKELY";
|
||||||
|
case GATT_INSUF_ENCRYPTION:
|
||||||
|
return "GATT INSUF ENCRYPTION";
|
||||||
|
case GATT_UNSUPPORT_GRP_TYPE:
|
||||||
|
return "GATT UNSUPPORT GRP TYPE";
|
||||||
|
case GATT_INSUF_RESOURCE:
|
||||||
|
return "GATT INSUF RESOURCE";
|
||||||
|
case GATT_CONN_LMP_TIMEOUT:
|
||||||
|
return "GATT CONN LMP TIMEOUT";
|
||||||
|
case GATT_CONTROLLER_BUSY:
|
||||||
|
return "GATT CONTROLLER BUSY";
|
||||||
|
case GATT_UNACCEPT_CONN_INTERVAL:
|
||||||
|
return "GATT UNACCEPT CONN INTERVAL";
|
||||||
|
case GATT_ILLEGAL_PARAMETER:
|
||||||
|
return "GATT ILLEGAL PARAMETER";
|
||||||
|
case GATT_NO_RESOURCES:
|
||||||
|
return "GATT NO RESOURCES";
|
||||||
|
case GATT_INTERNAL_ERROR:
|
||||||
|
return "GATT INTERNAL ERROR";
|
||||||
|
case GATT_WRONG_STATE:
|
||||||
|
return "GATT WRONG STATE";
|
||||||
|
case GATT_DB_FULL:
|
||||||
|
return "GATT DB FULL";
|
||||||
|
case GATT_BUSY:
|
||||||
|
return "GATT BUSY";
|
||||||
|
case GATT_ERROR:
|
||||||
|
return "GATT ERROR";
|
||||||
|
case GATT_CMD_STARTED:
|
||||||
|
return "GATT CMD STARTED";
|
||||||
|
case GATT_PENDING:
|
||||||
|
return "GATT PENDING";
|
||||||
|
case GATT_AUTH_FAIL:
|
||||||
|
return "GATT AUTH FAIL";
|
||||||
|
case GATT_MORE:
|
||||||
|
return "GATT MORE";
|
||||||
|
case GATT_INVALID_CFG:
|
||||||
|
return "GATT INVALID CFG";
|
||||||
|
case GATT_SERVICE_STARTED:
|
||||||
|
return "GATT SERVICE STARTED";
|
||||||
|
case GATT_ENCRYPTED_NO_MITM:
|
||||||
|
return "GATT ENCRYPTED NO MITM";
|
||||||
|
case GATT_NOT_ENCRYPTED:
|
||||||
|
return "GATT NOT ENCRYPTED";
|
||||||
|
case GATT_CONGESTED:
|
||||||
|
return "GATT CONGESTED";
|
||||||
|
case GATT_CCCD_CFG_ERROR:
|
||||||
|
return "GATT CCCD CFG ERROR";
|
||||||
|
case GATT_PROCEDURE_IN_PROGRESS:
|
||||||
|
return "GATT PROCEDURE IN PROGRESS";
|
||||||
|
case GATT_VALUE_OUT_OF_RANGE:
|
||||||
|
return "GATT VALUE OUT OF RANGE";
|
||||||
|
case TOO_MANY_OPEN_CONNECTIONS:
|
||||||
|
return "TOO MANY OPEN CONNECTIONS";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN (" + error + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.exception;
|
||||||
|
|
||||||
|
public class BluetoothDisabledException extends ConnectionException {
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.exception;
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public class ConnectionException extends Exception {
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.exception;
|
||||||
|
|
||||||
|
public class DeviceDisconnectedException extends ConnectionException {
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.exception;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import no.nordicsemi.android.ble.callback.profile.ProfileReadResponse;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class InvalidDataException extends Exception {
|
||||||
|
private final ProfileReadResponse response;
|
||||||
|
|
||||||
|
public InvalidDataException(@NonNull final ProfileReadResponse response) {
|
||||||
|
this.response = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProfileReadResponse getResponse() {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.exception;
|
||||||
|
|
||||||
|
import no.nordicsemi.android.ble.Request;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public final class InvalidRequestException extends Exception {
|
||||||
|
private final Request request;
|
||||||
|
|
||||||
|
public InvalidRequestException(final Request request) {
|
||||||
|
super("Invalid request");
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the invalid request.
|
||||||
|
* @return The invalid request.
|
||||||
|
*/
|
||||||
|
public Request getRequest() {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.exception;
|
||||||
|
|
||||||
|
import no.nordicsemi.android.ble.Request;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public final class RequestFailedException extends Exception {
|
||||||
|
private final Request request;
|
||||||
|
private final int status;
|
||||||
|
|
||||||
|
public RequestFailedException(final Request request, final int status) {
|
||||||
|
super("Request failed with status " + status);
|
||||||
|
this.request = request;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the request status. One of {{@link android.bluetooth.BluetoothGatt}} GATT_*
|
||||||
|
* or {@link no.nordicsemi.android.ble.callback.FailCallback} REASON_* codes.
|
||||||
|
*
|
||||||
|
* @return Error code.
|
||||||
|
*/
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the request that failed.
|
||||||
|
* @return The request that failed.
|
||||||
|
*/
|
||||||
|
public Request getRequest() {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.response;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.ConnectionPriorityCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The synchronous response type for connection priority requests.
|
||||||
|
*
|
||||||
|
* @see ConnectionPriorityCallback
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class ConnectionPriorityResponse implements ConnectionPriorityCallback, Parcelable {
|
||||||
|
private BluetoothDevice device;
|
||||||
|
|
||||||
|
@IntRange(from = 6, to = 3200)
|
||||||
|
private int interval;
|
||||||
|
|
||||||
|
@IntRange(from = 0, to = 499)
|
||||||
|
private int latency;
|
||||||
|
|
||||||
|
@IntRange(from = 10, to = 3200)
|
||||||
|
private int supervisionTimeout;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnectionUpdated(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 6, to = 3200) final int interval,
|
||||||
|
@IntRange(from = 0, to = 499) final int latency,
|
||||||
|
@IntRange(from = 10, to = 3200) final int timeout) {
|
||||||
|
this.device = device;
|
||||||
|
this.interval = interval;
|
||||||
|
this.latency = latency;
|
||||||
|
this.supervisionTimeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BluetoothDevice getBluetoothDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection interval determines how often the Central will ask for data from the Peripheral.
|
||||||
|
* When the Peripheral requests an update, it supplies a maximum and a minimum wanted interval.
|
||||||
|
* The connection interval must be between 7.5 ms and 4 s.
|
||||||
|
*
|
||||||
|
* @return Connection interval used on this connection, 1.25ms unit.
|
||||||
|
* Valid range is from 6 (7.5ms) to 3200 (4000ms).
|
||||||
|
*/
|
||||||
|
@IntRange(from = 6, to = 3200)
|
||||||
|
public int getConnectionInterval() {
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By setting a non-zero slave latency, the Peripheral can choose to not answer when
|
||||||
|
* the Central asks for data up to the slave latency number of times.
|
||||||
|
* However, if the Peripheral has data to send, it can choose to send data at any time.
|
||||||
|
* This enables a peripheral to stay sleeping for a longer time, if it doesn't have data to send,
|
||||||
|
* but still send data fast if needed. The text book example of such device is for example
|
||||||
|
* keyboard and mice, which want to be sleeping for as long as possible when there is
|
||||||
|
* no data to send, but still have low latency (and for the mouse: low connection interval)
|
||||||
|
* when needed.
|
||||||
|
*
|
||||||
|
* @return Slave latency for the connection in number of connection events.
|
||||||
|
* Valid range is from 0 to 499.
|
||||||
|
*/
|
||||||
|
@IntRange(from = 0, to = 499)
|
||||||
|
public int getSlaveLatency() {
|
||||||
|
return latency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This timeout determines the timeout from the last data exchange till a link is considered lost.
|
||||||
|
* A Central will not start trying to reconnect before the timeout has passed,
|
||||||
|
* so if you have a device which goes in and out of range often, and you need to notice when
|
||||||
|
* that happens, it might make sense to have a short timeout.
|
||||||
|
*
|
||||||
|
* @return Supervision timeout for this connection, in 10ms unit.
|
||||||
|
* Valid range is from 10 (100 ms = 0.1s) to 3200 (32s).
|
||||||
|
*/
|
||||||
|
@IntRange(from = 10, to = 3200)
|
||||||
|
public int getSupervisionTimeout() {
|
||||||
|
return supervisionTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected ConnectionPriorityResponse(final Parcel in) {
|
||||||
|
device = in.readParcelable(BluetoothDevice.class.getClassLoader());
|
||||||
|
interval = in.readInt();
|
||||||
|
latency = in.readInt();
|
||||||
|
supervisionTimeout = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(device, flags);
|
||||||
|
dest.writeInt(interval);
|
||||||
|
dest.writeInt(latency);
|
||||||
|
dest.writeInt(supervisionTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ConnectionPriorityResponse> CREATOR = new Creator<ConnectionPriorityResponse>() {
|
||||||
|
@Override
|
||||||
|
public ConnectionPriorityResponse createFromParcel(final Parcel in) {
|
||||||
|
return new ConnectionPriorityResponse(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConnectionPriorityResponse[] newArray(final int size) {
|
||||||
|
return new ConnectionPriorityResponse[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.response;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.MtuCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class MtuResult implements MtuCallback, Parcelable {
|
||||||
|
private BluetoothDevice device;
|
||||||
|
|
||||||
|
@IntRange(from = 23, to = 517)
|
||||||
|
private int mtu;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMtuChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = 23, to = 517) final int mtu) {
|
||||||
|
this.device = device;
|
||||||
|
this.mtu = mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BluetoothDevice getBluetoothDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the agreed MTU. The maximum packet size is 3 bytes less then MTU.
|
||||||
|
*
|
||||||
|
* @return The MTU.
|
||||||
|
*/
|
||||||
|
@IntRange(from = 23, to = 517)
|
||||||
|
public int getMtu() {
|
||||||
|
return mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected MtuResult(final Parcel in) {
|
||||||
|
device = in.readParcelable(BluetoothDevice.class.getClassLoader());
|
||||||
|
mtu = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(device, flags);
|
||||||
|
dest.writeInt(mtu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<MtuResult> CREATOR = new Creator<MtuResult>() {
|
||||||
|
@Override
|
||||||
|
public MtuResult createFromParcel(final Parcel in) {
|
||||||
|
return new MtuResult(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MtuResult[] newArray(final int size) {
|
||||||
|
return new MtuResult[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.response;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.annotation.PhyValue;
|
||||||
|
import no.nordicsemi.android.ble.callback.PhyCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class PhyResult implements PhyCallback, Parcelable {
|
||||||
|
private BluetoothDevice device;
|
||||||
|
|
||||||
|
@PhyValue
|
||||||
|
private int txPhy;
|
||||||
|
|
||||||
|
@PhyValue
|
||||||
|
private int rxPhy;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPhyChanged(@NonNull final BluetoothDevice device,
|
||||||
|
@PhyValue final int txPhy, @PhyValue final int rxPhy) {
|
||||||
|
this.device = device;
|
||||||
|
this.txPhy = txPhy;
|
||||||
|
this.rxPhy = rxPhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BluetoothDevice getBluetoothDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhyValue
|
||||||
|
public int getTxPhy() {
|
||||||
|
return txPhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PhyValue
|
||||||
|
public int getRxPhy() {
|
||||||
|
return rxPhy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected PhyResult(final Parcel in) {
|
||||||
|
device = in.readParcelable(BluetoothDevice.class.getClassLoader());
|
||||||
|
txPhy = in.readInt();
|
||||||
|
rxPhy = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(device, flags);
|
||||||
|
dest.writeInt(txPhy);
|
||||||
|
dest.writeInt(rxPhy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<PhyResult> CREATOR = new Creator<PhyResult>() {
|
||||||
|
@Override
|
||||||
|
public PhyResult createFromParcel(final Parcel in) {
|
||||||
|
return new PhyResult(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PhyResult[] newArray(final int size) {
|
||||||
|
return new PhyResult[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.response;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataReceivedCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic read response class that returns the data received and the device from which data
|
||||||
|
* were read.
|
||||||
|
* Overriding class must call super on {@link #onDataReceived(BluetoothDevice, Data)} in
|
||||||
|
* order to make getters work properly.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class ReadResponse implements DataReceivedCallback, Parcelable {
|
||||||
|
private BluetoothDevice device;
|
||||||
|
private Data data;
|
||||||
|
|
||||||
|
public ReadResponse() {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataReceived(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||||
|
this.device = device;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BluetoothDevice getBluetoothDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Data getRawData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected ReadResponse(final Parcel in) {
|
||||||
|
device = in.readParcelable(BluetoothDevice.class.getClassLoader());
|
||||||
|
data = in.readParcelable(Data.class.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(device, flags);
|
||||||
|
dest.writeParcelable(data, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ReadResponse> CREATOR = new Creator<ReadResponse>() {
|
||||||
|
@Override
|
||||||
|
public ReadResponse createFromParcel(final Parcel in) {
|
||||||
|
return new ReadResponse(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReadResponse[] newArray(final int size) {
|
||||||
|
return new ReadResponse[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.response;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.RssiCallback;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class RssiResult implements RssiCallback, Parcelable {
|
||||||
|
private BluetoothDevice device;
|
||||||
|
|
||||||
|
@IntRange(from = -128, to = 20)
|
||||||
|
private int rssi;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRssiRead(@NonNull final BluetoothDevice device,
|
||||||
|
@IntRange(from = -128, to = 20) final int rssi) {
|
||||||
|
this.device = device;
|
||||||
|
this.rssi = rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BluetoothDevice getBluetoothDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@IntRange(from = -128, to = 20)
|
||||||
|
public int getRssi() {
|
||||||
|
return rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected RssiResult(final Parcel in) {
|
||||||
|
device = in.readParcelable(BluetoothDevice.class.getClassLoader());
|
||||||
|
rssi = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(device, flags);
|
||||||
|
dest.writeInt(rssi);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<RssiResult> CREATOR = new Creator<RssiResult>() {
|
||||||
|
@Override
|
||||||
|
public RssiResult createFromParcel(final Parcel in) {
|
||||||
|
return new RssiResult(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RssiResult[] newArray(final int size) {
|
||||||
|
return new RssiResult[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package no.nordicsemi.android.ble.response;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothDevice;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import no.nordicsemi.android.ble.callback.DataSentCallback;
|
||||||
|
import no.nordicsemi.android.ble.data.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic write response class that returns the target device and the data that were sent.
|
||||||
|
* Overriding class must call super on {@link #onDataSent(BluetoothDevice, Data)} in
|
||||||
|
* order to make getters work properly.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused", "WeakerAccess"})
|
||||||
|
public class WriteResponse implements DataSentCallback, Parcelable {
|
||||||
|
private BluetoothDevice device;
|
||||||
|
private Data data;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDataSent(@NonNull final BluetoothDevice device, @NonNull final Data data) {
|
||||||
|
this.device = device;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BluetoothDevice getBluetoothDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Data getRawData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parcelable
|
||||||
|
protected WriteResponse(final Parcel in) {
|
||||||
|
device = in.readParcelable(BluetoothDevice.class.getClassLoader());
|
||||||
|
data = in.readParcelable(Data.class.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(final Parcel dest, final int flags) {
|
||||||
|
dest.writeParcelable(device, flags);
|
||||||
|
dest.writeParcelable(data, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<WriteResponse> CREATOR = new Creator<WriteResponse>() {
|
||||||
|
@Override
|
||||||
|
public WriteResponse createFromParcel(final Parcel in) {
|
||||||
|
return new WriteResponse(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WriteResponse[] newArray(final int size) {
|
||||||
|
return new WriteResponse[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
47
_android/src/no/nordicsemi/android/ble/utils/ILogger.java
Normal file
47
_android/src/no/nordicsemi/android/ble/utils/ILogger.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package no.nordicsemi.android.ble.utils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public interface ILogger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the given message with given log priority into the all managed devices' log session.
|
||||||
|
*
|
||||||
|
* @param priority the log priority.
|
||||||
|
* @param message the message to be logged.
|
||||||
|
*/
|
||||||
|
void log(final int priority, @NonNull final String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the given message with given log priority into the all managed devices' log session.
|
||||||
|
*
|
||||||
|
* @param priority the log priority.
|
||||||
|
* @param messageRes string resource id.
|
||||||
|
* @param params additional (optional) parameters used to fill the message.
|
||||||
|
*/
|
||||||
|
void log(final int priority, @StringRes final int messageRes, @Nullable final Object... params);
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Nordic Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package no.nordicsemi.android.ble.utils;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothGattCharacteristic;
|
||||||
|
import android.bluetooth.BluetoothGattDescriptor;
|
||||||
|
|
||||||
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
|
public class ParserUtils {
|
||||||
|
protected final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
|
public static String parse(final BluetoothGattCharacteristic characteristic) {
|
||||||
|
return parse(characteristic.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String parse(final BluetoothGattDescriptor descriptor) {
|
||||||
|
return parse(descriptor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String parse(final byte[] data) {
|
||||||
|
if (data == null || data.length == 0)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
final char[] out = new char[data.length * 3 - 1];
|
||||||
|
for (int j = 0; j < data.length; j++) {
|
||||||
|
int v = data[j] & 0xFF;
|
||||||
|
out[j * 3] = HEX_ARRAY[v >>> 4];
|
||||||
|
out[j * 3 + 1] = HEX_ARRAY[v & 0x0F];
|
||||||
|
if (j != data.length - 1)
|
||||||
|
out[j * 3 + 2] = '-';
|
||||||
|
}
|
||||||
|
return "(0x) " + new String(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
181
main.qml
181
main.qml
@@ -1,6 +1,7 @@
|
|||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
import QtQuick.Window 2.2
|
import QtQuick.Window 2.2
|
||||||
import QtQuick.Controls 2.4
|
import QtQuick.Controls 2.4
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: window
|
id: window
|
||||||
@@ -13,50 +14,87 @@ Window {
|
|||||||
Column {
|
Column {
|
||||||
id: column
|
id: column
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: "dist1: " + ((mgmt.dist1 ? mgmt.dist1+sld1.value : 0)/1000).toFixed(2);
|
text: "FTM dist1: " + ((mgmt.dist1 ? mgmt.dist1+sld1.value : 0)/1000).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: "dist2: " + ((mgmt.dist2 ? mgmt.dist2+sld1.value : 0)/1000).toFixed(2);
|
text: "FTM dist2: " + ((mgmt.dist2 ? mgmt.dist2+sld1.value : 0)/1000).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: "dist3: " + ((mgmt.dist3 ? mgmt.dist3+sld1.value : 0)/1000).toFixed(2);
|
text: "FTM dist3: " + ((mgmt.dist3 ? mgmt.dist3+sld1.value : 0)/1000).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "FTM dist4: " + ((mgmt.dist4 ? mgmt.dist4+sld1.value : 0)/1000).toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
Label {
|
|
||||||
text: "dist4: " + ((mgmt.dist4 ? mgmt.dist4+sld1.value : 0)/1000).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Slider {
|
Slider {
|
||||||
width: 400;
|
width: 400;
|
||||||
id: sld1;
|
id: sld1;
|
||||||
from: -3000;
|
from: -1000;
|
||||||
to: 5000;
|
to: 1000;
|
||||||
onValueChanged: leCanvas.requestPaint();
|
value: mgmt.offset;
|
||||||
|
onValueChanged: {
|
||||||
|
mgmt.offset = value;
|
||||||
|
leCanvas.requestPaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
text: "offset: " + sld1.value;
|
text: "offset: " + sld1.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "UWB dist1: " + mgmt.uwbDist1.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "UWB dist2: " + mgmt.uwbDist2.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "UWB dist3: " + mgmt.uwbDist3.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: "UWB dist4: " + mgmt.uwbDist4.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: mgmt
|
target: mgmt
|
||||||
onDistChanged: leCanvas.requestPaint();
|
onDistChanged: leCanvas.requestPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Button {
|
RowLayout {
|
||||||
text: "party hard";
|
Button {
|
||||||
onClicked: mgmt.trigger();
|
text: "party hard";
|
||||||
}
|
onClicked: mgmt.trigger();
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "stop"
|
text: "stop"
|
||||||
onClicked: mgmt.stop();
|
onClicked: mgmt.stop();
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "reset sld"
|
||||||
|
onClicked: {
|
||||||
|
sld1.value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: "High Five"
|
||||||
|
onClicked: {
|
||||||
|
mgmt.manualCheckpoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas {
|
Canvas {
|
||||||
@@ -74,14 +112,17 @@ Window {
|
|||||||
readonly property double s: 0.02;
|
readonly property double s: 0.02;
|
||||||
|
|
||||||
|
|
||||||
function leArc(ctx, cx, cy, dist, stdDev) {
|
function leArc(ctx, cx, cy, dist, stdDev, caption) {
|
||||||
|
|
||||||
// center circle
|
// center circle
|
||||||
ctx.fillStyle = "#000000";
|
ctx.fillStyle = (dist < 0 ? "#FF0000" : "#000000");
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(cx*s, cy*s, 2, 0, 360);
|
ctx.arc(cx*s, cy*s, 2, 0, 360);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
|
|
||||||
|
ctx.font = "12px Arial";
|
||||||
|
ctx.fillText(caption, cx*s, cy*s);
|
||||||
|
|
||||||
// error circle
|
// error circle
|
||||||
// ctx.beginPath();
|
// ctx.beginPath();
|
||||||
// ctx.arc(cx*s, cy*s, (dist+sld1.value)*s, 0, 360);
|
// ctx.arc(cx*s, cy*s, (dist+sld1.value)*s, 0, 360);
|
||||||
@@ -91,12 +132,13 @@ Window {
|
|||||||
// ctx.stroke();
|
// ctx.stroke();
|
||||||
|
|
||||||
// circle
|
// circle
|
||||||
ctx.lineWidth = 1;
|
if (dist > 0) {
|
||||||
ctx.strokeStyle = "#aa000000";
|
ctx.lineWidth = 1;
|
||||||
ctx.beginPath();
|
ctx.strokeStyle = "#aa000000";
|
||||||
ctx.arc(cx*s, cy*s, (dist+sld1.value)*s, 0, 360);
|
ctx.beginPath();
|
||||||
ctx.stroke();
|
ctx.arc(cx*s, cy*s, dist*s, 0, 360);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPaint: {
|
onPaint: {
|
||||||
@@ -110,53 +152,68 @@ Window {
|
|||||||
//ctx.strokeStyle = Qt.rgba(0, 0, 0, 1)
|
//ctx.strokeStyle = Qt.rgba(0, 0, 0, 1)
|
||||||
//ctx.lineWidth = 1
|
//ctx.lineWidth = 1
|
||||||
|
|
||||||
var ox = 4000;
|
// var ox = 4000;
|
||||||
var oy = 4000;
|
// var oy = 4000;
|
||||||
|
|
||||||
var cx1 = ox+0;
|
// var cx1 = ox+0;
|
||||||
var cy1 = oy+0;
|
// var cy1 = oy+0;
|
||||||
|
|
||||||
var cx2 = ox+0;
|
// var cx2 = ox+0;
|
||||||
var cy2 = oy+7250;
|
// var cy2 = oy+7250;
|
||||||
|
|
||||||
var cx3 = ox+9000;
|
// var cx3 = ox+9000;
|
||||||
var cy3 = oy+7250;
|
// var cy3 = oy+7250;
|
||||||
|
|
||||||
var cx4 = ox+9000;
|
// var cx4 = ox+9000;
|
||||||
var cy4 = oy+0;
|
// var cy4 = oy+0;
|
||||||
|
|
||||||
leArc(ctx, cx1, cy1, mgmt.dist1, mgmt.stdDev1);
|
var ox = 4000;
|
||||||
leArc(ctx, cx2, cy2, mgmt.dist2, mgmt.stdDev2);
|
var oy = 4000;
|
||||||
leArc(ctx, cx3, cy3, mgmt.dist3, mgmt.stdDev3);
|
|
||||||
leArc(ctx, cx4, cy4, mgmt.dist4, mgmt.stdDev4);
|
var cx1 = ox+0;
|
||||||
|
var cy1 = oy+0;
|
||||||
|
|
||||||
|
var cx2 = ox+9000;
|
||||||
|
var cy2 = oy+0;
|
||||||
|
|
||||||
|
var cx3 = ox+9000;
|
||||||
|
var cy3 = oy+6200;
|
||||||
|
|
||||||
|
var cx4 = ox+0;
|
||||||
|
var cy4 = oy+6200;
|
||||||
|
|
||||||
|
leArc(ctx, cx1, cy1, mgmt.dist1, mgmt.stdDev1, 1);
|
||||||
|
leArc(ctx, cx2, cy2, mgmt.dist2, mgmt.stdDev2, 2);
|
||||||
|
leArc(ctx, cx3, cy3, mgmt.dist3, mgmt.stdDev3, 3);
|
||||||
|
leArc(ctx, cx4, cy4, mgmt.dist4, mgmt.stdDev4, 4);
|
||||||
|
|
||||||
var sigma = 2000;
|
var sigma = 2000;
|
||||||
var stepSize = 333;
|
var stepSize = 333;
|
||||||
|
|
||||||
var maxP = Math.pow( 1.0 / Math.sqrt(2*Math.PI*sigma), 4.1);
|
var maxP = Math.pow( 1.0 / Math.sqrt(2*Math.PI*sigma), 4.1);
|
||||||
|
|
||||||
for (var y = 0; y < leCanvas.height/s; y += stepSize) {
|
// for (var y = 0; y < leCanvas.height/s; y += stepSize) {
|
||||||
for (var x = 0; x < leCanvas.width/s; x += stepSize) {
|
// for (var x = 0; x < leCanvas.width/s; x += stepSize) {
|
||||||
|
|
||||||
var d1 = Math.sqrt( Math.pow(x-cx1, 2) + Math.pow(y-cy1, 2) ) - (mgmt.dist1-sld1.value);
|
// var d1 = Math.sqrt( Math.pow(x-cx1, 2) + Math.pow(y-cy1, 2) ) - (mgmt.dist1-sld1.value);
|
||||||
var d2 = Math.sqrt( Math.pow(x-cx2, 2) + Math.pow(y-cy2, 2) ) - (mgmt.dist2-sld1.value);
|
// var d2 = Math.sqrt( Math.pow(x-cx2, 2) + Math.pow(y-cy2, 2) ) - (mgmt.dist2-sld1.value);
|
||||||
var d3 = Math.sqrt( Math.pow(x-cx3, 2) + Math.pow(y-cy3, 2) ) - (mgmt.dist3-sld1.value);
|
// var d3 = Math.sqrt( Math.pow(x-cx3, 2) + Math.pow(y-cy3, 2) ) - (mgmt.dist3-sld1.value);
|
||||||
var d4 = Math.sqrt( Math.pow(x-cx4, 2) + Math.pow(y-cy4, 2) ) - (mgmt.dist4-sld1.value);
|
// var d4 = Math.sqrt( Math.pow(x-cx4, 2) + Math.pow(y-cy4, 2) ) - (mgmt.dist4-sld1.value);
|
||||||
|
|
||||||
var p = 1;
|
// var p = 1;
|
||||||
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d1*d1/(2*sigma*sigma) );
|
// p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d1*d1/(2*sigma*sigma) );
|
||||||
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d2*d2/(2*sigma*sigma) );
|
// p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d2*d2/(2*sigma*sigma) );
|
||||||
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d3*d3/(2*sigma*sigma) );
|
// p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d3*d3/(2*sigma*sigma) );
|
||||||
p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d4*d4/(2*sigma*sigma) );
|
// p *= 1.0 / Math.sqrt(2*Math.PI*sigma) * Math.exp( - d4*d4/(2*sigma*sigma) );
|
||||||
|
|
||||||
//p = Math.pow(p, 1);
|
// //p = Math.pow(p, 1);
|
||||||
|
|
||||||
if (p > maxP / 50) {
|
// if (p > maxP / 50) {
|
||||||
ctx.fillStyle = Qt.rgba(1,0,0, p/maxP);
|
// ctx.fillStyle = Qt.rgba(1,0,0, p/maxP);
|
||||||
ctx.fillRect(x*s, y*s, stepSize*s, stepSize*s);
|
// ctx.fillRect(x*s, y*s, stepSize*s, stepSize*s);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
99
uwb.h
Normal file
99
uwb.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#ifndef UWB_H
|
||||||
|
#define UWB_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct UwbPosition {
|
||||||
|
int x = 0;
|
||||||
|
int y = 0;
|
||||||
|
int z = 0;
|
||||||
|
uint8_t quali = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UwbDistance {
|
||||||
|
uint16_t nodeID = 0;
|
||||||
|
int distance = 0;
|
||||||
|
uint8_t quali = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct UwbResult {
|
||||||
|
UwbPosition pos;
|
||||||
|
std::vector<UwbDistance> distances;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void uwb_parse_pos(const unsigned char input[], UwbPosition& pos)
|
||||||
|
{
|
||||||
|
// X,Y,Z coordinates (each 4 bytes) and quality factor (1 byte), total size: 13 bytes
|
||||||
|
|
||||||
|
pos.x = input[0];
|
||||||
|
pos.x |= input[1] << 8;
|
||||||
|
pos.x |= input[2] << 16;
|
||||||
|
pos.x |= input[3] << 24;
|
||||||
|
|
||||||
|
pos.y = input[4];
|
||||||
|
pos.y |= input[5] << 8;
|
||||||
|
pos.y |= input[6] << 16;
|
||||||
|
pos.y |= input[7] << 24;
|
||||||
|
|
||||||
|
pos.z = input[8];
|
||||||
|
pos.z |= input[9] << 8;
|
||||||
|
pos.z |= input[10] << 16;
|
||||||
|
pos.z |= input[11] << 24;
|
||||||
|
|
||||||
|
pos.quali = input[12];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uwb_parse_dist(const unsigned char input[], std::vector<UwbDistance>& result)
|
||||||
|
{
|
||||||
|
// First byte is distance count(1 byte)
|
||||||
|
// Sequence of node ID(2 bytes), distance in mm(4 bytes) and quality factor(1 byte)
|
||||||
|
// Max value contains 15 elements, size: 8 - 106
|
||||||
|
|
||||||
|
size_t numOfAnchors = input[0];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numOfAnchors; i++)
|
||||||
|
{
|
||||||
|
size_t offset = 1 + i * 7;
|
||||||
|
|
||||||
|
UwbDistance dist;
|
||||||
|
|
||||||
|
dist.nodeID = input[offset + 1] << 8 | input[offset];
|
||||||
|
dist.distance = input[offset + 5] << 24
|
||||||
|
| input[offset + 4] << 16
|
||||||
|
| input[offset + 3] << 8
|
||||||
|
| input[offset + 2];
|
||||||
|
dist.quali = input[offset + 6];
|
||||||
|
|
||||||
|
result.push_back(dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UwbResult uwb_parse(const unsigned char input[])
|
||||||
|
{
|
||||||
|
UwbResult result;
|
||||||
|
|
||||||
|
if (input[0] == 0)
|
||||||
|
{
|
||||||
|
// pos only
|
||||||
|
uwb_parse_pos(&input[1], result.pos);
|
||||||
|
}
|
||||||
|
else if (input[0] == 1)
|
||||||
|
{
|
||||||
|
// dist only
|
||||||
|
uwb_parse_dist(&input[1], result.distances);
|
||||||
|
}
|
||||||
|
else if (input[0] == 2)
|
||||||
|
{
|
||||||
|
// Encoded Position (as above, 13 bytes)
|
||||||
|
// Encoded Distances(as above, 8 - 29 bytes).Position and distances
|
||||||
|
// are sent by tag, with a maximum number of 4 ranging anchors
|
||||||
|
uwb_parse_pos(&input[1], result.pos);
|
||||||
|
uwb_parse_dist(&input[1 + 13], result.distances);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UWB_H
|
||||||
Reference in New Issue
Block a user