V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
ideacco
V2EX  ›  JavaScript

JS 如何将 16 进制的数据转成 ArrayBuffer

  •  
  •   ideacco · 2020-12-02 20:29:42 +08:00 · 3300 次点击
    这是一个创建于 1458 天前的主题,其中的信息可能已经有所发展或是发生改变。

    RT,最近在研究蓝牙硬件,通过 Chrome 的 WEB 蓝牙接口实现蓝牙硬件控制的功能,在实现的过程中遇到一个问题, 我们的蓝牙通讯协议上面的命令都是 16 进制的比如: 打开 LED 灯,命令是"0x20",关闭 LED 是 :“0x21”,通过 web API 接口连接成功后,随便传了一个 str 的命令过去,结果就返回错误信息:

    'writeValue' on 'BluetoothRemoteGATTCharacteristic': The provided value is not of type '(ArrayBuffer or ArrayBufferView)
    
    

    就是说这个接口只支持传递 ArrayBuffer 的数据,但是我如何将“0x20”这样的 16 进制命令转换成 ArrayBuffer 呢? 我试了几次,发现 ArrayBuffer 内的数据始终是 10 进制的,只能来 V2 求大神指点一二了

    19 条回复    2020-12-03 01:31:26 +08:00
    ideacco
        1
    ideacco  
    OP
       2020-12-02 20:34:52 +08:00
    之前在 nodejs 上,有一个 Buffer.from 的命令,可以直接将 16 进制传到硬件,在原生 js 上有点蒙了。。。
    rekulas
        2
    rekulas  
       2020-12-02 20:35:13 +08:00
    你用的什么转 new ArrayBuffer(0x20) 试过吗
    rekulas
        3
    rekulas  
       2020-12-02 20:36:22 +08:00
    如果各种方法都不行我怀疑可能和你的传输数据 encode 方法有关
    aloxaf
        4
    aloxaf  
       2020-12-02 20:45:12 +08:00
    虽然我不会 JS,但我感觉你应该是搞错了什么……

    前几天在一个 Python 群也看到有人问了类似的问题。
    你要知道进制是给人看的,而对于人来说 10 进制是最自然的,所以不管你存进去的是什么,最终都会以十进制展示。
    across
        5
    across  
       2020-12-02 20:45:39 +08:00
    假设命令是 8 位长度的,这样么?
    const CMD_BTYE_LENGTH = 8;
    const buffer = new ArrayBuffer(CMD_BTYE_LENGTH);
    const cmd = new DataView(buffer, 0, CMD_BTYE_LENGTH);
    cmd.setInt8(0, 0x21);
    console.log(cmd.getInt8(0));
    ccworker
        6
    ccworker  
       2020-12-02 20:47:28 +08:00
    new Uint8Array([0x21])
    ccworker
        7
    ccworker  
       2020-12-02 20:48:51 +08:00
    var a = new Uint8Array([0x21])
    a.buffer
    ideacco
        8
    ideacco  
    OP
       2020-12-02 20:58:27 +08:00
    @ccworker 感谢回复,a.buffer 打印出来是 33,也就是说变成了 10 进制的了,我想着是 比如 “5A20”,ArrayBuffer 打印出来应该是 [5a,20]
    across
        9
    across  
       2020-12-02 21:07:15 +08:00 via iPhone
    @ideacco tostring ( 16 )的事。
    该补课字符串格式化了....
    ideacco
        10
    ideacco  
    OP
       2020-12-02 21:13:15 +08:00
    @across 主要是 API 要求必须传递 ArrayBuffer 类型。
    aloxaf
        11
    aloxaf  
       2020-12-02 21:18:21 +08:00
    @ideacco 你这问题太过离谱我都不知道该如何向你解释……

    你觉得在 js 里 0x20 == 32 的结果是什么? false ?
    ideacco
        12
    ideacco  
    OP
       2020-12-02 21:43:50 +08:00
    @aloxaf 感谢兄弟的回复,我知道在 js 里面 0x20 就是 32 了,可是我这边的 API 要求使用 ArrayBuffer 类型,但是这个类型你 使用 new Uint8Array([0x20]) 结果是它会传给硬件 32,而硬件支持 10 进制的啊.
    ideacco
        13
    ideacco  
    OP
       2020-12-02 21:44:34 +08:00
    @aloxaf 上面口误,硬件 不支持 10 进制的命令...
    lscho
        14
    lscho  
       2020-12-02 21:49:35 +08:00
    我觉得你应该从传输数据来检查。。。传递 ArrayBuffer 应该需要修改一下传输数据的类型才行,不能用 string 类型
    ideacco
        15
    ideacco  
    OP
       2020-12-02 21:51:37 +08:00
    @lscho 有道理啊,我去试一下,谢谢了
    yggd
        16
    yggd  
       2020-12-02 22:24:40 +08:00
    ysc3839
        17
    ysc3839  
       2020-12-02 22:26:01 +08:00 via Android   ❤️ 1
    个人怀疑你没搞懂计算机处理数据的方式。
    计算机里面存的都是二进制数据,没有十进制或十六进制。
    你说的“十进制”、“十六进制”是程序为了方便用户阅读,把二进制数据转换成十进制或十六进制的字符串,再显示出来。

    个人建议你提供这个硬件的文档或者示例代码,目前的信息太少,无法知道具体该如何解决。
    ideacco
        18
    ideacco  
    OP
       2020-12-03 01:30:48 +08:00
    @yggd 非常感谢参考的文档,已经顺利解决
    ideacco
        19
    ideacco  
    OP
       2020-12-03 01:31:26 +08:00
    @ysc3839 感谢回复,的确是因为自己水平有限,并且还没仔细读文档
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1358 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 17:31 · PVG 01:31 · LAX 09:31 · JFK 12:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.