最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

10-對 part8-breakout-ble 的翻譯和搬運

2023-08-15 22:59 作者:Xdz-2333  | 我要投稿

非黑色字體均為我自己添加

圖均為原文中的圖

原文在文章末尾

接收藍(lán)牙數(shù)據(jù)

????????所以我們掌握了廣播技術(shù)并且向外廣播了我們的數(shù)據(jù).但那只是故事的一部分!在這個部分中,我們將要探索如何從另外一個源接收數(shù)據(jù).這個更令人興奮,因為我們要開始使用其他設(shè)備作為遠(yuǎn)程控制器.

????????實際上,我的主意是通過接收來自我的MacBook Pro的觸控板上的藍(lán)牙信息來控制part6中我們寫的breakout游戲.很好,不是嗎?

建立一個藍(lán)牙Breakout控制器

????????讓我們首先建立用于從電腦上廣播的代碼.我們本質(zhì)上需要在代碼中創(chuàng)建一個BLE外設(shè).

????????我們不用從草稿開始建立起所有東西,因為我們不再是裸機(jī)了!我使用Bleno庫(https://github.com/noble/bleno 這玩意好像停止更新了),它在這種工作中是極為流行的.它需要一些Node.js(https://nodejs.org/en/download)的知識,但是我再開始之前也沒有并且我相信你也可以.

????????你裝好Node.js之后,使用npm命令?npm install bleno 來安裝Bleno?.因為我用的是Mac,并且運行最新的Mac OS X 版本(大于Catalina),我需要使用如下三步(https://punchthrough.com/how-to-use-node-js-to-speed-up-ble-app-development/):

  • npm install github:notjosh/bleno#inject-bindings

  • npm install github:notjosh/bleno-mac

  • npm install github:sandeepmistry/node-xpc-connection#pull/26/head

????????我是用Bleno庫中的echo的例子(https://github.com/noble/bleno/tree/master/examples/echo)作為我的基本代碼.這個例子實現(xiàn)了藍(lán)牙外設(shè),暴露了這些服務(wù):

  • 讓一個連接上的設(shè)備讀取一個本地存儲的字節(jié)

  • 讓一個連接上的設(shè)備更新本地存儲的字節(jié)(它也能被從本地修改)

  • 當(dāng)本地存儲的字節(jié)發(fā)生變化時,讓一個連接上的設(shè)備接收更新

  • 讓一個連接上的設(shè)備取消接收更新

????????當(dāng)你知道我的設(shè)計是讓樹莓派接收在我電腦上運行的服務(wù)的更新時并不會驚訝.本地存儲的字節(jié)的值會在本地更新來反映當(dāng)前變化時的鼠標(biāo)狀態(tài).每當(dāng)我移動我MacBookPro的鼠標(biāo)時,樹莓派都會被通知,就像有魔法一樣!

????????你可以看到我對Bleno的echo 例子所做的改動,它在part8-breakou-ble中的controller子文件夾中.它終究是使用 iohook(https://github.com/wilix-team/iohook),所以我使用?npm install iohook 安裝了iohook.這些是有趣的位(其他的比較無聊).:

var ioHook = require('iohook');


var buf = Buffer.allocUnsafe(1);

var obuf = Buffer.allocUnsafe(1);

const scrwidth = 1440;

const divisor = scrwidth / 100;


ioHook.on( 'mousemove', event => {

? ?buf.writeUInt8(Math.round(event.x / divisor), 0);


? ?if (Buffer.compare(buf, obuf)) {

? ? ? e._value = buf;

? ? ? if (e._updateValueCallback) e._updateValueCallback(e._value);

? ? ? buf.copy(obuf);

? ?}

});


ioHook.start();

????????在這里,我捕捉了鼠標(biāo)的x坐標(biāo),并且把它轉(zhuǎn)換成0(屏幕左邊)到100(屏幕右邊)之間的數(shù)字.如果它從我們之前看到的數(shù)值變化,我們更新回調(diào)的值.(我們的樹莓派只需要知道什么時候位置更新了).只要回調(diào)函數(shù)更新,那么任何連上的設(shè)備都將被通知.

????????我們有一個自己的藍(lán)牙游戲控制器.盡管有些粗糙.你可以使用命令 node main.js 來運行它,但是它不會做什么,如果沒有東西連上的話.

讓樹莓派連上Breakout控制器

????????main.js,當(dāng)它運行的時候,在那里廣播藍(lán)牙調(diào)制調(diào)解器是空閑可用的,和我們的埃迪斯通燈塔是一樣的技術(shù).現(xiàn)在我們樹莓派這邊的任務(wù)是:

  • 開始監(jiān)聽(或者說掃描)這些廣播,這樣我們可以知道哪里echo服務(wù)可以被找到

  • 找到它就連到echo服務(wù)上

  • 訂閱來接收鼠標(biāo)位置的更新

  • 監(jiān)聽這些更新,一旦接收到后就做些事情

????????記得我提到了我們在part7-Bluetooth中所討論過的 run_search函數(shù)嗎?它就是做這個的.這次注釋掉 run_eddystone() 函數(shù)并且讓 run_search() 運行,當(dāng)你的echo服務(wù)在電腦上運行時.當(dāng)你的手指在觸控板上滑動時,你應(yīng)該在樹莓派上看到更新!

????? ?run_search() 使藍(lán)牙控制器進(jìn)入掃描模式而不是廣播(看到part7-Bluetooth中的鏈接來了解這是怎么做到的). kernel.c 中的 bt_search() 被反復(fù)調(diào)用直到它接收到了特殊的廣播數(shù)據(jù) -- 即注意到了echo 服務(wù)的服務(wù)ID空閑(十六進(jìn)制代碼位 0xEC00),即它的廣播名字"echo"?.如果它看見了相同的廣播報告,然后它就假設(shè)它找到目標(biāo).原始的藍(lán)牙設(shè)備地址會被記錄.

????????我們發(fā)送 connect() 來要求地址(TI的文檔中LE創(chuàng)造一個鏈接)并且現(xiàn)在反復(fù)調(diào)用 bt_conn() 知道我們被通知鏈接成功完成.當(dāng)這個完成后,我們得到一個非零的 connection_handle . 我們從現(xiàn)在使用這個來確認(rèn) 來自/到 echo 服務(wù)的通信.

????????接下來我們使用在 bt.c 文件里的sendACLsubscribe() 中的這個句柄來發(fā)送訂閱請求.我們告訴他對接收它存儲的值(或者字符)的更新 感興趣.我實際上做了很多反向工程來得到這些代碼.HCL之上的ACL 數(shù)據(jù)包并沒有很多文檔.讀一下這個(https://forums.raspberrypi.com//viewtopic.php?t=233140)來了解我是如何成功的.樹莓派官方操作系統(tǒng)上的 gettool 和 hcitool 被證明是我的好朋友!

????????最后,我們反復(fù)調(diào)用 acl_poll() 來看這里是否有更新在等待.到達(dá)我們這里的數(shù)據(jù)是 ACL 包的形式,除了其他東西,它識別它向其發(fā)送/使用的通信的句柄(值得與我們記錄的句柄進(jìn)行核對,這樣我們直到它是為我們發(fā)的)和長度以及操作碼.

原作者給出的ACL格式說明圖

????????操作碼 0x1B 代表了 "ATT 句柄值提醒" (TI 文檔中的 ATT_HandleValueNoti ).這就是我們要找的更新?在part7里面只是單純的打印出更新值來展示它已經(jīng)被接收到了.

最后一公里

????????有了這個,這樣part6和part7的代碼就能很好的運行,合并他們來創(chuàng)造一個可以運行的通過藍(lán)牙控制的Breakout實現(xiàn)!畢竟這正是我最終得到part8代碼的原因……如果你卡住了,都在我的倉庫里.

????????好運!下次,我們將著眼于在游戲玩法中添加聲音……


Receiving Bluetooth data

So we've mastered advertising and we're broadcasting data out into the World. But that's only half the story! In this part, we'll be exploring how to receive data from an external source. This is much more exciting as we can begin to use other devices as remote controllers.


In fact, my idea for this part is to control the Breakout game we wrote in part6 by receiving data from the trackpad on my MacBook Pro over Bluetooth! Neat, eh?


Building a Bluetooth Breakout controller

Let's first build the controller code for broadcasting from the laptop. We essentially need to create a BLE peripheral in code.


We don't need to build everything from scratch since we're not on bare metal any more! I used the [Bleno library](https://github.com/noble/bleno), which is extremely popular for this kind of work. It requires some [Node.js](https://nodejs.org/en/download/) knowledge, but I didn't have any before I started and so I'm sure you'll be fine too.


Once you've got Node.js installed, use `npm` to install Bleno with `npm install bleno`. Because I'm on a Mac and running a recent version of Mac OS X (> Catalina), I needed to do this using [these three steps](https://punchthrough.com/how-to-use-node-js-to-speed-up-ble-app-development/) instead:


?* `npm install github:notjosh/bleno#inject-bindings`

?* `npm install github:notjosh/bleno-mac`

?* `npm install github:sandeepmistry/node-xpc-connection#pull/26/head`


I used the [echo example](https://github.com/noble/bleno/tree/master/examples/echo) in the Bleno repository as my base code. This example implements a Bluetooth peripheral, exposing a service which:


?* lets a connected device read a locally stored byte value

?* lets a connected device update the locally stored byte value (it can be changed locally too...!)

?* lets a connected device subscribe to receive updates when the locally stored byte value changes

?* lets a connected device unsubscribe from receiving updates


You won't be surprised to know that my design is for our Raspberry Pi to subscribe to receive updates from this service running on my laptop. That locally stored byte value will be updated locally to reflect the current mouse cursor position as it changes. Our Raspberry Pi will then be notified every time I move the mouse on my MacBook Pro as if by magic!


You can see the changes I made to the Bleno echo example to implement this in the _controller_ subdirectory of this part8-breakout-ble. They boil down to making use of [iohook](https://github.com/wilix-team/iohook), which I installed using `npm install iohook`. Here's the interesting bit (the rest is just plumbing):


```c

var ioHook = require('iohook');


var buf = Buffer.allocUnsafe(1);

var obuf = Buffer.allocUnsafe(1);

const scrwidth = 1440;

const divisor = scrwidth / 100;


ioHook.on( 'mousemove', event => {

? ?buf.writeUInt8(Math.round(event.x / divisor), 0);


? ?if (Buffer.compare(buf, obuf)) {

? ? ? e._value = buf;

? ? ? if (e._updateValueCallback) e._updateValueCallback(e._value);

? ? ? buf.copy(obuf);

? ?}

});


ioHook.start();

```


Here, I'm capturing the x coordinate of the mouse cursor and translating it into a number between 0 (far left of the screen) and 100 (far right of the screen). If it changes from the previous value we saw, we update the callback value (our Raspberry Pi only needs to know when the position has changed). As the callback value is updated, so any subscribed devices will be notified.


And we have ourselves a working, albeit a bit hacky, Bluetooth game controller! You can run it with the command `node main.js`, but it won't do much without something to connect to it.


Connecting to our Breakout controller from the Raspberry Pi

_main.js_, when running, is sitting there broadcasting the Breakout controller's availability publicly, using exactly the same techniques that our Eddystone beacon used. Our tasks on the Pi are now:


?* to start listening (called "scanning") for these adverts so we know where the echo service can be found

?* to connect to the echo service, having found it

?* to subscribe to receive its updates on cursor position

?* to listen for these updates and do something upon receipt


Remember I mentioned that we'd discuss the `run_search()` function in part7-bluetooth? Well, this is exactly what it does. This time comment out the `run_eddystone()` function and let `run_search()` run whilst your echo service is running on the laptop. As you wiggle your finger on the trackpad, you should see the updates coming through on the Pi!


Instead of advertising, `run_search()` puts the Bluetooth controller into scanning mode (see links in part7-bluetooth to learn more about how this is done). `bt_search()` in _kernel.c_ is then called repeatedly until it receives some specific advertising data - namely a notification of the availability of the echo service's Service ID (hexadecimal number 0xEC00), as well as its broadcast name 'echo'. If it sees both in the same advertising report then it assumes it's found what it's looking for. The originating Bluetooth Device Address is noted.


We send a `connect()` request to that address (LE Create Connection in the TI docs) and now call `bt_conn()` repeatedly until we're notified that the connection has completed successfully. When this happens, we get a non-zero `connection_handle`. We'll use this to identify communications from/to the echo service from now on.


Next we send a subscription request to the service using that handle in `sendACLsubscribe()` in _bt.c_. We tell it that we're interested in receiving updates to its stored value (or "characteristic"). I actually did a lot of reverse-engineering to get to this code. ACL data packets over HCI are not widely documented. Have a read of [this forum thread](https://www.raspberrypi.org/forums/viewtopic.php?t=233140) to see the kind of things I did to succeed. `gatttool` and `hcitool` on Raspbian turned out to be my very good friends!


Finally, we call `acl_poll()` repeatedly to see if there are any updates waiting. The data comes to us in the form of an ACL packet, which identifies, amongst other things, the connection handle it was sent to/using (worth checking against our recorded handle so we know it's for us) as well as data length and an opcode.?


![ATT handle value notification opcode 1b](images/8-opcode-1b.png)


The opcode 0x1B represents a "ATT handle value notification" (ATT_HandleValueNoti in the TI docs). Those are the updates we're looking for. In part7 we simply print the update to debug to show it's been received.


The last mile

With this, it's a good exercise to take part6 and part7 code and merge them to form a working Breakout implementation that's controlled via Bluetooth! After all, that's exactly how I ended up with the part8 code... If you get stuck, it's all in my repo.


Good luck! Next time, we'll look at adding sound to the gameplay...



10-對 part8-breakout-ble 的翻譯和搬運的評論 (共 條)

分享到微博請遵守國家法律
龙江县| 永春县| 台南市| 昌宁县| 天台县| 汤阴县| 阳城县| 潞城市| 依兰县| 和政县| 宁强县| 喀喇沁旗| 图片| 娱乐| 舞阳县| 南京市| 乐都县| 洛南县| 宜黄县| 阿克陶县| 松原市| 木里| 平阴县| 东乡族自治县| 偃师市| 华亭县| 旺苍县| 炎陵县| 平利县| 长白| 宝应县| 霍山县| 临泽县| 菏泽市| 绥中县| 安远县| 桐城市| 台北县| 上林县| 金门县| 德清县|