每次滑块更改时,如何通过蓝牙 LE 发送滑块值,而不会发送垃圾邮件“交易已在进行中”错误?

问题描述

我正在使用网站中的 GUI 通过 BLE 控制电机的速度。每次滑块改变位置时,都会触发一个新的“oninput”事件。当您使用滑块时,这种情况大约会以 50 倍/秒的速度发生。因为您一次只能发送一个 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);
        });
}

(此 schrijfUint32Value(karDelta,waarde) 调用 BLE 模块脚本中的方法并将数字转换为字节数组,然后 使用 Javascript BLE 函数 karakteristiek.writeValueWithResponse(byteArr) )

问题:我在滥用错误系统,这可能效率不高。 git 上的作者说,正确的方法是仅在前一个请求返回承诺后才发送新请求,这样您就不会首先收到“正在进行 GAAT 传输”错误。知道了这一点,有没有更干净、更高效、更好、更像 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 解决方案,我能够编写适用于我的应用程序的版本。我删除了一些承诺并添加了对网络错误的检查以防止无限循环:

@Component
@RequiredArgsConstructor
public class Person {
  @Autowired private Ops op;
  private final PersonRepository personRepository;

  @SneakyThrows
  public Object doTest() {
    personRepository.findPersonWithName();
  }
}

@Repository
public interface PersonRepository {
  @Transactional(readOnly = true)
  @Query(
      value = "SELECT e from #{#entityName} e where  e.name = ?1 )
  Optional<Object> findPersonWithName(String name);


 @Query("SELECT e from #{#entityName} e where e.Occupation = ?1)
  Optional<DataSourceEntity> findByOccupationName(String occupationName);
}