【问题标题】:How to encode a string when sent via WebBluetooth通过 WebBluetooth 发送时如何对字符串进行编码
【发布时间】:2020-06-22 17:20:02
【问题描述】:

我对使用 WebBluetooth 和 Arduino 很陌生。我想创建一个充当条形码阅读器的 PWA。但与其他应用程序相比,我想通过 WebBluetooth 将发现的代码发送到应该模拟键盘的加密狗。我的加密狗基于 Arduino Leonardo 和 HM-10 蓝牙模块。

我的 Arduino 草图是:

// include keyboard
#include <Keyboard.h>

// include softserial
#include <SoftwareSerial.h>

// set pins
const int bluetooth_rx_pin = 10;
const int bluetooth_tx_pin = 11;

const int led_blue = 0;
const int led_green = 1;
const int led_red = 2;
const int led_yellow = 3;

// configure connection to bluetooth module as SoftwareSerial
SoftwareSerial SerialBT(bluetooth_rx_pin, bluetooth_tx_pin);

String input;

void setup() {
  // establish connection to bluetooth module
  SerialBT.begin(9600);
  
  // start keyboard functionality
  Keyboard.begin();

  // set pin mode for LEDs
  pinMode(led_blue, OUTPUT);
  pinMode(led_green, OUTPUT);
  pinMode(led_red, OUTPUT);
  pinMode(led_yellow, OUTPUT);

  // switch on blue LED to show finished setup
  digitalWrite(led_blue, HIGH);
}

void loop() {
  // switch red off an green on to show that the device is ready to recieve data via bluetooth
  digitalWrite(led_green, HIGH);
  digitalWrite(led_red, LOW);
  digitalWrite(led_yellow, LOW);

  // check availability of bluetooth data
  if (SerialBT.available()){
    // switch off green led, switch on red led
    digitalWrite(led_green, LOW);
    digitalWrite(led_red, HIGH);

    // get data from bluetooth serial
    input = SerialBT.readString();

    // print the string
    Keyboard.print(input);

    // switch yellow LED on
    digitalWrite(led_yellow, HIGH);
    
    // send success message
    SerialBT.println("OK");
  }
}

我用于建立连接的 JavaScript 是:

var myCharacteristic;

var deviceName;

var bluetoothConnected = false;

function bluetoothConnect() {
    let serviceUuid = "0000ffe0-0000-1000-8000-00805f9b34fb";

    let characteristicUuid = "0000ffe1-0000-1000-8000-00805f9b34fb";

    navigator.bluetooth.requestDevice({filters: [{services: [serviceUuid]}]})
        .then(device => {
            log('Connecting...');
            deviceName = device.name;
            return device.gatt.connect();
        })
        .then(server => {
            console.log('Getting Service...');
            return server.getPrimaryService(serviceUuid);
        })
        .then(service => {
            console.log('Getting Characteristic...');
            return service.getCharacteristic(characteristicUuid);
        })
        .then(characteristic => {
            myCharacteristic = characteristic;
            return myCharacteristic.startNotifications().then(_ => {
                console.log('> Notifications started');
                log("Connected to: " + deviceName);
                bluetoothConnected = true;
                showContentContainer();
                setBluetoothDeviceName(deviceName);
                myCharacteristic.addEventListener('characteristicvaluechanged',
                    handleNotifications);
            });
        })
        .catch(error => {
            console.log('Argh! ' + error);
        });
}

function bluetoothDisconnect() {
    if (myCharacteristic) {
        myCharacteristic.stopNotifications()
            .then(_ => {
                console.log('> Notifications stopped');
                log("Disconnected")
                myCharacteristic.removeEventListener('characteristicvaluechanged',
                    handleNotifications);
            })
            .catch(error => {
                console.log('Argh! ' + error);
            });
    }
}

function handleNotifications(event) {
    let value = event.target.value;
    log(deviceName + "> " + new TextDecoder().decode(value));
}

function bluetoothSend(text) {
    log("You> " + text);
    myCharacteristic.writeValue(str2ab(text+"\n"))
}

function str2ab(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint16Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
}

function log(str) {
    console.log(str);
}

我用作模板https://github.com/hewittwill/WebBluetooth-Terminal/blob/master/index.html

现在,我只输入了第一个字母。如果我添加控制台输出并在终端中查看它,一切看起来都很好。我已经尝试将字符串拆分为 arduino 上的 char 数组,并分别发送每个 char。这会导致随机输入其他字符。因此,我假设 Arduino 无法正确解码通过蓝牙接收的字符串。

任何帮助表示赞赏。

【问题讨论】:

    标签: c arduino bluetooth web-bluetooth


    【解决方案1】:

    str2ab() 中的代码将字符串转换为使用 UTF-16 编码的ArrayBuffer。像“嗨!”这样的字符串变为{72, 0, 105, 0, 33, 0}。 Arduino 库通常需要 UTF-8(或更可能是 ASCII),因此它们将这些零解释为字符串的结尾,而不是 16 位字符的高位字节。

    除了用于转换从设备接收到的ArrayBuffers 的TextDecoder Javascript 还具有内置的TextEncoder 类,它可以做相反的事情并产生一个填充UTF-8 的ArrayBuffer,这应该被设备正确解释。

    改用bluetoothSend() 的这种实现:

    function bluetoothSend(text) {
        log("You> " + text);
        myCharacteristic.writeValue(new TextEncoder().encode(text+"\n"))
    }
    

    【讨论】:

    • 谢谢!它解决了我的问题。 Arduino 现在正在正确接收数据。但是我仍然对键盘库有疑问。由于我使用的是德语键盘,因此某些字符无法正确打印。有人有胶水怎么解决吗?
    • 我建议将其作为一个单独的问题提出。
    猜你喜欢
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 2015-04-04
    • 1970-01-01
    • 2020-08-16
    • 2010-11-22
    • 1970-01-01
    相关资源
    最近更新 更多