20201116のNode.jsに関する記事は4件です。

obniz × LINE bot 距離センサに近づいたらLED点灯&LINEへお知らせをpushしてみる

自己紹介

大学時代C言語を学んでから十数年以来のプログラミングを始めています。
本業はweb制作で、ホームページとLINE連携の需要がとても多く、LINEbotに興味を持ちました。
今回も練習した事のメモです。

やったこと

obnizの超音波測距センサーで100cm以内に近づくとフルカラーLED WS2811で指定した色が光る。
さらにはLINE botに近づいた事を知らせます。

obnizの超音波距離センサーで近づくとLEDが光る

という部分の動作確認です。

const obniz = new Obniz('obnizID');

obnizIDを書き換えます。

const Obniz = require('obniz');
const obniz = new Obniz('obnizID');

obniz.onconnect = async() => {
    // 超音波測距センサを利用
    const hcsr04 = obniz.wired('HC-SR04', { gnd: 11, echo: 10, trigger: 9, vcc: 8 });

    // LEDを利用
    const rgbled = obniz.wired('WS2811', { gnd: 0, vcc: 1, din: 2 });

    // obnizディスプレイ(初期表示)
    obniz.display.clear();
    obniz.display.print('obniz Ready');

    // setIntervalで定期実行
    setInterval(async() => {
        // 距離を取得
        let distance = await hcsr04.measureWait();
        // 小数点以下がたくさんあるのでここでは整数に
        distance = Math.floor(distance);
        // 距離をコンソールに表示
        console.log(distance + ' mm');
        // 距離をobnizディスプレイに表示
        obniz.display.clear();
        obniz.display.print(distance + ' mm');
        // 距離によって判定
        if (distance < 100.0) {
            // 100mm = 10cm 未満の場合 obnizディスプレイ表示
            obniz.display.clear();
            obniz.display.print('Too close!!');
            // LEDオン
            rgbled.rgbs([
                [0xFF, 0x00, 0x00], // red
                [0x00, 0x00, 0xFF] // blue
            ])
        } else {
            // 100mmを超えるときは色が反転
            rgbled.rgbs([
                [0x00, 0x00, 0xFF],
                [0xFF, 0x00, 0x00]
            ])
        }
    }, 5000); // 5000ミリ秒 = 5秒ごとに実行
};

LINEbotと接続

ここがなかなかうまくいかず、苦労しました。

エラーが結構出まして。
どこまで動いているのか切り分ける為、細かくコードの中に

console.log('Hello2!');

を入れていきました。
そうする事で、Hello2!が表示されたかされていないのかで、どこの記述が怪しいのか判別する事が出来ました。

image.png

時間かかりましたが、ようやくエラー表示が消え距離が出力されるようになりました。
そして、ngrokを実行して、LINE botのwebhookへ入力すると

image.png

100mm以内に近づいた時だけ、LINEに通知が送られます。成功しました。

まとめ

今回は超音波測距センサーってなんか凄いな!と思い、超音波測距センサー×LINEを実装したのですが、実生活に役立つ機能を持つ開発をしていきたいなと思いました。実生活の自動化とても気になっています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

obnize × LINE bot で近づいたらLED&LINEでお知らせ

自己紹介

大学時代C言語を学んでから十数年以来のプログラミングを始めています。
本業はweb制作で、ホームページとLINE連携の需要がとても多く、LINEbotに興味を持ちました。
今回も練習した事のメモです。

やったこと

obnizeの超音波測距センサーで100cm以内に近づくとフルカラーLED WS2811で指定した色が光る。
さらにはLINE botに近づいた事を知らせます。

obnizeの超音波距離センサーで近づくとLEDが光る

という部分の動作確認です。

const obniz = new Obniz('obnizID');

obnizIDを書き換えます。

const Obniz = require('obniz');
const obniz = new Obniz('obnizID');

obniz.onconnect = async() => {
    // 超音波測距センサを利用
    const hcsr04 = obniz.wired('HC-SR04', { gnd: 11, echo: 10, trigger: 9, vcc: 8 });

    // LEDを利用
    const rgbled = obniz.wired('WS2811', { gnd: 0, vcc: 1, din: 2 });

    // obnizディスプレイ(初期表示)
    obniz.display.clear();
    obniz.display.print('obniz Ready');

    // setIntervalで定期実行
    setInterval(async() => {
        // 距離を取得
        let distance = await hcsr04.measureWait();
        // 小数点以下がたくさんあるのでここでは整数に
        distance = Math.floor(distance);
        // 距離をコンソールに表示
        console.log(distance + ' mm');
        // 距離をobnizディスプレイに表示
        obniz.display.clear();
        obniz.display.print(distance + ' mm');
        // 距離によって判定
        if (distance < 100.0) {
            // 100mm = 10cm 未満の場合 obnizディスプレイ表示
            obniz.display.clear();
            obniz.display.print('Too close!!');
            // LEDオン
            rgbled.rgbs([
                [0xFF, 0x00, 0x00], // red
                [0x00, 0x00, 0xFF] // blue
            ])
        } else {
            // 100mmを超えるときは色が反転
            rgbled.rgbs([
                [0x00, 0x00, 0xFF],
                [0xFF, 0x00, 0x00]
            ])
        }
    }, 5000); // 5000ミリ秒 = 5秒ごとに実行
};

LINEbotと接続

ここがなかなかうまくいかず、苦労しました。

エラーが結構出まして。
どこまで動いているのか切り分ける為、細かくコードの中に

console.log('Hello2!');

を入れていきました。
そうする事で、Hello2!が表示されたかされていないのかで、どこの記述が怪しいのか判別する事が出来ました。

image.png

時間かかりましたが、ようやくエラー表示が消え距離が出力されるようになりました。
そして、ngrokを実行して、LINE botのwebhookへ入力すると

image.png

100mm以内に近づいた時だけ、LINEに通知が送られます。成功しました。

まとめ

今回は超音波測距センサーってなんか凄いな!と思い、超音波測距センサー×LINEを実装したのですが、実生活に役立つ機能を持つ開発をしていきたいなと思いました。実生活の自動化とても気になっています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

飲みに誘いにくい人が使う、飲みお誘いLINE Botの「用途に合わせた宛先設定部分」

リモートが続いてふさぎ込んでしまう人を救いたい

 コロナの影響でリモートでお仕事をすることが増えて、
 よほどオープンにぐいぐい誘える人でない限り、人を飲みに誘うのも気がひけてしまう。(私もその一人です)
 今、会社に入った新人の子たちなど、顔も知らない社員の人がいっぱいいる。なかなかつながりが広がらないのが課題です。
 だけど飲みたい。(言わずもがな対策は必須で)
 
 そんなときに会社の人たちを飲みに誘うサービスをLINE Botで作っています。
 その1機能がこれです。まだDBへの接続などはやってなくて出し分けの部分のみ。

 

 なんでLINE Botを使ったかというと、
 シャイな人でも使えて、利点として大体の人が使っている。どこでもメッセージを送れる。
 といったところがあります。

 LINEということもあり、ユーザはメッセージやボタンで操作していくことになるので、
 操作感の確認をしようと思い、○○したら××が返ってきて、そのあとどういうアクションをとるかなど、
 アクションの設計について作ったものをヒアリングしています。
 

操作感を後輩(若い子)にヒアリング聞いてみた

 ■操作感
  ・LINEであるのはよい、導入しやすいメッセージも簡潔で使いやすいと思う。
  ・自分が登録した名前が出るのも安心感がある。誰とも知らない人と飲むよりよい。
  ・今、1グループの人数をある限られた数にしているが、人数を言い出しっぺの人が決められるようにするとよいと思う。

 ■操作感というより企画の部分
  ・自分だと1人目になるのは恥ずかしいかもしれない。Bot内に含まれる人の多さがちょっと気になる。
  ・1年目の子が使うのはいいと思う。1年目の子が1人目であれば、2人目で続いて自分(先輩たち)も使いたい。

 ■フィードバックを受けた改善活動 
  ・人数を決められるようにする機能は後々追加していくことにしよう。
   コロナが終わるまでは4人が上限としたいので、今回の開発範囲に入れるかは検討。
   
  ・1人目になるのが恥ずかしい。
   ⇒目立つのが苦手なのが多い日本人の見られる傾向。
    誰かが言ってくれたら乗っかりたいという流れ。
    言い出しっぺになることが多い人に、
    「そろそろ行く?」みたいなメッセージを送って、
    1人目になる機会を増やすか、
    なかなか言い出しっぺにならない人の1人目になる意識を盛り上げていく施策は必要かも。

作っている機能

 募集(登録)こんな人が飲み行くって言ってるよ!と伝えるようにBotの友達皆に「Broad」で連絡
 集まった連絡  既定の人数集まったら、集まったメンバーをBotの友達皆に「Broad」で連絡
 キャンセル いけなくなった時の機能。
       一緒に飲みに行く人たちだけでいいので、そのデータをとってきて「Multicast」で配信
 連絡    お店や集合時間の連絡に使用。
       一緒に飲みに行く人たちだけでいいので、そのデータをとってきて「Multicast」で配信
 他、想定にないメッセージ 送ってきた人にちゃんと書き方を守ってもらうように「Reply」で返信

構成

 基本的にユーザの操作はLINEで完結させる予定です。
 DBを通さない状態(固定データ)で出し分け出来るところまで作っています。
 

環境

 Node.js
 LINE Messaging API
 Cloud Functions 諸事情でサーバレスの方がやりやすかったため。

ソース(動くけどまだ作りきってない)

アクセストークンなどは環境変数にしています。

'use strict';

// LINESDKのライブラリをインポート
const line = require('@line/bot-sdk');

// コンフィグ
const config = {
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
  channelSecret: process.env.CHANNEL_SECRET,
};

const client = new line.Client(config);

// 1グループに入る最大人数を定義
const GROUP_MEMBER_LIMIT = 4;

// LINEサーバーからWebhookがあると「サーバー部分」から以下の "handleEvent" という関数が呼び出されます
async function handleEvent(event) {
    console.log(event);
    var message = 'Please push text message.';
    if (event.type !== 'message' || event.message.type !== 'text') {
        return Promise.resolve(null);
    }

    // レスポンスの関数を実行します
    return responseFunction(event);

}

// ユーザのメッセージに対してどう返すかを定義
const responseFunction = async (event) => {
    // 送られてくるイベントがテキストメッセージであれば下記の対応
    if (event.type === 'message' && event.message.type === 'text') {

        // 想定しているメッセージ形式であるかチェック


        // 送られてきたメッセージを分解
        const message_arr = event.message.text.split(" ");
        console.log(message_arr[0]);
        console.log(message_arr[1]);

        let pushText = '';
        // 飲みに行きたい人が出たときの処理 チャンネル全体に告知
        if (check_go(message_arr[0])) {
            console.log("飲みに行きたいってさ");
            // 名前の抽出
            const user_name = message_arr[1];
            let member_count = 0;            


            // すでに今日飲みに行きたい人に自分が入っているか確認。入っていたら入ってますと連絡して終了。

            // 現在の登録人数を確認 今日の最初の登録かの確認に使用

            // 一番数字が大きい今日のグループNoとメンバーNoを取得

            // 1グループに入る最大人数と同じであれば、新規グループを作ってメンバー1人目として登録、そうでなければ追加登録



            //後で書き換えする処理
            if(user_name === "ちょめお"){
                member_count = 1;
            }else if(user_name === "ちょめすけ"){
                member_count = 2;
            }else if(user_name === "ちょめこ"){
                member_count = 3;
            }else{
                member_count = 4;
            }
            pushText = "飲みに行きたい人" + member_count + "人目 " + user_name;



            if(member_count === GROUP_MEMBER_LIMIT){
                // 最後に登録した人が所属するグループに入っている名前を取得して格納

                let user_name_list = ["ちょめお","ちょめすけ","ちょめこ","ちょむちょむ"];

                pushText += " グループの飲みに行くメンバーは、"
                // 同じグループの人数分ループ
                for(var i = 0 ; i <= user_name_list.length - 1 ; i++ ){
                    pushText += user_name_list[i] + "さん、";
                }
                pushText += "です!張り切っていきましょう!"
            }

            // チャンネルに登録されている方たちに連絡
            return client.broadcast({
                type: "text",
                text: pushText
            }).then(data => console.log(data))
            .catch(e => console.log(e))


        // キャンセル者が出たときのメッセージ 同じグループの人に届ける
        }else if(check_cancel(message_arr[0])){
            console.log("キャンセルしたい");
            try{

                // すでに今日飲みに行きたい人に自分が入っているか確認。入ってなかったら登録されてませんと連絡して終了。


                // 出席者リストからキャンセル者を削除する DELか、削除フラグを使うか考えどころ


                // キャンセル連絡をした人の名前をセット
                const user_name = message_arr[1];            
                // 誰がキャンセルしたかグループの人に連絡する用のメッセージ
                pushText = user_name + "さんがキャンセルしました";

                // メッセージ送信先配列の初期化
                let destination_list = ['ユーザID'];

                // メッセージ配列の初期化
                let message_list = [];
                message_list = [{type: 'text',text: pushText}];

                // 同じグループの人たちを取り出す処理

                // 宛先リストにユーザIDを追加

                console.log(destination_list);
                console.log(message_list);

                // 対象は同じグループの人たち
                client.multicast(destination_list,
                message_list
                )


            }catch(err){
                console.log(err.name +  ': ' + err.message);
                process.exit(-1);
            }
            // resolveを返す
            return Promise.resolve(null);

        // 連絡事項が来た時の処理 飲みに行く同じグループの人へ届ける
        }else if(check_contact(message_arr[0])){
            console.log("連絡事項あり!");
            try{

                // すでに今日飲みに行きたい人に自分が入っているか確認。入ってなかったら登録されてませんと連絡して終了。

                // 連絡事項の場合はそのままのメッセージを返す
                pushText = event.message.text;

                // メッセージ送信先配列の初期化
                let destination_list = ['ユーザID'];

                // メッセージ配列の初期化
                let message_list = [];
                message_list = [{type: 'text',text: pushText}];

                // 同じグループの人たちを取り出す処理

                // 宛先リストにユーザIDを追加

                console.log(destination_list);
                console.log(message_list);

                // 対象は同じグループの人たち
                client.multicast(destination_list,
                message_list
                )


            }catch(err){
                console.log(err.name +  ': ' + err.message);
                process.exit(-1);
            }
            // resolveを返す
            return Promise.resolve(null);




        }else{
            // 提供している機能以外(飲みに行きたい・キャンセルしたい・連絡)だった時
            return client.replyMessage(event.replyToken, {
                type: 'text',
                text: '「飲みに行きたい 名前」か「キャンセル 名前」か「連絡 内容を入れる」(全角スペースを真ん中に入れます。)と話しかけてね。'
            });
        }
        // 「プッシュ」で後からユーザーに通知します
        return client.pushMessage(event.source.userId, {
            type: 'text',
            text: pushText,
        });
    }


}

// 飲みに行きたいパターンかチェック
function check_go(event_text) {
    if(event_text === '飲みに行きたい'){
        return true;
    }else {
        return false;
    }
}

// キャンセルしたいパターンかチェック
function check_cancel(event_text) {
    if(event_text === 'キャンセル'){
        return true;
    }else {
        return false;
    }
}

// キャンセルしたいパターンかチェック
function check_contact(event_text) {
    if(event_text === '連絡'){
        return true;
    }else {
        return false;
    }
}


exports.handler = function linebot_message (req, res) {
  Promise
    .all(req.body.events.map(handleEvent))
    .then(result => res.status(200).send(`Success: ${result}`))
    .catch(err => res.status(400).send(err.toString()));
};

今後の展開

 ・飲み会の同グループの人たちを抽出する機能を作る。
 ・データ登録機能からつくる
 ・キャンセル(削除)を作る。
 ・エラーが起きたときのユーザへのメッセージ
 ・人数の枠を可変にするのは、後々検討

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

javascriptで文字列を分解して配列化メモ

書き方

分割対象の文字列.split(区切りに使用する文字列)

今回の場合

LINEから受け取ったメッセージ「飲みに行きたい 名前」なので、

const message_arr = event.message.text.split(" ")

全角スペースかな。

全角スペースを入れていないときは、配列の2個目の要素は「undefined」になる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む