This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

さくらのIotPlatform、駅すぱあとWebサービスを連携させたアプリケーション作成

Last updated at Posted at 2017-04-10

sakura.io、駅すぱあとWebサービスを連携させたアプリケーション作成

以下の画像の「Webサービス連携」部分を説明します。

スクリーンショット 2017-04-10 11.19.30.png

手順

  1. 駅情報を取得してみる
  2. 時刻表をslackに流してみる

駅情報を取得してみる

まず手始めに、node-redで駅すぱあとWebサービスにアクセスし、駅情報をデバッグウィンドウに表示してみましょう。

フローの読み込み

以下のjsonデータをコピーします。

[
    {
        "id": "19b0bb6c.855355",
        "type": "comment",
        "z": "587a8026.d6a8e",
        "name": "駅取得",
        "info": "",
        "x": 90,
        "y": 180,
        "wires": []
    },
    {
        "id": "6a66ce57.3cff9",
        "type": "http request",
        "z": "587a8026.d6a8e",
        "name": "get station",
        "method": "GET",
        "ret": "obj",
        "url": "",
        "tls": "",
        "x": 450,
        "y": 220,
        "wires": [
            [
                "a831f7a0.143f68"
            ]
        ]
    },
    {
        "id": "fd0d2f59.0b0a5",
        "type": "function",
        "z": "587a8026.d6a8e",
        "name": "set url",
        "func": "var stationName = msg.payload\nvar url = encodeURI(context.global.ekispertWebServiceEndpoint + \"/v1/json/station?key=\" + context.global.ekispertWebServiceKey + \"&type=train&limit=1&name=\" + stationName)\nvar newMsg = {\n  url: url\n}\nreturn newMsg",
        "outputs": 1,
        "noerr": 0,
        "x": 310,
        "y": 220,
        "wires": [
            [
                "6a66ce57.3cff9"
            ]
        ]
    },
    {
        "id": "53926285.dfebfc",
        "type": "inject",
        "z": "587a8026.d6a8e",
        "name": "",
        "topic": "stationName",
        "payload": "なんば",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "x": 150,
        "y": 220,
        "wires": [
            [
                "fd0d2f59.0b0a5"
            ]
        ]
    },
    {
        "id": "a831f7a0.143f68",
        "type": "function",
        "z": "587a8026.d6a8e",
        "name": "set station",
        "func": "context.global.stationName = msg.payload.ResultSet.Point.Station.Name\ncontext.global.stationCode = msg.payload.ResultSet.Point.Station.code\n\nreturn {\n  payload: {\n    stationName: context.global.stationName,\n    stationCode: context.global.stationCode\n  }\n}",
        "outputs": 1,
        "noerr": 0,
        "x": 630,
        "y": 220,
        "wires": [
            [
                "d488d6ff.bfd1c8"
            ]
        ]
    },
    {
        "id": "d488d6ff.bfd1c8",
        "type": "debug",
        "z": "587a8026.d6a8e",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "payload",
        "x": 810,
        "y": 220,
        "wires": []
    },
    {
        "id": "8dd4c0c2.b8756",
        "type": "inject",
        "z": "587a8026.d6a8e",
        "name": "Init",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": true,
        "x": 110,
        "y": 120,
        "wires": [
            [
                "ab2b57e3.824908"
            ]
        ]
    },
    {
        "id": "ab2b57e3.824908",
        "type": "function",
        "z": "587a8026.d6a8e",
        "name": "set variables",
        "func": "// 定数\ncontext.global.WebHookURL = \"!!! slackのwebhook urlを記入 !!!\"\ncontext.global.ekispertWebServiceKey = \"!!! 駅すぱあとwebサービスのアクセスキーを記入 !!!\"\ncontext.global.ekispertWebServiceEndpoint = \"http://api.ekispert.jp\"\n\n// 変数\ncontext.global.upperlimit = 0\ncontext.global.lightSensorOutput = 0\ncontext.global.stationCode = \"\"\ncontext.global.stationName = \"\"\ncontext.global.isLightOffNow = false\ncontext.global.isLightOffBefore = false\n",
        "outputs": "0",
        "noerr": 0,
        "x": 270,
        "y": 120,
        "wires": []
    },
    {
        "id": "def1fb54.561a68",
        "type": "comment",
        "z": "587a8026.d6a8e",
        "name": "グローバル変数の定義",
        "info": "",
        "x": 140,
        "y": 80,
        "wires": []
    }
]

メニュー > 読み込み > クリップボード をクリックし、先ほどコピーしたjsonデータを貼り付けて読み込みを押します。

スクリーンショット 2017-04-10 11.52.41.png

スクリーンショット 2017-04-10 11.53.24.png

フローが読み込まれるので、適当な位置に置きます。

スクリーンショット 2017-04-10 11.59.26.png

ノードの編集

グローバル変数をセットします。
set variablesノードをダブルクリックし、ノードの編集を行います。context.global.ekispertWebServiceKeyの値を、当日お伝えするアクセスキーに置き換えます。

フローの実行

画面右上にあるデプロイをクリックして、フローを保存します。
timestampノードのスクリーンショット 2017-04-10 12.49.48.pngをクリックして、デバッグウィンドウになんばと表示されていたら成功です。

スクリーンショット 2017-06-22 19.11.39.png

照度センサの値をトリガに駅の時刻表をslackに流してみる

slackのbot作成

駅の時刻表をつぶやいてくれるslack botを作成します。
https://slack.com/apps にアクセスします。
画面右上のSign inをクリックし、handson20170623を入力してcontinueをクリックします。

スクリーンショット 2017-06-22 19.13.06.png

メールアドレスとパスワードを入力してsign inをクリックします。

以下の画面中央の検索窓にincoming webhookと入力し、一番上に出てきたintegrationをクリックします。

スクリーンショット 2017-04-10 13.22.34.png

Add Configrationをクリックします。

スクリーンショット 2017-04-10 13.32.37.png

Post to Channel#randomチャンネルを選択してAdd Incoming Webhooks Integrationをクリックします。

スクリーンショット 2017-04-10 13.33.15.png

以下の画面にありますWebhook URLは後ほど利用するので、コピーしておくと良いです。

自分が設定したbotかどうかわかりやすくするために、Customize NameCustomize Iconを変更してSave Settingsをクリックします。

スクリーンショット 2017-04-10 13.35.00.png

slackの処理ノードを追加

メニュー > 処理ノードの追加削除 をクリックします。

スクリーンショット 2017-04-10 13.02.36.png

処理ノードを追加というタブをクリックし、検索窓にnode-red-contrib-slackと入力して、一番上に表示された処理ノードをインストールします。

スクリーンショット 2017-04-10 13.03.23.png

フローの読み込み

以下のjsonデータをコピーします。

[{"id":"bcd4302f.5a8ab","type":"websocket in","z":"fafa05fa.7df188","name":"Recieve data","server":"","client":"bcdfa2bd.f3d8d","x":110,"y":200,"wires":[["dc7908db.6694f8","add1cfe4.1c753"]]},{"id":"eb3ecbea.1024c8","type":"function","z":"fafa05fa.7df188","name":"Set light value","func":"context.global.lightSensorOutput = msg.payload.payload.channels[0].value;\ncontext.global.upperlimit = msg.payload.payload.channels[1].value;\ncontext.global.isLightOffBefore = context.global.isLightOffNow\nvar newMsg = {\n  payload: context.global.lightSensorOutput + \" and \" + context.global.upperlimit\n}\n\nreturn newMsg","outputs":"1","noerr":0,"x":180,"y":320,"wires":[["8cccb387.f68da"]]},{"id":"dc7908db.6694f8","type":"json","z":"fafa05fa.7df188","name":"","x":270,"y":200,"wires":[["7e8ec163.9d985"]]},{"id":"7e8ec163.9d985","type":"switch","z":"fafa05fa.7df188","name":"Filter keepalives","property":"payload.type","propertyType":"msg","rules":[{"t":"neq","v":"keepalive","vt":"str"}],"checkall":"true","outputs":1,"x":440,"y":200,"wires":[["eb3ecbea.1024c8"]]},{"id":"add1cfe4.1c753","type":"debug","z":"fafa05fa.7df188","name":"","active":true,"console":"false","complete":"payload","x":270,"y":260,"wires":[]},{"id":"2ef8f9b.56f8606","type":"comment","z":"fafa05fa.7df188","name":"sakura.ioから照度センサの値を取得","info":"","x":250,"y":160,"wires":[]},{"id":"8cccb387.f68da","type":"switch","z":"fafa05fa.7df188","name":"","property":"lightSensorOutput","propertyType":"global","rules":[{"t":"gt","v":"upperlimit","vt":"global"},{"t":"lte","v":"upperlimit","vt":"global"}],"checkall":"true","outputs":2,"x":350,"y":320,"wires":[["5dfd702c.795ef"],["7525453c.80e1ac"]]},{"id":"5dfd702c.795ef","type":"function","z":"fafa05fa.7df188","name":"set boolean","func":"context.global.isLightOffNow = true;\n\nvar newMsg = {\n  payload: \"now:\" + context.global.isLightOffNow + \",before:\" + context.global.isLightOffBefore\n}\n\nreturn newMsg;","outputs":1,"noerr":0,"x":510,"y":300,"wires":[["999500f9.ec1de"]]},{"id":"7525453c.80e1ac","type":"function","z":"fafa05fa.7df188","name":"set boolean","func":"context.global.isLightOffNow = false;\n\nvar newMsg = {\n  payload: \"now:\" + context.global.isLightOffNow + \",before:\" + context.global.isLightOffBefore\n}\n\nreturn newMsg;","outputs":1,"noerr":0,"x":510,"y":340,"wires":[["999500f9.ec1de"]]},{"id":"999500f9.ec1de","type":"debug","z":"fafa05fa.7df188","name":"","active":true,"console":"false","complete":"payload","x":690,"y":320,"wires":[]},{"id":"e3b47492.258588","type":"inject","z":"fafa05fa.7df188","name":"","topic":"","payload":"","payloadType":"date","repeat":"2","crontab":"","once":false,"x":130,"y":420,"wires":[["a4fadca1.d23f"]]},{"id":"286334de.dc3cec","type":"http request","z":"fafa05fa.7df188","name":"get direction","method":"GET","ret":"obj","url":"","tls":"","x":730,"y":420,"wires":[["9b91ddbb.ee919"]]},{"id":"b7ad5715.cdacf8","type":"function","z":"fafa05fa.7df188","name":"set url","func":"var newMsg = {\n  url: context.global.ekispertWebServiceEndpoint + \"/v1/json/station/timetable?key=\" + context.global.ekispertWebServiceKey + \"&stationCode=\" + context.global.stationCode\n}\nreturn newMsg;","outputs":1,"noerr":0,"x":570,"y":420,"wires":[["286334de.dc3cec"]]},{"id":"3984eecb.9b7a02","type":"http request","z":"fafa05fa.7df188","name":"get timetable","method":"GET","ret":"obj","url":"","tls":"","x":290,"y":480,"wires":[["9e64958a.3acf88"]]},{"id":"9b91ddbb.ee919","type":"function","z":"fafa05fa.7df188","name":"set url","func":"var newMsg = {\n  url: \"http://api.ekispert.jp/v1/json/station/timetable?key=wC4SR9ETBhBcJ3Bv&stationCode=\" + context.global.stationCode + \"&code=1\",\n}\nreturn newMsg;","outputs":1,"noerr":0,"x":130,"y":480,"wires":[["3984eecb.9b7a02"]]},{"id":"9e64958a.3acf88","type":"function","z":"fafa05fa.7df188","name":"format message","func":"var hourTable = msg.payload.ResultSet.TimeTable.HourTable;\nvar times = [];\nvar displayTimes = [];\nvar stationName = msg.payload.ResultSet.TimeTable.Station.Name;\nvar lineName = msg.payload.ResultSet.TimeTable.Line.Name;\nvar direction = msg.payload.ResultSet.TimeTable.Line.Direction;\nvar minuteAfter = 20;\n\n// 現在時刻の取得\nvar now = new Date();\n\n// 現在時刻から○分後の時刻を取得\nvar timeAfter = new Date();\ntimeAfter.setMinutes(timeAfter.getMinutes() + minuteAfter);\n\n// 時刻表をtimes変数に格納\nfor(var i = 0; i < hourTable.length; i++ ) {\n  for(var j = 0; j < hourTable[i].MinuteTable.length; j++) {\n    times.push(new Date(now.getFullYear(), now.getMonth(), now.getDate(), hourTable[i].Hour, hourTable[i].MinuteTable[j].Minute));\n  }\n}\n\n// 現在時刻から○分以内の時刻のみ抽出\nfor(var i = 0; i < times.length; i++) {\n  if(now < times[i] && times[i] < timeAfter) {\n    displayTimes.push(times[i]);\n  }\n}\n\nvar slackMessage = `${lineName} ${stationName}の電車を調べたよ!\\n■${direction} 方面\\n${displayTimes.join(\"\\n\")}`;\n\nvar newMsg = {\n  payload: slackMessage,\n  channelURL: context.global.WebHookURL\n}\nreturn newMsg;","outputs":1,"noerr":0,"x":480,"y":480,"wires":[["a55f0d31.f2495"]]},{"id":"a55f0d31.f2495","type":"slack","z":"fafa05fa.7df188","name":"","channelURL":"","username":"","emojiIcon":"","channel":"","x":650,"y":480,"wires":[]},{"id":"99e69b35.9ac898","type":"comment","z":"fafa05fa.7df188","name":"時刻表取得","info":"","x":100,"y":380,"wires":[]},{"id":"a4fadca1.d23f","type":"switch","z":"fafa05fa.7df188","name":"","property":"isLightOffNow","propertyType":"global","rules":[{"t":"true"}],"checkall":"true","outputs":1,"x":290,"y":420,"wires":[["ce9ff196.b5822"]]},{"id":"ce9ff196.b5822","type":"switch","z":"fafa05fa.7df188","name":"","property":"isLightOffBefore","propertyType":"global","rules":[{"t":"false"}],"checkall":"true","outputs":1,"x":430,"y":420,"wires":[["b7ad5715.cdacf8"]]},{"id":"bcdfa2bd.f3d8d","type":"websocket-client","z":"","path":"wss://api.sakura.io/ws/v1/79f4a250-255e-4b8a-ae06-9c48b5721e0d","wholemsg":"false"}]

メニュー > 読み込み > クリップボード をクリックし、先ほどコピーしたjsonデータを貼り付けて読み込みを押します。

スクリーンショット 2017-04-10 11.52.41.png

スクリーンショット 2017-04-10 11.53.24.png

フローが読み込まれるので、適当な位置に置きます。

スクリーンショット 2017-04-10 13.08.54.png

ノードの編集

set variablesノードをダブルクリックし、context.global.WebHookURLの値を、先ほどslackで設定した Incoming Webhooks のWebhook URLに置き換えます。

Recieve dataノードをダブルクリックし、表示されたウィンドウ内のスクリーンショット 2017-04-10 13.54.53.pngマークをクリックし、websocketURL[^1]を入力します。

スクリーンショット 2017-04-10 13.56.08.png

フローの実行

画面右上にあるデプロイをクリックして、フローを保存します。
照度センサを手で覆ったタイミングでslackにメッセージがきたら成功です。

スクリーンショット 2017-06-22 19.15.17.png

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up