2025年 05月 16日

7年放置した mqtt_topic_exporter を Copilot とともに書きかえた

mqtt_topic_exporter という mqtt ブローカーに接続して特定の topic を subscribe して prometheus 形式で出すというのを、7年前に書いたまま放置していた。

放置といっても(珍しく)使ってなかったわけではなく、ビルド済みバイナリをずっと使い続けていた。けどまぁ7年も経過すると何もかもかわっており (当時 go.mod すらなかった)、現行のツールチェインではビルドできなくなっていたので、なおすことにした。

  1. 現行ツールチェイン (go 1.22) でビルド可能に
    • ついでに kingpin を使うには小粒ツールすぎるので標準の flag に置き換えた
  2. Dev Container に対応させた
    • mqtt broker がないとデバッグできないので、Eclipse Mosquitto を docker-compose で同時に立ち上げてあげる感じに
  3. e2e テストを追加
    • Dev Container 内部で、Mosquitto と接続してうまいこといくかのテスト
  4. graceful shutdown
  5. リファクタリング

全体的に Copilot Agent に分からんこと聞いたり、やりたいことを指示するだけでほぼ完了させることができた。特にテストは自力で書こうと思うとダルすぎてたぶん一生やらなかった。「どうしたらいいかねえ」ぐらいのふわっとした段階から壁打ちして方針 (e2eだけテストしようとか) 決めて、雑に初期実装してくれるのはありがたい……

ただ今回、普通に指示するだけだとベタ書きする感じだったので、分けてほしい部分は個別に指示する必要があった。あとやっぱり普通に嘘をつかれる。「version.NewCollector() はなくなりました (正しくは別パッケージに移動)」とか

2025年 01月 24日

Google Spreadsheet で配列リテラルに QUERY() したときのカラム名

Google Spreadsheet は {A:A, C:C, R:R} みたいに式を書くと、横方向に結合して新しいテーブルとして評価することができる (縦に連結する場合はセミコロン)。これは「配列」と呼ばれている。配列

配列とは、値を含む行と列からなるテーブルのことです

このテーブルに対して QUERY する場合、カラム名は Col1 Col2 ... となるらしい。

例えばこのように

QUERY({SheetA!$C:$C,INDEX(IFERROR(VALUE(SheetA!O:O), 0))}, "SELECT SUM(Col2) WHERE Col1 = '"&$C6&"' LABEL SUM(Col2)''", 1)

QUERY の結果からカラム名を消したい場合

LABEL Col1 "" のように SELECT したカラムに対してラベルを空にすると消えてくれる。

2024年 12月 15日

この日記上の Twitter 関係のボタンを削除した

Bluesky に置き換えた。Bluesky の共有は以下のようにすればいいみたい

https://bsky.app/intent/compose?text=...
2024年 12月 05日

FNIRSI DPS-150 安定化電源のUSBプロトコルを解析してアプリ実装した


FNIRSI DPS-150 直流安定化電源 0~30V 0~5A電圧電流調整 CNC プログラマブルスイッチング電源 4桁 IPSディスプレイ 150W低雑音 高精度 研究実験室用 テスト修理 バッテリー充電 電気のメンテナンス - FNIRSI

FNIRSI

5.0 / 5.0

FNIRSI DPS-150 という実験用の直流安定化電源を買ってみた。USB-PD から電源をひっぱってこれるという最近の流行りというか ALIENTEK DP100 とかの系統の製品

特別悪いところは今のところ感じてない。50mV以下の電圧にはならないぐらい。画面が大きくてみやすい。

FNIRSI というとあやしいオシロスコープを買ったことがあるのでスペック表記はあんまり信用できない。

USBのプロトコル解析とウェブアプリ化

冒頭の動画で説明してるけどUSBプロトコル(シリアルポート)を解析してウェブアプリとして再実装した。JSでプログラマブルに制御を書けるようになった。

ウェブアプリの細かい話1: タイムアウト付きのJS実行

プログラマブルにするにあたって、うっかり無限ループを書いたときのためにスクリプトの実行時間にタイムアウトをつけたいなと思った。

かつてはそんなこと実現できなかったけど、今は Worker#terminate() があるので、Worker 化できる関数なら実現できるみたいだった。functionWithTimeout() みたいな関数を作ってみたけど動いてる。

https://gist.github.com/cho45/cda6bb74d3d82790663762da43298538

ウェブアプリの細かい話1: シリアルポート通信のWorker化

ブラウザのコンテキストだと、タブが非アクティブになったときなどに、 setTimeout() の時間がとんでもないことになるとか、いろいろ制限がある。

面倒くさくても定期的に処理を行いたい通信プロセスは Worker に逃がすほうが良い。Comlink を使っている。


ref

2024年 10月 07日

macOS の EOS Utility 「カメラとUSB接続できませんでした」

どうあがいても接続できなくて困った。

どうやらなんか Google Chrome が USB デバイスをかたっぱしからオープンする挙動をしているようで、busy 状態になっているようだった。libusb 関係のなにかなのかもしれない。

EOS Utility 3@(null): AppleUSBHostUserClient::openGated: failed to open Canon Digital Camera@01100000: provider is already opened for exclusive access by pid 602, Google Chrome

Console.app で検索かけていたら以上のエラーログが見れたので原因がわかったけど、わかりにくすぎる

ptpcamerad も変な挙動をしていてカメラが繋がらなくなる。強制的に終了しても起動してくるのでやっかい

EOS Utility 3@(null): AppleUSBHostUserClient::openGated: failed to open IOUSBHostInterface@0: provider is already opened for exclusive access by pid 17290, ptpcamerad

止めた。

sudo launchctl unload /System/Library/LaunchAgents/com.apple.ptpcamerad.plist
sudo launchctl disable gui/501/com.apple.ptpcamerad

ref

2024年 10月 02日

transix AFTR のロードバランス

たびたび transix の IPv4 のポート制限(1024)にひっかかって、そのたびにAFTRを切り替えていたけど、ふと思いついてトンネルを2つ貼って、ロードバランスして2048上限になるようにしてみた。

これでまだ上限あたるようだとほんとにお手上げなんだけど、なんかもっといい方法ないんかな~

ip route default gateway tunnel 1 gateway tunnel 2
tunnel select 1
 tunnel encapsulation ipip
 tunnel endpoint address 2404:8e00::feed:100
 ip tunnel mtu 1460
 ip tunnel secure filter in 1020 1030 2000
 ip tunnel secure filter out 1010 1011 1012 1013 1014 1015 3000 dynamic 100 101
 102 103 104 105 106 107
 ip tunnel tcp mss limit auto
 tunnel enable 1
tunnel select 2
 tunnel encapsulation ipip
 tunnel endpoint address 2404:8e00::feed:101
 ip tunnel mtu 1460
 ip tunnel secure filter in 1020 1030 2000
 ip tunnel secure filter out 1010 1011 1012 1013 1014 1015 3000 dynamic 100 101
 102 103 104 105 106 107
 ip tunnel tcp mss limit auto
 tunnel enable 2

RTX1200 は「ポートセービングIPマスカレード」とよばれるのはできないらしい。ルーター自体あたらしくして、有効にできたらもうちょっと余裕でるかもだけど、ポートセービングIPマスカレードもTCPにしか適用されないので、どれぐらい効果あるものなのかよくわからない。

紫外線遮蔽率とUPFとSPF、PA

UPF

UPF は衣類に使われる。UPF50 の意味は紫外線の影響を1/50にするという意味

なので紫外線遮蔽率に換算できる (1 - 1/UPF)

UPF 50の場合、(1 - 1/50) = 98%

SPF / PA

SPF は UV-B、PA は UV-A に対する指標ということになっている。

SPFとPAは基本的にはなんと人体実験によって測定されている。
(一応分光による評価するシステムもあるらしい
https://www.jasco.co.jp/jpn/technique/applicationdata/UV/130-UV-0041.html )

SPF値は、その値を示す日焼け止め化粧品を塗って紫外線を浴びた場合に、何も塗らなかった時と同程度に赤い日焼け(サンバーン、紅斑)を起こすまでにかかる時間の倍率を示しています。例えば、SPF25の日焼け止めクリームを塗ると、素肌と同程度の紅斑を起こすには25倍の時間がかかることを意味しています。

一方PA値は、黒い日焼け(サンタン)を対象としており、何も塗らなかった時と同程度のサンタンを起こす時間の倍率の数値がPA≦2ならばPA、PA=4~8ならばPA++と記号で格付けされます。

これらSPF値やPA値の評価方法は、ISO-24442やISO-24444を元に日本化粧品工業連合会で規定されており、1cm2当たりに2mgまたは2µLの試料を被験者の皮膚に塗布して人工太陽灯による照射を行い、塗布した場所としない場所の最小紅化時間を測定します。しかし、この試験は研究開発段階で行うにはコストがかかり、被験者の個人差も現れます。

PA+ : PPD値が2以上4未満
PA++ : PPD値が4以上8未満
PA+++ : PPD値が8以上16未満
PA++++ : PPD値が16以上

PAは一度PPD値という数値から変換されて謎の指標になる。PPDとSPFの数値の意味はUPFと同じように影響を1/nにするということなので、波長ごとの遮蔽率とみることができる(はず)

たとえば

  • SPF50
  • PA+++

なら SPF50 = UV-B を 98%カット、PA+++ = UV-A を 88%~94% カット という換算が一応できる (はず?)

2024年 09月 19日

ネコ演算子 (ねこみみ演算子) とは

ねこみみ演算子で検索するとものすごい古いエントリがヒットしてなおかつ内容がネコ演算子に関係するものではないという問題がある。

今思いだそうとしても、ねこみみ演算子ってなんだっけ?と思ったので記録しとく

ネコ演算子

そもそもねこみみ演算子というのは(たぶん)なくて、ネコ演算子のことだと思う。

Perl6 の ^..^ オペレータのことを Neko Operator と呼んでいたという記録が2005年8月

範囲演算子
末尾を含まない「..^」(Rubyの「...」)、先頭を含まない「^..」、 先頭と末尾を含まない「^..^」。Damianはこれを「Neko operator」と呼んでいた。 2ちゃんかっつーの。

https://matz.rubyist.net/20050803.html#p02

Perl6 は Raku と名前をかえてリリースされたけどネコ演算子は現存している Raku Operators

2024年 09月 07日

DaVinci Resolve で作成した動画を Android YouTube でアップロードしようとすると「動画をプレビューできません」となる

追記: 今はショート動画をPCからアップロードした場合、モバイルの編集画面からショート動画のサムネイルを設定できるようになっている。
このため、いちいちモバイルYouTubeを使ってアップロードする必要ない

以下のようにすれば良い。タイムコードが入っている動画ファイルはYouTubeアプリでは開けないらしい (Google Photos などでは普通に開ける)

ffmpeg -i '/mnt/c/Users/cho45/Desktop/doremi.mp4' -c:a copy -c:v copy -write_tmcd 0 '/mnt/c/Users/cho45/Desktop/doremi-removed-tmcd.mp4'

なんでPCからアップロードしないの?


PCからショート動画をアップロードする場合、なぜかサムネイルを指定できないという大きな欠点がある。なのでサムネイルが適切に設定されない場合、モバイル版の YouTube アプリを使ってアップロードする必要がある。

他の方法は?

Google Photos では開けるので、Google Photos で開いて、コントラストを1だけ変更したりなんでもいいのでちょっと編集して「コピーを保存」すれば YouTube で開ける動画にはなる。うまくはいくけど再エンコード走るのでだるい。

参考

日本語ではどうしても解決せず「android youtube unable to preview」で解決

ref.

Android と USB 接続したとき、どうあがいても一部のファイルを転送できない

症状としては

  • ファイル転送 / Android Auto モードで USB 接続し
  • Windows Explorer からコピーしたいデバイスのフォルダを開き
  • ほとんどのファイルのコピーは成功するが (jpg や txt など)
  • mp4 ファイルだけ転送することができない
  • エラーの表示などはまったくないが Explorer からエラー音はなる
  • 転送できないファイルを .txt に拡張子をかえると、コピーダイアログまでは出るようになるが、やはりコピーはできない

どうあがいても無理。MTP など他のモードでも無理。Android のファイル転送モードはやたら遅くて、なんか変な制御がかかっているんだろうけど、挙動がおかしすぎるのでできるだけ使わないほうが良い……

他の解決方法: Google クイック共有 / Quick Share / 旧ニアバイシェア

たぶん代替としてはこれが一番簡単かつ最速
https://support.google.com/android/answer/9286773?hl=ja

他の解決方法: Google Drive 経由

次点で間違いなく解決はできるがめんどくさい + Google Drive に保存する必要がなくても、一時的に保存する必要がある