若くない何かの悩み

何かをdisっているときは、たいていツンデレですので大目に見てやってください。

あまりに BLE マクロを Nature Remo 上でデバッグするのが苦行だったので Swift 用の開発環境を整えた

TL;DR

Android nRF Connect の BLE マクロのサブセットを macOS/iOS/... 上で開発する環境を用意しました。

github.com

import Foundation
import BLEMacroEasy

// You can find your iPhone's UUID by running the following command in Terminal:
// $ git clone https://github.com/Kuniwak/swift-ble-macro
// $ cd swift-ble-macro
// $ swift run ble discover
let myIPhoneUUID = UUID(uuidString: "********-****-****-****-************")!
let myMacro = try String(contentsOf: URL(string: "https://ble-macro.kuniwak.com/iphone/battery-level.xml")!)

try await run(macroXMLString: myMacro, on: myIPhoneUUID) { data in
    // This handler is called when every value read from the peripheral.
    let batteryLevel = Int(data[0])
    print("\(batteryLevel)%")
}

macOS/iOS/... 上で BLE マクロを実行する機能のほかマクロの開発を助ける CLI を提供しています。BLE マクロ実行機能については README を見てください。CLI は BLE デバイスのスキャン、マクロのバリデーション、マクロの実行、対話的なマクロ実行をサポートしています:

$ # BLE デバイスをスキャンする
$ ble discover
00000000-0000-0000-0000-000000000000    Example Device 1    -78
11111111-1111-1111-1111-111111111111    Example Device 2    -47
22222222-2222-2222-2222-222222222222    Example Device 3    -54
...

$ # Ctrl+C でスキャンを中断する

$ # BLE マクロを実行する
$ ble run path/to/your/ble-macro.xml --uuid 00000000-0000-0000-0000-000000000000

$ # BLE マクロを対話的に実行する
$ ble repl --uuid 00000000-0000-0000-0000-000000000000
connecting...
connected

(ble) ?
write-command, w, wc    Write to a characteristic without a response
write-descriptor, wd    Write to a descriptor
write-request, req      Write to a characteristic with a response
read, r Read from a characteristic
discovery-service, ds   Discover services
discovery-characteristics, dc   Discover characteristics
discovery-descriptor, dd        Discover descriptors
q, quit Quit the REPL

(ble) dc
180A 2A29 read
180A 2A24 read
D0611E78-BBB4-4591-A5F8-487910AE4366 8667556C-9A37-4C91-84ED-54EE27D90049 write/write/notify/extendedProperties
9FA480E0-4967-4542-9390-D343DC5D04AE AF0BADB1-5B99-43CD-917A-A77BC549E3CC write/write/notify/extendedProperties
180F 2A19 read/notify
1805 2A2B read/notify
1805 2A0F readk

(ble) r 180F 2A19
58

なお開発した BLE マクロは Kuniwak/ble-macro で公開しています。

背景

Nature Remo に BLE(Bluetooth Low Energy)マクロ機能が搭載されました(公式アナウンス)。対応機種(Nature Remo3、Nature Remo mini2 ファミリー)の Remo をお使いなら BLE デバイスを Remo から操作できます。そこで BLE で操作できる我が家の Philips Hue のフルカラー電球x3を Remo から操作すべく BLE マクロの開発を始めました(無駄にフルカラーなのはこの動画を見て淡い憧れがあったため)。

我が家の Philips Hue

Remo のサポートしている BLE マクロは Android nRF Connect のサブセットです。マクロは XML で記述します。例えば Hue を白昼色で点灯させるには次のように記述します:

<macro name="hue-daylight-white" icon="BRIGHTNESS_HIGH">
    <assert-service description="Hue" uuid="932c32bd-0000-47a2-835a-a8d455b859dd">
        <assert-characteristic description="Combined" uuid="932c32bd-0007-47a2-835a-a8d455b859dd">
            <property name="WRITE" requirement="MANDATORY"/>
        </assert-characteristic>
    </assert-service>
    <write description="Set to Daylight White" characteristic-uuid="932c32bd-0007-47a2-835a-a8d455b859dd" service-uuid="932c32bd-0000-47a2-835a-a8d455b859dd" value="0101010201fe0302fa0005020100" type="WRITE_REQUEST" />
</macro>

BLE マクロでは service や characteristic という操作窓口で値の読み書きを指示できます。有名なデバイスならばこれらは 第三者による仕様の推測 である程度詳細がわかります。ただマクロを記述して Remo で動作する状態に持っていくまでにはそれなりに試行錯誤が必要になります。この試行錯誤がとにかく苦行でした

公式曰く Android なら nRF Connect for Mobile アプリで BLE マクロの記録から実行までをサポートしているらしく楽にマクロを開発できるようです。しかし手元には Android 端末がありませんでした。iOS 用に同じ開発者の 同名のアプリ がありますがこれにはマクロ機能がついていません。そのため最初の頃は Remo に BLE マクロを食べさせてみて理由のほとんどわからないエラーに直面して、BLE マクロを勘で書き換えて…というサイクルを回していました。

エラーに詳細な情報がない様子

このサイクルがあまりに不毛であったため Android の nRF Connect for Mobile と同様の機能をもつ環境をなんとか整えられないかと思い Kuniwak/swift-ble-macro を開発しました。nRF Connect for Mobile よりも大幅に機能は少ないですが、Remo で動作する BLE マクロを開発するには十分な機能を持っています。ぜひご活用ください。

なおBLE マクロを開発するには既存のアプリがどんな通信を BLE デバイスとしているかをキャプチャすることも重要です。詳しくは次のブログを読むとやり方がわかるでしょう:

harumi.sakura.ne.jp

BLE マクロを開発した際の苦労

Hue や Switchbot でさまざまな苦労をしたのでここで供養しておきます。

Hue から insufficient encryption エラーが返ってくる

Hue はペアリングしないと操作できないようです。ペアリングしていない central から read/write しようとすると insufficient encryption エラーが発生します。なおペアリングされるのは最初にペアリングされたデバイスのみです(後述する方法でこれを回避できる)。例えば初回に Hue のアプリで接続してしまうとそれ以降のデバイス(e.g. Remo、Google Nest mini)からは操作を受け付けてくれなくなってしまいます。これを回避するにペアリングしてある Hue の公式アプリ > 設定 > 音声アシスタント > Google Home > 検出可能にする、の操作が必要です。この操作によってごく短時間(1minほど?)ペアリングを受け付けてくれるようになります。これは service 0000fe0f-0000-1000-8000-00805f9b34fb の characteristic 97fe6561-2004-4f62-86e9-b71ee2da3d220x01 を書き込むことで再現できます(検出可能にする BLE マクロ)。

ペアリングし損ねた Hue のファクトリリセット方法がわからない

公式アプリや Mac などにペアリングする前に Google Nest mini などにペアリングされてしまうと前述の insufficient encryption 問題によって公式アプリや Mac などから操作ができなくなります。ファクトリリセットは BLE による操作で実現されているため公式アプリがペアリングされていない状況ではファクトリリセットが必要になります。

Hue をファクトリリセットする方法として点灯と消灯のサイクルを回す方法が紹介されています。しかし私の Hue(モデル LCA009、ファームウェアバージョン v1.116.3)ではうまく動きませんでした。代わりに、Hue の電源を壁面のスイッチ等から落としてから再び電源を入れると、ごく短時間 & かなりの近距離であれば Hue の公式アプリで検出可能になることを発見しました。そこからファクトリリセットができました。

Switchbot を操作しようとしても反応しない

Switchbot も BLE によって操作ができるデバイスです。ただこいつもなかなかの曲者です。v6.6 なら Discord の開発者コミュニティに紹介されているマクロ で操作ができるのですが v6.3 では操作を受け付けてくれません。試行錯誤しているうち v6.3 でも characteristic cba20002-224d-11e6-9fb8-0002a5d5c51b に 0x01 を書き込む前に cba20003-224d-11e6-9fb8-0002a5d5c51b で通知の購読をすると爪が動くことを発見しました。ということで v6.3 で動くマクロは以下になります:

<macro name="switchbot-push" icon="PLAY">
    <assert-service description="Switchbot" uuid="cba20d00-224d-11e6-9fb8-0002a5d5c51b">
        <assert-characteristic description="Push" uuid="cba20002-224d-11e6-9fb8-0002a5d5c51b">
            <property name="WRITE" requirement="MANDATORY"/>
        </assert-characteristic>
        <assert-characteristic description="Configuration" uuid="cba20003-224d-11e6-9fb8-0002a5d5c51b">
            <property name="NOTIFY" requirement="MANDATORY"/>
            <assert-cccd />
        </assert-characteristic>
    </assert-service>
    <write-descriptor description="Enable notifications" characteristic-uuid="cba20003-224d-11e6-9fb8-0002a5d5c51b" service-uuid="cba20d00-224d-11e6-9fb8-0002a5d5c51b" uuid="00002902-0000-1000-8000-00805f9b34fb" value="0100" />
    <write description="Write 0x570100" characteristic-uuid="cba20002-224d-11e6-9fb8-0002a5d5c51b" service-uuid="cba20d00-224d-11e6-9fb8-0002a5d5c51b" value="570100" type="WRITE_REQUEST" />
    <wait-for-notification description="Wait for notification" characteristic-uuid="cba20003-224d-11e6-9fb8-0002a5d5c51b" service-uuid="cba20d00-224d-11e6-9fb8-0002a5d5c51b" timeout="5000" />
</macro>

お世話になった製品・文献

最後にお世話になった製品・文献を紹介します:

github.com

github.com

テスト技法「同値分割」を信頼していいのかわからなくなった

これまで同値分割を信頼できる手法だと信じてきました。最近になってどうして同値分割が信頼できる方法なのかその理由を私が説明できないことに気づきました。この原因は2つあります:

  1. 同値分割の分割の基準が不明確であること
  2. 後述するいくつかの仮定を満たさない場合、ある同値パーティションの代表値の出力が正しければその同値パーティションの他の値の出力も正しいといえる根拠に乏しいこと

この2つから、不明確な基準の同値分割はその信頼性の説明ができないこと、同値テストは後述するいくつかの仮定が満たされたときのみ有効な手段でありいずれかの仮定が満たされない場合はさして信頼できないことが導かれます。

この記事ではこの結論に至るまでの過程について詳しく説明していきます。なお誤りのご指摘は大歓迎です。ぜひ皆さんで議論しましょう。

続きを読む

私の TDD の理解と Kent Beck による TDD の解説の比較

TDD(テスト駆動開発)の提唱者 Kent Beck による TDD の定義の解説を @t_wada さんが翻訳したブログが公開されました。

t-wada.hatenablog.jp

ここで解説されている TDD と私のこれまで理解していた TDD(後述)を比較します。 みなさんの TDD の理解もぜひ知りたいので自身の思う TDD のプロセスを教えてください。

TL;DR

概ね一致していたようです。細かい差異としては Kent Beck は後述する PFD の「脳内の SUT 仕様(D10)」を生成するアクティビティも TDD に含まれていると主張しているようなので、仕様を分析してテストシナリオを洗いだすアクティビティを D10 の前に追加するとよさそうですね。

私の理解していた TDD

PFD(Process Flow Diagram) で表現します。

PFD

TDD のプロセスの PFD 表現

緑色の成果物はテストが成功する成果物であることを意味し、赤色の成果物はテストが成功しない成果物であることを意味します。

要素表

成果物要素表

アクティビティID アクティビティの説明
A1 脳内のテスト対象(SUT)の仕様から最も実装の容易な入出力の組を選び、これを最初のテストケースとしてテストに追加する。
A2 空のSUTのままテストを実行し失敗することを確認する。これには失敗すべきときに実際にテストが失敗することを確認する意図がある。
A3 D6のテストを成功させる最も単純な実装をSUTに実装する。期待される出力をそのままreturnするので構わない。この作業はFakeItと呼ばれる。テストが成功すべきときに実際に成功することを確認する意図がある。
A4 テストが失敗であればD7へのテストが通るようにテストを修正する。もし修正しなくともテストが成功するようであれば何もしない。
A5 脳内仕様から同値パーティションの代表値や境界値となる入力を選んでテストケースとして実装しテストに追加する。同値パーティションの代表値を入力に選ぶ場合はテストケースの名前に同値パーティションの名前を設定する。境界値を選ぶ場合はその境界値を選んだことがわかるような名前をテストケースの名前として設定する。この時点ではまだSUTを編集してはいけない。
A6 テストを実行する。
A7 テストが成功するまで最も素早く実装できる方法でSUTを編集する。もし最初からテストが成功している場合は何もしない。この時点ではコードの簡潔さを気にしない。
A8 SUTまたはテストのいずれか一方(Xとする)だけを簡潔する。もしテストが失敗する場合はテストが成功するようになるまでXを修正する。これをリファクタリングという。

プロセス要素表

成果物ID 成果物の説明 実行可能なリソース
D0.0 仕様のサンプルである全てのテストケースにおいて実際の出力が期待する出力と一致するテスト対象(SUT)。SUTの実装は簡潔であり保守性が高い。サンプル数が十分であれば仕様を満たしたテスト対象の実装と見なしてよい。 実装者
D0.1 仕様のサンプルである入出力の組のすべてが実際にSUTから得られるか確かめるコード。実装が簡潔であり保守性が高い。もし1つでもSUTからの出力が仕様から期待される出力と異なるならば全体として失敗を返す。そうでなければ全体として成功を返す。 実装者
D1 仕様のサンプルである全てのテストケースにおいて実際の出力が期待する出力と一致するSUT。SUTの実装は簡潔であるとは限らない。サンプル数が十分であれば仕様を満たしたテスト対象の実装と見なしてよい。 実装者
D2 追加されたテストケース以外は成功するテスト。追加されたテストケースだけは成功・失敗のどちらでもよい。 実装者
D3 仕様のサンプルである入出力の組のすべてが実際にSUTから得られるか確かめるコード。テストの実装が簡潔であるとは限らない。もし1つでもSUTからの出力が仕様から期待される出力と異なるならば全体として失敗を返す。そうでなければ全体として成功を返す。 実装者
D4 仕様のサンプルであるテストケースにおいて実際の出力が期待する出力と一致するとは限らないSUT。SUTの実装は簡潔であるとは限らない。 実装者
D5 仕様のサンプルとして選ばれた1つの入出力の組が実際にSUTから得られるか確かめるコード。もしSUTからの出力が仕様から期待される出力と異なるならば全体として失敗を返す。そうでなければ全体として成功を返す。 実装者
D6 仕様のサンプルとして最初に選ばれた入出力の組が実際にSUTから得られるか確かめるコード。もしSUTからの出力が仕様から期待される出力と異なるならば全体として失敗を返す。そうでなければ全体として成功を返すべきだがそうなっているとは限らない。 実装者
D7 仕様のサンプルとして最初に選ばれた入出力の組が実際に帰ってくるSUT。SUTの実装は期待する出力をreturnで返す程度に極めて単純であるべきである。 実装者
D8 何も実装されていないテスト。 実装者
D9 何も実装されていないSUT。 実装者
D10 実装者の脳内にあるこれから実装したいコンポーネントの仕様。テストケースを追加するうちに浮き彫りにできるので明確である必要はこの時点ではない。 実装者

終わりに

みなさんの TDD の理解もぜひ知りたいので自身の思う TDD のプロセスを教えてください!

書評:GitHub Copilot とのペアプロ TDD でつくるローグライク RPG

本記事は「GitHub Copilot とのペアプロ TDD でつくるローグライク RPG」の書評です。題名にローグライクRPGとあるのでゲーム開発の本なのかなと思ってしまいますが、本題は仕様の端的な表現をもたないシステムを LLM を使って真っ当に開発する方法の解説だと思います。タイトルにローグライクRPGと書いていることでゲーム開発に興味のない人の興味を失わせてしまい損をしている気がします。

背景

最近の LLM の流行を受けて私も Chat-GPT や GitHub Copilot といった LLM を開発で利用しています。端的に仕様を表現できるシステムは LLM に質問して実装を得る方が自分で実装するより圧倒的に速く正確であるという感想を抱いています。ただ端的に仕様を表現できるシステムばかりではありません。えてして価値を生んでいるシステムというのは端的な仕様の表現が存在しないものです。最近ではそういう状況で LLM とどう付き合うべきかについて試行錯誤を重ねています。そんなとき @nowsprinting さんから「GitHub Copilot とのペアプロ TDD でつくるローグライク RPG」をいただきました。数多くの同意できる箇所があり、また学びのある良書だと評価しました。TDDやペアプログラミング、GitHub Copilot の説明が本書のおおよそ1/3を占めているのでこれらに馴染みのない方々もお勧めできます。

booth.pm

以下に特に強く同意できる点と学べた点を紹介していきます:

強く同意:LLM にはテストコードではなくプロダクトコードの生成を担当させる

テストコードは堅実に人間が書くことでプロダクトコード(ゲーム本体コード)を保護し、プロダクトコードの実装は Copilot に任せるという役割分担ができます。

── GitHub Copilot とのペアプロ TDD でつくるローグライク RPG

この役割分担(以降で実装担当LLM法と呼びます)は端的な仕様の表現が存在しないシステムにおける LLM との付き合い方の標準形の一部だと思います。

世間ではテストコードの実装とプロダクトコードの実装の立場を逆にした形の付き合い方(=プロダクトコードを人間がかき、そのテストコードを LLM に生成させる方法。以降ではテスト担当LLM法と呼びます)がよく紹介されています。

方法の名前 プロダクトコードの実装担当 テストコードの実装担当
実装担当 LLM 法 LLM 人間
テスト担当 LLM 法 人間 LLM

テスト担当 LLM 法は本書が紹介している実装担当 LLM 法より劣っていると私は考えています。これはテスト担当 LLM 法が仕様の推測というプロセスを含むことが原因です。この説明には仕様における未定義な出力について理解しておく必要があります。

仕様は出力が未定義となる入力をもちえます。たとえば Wikipedia に記載されているいわゆる Fizz Buzz 関数 の仕様は以下のようになっています:

入力 出力
... 未定義
-2 未定義
-1 未定義
0 未定義
1 1
2 2
3 Fizz
4 4
5 Buzz
... ...

このとき FizzBuzz 関数の実装は仕様が出力を定義している入力(ここでは1以上の整数)に対する出力が一致しているとき仕様を満たしたといえます*1。つまりそれを満たしてさえいれば出力が未定義となる入力はどんな出力にしても構わないということです。仮に入力が未定義の出力を持つ入力である 0 のとき FizzBuzz という出力にしても仕様を満たせますし、あるいは例外を発生させても仕様を満たせます。このように仕様には未定義の出力が許されています。その理由は実装者に出力を選ぶ裁量を与えることで実装者にとって都合のよい出力を選べるようにするためです。こうすることにより実装コストの削減が見込めます。さらに実装コストだけでなく保守コストと検証コストも下げられます。なぜなら実装にゆとりがあるほどリファクタリング*2をしやすくなるからです。また出力が未定義の入力は検証をしなくてよいですから検証コストも下げられます。

まとめると仕様は一部の入力に対する振る舞いを未定義にすることが許されています*3

さてテストコードはテスト対象となるプロダクトコードの仕様の一部です。つまりプロダクトコードからテストコードを生成させるプロセスは仕様を別に与えない限り仕様の推測というプロセスを必然的に含みます。そしてプロダクトコードは仕様のどの入力に対する出力が未定義だったかという情報をもっていません。そのため必要以上に未定義にしてしまうあるいは必要以上に定義してしまうことがほとんどでしょう。必要以上に出力を未定義にしてしまえば欠陥を見抜けないテストコードになりますし、必要以上に出力を定義してしまえばリファクタリングするたびに壊れる脆弱なテストコードになります。したがって仕様を推測するプロセスを含むテスト担当 LLM 法は仕様を推測するプロセスのない実装担当 LLM 法より劣っているといえるのです*4

学び: TDD Copilot ペアプロには十分な仕様を書くゲームとしての面白さがある

本書を通じて「プロダクトコードを直接修正するのは最終手段」とされており、そのため LLM へ十分な仕様を与えないと何度も実装を生成する羽目になります。これは人間側の仕様表現ギプスになっているという点がとても面白いと思います。ただし仕様を不必要に定義してしまっていることにはペナルティはないのでこのペナルティが発生するようもう一工夫したいところです。とはいえ仕様表現ギプスとする目的で今度うちの部署でもやってみようかなと思いました。

気づき: 擬似乱数的な振る舞いがほしいときの LLM への指示が難しい

4.2 節ではAssertメソッドの書き方によって仕様として「ランダムであることを匂わせ」ています。これをもっと直接的に仕様として指示できないかと思い property-based testing でその分布が期待したものになっているかを検定する方法を試すことにしました。その単純な例として [0, 100) の区間で正規分布にしたがう擬似乱数生成機を GitHub Copilot と Chat-GPT (GPT4) に生成させてみたところ正規性の検定以前に最頻値の検定で GitHub Copilot と Chat-GPT ともに脱落しました。ただGPT-4 の回答はずるくて面白かったです:

そこで仕様を「与えられたシード値から [0, 100) の区間で正規分布にしたがう値を返す擬似乱数生成機を C# で実装してください」のように自然言語として与えてみたところ、GitHub Copilot Chat と Chat-GPT(GPT4)のいずれも Box-Muller 変換System.Random をもとに正規分布にしたがう関数を出力してくれました。つまり疑似乱数的な振る舞いが欲しいときは C# のテストコードとして仕様を与えるより自然言語で仕様を与えた方が有利なようです。こういう場合は Copilot にお任せではなく Chat-GPT ないしは Copilot Chat に自然言語仕様を与えた方がよいということでしょう。一般化すると端的な仕様の表現が存在する場合はテストの代わりに端的な仕様の表現を与えた方がよい回答が得られるということかもしれません。

気づき: 有限状態機械を生成させるのに1つ1つの状態遷移をC#のテストコードとして記述するより端的な表現を与えたい

5章ではプレイヤーを状態機械として実装させています。そのために1つ1つの状態遷移を個別のテストケースとして実装しています。ただ CSP によるプロセスの記法を学んだ後ではかなり冗長かつ自由度が高すぎる表現に感じます。CSP で仕様を端的に表現したらそれを満たす C# の実装を LLM が出力する未来がはやく来てほしいですね。

終わりに

冒頭にも述べた通り、本書は数多くの同意できる箇所がありまた学びのある良書だと評価しました。TDDやペアプログラミング、GitHub Copilot の説明が本書のおおよそ1/3を占めているのでこれらに馴染みのない方々もお勧めできます。ぜひ LLM を使ったプログラミング入門の教科書として本書を活用してみてはいかがでしょうか。

*1:ここでは部分正当性のみを考えています。

*2:ここではリファクタリングとはある仕様を満たしている実装をその仕様を満たす別の実装へと変えることとしています。一般的には実装の 外観 を変えずに実装を変えることと説明されますがここで 外観 が何を指すかは不明確です。外観 を仕様とした方がより厳密に理解できます。

*3:すべての入力を未定義にしてもいいのですがそんな仕様は有益ではないでしょう。

*4:厳密にはテストコードはサンプルされた仕様でしかないためテストコードを与えるだけでは依然として仕様の推測プロセスが必要になります。 そこでテストケース名に同値パーティションの名前を書くなどしてサンプルされていない値についても手がかりを与えるとこの問題を緩和できるでしょう。

大震災に備えた救急箱に何を入れるべきなのか?

大震災に備え我が家に備えておく救急箱に何を入れるべきか検討した記録です。

TL;DR

以下の用品が災害時に多い傷病に対する応急手当プロセスに必要でかつ救急箱に入るものです。:

品名 数量 製品の例
ゴム手袋 1組 ※男性はサイズ M だと入らないかもしれません。私もMはパツパツでした
サージカルテープ 1本
巻き包帯 1本
感染防護具 1つ
三角巾 9つ*1
清潔なハサミ 1本 ※後述の救急箱上段にギリギリ入りますが窮屈でした
大きなガーゼ 1枚
サムスプリント 2本*2 https://www.yodobashi.com/product-detail/100000001004432395/
滅菌されたガーゼ 1枚
棘ぬき 1本
手指消毒用アルコール 1つ
穴の空いたペットボトルの蓋 1つ

かなり量が多いので次のような大型の救急箱でないと格納しきれません(2024/02/03追記: 紹介している救急箱はポリプロピレン製のため耐候性はありません。暗所に保存してください):

救急箱 ホワイト F-2465

救急箱 ホワイト F-2465

  • カワタキコーポレーション(Kawataki Corporation)
Amazon

救急箱に入らないものの必要な用品に次のものがあります:

品名 数量 製品の例
スマートフォン 1つ -
非常用ブランケット(乾いた毛布で代替可能) 人数分
500mL 飲料水ペットボトル 1本
日本全国AEDマップ 1つ aedm.jp
担架 1つ(身長より長い物干し竿と毛布で代替可能)

上記のリストを満足する既製の救急用品セットは見つかりませんでした。個別に購入するのが面倒に感じた場合は上記の6割弱があらかじめ格納された次の救急用品セットを買うのでも買わないよりはマシだと思います:

これらの用品の使い方は各自治体の開催する上級救命講習で教われます。用品を備えるだけでは使い方がわからないので上級救命講習の受講も併せて検討するとよいでしょう。受講の時間が取れない方は 応急手当Web講習 - 総務省 を見るとよいでしょう。

なお上記のリストはあくまで無資格・無免許の一般市民が検討したものとご承知ください。信頼性の評価を第三者ができるように以下にこのリストの作成手法を説明します。

背景

著名な防災用品のチェックリスト*3*4は救急箱や救急セットを備えておくよう指示しています。しかしその中身への言及はごく僅かで何を用意しておけばいいのかわかりません。

過去には労働安全衛生規則が事業場に一律で備えるべき救急用具を規定していましたが、事業場ごとに負傷や疾病の発生状況が異なることから令和3年末にその規定は削除されました*5

「救急箱 中身」で検索したトップヒットは 2006 年の総合南東北病院による「家庭用救急箱には何を用意すればいいのか?」でした。ただこれをみても (1) どの怪我に何を使うのかわからない、(2) 災害時の怪我に対応しきれるかわからない、という問題があります。その他ヒットしたWebサイトをみても同様の問題がありました。

そこでこの記事では災害時に多い怪我に対応できる応急手当のプロセスとそれを実現できる災害用救急箱の中身を検討します。なお私は医師免許、防災士のいずれの免許及び資格を所持していません。そのためここでの検討はあくまで無資格・無免許の一般市民によるものとご承知ください。

手法

次の7ステップで応急手当プロセスと災害用救急箱の中身を検討しました:

  1. 災害時に多い傷病を調べる
  2. それぞれに対応する応急手当プロセスを調べる
  3. 応急手当プロセスの初期成果物を洗い出す
  4. その他の目的の救急セットと比較し不足やよりよい代替品を洗い出す
  5. 3 と 4 をまとめて重複を取り除きつつ抽象的なものは具体的なものへと置き換える
  6. 災害時に使えなくなる成果物を代替する
  7. 救急箱に入るものと入らないものを分ける

STEP1. 災害時に多い傷病を調べる

行政によると地震による傷病の支配的な原因は家具類の転倒・落下・移動によるものだそうです:

地震のケガの原因の約30%~50%が、家具類の転倒・落下・移動によるものでした。

出典: 地震時の危険 - 東京消防庁

それ以外の原因についても調べてみました。阪神淡路大震災による怪我の内訳は次の通りのようです:

内部被害による怪我の原因

出典: 約6割の部屋で家具が転倒、散乱した - 消防庁

東日本大震災について死因は溺死が 90% を占めています*6

記憶に新しい能登半島地震では次の通りでした:

死因で最も多かったのは、倒壊した建物の下敷きになったことなどによる「圧死」で、全体の41%にあたる92人、次いで、「窒息」や「呼吸不全」が49人(22%)でした。 さらに「低体温症」や「凍死」が32人(14%)にのぼり、真冬に起きた災害で、多くの人が救助を待つなどする間、寒さによって体力を奪われ、亡くなったとみられる実態が浮き彫りになりました。

出典: 能登半島地震の死因「圧死」92人「低体温症」や「凍死」32人 警察庁 専門家“過去の災害より多い印象 - NHK

これらをまとめると災害時に考慮すべき傷病の原因は以下の6つです:

  • 家具類の転倒・落下・移動
  • ガラス
  • 家屋の倒壊
  • 火災
  • 溺水
  • 低温

傷病の原因それぞれから発生しうる傷病を次のように推測しました:

原因 傷病
家具類の転倒・落下・移動 窒息
家具類の転倒・落下・移動 骨折・ひび
家具類の転倒・落下・移動 打撲
家具類の転倒・落下・移動 切裂傷
家具類の転倒・落下・移動 捻挫・脱臼
家具類の転倒・落下・移動 熱傷
ガラス 切裂傷
家屋の倒壊 窒息
家屋の倒壊 骨折・ひび
家屋の倒壊 打撲
家屋の倒壊 切裂傷
家屋の倒壊 捻挫・脱臼
火災 熱傷
溺水 窒息
低温 低体温症

これをまとめると対処したい傷病は次の7つです:

  • 窒息
  • 骨折・ひび
  • 打撲
  • 切裂傷
  • 捻挫・脱臼
  • 熱傷
  • 低体温症

STEP2. それぞれに対応する応急手当プロセスを調べる

STEP1 で洗い出された傷病のそれぞれについて、救急隊または医療機関に引き継ぐまでに必要な手当(広義の応急手当)のプロセスを調べました。

応急手当のプロセスは「上級救命講習テキスト」(東京防災救急協会 版)をもとに PFD (Process Flow Diagram) で表現しました。上級救命講習テキストは各自治体が開催している上級救命講習のうち東京都が開催しているもののテキストです。上級救命講習とは成人・小児・乳児の心肺蘇生やAED、異物除去、止血法、傷病者管理、外傷の応急手当、搬送法などを学べる講習です(東京都の例)。つまりこのテキストに登場する救急用品の使用方法は上級救命講習を受講すると理解できると期待できます。

また表現方法として PFD を選んだ理由は、自然言語やフローチャートで表現されたプロセスは成果物を見落としやすいのに対して PFD では成果物が明示され成果物の不足を発見しやすいためです。成果物の不足はすべてのプロセスについて入力成果物から出力成果物を生成できるかを確認すると見抜けることが多いです。

ただ PFD は条件分岐の表現が苦手です。そのため今回は条件分岐を表現できる拡張を施した CPFD (Conditional PFD) を使いました。CPFD はオリジナルの PFD に条件分岐プロセスを追加した PFD の拡張です。CPFD に含まれるすべての条件分岐ノードへ値を割り当てるとその条件下の PFD を出力します。CPFD の初期成果物は生成されうるすべての PFD の初期成果物の合併になります。つまり震災時に発生しうる傷病それぞれの応急手当の CPFD の初期成果物の合併が救急箱に備えておくべき用品となります。

窒息の応急手当プロセス

心肺蘇生プロセス

骨折・ひびの応急手当プロセス

骨折の応急手当プロセス

打撲の応急手当プロセス

上級救命講習テキストには打撲の応急手当プロセスの記述はありませんでした。そこで愛媛大学総合健康センターによる応急手当プロセス*7で代替しました:

打撲・捻挫の応急手当プロセス

切裂傷の応急手当プロセス

直接圧迫止血法のプロセス

外傷の応急手当プロセス

破線の成果物は上級救命講習テキストにはないものの手当に必要となるであろうと補完した用品です。

捻挫・脱臼の応急手当プロセス

上級救命講習テキストには捻挫・脱臼の応急手当プロセスの記述はありませんでした。そこで愛媛大学総合健康センターによる応急手当プロセス*8で代替しました:

打撲・捻挫の応急手当プロセス

熱傷の応急手当プロセス

熱傷の応急手当プロセス

破線の成果物は上級救命講習テキストにはないものの手当に必要となるであろうと補完した用品です。

低体温症の応急手当プロセス

低体温症の応急手当プロセス

STEP 3. 応急手当プロセスの初期成果物を洗い出す

これらの CPFD の初期成果物の一覧を以下に示します:

プロセス 傷病 初期成果物名 備考
心肺蘇生 心肺停止 傷病者
心肺蘇生 心肺停止 不安全かもしれない環境
心肺蘇生 心肺停止 搬送手段
心肺蘇生 心肺停止 119番通報の手段
心肺蘇生 心肺停止 日本全国AEDマップ
心肺蘇生 心肺停止 感染防護具
直接圧迫止血法 大出血 大出血している人
直接圧迫止血法 大出血 大きなガーゼ タオルでもよい
直接圧迫止血法 大出血 ゴム手袋 ビニール袋でもよい
外傷の応急手当 外傷 出血している人
外傷の応急手当 外傷 水道水
外傷の応急手当 外傷 滅菌されたガーゼ 滅菌された三角巾でもよい
外傷の応急手当 外傷 巻き包帯 ネット包帯または三角巾でもよい
外傷の応急手当 外傷 清潔なハサミ ガーゼを切るときに使う
外傷の応急手当 外傷 サージカルテープ ガーゼの固定に使う
外傷の応急手当 外傷 ゴム手袋 ガーゼの処置に使う
骨折の応急手当 骨折 骨折の疑われる人
骨折の応急手当 骨折 副子 身長の半分のもの2つ
骨折の応急手当 骨折 三角巾 9つ
熱傷の応急手当 熱傷 熱傷
熱傷の応急手当 熱傷 清潔な流水
熱傷の応急手当 熱傷 清潔なガーゼ 三角巾や清潔なタオル、シーツでもよい
熱傷の応急手当 熱傷 清潔なハサミ ガーゼを切るときに使う
熱傷の応急手当 熱傷 サージカルテープ ガーゼの固定に使う
熱傷の応急手当 熱傷 ゴム手袋 ガーゼの処置に使う
打撲・捻挫の応急手当 打撲 打撲または捻挫した人
打撲・捻挫の応急手当 打撲 氷水など
打撲・捻挫の応急手当 捻挫 打撲または捻挫した人
打撲・捻挫の応急手当 捻挫 氷水など
低体温症の応急手当 低体温症 乾いた衣服や毛布
低体温症の応急手当 低体温症 搬送手段
低体温症の応急手当 低体温症 低体温症の疑われる人

STEP4. その他の目的の救急セットと比較して不足やよりよい代替品を洗い出す

経験的に登山用、軍用およびライフセーバーの救急セットには収納容積が小さく効率的な用品が入っていることが多いためそれらを調べ不足や代替品を洗い出しました。

登山用の救急セット

【現役ガイド直伝】 登山初級者でも安心「実用的ファーストエイドキット」を大公開! - YAMA HACK持たない理由がない!非常時以外でも使えるエマージェンシーシートの実力が侮れない・・・ - YAMAHACK を参考に STEP5 の内容に加えて以下の4+1用品が洗い出されました:

  • 棘ぬき
  • サムスプリント(副子の一種)
  • 手指消毒用アルコール
  • 穴の空いたペットボトルの蓋
  • 非常用ブランケット

軍用の救急セット

米軍の応急処置キットIFAK - ミリタリーショップレプマート を参考に STEP5 の内容に加えて以下の用品が洗い出されましたが、それぞれに付記した理由で代替品とは見做しませんでした:

  • CAT ターニケット(止血帯)
    • 上級救命講習によれば訓練されていないバイスタンダーに止血帯法は推奨されていません。そのため代替品から取り除きました
  • 経鼻エアウェイ
    • 上級救命講習では気道確保の手法として頭部後屈あご先挙上法が指示されています。また 経鼻エアウェイの挿入 - MSDマニュアル を読む限り非医療従事者が扱えるものとは思えませんでした。そのため代替品から取り除きました

ライフセーバーの救急セット

ライフセーバーの用品として CPR ボードがあるようです。これは気道確保と胸骨圧迫をやりやすくするためのものです。

STEP5. STEP3, 4 の成果物をまとめて重複を取り除きつつ抽象的なものは具体的なものへと置き換える

STEP3, 4 の成果物をまとめて重複を取り除き、抽象的なものは具体的なものへと置き換えました:

品名 まとめた品名または具体化した品名
ゴム手袋
サージカルテープ
巻き包帯
感染防護具
三角巾
清潔なハサミ
大きなガーゼ
サムスプリント 副子
滅菌されたガーゼ 清潔なガーゼ
棘ぬき
手指消毒用アルコール
スマートフォン 119番通報の手段
乾いた衣服や毛布
非常用ブランケット
清潔な流水 水道水
日本全国AEDマップ
担架 搬送手段
氷水

STEP6. 災害時に使えなくなる成果物を代替する

災害時は断水および停電になりうるため、それによって使用できなくなりうる品を代替品に取り替えました:

品名 断水・停電時に使えなくなる品名
ゴム手袋
サージカルテープ
巻き包帯
感染防護具
三角巾
清潔なハサミ
大きなガーゼ
サムスプリント
滅菌されたガーゼ
棘ぬき
手指消毒用アルコール
119番通報の手段
乾いた衣服や毛布
非常用ブランケット
500mL 飲料水ペットボトル*9 清潔な流水, 氷水
穴の空いたペットボトルの蓋 清潔な流水, 氷水
日本全国AEDマップ
担架

STEP7. 救急箱に入るものと入らないものを分ける

次の大きめの救急箱を目安に救急箱に入るものと入らないものを分けました。数量は CPFD の備考をもとにしています:

救急箱 ホワイト F-2465

救急箱 ホワイト F-2465

  • カワタキコーポレーション(Kawataki Corporation)
Amazon

品名 救急箱に入れられる 数量
ゴム手袋 o 1組
サージカルテープ o 1本
巻き包帯 o 1本
感染防護具 o 1つ
三角巾 o 9つ
清潔なハサミ o 1本
大きなガーゼ o 1枚
サムスプリント o 2本
滅菌されたガーゼ o 1枚
棘ぬき o 1本
手指消毒用アルコール o 1つ
穴の空いたペットボトルの蓋 o 1つ
スマートフォン x 1つ
乾いた衣服や毛布 x 人数分
非常用ブランケット x 人数分
500mL 飲料水ペットボトル x 1本
日本全国AEDマップ x 1つ
担架 x 1つ

こうして冒頭の救急用品のリストが出来上がりました。またその救急用品をどのように使うかを明らかにできました。

おわりに

これらの用品の使い方は各自治体の開催する上級救命講習で教われます。用品を備えるだけでは使い方がわからなくていざという時に困ります。上級救命講習の受講も併せて検討するとよいでしょう。上級救命講習の申し込み方法についてはお住まいの各自治体にお問い合わせください。実習の時間を捻出できない方は 応急手当Web講習 - 総務省 を見るとよいでしょう。

またそもそも家具の転倒や家屋の倒壊、火災を予防するための準備が有効であることはいうまでもありません。家具の固定、家屋の耐震補強、消火器の設置、感震ブレーカーの設置を進めていきましょう。

新築住宅に1年住んでわかった後悔ポイントとおすすめ設備

新築住宅に住み始めてから1年経過しました。この1年を振り返ってよかったポイントや後悔ポイント、おすすめ設備を紹介します。

  • よかったポイント
  • 後悔ポイント
    • トイレの照明スイッチの位置がドアに向かって左右逆だった
      • 問題
      • 有効そうな予防策
      • 対応策
    • トイレの照明を人感センサーにし忘れた
      • 問題
      • 有効そうな予防策
      • 次善の対応策
        • 追記(2024/01/09)
    • トイレのタンクを断水時用に貯水タンク付きにしたつもりが付いてないかもしれない
      • 問題
      • 有効そうな予防策
      • 次善の対応策
    • 予定外に常設のテレビを設置することになり準備ができていなかった
      • 問題
      • 有効そうな予防策
      • 次善の対応策
    • リビング階段にカーテンレールつける準備ができていなかった
      • 問題
      • 有効そうな予防策
      • 次善の対応策
    • 蓄電池の容量が少なかった
      • 問題
      • 有効そうな予防策
      • 次善の対応策
    • エコキュートが昼間に沸き上げしてくれない
      • 問題
      • 有効そうな予防策
      • 次善の対応策
    • 階段上出口にオートロック付きのベビーゲートを置く空間がなかった
      • 問題
      • 有効そうな予防策
      • 次善の対応策
  • おすすめ設備
    • スマート分電盤
    • 階段下収納の小ドア
    • お手入れが楽な TOTO のラクラクスマート水栓
    • 洗面台裏のランドリーコーナー
    • 水量が多い水道直圧式のエコキュート
    • 玄関の電動アシスト自転車のバッテリー充電用コンセント
    • 鏡なしカウンターなしのユニットバス
    • プライバシー保護に優れそれでいて明るいレースカーテン
    • 広いキッチン
    • リビング扉と玄関扉の窓
  • 終わりに
続きを読む