thingy52_web_bluetooth
Advanced tools
Comparing version 1.3.5 to 1.4.0-transpiled
@@ -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); |
211
js/Thingy.js
@@ -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", |
116
README.md
@@ -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", |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
432303
81
7806
602
2