2018年5月24日木曜日

pgAdminとWiresharkを用いたORCA,OpenDolphinの閲覧

今回は、スマートフォンアプリケーションを作っていく中で必要なデータを取得するテーブルがORCA,Opendolphinのどこに格納されているのかを、データベースマネジメントシステムPostgreSQLのGUIクライアントツールであるpgAdminを用いて確認をした。

pgAdminをインストール後、Serverの登録を行っていく。

図1:pgAdminの起動画面
図1のような過程でサーバーの設定画面へ行く。
左のタブから「server」を選択し、右クリック>Create>Server...をクリックする。
図2:サーバ名の入力

図3:IPアドレス・ポート番号の入力
すると、サーバー設定のポップアップが表示されるので、図2、図3のようにサーバーの設定を行った。
ORCAが使用するデータベースはLinuxサーバ上にインストールされているので、ポート番号にはPostgreSQLの標準ポート番号である5432を入力する。
一方、OpenDolphinが使用するデータベースはDocker上で動いているので、コンテナが外部に公開しているPostgreSQLのポート番号である32768を入力することに注意する。
サーバー設定が完了すると左タブのSeverに設定した名前(今回はORCAとOpenDolphin)が表示されるのでデータベースが含まれるテーブルの確認を行う。なお、テーブルデータが格納されている場所はServer>サーバーの名前>データベース>データベース名>スキーマ>パブリック>テーブルで確認することができる。
図4.pgAdminのブラウザ(左側)

図5:ORCAの患者テーブル(tbl_ptinf)

図6:OpenDolphiのd_moduleテーブル
そして、閲覧したいテーブル上で右クリック>View/Edit Data>All Rowsでテーブル内のデータを閲覧することができる。
図5、図6は実際にデータベースの閲覧を行った図である。
図5はORCAのデータベースにある患者情報テーブル(tbl_ptinf)の中身である。なお、ORCAのテーブル定義書は公開されている。
一方、図6はOpenDolphinのデータベースにあるオーダ情報などが格納されているテーブル(d_module)の中身である。残念ながら、OpenDolphinのデータベーステーブル定義書は公開されていないようなので、pgAdmin等のDBクライアントツールでテーブルスキーマを確認するしかない。

次に、OpenDolphinクライアントがサーバとの間でどのようなデータをやり取りしているか確認するために、パケットキャプチャツールWiresharkを用いて通信データ内容をキャプチャした。
図7:Wiresharkの画面(キャプチャフィルタの設定)
図7のようにキャプチャフィルタに「host 172.16.108.251」を設定してパケットキャプチャした。ここで、172.16.108.251はOpenDolphinサーバのIPアドレスである。
手順としては、まずあらかじめOpenDolphinを起動しておき、患者のカルテを開く手前の状態にしておく。次にWirasharkでパケットキャプチャを行い、パケットのやり取りを確認した。それが以下の図8である。
図8:パケット一覧

そして、protocolが「HTTP」infoが「GET...」から始まるパケットを探し、右クリックのメニューから「HTTPストリーム」を実行することで、キャプチャしたパケットの詳細な内容を確認することができる。尚、HTTPストリームを行った際に該当したパケットが表示されない場合は、別のパケットに格納されている可能性があるので、順次上記の条件で始まるパケットを確認していく必要がある。
図9.ログイン時のメッセージのやり取り


上記の図9がHTTPストリームを行った後に表示される通信内容である。右下の「show and save data as」の項目を「UTF-8形式」に変更することで、パケットの内容が日本語で表示されるようになる。
ここで、HTTPヘッダ(図9の赤文字で示されている部分)を確認すると、1行目はGET~から表示されているURLを指定し、2行目では、json形式で表示するように要求をしている。そして、4行目では認証のためのパスワードのハッシュ(MD5)を、5行目ではログインユーザIDを指定している(ユーザIDは医療機関コード:ユーザIDという形式になっていることがわかる)。
このようなAPIをRESTful APIという。OpenDolphinはRESTful APIをサポートしており、任意のクライアントから所定のRESTful APIを用いてデータを取得(あるいは追加・更新・削除)ができるようになっている。そのため、クライアントは直接データベースにアクセスすることなくデータを取得できる。
GET /dolphin/openSource/user/1.3.6.1.4.1.9414.70.1:mtanaka HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: 5f4dcc3b5aa765d61d8327deb882cf99
userName: 1.3.6.1.4.1.9414.70.1:mtanaka
Host: 172.16.108.251:8080
Connection: Keep-Alive
json形式とは、JavaScript Object Notationの略で、JavaScriptでオブジェクトを記述する書式である。下記はサーバからのレスポンスで、ボディ部にはJSON形式でサーバからデータが送られてきていることがわかる。JSON形式のデータは、全体を"{}"でくくり、キーと値を「"キー名":"値"」の形式で表記する。そして、この"キー":"値"ペアを","(カンマ)で区切って表記する。また、データは階層的に記述することができる。例えば下記の例では、facilityModelという項目の中がさらに{}で括られたオブジェクトになっており、その中にfacilityIdやfacilityNameといった要素が入っている。
HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 833
Date: Fri, 25 May 2018 02:42:01 GMT

{
  "userId": "1.3.6.1.4.1.9414.70.1:mtanaka",
  "facilityModel": {
    "facilityId": "1.3.6.1.4.1.9414.70.1",
    "facilityName": "クリニック",
    "zipCode": "",
    "telephone": "",
    "facsimile": null,
    "s3URL": null,
    "s3AccessKey": null,
    "s3SecretKey": null,
    "memberType": "FACILITY_USER",
    "registeredDate": "2018-05-10",
    "url": "",
    "address": "",
    "id": 1
  },
  "sirName": "中田",
  "givenName": "太郎",
  "commonName": "中田 太郎",
  "departmentModel": {
    "departmentCodeSys": "MML0028",
    "departmentDesc": "内科",
    "department": "01"
  },
  "memo": null,
  "email": "nakata@dolphin.jp",
  "orcaId": "10006",
  "useDrugId": "",
  "memberType": "FACILITY_USER",
  "registeredDate": "2018-05-17",
  "licenseModel": {
    "licenseDesc": "医師",
    "licenseCodeSys": "MML0026",
    "license": "doctor"
  },
  "roles": [
    {
      "userId": "1.3.6.1.4.1.9414.70.1:mtanaka",
      "role": "user",
      "id": 11
    }
  ],
  "password": "5f4dcc3b5aa765d61d8327deb882cf99",
  "id": 10
}
先に見たようにOpenDolphinのRESTful APIはHTTPリクエストヘッダに認証用のパスワードとユーザIDを設定している。したがって、ブラウザのアドレスにURLだけ入力してもエラーになるだけである(図10)。

図10 :ブラウザからURLを入力した場合はエラーになる
同様にして、OpenDolphinのクライアント-サーバ間の通信をパケットキャプチャすることでJSON形式の通信内容を取得できる。それを解析すれば独自にスマホアプリを開発できる。
例えば、以下は検査データのパケットをキャプチャしたものである。
{
  "list": [
    {
      "progressState": null,
      "items": [
        {
          "laboCode": null,
          "lipemia": null,
          "hemolysis": null,
          "dialysis": null,
          "reportStatus": "E",
          "groupCode": "01",
          "groupName": "生化学的検査",
          "parentCode": "0001",
          "medisCode": "3J010000002327101",
          "itemName": "総ビリルビン",
          "abnormalFlg": null,
          "normalValue": "0.2-1.2",
          "specimenCode": "023",
          "specimenName": "血清",
          "commentCode1": null,
          "comment1": null,
          "commentCode2": null,
          "comment2": null,
          "sortKey": null,
          "itemCode": "0001",
          "sampleDate": "2018-05-02 00:00",
          "patientId": "1.3.6.1.4.1.9414.70.1:00004",
          "unit": "mg/dL",
          "value": "0.811980324",
          "id": 2079
        },
        {
          "laboCode": null,
          "lipemia": null,
          "hemolysis": null,
          "dialysis": null,
          "reportStatus": "E",
          "groupCode": "01",
          "groupName": "生化学的検査",
          "parentCode": "0002",
          "medisCode": "3J015000002327101",
          "itemName": "直接ビリルビン",
          "abnormalFlg": null,
          "normalValue": "0.0-0.4",
          "specimenCode": "023",
          "specimenName": "血清",
          "commentCode1": null,
          "comment1": null,
          "commentCode2": null,
          "comment2": null,
          "sortKey": null,
          "itemCode": "0002",
          "sampleDate": "2018-05-02 00:00",
          "patientId": "1.3.6.1.4.1.9414.70.1:00004",
          "unit": "mg/dL",
          "value": "0.305672831",
          "id": 2080
        },
        ・・・・(中略)・・・・
      ],
      "sampleDate": "2018-04-28 00:00",
      "laboCenterCode": "LSCC",
      "moduleKey": "LSCC2018042842011",
      "reportFormat": null,
      "patientName": "佐山 清二",
      "patientSex": "M",
      "numOfItems": null,
      "patientId": "1.3.6.1.4.1.9414.70.1:00004",
      "id": 1153
    }
  ]
}
groupName:"生化学検査”,parentCode":"0001"…といったように、それぞれ対応したテーブルと、それに該当するデータがパケットとして送信されていることがわかる。このパケットからデータを取得することで、OpenDolphin上でデータの表示をすることができるのだということが分かった。
今回は確認が容易である検査データのパケットキャプチャを行ったが、pgAdmin上で確認できなかった所見欄のデータも同じように確認することができるであろう。
各データの格納場所と、取得方法に関する大まかな検討はつけることができたので、
次回はスマホアプリケーションの開発に挑戦していこうと思う。

【TIPS】

以下にOpenDolphinのいくつかの通信をキャプチャしたものを示す。

受付リスト

これはログイン後、受付リスト(図11)が表示されるときの通信内容をキャプチャしたものである。
図11.受付リスト
GET /dolphin/openSource/pvt2/pvtList HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: 5f4dcc3b5aa765d61d8327deb882cf99
userName: 1.3.6.1.4.1.9414.70.1:mtanaka
Host: 172.16.108.251:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 2346
Date: Fri, 25 May 2018 02:47:17 GMT

{
  "list": [
    {
      "memo": null,
      "facilityId": "1.3.6.1.4.1.9414.70.1",
      "patientModel": {
        "romanName": null,
        "nationality": null,
        "nationalityDesc": null,
        "maritalStatus": null,
        "jpegPhoto": null,
        "mobilePhone": null,
        "relations": null,
        "reserve1": null,
        "reserve2": null,
        "reserve3": null,
        "reserve4": null,
        "reserve5": null,
        "reserve6": null,
        "memo": null,
        "email": null,
        "facilityId": "1.3.6.1.4.1.9414.70.1",
        "telephone": null,
        "patientId": "00004",
        "healthInsurances": [
          {
            "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTYxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUFZUSGVhbHRoSW5zdXJhbmNlTW9kZWwiPgogIDx2b2lkIHByb3BlcnR5PSJHVUlEIj4KICAgPHN0cmluZz41Yjk0NWIyZi01Mzg4LTQ0ODMtYjlhYS0wOTdkMDJhZDk1MmE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudEdyb3VwIj4KICAgPHN0cmluZz7vvJLvvJDvvJDvvJA8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudE51bWJlciI+CiAgIDxzdHJpbmc+77yW77yY77yV77yTPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJleHBpcmVkRGF0ZSI+CiAgIDxzdHJpbmc+OTk5OS0xMi0zMTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iZmFtaWx5Q2xhc3MiPgogICA8c3RyaW5nPmZhbHNlPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzcyI+CiAgIDxzdHJpbmc+57WE5ZCIPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzc0NvZGUiPgogICA8c3RyaW5nPjA2PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzc0NvZGVTeXMiPgogICA8c3RyaW5nPk1NTDAwMzE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Imluc3VyYW5jZU51bWJlciI+CiAgIDxzdHJpbmc+MDYzMzAwNzA8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9InBheU91dFJhdGlvIj4KICAgPHN0cmluZz4wLjMwPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJzdGFydERhdGUiPgogICA8c3RyaW5nPjIwMTctMTAtMzA8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
            "id": 32
          }
        ],
        "kanaName": "サヤマ セイジ",
        "gender": "male",
        "genderDesc": "M",
        "birthday": "1948-06-15",
        "simpleAddressModel": null,
        "appMemo": "診察1",
        "pvtDate": null,
        "ownerUUID": null,
        "fullName": "佐山 清二",
        "id": 31
      },
      "deptName": "内科",
      "deptCode": "01",
      "doctorName": "久森 良子",
      "doctorId": "10002",
      "jmariNumber": "JPN000000000000",
      "pvtDate": "2018-05-17T15:22:21",
      "department": "内科,01,久森 良子,10002,JPN000000000000,",
      "firstInsurance": "06 組合",
      "insuranceUid": "5b945b2f-5388-4483-b9aa-097d02ad952a",
      "lastDocDate": null,
      "appointment": null,
      "id": 34,
      "state": 0
    }
  ]
}

患者検索

患者検索画面でキーワードに"0000"を入力してエンターキーを押したときの通信内容をキャプチャしたものである。
図12.患者検索画面
GET /dolphin/openSource/patient/digit/0000 HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: 5f4dcc3b5aa765d61d8327deb882cf99
userName: 1.3.6.1.4.1.9414.70.1:mtanaka
Host: 172.16.108.251:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 7830
Date: Fri, 25 May 2018 02:49:22 GMT

{
  "list": [
    {
      "romanName": null,
      "nationality": null,
      "nationalityDesc": null,
      "maritalStatus": null,
      "jpegPhoto": null,
      "mobilePhone": null,
      "relations": null,
      "reserve1": null,
      "reserve2": null,
      "reserve3": null,
      "reserve4": null,
      "reserve5": null,
      "reserve6": null,
      "memo": null,
      "email": null,
      "facilityId": "1.3.6.1.4.1.9414.70.1",
      "telephone": null,
      "patientId": "00003",
      "healthInsurances": [
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUFZUSGVhbHRoSW5zdXJhbmNlTW9kZWwiPgogIDx2b2lkIHByb3BlcnR5PSJHVUlEIj4KICAgPHN0cmluZz40MDIyNjE1ZC1kNWE0LTRiY2ItYWJiMC1hZTY2MTEzY2FjMTg8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudEdyb3VwIj4KICAgPHN0cmluZz7vvJHvvJDvvJg8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudE51bWJlciI+CiAgIDxzdHJpbmc+77yU77yT77yS77yV77yS77yRPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJleHBpcmVkRGF0ZSI+CiAgIDxzdHJpbmc+OTk5OS0xMi0zMTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iZmFtaWx5Q2xhc3MiPgogICA8c3RyaW5nPmZhbHNlPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzcyI+CiAgIDxzdHJpbmc+57WE5ZCIPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzc0NvZGUiPgogICA8c3RyaW5nPjA2PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzc0NvZGVTeXMiPgogICA8c3RyaW5nPk1NTDAwMzE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Imluc3VyYW5jZU51bWJlciI+CiAgIDxzdHJpbmc+MDYwNDAxMzM8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9InBheU91dFJhdGlvIj4KICAgPHN0cmluZz4wLjMwPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJzdGFydERhdGUiPgogICA8c3RyaW5nPjIwMTctMTAtMzA8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
          "id": 28
        }
      ],
      "kanaName": "サカイ ハルヨ",
      "gender": "female",
      "genderDesc": "F",
      "birthday": "1976-06-04",
      "simpleAddressModel": null,
      "appMemo": "診察1",
      "pvtDate": "2018-05-17T15:22:20",
      "ownerUUID": null,
      "fullName": "酒井 春代",
      "id": 27
    },
    {
      "romanName": null,
      "nationality": null,
      "nationalityDesc": null,
      "maritalStatus": null,
      "jpegPhoto": null,
      "mobilePhone": null,
      "relations": null,
      "reserve1": null,
      "reserve2": null,
      "reserve3": null,
      "reserve4": null,
      "reserve5": null,
      "reserve6": null,
      "memo": null,
      "email": null,
      "facilityId": "1.3.6.1.4.1.9414.70.1",
      "telephone": null,
      "patientId": "00002",
      "healthInsurances": [
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfNDUiIGNsYXNzPSJqYXZhLmJlYW5zLlhNTERlY29kZXIiPgogPG9iamVjdCBjbGFzcz0ib3Blbi5kb2xwaGluLmluZm9tb2RlbC5QVlRIZWFsdGhJbnN1cmFuY2VNb2RlbCI+CiAgPHZvaWQgcHJvcGVydHk9IkdVSUQiPgogICA8c3RyaW5nPjFhYWM3MjMyLWEwZWEtNDM2Ny1hODMwLTE0OTE5NjMzYTYzZjwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xpZW50R3JvdXAiPgogICA8c3RyaW5nPumDvTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xpZW50TnVtYmVyIj4KICAgPHN0cmluZz7vvJfvvJfvvJTvvJLvvJE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImV4cGlyZWREYXRlIj4KICAgPHN0cmluZz45OTk5LTEyLTMxPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJmYW1pbHlDbGFzcyI+CiAgIDxzdHJpbmc+dHJ1ZTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iaW5zdXJhbmNlQ2xhc3MiPgogICA8c3RyaW5nPuWcsOaWueWFsea4iDwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iaW5zdXJhbmNlQ2xhc3NDb2RlIj4KICAgPHN0cmluZz4zMjwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iaW5zdXJhbmNlQ2xhc3NDb2RlU3lzIj4KICAgPHN0cmluZz5NTUwwMDMxPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VOdW1iZXIiPgogICA8c3RyaW5nPjMyMTMwMjEzPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJwYXlPdXRSYXRpbyI+CiAgIDxzdHJpbmc+MC4zMDwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0ic3RhcnREYXRlIj4KICAgPHN0cmluZz4yMDE3LTEwLTI1PC9zdHJpbmc+CiAgPC92b2lkPgogPC9vYmplY3Q+CjwvamF2YT4K",
          "id": 40
        }
      ],
      "kanaName": "フクダ ヨシヒロ",
      "gender": "male",
      "genderDesc": "M",
      "birthday": "1961-08-27",
      "simpleAddressModel": null,
      "appMemo": "診察1",
      "pvtDate": "2018-05-17T15:22:52",
      "ownerUUID": null,
      "fullName": "福田 佳宏",
      "id": 39
    },
    {
      "romanName": null,
      "nationality": null,
      "nationalityDesc": null,
      "maritalStatus": null,
      "jpegPhoto": null,
      "mobilePhone": null,
      "relations": null,
      "reserve1": null,
      "reserve2": null,
      "reserve3": null,
      "reserve4": null,
      "reserve5": null,
      "reserve6": null,
      "memo": null,
      "email": null,
      "facilityId": "1.3.6.1.4.1.9414.70.1",
      "telephone": null,
      "patientId": "00004",
      "healthInsurances": [
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTYxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUFZUSGVhbHRoSW5zdXJhbmNlTW9kZWwiPgogIDx2b2lkIHByb3BlcnR5PSJHVUlEIj4KICAgPHN0cmluZz41Yjk0NWIyZi01Mzg4LTQ0ODMtYjlhYS0wOTdkMDJhZDk1MmE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudEdyb3VwIj4KICAgPHN0cmluZz7vvJLvvJDvvJDvvJA8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudE51bWJlciI+CiAgIDxzdHJpbmc+77yW77yY77yV77yTPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJleHBpcmVkRGF0ZSI+CiAgIDxzdHJpbmc+OTk5OS0xMi0zMTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iZmFtaWx5Q2xhc3MiPgogICA8c3RyaW5nPmZhbHNlPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzcyI+CiAgIDxzdHJpbmc+57WE5ZCIPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzc0NvZGUiPgogICA8c3RyaW5nPjA2PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJpbnN1cmFuY2VDbGFzc0NvZGVTeXMiPgogICA8c3RyaW5nPk1NTDAwMzE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Imluc3VyYW5jZU51bWJlciI+CiAgIDxzdHJpbmc+MDYzMzAwNzA8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9InBheU91dFJhdGlvIj4KICAgPHN0cmluZz4wLjMwPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJzdGFydERhdGUiPgogICA8c3RyaW5nPjIwMTctMTAtMzA8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
          "id": 32
        }
      ],
      "kanaName": "サヤマ セイジ",
      "gender": "male",
      "genderDesc": "M",
      "birthday": "1948-06-15",
      "simpleAddressModel": null,
      "appMemo": "診察1",
      "pvtDate": "2018-05-17T15:22:21",
      "ownerUUID": null,
      "fullName": "佐山 清二",
      "id": 31
    },
    {
      "romanName": null,
      "nationality": null,
      "nationalityDesc": null,
      "maritalStatus": null,
      "jpegPhoto": null,
      "mobilePhone": null,
      "relations": null,
      "reserve1": null,
      "reserve2": null,
      "reserve3": null,
      "reserve4": null,
      "reserve5": null,
      "reserve6": null,
      "memo": null,
      "email": null,
      "facilityId": "1.3.6.1.4.1.9414.70.1",
      "telephone": null,
      "patientId": "00001",
      "healthInsurances": [
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTcxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUFZUSGVhbHRoSW5zdXJhbmNlTW9kZWwiPgogIDx2b2lkIHByb3BlcnR5PSJHVUlEIj4KICAgPHN0cmluZz45MjYyOTRlZi03YTZmLTRlOTYtODEyNS03OThlMzQwYWNhNjM8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudEdyb3VwIj4KICAgPHN0cmluZz7vvJTvvJHvvJDvvJbvvJHvvJLvvJTvvJI8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsaWVudE51bWJlciI+CiAgIDxzdHJpbmc+77yZ77yW77yT77yVPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJleHBpcmVkRGF0ZSI+CiAgIDxzdHJpbmc+OTk5OS0xMi0zMTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iZmFtaWx5Q2xhc3MiPgogICA8c3RyaW5nPnRydWU8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Imluc3VyYW5jZUNsYXNzIj4KICAgPHN0cmluZz7ljZTkvJrjgZHjgpPjgb08L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Imluc3VyYW5jZUNsYXNzQ29kZSI+CiAgIDxzdHJpbmc+MDk8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Imluc3VyYW5jZUNsYXNzQ29kZVN5cyI+CiAgIDxzdHJpbmc+TU1MMDAzMTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iaW5zdXJhbmNlTnVtYmVyIj4KICAgPHN0cmluZz4wMTQwMDAxOTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0icGF5T3V0UmF0aW8iPgogICA8c3RyaW5nPjAuMzA8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9InN0YXJ0RGF0ZSI+CiAgIDxzdHJpbmc+MjAxNy0xMC0yNTwvc3RyaW5nPgogIDwvdm9pZD4KIDwvb2JqZWN0Pgo8L2phdmE+Cg==",
          "id": 1867
        }
      ],
      "kanaName": "ヤマシタ コウスケ",
      "gender": "male",
      "genderDesc": "M",
      "birthday": "1970-12-06",
      "simpleAddressModel": null,
      "appMemo": "診察1",
      "pvtDate": "2018-05-23T13:56:45",
      "ownerUUID": "w3415038:89bc6c0b-0e94-4e12-ac5a-70283c6cc145",
      "fullName": "山下 浩介",
      "id": 35
    }
  ]
}

カルテ表示

患者一覧画面で患者を選択したときに図13のカルテ画面が表示されるが、そのときの通信内容をキャプチャしたものである。
図13 カルテ表示画面

このときのパケット一覧を以下に示す。
図14.カルテを出した時のパケットの一覧
 このとき全部で3回のセッションがキャプチャできた。最初のキャプチャは以下の通りである。これは、どうやらこの患者に対して作成された2通のカルテの情報がサーバから送られてきているようである。ここのカルテはdocInfoList配列の要素になっている。
GET /dolphin/openSource/karte/31,2008-05-25%2011:00:00 HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: 5f4dcc3b5aa765d61d8327deb882cf99
userName: 1.3.6.1.4.1.9414.70.1:mtanaka
Host: 172.16.108.251:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 2102
Date: Fri, 25 May 2018 02:52:13 GMT

{
  "lastDocDate": 1526539476658,
  "created": "2018-05-17",
  "allergies": null,
  "heights": null,
  "weights": null,
  "patientVisits": [
    "2018-05-17T15:22:21"
  ],
  "docInfoList": [
    {
      "departmentCodeSys": null,
      "docPk": 79,
      "purposeDesc": null,
      "purposeCodeSys": null,
      "healthInsuranceCodeSys": null,
      "versionNotes": null,
      "parentId": null,
      "parentIdDesc": null,
      "parentIdCodeSys": null,
      "labtestOrderNumber": null,
      "pvthealthInsuranceModel": null,
      "createrLisence": null,
      "title": "嘔吐・下痢の症状がみられる",
      "departmentDesc": "内科,01,小井 優成,10004,JPN000000000000",
      "firstConfirmDate": 1526539476658,
      "confirmDate": 1526539476658,
      "facilityName": null,
      "patientName": null,
      "patientId": null,
      "department": "01",
      "parentPk": 0,
      "docId": "6cd5ea01ac10667f015ec41706ccae36",
      "sendClaim": false,
      "parentIdRelation": null,
      "docType": "karte",
      "healthInsurance": "06",
      "healthInsuranceDesc": "06 組合",
      "healthInsuranceGUID": "5b945b2f-5388-4483-b9aa-097d02ad952a",
      "claimDate": 1526539466036,
      "purpose": "recode",
      "patientGender": null,
      "versionNumber": "1.0",
      "hasTreatment": false,
      "hasLaboTest": false,
      "sendLabtest": false,
      "sendMml": false,
      "hasRp": true,
      "hasImage": false,
      "hasMark": false,
      "status": "F"
    },
    {
      "departmentCodeSys": null,
      "docPk": 48,
      "purposeDesc": null,
      "purposeCodeSys": null,
      "healthInsuranceCodeSys": null,
      "versionNotes": null,
      "parentId": null,
      "parentIdDesc": null,
      "parentIdCodeSys": null,
      "labtestOrderNumber": null,
      "pvthealthInsuranceModel": null,
      "createrLisence": null,
      "title": "風邪初診",
      "departmentDesc": "内科,01,小井 優成,10004,JPN000000000000",
      "firstConfirmDate": 1526538665611,
      "confirmDate": 1526538665611,
      "facilityName": null,
      "patientName": null,
      "patientId": null,
      "department": "01",
      "parentPk": 0,
      "docId": "6cc5df93ac10667f014541e8efd2397f",
      "sendClaim": false,
      "parentIdRelation": null,
      "docType": "karte",
      "healthInsurance": "06",
      "healthInsuranceDesc": "06 組合",
      "healthInsuranceGUID": "5b945b2f-5388-4483-b9aa-097d02ad952a",
      "claimDate": 1526538643879,
      "purpose": "recode",
      "patientGender": null,
      "versionNumber": "1.0",
      "hasTreatment": false,
      "hasLaboTest": false,
      "sendLabtest": false,
      "sendMml": false,
      "hasRp": true,
      "hasImage": false,
      "hasMark": false,
      "status": "F"
    }
  ],
  "memoList": null,
  "id": 33
}
次は、2つ目のセッションの通信内容である。
クライアントはPUTメソッドを送っている。RESTfulでは、PUTメソッドは書き込みを意味する。クライアントからのリクエストメッセージのボディ部を見ると医療機関コードfacilityIdやownerUUIDなどの情報がある。これに対してサーバはレスポンスメッセージのボディ部にただ単に1とだけ返信している。このメッセージのやり取りがどのような役割を担っているのか不明である。
PUT /dolphin/openSource/chartEvent/event HTTP/1.1
Accept-Encoding: gzip, deflate
Content-Type: application/json
password: 5f4dcc3b5aa765d61d8327deb882cf99
userName: 1.3.6.1.4.1.9414.70.1:mtanaka
Content-Length: 295
Host: 172.16.108.251:8080
Connection: Keep-Alive

{
  "state": 1,
  "patientVisitModel": null,
  "byomeiCount": 0,
  "issuerUUID": "mtanaka:8a8e884a-103d-4c1c-8f0d-0eef4f5df2e0",
  "byomeiCountToday": 0,
  "facilityId": "1.3.6.1.4.1.9414.70.1",
  "memo": null,
  "patientModel": null,
  "ownerUUID": "mtanaka:8a8e884a-103d-4c1c-8f0d-0eef4f5df2e0",
  "ptPk": 31,
  "eventType": 0,
  "pvtPk": 0
}

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 1
Date: Fri, 25 May 2018 02:52:13 GMT

1
最後に3つ目のセッションの通信内容を以下に示す。どうやらこれが開いているカルテの内容のようである。
GET /dolphin/openSource/karte/documents/79 HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
password: 5f4dcc3b5aa765d61d8327deb882cf99
userName: 1.3.6.1.4.1.9414.70.1:mtanaka
Host: 172.16.108.251:8080
Connection: Keep-Alive

HTTP/1.1 200 OK
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/9
Content-Type: application/json
Content-Length: 10286
Date: Fri, 25 May 2018 02:52:14 GMT

{
  "list": [
    {
      "linkId": 0,
      "linkRelation": null,
      "recorded": 1526539476658,
      "userModel": {
        "userId": null,
        "facilityModel": null,
        "sirName": null,
        "givenName": null,
        "commonName": "内田 裕也",
        "departmentModel": null,
        "memo": null,
        "email": null,
        "orcaId": null,
        "useDrugId": null,
        "memberType": null,
        "registeredDate": null,
        "licenseModel": null,
        "roles": null,
        "password": null,
        "id": 13
      },
      "karteBean": {
        "lastDocDate": null,
        "created": null,
        "allergies": null,
        "heights": null,
        "weights": null,
        "patientVisits": null,
        "docInfoList": null,
        "memoList": null,
        "id": 33
      },
      "started": 1526539476658,
      "ended": null,
      "docInfoModel": {
        "departmentCodeSys": null,
        "docPk": 79,
        "purposeDesc": null,
        "purposeCodeSys": null,
        "healthInsuranceCodeSys": null,
        "versionNotes": null,
        "parentId": null,
        "parentIdDesc": null,
        "parentIdCodeSys": null,
        "labtestOrderNumber": null,
        "pvthealthInsuranceModel": null,
        "createrLisence": null,
        "title": "嘔吐・下痢の症状がみられる",
        "departmentDesc": "内科,01,小井 優成,10004,JPN000000000000",
        "firstConfirmDate": 1526539476658,
        "confirmDate": 1526539476658,
        "facilityName": null,
        "patientName": null,
        "patientId": null,
        "department": "01",
        "parentPk": 0,
        "docId": "6cd5ea01ac10667f015ec41706ccae36",
        "sendClaim": false,
        "parentIdRelation": null,
        "docType": "karte",
        "healthInsurance": "06",
        "healthInsuranceDesc": "06 組合",
        "healthInsuranceGUID": "5b945b2f-5388-4483-b9aa-097d02ad952a",
        "claimDate": 1526539466036,
        "purpose": "recode",
        "patientGender": null,
        "versionNumber": "1.0",
        "hasTreatment": false,
        "hasLaboTest": false,
        "sendLabtest": false,
        "sendMml": false,
        "hasRp": true,
        "hasImage": false,
        "hasMark": false,
        "status": "F"
      },
      "confirmed": 1526539476658,
      "modules": [
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTYxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUHJvZ3Jlc3NDb3Vyc2UiPgogIDx2b2lkIHByb3BlcnR5PSJmcmVlVGV4dCI+CiAgIDxzdHJpbmc+Jmx0O3NlY3Rpb24gc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7MTQmcXVvdDsmZ3Q7Jmx0O3BhcmFncmFwaCBzdGFydD0mcXVvdDswJnF1b3Q7IGVuZD0mcXVvdDsxNCZxdW90OyZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDswJnF1b3Q7IGVuZD0mcXVvdDsxMyZxdW90OyBuYW1lPSZxdW90O2NvbnRlbnQmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q75ZiU5ZCQ44O75LiL55ei44Gu55eH54q244GM44G/44KJ44KM44KLJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7Y29udGVudCBzdGFydD0mcXVvdDsxMyZxdW90OyBlbmQ9JnF1b3Q7MTQmcXVvdDsmZ3Q7Jmx0O3RleHQmZ3Q7CiZsdDsvdGV4dCZndDsmbHQ7L2NvbnRlbnQmZ3Q7Jmx0Oy9wYXJhZ3JhcGgmZ3Q7Jmx0Oy9zZWN0aW9uJmd0Ozwvc3RyaW5nPgogIDwvdm9pZD4KIDwvb2JqZWN0Pgo8L2phdmE+Cg==",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1526539476658,
          "userModel": {
            "userId": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "roles": null,
            "password": null,
            "id": 13
          },
          "karteBean": {
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "id": 33
          },
          "started": 1526539476658,
          "ended": null,
          "moduleInfoBean": {
            "stampNumber": 0,
            "stampName": "progressCourse",
            "stampRole": "soaSpec",
            "entity": "progressCourse"
          },
          "confirmed": 1526539476658,
          "status": "F",
          "id": 80
        },
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTYxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlRG9scGhpbiI+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+MTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIxIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4wPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz4xMTIwMDc0MTA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPuWGjeioujwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgPC9vYmplY3Q+CiAgICA8L3ZvaWQ+CiAgIDwvYXJyYXk+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICA8c3RyaW5nPjEyMDwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NDb2RlU3lzdGVtIj4KICAgPHN0cmluZz5DbGFpbTAwNzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhc3NOYW1lIj4KICAgPHN0cmluZz7lho3oqLoo5YaN6Ki6KTwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0ib3JkZXJOYW1lIj4KICAgPHN0cmluZz7oqLrmlq3mlpk8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1526539476658,
          "userModel": {
            "userId": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "roles": null,
            "password": null,
            "id": 13
          },
          "karteBean": {
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "id": 33
          },
          "started": 1526539476658,
          "ended": null,
          "moduleInfoBean": {
            "stampNumber": 1,
            "stampName": "再診",
            "stampRole": "p",
            "entity": "baseChargeOrder"
          },
          "confirmed": 1526539476658,
          "status": "F",
          "id": 81
        },
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTYxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuQnVuZGxlTWVkIj4KICA8dm9pZCBwcm9wZXJ0eT0iYWRtaW4iPgogICA8c3RyaW5nPlvnlKjms5VdIO+8keaXpe+8k+Wbnuavjumjn+W+jOOBqzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iYWRtaW5Db2RlIj4KICAgPHN0cmluZz4wMDEwMDAzMDE8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImJ1bmRsZU51bWJlciI+CiAgIDxzdHJpbmc+Nzwvc3RyaW5nPgogIDwvdm9pZD4KICA8dm9pZCBwcm9wZXJ0eT0iY2xhaW1JdGVtIj4KICAgPGFycmF5IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSIgbGVuZ3RoPSIxIj4KICAgIDx2b2lkIGluZGV4PSIwIj4KICAgICA8b2JqZWN0IGNsYXNzPSJvcGVuLmRvbHBoaW4uaW5mb21vZGVsLkNsYWltSXRlbSI+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGUiPgogICAgICAgPHN0cmluZz4yPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZVN5c3RlbSI+CiAgICAgICA8c3RyaW5nPkNsYWltMDAzPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9ImNvZGUiPgogICAgICAgPHN0cmluZz42MTA0MjEzMjA8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0ibmFtZSI+CiAgICAgICA8c3RyaW5nPuOCouODgOODqeODvOODiO+8o++8sumMoO+8ke+8kO+9je+9hzwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXIiPgogICAgICAgPHN0cmluZz4zPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICAgPHZvaWQgcHJvcGVydHk9Im51bWJlckNvZGUiPgogICAgICAgPHN0cmluZz4xMDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJudW1iZXJDb2RlU3lzdGVtIj4KICAgICAgIDxzdHJpbmc+Q2xhaW0wMDQ8L3N0cmluZz4KICAgICAgPC92b2lkPgogICAgICA8dm9pZCBwcm9wZXJ0eT0idW5pdCI+CiAgICAgICA8c3RyaW5nPumMoDwvc3RyaW5nPgogICAgICA8L3ZvaWQ+CiAgICAgIDx2b2lkIHByb3BlcnR5PSJ5a3pLYm4iPgogICAgICAgPHN0cmluZz4xPC9zdHJpbmc+CiAgICAgIDwvdm9pZD4KICAgICA8L29iamVjdD4KICAgIDwvdm9pZD4KICAgPC9hcnJheT4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9ImNsYXNzQ29kZSI+CiAgIDxzdHJpbmc+MjExPC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc0NvZGVTeXN0ZW0iPgogICA8c3RyaW5nPkNsYWltMDA3PC9zdHJpbmc+CiAgPC92b2lkPgogIDx2b2lkIHByb3BlcnR5PSJjbGFzc05hbWUiPgogICA8c3RyaW5nPuaKleiWrCjlhoXmnI3jg7vpoJPmnI3jg7voqr/liaQpKOmZouWGhSk8L3N0cmluZz4KICA8L3ZvaWQ+CiAgPHZvaWQgcHJvcGVydHk9Im1lbW8iPgogICA8c3RyaW5nPuWGheeUqO+8iOmZouWGheWHpuaWuSk8L3N0cmluZz4KICA8L3ZvaWQ+CiA8L29iamVjdD4KPC9qYXZhPgo=",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1526539476658,
          "userModel": {
            "userId": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "roles": null,
            "password": null,
            "id": 13
          },
          "karteBean": {
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "id": 33
          },
          "started": 1526539476658,
          "ended": null,
          "moduleInfoBean": {
            "stampNumber": 2,
            "stampName": "アダラートCR錠10mg",
            "stampRole": "p",
            "entity": "medOrder"
          },
          "confirmed": 1526539476658,
          "status": "F",
          "id": 82
        },
        {
          "beanBytes": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPGphdmEgdmVyc2lvbj0iMS44LjBfMTYxIiBjbGFzcz0iamF2YS5iZWFucy5YTUxEZWNvZGVyIj4KIDxvYmplY3QgY2xhc3M9Im9wZW4uZG9scGhpbi5pbmZvbW9kZWwuUHJvZ3Jlc3NDb3Vyc2UiPgogIDx2b2lkIHByb3BlcnR5PSJmcmVlVGV4dCI+CiAgIDxzdHJpbmc+Jmx0O3NlY3Rpb24gc3RhcnQ9JnF1b3Q7MCZxdW90OyBlbmQ9JnF1b3Q7NSZxdW90OyZndDsmbHQ7cGFyYWdyYXBoIHN0YXJ0PSZxdW90OzAmcXVvdDsgZW5kPSZxdW90OzImcXVvdDsmZ3Q7Jmx0O2NvbXBvbmVudCBzdGFydD0mcXVvdDswJnF1b3Q7IGVuZD0mcXVvdDsxJnF1b3Q7IG5hbWU9JnF1b3Q7c3RhbXBIb2xkZXImcXVvdDsgY29tcG9uZW50PSZxdW90OzAmcXVvdDsmZ3Q7Jmx0Oy9jb21wb25lbnQmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7MSZxdW90OyBlbmQ9JnF1b3Q7MiZxdW90OyZndDsmbHQ7dGV4dCZndDsKJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7L3BhcmFncmFwaCZndDsmbHQ7cGFyYWdyYXBoIHN0YXJ0PSZxdW90OzImcXVvdDsgZW5kPSZxdW90OzMmcXVvdDsmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7MiZxdW90OyBlbmQ9JnF1b3Q7MyZxdW90OyZndDsmbHQ7dGV4dCZndDsKJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7L3BhcmFncmFwaCZndDsmbHQ7cGFyYWdyYXBoIHN0YXJ0PSZxdW90OzMmcXVvdDsgZW5kPSZxdW90OzUmcXVvdDsmZ3Q7Jmx0O2NvbXBvbmVudCBzdGFydD0mcXVvdDszJnF1b3Q7IGVuZD0mcXVvdDs0JnF1b3Q7IG5hbWU9JnF1b3Q7c3RhbXBIb2xkZXImcXVvdDsgY29tcG9uZW50PSZxdW90OzEmcXVvdDsmZ3Q7Jmx0Oy9jb21wb25lbnQmZ3Q7Jmx0O2NvbnRlbnQgc3RhcnQ9JnF1b3Q7NCZxdW90OyBlbmQ9JnF1b3Q7NSZxdW90OyZndDsmbHQ7dGV4dCZndDsKJmx0Oy90ZXh0Jmd0OyZsdDsvY29udGVudCZndDsmbHQ7L3BhcmFncmFwaCZndDsmbHQ7L3NlY3Rpb24mZ3Q7PC9zdHJpbmc+CiAgPC92b2lkPgogPC9vYmplY3Q+CjwvamF2YT4K",
          "linkId": 0,
          "linkRelation": null,
          "recorded": 1526539476658,
          "userModel": {
            "userId": null,
            "facilityModel": null,
            "sirName": null,
            "givenName": null,
            "commonName": null,
            "departmentModel": null,
            "memo": null,
            "email": null,
            "orcaId": null,
            "useDrugId": null,
            "memberType": null,
            "registeredDate": null,
            "licenseModel": null,
            "roles": null,
            "password": null,
            "id": 13
          },
          "karteBean": {
            "lastDocDate": null,
            "created": null,
            "allergies": null,
            "heights": null,
            "weights": null,
            "patientVisits": null,
            "docInfoList": null,
            "memoList": null,
            "id": 33
          },
          "started": 1526539476658,
          "ended": null,
          "moduleInfoBean": {
            "stampNumber": 3,
            "stampName": "progressCourse",
            "stampRole": "pSpec",
            "entity": "progressCourse"
          },
          "confirmed": 1526539476658,
          "status": "F",
          "id": 83
        }
      ],
      "attachment": null,
      "schema": null,
      "status": "F",
      "id": 79
    }
  ]
}
この中にbeanBytesという項目があり、その値として長い文字列が設定されている。
これはBASE64でエンコードされたデータで、デコードすると次のようなXMLが得られた。
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_161" class="java.beans.XMLDecoder">
 <object class="open.dolphin.infomodel.ProgressCourse">
  <void property="freeText">
   <string>
    <section start="0" end="14">
     <paragraph start="0" end="14">
      <content start="0" end="13" name="content">
       <text>嘔吐・下痢の症状がみられる</text>
      </content>
      <content start="13" end="14">
       <text></text>
      </content>
     </paragraph>
    </section>
   </string>
  </void>
 </object>
</java>
これを見ると、カルテの左側、つまり経過記録のようである。OpenDolphinではカルテに表示するデータをこのようにXML形式で記述しているようである。XMLなので、セクションやパラグラフの開始や終わりを属性として記述できるため、単なる文字列ではなくオブジェクトとして扱えるためであろう。

MD5ハッシュを計算するLinuxコマンドmd5sum

$ echo -n password | md5sum
5f4dcc3b5aa765d61d8327deb882cf99  -
この例では文字列"password"のMD5ハッシュ値を計算している。echoコマンドのオプション -n は改行を出力しないという意味。
また、Web上にMD5ハッシュ値を計算するサイトがある。

JSONの整形

OpenDolphinの通信内容をキャプチャすると、サーバからのレスポンスのボディ部にJSON形式のデータが格納されて戻ってくるが、適切に改行されていないため、わかりにくい。そのような時にはWeb上にJSON整形ツールがあるので利用するとよい。このブログで紹介したJSONデータはすべてそのツールを用いて整形してある。
図15.JSON整形ツール

BASE64デコードツール

カルテを開いたときにサーバから届くJSON形式のデータ(2つ目のGETメソッドに対するレスポンス)の中にbeanBytesという項目がある。この項目はBASE64にエンコーディングされている。BASE64にエンコードされたデータをデコードするツールがWeb上にあり、それを用いることによりメッセージの中身がわかる。
図16.BASE64でコードツール

5 件のコメント:

  1. 検索経由で見つけました。
    興味深い(予備)研究ですね。
    読んで思うところがあったので、よろしければ
    https://phazor.info/OpenOcean/?p=77
    を読んでみてください。

    返信削除
  2. コメントをありがとうございます。
    当初、FHIR (https://www.hl7.org/fhir/) でRESTful APIを作るつもりでいました(OpenDolphin serever -> FHIR server -> スマホアプリ)。ところが調べていくうちにOpenDolphinが独自にRESTful APIを提供していることがわかったので、とりあえずそれを調べてみようということでキャプチャしています。以前、ORCAのAPI(RESTfulではありませんが)を使ってスマホアプリを開発したことがあります。ORCAもOpenDolphinも独自のAPIを実装しているので、ご指摘の通り仕様が変わればクライアントもそれに応じてプログラムの修正が必要です。これが過去何年にもわたって医療情報の世界で繰り返されてきたことです。これを断ち切るにはHL7のような標準規格を利用すべきですが、なかなか進みません。そこで私たちはそれを実現しようと現在の研究に取り組んだわけです。RESTful APIはちょうどRDBMSのSQLのように標準化されれば、もっともっと利用の幅が広がるのではないかと思います。

    返信削除
  3. なるほど。
    ある程度、推測がついたら、ソースにあたると、(サーバも含め)自由に改変できるかもしれませんね。

    返信削除
  4. 追加情報です。
    Dolphin のRESTful API の URL はドッカー版と正規版で微妙に違うようです。
    (いちおう私のソフトはドッカー版とはつながりました)
    MONACA というものは URL の変更に柔軟に対応できるものなのですか?

    返信削除
  5. MONACA(https://ja.monaca.io/)はHTML5とJavascriptを用いてスマホアプリを開発する環境です。ですから、ドッカー版と正規版でURLをスイッチすることは可能です。

    返信削除

レーダーチャートの表示2

前回 レーダーチャートの表示を行うことが出来たので、今回は実際の値を代入したグラフの描画を試みる。 .controller('RaderChartController', ['$scope', 'Countries', funct...