はじめに
NRIハッカソン bit.Connect - Hack for NEWSTYLE というイベントに参加してきました。
https://bitconnect.nri.co.jp/
IBMクラウドのファンクションを活用していたのを評価され、IBM賞をいただきました!
企業さんの技術サポートも手厚く、第一線の方に直接Slackで手取り足取り教えてもらえたのでめちゃくちゃ贅沢な時間を過ごせました!
つくったもの
お地蔵さんデモ動画
https://www.youtube.com/watch?v=8mviNWsBKp8
余談ですが、最初は磁石にピップエレキバンを使ってみたんですが、意外と磁力が弱く、動作が安定しないので、100均で買った磁石に付け替えました。
ストーリーなど作品の詳細はこちら
https://protopedia.net/prototype/2151
ハードウェアの実装
今回は2人チームで参加し、私の担当がobnizを用いたハードウェアの部分だったので、実装について困ったことや役に立ったことなどをつらつらと書いていきます
IBMクラウドをはじめて触った友人(AWSは日常的に触ってる人)曰く、とても使いやすかったとのこと
・AWSみたいな迷子になりそうなUIではなく、やりたいことがどうしたらいいのかすぐわかるような素晴らしいUI
・ハッカソンで使うなら、初めてでもこっちの方が楽かもしれない
とのことなので、私も触ってみようかなと思いました。
構成について
今回の作品でobnizでやるべきことは以下の3点でした。
1. IBMクラウドのファンクションからAPIを叩いてハードウェアで動作をさせる
2. 1が起きてから元に戻るまでの時間を計測する
3. 2の結果をIBMクラウドのファンクションに知らせる
1~3の流れは、ユーザーがすぐ行動すれば一瞬ですが、なかなか行動しないユーザーもいると想定され、待機時間が読めません。
なので本来は、1の機能だけを請け負うobnizと2~3の機能だけを請け負うobnizの2台構成でやるべきですが、所持台数の制限と、ハッカソンという限られた時間の中で対応するために、1~3を一つのobnizで実装できるように試行錯誤を行いました。(obnizの木戸さんありがとうございました!)
obnizクラウドでWebhookURLを吐き出す
結論から言うとこれは、今回の要件には適していなかったので他のサービスを利用しました。
obnizクラウドはobnizのホスティングサービスで簡単にWebhookURLを吐き出せました(今回初利用)
obniz のコンソールにアクセスし、デバイスを選択します(デバイスをまだアカウントに紐づけてない人は紐付けをしてから)
いろんなテンプレートがありますが、今回は「空のプロジェクト」を選択
コードをちゃちゃっと書いて
<html><head><metacharset="utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1"/><linkrel="stylesheet"href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"/><script src="https://code.jquery.com/jquery-3.2.1.min.js"></script><script src="https://unpkg.com/obniz@3.x/obniz.js"crossorigin="anonymous"></script></head><body><divid="obniz-debug"></div><divclass="container"><divclass="text-center"><pid="start_date-text">開始時間 : </p><pid="start_date"></p><pid="end_date-text">終了時間 : </p><pid="end_date"></p></div></div><script>//type in your obniz IDvarobniz=newObniz("OBNIZ_ID_HERE");obniz.onconnect=asyncfunction(){// obnizクラウド上での動作かどうかの判定if(Obniz.App.isCloudRunning()){obniz.display.print('===== start');// ソレノイドを0,1に繋ぐvarsolenoid=obniz.wired('Solenoid',{gnd:0,signal:1});solenoid.click();// マグネットスイッチを9,10,11に繋ぐvarct10=obniz.wired("CT10",{gnd:9,vcc:10,signal:11});myFunc=asyncfunction(){conststart_date=newDate();$("#start_date").text(start_date);obniz.display.print("start_date");obniz.display.print(start_date);// マグネットスイッチがONになる(笠が被される)のを待つ(ハッカソンみあふれるコード)awaitct10.stateWait(true);constend_date=newDate();$("#end_date").text(end_date);obniz.display.print("end_date");obniz.display.print(end_date);constscore=end_date-start_dateobniz.display.draw(score);}// APIをキックしてすぐだと、誤作動するので若干ディレイをかけて実行setTimeout(myFunc,1000);// 実際に動かしたコードではないので雰囲気が伝われば$.ajax({type:'POST',// このURLはすでに無効ですurl:'https://b3fcdcbe.us-south.apigw.appdomain.cloud/ojizo/record',data:{score:score},dataType:'json'});}}</script></body></html>
アプリの設定からブラウザ実行にチェックを入れて設定を更新します
デバイス一覧から「Webhook URLの確認」が選択できるようになります
注意点
obnizクラウドではawaitをかけて待機していても、接続が最大30秒までなので今回の要件的には適さないようでした。
待機ができる
以上のことをobnizの木戸さんに相談したところ、 repl.itというサービスで実現できるかもとの情報をいただき、試してみました。
repl.itではNode.jsのホスティングが無料ででき、APIとしても公開できます。
コードをnodejs用にすこし修正し(こちら大変たすけていただきました🙇♂️ありがとうございました🙇♂️)
constexpress=require('express');constObniz=require('obniz');constfetch=require("node-fetch")constapp=express();constport=3000;letsolenoid=null;letct10=null;letobniz=newObniz("xxxxxxxx");obniz.onconnect=function(){console.log("connected")solenoid=obniz.wired('Solenoid',{gnd:0,signal:1});ct10=obniz.wired("CT10",{gnd:9,vcc:10,signal:11});}// トップページに来たときにapp.get('/',async(req,res)=>{//とりあえずレスポンスは先に返す(ブラウザ対策)res.json({"status":"OK"});if(obniz.connectionState==="connected"){obniz.display.print('===== start');solenoid.click();conststart_date=newDate();// $("#start_date").text(start_date);obniz.display.print("start_date");obniz.display.print(start_date);awaitct10.stateWait(true);constend_date=newDate();obniz.display.print("end_date");obniz.display.print(end_date);score=end_date-start_date// $.ajaxはnodejsで使えないのでfetchに変換constdata={user_id:obniz.id,start_date:start_date,end_date:end_date,};awaitfetch('https://b3fcdcbe.us-south.apigw.appdomain.cloud/ojizo/record',{method:"POST",mode:'cors',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)})}})app.listen(port,()=>{console.log(`Example app listening at http://localhost:${port}`)});console.log("wakeup")
これで10分は待機できるようになりました!
まとめ
・ひさびさのハッカソンはすごく楽しい
・ピップエレキバンの磁力はそんなに強くない
・ハードウェアは極力シンプルな動きにしないとツラくなる(今回で言うと、やっぱどうにかobniz二台構成にしたほうがやりやすかったろうなぁ)
・IBMクラウドのファンクションはわかりやすくて便利だぞ