LineBot也可以做觸控選單

之前的文章有介紹過用LineBot操控物聯網裝置,但是我們知道,Line就是個文字訊息的溝通介面,所以所有操控物聯網的指令,全都是要靠文字對話的輸入方式來下達指令,這樣子的話操控物聯網就有點麻煩,不像使用APP有各種按鍵或選單來得方便。但是,其實Line也是可以在對話框產生選單的,以Line的術語來說,叫做template。使用template,在LineBot程式中設定好選單的內容、文字,使用者按下之後,就像輸入一些文字進LineBot,使用者不需經過打字的步驟,就可以傳送訊息給LineBot。

所以,以Line的template這種方式來控制物聯網,就可以不用透過文字輸入而能夠比較輕鬆方便控制物聯網上的裝置。

LineBot可以在Line的對話畫面創建選單

透過按下選單的方式,便可以操控物聯網裝置

Line上的選單文字皆可自訂

這一篇文章的程式碼,拿之前「如何用LineBot控制家電」的程式來加以修改成有選單的模式。Line的template選單,還有許多的變化,有興趣的人可以參考Line的API,https://devdocs.line.me/en/#template-messages

require('webduino-js');
require('webduino-blockly');

var linebot = require('linebot');
var express = require('express');
var math = require('mathjs');

var bot = linebot({
  channelId: '請輸入LineBot的channelId',
  channelSecret: '請輸入LineBot的channelSecret',
  channelAccessToken: '請輸入LineBot的channelAccessToken'
});
//以下的Webduino的device,請輸入自己webduino的DeviceID
var myBoardVars={board: 'Smart', device: '這裡請輸入webduino的Device ID,前後引號不能去掉', transport: 'mqtt'};

//注意:上面為連結Webduino Smart的連結語法,如果你的板子是webduino馬克一號或是Fly,請將上面的語法刪掉,並改成以下的連結語法。var myBoardVars={device: '這裡請輸入webduino的Device ID,前後引號不能去掉'};

var rgbled;
var relay;
var myBoard;

//以下就是LineBot選單的格式
var myLineTemplate={
    type: 'template',
    altText: 'this is a confirm template',
    template: {
        type: 'buttons',
        text: '按下選單可以控制物聯網裝置!\n輸入?可以再看到這個選單!',
        actions: [{
            type: 'postback',
            label: 'LED開',
            data: 'LED開'
        }, {
            type: 'postback',
            label: 'LED關',
            data: 'LED關'
        },{
            type: 'postback',
            label: '電燈開',
            data: '電燈開'
        },{
            type: 'postback',
            label: '電燈關',
            data: '電燈關'
        }]
    }
};

//LineBot處理文字訊息的函式
bot.on('message', function(event) {
   var myReply='';
   if (event.message.type === 'text') {
      myReply=processText(event.message.text);
   }
   if (event.message.type === 'sticker') {
      myReply='你太幽默了!';
   console.log('sticker');
   }
   if (event.message.type === 'image') {
      myReply='這照片好帥!';
   }
   event.reply(myReply).then(function(data) {
      // success 
      console.log('訊息已傳送!');
   }).catch(function(error) {
      // error 
      console.log('error');
   });
});

//LineBot處理使用者按下選單的函式
bot.on('postback', function (event) {
   var myResult=setIoT(event.postback.data);
   if (myResult!=''){
      event.reply(myResult).then(function(data) {
         // success 
         console.log('訊息已傳送!');
      }).catch(function(error) {
         // error 
         console.log('error');
      });
   }
});


function processText(myMsg){
   var myResult=setIoT(myMsg);
   if (myResult!=''){}
   else if (myMsg==='你好' || myMsg==='早安' || myMsg==='午安' || myMsg==='晚安')
      myResult=myMsg; 
   else if (myMsg==='我很帥')
      myResult='我也這麼覺得';
   else if (myMsg==='繼電器')
      myResult='5號腳位';
   else if (myMsg==='再見')
      myResult='這麼快就要離開我了!';
   else if (myMsg==='?' || myMsg==='?')
//使用者輸入問號,則會把選單當做訊息傳送給使用者
      myResult=myLineTemplate;
   else{
      myResult='';
      try{
         myResult='答案是'+math.eval(myMsg.toLowerCase()).toString();
      }catch(err){
         myResult='';
      }
      if (myResult==='')
         myResult='抱歉,我不懂這句話的意思!';
   }
   return myResult;
}

//處理webduino腳位開關的函式
function setIoT(fromMsg){
   var returnResult='';
   if (fromMsg==='led開' || fromMsg==='LED開'){
      if (!deviceIsConnected())
         returnResult='裝置未連接!';
      else{
         returnResult='LED已打開!';
         rgbled.setColor('#FFFFFF');
      }
   }
   else if (fromMsg==='led關' || fromMsg==='LED關'){
      if (!deviceIsConnected())
         returnResult='裝置未連接!';
      else{
         returnResult='LED已關閉!';
         rgbled.setColor('#000000');
      }
   }
   else if (fromMsg==='電燈開'){
      if (!deviceIsConnected())
         returnResult='裝置未連接!';
      else{
         returnResult='電燈已打開!';
         relay.on();
      }
   }
   else if (fromMsg==='電燈關'){
      if (!deviceIsConnected())
         returnResult='裝置未連接!';
      else{
         returnResult='電燈已關閉!';
         relay.off();
      }
   }
   return returnResult;
}

boardReady(myBoardVars, true, function (board) {
   myBoard=board;
   board.systemReset();
   board.samplingInterval = 50;
   rgbled = getRGBLedCathode(board, 15, 12, 13);
   relay = getRelay(board, 5);
   rgbled.setColor('#000000');
   relay.off();
});

//以下為檢查webduino是否已連線成功的函式
function deviceIsConnected(){
   if (myBoard===undefined)
      return false;
   else if (myBoard.isConnected===undefined)
      return false;
   else
      return myBoard.isConnected;
}


const app = express();
const linebotParser = bot.parser();
app.post('/', linebotParser);

//因為 express 預設走 port 3000,而 heroku 上預設卻不是,要透過下列程式轉換
var server = app.listen(process.env.PORT || 8080, function() {
  var port = server.address().port;
  console.log("App now running on port", port);
});