LineBot控制micro:bit
2017年6月多研究了LineBot,到了8月多,又碰上了micro:bit的熱潮,也花了一些時間玩玩,心中早想把這兩種東西搞在一起,卻直到十二月才動手,其間有碰到一些盲點,但很高興所有的事情都能克服。
許多人用手機控制micro:bit大部份都是用App Inventor2來寫手機程式控制micro:bit,因為之前有稍稍研究了一下LineBot,大部份人手機都有Line,所以,若能用Line來控制micro:bit,應該也挺有趣的。之前寫了許多有關LineBot的文章,Line要和microbit連結,需要有相關LineBot的背景知識,這一篇文章不會再贅述,就請有需要的朋友看看以前我有關的LineBot的文章吧!
Line可以和micro:bit連線溝通
node.js執行LineBot程式當做Line和micro:bit的中介
一、安裝LineBot用的package
LineBot端的程式是使用node.js,今天這個程式需要有的package有三個:linebot、express,以及serialport,前二個package是LineBot執行時所必需的,serialport這個package則是LineBot程式和micro:bit用序列埠溝通時所必需用到的,所以請先用rmp安裝好這三個package。(node.js的安裝及package的安裝,請參考安裝node.js申請heroku)
二、安裝micro:bit和電腦連接的mbed驅動程式。(相關序列埠介紹及驅動程式,請參考序列埠和micro:bit溝通)
三、在node.js的環境中建立程式,取名index.js,程式內容如下:
var linebot = require('linebot');
var express = require('express');
var SerialPort = require('serialport');
var bot = linebot({
channelId: '這裡改成自己Line的channelId',
channelSecret: '這裡改成自己Line的channelSecret',
channelAccessToken: '這裡改成自己Line的channelAccessToken'
});
//以下的com5請自行修改成自己的micro:bit和電腦連接時的com port名稱
//但是baudRate,115200的值,請勿修改
var mySerial = new SerialPort('com5', {baudRate: 115200});
var myId;
const Delimiter = SerialPort.parsers.Delimiter;
const parser = mySerial.pipe(new Delimiter({ delimiter: Buffer.from('\n') }));
//這一段的程式是專門處理當有人傳送文字訊息給LineBot時,我們的處理回應
bot.on('message', function(event) {
if (event.message.type = 'text') {
myId=event.source.userId;
var msg = event.message.text;
console.log(msg);
sendToMicrobit(msg);
}
});
function sendToMicrobit(msgFromLine){
var myMsg='';
if (msgFromLine=='溫度')
myMsg='temperature\n';
else if (msgFromLine=='光線')
myMsg='light\n';
else if (msgFromLine=='清除'){
myMsg='clear\n';
bot.push(myId,'micro:bit的LED畫面已清除!')
} else if (msgFromLine.startsWith('聲音')){
myMsg=msgFromLine.replace('聲音','tn')+'\n';
bot.push(myId,'micro:bit發出聲音:'+msgFromLine.replace('聲音',''));
} else if (!isNaN(msgFromLine)){
bot.push(myId,'已傳送編號'+msgFromLine+'的圖案到micro:bit');
myMsg=msgFromLine+'\n';
} else{
bot.push(myId,'您好,目前可以用的指令有\n溫度(會回報溫度)\n光線(會回報光值)\n0~39(microbit的LED會顯示編號圖案)\n清除(清掉LED畫面)\n聲音加上簡譜數字(例如聲音123)');
myMsg='\n';
}
mySerial.write(myMsg, function(err) {
if (err) {
return console.log('Error on write: ', err.message);
}
console.log('訊息已傳送至micro:bit:'+myMsg);
});
}
parser.on('data', function (data) {
var myString=data.toString();
console.log('Data:',myString);
if (myString.startsWith('temperature')){
myString=myString.replace('temperature','溫度');
} else if (myString.startsWith('light')){
myString=myString.replace('light','光線');
} else if (myString==='A\r' || myString==='B\r'){
myString=myString.replace('\r','')+'鍵已被按下!';
}
bot.push(myId,myString);
});
mySerial.on('error', function(err) {
console.log('Error: ', err.message);
})
const app = express();
const linebotParser = bot.parser();
app.post('/', linebotParser);
var server = app.listen(process.env.PORT || 8080, function() {
var port = server.address().port;
console.log('目前的port是', port);
});
四、程式該放在哪裡?
因為LineBot需要https的伺服器,以前我的文章都是教大家要把程式放上heroku(https://www.heroku.com/),heroku會提供空間以及程式環境,最重要的是提供https讓Line來界接。但是,micro:bit無法連上heroku,所以,LineBot的程式不能放在heroku上,只能放在電腦上來連接,所以,LineBot的程式也得要放在本機的電腦上。有一個程式叫做ngrok,它能夠提供https,並且提供轉址,讓Line的訊息能夠透過ngrok轉址到您的電腦上,就算是電腦在區域網路的虛擬IP也可以,ngrok的網址 https://ngrok.com/,下載適合的ngrok程式後,在命令列執行指令,指令如下:
- ngrok http 8080
ngrok會取得一個https的網址(如下圖圖片所示),將自己取得的https網址填入Line的Message API的Webhook URL,讓Line的伺服器可以識別得到您的電腦。這個ngrok程式不要關掉,如果關掉再重新啟動ngrok,又會重新取得一個不一樣的https網址。
執行ngrok,以取得https網址
將取得的網址填入Message API裡的Webhook URL欄位裡
五、micro:bit的程式如下,請在makecode裡將以下的程式貼上Javascript頁面,下載後存入micro:bit裡
let tons: number[] = []
let myBeat = 0
let myNumber = 0
let myString = ""
tons = [262, 294, 330, 349, 392, 440, 494, 523, 587]
input.onButtonPressed(Button.A, () => {
serial.writeLine("A")
})
input.onButtonPressed(Button.B, () => {
serial.writeLine("B")
})
function playMusic() {
myString = myString.substr(2)
myBeat = 1
for (let i = 0; i < myString.length; i++) {
if (i == (myString.length - 1)) {
music.playTone(tons[parseInt(myString.charAt(i)) - 1], music.beat(BeatFraction.Whole))
} else {
if (myString.charAt(i + 1) == "-") {
myBeat = BeatFraction.Double
} else if (myString.charAt(i + 1) == "~") {
myBeat = BeatFraction.Half
} else {
myBeat = BeatFraction.Whole
}
music.playTone(tons[parseInt(myString.charAt(i)) - 1], music.beat(myBeat))
if ((myString.charAt(i + 1) == "-") || (myString.charAt(i + 1) == "~")) {
i++
}
}
}
}
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), () => {
myString = serial.readUntil(serial.delimiters(Delimiters.NewLine))
myNumber = parseInt(myString)
if (myString == "temperature") {
serial.writeLine("temperature=" + input.temperature())
basic.showNumber(input.temperature())
} else if (myString == "light") {
serial.writeLine("light=" + input.lightLevel())
basic.showNumber(input.lightLevel())
} else if (myString == "clear") {
basic.clearScreen()
} else if (myString.substr(0, 2) == "tn") {
playMusic()
} else if (myString == "0") {
basic.showIcon(IconNames.Heart)
} else if (myNumber > 0 && myNumber < 40) {
basic.showIcon(myNumber)
}
})
六、將micro:bit與電腦連接(要用raspberry pi 也可以),連接要用藍芽或是序列埠都行,只要com port和上面index.js裡面的com port一樣即可,啟動index.js,指令:
- node index.js
接下來就可以用Line和micro:bit連線下指令了,程式裡可以用的指令如下:
1.溫度(會回報溫度)
2.光線(會回報光值)
3.輸入0~39,microbit的LED會顯示編號相對應的圖案)
4.清除(清掉LED畫面)
5.聲音加上簡譜數字,例如:聲音123,會發出Do、Re、Me的聲音各一拍;數字後面接著減號,則那個音會演奏2拍,數字後面接著~,則那個音會演奏半拍,例如下指令:聲音1-2~3,Do是2拍,Re是半拍,Me是1拍。
Line的執行畫面