LoginSignup
12
1

More than 5 years have passed since last update.

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

Posted at

はじめに

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

  • 何か開発したいと思いつつ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記事を書きたかったんですが無理すぎました
  • 電池とクリック回数の減りがマッハ
12
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
1