SORACOM LTE-M ButtonでSlackにモールス信号を送れるようにした

SORACOM LTE-M ButtonでSlackにモールス信号を送れるようにした:


はじめに

  • ある日、会社にたくさんのSORACOMボタンが届いた


    68747470733a2f2f71696974612d696d6167652d
  • 何か開発したいと思いつつSORACOMさんのドキュメントを読んでみる
  • 1つのボタンでシングルクリック、ダブルクリック、長押しが出来るようだ
  • モールス信号が打てますね!思いついたらすぐ開発していく


開発方法


仕様


  • 和文モールス符号を扱えるようにする
  • クリックはそれぞれ以下のように扱う

    • シングルクリック: トン
    • 長押し: ツー
    • ダブルクリック: 区切り文字

      • (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へ送る


Screenshot from 2018-11-11 19-19-42.png


  • いい感じですね


終わりに

  • 1回のクリックから送信完了までそこそこ時間がかかってしまう
  • 本当はモールス信号でQiita記事を書きたかったんですが無理すぎました
  • 電池とクリック回数の減りがマッハ

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)