node.jsでマイコンボード(ARDUINO UNO)と会話2

前回では下記の1.~3.までをしました。

  1. Arduino UNOとBME280をつなぎ温度、気圧、湿度を取得
  2. Arduino UNOとPCをシリアルポートで通信してデータを取り込む
  3. PC側のシリアル通信プログラムはnode.jsで作る
  4. 上記で作成した通信プログラムとREST APIで通信してnode.js+VueでBME280のデータを表示する

今回は4.のデータを取得node.js+Vue.jsでデータ表示を行いたいと思います。

Vue.jsのインストール

Vue-cliを使って試そうと思いますので以下のようにインストールします。

> npm install -g @vue/cli
> vue create vue_bme280
> cd vue_bme280
> npm run serve

でひとまずテンプレートを実行して確認します。

テンプレート変更

テンプレート修正して、希望のものに近づけていきます。 ./componentsにBme280Api.vueを作成。HelloWorld.vueからコピペ、いらない所を削除で作ります。

<template>
  <div class="bme280api">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'Bme280Api',
  props: {
    msg: String
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

App.vueを修正してBme280Api.vueを呼び出します。

axiosを利用する。

どうもAPIを呼び出すのはaxiosというライブラリを使うのが良いみたいです。 まずはここに書いている通りにaxiosをインストールします。

github.com

まあ、行ったのは

> npm i axios

だけですけどね。 そして以下を参考にApp.vueを改造します。

jp.vuejs.org

改造したソースコードです。

<template>
  <div id="app">
    <Bme280Api msg="API BME280" :info="info"/>
  </div>
</template>

<script>
import Bme280Api from './components/Bme280Api.vue'
import axios from 'axios'

export default {
  name: 'app',
  components: {
    Bme280Api
  },
  data () {
    return {
      info: ""
    }
  },
  mounted () {
    axios
      .get('http://localhost:3000/api/bme280')
      .then(response => (this.info = response.data))
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

そして前回のコードを動作させてAPI呼び出し!

mechagocha.hatenablog.com

ところが動作させようとしたとき問題発生。なんかCORSがどうのこうのとエラーが出ていてBME280のデータが取得できない。。。

そこで下記を参考に前回のコードを変更します。 qiita.com

以下が修正後

/* 1. expressモジュールをロードし、インスタンス化してappに代入。*/
var express = require("express");
var app = express();

// CORSを許可する
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
  });

/* 2. listen()メソッドを実行して3000番ポートで待ち受け。*/
var server = app.listen(3000, function(){
    console.log("Node.js is listening to PORT:" + server.address().port);
});

/* 3. 以後、アプリケーション固有の処理 */

const uartData = require("./serial.js");
uartData.startParser();

// dataを取得するAPI

app.get("/api/bme280", function(req, res, next){
    let bme280=uartData.getBme280Data();
    res.json(bme280);
});

修正後再立ち上げしてみると、あら不思議。。。上手く動くじゃないですか。ありがとうございます。

でBme280Api.vueをもう一度変更してとりあえずデータ表示させます。

<template>
  <div class="bme280api">
    <h1>{{ msg }}</h1>
    <p>{{info}}</p>
    <p>温度:{{tempData}}℃</p>
    <p>気圧:{{pressureData}}HP</p>
    <p>湿度:{{humidityData}}%</p>
  </div>
</template>

<script>
export default {
  name: 'Bme280Api',
  props: {
    msg: String,
    info: {}
  },
  computed:{
    tempData: function(){
      return this.info.temperature;
    },
    pressureData: function(){
      return this.info.pressure;
    },
    humidityData: function(){
      return this.info.humidity;
    },
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

でけました。ブラウザで表示されました。

f:id:mechagocha:20190402232223j:plain
ブラウザで表示

よし!ここまでできて大満足です。次回はデータを綺麗に表示させよう。


ではまた。