New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

thingy52_web_bluetooth

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

thingy52_web_bluetooth - npm Package Compare versions

Comparing version 1.3.5 to 1.4.0-transpiled

es5/AbsoluteOrientationSensor.js

2

index.js

@@ -1,3 +0,3 @@

import Thingy from "./js/Thingy.js";
import Thingy from "./es5/Thingy.js";
export default Thingy;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_ORIENTATION_UUID,
decoder: this.decodeOrientationData.bind(this),
decoder: this.decodeOrientationData,
};
}
decodeOrientationData(data) {
decodeOrientationData = (data) => {
try {

@@ -52,0 +52,0 @@ const orientation = data.getUint8(0);

@@ -45,8 +45,8 @@ /*

uuid: this.device.TCS_ADV_PARAMS_UUID,
decoder: this.decodeAdvertisingParam.bind(this),
encoder: this.encodeAdvertisingParam.bind(this),
decoder: this.decodeAdvertisingParam,
encoder: this.encodeAdvertisingParam,
};
}
decodeAdvertisingParam(data) {
decodeAdvertisingParam = (data) => {
try {

@@ -67,5 +67,4 @@ // Interval is given in units of 0.625 milliseconds

async encodeAdvertisingParam(params) {
encodeAdvertisingParam = async (params) => {
try {
if (typeof params !== "object") {

@@ -72,0 +71,0 @@ const error = new Error("The argument has to be an object.");

@@ -45,7 +45,7 @@ /*

uuid: "battery_level",
decoder: this.decodeBatteryStatus.bind(this),
decoder: this.decodeBatteryStatus,
};
}
decodeBatteryStatus(data) {
decodeBatteryStatus = (data) => {
try {

@@ -52,0 +52,0 @@ const batteryStatus = data.getInt8(0);

@@ -45,7 +45,7 @@ /*

uuid: this.device.TUIS_BTN_UUID,
decoder: this.decodeButtonData.bind(this),
decoder: this.decodeButtonData,
};
}
decodeButtonData(data) {
decodeButtonData = (data) => {
try {

@@ -52,0 +52,0 @@ const state = data.getUint8(0);

@@ -45,10 +45,10 @@ /*

uuid: this.device.TCS_CLOUD_TOKEN_UUID,
decoder: this.decodeCloudToken.bind(this),
encoder: this.encodeCloudToken.bind(this),
decoder: this.decodeCloudToken,
encoder: this.encodeCloudToken,
};
}
decodeCloudToken(data) {
decodeCloudToken = (data) => {
try {
const decoder = new TextDecoder("utf-8");
const decoder = new TextDecoder();
const token = decoder.decode(data);

@@ -65,3 +65,3 @@

encodeCloudToken(token) {
encodeCloudToken = (token) => {
try {

@@ -73,5 +73,6 @@ if (token.length > 250) {

const encoder = new TextEncoder("utf-8").encode(token);
const encoder = new TextEncoder();
const encodedToken = encoder.encode(token);
return encoder;
return encodedToken;
} catch (error) {

@@ -78,0 +79,0 @@ throw error;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TES_COLOR_UUID,
decoder: this.decodeColorData.bind(this),
decoder: this.decodeColorData,
};
}
decodeColorData(data) {
decodeColorData = (data) => {
try {

@@ -85,5 +85,5 @@ const littleEndian = true;

const formattedData = {
red: red.toFixed(0),
green: green.toFixed(0),
blue: blue.toFixed(0),
red: parseInt(red.toFixed(0)),
green: parseInt(green.toFixed(0)),
blue: parseInt(blue.toFixed(0)),
};

@@ -90,0 +90,0 @@

@@ -45,8 +45,8 @@ /*

uuid: this.device.TCS_CONN_PARAMS_UUID,
decoder: this.decodeConnectionParam.bind(this),
encoder: this.encodeConnectionParam.bind(this),
decoder: this.decodeConnectionParam,
encoder: this.encodeConnectionParam,
};
}
decodeConnectionParam(data) {
decodeConnectionParam = (data) => {
try {

@@ -73,3 +73,3 @@ // Connection intervals are given in units of 1.25 ms

async encodeConnectionParam(params) {
encodeConnectionParam = async (params) => {
try {

@@ -76,0 +76,0 @@ if (typeof params !== "object") {

@@ -45,8 +45,8 @@ /*

uuid: this.device.TCS_EDDYSTONE_UUID,
decoder: this.decodeEddystoneData.bind(this),
encoder: this.encodeEddystoneData.bind(this),
decoder: this.decodeEddystoneData,
encoder: this.encodeEddystoneData,
};
}
decodeEddystoneData(data) {
decodeEddystoneData = (data) => {
try {

@@ -72,3 +72,3 @@ // According to Eddystone URL encoding specification, certain elements can be expanded: https://github.com/google/eddystone/tree/master/eddystone-url

const prefix = prefixArray[data.getUint8(0)];
const decoder = new TextDecoder("utf-8");
const decoder = new TextDecoder();
let url = decoder.decode(data);

@@ -89,3 +89,3 @@ url = prefix + url.slice(1);

encodeEddystoneData(data) {
encodeEddystoneData = (data) => {
try {

@@ -92,0 +92,0 @@ // Uses URL API to check for valid URL

@@ -45,8 +45,8 @@ /*

uuid: this.device.TES_CONFIG_UUID,
decoder: this.decodeConfigData.bind(this),
encoder: this.encodeConfigData.bind(this),
decoder: this.decodeConfigData,
encoder: this.encodeConfigData,
};
}
decodeConfigData(data) {
decodeConfigData = (data) => {
try {

@@ -90,3 +90,3 @@ const littleEndian = true;

async encodeConfigData(params) {
encodeConfigData = async (params) => {
try {

@@ -93,0 +93,0 @@ if (typeof params !== "object") {

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_EULER_UUID,
decoder: this.decodeEulerData.bind(this),
decoder: this.decodeEulerData,
};
}
decodeEulerData(data) {
decodeEulerData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -29,2 +29,3 @@ /*

this.addEventListener = (type, ...args) => {

@@ -31,0 +32,0 @@ return eventTarget.addEventListener(type, ...args);

@@ -32,8 +32,9 @@ /*

import EventTarget from "./EventTarget.js";
import ThingyController from "./ThingyController.js";
import Utilities from "./Utilities.js";
class FeatureOperations extends EventTarget {
class FeatureOperations {
constructor(device, type) {
super();
this.device = device;
this.utilities = new Utilities(this.device);
this.type = type || this.constructor.name;

@@ -43,3 +44,11 @@ this.latestReading = new Map();

async _connect() {
_connect = async () => {
if (!("thingyController" in this)) {
// has to be put here rather than in the constructor as we need access to the id of the device
// which is not accessible before the device has performed its connect method
this.thingyController = new ThingyController(this.device);
}
this.thingyController.addExecutedOperation(this.type, "connect");
if (("connected" in this.characteristic) && this.characteristic.connected) {

@@ -50,5 +59,5 @@ console.log(`You're already connected to the ${this.type} feature`);

if (this.getGattAvailable()) {
if (this.thingyController.getGattStatus()) {
try {
this.setGattBusy();
this.thingyController.setGattStatus(false);

@@ -58,3 +67,3 @@ this.service.service = await this.device.server.getPrimaryService(this.service.uuid);

this.setGattAvailable();
this.thingyController.setGattStatus(true);

@@ -77,3 +86,3 @@ this.characteristic.connected = true;

// by the functions over. Could prove difficult, will have to see if
// I can alter how verifyAction & verifyReaction works, as it's
// we can alter how verifyAction & verifyReaction works, as it's
// only used by the microphone per now

@@ -88,10 +97,17 @@ }*/

} catch (error) {
this.setGattAvailable();
this.queueOperation("connect", this._connect.bind(this));
if ("thingyController" in this) {
this.thingyController.setGattStatus(true);
this.thingyController.enqueue(this.type, "connect", () => this._connect());
}
this.characteristic.connected = false;
this.processError(error);
if ("utilities" in this) {
this.utilities.processEvent("error", this.type, error);
}
return false;
}
} else {
this.queueOperation("connect", this._connect.bind(this));
this.thingyController.enqueue(this.type, "connect", () => this._connect());
return false;

@@ -101,7 +117,3 @@ }

async _wait(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async _read(returnRaw = false) {
_read = async (returnRaw = false) => {
try {

@@ -119,15 +131,17 @@ let connectIteration = 0;

if (connectIteration === 50) {
const e = new Error(`As we couldn't connect to the ${this.type} feature, the read operation can't be executed`);
this.processError(e);
if (connectIteration === 250) {
const error = new Error(`As we couldn't connect to the ${this.type} feature, the read operation can't be executed`);
this.utilities.processEvent("error", this.type, error);
return false;
}
// waiting for the connect operation to go through
await this._wait(200);
// waiting a set amount of time for any ongoing BLE operation to conclude
await this.utilities.wait(20);
}
this.thingyController.addExecutedOperation(this.type, "read");
if (!this.hasProperty("read")) {
const e = new Error(`The ${this.type} feature does not support the read method`);
this.processError(e);
const error = new Error(`The ${this.type} feature does not support the read method`);
this.utilities.processEvent("error", this.type, error);
return false;

@@ -137,4 +151,4 @@ }

if (!this.characteristic.decoder) {
const e = new Error("The characteristic you're trying to read does not have a specified decoder");
this.processError(e);
const error = new Error("The characteristic you're trying to read does not have a specified decoder");
this.utilities.processEvent("error", this.type, error);
return false;

@@ -146,12 +160,12 @@ }

if (readIteration === 50) {
const e = new Error("We could not process your read request at the moment due to high operational traffic");
this.processError(e);
if (readIteration === 250) {
const error = new Error("We could not process your read request at the moment due to high operational traffic");
this.utilities.processEvent("error", this.type, error);
return false;
}
if (this.getGattAvailable()) {
this.setGattBusy();
if (this.thingyController.getGattStatus()) {
this.thingyController.setGattStatus(false);
let prop = await this.characteristic.characteristic.readValue();
this.setGattAvailable();
this.thingyController.setGattStatus(true);

@@ -164,3 +178,4 @@ if (returnRaw !== true) {

} else {
await this._wait(200);
// waiting a set amount of time for any ongoing BLE operation to conclude
await this.utilities.wait(20);
}

@@ -171,4 +186,4 @@ }

} catch (error) {
this.setGattAvailable();
this.processError(error);
this.thingyController.setGattStatus(true);
this.utilities.processEvent("error", this.type, error);
return false;

@@ -178,7 +193,7 @@ }

async _write(prop) {
_write = async (prop) => {
try {
if (prop === undefined) {
const e = new Error("You have to write a non-empty body");
this.processError(e);
const error = new Error("You have to write a non-empty body");
this.utilities.processEvent("error", this.type, error);
return false;

@@ -198,15 +213,17 @@ }

if (connectIteration === 50) {
const e = new Error(`As we couldn't connect to the ${this.type} feature, the read operation can't be executed`);
this.processError(e);
if (connectIteration === 250) {
const error = new Error(`As we couldn't connect to the ${this.type} feature, the write operation can't be executed`);
this.utilities.processEvent("error", this.type, error);
return false;
}
// waiting for the connect operation to go through
await this._wait(200);
// waiting a set amount of time for any ongoing BLE operation to conclude
await this.utilities.wait(20);
}
this.thingyController.addExecutedOperation(this.type, "write");
if (!this.hasProperty("write") && !this.hasProperty("writeWithoutResponse")) {
const e = new Error(`The ${this.type} feature does not support the write or writeWithoutResponse method`);
this.processError(e);
const error = new Error(`The ${this.type} feature does not support the write or writeWithoutResponse method`);
this.utilities.processEvent("error", this.type, error);
return false;

@@ -216,4 +233,4 @@ }

if (!this.characteristic.encoder) {
const e = new Error("The characteristic you're trying to write does not have a specified encoder");
this.processError(e);
const error = new Error("The characteristic you're trying to write does not have a specified encoder");
this.utilities.processEvent("error", this.type, error);
return false;

@@ -225,23 +242,21 @@ }

if (writeIteration === 50) {
const e = new Error("We could not process your read request at the moment due to high operational traffic");
this.processError(e);
if (writeIteration === 250) {
const error = new Error("We could not process your read request at the moment due to high operational traffic");
this.utilities.processEvent("error", this.type, error);
return false;
}
if (this.getGattAvailable()) {
if (this.thingyController.getGattStatus()) {
const encodedProp = await this.characteristic.encoder(prop);
this.setGattBusy();
this.thingyController.setGattStatus(false);
await this.characteristic.characteristic.writeValue(encodedProp);
this.setGattAvailable();
this.thingyController.setGattStatus(true);
// emit event for successful write
const ce = new CustomEvent("write", {detail: {
feature: this.type,
value: prop,
}});
this.device.dispatchEvent(ce);
this.utilities.processEvent("write", this.type, prop);
returnValue = true;
} else {
await this._wait(200);
// waiting a set amount of time for any ongoing BLE operation to conclude
await this.utilities.wait(20);
}

@@ -252,4 +267,4 @@ }

} catch (error) {
this.setGattAvailable();
this.processError(error);
this.thingyController.setGattStatus(true);
this.utilities.processEvent("error", this.type, error);
return false;

@@ -259,6 +274,6 @@ }

async _notify(enable, verify = false) {
_notify = async (enable, verify = false) => {
if (!(enable === true || enable === false)) {
const e = new Error("You have to specify the enable parameter (true/false)");
this.processError(e);
const error = new Error("You have to specify the enable parameter (true/false)");
this.utilities.processEvent("error", this.type, error);
return;

@@ -271,3 +286,3 @@ }

if (!connected) {
this.queueOperation("notify", this._notify.bind(this, enable, verify));
this.thingyController.enqueue(this.type, (enable ? "start" : "stop"), () => this._notify(enable, verify));
return false;

@@ -277,5 +292,7 @@ }

this.thingyController.addExecutedOperation(this.type, (enable ? "start" : "stop"));
if (!this.hasProperty("notify")) {
const e = new Error(`The ${this.type} feature does not support the start/stop methods`);
this.processError(e);
const error = new Error(`The ${this.type} feature does not support the start/stop methods`);
this.utilities.processEvent("error", this.type, error);
return;

@@ -292,4 +309,4 @@ }

if (!this.characteristic.decoder) {
const e = new Error("The characteristic you're trying to notify does not have a specified decoder");
this.processError(e);
const error = new Error("The characteristic you're trying to notify does not have a specified decoder");
this.utilities.processEvent("error", this.type, error);
return;

@@ -300,23 +317,12 @@ }

try {
const decodedData = await this.characteristic.decoder(e.target.value);
let ce;
const data = await this.characteristic.decoder(e.target.value);
if (verify) {
ce = new CustomEvent("verifyReaction", {detail: {feature: this.type, data: decodedData}});
this.dispatchEvent(ce);
/*ce = new CustomEvent("verifyReaction", {detail: {feature: this.type, data: decodedData}});
this.dispatchEvent(ce);*/
} else {
this.latestReading.clear();
for (const elem in decodedData) {
this.latestReading.set(elem, decodedData[elem]);
}
const e = new Event("reading");
this.dispatchEvent(e);
ce = new CustomEvent("characteristicvaluechanged", {detail: {feature: this.type, data: decodedData}});
this.device.dispatchEvent(ce);
this.utilities.processEvent(this.type, this.type, data);
}
} catch (error) {
// have to find a way to remove event listeners from characteristics
this.utilities.processEvent("error", this.type, error);
}

@@ -327,11 +333,11 @@ };

if (this.getGattAvailable()) {
this.setGattBusy();
if (this.thingyController.getGattStatus()) {
this.thingyController.setGattStatus(false);
if (enable) {
try {
const csn = await characteristic.startNotifications();
this.setGattAvailable();
this.thingyController.setGattStatus(true);
if (!this.characteristic.hasEventListener) {
csn.addEventListener("characteristicvaluechanged", onReading.bind(this));
csn.addEventListener("characteristicvaluechanged", (e) => onReading(e));
this.characteristic.hasEventListener = true;

@@ -348,6 +354,6 @@ }

} catch (error) {
this.setGattAvailable();
this.queueOperation("notify", this._notify.bind(this, enable, verify));
this.thingyController.setGattStatus(true);
this.thingyController.enqueue(this.type, (enable ? "start" : "stop"), () => this._notify(enable, verify));
this.characteristic.notifying = false;
this.processError(error);
this.utilities.processEvent("error", this.type, error);
return false;

@@ -358,6 +364,13 @@ }

const csn = await characteristic.stopNotifications();
this.setGattAvailable();
this.thingyController.setGattStatus(true);
this.characteristic.notifying = false;
// not ideal
if (this.type === "microhpone") {
if (this.audioCtx) {
this.suspendAudioContext();
}
}
if (this.device.logEnabled) {

@@ -367,12 +380,8 @@ console.log(`Notifications disabled for the ${this.type} feature`);

if (this.audioCtx) {
this.suspendAudioContext();
}
return true;
} catch (error) {
this.setGattAvailable();
this.queueOperation("notify", this._notify.bind(this, enable, verify));
this.thingyController.setGattStatus(true);
this.thingyController.enqueue(this.type, (enable ? "start" : "stop"), () => this._notify(enable, verify));
this.characteristic.notifying = true;
this.processError(error);
this.utilities.processEvent("error", this.type, error);
return false;

@@ -382,3 +391,3 @@ }

} else {
this.queueOperation("notify", this._notify.bind(this, enable, verify));
this.thingyController.enqueue(this.type, (enable ? "start" : "stop"), () => this._notify(enable, verify));
return false;

@@ -388,53 +397,23 @@ }

hasProperty(property) {
hasProperty = (property) => {
return (this.characteristic.characteristic.properties[property] === true ? true : false);
}
async start() {
start = async () => {
return await this._notify(true);
}
async stop() {
stop = async () => {
return await this._notify(false);
}
async read() {
read = async () => {
return await this._read();
}
async write(data) {
write = async (data) => {
return await this._write(data);
}
setGattBusy() {
window.thingyController[this.device.device.id].gattBusy = true;
}
setGattAvailable() {
window.thingyController[this.device.device.id].gattBusy = false;
this.device.dispatchEvent(new Event("gattavailable"));
}
getGattAvailable() {
return !window.thingyController[this.device.device.id].gattBusy;
}
queueOperation(method, f) {
window.thingyController[this.device.device.id].operationQueue.push({feature: this.type, method, f});
this.device.dispatchEvent(new Event("operationqueued"));
}
processError(error) {
console.error(`The ${this.type} feature has reported an error: ${error}`);
const ce = new CustomEvent("error", {detail: {
feature: this.type,
error,
}});
this.device.dispatchEvent(ce);
}
}
export default FeatureOperations;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TCS_FW_VER_UUID,
decoder: this.decodeFirmwareVersion.bind(this),
decoder: this.decodeFirmwareVersion,
};
}
decodeFirmwareVersion(data) {
decodeFirmwareVersion = (data) => {
try {

@@ -52,0 +52,0 @@ const major = data.getUint8(0);

@@ -45,7 +45,7 @@ /*

uuid: this.device.TES_GAS_UUID,
decoder: this.decodeGasData.bind(this),
decoder: this.decodeGasData,
};
}
decodeGasData(data) {
decodeGasData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_GRAVITY_UUID,
decoder: this.decodeGravityVectorData.bind(this),
decoder: this.decodeGravityVectorData,
};
}
decodeGravityVectorData(data) {
decodeGravityVectorData = (data) => {
try {

@@ -52,0 +52,0 @@ const x = data.getFloat32(0, true);

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_HEADING_UUID,
decoder: this.decodeHeadingData.bind(this),
decoder: this.decodeHeadingData,
};
}
decodeHeadingData(data) {
decodeHeadingData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TES_HUMIDITY_UUID,
decoder: this.decodeHumidityData.bind(this),
decoder: this.decodeHumidityData,
};
}
decodeHumidityData(data) {
decodeHumidityData = (data) => {
try {

@@ -52,0 +52,0 @@ const humidity = data.getUint8(0);

@@ -45,8 +45,8 @@ /*

uuid: this.device.TUIS_LED_UUID,
decoder: this.decodeLedData.bind(this),
encoder: this.encodeLedData.bind(this),
decoder: this.decodeLedData,
encoder: this.encodeLedData,
};
}
decodeLedData(data) {
decodeLedData = (data) => {
try {

@@ -53,0 +53,0 @@ const mode = data.getUint8(0);

@@ -45,5 +45,3 @@ /*

uuid: this.device.TSS_MIC_UUID,
decoder: this.decodeMicrophoneData.bind(this),
// verifyAction: this.verifyMicrophoneAction.bind(this),
// verifyReaction: this.verifyMicrophoneReaction.bind(this),
decoder: this.decodeMicrophoneData,
};

@@ -59,10 +57,9 @@

5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767];
this.suspendAudioContext = this.suspendAudioContext.bind(this);
}
async suspendAudioContext() {
suspendAudioContext = async () => {
await this.audioCtx.suspend();
}
decodeMicrophoneData(event) {
decodeMicrophoneData = (event) => {
const audioPacket = event.buffer;

@@ -78,3 +75,3 @@ const adpcm = {

async verifyMicrophoneAction() {
verifyMicrophoneAction = async () => {
try {

@@ -108,3 +105,3 @@ await this.device.mtu._write(140);

_decodeAudio(adpcm) {
_decodeAudio = (adpcm) => {
try {

@@ -188,3 +185,3 @@ // Allocate output buffer

play(audio) {
play = (audio) => {
if (this._audioStack === undefined) {

@@ -198,3 +195,3 @@ this._audioStack = [];

}
_scheduleAudioBuffers() {
_scheduleAudioBuffers = () => {
while (this._audioStack.length > 0) {

@@ -201,0 +198,0 @@ const bufferTime = 0.01; // Buffer time in seconds before initial audio chunk is played

@@ -45,8 +45,8 @@ /*

uuid: this.device.TMS_CONFIG_UUID,
decoder: this.decodeConfigData.bind(this),
encoder: this.encodeConfigData.bind(this),
decoder: this.decodeConfigData,
encoder: this.encodeConfigData,
};
}
decodeConfigData(data) {
decodeConfigData = (data) => {
try {

@@ -74,3 +74,3 @@ const littleEndian = true;

async encodeConfigData(params) {
encodeConfigData = async (params) => {
try {

@@ -77,0 +77,0 @@ if (typeof params !== "object") {

@@ -45,8 +45,8 @@ /*

uuid: this.device.TCS_MTU_REQUEST_UUID,
decoder: this.decodeMtu.bind(this),
encoder: this.encodeMtu.bind(this),
decoder: this.decodeMtu,
encoder: this.encodeMtu,
};
}
decodeMtu(mtuSize) {
decodeMtu = (mtuSize) => {
try {

@@ -62,3 +62,3 @@ const littleEndian = true;

encodeMtu(mtuSize, peripheralRequest = true) {
encodeMtu = (mtuSize, peripheralRequest = true) => {
try {

@@ -65,0 +65,0 @@ if (mtuSize < 23 || mtuSize > 276) {

@@ -45,10 +45,10 @@ /*

uuid: this.device.TCS_NAME_UUID,
decoder: this.decodeName.bind(this),
encoder: this.encodeName.bind(this),
decoder: this.decodeName,
encoder: this.encodeName,
};
}
decodeName(data) {
decodeName = (data) => {
try {
const decoder = new TextDecoder("utf-8");
const decoder = new TextDecoder();
const name = decoder.decode(data);

@@ -64,3 +64,3 @@ const decodedName = {

encodeName(data) {
encodeName = (data) => {
try {

@@ -67,0 +67,0 @@ if (data.length > 10) {

@@ -45,7 +45,7 @@ /*

uuid: this.device.TES_PRESSURE_UUID,
decoder: this.decodePressureData.bind(this),
decoder: this.decodePressureData,
};
}
decodePressureData(data) {
decodePressureData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_QUATERNION_UUID,
decoder: this.decodeQuaternionData.bind(this),
decoder: this.decodeQuaternionData,
};
}
decodeQuaternionData(data) {
decodeQuaternionData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_RAW_UUID,
decoder: this.decodeRawDataData.bind(this),
decoder: this.decodeRawDataData,
};
}
decodeRawDataData(data) {
decodeRawDataData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -49,3 +49,3 @@ /*

decodeRotationData(data) {
decodeRotationData = (data) => {
try {

@@ -52,0 +52,0 @@ // Divide by 2^2 = 4 to get correct values

@@ -45,8 +45,8 @@ /*

uuid: this.device.TSS_CONFIG_UUID,
decoder: this.decodeSoundConfigurationData.bind(this),
encoder: this.encodeSoundConfigurationData.bind(this),
decoder: this.decodeSoundConfigurationData,
encoder: this.encodeSoundConfigurationData,
};
}
decodeSoundConfigurationData(data) {
decodeSoundConfigurationData = (data) => {
try {

@@ -65,3 +65,3 @@ const speakerMode = data.getUint8(0);

async encodeSoundConfigurationData(data) {
encodeSoundConfigurationData = async (data) =>{
try {

@@ -68,0 +68,0 @@ if (typeof data !== "object") {

@@ -46,3 +46,3 @@ /*

uuid: this.device.TSS_SPEAKER_DATA_UUID,
encoder: this.encodeSpeakerData.bind(this),
encoder: this.encodeSpeakerData,
};

@@ -53,3 +53,3 @@

async encodeSpeakerData(data) {
encodeSpeakerData = (data) => {
try {

@@ -56,0 +56,0 @@ if (data.mode === 1) {

@@ -45,7 +45,7 @@ /*

uuid: this.device.TSS_SPEAKER_STAT_UUID,
decoder: this.decodeSpeakerStatus.bind(this),
decoder: this.decodeSpeakerStatus,
};
}
decodeSpeakerStatus(data) {
decodeSpeakerStatus = (data) => {
try {

@@ -52,0 +52,0 @@ const speakerStatus = data.getInt8(0);

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_STEP_UUID,
decoder: this.decodeStepData.bind(this),
decoder: this.decodeStepData,
};
}
decodeStepData(data) {
decodeStepData = (data) => {
try {

@@ -52,0 +52,0 @@ const littleEndian = true;

@@ -45,7 +45,7 @@ /*

uuid: this.device.TMS_TAP_UUID,
decoder: this.decodeTapData.bind(this),
decoder: this.decodeTapData,
};
}
decodeTapData(data) {
decodeTapData = (data) => {
try {

@@ -52,0 +52,0 @@ const direction = data.getUint8(0);

@@ -45,7 +45,7 @@ /*

uuid: this.device.TES_TEMP_UUID,
decoder: this.decodeTemperature.bind(this),
decoder: this.decodeTemperature,
};
}
decodeTemperature(data) {
decodeTemperature = (data) => {
try {

@@ -52,0 +52,0 @@ const integer = data.getInt8(0);

@@ -33,3 +33,2 @@ /*

import AdvertisingParametersService from "./AdvertisingParametersService.js";
import EventTarget from "./EventTarget.js";
import MicrophoneSensor from "./MicrophoneSensor.js";

@@ -64,2 +63,5 @@ import MTUService from "./MTUService.js";

import BatteryService from "./BatteryService.js";
import ThingyController from "./ThingyController.js";
import Utilities from "./Utilities.js";
import EventTarget from "./EventTarget.js";

@@ -69,3 +71,2 @@ class Thingy extends EventTarget {

super();
this.logEnabled = options.logEnabled;

@@ -132,4 +133,4 @@ this.connected = false;

this.addEventListener("characteristicvaluechanged", this.receiveReading.bind(this));
this.addEventListener("gattavailable", this.handleGattAvailable.bind(this));
this.addEventListener("gattavailable", () => this.executeQueuedOperations());
this.addEventListener("operationqueued", () => this.executeQueuedOperations());

@@ -168,3 +169,3 @@ this.advertisingparameters = new AdvertisingParametersService(this);

async connect() {
connect = async () => {
try {

@@ -181,6 +182,8 @@ // Scan for Thingys

optionalServices: this.serviceUUIDs,
});
})
this.connected = true;
this.device.addEventListener('gattserverdisconnected', (e) => this.onDisconnected(e));
this.setConnected(true);
if (this.logEnabled) {

@@ -193,22 +196,7 @@ console.log(`Found Thingy named "${this.device.name}", trying to connect`);

if (window.thingyController === undefined) {
window.thingyController = {};
}
this.thingyController = new ThingyController(this);
this.utilities = new Utilities(this);
if (window.thingyController[this.device.id] === undefined) {
window.thingyController[this.device.id] = {};
}
return true;
if (window.thingyController[this.device.id].gattBusy === undefined) {
window.thingyController[this.device.id].gattBusy = false;
}
if (window.thingyController[this.device.id].operationQueue === undefined) {
window.thingyController[this.device.id].operationQueue = [];
}
if (window.thingyController[this.device.id].executingQueuedOperations === undefined) {
window.thingyController[this.device.id].executingQueuedOperations = false;
}
if (this.logEnabled) {

@@ -218,24 +206,9 @@ console.log(`Connected to "${this.device.name}"`);

} catch (error) {
this.connected = false;
const e = new Error(error);
throw e;
}
}
this.setConnected(false);
receiveReading(reading) {
const source = reading.detail.feature;
const data = reading.detail.data;
const featureSpecificEvent = new CustomEvent(`${source}`, {detail: data});
if ("utilities" in this) {
this.utilities.processEvent("error", "thingy", error);
}
this.dispatchEvent(featureSpecificEvent);
}
// used to make sure that operations are executed, without regard to the operation's outcome
handleGattAvailable() {
// considering changing this to an array of the actual operations executed to use in the failcheck in executeQueuedOperations
// thus we can keep track of both the number of operations executed and their details
window.thingyController[this.device.id].numExecutedOperationsWhileExecutingQueuedOperations++;
if (!window.thingyController[this.device.id].executingQueuedOperations && window.thingyController[this.device.id].operationQueue.length !== 0 && !window.thingyController[this.device.id].gattBusy) {
this.executeQueuedOperations();
return false;
}

@@ -247,86 +220,106 @@ }

// if an operation fails three times and seemingly no other operations are executed at the same time, the operation is discarded.
async executeQueuedOperations() {
executeQueuedOperations = async () => {
try {
window.thingyController[this.device.id].executingQueuedOperations = true;
window.thingyController[this.device.id].numExecutedOperationsWhileExecutingQueuedOperations = 0;
const triedOperations = {};
let operation;
if (!this.thingyController.getExecutingQueuedOperations()) {
if (this.thingyController.getNumQueuedOperations() !== 0) {
if (this.thingyController.getGattStatus()) {
this.thingyController.setExecutingQueuedOperations(true);
const triedOperations = {};
let operation;
let totalOperationsExecutedUntilLastIteration = 0;
let totalOperationsExecutedSinceLastIteration = 0;
let totalOperationsExecutedUntilLastIteration = 0;
let totalOperationsExecutedSinceLastIteration = 0;
while (this.thingyController.getNumQueuedOperations() !== 0) {
if (!this.getConnected()) {
break;
}
totalOperationsExecutedSinceLastIteration = this.thingyController.getNumExecutedOperations() - totalOperationsExecutedUntilLastIteration;
totalOperationsExecutedUntilLastIteration = this.thingyController.getNumExecutedOperations();
operation = this.thingyController.dequeue();
if (!(operation.feature in triedOperations)) {
triedOperations[operation.feature] = {};
}
if (!(operation.method in triedOperations[operation.feature])) {
triedOperations[operation.feature][operation.method] = 0;
}
triedOperations[operation.feature][operation.method]++;
const successful = await operation.f();
while (window.thingyController[this.device.id].operationQueue.length !== 0) {
if (!this.connected) {
break;
}
// this condition will hopefully never be met
if (triedOperations[operation.feature][operation.method] === 10 && successful !== true) {
this.thingyController.removeQueuedOperation(operation);
this.utilities.processEvent("operationdiscarded", "thingy", operation);
}
if (triedOperations[operation.feature][operation.method] >= 3) {
if (successful !== true) {
if (totalOperationsExecutedSinceLastIteration < 2) {
if (totalOperationsExecutedSinceLastIteration === 1) {
const op = this.thingyController.getExecutedOperation(this.thingyController.getNumExecutedOperations() - 1);
totalOperationsExecutedSinceLastIteration = window.thingyController[this.device.id].numExecutedOperationsWhileExecutingQueuedOperations - totalOperationsExecutedUntilLastIteration;
totalOperationsExecutedUntilLastIteration = window.thingyController[this.device.id].numExecutedOperationsWhileExecutingQueuedOperations;
operation = window.thingyController[this.device.id].operationQueue.shift();
if (!(operation.feature in triedOperations)) {
triedOperations[operation.feature] = {};
}
if (op.feature !== operation.feature || op.method !== operation.method) {
continue;
}
}
if (!(operation.method in triedOperations[operation.feature])) {
triedOperations[operation.feature][operation.method] = 0;
}
triedOperations[operation.feature][operation.method]++;
const successful = await operation.f();
if (triedOperations[operation.feature][operation.method] >= 3) {
if (successful !== true) {
if (totalOperationsExecutedSinceLastIteration === 1) {
// we have now tried this particular operation three times.
// It's still not completing successfully, and no other operations
// are going through. We are therefore discarding it.
// see handleGattAvailable
for (let i=0;i<window.thingyController[this.device.id].operationQueue.length;i++) {
const op = window.thingyController[this.device.id].operationQueue[i];
if (operation.feature === op.feature && operation.method === op.method) {
window.thingyController[this.device.id].operationQueue.splice(i, 1);
i--;
// we have now tried this particular operation three times.
// It's still not completing successfully, and no other operations
// are going through. We are therefore discarding it.
this.thingyController.removeQueuedOperation(operation);
this.utilities.processEvent("operationdiscarded", "thingy", operation);
}
}
}
this.dispatchOperationDiscardedEvent(operation);
}
}
this.thingyController.setExecutingQueuedOperations(false);
}
}
}
window.thingyController[this.device.id].executingQueuedOperations = false;
}
} catch (error) {
// some error occurred, do something
window.thingyController[this.device.id].executingQueuedOperations = false;
this.thingyController.setExecutingQueuedOperations(false);
this.utilities.processEvent("error", "thingy", error);
}
}
dispatchOperationDiscardedEvent(operation) {
if (this.logEnabled) {
console.log(`The ${operation.method} operation on the ${operation.feature} feature could not be performed at this moment. An event containing the operation's details has been dispatched under the name 'operationdiscarded'`);
getConnected = () => {
return this.connected;
}
setConnected = (bool) => {
this.connected = bool;
}
resetDeviceProperties = () => {
this.setConnected(false);
this.thingyController.terminate();
}
onDisconnected = ({target}) => {
if (!this.getConnected()) {
if (this.logEnabled) {
console.log(`Disconnected from device named ${target.name}`);
}
} else {
this.resetDeviceProperties();
this.utilities.processEvent("disconnected", "thingy");
}
this.device.dispatchEvent(new CustomEvent("operationdiscarded", {detail: operation}));
}
async disconnect() {
disconnect = async () => {
try {
this.connected = false;
this.resetDeviceProperties();
await this.device.gatt.disconnect();
window.thingyController[this.device.id] = undefined;
if (this.logEnabled) {
console.log(`Disconnected from "${this.device.name}"`);
}
return true;
} catch (error) {
this.connected = true;
const e = new Error(error);
throw e;
this.utilities.processEvent("error", "thingy", error);
return false;
}

@@ -333,0 +326,0 @@ }

{
"name": "thingy52_web_bluetooth",
"version": "1.3.5",
"version": "1.4.0-transpiled",
"description": "API for connecting to and interacting with Nordic Semiconductor's Thingy:52 in the browser",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -110,2 +110,3 @@ # Nordic Thingy:52 for Web Bluetooth

| Advertising parameters | No | Yes | Yes |
| Battery | Yes | Yes | No |
| Button | Yes | No | No |

@@ -125,5 +126,5 @@ | Cloud token | No | Yes | Yes |

| LED | No | Yes | Yes |
| Microphone (in development) | Yes | No | No |
| Microphone | Yes | No | No |
| Motion configuration | No | Yes | Yes |
| MTU (in development) | - | - | - |
| MTU | No | Yes | Yes |
| Name | No | Yes | Yes |

@@ -134,3 +135,5 @@ | Pressure | Yes | No | No |

| Rotation matrix orientation | Yes | No | No |
| Speaker (in development) | - | - | - |
| Sound configuration | No | Yes | Yes |
| Speaker Data | No | No | Yes |
| Speaker Status | Yes | No | No |
| Step counter | Yes | No | No |

@@ -147,15 +150,16 @@ | Tap | Yes | No | No |

- [Thingy](#thingy)
- [Absolute orientation](#absolute-orientation)
- [Advertising parameters](#advertising-parameters)
- [Absolute Orientation](#absolute-orientation)
- [Advertising Parameters](#advertising-parameters)
- [Battery](#battery)
- [Button](#button)
- [Cloud token](#cloud-token)
- [Cloud Token](#cloud-token)
- [Color](#color)
- [Connection parameters](#connection-parameters)
- [Connection Parameters](#connection-parameters)
- [DFU](#dfu)
- [Eddystone url](#eddystone-url)
- [Environment configuration](#environment-configuration)
- [Euler orientation](#euler-orientation)
- [Environment Configuration](#environment-configuration)
- [Euler Orientation](#euler-orientation)
- [Firmware](#firmware)
- [Gas](#gas)
- [Gravity vector](#gravity-vector)
- [Gravity Vector](#gravity-vector)
- [Heading](#heading)

@@ -165,11 +169,13 @@ - [Humidity](#humidity)

- [Microphone](#microphone)
- [Motion configuration](#motion-configuration)
- [Motion Configuration](#motion-configuration)
- [MTU](#mtu)
- [Name](#name)
- [Pressure](#pressure)
- [Quaternion orientation](#quaternion-orientation)
- [Raw data](#raw-data)
- [Rotation matrix orientation](#rotation-matrix-orientation)
- [Speaker](#speaker)
- [Step counter](#step-counter)
- [Quaternion Orientation](#quaternion-orientation)
- [Raw Data](#raw-data)
- [Rotation Matrix Orientation](#rotation-matrix-orientation)
- [Sound Configuration](#sound-configuration)
- [Speaker Data](#speaker-data)
- [Speaker Status](#speaker-status)
- [Step Counter](#step-counter)
- [Tap](#tap)

@@ -185,3 +191,3 @@ - [Temperature](#temperature)

### Absolute orientation
### Absolute Orientation
`thingy.absoluteorientation`

@@ -198,3 +204,3 @@

### Advertising parameters
### Advertising Parameters
`thingy.advertisingparameters`

@@ -213,2 +219,15 @@

### Battery
`thingy.battery`
`event: battery`
Allows interaction with the connected device's battery level
**Supported operations**
- `start` - Starts sending battery level data from the connected device
- `stop` - Terminates sending battery level data from the connected device
- `read` - Reads the connected device's battery level
### Button

@@ -226,3 +245,3 @@ `thingy.button`

### Cloud token
### Cloud Token
`thingy.cloudtoken`

@@ -251,3 +270,3 @@

### Connection parameters
### Connection Parameters
`thingy.connectionparameters`

@@ -310,3 +329,3 @@

### Euler orientation
### Euler Orientation
`thingy.eulerorientation`

@@ -441,3 +460,6 @@

In development
- `read` - Reads the MTU of the connected device
- `write` - Writes the MTU of the connected device.
- **Parameters**:
- MTU - Integer in the range 23 to 276.

@@ -505,12 +527,54 @@

### Speaker
`thingy.speaker`
### Sound Configuration
`thingy.soundconfiguration`
Allows interaction with the connected device's speaker
Allows interaction with the connected device's sound configuration
**Supported operations**
In development
- `read` - Reads the connected device's current sound configuration
- `write` - Writes the sound configuration of the connected device
- **Parameters**:
- Object:
- speakerMode (Sets the speaker mode). Must be one of the integers:
- 1 - Frequency mode.
- 2 - 8-bit PCM mode (used for streaming audio to Thingy).
- 3 - Sample mode.
- microphoneMode (Sets the microphone mode). Must be one of the integers:
- 1 - ADPCM mode.
- 2 - SPL mode.
### Speaker Data
`thingy.speakerdata`
Allows interaction with the connected device's speaker data.
Note that speaker mode has to be set to the desired mode beforehand by writing to [Sound Configuration](#sound-configuration).
**Supported operations**
- `write` - Writes to the speaker of the connected device
- **Parameters**:
- Object:
- mode - Mode of the speaker. Can be one of the following: 1, 2 or 3.
- mode = 1:
- frequency - Frequency in Hz. Integer larger than 0.
- duration - Duration in ms. Integer larger than 0.
- volume - Volume in %. Integer in the range 0 to 100.
- mode = 2:
- data - 8-bit PCM samples. Audio data of size between 20-273 bytes. See audiostream.html in examples folder for example
- mode = 3:
- sample - Sample ID. Integer in the range 0 to 8
### Speaker Status
`thingy.speakerstatus`
`event: speakerstatus`
Allows interaction with the connected device's speaker status
**Supported operations**
- `start` - Starts sending the speaker status from the connected device
- `stop` - Terminates sending the speaker status from the connected device
### Step counter

@@ -517,0 +581,0 @@ `thingy.stepcounter`

{
"compilerOptions": {
"module": "es6",
"allowJs": true,
"target": "es5",
"outDir": "build",
"checkJs": true,
"outDir": "es5",
"checkJs": false,
"lib": [

@@ -13,2 +14,3 @@ "es6",

"exclude": [
"index.js",
"node_modules",

@@ -15,0 +17,0 @@ "docs",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc