あんパン

こしあん派

Let's Splitを組み立てた

大抵のエンジニアにとってキーボードは、触らない日はないというほど身近なインターフェースだと思う。いままでHHKBやErgoDoxなど自分に合う鞍*1を探してきたわけだけれど、自分で作ってみるというのもアリなのではないか、とふと思い至った。

しかし、電子工作の経験もそんなにない自分がいきなり設計から始めてひとつのキーボードを完成させるのは途方もなく壮大な計画に思えたので、まずはキット的なものを探して自分で組み立ててみることにした。そうして調べた結果、Let's Splitというキーボードを組み立てることになった。

Let's Split

普段生活しているとなかなかお目にかかることはないけれど、世の中には40%キーボードといって、キーが48個しかついていないキーボードがある。レイヤーを切り替えて1つのキーに複数の役割をアサインして使う。

Let's Splitはredditの/r/MechanicalKeyboards/のユーザWootpatoot氏によって作られた左右分離型40%キーボードで、PCBが市販されており、ダイオードやらスイッチやらを実装して組み立てることができる。

材料を購入する

ここを参考にして揃えるとよい。

github.com

Part Cost Shop
PCB $10 switchTop
TRRS Jack *2 $3 switchTop
Switches *60 $15 switchTop
Keycaps $49.06(送料込) pimpmykeyboard
Diodes 1N4148 *500 \500 秋月
Tact Switch *2 \10 秋月
Pro Micro *2 \1,200 (送料込) Amazon
Plates $65.17 (送料込) Ponoko
M3 Standoffs & Screws $5.36 (送料込) AliExpress 1 2
  • 秋月の送料は500円
  • switchTopの送料は$8.50

かかった費用の合計としては、このときのレートで19,919円(送料込)であった。このほか、はんだごてやら何やらと機材を揃えたので、3万程度にはなっていると思う。

タクトスイッチはPro MicroのRSTとGNDに実装して、ファームウェア焼き込み時のリセットボタンとして使う。

ケースはこの部分を参考に、Ponokoで注文した。letssplitv2.svgはどこにも見当たらないのだが、QMK Firmwareのリポジトリの古いコミットに存在する(大分無理やりっぽい)。他、どこかにある感じだったら教えてください:bow:

$ git clone git@github.com:qmk/qmk_firmware.git
$ cd qmk_firmware
$ git checkout ca01d94005f67ec4fa9528353481faa622d949ae
$ ls keyboards/lets_split/imgs/
 left.stl  'lets split rev2 case.iges'   letssplitv2.svg   plate.stl   right.stl   split-keyboard-i2c-schematic.png   split-keyboard-serial-schematic.png

ネジとスペーサは良いやつを買った方が良いと思う。今回買ったやつは使えないこともないのだけど、質が悪くて、ミリネジとインチネジがあっていない時みたいな舐め方をする。また、スペーサが10mm指定だけど、高くて良いのであればもう少し長めにしてネジも長いやつにしたほうが良いと思う。ネジが短すぎて留めるのに苦労した。

キーキャップは、単体で買うよりもTKL Base Setで買う方がお得だった。無刻印で良い場合は、とにかくx1のキーが48個以上あれば良い。

これとは別に、TRRSケーブルも購入した。

また、ネジが若干出っ張っており安定感に欠けていたので、ゴム足も購入した。

3M しっかりつくクッションゴム 7.9x2.2mm 丸形 22粒 CS-01

3M しっかりつくクッションゴム 7.9x2.2mm 丸形 22粒 CS-01

組み立てる

以下の順序で実装した。

  • ダイオード
  • TRRSジャック
  • ピンヘッダ
  • キースイッチ
  • Pro Micro

インターネットにたくさん情報があるので、そっちを参考にすると良いと思う。気をつける点としては以下くらい?

  • ダイオードの導通試験できればやりたい
    • Prime Nowでテスター買った
  • ダイオードは黒線(カソード)が四角い方(GND)になるように実装する
    • Double check your work. Black lines should be facing the square pad. とのこと
  • Pro Microを実装する前にキースイッチをはんだ付けして足を切る
  • Pro Microの向き(上下)

あと、ネジ留めをする際に、Pro Micro横に設置するスペーサが基板の一部と干渉してうまく入らないことがあった。当該部分は結構ギリギリまで穴が合いていて脆い感じだったので、ニッパーで切り落としてスペーサを設置した。

ファームウェアを焼く

焼き込みにあたって、AVRの環境が必要。

$ brew tap osx-cross/avr
$ brew install avr-gcc
$ brew install avrdude

avr-gccは入れるのに30分弱くらいかかる。インストールを終えたら、QMK Firmwareを手元にcloneしてきて、自分のキーマップのディレクトリを切っておく。あとでカスタムするとして、とりあえずはdefaultからコピーする。

$ git clone git@github.com:qmk/qmk_firmware.git
$ cd qmk_firmware/keyboards/lets_split
$ cp -r keymaps/default keymaps/USER_NAME

avr-gccでhexファイルを生成してから、PCとPro MicroをmicroUSBケーブルで繋いでPro Microに焼き込む

$ make rev2-USER_NAME
$ make rev2-USER_NAME-avrdude

という具合。make rev2-USER_NAME-avrdudeを実行するときに、Pro MicroのRSTとGNDをショートさせる必要がある。今回はタクトスイッチを実装していて、押すだけでショートできるようにしていた。モノによって素早く2回ショートだったり、長押しだったりするっぽい。自分のは長押しだった。

これでうまく動けば完成。動作確認はkeycode.infoで正しいkeycodeが取れているかどうかを見た。

参考

YAPC::Fukuoka 2017 HAKATAを見にいった

ブログを書くまでがYAPCということで、もう一週間以上前のことになるのだけど、そのときのことを書く。(月火と京都出張だったり、今週はなにかとイベントがあって遅れたのじゃ…)

yapcjapan.org

YAPCはYet Another Perl Conferenceの略で、一般社団法人 JPAが主催する、Perlを軸としたITに関わる全ての人のためのカンファレンスです。

です。

トーク

オープニングからずっとA会場に居る、ランチセッション後はずっとB会場に居るという感じでトークを観覧した。いったりきたりすると席の確保が面倒なのでわりとこうなりがち。

見た中からいくつか良かったトークについて書く。

分散ユニークID採番機katsubushiとWebアプリケーションへの応用例

個人的に今回のベストトーク。Golangで書かれた分散ユニークID採番機katsubushiが生まれた経緯とその仕様紹介、単純にレコードのidとして使う以外の応用例などの紹介。

単一のリクエストにidを発行して引き回して各種ログに記録するというのが良かったなと思った。スライドにもあったけど非同期のジョブが落ちた時の調査は割と困難で、どのリクエスト起因なのかなどが分かるのは良さそう。(今ならこれだけであればkatsubushiを使う必要はなくて、Nginxの$request_idを引き回すで良さそうという話もありそう。)

Web application good error messages and bad error messages

良いエラーメッセージとは、悪いエラーメッセージとは、というトーク。アプリケーションを作る上で、例外を吐く時のメッセージとか、何らかの問題が発生したときにユーザ向けにその旨を伝えるためのメッセージを書くことは避けられないわけだけれど、きちんと意識しないとふんわりとしがちで、そのメッセージが実際にどのように役に立つのかなどを考えずにいると、中身がなかったり不十分だったりする文字列が並ぶことがある。

トークでは、エラーメッセージについて次元という分類でレベルを整理されてたのが良かったなと思った。

最近実際に、1年くらい前に書いたエラーメッセージが情報量が少なくて何を言っているのか全く意味がわからんぞということがあり、共感があってよかった。

個人的な意見なのだけれど、エラーメッセージを中途半端に高次元にする必要はないと思っている。ここでいう中途半端な高次元というのは、対処方法や解決手段が提案されているということ。

これは心理的な問題で、素人PCユーザ気質が抜けないので、対処の手段が分かってるならそうしろや、という気持ちになってしまいどうにもストレスが溜まる。例えば、gitのサブコマンドをtypoしたときに出るDid you mean this?みたいなのが出るのが苦手だ。

そこまでわかっているなら修正しますか?と聞いてきて、1クリックで修正したコマンドが発行できるとうれしい。発表中にはなかったけど、これが一番の高次元であるといえるのではないか。(もちろん、これがエラーメッセージの範疇に入るのかという話題もありそう。)

例えば、僕のシェルとかはそうなっている。

[wadamasayoshi@sibelius] $ vmi hoge.txt
vim is correct? [n,y,a,e]:

とはいいつつもちろんそこまで高次元にするコストが払える場面が少ないことも理解しており、かつ簡潔に何が起きているか分かるだけというよりかは解決手段まで提示されているほうが良いので、3次元的なエラーメッセージを記述する程度にとどまることは十分に頷ける。

新時代のテストフレームワークTest2

弊社akiymさんのトーク。Perlのテストフレームワーク、Test2の紹介とハマりどころの説明。先日、とあるツールをcpanmでいれたところ勝手にTest2がインストールされて手元のテスト環境が完膚無きまでに破壊されてしまうという現象が起こっていて、トークを聞いたところ「あぁ、これ見たことあるやつだ……」というのが2,3回くらいあって面白かった。Test2便利そうだったので使いたい。

Test::Deep的な記述ができるakiymさん謹製のモジュールTest2::DeepLikeがかなり強力そうで、これぞ顧客の求めていたものなのでは…と思った。

github.com

その他

飛行機

飛行機あまり乗ったことがなくて、沖縄に修学旅行で行ったのが最初で最後だったので、一人で乗るのは初めてだった。当日家を出る1時間くらいまでなんの準備もしておらず、準備を始めてから国内線の機内持ち込みが可能なものを調べたりとか手荷物の数に制限があることとかを知ったりして、とにかく大慌てで準備した。今度はもう大丈夫だと思う。

あと、高校生のときに気胸やったんですが、さすがにもう大丈夫でした。

宿

飛行機と2泊の宿併せてパックでとって3.2万くらいで、正直もう少し金積んでおけばよかったかなという気分。

本当は博多駅近くの宿を取りたかったのだけど、既に埋まっていて大濠公園という駅(博多から数駅)の宿になった、という話を同僚のid:papixさんにお話したところ「人権はある宿ですよ」という含みのあるコメントを頂いたので、実際に行ってみたところ、0.8人権程度であった。

微妙な香りがしたり、風呂が異常に狭かったり、操作可能な空調がなかったり、物理鍵&オートロックなしだったりというのが耐えられるのであれば良いと思う。。。まあ安いので今回はよしということで。

ご飯

ご飯の方は期待通り美味しかったです。ラーメンだけ食べ損ねた。

前夜祭チケット取れなかった組で寿司食べに行ったり、そのあと前夜祭組と合流してラーソーメン食べたり。YAPC翌日は駅でお土産かったり近くの飲み屋でいろいろ飲んだりした。

ロッカー

よし帰るぞということになって、衣服とか預けてたロッカーまで戻ったら鍵番号が書いてあるレシートを紛失した。最近、物理鍵ではなくて、預けた時に出てくるレシートの鍵番号または交通系電子マネーで解錠するタイプのロッカーがあるけど、預けたところは電子マネーが使えなくて、仕方なく番号入力するタイプで預けた。

が、見事にそのレシートを紛失した。係員の人に電話して20分ほど待ったところ、中身の確認とサイン+電話番号で荷物を回収できた。気をつけましょう。

次回

来年2018年3月3日に沖縄の恩納村ということで、楽しみですね。今度は是非ともトークしたいと思うのだけど、倍率高いんだろうなー。

yapcjapan.org

axiosでHTMLを取得してきてappendChildで埋め込む

普段axiosを使うときはレスポンスがJSONなAPIを叩くことが多いが、HTMLを取得して挿入することもあると思う。innerHTMLで直接挿入することもできるが、responseTypedocumentにすることでappendChildで要素を挿入することができる。

import axios from 'axios';

axios({
  method       : 'GET', 
  url          : '/api/response/as/html', 
  params       : { hoge: 'fuga' }, 
  responseType : 'document', 
})
.then((res) => {
    const body = document.querySelector('body');
    Array.from(res.data.body.childNodes).forEach((node) => {
      body.appendChild(node);
    });
});

Windows 10とUbuntu 16.10 on LVM on LUKSを1つのマシンに同居させる

これの続き。

前回はrootとswapを別のパーティションに作成したため、起動時にパスワードを2回入れる必要があった。まあこれでも良いのだが、煩雑なので1回で済ませられるようにしたい。そこで、LVM on LUKSを試してみることにした。暗号化した1つのパーティション上にLVMで複数の論理ボリュームを作成し、rootとswapを割り当てる。

参考にしたのは以下。

www.youtube.com

上記動画ではUEFIブートを前提としていないので若干手順が異なる。


前回と同様にWindowsのディスク管理でCドライブを縮小しLinuxのインストール領域を作る。unetbootinでUbuntu Desktop 16.10のインストールディスクを作っておく。

一旦シャットダウンしてインストールディスクから起動し、GPartedで未割り当ての領域に以下のようにパーティションを作る。

  • /boot用のパーティション: ext2, 500MiB (ここでは/dev/sda5)
  • /用のパーティション: ext4, 残り領域すべて (ここでは/dev/sda6)

このとき、/用のパーティションにはlvmフラグを立てておく。

端末を開いて以下のコマンドを順番に実行する

$ sudo -i
# cryptsetup luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 2000 /dev/sda6
# cryptsetup luksOpen /dev/sda6 sda6-crypt
# pvcreate /dev/mapper/sda6-crypt
# vgcreate UbuntuVG /dev/mapper/sda6-crypt
# lvcreate -C y -L 16G -n swap UbuntuVG
# lvcreate -C n -l 100%FREE -n root UbuntuVG

やっていることは以下の通り

  • cryptsetup luksFormat/dev/sda6を暗号化
  • cryptsetup luksOpen/dev/mapper/sda6-cryptにマウント
  • pvcreateでLVMの物理ボリュームを初期化
  • vgcreateで物理ボリューム上にボリュームグループを作成
  • lvcreateでボリュームグループ上に論理ボリュームを2つ作成
    • -Cオプションは論理ボリュームを隣接させるかどうかのオプション
    • -Lオプションはボリュームのサイズを指定するオプションで、16Gなど数値で明示的に指定する
    • -lオプションはボリュームのサイズを指定するオプションで、100%FREEのように割合で指定できる

ここまで実行したら、インストーラを起動して通常通りインストールする。なお、ここではサードパーティのアプリケーション等をインストールしない。

インストール先の選択では「それ以外」を選んで

  • /dev/UbuntuVG/rootをext4で初期化して/をマウントポイントに指定
  • /dev/UbuntuVG/swapをswap領域に指定
  • /dev/sda5をext2で初期化して/bootをマウントポイントに指定
  • ブートローダのインストール先を/dev/sdaに指定

を行い、インストールを続ける。一通り実行したら、再起動せずにUbuntuの試用を続ける。

再び端末を開いて以下を行う

$ sudo -i
# mount /dev/mapper/UbuntuVG-root /mnt
# mount /dev/sda5 /mnt/boot
# mount /dev/sda2 /mnt/boot/efi
# cd /mnt
# mount --rbind /dev dev
# mount --rbind /sys sys
# mount --rbind /run run
# mount --bind /proc proc
# chroot . /bin/bash -l
(chroot)# echo "sda6-crypt UUID=/dev/sda6のUUID none luks,discard" > /etc/crypttab
(chroot)# update-initramfs -u
(chroot)# grub-install --recheck /dev/sda
(chroot)# grub-mkconfig -o /boot/grub/grub.cfg
(chroot)# exit
# cd 
# umount -l /mnt
# sync
# reboot

やっていることは以下の通り

  • mount/mnt以下に作成したパーティションたちをマウントする
    • Windows Boot Managerの/dev/sda2/mnt/boot/efiにマウントしておかないとgrub-install --recheck /dev/sdaで弾かれる
  • /etc/crypttabを作成する
    • 各項目はタブ区切り
    • sda6-cryptは先程luksOpenで使った名前をそのまま使う
    • UUIDは、別の端末を開いてsudo cryptsetup luksOpen /dev/sda6すると表示される
      • sudo blkid/dev/sda6のものを探しても良い
    • noneは鍵の場所指定。今回は鍵がないのでnoneとする
    • luks,discardはオプション。discardはSSDの場合のみつける
      • SSDのパフォーマンスを維持するためTRIMコマンドを使うかどうかの指定
  • grub-mkconfig -o /boot/grub/grub.cfgでブートメニューを更新

あとはchroot環境を抜けてマウントしてたパーティションをアンマウントし再起動する。Ubuntuを起動するとsda6-cryptのパスワードを1回だけ求められ、入力すると起動できる。


これでUbuntu 16.10 on LVM on LUKSの環境を整えられた。Windows側の領域をBitLockerで暗号化している場合は、これらの作業を終えたあとにWindowsを起動する時、初回のみBitLockerの回復キーを入力して起動する必要がある。

Windowsが入っているマシンにパーティションを暗号化した上でUbuntuを同居させる

新型MacBook Proのキーボードをヨドバシ店頭で触ったところ2秒でやっていけないことに気づいたのでThinkPad X260を購入した。ThinkPad EdgeやX201を使っていたこともありX260自体にはなんの不満もなく、安価でそこそこのスペックの製品を買うことができてよかった。

一方で、Windows 10でこれまでMacでやっていたような開発を続けるのは困難だということもわかってきた。最初はLinux Subsystem for WindowsやらPowerShellやらでなんとかなるだろうと見込んでいたものの、その見立ては完全に外れていた。

そこで、Ubuntu 16.10を同居させてデュアルブートできるようにした。Windowsを飛ばしてUbuntuのみにしなかったのは、ひとえに紙芝居的なゲームをするため。Ubuntuにしたのは、わざわざOSのメンテにコストをかける気持ちがなかったため。

Ubuntuをデュアルブートするのは簡単で、Windows側でディスクを縮小して、unetbootinでUSBメモリに焼いたインストーラからうまい具合にインストールすれば良い。しかし、パーティションの暗号化をしつつインストールするには一手間必要だったので、ここにメモする。なお、Windowsが入っているパーティションはBitLockerで暗号化している。


基本的にはここの通りにすると良い。ディスクの暗号化にはLUKSを使う。

askubuntu.com

いきなりインストーラを起動するのではなく、GPartedでパーティションを切る。元のサイトでは

  • boot (ext2) - If you have Windows installed with UEFI, this can be skipped,
  • root (ext4),
  • swap (linux-swap)

と書いてあるが、UEFIブートしているにもかかわらずbootパーティションを作らずにインストールしたところ、grubのインストール時にコケたのでどうも必要そうだった。この場合、実際にディスクを暗号化するのはrootとswapのみになる。どちらもパスワードを別個に設定して、起動時には両方のパスワードを入力してマウントすることになる。(が、なぜコケたのか正直良くわかっていないし、本当に使われているのかわからない。誰か教えてくれ!!!)

今回はboot領域を250MiBで確保し、ext4でフォーマットした上でboot,espフラグを立てた。root, swapは上記の通り。適用すると、sda5,sda6,sda7ができた。

次の詰まりポイントはcryptsetup luksFormatだと思う。コマンド自体はこれで問題ないが、Are you sure? (Type uppercase yes):と出て来るので、大文字でYESと記入する必要がある。入力すると、パスワードと確認用にもう一度パスワードを求められるので記入する。これをsda6とsda7それぞれに行う。

それぞれluksOpenでrootとswapでマウントしたら、それぞれmkfs.ext4やらmkswapやらしておく。あとはインストーラを起動して、インストール先の選択時に「それ以外」を選び、パーティションをそれぞれ設定する。sda5は初期化せず、マウントポイントを/bootにする。/dev/mapper/rootのマウントポイントを/に、/dev/mapper/swapはすでにswapになっているはずなのでそのままにする。

通常通りインストールを終えたら、再起動せずにもう一度端末を開く。

リンク先に書いてあるとおりrootやらbootやらをマウントしてchrootしておく。ここで/etc/crypttabを設定する。

root UUID=<uuid> none luks
swap UUID=<uuid> none luks,swap

というような内容になるはず。このuuidはsudo bulkidで探せば見つかるが、sudo cryptsetup luksUUID /dev/sda6などとしたほうが素早く見つかる。別の端末を開いて実行しないと取得できないので要注意。その他詰まりどころはないはずなのでリンク先の通りに実行して再起動すると良い。ちなみにupdate-initramfs -uするときにwarningを吐く気がするけれど、無視して問題ない。

再起動後、rootとswapのパスワードをそれぞれ入力するとUbuntuを起動することができる。