每次滑块更改时如何通过蓝牙 LE 发送滑块值而不会出现垃圾邮件 "Transaction already in progress" 错误?
How can I send a slider value over Bluetooth LE every time the slider changes without spamming "Transaction already in progress" errors?
我在网站上使用 GUI 通过 BLE 控制电机的速度。每次滑块改变位置时,都会触发一个新的“oninput”事件。当您使用滑块时,这种情况大约会以 50x /sec 的速度发生。因为您一次只能发送一个 BLE 传输,而 BLE 传输需要大约 50 毫秒,所以有很多“交易已经在进行中”的错误。这导致最后几个输入丢失。当您从左向右快速滑动滑块时,步进电机将接收到该位置位于中间某处。我想要一个解决方案:
- 我可以改变滑块,在我松开滑块之前看到步进电机加速和减速。
- 我还希望我停止滑动之前的最终值是步进电机最终确定的值。
这是我的 hacky 解决方案:在输入时调用异步方法尝试发送值。如果它失败了,那么它会检查它是否失败,因为已经有另一个传输正在进行而不是其他错误。如果是这种情况,它会检查它尝试发送的值是否仍然是发送失败后的最新值。只有满足这两个条件,它才会调用自己并重试。
代码如下:
document.getElementById("sldSpeed").oninput = updateSpeed;
let speed = 0;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100} cm/s`;
schrijfRealTimeSpeed(speed);
};
async function schrijfRealTimeSpeed(waarde) {
schrijfUint32Value(karDelta, waarde)
.catch((problem) => {
if (problem.message === "GATT operation already in progress." & waarde === speed)
schrijfRealTimeSpeed(waarde);
});
}
(this schrijfUint32Value(karDelta, waarde) 调用 BLE 模块脚本中的方法并将数字转换为字节数组,然后
使用 Javascript BLE 函数 karakteristiek.writeValueWithResponse(byteArr) )
问题:我在滥用错误系统,这可能效率不高。 git 上的作者说,正确的方法是仅在先前的请求返回承诺后才发送新请求,这样您就不会一开始就收到“GAAT transmission in progress”错误。知道了这一点,是否有更清洁、更高效、更好、更像 javascript 的方法来解决这个问题?
这个对你有用吗
document.getElementById("sldSpeed").oninput = updateSpeed;
let speed = 0;
let firstrun = true;
let lastvalue = 0;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100}cm/s`;
if (firstrun == true)
{
firstrun = false;
schrijfRealTimeSpeed(speed);
}
}
async function schrijfRealTimeSpeed(waarde) {
const realtimepromise = new Promise(async (resolve, reject) => {
if (lastvalue!= waarde)
{
lastvalue = waarde;
await schrijfUint32Value(karDelta, waarde);
resolve();
} else
{
reject();
firstrun = true;
}
});
realtimepromise.then( (val) => schrijfRealTimeSpeed(speed));
}
使用 Ignamuses 解决方案,我能够编写适用于我的应用程序的版本。我删除了一些承诺并添加了网络错误检查以防止无限循环:
let speed = 0;
let busy = false;
let speedLastTransmitted = 0;
document.getElementById("sldSpeed").oninput = updateSpeed;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100}cm/s`;
if (busy === false) {
busy = true;
schrijfRealTimeSpeed(speed);
}
}
async function schrijfRealTimeSpeed(waarde) {
if (speedLastTransmitted === waarde)
busy = false;
else {
schrijfUint32Value(karDelta, waarde)
.then(() => {
speedLastTransmitted = waarde;
schrijfRealTimeSpeed(speed);
})
.catch((err) => {
console.log(err)
});
}
}
我在网站上使用 GUI 通过 BLE 控制电机的速度。每次滑块改变位置时,都会触发一个新的“oninput”事件。当您使用滑块时,这种情况大约会以 50x /sec 的速度发生。因为您一次只能发送一个 BLE 传输,而 BLE 传输需要大约 50 毫秒,所以有很多“交易已经在进行中”的错误。这导致最后几个输入丢失。当您从左向右快速滑动滑块时,步进电机将接收到该位置位于中间某处。我想要一个解决方案:
- 我可以改变滑块,在我松开滑块之前看到步进电机加速和减速。
- 我还希望我停止滑动之前的最终值是步进电机最终确定的值。
这是我的 hacky 解决方案:在输入时调用异步方法尝试发送值。如果它失败了,那么它会检查它是否失败,因为已经有另一个传输正在进行而不是其他错误。如果是这种情况,它会检查它尝试发送的值是否仍然是发送失败后的最新值。只有满足这两个条件,它才会调用自己并重试。
代码如下:
document.getElementById("sldSpeed").oninput = updateSpeed;
let speed = 0;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100} cm/s`;
schrijfRealTimeSpeed(speed);
};
async function schrijfRealTimeSpeed(waarde) {
schrijfUint32Value(karDelta, waarde)
.catch((problem) => {
if (problem.message === "GATT operation already in progress." & waarde === speed)
schrijfRealTimeSpeed(waarde);
});
}
(this schrijfUint32Value(karDelta, waarde) 调用 BLE 模块脚本中的方法并将数字转换为字节数组,然后 使用 Javascript BLE 函数 karakteristiek.writeValueWithResponse(byteArr) )
问题:我在滥用错误系统,这可能效率不高。 git 上的作者说,正确的方法是仅在先前的请求返回承诺后才发送新请求,这样您就不会一开始就收到“GAAT transmission in progress”错误。知道了这一点,是否有更清洁、更高效、更好、更像 javascript 的方法来解决这个问题?
这个对你有用吗
document.getElementById("sldSpeed").oninput = updateSpeed;
let speed = 0;
let firstrun = true;
let lastvalue = 0;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100}cm/s`;
if (firstrun == true)
{
firstrun = false;
schrijfRealTimeSpeed(speed);
}
}
async function schrijfRealTimeSpeed(waarde) {
const realtimepromise = new Promise(async (resolve, reject) => {
if (lastvalue!= waarde)
{
lastvalue = waarde;
await schrijfUint32Value(karDelta, waarde);
resolve();
} else
{
reject();
firstrun = true;
}
});
realtimepromise.then( (val) => schrijfRealTimeSpeed(speed));
}
使用 Ignamuses 解决方案,我能够编写适用于我的应用程序的版本。我删除了一些承诺并添加了网络错误检查以防止无限循环:
let speed = 0;
let busy = false;
let speedLastTransmitted = 0;
document.getElementById("sldSpeed").oninput = updateSpeed;
function updateSpeed() {
speed = document.getElementById("sldSpeed").value;
speed = parseInt(speed * 100);
document.getElementById("lblSpeed").innerHTML = `${speed / 100}cm/s`;
if (busy === false) {
busy = true;
schrijfRealTimeSpeed(speed);
}
}
async function schrijfRealTimeSpeed(waarde) {
if (speedLastTransmitted === waarde)
busy = false;
else {
schrijfUint32Value(karDelta, waarde)
.then(() => {
speedLastTransmitted = waarde;
schrijfRealTimeSpeed(speed);
})
.catch((err) => {
console.log(err)
});
}
}