SORACOM LTE-M ButtonでSlackにモールス信号を送れるようにした
SORACOM LTE-M ButtonでSlackにモールス信号を送れるようにした:
はじめに
- ある日、会社にたくさんのSORACOMボタンが届いた
- 何か開発したいと思いつつSORACOMさんのドキュメントを読んでみる
- 1つのボタンでシングルクリック、ダブルクリック、長押しが出来るようだ
- モールス信号が打てますね!思いついたらすぐ開発していく
開発方法
-
まずはSORACOMさんの素晴らしいドキュメントを参考にボタンを押したらSlackへ通知できる状態にする
- この2つのドキュメントを読めばOKです
- この2つのドキュメントを読めばOKです
- この状態をベースにモールス信号処理部分のコードを加えていく
仕様
-
和文モールス符号を扱えるようにする - クリックはそれぞれ以下のように扱う
- シングルクリック: トン
- 長押し: ツー
- ダブルクリック: 区切り文字
- (e.g.)シングルクリック、長押し、ダブルクリック => イ
- ダブルクリックが2連続で来たらSlackへ通知させる
- 1回のシングルクリック、ダブルクリック、長押しごとにAWS Lambdaがコールされてくるが全信号の終わりまで状態を持つ必要がある
- AWS Lambdaは
/tmp
を扱えるのでファイルを作成しダブルクリックが2連続で来るまで状態を管理する
コード
index.js
const https = require('https'); const url = require('url'); const fs = require('fs'); const defaultSlackUrl = process.env['SLACK_URL'] const tmpFilePath = "/tmp/morse_signal.txt" const getSignal = { "SINGLE": ".", // トン "DOUBLE": " ", // デリミタ "LONG": "-" // ツー } const wabunMorseCode = { ".-": "イ", ".-.-": "ロ", "-...": "ハ", "-.-.": "ニ", "-..": "ホ", ".": "ヘ", "..-..": "ト", "..-.": "チ", "--.": "リ", "....": "ヌ", "-.--.": "ル", ".---": "ヲ", "-.-": "ワ", ".-..": "カ", "--": "ヨ", "-.": "タ", "---": "レ", "---.": "ソ", ".--.": "ツ", "--.-": "ネ", ".-.": "ナ", "...": "ラ", "-": "ム", "..-": "ウ", ".-..-": "ヰ", "..--": "ノ", ".-...": "オ", "...-": "ク", ".--": "ヤ", "-..-": "マ", "-.--": "ケ", "--..": "フ", "----": "コ", "-.---": "エ", ".-.--": "テ", "--.--": "ア", "-.-.-": "サ", "-.-..": "キ", "-..--": "ユ", "-...-": "メ", "..-.-": "ミ", "--.-.": "シ", ".--..": "ヱ", "--..-": "ヒ", "-..-.": "モ", ".---.": "セ", "---.-": "ス", ".-.-.": "ン", "..": "゛", "..--.": "゜" } const writeSignal = (signal) => { console.log(signal); fs.appendFileSync(tmpFilePath, signal); } const readSignal = () => { return fs.readFileSync(tmpFilePath, 'utf8'); } const decodeWabunMorseCode = (signal) => { return wabunMorseCode[signal] ? wabunMorseCode[signal] : "?" // デコードできない場合は?を返す } const sendSlack = (event, context, callback, message) => { var slackUrl = (event.placementInfo.attributes.slackUrl) ? event.placementInfo.attributes.slackUrl : defaultSlackUrl if (!slackUrl) { } var slackReqOptions = url.parse(slackUrl); slackReqOptions.method = 'POST'; slackReqOptions.headers = { 'Content-Type': 'application/json' }; var payload = { 'text': message } if (event.placementInfo.attributes.username) { payload.username = event.placementInfo.attributes.username; } if (event.placementInfo.attributes.iconEmoji) { payload.icon_emoji = event.placementInfo.attributes.iconEmoji; } if (event.placementInfo.attributes.iconUrl) { payload.icon_url = event.placementInfo.attributes.iconUrl; payload.as_user = false; } if (event.placementInfo.attributes.slackChannel) { payload.channel = event.placementInfo.attributes.slackChannel; } var body = JSON.stringify(payload); slackReqOptions.headers = { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body), }; var req = https.request(slackReqOptions, function(res) { if (res.statusCode === 200) { console.log('Posted to slack'); callback(null, { "result": "ok" }); } else { callback(false, { "result": "ng", "reason": 'Failed to post slack ' + res.statusCode }) } return res; }); req.write(body) req.end(); } exports.handler = (event, context, callback) => { console.log('Received event:', JSON.stringify(event, null, 2)); writeSignal(getSignal[event.deviceEvent.buttonClicked.clickType]); const singals = readSignal(); console.log("\"" + singals + "\""); // デリミタが連続で来たらメッセージ送信 if (singals.match(/.+ $/)) { var message = singals.split(" ").map(function(signal) { console.log("signal: " + signal); if (signal === "") { // デリミタのみを無視 return ""; } else { return decodeWabunMorseCode(signal) // return wabun_morse[signal]; } }); // console.log(message.join("")); sendSlack(event, context, callback, message.join("")); fs.unlinkSync(tmpFilePath); } };
モールス信号を送ってみる
- 送りたいメッセージを決めて間違えないようにボタンをクリックする
- この記事のなかでこの作業が一番難しいです
---- コ .-.-. ン -.-. ニ ..-. チ -... ハ .---. セ .-.. カ .- イ
- 最後にダブルクリックが連続になるようにしてSlackへ送る
- いい感じですね
終わりに
- 1回のクリックから送信完了までそこそこ時間がかかってしまう
- 本当はモールス信号でQiita記事を書きたかったんですが無理すぎました
- 電池とクリック回数の減りがマッハ
コメント
コメントを投稿