SORAJIROをつくった上での課題とか

# はじめに

[MAヒーローズ・リーグ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/heroesleague)の2日目つまりは過去の投稿です。なんかアドベントカレンダーがスカスカだったので入れておきます。とはいっても今回とれた賞とかはないので自己満足記事です。

# つくったもの

つくったものは[SORAJIRO](https://protopedia.net/prototype/2036)です。作品のクオリティはともかくとして、我ながら味のある動画ができたのではないかと思っています。とはいえ周りのレベルが高かったので表彰に行くことは難しかったですね。
とりあえず今回はSORAJIROを作る過程で難しかったことを書いていこうと思います。

# Reactでobnizのnpmパッケージを使うのができなかった。

今回はobnizというマイコンを使って開発を行ったのですが、このobnizをReactで使うことに苦戦しました。[obniz用のnpmパッケージ](https://www.npmjs.com/package/obniz)があるのでそれを使いたかったのですが、謎のエラーで動かず苦戦しました。
実はこのことをFacebookで呟くと@wicketさんに[その解決方法の記事](https://qiita.com/wicket/items/324ab34bfdabeb5767cb)を書いてくださいました。なのですが、今回はライブラリを使わずに直接Websoketを使ってobnizとのやりとりを実装しました（ごめんなさい。。）。

```js
const connectSensor = () => {
    const socket = new WebSocket(host + `/obniz/${sensorId}/ws/1`)
    socket.onmessage = (event) => {
      const arr = JSON.parse(event.data)
      for (let i = 0; i < arr.length; i++) {
        const obj = arr[i]
        if (obj.ws && obj.ws.redirect) {
          socket.onmessage = null
          socket.close()
          setHost(obj.ws.redirect)
          connectSensor()
        }
        if (obj.ws && obj.ws.ready) {
          setSensorId('')
          setConnectable(false)
          socket.send(JSON.stringify([
            {
              io0: {
                direction: "output",
                value: true
              },
            },
            {
              ad1: {
                stream: true
              }
            },
            {
              io2: {
                direction: "output",
                value: false
              },
            },
          ]))
        }
        if (obj.ad1) {
          setData(Number(obj.ad1))
        }
      }
    }
  }
```

これでもコード量は大したことはないのですが、やっぱりライブラリを使ったほうが実装はキレイになるので積極的に使っていきたいところではあります。。。

# ニオイの検出はさすがに難しい

これはもともと難しいと思っていたので真面目に取り組むつもりはなかったのですが（こういうサボりぐせが良くないんだろうなとも思ってますが）、センサーから安定した値を入力させること自体も結構難しかったです。今回実装した処理は

```js
if (data > 0.2) {
  setGalic(galic + 1)
}
```

ぐらいのあまりにもひどすぎる実装なのですが、これでも難しかった（というよりは面倒だった）のは[今回用いたガスセンサ](https://jp.seeedstudio.com/Grove-Gas-Sensor-MQ9.html)の値が安定しなさすぎることでした。これはニオイセンサではなく本来の用途はガス漏れなどの検知などに使うようなものみたいなので、吐いた息からニンニク臭をはかるという特殊な用途には向いてなかったのだろうなと思います（そらそうやで）。

# ニンニク値のリアルタイム同期が難しい

今回SkyWayを使ってビデオチャットを実装しています（実装方法は[自分の記事を参照した](https://qiita.com/ufoo68/items/0680b44c01282d7a89b0)）。そしてSORAJIROに加えたい要素としてセンサー値をお互いにリアルタイムで同期させることをやりたかったのですが、良い実装方法がわからず結局センサー値を相手に送るボタンをつくって妥協する形になりました。データの送信にはSkyWayの[send](https://webrtc.ecl.ntt.com/api-reference/javascript.html#methods-3)メソッドを用いました。

```jsx
export const SkyWay = ({ galic, setCalled }) => {
  const conn = useRef(null)
  ...
  const makeCall = () => {
    const mediaConnection = peer.call(callId, localVideo.current.srcObject)
    conn.current = peer.connect(callId)
    mediaConnection.on('stream', async stream => {
      remoteVideo.current.srcObject = stream
      await remoteVideo.current.play().catch(console.error)
      setCallId('')
      setGalicable(true)
    })
  }
  return (
   ...
        <Button disabled={!galicable} 
          onClick={() => conn.current.send(galic)} color="primary">🧄ニンニクを投げる🧄</Button>
   ...
  )
}
```

# おわりに

まあ改めて記事でまとめてみると結局色々と課題は残っているのだなと思いました。おそらく来年もヒーローズリーグには挑戦するかとは思いますが、SORAJIROには飽きてしまったので別の作品でトライする可能性が高い気がしますが、やっぱり課題があるからこそモノづくりって楽しいなと思います。