ClojureScriptとBLE

2017年Clojure Advent Calendar 15日目の記事として書きました。

今年、ニャンパスとして、またプライベートでいろいろとBLEを扱うコードをClojureScriptで書きましたので、まとめてみます。

使用したデバイスは、micro:bitです。秋葉原や通販等で手に入り、BLE、25個のLED、加速度センサーがついている学習用のボードです。ブラウザ上でビジュアルプログラミングでの開発ができたりと面白いので、年末年始に遊んでみてください。

ClojureScriptでの環境の作り方から始まって、micro:bitとPCとの接続、リモートでのLチカを試すというIoTなClojureScriptの内容となってます。

1. ClojureScriptで、BLEな環境を作る


Node.js、npm、Leiningenを入れておいてください。プロジェクトを作ります。

  $ lein new figwheel-node ble

figwheel-nodeテンプレートを使い、できたファイルはこんな感じです。

./project.clj
./README.md
./package.json
./.gitignore
./src
./src/ble
./src/ble/core.cljs
./dev
./dev/user.clj

今回、PC側をBLEのセントラルとして振る舞わせ、micro:bitをペリフェラルとして操作しますので、そのためセントラル側のプログラムとしてnobleというライブラリを使います。
OS毎に依存するものが違いますので、サイトで事前に確認しておいたほうが良いです。


※nobleはMac、Linux、Windows、FreeBSDをサポートしており、僕自身今年nobleを使ったコードをClojureScriptを使って、Windos、Mac、Linuxそれぞれで動かしていて動作は安定していました。

では、nobleを以下のコマンドを実行しておきます。

  $ npm install noble

※普段はlein-npm等を使ってproject.cljでnpmライブラリの依存を管理していますが、今回説明の都合上素直にnpm経由でインストールしています。

nobleのインストールさえ成功すればあとは、ClojureScriptでの開発の準備が整ったことになります。
Figwheelがすでに入っていますので、EmacsからCIDERを使った開発を行う手順は以下のようになります。
  1. Emacsからcider-jack-inでnREPLサーバーを起動
  2. REPL上から、
    (fig-start)
    (cljs-repl)
    と入力。
  3. ターミナルから以下のコマンドを実行。(root権限が必要だったので、"sudo"をつけています。)
    sudo node ./target/js/compiled/ble.js
これで、BLEを操作するためのClojureScriptのREPL環境が整いましたのでレッツ・ハックしていってください。



試しに、周りのBLEデバイスを見つけてくるサンプルです。

  (ns ble.core
    (:require [cljs.nodejs :as nodejs]))

  (def noble (nodejs/require "noble"))

  (nodejs/enable-util-print!)

  (.on noble "stateChange" (fn [state]
                             (if (= state "poweredOn")
                               (.startScanning noble)
                               (.stopScanning noble))))

  (.on noble "discover" (fn [peripheral]
                          (prn peripheral)))

2. micro:bitにClojureScriptからつないでみる


micro:bitのBLEでの接続は、nobleのライブラリを使っても実現できるのですが、JavaScriptのライブラリとして、micro:bit用に特化したライブラリが用意されておりこちらを利用するとさくっとmicro:bitとつなぐことができます。
micro:bit側にまずはファームウェアを書き込みますのでここからhexファイルをダウンロードし、PCとUSBケーブルで繋いだ状態で表示される"MICROBIT"フォルダへhexファイルを放り込んでください。

ClojureScript側は、node-bbc-microbitをまずインストールします。

  $ npm install bbc-microbit

node-bbc-microbitの依存ライブラリでnobleが使われており、すでにnobleを入れていますので、必要な依存関係は解決されているはずです。

さきほど書いたcore.cljsは以下のように書き換えます。

  (ns ble.core
    (:require [cljs.nodejs :as nodejs]))

  (def microbit (nodejs/require "bbc-microbit"))

  (nodejs/enable-util-print!)

  (.discoverAll microbit (fn [bit]
                           (println "id:" (.-id bit) ", addr:" (.-address bit))))

うまくいけば、周囲のmicro:bitを拾って以下のようになるはずです。

  $ sudo node ./target/js/compiled/ble.js
  id: xxxxx, addr: xx:xx:xx:xx:xx:xx

3. Lチカ

この段階でただ繋がっただけなので、せっかくなのでLチカ(LEDを点滅)して終わりにしたいと思います。

micro:bitは、0から3番までのGPIOが扱いやすい形で出ていますので、ワニ口クリップ等で、写真のように配線してください。

ジャンパーワイヤー経由で、LEDと抵抗を繋ぎ、micro:bitの0番ピンと、GNDピンに割り当てています。


最後に、LチカのBLE経由版のコードは以下のとおりです。

(ns ble.core
  (:require-macros [cljs.core.async.macros :refer [go-loop]])
  (:require [cljs.core.async :refer [timeout]]
            [cljs.nodejs :as nodejs]))

(def microbit (nodejs/require "bbc-microbit"))

(def output-pin 0)

(defn toggle-pin [bit]
  (go-loop [seconds 1]
    (prn :seconds seconds)
    (<! (timeout 1000))
    (.writePin bit output-pin (if (= (mod seconds 2) 0) 1 0))
    (recur (inc seconds))))

(defn setup [bit]
  (.pinOutput bit output-pin
              (fn []
                (.pinDigital bit output-pin
                                  (fn [] (toggle-pin bit))))))

(.discover microbit (fn [bit]
                      (println bit)
                      (.connectAndSetup bit #(setup bit))))

まとめ

今回はmicro:bitを使った操作をClojureScriptから試してみました。

Raspberry PiにClojureScriptを入れて、自社で作ったBLEデバイスの制御を行うということも問題なくできています。REPLが使えることは、デバイスの動きを見ながら開発が出来る大変な強みだと思っています。
ぜひIoTな案件でClojureScriptを試してみてください!

コメント

人気の投稿