Airhorner with added Web USB

This new year Andre Bandarra left me a little surprise on my desk: A physical airhorner built with Web USB!
Check it out, well actually it will be hard, Andre created a small sketch for an Arduino Uno that connects over USB that is not yet available, however the code on the site is rather neat and not too complex if you are experienced with any form of USB programming.


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan

<p>This new year <a href="https://twitter.com/andreban">Andre Bandarra</a> left me a little surprise on my desk: A physical airhorner built with Web USB!</p> <figure><video src="https://paul.kinlan.me/videos/2020-01-06-airhorner-with-added-web-usb-0.mp4" alt="Airhorner with usb" controls></video></figure> <p><a href="https://webusb-horn.firebaseapp.com/">Check it out</a>, well actually it will be hard, Andre created a small sketch for an Arduino Uno that connects over USB that is not yet available, however the code on the site is rather neat and not too complex if you are experienced with any form of USB programming.</p> <p>Andre's code connects to the device and waits for the user to approve, configures the connection, and then continuously reads from the device looking for the string 'ON' (which is a flag that is set when the button is pressed).</p> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-Javascript" data-lang="Javascript"><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">HardwareButton</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">airhorn</span>) { <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">airhorn</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">airhorn</span>; <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">decoder</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">TextDecoder</span>(); <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">connected</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>; <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">self</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">this</span>; <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">_loopRead</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> <span style="color:#66d9ef">function</span>() { <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">'no device'</span>); <span style="color:#66d9ef">return</span>; } <span style="color:#66d9ef">try</span> { <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">transferIn</span>(<span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">64</span>); <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">command</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">decoder</span>.<span style="color:#a6e22e">decode</span>(<span style="color:#a6e22e">result</span>.<span style="color:#a6e22e">data</span>); <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">command</span>.<span style="color:#a6e22e">trim</span>() <span style="color:#f92672">===</span> <span style="color:#e6db74">'ON'</span>) { <span style="color:#a6e22e">airhorn</span>.<span style="color:#a6e22e">start</span>({<span style="color:#a6e22e">loop</span><span style="color:#f92672">:</span> <span style="color:#66d9ef">true</span>}); } <span style="color:#66d9ef">else</span> { <span style="color:#a6e22e">airhorn</span>.<span style="color:#a6e22e">stop</span>(); } <span style="color:#a6e22e">self</span>.<span style="color:#a6e22e">_loopRead</span>(); } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">e</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">'Error reading data'</span>, <span style="color:#a6e22e">e</span>); } }; <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">connect</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> <span style="color:#66d9ef">function</span>() { <span style="color:#66d9ef">try</span> { <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">device</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">navigator</span>.<span style="color:#a6e22e">usb</span>.<span style="color:#a6e22e">requestDevice</span>({ <span style="color:#a6e22e">filters</span><span style="color:#f92672">:</span> [{<span style="color:#e6db74">'vendorId'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x2341</span>, <span style="color:#e6db74">'productId'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x8057</span>}] }); <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">device</span>; <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">open</span>(); <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">selectConfiguration</span>(<span style="color:#ae81ff">1</span>); <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">claimInterface</span>(<span style="color:#ae81ff">0</span>); <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">selectAlternateInterface</span>(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>); <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">controlTransferOut</span>({ <span style="color:#e6db74">'requestType'</span><span style="color:#f92672">:</span> <span style="color:#e6db74">'class'</span>, <span style="color:#e6db74">'recipient'</span><span style="color:#f92672">:</span> <span style="color:#e6db74">'interface'</span>, <span style="color:#e6db74">'request'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x22</span>, <span style="color:#e6db74">'value'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x01</span>, <span style="color:#e6db74">'index'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x00</span>, }); <span style="color:#a6e22e">self</span>.<span style="color:#a6e22e">_loopRead</span>(); } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">e</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">'Failed to Connect: '</span>, <span style="color:#a6e22e">e</span>); } }; <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">disconnect</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">async</span> <span style="color:#66d9ef">function</span>() { <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span>) { <span style="color:#66d9ef">return</span>; } <span style="color:#a6e22e">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">controlTransferOut</span>({ <span style="color:#e6db74">'requestType'</span><span style="color:#f92672">:</span> <span style="color:#e6db74">'class'</span>, <span style="color:#e6db74">'recipient'</span><span style="color:#f92672">:</span> <span style="color:#e6db74">'interface'</span>, <span style="color:#e6db74">'request'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x22</span>, <span style="color:#e6db74">'value'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x00</span>, <span style="color:#e6db74">'index'</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0x00</span>, }); <span style="color:#a6e22e">await</span> <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span>.<span style="color:#a6e22e">close</span>(); <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">device</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">null</span>; }; <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">init</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span>() { <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">buttonDiv</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">'#connect'</span>); <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">button</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">buttonDiv</span>.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">'button'</span>); <span style="color:#a6e22e">button</span>.<span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">'click'</span>, <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">connect</span>.<span style="color:#a6e22e">bind</span>(<span style="color:#66d9ef">this</span>)); <span style="color:#a6e22e">button</span>.<span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">'touchend'</span>, <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">connect</span>.<span style="color:#a6e22e">bind</span>(<span style="color:#66d9ef">this</span>)); <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">navigator</span>.<span style="color:#a6e22e">usb</span>) { <span style="color:#a6e22e">buttonDiv</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">'available'</span>); } }; <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">init</span>(); }; </code></pre></div><p>If you are interested in what the Arduino side of things looks like, Andre will release the code soon, but it's directly inspired by the <a href="https://github.com/webusb/arduino">WebUSB examples for Arduino</a>.</p>


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan


Print Share Comment Cite Upload Translate Updates
APA

Paul Kinlan | Sciencx (2020-01-06T13:56:40+00:00) Airhorner with added Web USB. Retrieved from https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/

MLA
" » Airhorner with added Web USB." Paul Kinlan | Sciencx - Monday January 6, 2020, https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/
HARVARD
Paul Kinlan | Sciencx Monday January 6, 2020 » Airhorner with added Web USB., viewed ,<https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/>
VANCOUVER
Paul Kinlan | Sciencx - » Airhorner with added Web USB. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/
CHICAGO
" » Airhorner with added Web USB." Paul Kinlan | Sciencx - Accessed . https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/
IEEE
" » Airhorner with added Web USB." Paul Kinlan | Sciencx [Online]. Available: https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/. [Accessed: ]
rf:citation
» Airhorner with added Web USB | Paul Kinlan | Sciencx | https://www.scien.cx/2020/01/06/airhorner-with-added-web-usb/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.