GHSの中身「ACOM」とは?【測定値を1つのObservationで表す仕組み】

bluetooth

こんな悩みはありませんか?

前回の記事で、GHSは 「測定値の意味(ACOM)」と「運び方(GATT)」を分離し、種別の違いは MDCコードで表す——という話をしました。

でも、こう思いませんでしたか。

ACOMって、結局どんなデータの形をしているの?

今回はそこを開けます。結論から言うと、ACOMの正体は 「Observation(オブザベーション)」という1つの箱です。血圧も体温もSpO₂も、すべてこの同じ箱に入ります。

この記事を読めば、次の3つがクリアになります。

  1. ACOMの中心にある Observation が何を表すオブジェクトなのか
  2. その中に何が入っているのか(実データ例と、GATTを流れる実際のバイト列で確認)
  3. なぜ同じ箱で、あらゆるセンサー種別を表せるのか

GHSの全体像がまだの方は、先に 医療センサーBLEの新規格「GHS」とは? を読むとスムーズです。


ACOMとは何か

ACOM(abstract and generic information content model)は、IEEE 11073-10206 が定義する「測定値の意味を表す抽象モデル」です。日本語にすると「抽象的で汎用的な、情報内容のモデル」。要するに、“測定値をどう表すか”の共通ルールです。

出自も押さえておくと理解が深まります。ACOMは、従来のパーソナルヘルスデバイス標準 IEEE 11073-20601 のモデルを簡素化・更新した版です。つまりまったくの新顔ではなく、PHD(Personal Health Device)標準の系譜に連なるものです。

GHSがやっているのは、この ACOM を BLE の GATT に載せて運ぶこと。だからこそ、まず ACOM の形を知ることが、GHS理解の近道になります。


ACOMの主役は「Observation」

ACOMの中心にあるオブジェクトが Observation です。ひとことで言えば、「1回の測定を表す箱」

血圧を測っても、体温を測っても、SpO₂を測っても、出てくるのはすべて「Observation」という同じ器です。そして、その箱の中の「これは何の測定か」を決めるのが、前回登場した MDCコード(IEEE 11073-10101) です。

ACOMのクラス図(UML)では、Observationは基底クラスとして、type(何の測定か=MDCコード)、time-stamp(時刻)、id(接続中の一意ID)、derived-fromhas-member(他の測定との関連)といった共通の属性を持つものとして定義されています。

図1:Observationは「何の測定か(type=MDCコード)」「値(value)」「単位(unit)」「時刻(time-stamp)」などをひとまとめにした箱(ACOM基底クラスの主な属性)。

Observationの中身を、実データで見る

抽象的な説明だけだとピンとこないので、パルスオキシメータのSpO₂測定を例に、Observationのフィールドに何が入るかを見てみます(Bluetooth SIGの実装ガイドの例より)。

Observationのフィールド意味実例(SpO₂測定)
Class Typeどの型の測定かNumeric(数値)
Type測定の種類(MDCコード)MDC_PULS_OXIM_SAT_O2(code 150456)
Unit単位(MDCコード)MDC_DIM_PERCENT(%)
Value測定値89.0
Time Stamp測定時刻2017-09-04 16:30:00 +1:00

ここで大事なのは、「89.0」という数字だけでは、医療データとして意味をなさないということです。

  • それが SpO₂の値であること(Type)
  • 単位が であること(Unit)
  • いつ測ったのか(Time Stamp)

これらが揃って、初めて「2017年9月4日16時30分、SpO₂ 89.0%」という意味のあるデータになります。ACOMは、この“意味の同梱”を標準化しているわけです。

ちなみに、この「MDCコード」はACOMのモデル上 Term という型で表され、partition(区分)と term-code(コード)という2つの数値でできています。SpO₂の 2::19384 は、partition=2/term-code=19384 という意味です(上の表にあった 150456 は、この2つを1つの数値にまとめた表記で、2 × 65536 + 19384 の値です)。Observationの「何の測定か(type)」も「単位(unit)」も、同じ Term で表されます。

Observationはこのほかにも、測定ステータス・患者/ユーザID・補足情報・参照といったフィールドを持ちますが、まずは「値だけでなく意味がセットで入る箱」というイメージを掴めば十分です。


実物チラ見せ:GATTを流れるObservationのバイト列

ここまで見てきたObservationは、GATT上では実際に1本のバイト列として流れます。全フィールドの詳しい解読はここではしません(それは次回のテーマです)。まずは 「こういうものだ」と目で見るのが目的です。

構造は大きく、「1オクテットの Segmentation Header」+「Health Observation Body」 に分かれます。

図2:先頭にSegmentation Headerが付き、その後ろにObservation本体のフィールドが並ぶ。

Segmentation Header(1オクテット)

ビットフィールド意味
0First Segment最初のセグメントか
1Last Segment最後のセグメントか
2–7Rolling Segment Counterセグメント番号(0〜63でロールオーバー)

なぜ「セグメント」なのか。1回のNotify/Indicationで送れるサイズ(ATT MTU)には上限があるため、長い測定値はそこに収まりません。そこでGHSは、Observationを複数のセグメントに分割して送り、各セグメントの先頭にこのヘッダを付けます。受信側は First / Last / カウンタを見て、分割されたデータを元通りに組み立てます。

Health Observation Body(本体)

ヘッダの後ろに、Observation本体のフィールドが次の順で並びます。

フィールドサイズ(オクテット)要否
Observation Class Type1必須
Length2必須
Flags2必須
Observation Type(=MDCコード)4任意
Time Stamp9任意
Measurement Duration4任意
Measurement Status2任意
Observation Id4任意
Patient1任意
Supplemental Information可変任意
Derived From可変任意
Is Member Of可変任意
TLVs可変任意
Observation Value可変必須

注目してほしいのは、さっき表で見た抽象フィールド(Class Type、Type=MDCコード、Time Stamp、Value…)が、そのまま実バイトのフィールドとして並んでいることです。どの「任意」フィールドを含むかは、先頭近くの Flags が決めます。

ビット単位の意味やエンコード規則にはここでは踏み込みませんが、「抽象モデルのObservationが、実際にはこういう生データになる」という感覚さえ持ち帰れれば、この節は十分です。


Observationには8つの型(Class Type)がある

SpO₂のような単純な数値だけでなく、状態・文字列・波形なども、同じObservationの枠組みで表せます。ACOMの実装ガイドのクラス図(UML)では、これらは Observation を親とするサブクラスとして整理されていて、たとえば数値は NumericObservationunit: Termvalue: FLOAT を持つ)、波形は SampleArrayObservation という具合です。型は全部で次の8つです。

#Observation Class Type用途の例
1NumericSpO₂・体温などの単一数値
2Simple discrete状態コードなど
3String文字列
4Sample array波形(ECGなど)
5Compound discrete event複合イベント
6Compound state/event複合状態
7Compound複数値を1測定に(例:血圧=収縮期/拡張期/平均)
8TLV-encodedTLV符号化

入門としては、基本は「1 Numeric」と覚えておけば十分です。血圧のように複数の値を1回の測定にまとめたいときは「7 Compound」を使う、という程度を押さえておきましょう。


なぜ同じ箱で、あらゆる種別を表せるのか

ここまで来ると、前回の「答え合わせ」ができます。

種別ごとに変わるのは、Typeに入るMDCコードと、Valueの中身だけ。Observationという箱の構造そのものは共通です。

図3:箱は共通。「何の測定か」はMDCコードの差し替えで表現する。

だからこそ、デバイス種別が増えてもデータの表し方を作り直す必要がない。前回お伝えした「GHSは通信を共通化する」の正体は、この共通の箱=Observationにあったわけです。


ACOMのその先:2つの出口

最後に、Observationがこの先どこへ向かうかを押さえておきます。出口は2つあります。

  • BLEに載せる出口:先ほど見たように、ObservationはSegmentation Header+Bodyのバイト列としてGATTを流れます。そのビット単位の詳細が、次回のテーマです。
  • 電子カルテに載せる出口:ACOM Observationは、医療データ標準の FHIR Observation に素直に変換できます。TypeはFHIRのcodeに、ValueはvalueQuantityに……という形で、フィールドがほぼ1対1で対応します。

つまりObservationは、BLEでもカルテでも通用する共通の器として設計されている、というわけです。


まとめ

3行でまとめます。

  1. ACOMの中心は Observation=1回の測定を「Type(MDCコード)+Value+単位+時刻…」でひとまとめにする共通の箱
  2. GATT上では Segmentation Header + Body のバイト列として流れ、長い測定値は分割して送られる
  3. 種別で変わるのは中身(MDCコードと値)だけ。箱は共通だから種別追加に強く、FHIRにも素直に乗る

「値だけでなく意味がセットで運ばれる」——この設計が、GHSが種別に縛られず、かつ医療システムと繋がれる理由です。


参考(一次資料)

  • Bluetooth SIG『Generic Health Sensor Service(GHSS)』v1.0 §3.2 Live Health Observations(Segmentation Header / Health Observation Body)
  • Bluetooth SIG『Generic Health Sensor Design and Implementation Guide』v2(Appendix A: ACOM UMLモデル/§8 FHIRマッピング)
  • IEEE 11073-10206(ACOM)/ IEEE 11073-10101(MDC nomenclature)/ IEEE 11073-20601(PHD)
  • HL7 FHIR / FHIR PHD Implementation Guide(R4)

この記事はBluetooth SIGの公開仕様・実装ガイド、およびIEEE/HL7の公開情報をもとに構成しています。

コメント

タイトルとURLをコピーしました