hunamizawa’s blog

無い物は作りたい人のメモ帳

プログラマに転職してました&今年の振り返り

年を越す前に、今年の振り返りをしておかなければ。

転職してました

実は11月に、4年続けたドラッグストアのバイトを辞め、プログラマに転職してました。

いちおう登録販売者の資格も取得したので、このまま続けるルートもあったけど、別にコロナの騒乱で仕事が嫌になったとかではなく、単純にプログラミングのスキルを生かさないともったいない気がしたので。

まあ、自分が突き上げられた一番の理由は「未経験からプログラマになるのは27歳が限界」って言葉かな。やらずに後悔するのも嫌なので、思い切って面接を受けてみたら、こんなご時世だけど縁あってジョインさせて頂くことができた。

入社して、触ったこともないAndroidアプリ開発にいきなりアサインされたけど、2ヶ月間頑張ったら Issue を消化できるくらいにはなったので、これからはプログラミングで飯を食って行けそう。

諸般の事情を考慮してバイトで入社したが、これからはITエンジニアとして生きていく決心をしているので、まずは正社員登用を目指して修行を積んでいきたい。

今年の活動

今年取り組んだことで一番形になったのは、やっぱり mb-node かな。ディスクタイトルプリンターとしてそこそこ活躍してくれたけど、3ヶ月ぶりに使おうと思ったらインクタンクの中まで固まってたとさ。

ディスクタイトルを印刷しようと思ったのは、500枚くらいある録画済みBD-Rの管理のためのソフトウェアを作ろうとしているのが理由で、その成果の一部が AribB24.DotNet。そろそろ beta 外そうかな?

ESP8266 で作る置時計ベースキットを売ろう作戦は、コロナによるサプライチェーンの不安とかいろいろあって、やる気がなくなっている。そこからの成果である ESPPerfectTime は、初めて人からPRを貰えて嬉しかった。個人名義の活動は、基本的には自分が楽するためのことしかしてないけれども、それが誰かの役に立っているのなら嬉しい。

今年に限って言えば、プログラマとして採用してもらうためのポートフォリオ作りも個人活動の目的に含まれていて、それがなかったら天鳳の牌譜を画像に変換βは PHP じゃなく node.js とか C# で作ってたと思う。

あと表に出してないことで、完全に個人用で pixiv & twitter のイラストダウンローダー兼検索アプリを書くのに、けっこう時間を費やしてる感。というのも途中で、仕事でクリーンアーキテクチャというものを知ったので、その練習のために書き直しているのもある。

来年やりたいこと

一番は、体調を崩さないように、適度に適当にやること。自分のパフォーマンスが不安定にならないように自己管理して、常に一定の能力を発揮できることが最も大事なこと。一時すごく頑張っても、その後しばらく働けないようだと飯は食えない。

  • イラストダウンローダー完成
  • BD-R管理ソフト完成
  • ESP8266 で作る置時計ベースキットを売る
    • たぶんできなさそうなので、MAX7219 制御部分をライブラリとして切り出すぐらいはしたい
  • 室外温度計(これも ESP8266)完成
    • 太陽電池とセンサーだけ設置して満足してしまい、制御基板が出来ないまま1年以上放置してる()

MBrush (PrinCube) の研究② - node.js に移植しようとして先を越された

mb-node

とりあえず、MBrush のアプリを介さず CUI から画像を印刷できるようにした。

github.com

のだが、依存するレポジトリにも同様の機能が入ってしまったので、現状では存在意義が微妙……(泣

使い方

git clone --depth=1  --recursive https://github.com/hunamizawa/mb-node
cd mb-node
./build.sh
npm ci --production

MBrush を接続してから

node app.js input.png

これでWi-Fi 経由でプリンターに画像が転送される。USB 接続の場合は -c usb を足してくだち。

複数枚の画像を印刷したい場合は

node app.js input1.png input2.png

とすれば、MBrush の元々のアプリで印刷領域を複数設定したのと同じ挙動になる。

前回の続き

前回。

hunamizawa.hatenablog.com

WebAssembly (WASM) の存在は、多少は知っていた。C++ とか何かの言語で書いたソースを、Java でいうバイトコード、.NET でいう IL のような中間コードに変換して、Web ブラウザ上で実行できるようにする。JS よりも効率よく動作し、ランタイムをインストールする手間もない、お手軽クロスプラットフォーム、という話は聞いたことがあったが、実際に WebAssembly で実装されたアプリを見るのは初めてだった。

Chrome の開発者ツールで .wasm ファイルを覗くと、バイナリから勝手に human-readable なテキスト表現(S式)には変換してくれるが、アセンブリに近い言語なので読む気にはならない。他言語への移植は難しそう。

node.js に移植できそうな気がした

mbc.wasm と同じディレクトリにある mbc.js は、何かのツールで生成したコードのようである。調べたところ、EmscriptenC/C++ から WASM をコンパイルした際に生成される、JavaScript から WASM を呼ぶためのラッパーだと判明した。このラッパーを観察すると NODEFS 等、node.js に関係しそうな変数名が使われている。

で、前回話した、画像を .mbd 形式に変換する最中に、console に何かデバッグメッセージが流れてくる。その中にこんなのがあった。

mbc: (7) ["128", "168", "60", "-i0", "-o0", "-w0", "-s2"]

-i0 とか -o0 とか、なんかコマンドライン引数みたいだなあ、と思いつつ、この配列をどこで使ってるのか調べたところ、WASM の中にある callMain() という関数に渡されている様子。いかにもコンソールアプリ臭がする名前だ。

また、実験の過程で次のような ImageMagick っぽいエラーメッセージを吐いており、この WASM には ImageMagick が静的リンクされていると推測している。

UnableToOpenBlob 'ori.png': No such file or directory @ error/blob.c/OpenBlob/3497.
InvalidArgument '-colorize' '100-geometry' at CLI arg 12 @ error/operation.c/CLISimpleOperatorImage/2020.

おそらく開発者は、PNG 画像を .mbd 形式のファイルに変換するために、まず

$ ./foobar 128 168 60 -i0 -o0 -w0 -s2

のように使うコンソールアプリを作り、クロスプラットフォーム対応のために WASM へ移植したのだろう。

mbc.wasm の仕様

コマンドの引数:

[String(brightness), String(saturation), String(density), '-i' + invert, '-o' + c_order, '-w' + c_width, '-s' + dpi_step]

各変数の意味は https://github.com/dukelec/mb/blob/master/doc/dev.md に書いてあった:

args:
  img_dat: input png image, in type: Uint8Array
  brightness: 0~200, default 100
  saturation: 0~500, default 100
  density: 1~100, default 100
  cal.c,m,y: 1~255, default 255
  invert: print direction: 0: left to right, 1: right to left
  c_order: 0: CMY, 1: CYM. default 0
  c_width: cartridge chip width: 0: 4.4mm, 1: 4.9mm. default 0
  dpi_step: dpi setting: 1: 1200x1200, 2: 1200x600, 4: 1200x300
  st_cb: progress status callback function
ret:
  .mbd file data, in type: Uint8Array

WASM の初期化が重い

node.js の起動 + WASM の初期化で結構時間がかかる。画像が複数枚あると意外とストレスを感じる。もっとサクッと処理して欲しいなぁ。

というわけで、サーバーを立てて HTTP 経由で画像を渡せるようにする実験をしている。これなら WASM の初期化はサーバープロセス起動時の一度だけで済むよね。拙作の mb-node は今後この向きで育てていきたい。

*1:node.js 用に NODEFS なるものが用意されていたけど、使い方がよく分からなかった

MBrush (PrinCube) の研究①

「ハンディープリンター」というジャンルをご存知だろうか? ハンディスキャナーのごとく、小型の筐体を手に持って左右にスライドさせると、対象物に文字や画像を印刷できる。国内メーカーではリコーが唯一製品化していて、4万円ながら入荷待ち多数と大人気なようだ。

一方海外に目を向ければ、同様のコンセプトの製品がいくつかある。今回はその中から、中国メーカーの MBrush (PrinCube) を使ってみた。

購入の動機

  • 大量(数百枚)の Blu-ray ディスクに、ユニークな QR コードを印刷したい。
    • レーベル印刷できる(普通の)プリンターは、専用トレイにいちいちディスクをセットして、プリンターに挿入して…… という作業が面倒。1枚印刷するのに時間がかかりすぎる。もっと手軽に、高速に印刷したい。

MBrush を選択した理由

  • 安価(送料込みで95米ドル前後)
  • 日本国内でインク調達可能
  • Web アプリ経由で印刷するので、ハックして他アプリとの連携できそう

MBrush と PrinCube

MBrush と酷似の商品で PrinCube というモノがあるが、どうも両者は同一製品らしい。商標の都合?らしく、中国国内では MBrush、それ以外では PrinCube の名で売っているようだ。

MBrush (PrinCube) のしくみ

ヒューレット・パッカード (HP) のプリンターで、インクタンクとプリンタヘッドが一体になっている製品がある。これをハックして小型化したのが MBrush (PrinCube) だ。ヘッド付きインクは昔からあったので、超小さいプリンター作れるんじゃないかな~、と思ったことがあるが、まさにそれ。

HP のプリンターは日本国内でも売ってるので、インクの入手はたいへん容易(サプライを個人輸入しないで済むのは大きい)。62XL/64XL/804 あたりが使える。黒インクは使えないっぽい?

f:id:hunamizawa:20200828130219j:plain
MBrush 底面

底面の写真がこちら。電源スイッチと、インクを固定するフタのロック、移動方向を制限する2本のローラー、あとはセンサーが見える。これはおそらく赤外線センサーで、マウスと同じ原理で移動量を検出していると思われる。

f:id:hunamizawa:20200828130228j:plain
MBrush 基板

上フタもツメで止まっているだけなので簡単に開けられる。下側に MPU の Ingenic X1021 が見える。Wi-Fi の IF は蟹さん…ではなく ESP8089(8266EX じゃないよ!)、あと FPGA (Lattice iCE5) が積んであって、これでヘッドに送る信号を生成するのかな? 基板裏面にも何かありそうだけど、外すのが面倒なのでやめといた。

使ってみる

電源を入れるとアクセスポイントが立つので、そこに接続。192.168.44.1 にアクセスすると Web アプリが読み込まれる。

(MBrush 持ってない人もアプリの使い勝手はここで体験できる)

最初から入ってるサンプルを開いてみると、印刷したい領域を指定するクロップ枠を複数指定できるようになっている。

f:id:hunamizawa:20200804131235g:plain
クロップ枠の高さは固定値

クロップ枠の高さを変えてみると、うーん悲しいかな、横に書いてある実際の印字サイズの高さは 14.29 mm 固定で、変えられるのは幅だけのようだ。複数行印刷用の定規がついてきたのに、複数行に分けて印刷するようなオプションも見当たらない。

画像ファイルを読み込んで即印刷という機能もなく(これをやりたかった)、新規プロジェクトを立ち上げて、画像をキャンバスに追加して、クロップ枠を指定、という手順を必ず踏まないといけないようだ。

なんか微妙だなぁ。

Web アプリの動作を観察してみる

使いにくいので、さっそくハックしてみよう。ちなみにアプリのソースコードは探したら GitHub に転がってた。

github.com

印刷ボタンをクリックした時の流れを観察すると、PC 側で PNG 画像を一旦 .mbd なる内部ファイル形式に変換して、それを POST している。この処理は Web Worker 上で実行して、UI のブロッキングを防ぐ作りになっている。とてもモダンな感じだ。

で、肝心のコア部分は mbc.wasm で実装されている。wasm? そう、WebAssembly である。

次回へ続く。

hunamizawa.hatenablog.com

『天鳳の牌譜を画像に変換β』をリリースしていた

サービスを公開したのに、説明をどこにも書かず放置していたので今書く。

hunamizawa.com

これは何かというと、天鳳牌譜エディタβで入力した牌譜データを、画像1枚に整形して出力するツール。

説明

天鳳
麻雀が無料で打てるオンラインゲーム。
牌譜
麻雀の対局において、その経過(各プレイヤーの配牌や摸打)を記録したもの。

天鳳牌譜エディタβとは、紙の牌譜やリアル対局を、後でアニメーションとして再生させられる、大変便利なツールである。

天鳳の牌譜を画像に変換β』はその真逆を行く(不便な方へ向かう)ツールなわけで、誰得感が半端ないが、これを作ったのは PHP の勉強のためなのでご容赦願いたい。

作業のあれこれ

思いついてからリリースまでの経過は、だいたいこんな感じ。

結局、開発環境と運用環境のわずかな差で躓いて、時間を浪費してしまった気がする。環境を揃えるって大事。

利用実績

公開してから1ヶ月半ほど経過したが、現在までの利用者は 0 人でございます(うp主調べ)。

まあ、鯖に負荷かからないからいっか……。

Git/GitHub で困った時に見るリンク集

全体の流れ

qiita.com

やらかした時

  • 間違って git reset --hard してしまった

qiita.com

マージ

hpcmemo.hatenablog.com

beyondjapan.com

元に戻す

qiita.com

履歴操作

git-scm.com

qiita.com

差分を見る

qiita.com

qiita.com

はじめての Apache on Ubuntu その1

大体のことはここ↓を見れば分かる。

akabeko.me

CentOS ではなく Ubuntu を選択したのは、そこに Ubuntu machine があったから。特に深い意味はない。

ドメインの取得

サーバーはすでに所有しているものとする。筆者はさくらの VPS をサーバーとして使う。

まず、どこかからドメインを買ってくる。筆者は お名前.com で hunamizawa.com を購入。

DNSの設定

正引き

FQDN (hunamizawa.com) から IPアドレスを得る、基本的な設定。お名前.com の管理画面から、サーバーのIPアドレスをAレコード・AAAAレコードに設定する。メールは使う予定がないのでMXレコードは設定しない。

DNS がある程度浸透するまで数時間待つ。

逆引き

IPアドレスから FQDN (hunamizawa.com) を得るための設定。

nslookup hunamizawa.com が通るようになったので、さくらのVPSの管理画面から、ホスト名逆引き登録で hunamizawa.com を設定する。

この後、DNS が完全に浸透するまで3日ぐらい必要なので、その間にローンチの準備をするのが吉。

Apache のセットアップ

とりあえずここ↓を見て、http://hunamizawa.com/ にアクセスすると "It works!" と言ってくれる状態にする。

akabeko.me

で、冒頭に申し上げた通り Ubuntu を使っているので、よく使われる CentOS とは細かい違いがある。

  • Apache のユーザー名は www-dataapache ではない)
  • 設定ファイルの置き場は /etc/apache2
    • *-available*-enabled というディレクトリがあって、シンボリックリンクを張ることで必要なモジュールだけを読み込む仕掛けになっている。systemctl の enable/disable みたいなノリ。

SSL 証明書を取得

HTTP over SSL に必要な証明書を、Let's Encrypt から貰ってくる。ちょっと前なら SSL 証明書を貰うのにウン万円必要だったのに、すごい時代になったなぁ。

まず、certbot を入れる。apt-get で入るやつは古いから使わないほうが良いとのこと。

apt-get install python3 pip3
pip3 install certbot

依存関係で足りないモジュールがあれば都度 pip3 install する。自分の場合は「cryptography が古いよ」と言われたので install --upgrade cryptography した。

次に、80番ポートを一瞬開けておいて、次を実行する。

certbot certonly --webroot -w /var/www/html -d hunamizawa.com

連絡先のメアドを入れたり、利用規約への同意にチェックしたら、ACME によるドメイン名所有の認証が行われて、証明書が発行される。

free-ssl.jp

Apache のセットアップ(続き)

以降は HTTPS で serve すればよいが、ACME の仕様上 HTTP も開けておかないと証明書の更新ができない。サイト利用者の利便性も考えて、HTTP (80) 宛のリクエストを全部 HTTPS (443) にリダイレクトするように設定しておく。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^hunamizawa\.com
RewriteRule ^/(.*)$ https://hunamizawa.com/$1 [R=301,L]

qiita.com

SSL 証明書のパスを適切に設定する。

SSLCertificateFile      /etc/letsencrypt/live/hunamizawa.com/fullchain.pem
SSLCertificateKeyFile   /etc/letsencrypt/live/hunamizawa.com/privkey.pem

設定ファイルの構文チェック。

apachectl configtest

必要なモジュールをロードし、サイトの設定ファイルを読み込ませる。a2en**/a2dis***-enabledシンボリックリンクを張ったり剥がしたりするコマンド。

a2enmod ssl
a2enmod rewrite
a2dissite 000-default
a2ensite hunamizawa.com
systemctl restart apache2

80番と443番を開けて、SSL 関係のエラーが出ないこと、HTTP 宛リクエストが正常に 301 リダイレクトされることを確認する。

certbot を cron で回す

crontab に1行書き加えれば良い。

certbot renew

ここまで来れば、static なコンテンツを HTTPS で配信できる状態になった。後は PHP なり何なりのセットアップをすればよい。

Ubuntu での ImagickException: unable to open file `/tmp/magick-***' には extra package を入れろ

環境

症状

php-imagick 経由で SVG 画像を読み込む。

$img = new Imagick('hoge.svg');

すると、次の例外がスローされる。

PHP Fatal error:  Uncaught ImagickException: unable to open file `/tmp/magick-25662B639-gQXNdPk': No such file or directory @ error/constitute.c/ReadImage/544

原因と対処

Ubuntu で提供されている libmagickcore-6.q16-3 には、SVG のサポートが含まれていない。そのため SVG を読むと当然コケるのだが、なんの関連もない unable to open file なる例外が投げつけられるので、原因の把握には相当な時間を要することになる。

すなわち、libmagickcore-6.q16-3-extra を手動でインストールすれば問題は解消する。なお、php-imagick の依存関係で自動的にインストールされるのは無印 package だけであり、extra package は手動でインストールする必要がある。

apt-get install libmagickcore-6.q16-3-extra

事の顛末

私は PHP 初心者。ImageMagick と組み合わせたアプリを作り、サーバーで走らせたところ、このような例外に遭遇した。

ただ画像を読み込むだけなので、例外の原因の検討がつかない。ひとまず @ error/constitute.c と見えるので、imagick 側の問題か?と考える。

最初に疑ったのは、/tmp/ 絡みの例外なので PrivateTmp の影響。そこで PrivateTmp = false してみても、$img->setRegistry('tmp-directory', '/hogemoge') してみても、何も変わらない。

unable to open file tmp magick とかで検索してみると、「ImageMagick の特定バージョンでそういうバグがある」的な Issue を見たので、もしかしてバグを踏み抜いてる?

なら最新の ImageMagick を入れるか、と思って PECL の準備を始めた。ビルドの依存関係になるので何気なく aptitude show libmagickcore-6.q16-3-extra を見てみると

This package adds support for SVG, WMF, OpenEXR, DjVu and Graphviz to MagickCore.

あっ……

apt-get install libmagickcore-6.q16-3-extra で万事解決しましたとさ。