M5Stackと心拍センサユニット、kintoneを組み合わせてパルスオキシメーターの情報共有をする

木曜日 , 20, 1月 2022 Leave a comment

前回作成した『M5Stack/ATOMとGPSユニットを使って位置情報をクラウドに保存する / M5シリーズUIFlowからKintoneに直接データをアップロードする』を応用し、M5Stack/ATOMシリーズと心拍センサユニットの組み合わせで酸素飽和度(SpO2)と心拍数を計測し、計測した情報をサイボウズ社のkintoneに直接アップロードするプログラムを作成しました。
M5Stackにプログラムを転送する際、デバイスごとにユニークなIDを設定することでkintone側では複数のM5シリーズデバイスからアップロードされた計測データを一元管理することができます。

kintone側ではデバイスからアップロードされた酸素飽和度や最終計測日時などから計測対象者の状態を把握し業務支援を行うことができるようになると考えています。

IMG_8324

使い方

  • kintone上にアプリ(データベース)を作成し、外部からアクセスするためのAPIトークンを発行、および適切なアクセス権限を設定します。
    サンプルプログラムでは、「SpO2」というアプリを作成し、下表のようにフィールドを定義しています。

2022-01-20 (9)

フィールド名

データ型

フィールドコード

装置ID 文字列(1行) deviceid
装置計測日時 文字列(1行) devicetime
SpO2 数値 spo2
心拍数 数値 heartrate

※APIからアップロードする際に使用するのは、kintone上の「フィールド名」(設定画面一番上の項目)ではなく「フィールドコード」(設定画面一番下の項目)である点に注意が必要です。

  • kintoneのURL、APIトークン、アプリID、装置IDをソースコードの冒頭にある変数に設定します。
  • M5Burnerなどを使ってM5Stack/ATOM.シリーズのデバイスに転送します。
  • 電源を投入すると所定のWi-Fiに接続を試みます。
    接続が確立するとLEDがアニメーションを始めます。この状態でAボタンを押すと心拍センサからSpO2値と心拍数を取得しkintone上にアップロードします。
  • 酸素飽和度の値に応じてATOM MatrixのLED表示が以下のように変化します

表示

酸素飽和度値

spo2_normal

96%以上
spo2_caution 93%以上96%未満
spo2_warning 93%未満
spo2_error 0またはエラー

  • アップロードされたデータは下図のように記録されます。

2022-01-20 (8)

ソースコード

spo2_cybozu_pub_20220120

大きな画像を表示( http://www.ria-lab.com/omiyage/spo2_cybozu_pub_20220120.png )

from m5stack import *
from m5ui import *
from uiflow import *
import ntptime
import urequests
import wifiCfg
import json

import time
import unit

rgb.set_screen([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
heart1 = unit.get(unit.HEART, unit.PORTA)


spo2 = None
rate = None
API_URL = None
time = None
API_TOKEN = None
APP_ID = None
DEVICE_ID = None
data = None

wifiCfg.autoConnect(lcdShow=True)
wifiCfg.reconnect()



def buttonA_wasPressed():
  global spo2, rate, API_URL, time, API_TOKEN, APP_ID, DEVICE_ID, data
  spo2 = heart1.getSpO2()
  rate = heart1.getHeartRate()
  time = str((ntp.formatDatetime('-', ':')))
  print(str(spo2))
  if spo2 == 0 or spo2 == 'error':
    rgb.set_screen([0,0,0xff8080,0,0,0,0xff8080,0,0xff8080,0,0,0,0,0xff8080,0,0,0,0xff8080,0,0,0,0,0xff8080,0,0])
  else:
    if spo2 >= 96:
      rgb.set_screen([0,0x0000ff,0x0000ff,0x0000ff,0,0x0000ff,0,0,0,0x0000ff,0x0000ff,0,0,0,0x0000ff,0x0000ff,0,0,0,0x0000ff,0,0x0000ff,0x0000ff,0x0000ff,0])
    else:
      if spo2 >= 93 and spo2 < 96:
        rgb.set_screen([0,0,0xffff00,0,0,0,0,0xffff00,0,0,0,0,0xffff00,0,0,0,0,0,0,0,0,0,0xffff00,0,0])
      else:
        if spo2 < 93:
          rgb.set_screen([0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000])
  data = {'app':APP_ID,'record':({'deviceid':({'value':str(DEVICE_ID)}),'devicetime':({'value':str(time)}),'spo2':({'value':str(spo2)}),'heartrate':({'value':str(rate)})})}
  try:
    req = urequests.request(method='POST', url=API_URL,json=json.dumps(data), headers={'X-Cybozu-API-Token':API_TOKEN,'Content-Type':'application/json'})
  except:
    print(str('error'))
  wait(1)
  pass
btnA.wasPressed(buttonA_wasPressed)


print('init')
API_URL = 'https://<YOUR_SUBDOMAIN>.cybozu.com/k/v1/record.json'
API_TOKEN = '<YOUR_TOKEN>'
APP_ID = '<YOUR_APP_ID>'
DEVICE_ID = 'RIALAB_01'
rgb.set_screen([0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF,0,0xFFFFFF])
while not (wifiCfg.wlan_sta.isconnected()):
  wait_ms(500)
  print('retry')
ntp = ntptime.client(host='ntp.nict.jp', timezone=9)
heart1.setMode(0x03)
print('start')
while True:
  if btnA.isReleased():
    rgb.set_screen([0,0,0,0,0,0,0,0,0,0,0,0,0x00ffff,0,0,0,0,0,0,0,0,0,0,0,0])
    wait_ms(500)
    rgb.set_screen([0,0,0,0,0,0,0x00ffff,0x00ffff,0x00ffff,0,0,0x00ffff,0,0x00ffff,0,0,0x00ffff,0x00ffff,0x00ffff,0,0,0,0,0,0])
    wait_ms(500)
    rgb.set_screen([0x00ffff,0x00ffff,0x00ffff,0x00ffff,0x00ffff,0x00ffff,0,0,0,0x00ffff,0x00ffff,0,0,0,0x00ffff,0x00ffff,0,0,0,0x00ffff,0x00ffff,0x00ffff,0x00ffff,0x00ffff,0x00ffff])
    wait_ms(500)
  wait_ms(2)

まとめ

以前作成した『複数台のM5Stackと心拍センサーを使ったパルスオキシメーターを集中的にモニタリングする仕組みを自作する』の簡易版になります。
以前の版ではActiveMQなどのセットアップが必要など動かすためにはややハードル高めの準備が必要でしたが、今回の版ではWebサービスのkintoneを使うことで簡単に素早くセットアップできるようになっています。

Please give us your valuable comment

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください