🐾
モールス信号入力装置を作った
初めに
なんとなくモールス信号をキーボードから打てたら面白いなと思って作り始めました。
完全に趣味で実用性は皆無です。
モールス信号は基本的に短点、長点、休止符で全ての文字を表現するので0, 1, nullで表現しているとも言い換えられます。なんかコンピューターと同じに思えませんか?
context等で並行処理の恩恵は受けていたのですが、自分でgoroutineを触ることはあまりなかったのでとてもいい機会だったと思います。
本当はキー1つでやりたかったのですが、長押し判定をするのがデバイス云々の話にもなってしまいそうだったので、妥協して短点と長点を別々のキーで入力する形にしました。
リンクはこちら
中身の説明
goroutineを使って①入力処理、②出力処理及び入力の記憶を並行に行っています。
そしてこの2つのgoroutineをchというチャネルで繋いでいます。
コードはこんな感じです。
morse.go
import (
"bufio"
"fmt"
"morse/config"
"morse/pkg/file"
"morse/pkg/mykey"
"os"
"strings"
"time"
"github.com/eiannone/keyboard"
)
func main() {
ch := make(chan string)
ret := ""
// 標準入力の取得
if err := keyboard.Open(); err != nil {
panic(err)
}
defer keyboard.Close()
// ②チャネル受信処理
go func() {
// 入力のある場合とない場合の処理繰り返す
// 入力があった場合、もしくは一定時間経つとまた繰り返す
for {
select {
case v := <-ch:
if v == config.QUIT_LETTER {
// チャネルから受け取った値が終了の合図ならチャネル受信処理を終了させる
close(ch)
break
} else {
// 終了の合図以外なら短点、頂点もしくは空の文字列として処理
res := mykey.ConvertInputCode(v)
ret += res
fmt.Print(res) // 標準出力する
}
case <-time.After(config.TYPING_INTERVAL * time.Millisecond):
// chを受け取らずに一定間隔たった場合の処理
ret += config.INTERVAL_LETTER
fmt.Print(config.INTERVAL_LETTER)
}
}
}()
// ①チャネル送信処理
// 入力を受け取りチャネルに送信する
for {
char, _, err := keyboard.GetKey()
defer keyboard.Close()
if err != nil {
panic(err)
}
if string(char) == config.QUIT_PING {
// 終了のキーを押すと終了の合図をチャネルに送信しkeyboardをcloseし、入力処理を終了させる
ch <- config.QUIT_LETTER
keyboard.Close()
break
} else {
// 終了のキー以外ならば受け取った文字をチャネルに送信する
ch <- string(char)
}
}
}
簡単な機能説明
go run morse.go
で開始
___ 開始後 ___
jで短点を入力
kで頂点を入力
一定時間経つと(デフォルトだと.4秒)スペースが入力される
スペース3つで字間
スペース7つでスペース
lを入力すると終了
___ 終了後 ___
saveするか聞かれるのでy/nで選びEnter
yを選択したらファイル名を入力してEnter(空白でもOK)
ファイルがstorage下に保存される
使用したライブラリ
非同期標準入力取得
デコード
結び
糞の役にも立たぬものを作るのもまた一興ですね。
readmeとかもっとちゃんと書いていい感じにしたいです。
せっかくだし音もなるようにしたい。
Discussion