シェルスクリプトマガジン

特集3  ラズパイでコロナ感染症対策(Vol.73記載)

著者:麻生 二郎

新型コロナウイルス感染症対策として、日々の手洗いと検温は重要です。ただ、1人暮らしの人など、それらを習慣化するのは難しいかもしれません。本特集では、小型コンピュータボード「Raspberry Pi」(ラズパイ)と電子回路を用いて、新型コロナウイルス感染症対策を習慣化できるような支援システムを構築します。

シェルスクリプトマガジン Vol.73は以下のリンク先でご購入できます。

Part2 感染症対策システムを完成する

図2 pirm_sensor.pyのソースコード

#!/usr/bin/env python3

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(21,GPIO.IN)

pir = GPIO.input(21)
print(pir)

図3 temp_sensor.pyのソースコード

#!/usr/bin/env python3

from smbus2 import SMBus
from mlx90614 import MLX90614

bus = SMBus(1)
sensor = MLX90614(bus, address=0x5A)
print(sensor.get_ambient(),sensor.get_object_1())
bus.close()

図4 go_out.shのソースコード

#!/bin/bash

##外出確認の初期値と玄関にいる時間(秒)
GOOUT_CHECK=0
STAY_TIME=3

##表面体温の初期値と基準値
OUTSIDE_TEMP=0
OUTSIDE_TEMP_BASE=32

##周辺温度の初期値と基準値
AMBIENT_TEMP=35
AMBIENT_TEMP_BASE=28

##体内温度の基準値
INTSIDE_TEMP_BASE=36.7

##体内温度との差分
INSIDE_BODY_DIFF=4.2

##メッセージ集
MESSAGE1="おはようございます。出かける前に検温をしてください"
MESSAGE2="周辺温度が${AMBIENT_TEMP}であり、検温に適していません。エアコンをかけてください"
MESSAGE3="周辺温度が${AMBIENT_TEMP}です。検温を開始します。おでこをセンサーに向けてください"
MESSAGE4="今朝の体温は${INSIDE_TEMP}です。正常値なので外出可能です。マスクを着用し、予備のマスクも持って出かけてください"
MESSAGE5="今朝の体温は${INSIDE_TEMP}です。熱がありますので、正確に測れる体温計で再度測定してください"

##音声メッセージ関数
function voice_message(){
  echo $1 | open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow /dev/stdout | aplay --quiet
}

##外出の確認
while [ ${GOOUT_CHECK} -lt ${STAY_TIME} ]
do
  if [ $(pirm_sensor.py) -eq 1 ];then
    GOOUT_CHECK=$(echo "${GOOUT_CHECK} + 1" | bc)
  else
    GOOUT_CHECK=0
  fi
  sleep 1
done
voice_message ${MESSAGE1}

##周辺温度の確認
while [ ${AMBIENT_TEMP} -ge ${AMBIENT_TEMP_BASE} ]
do
  AMBIENT_TEMP=$(/usr/bin/python3 temp_sensor.py | cut -d " " -f 1)
  voice_message ${MESSAGE2}
  sleep 5
done
voice_message ${MESSAGE3}

##検温
while [ ${OUTSIDE_TEMP} -gt ${OUTSIDE_TEMP_BASE} ]
do
  OUTSIDE_TEMP=$(/usr/bin/python3 temp_sensor.py | cut -d " " -f 2)
  sleep 1
done
echo "$OUTSIDE_TEMP,$(date +%Y%m%d-%H:%M)" >> ${HOME}/body_temp.csv

##測定結果
INSIDE_TEMP=$(echo "scale=1; ${OUTSIDE_TEMP} + ${INSIDE_BODY_DIFF}" | bc)

if [ ${INSIDE_TEMP} -lt ${OUTSIDE_TEMP_BASE} ]; then
  voice_message ${MESSAGE4}
else
  voice_message ${MESSAGE5}
fi

図5 handwash_mouthwash.pyのソースコード

#!/usr/bin/env python3

import board
import busio
i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)

chan1 = AnalogIn(ads, ADS.P0)
chan2 = AnalogIn(ads, ADS.P1)
print(chan1.voltage,chan2.voltage)

図6 go_home.shのソースコード

#!/bin/sh

##帰宅確認の初期値
GOHOME_CHECK=0

##手洗いとうがいの初期値
HAND_WASH=1
MOUTH_WASH=1

##ハンドソープのポンプ圧力基準値
POMP_PUSH_BASE=3

##うがい用コップの重量基準値
CUP_WEIGHT_BASE=3

##メッセージ集
MESSAGE1="おかえりなさい。帰ってきたら,手を洗って、うがいをしましょう"
MESSAGE2="手洗いを確認しました"
MESSAGE3="うがいを確認しました"		

##音声メッセージ関数
function voice_message(){
  echo $1 | open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow /dev/stdout | aplay --quiet
}

##帰宅の確認
while [ ${GOHOME_CHECK} == 1 ]
do
  GOHOME_CHECK=$(pirm_sensor.py)
  sleep 1
done
voice_message ${MESSAGE1}

##手洗いとうがいの検出
while [ ${HANDWASH} == 1 -o ${MOUTHWASH} == 1 ]
do
  ##手洗い検出の処理
  HANDWASH_MOUTHWASH=$(handwash_mouthwash.py)
  if [ $(cut -d " " -f 1 ${HANDWASH_MOUTHWASH}) -gt ${POMP_PUSH_BASE} ]; then
    if [ $(HANDWASH) == 1 ]; then
      voice_message ${MESSAGE2}
      echo $(date +%Y%m%d-%H%M-%S) >> ${HOME}/handwash.csv
    fi
    HANDWASH=0
  fi
  ##うがい検出の処理
  if [ $(cut -d " " -f 2 ${HANDWASH_MOUTHWASH}) -lt ${CUP_WEIGHT_BASE} ]; then
    if [ $(MOUTHWASH) == 1 ]; then
      voice_message ${MESSAGE3}
      echo $(date +%Y%m%d-%H%M-%S) >> ${HOME}/mouthwash.csv
    fi
    MOUTHWASH=0
  fi
  sleep 0.5
done

図7 open_close.pyのソースコード

#!/usr/bin/env python3

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(20,GPIO.IN)

window = GPIO.input(20)
print(window)

図8 ventilation.shのソースコード

#!/bin/bash

##メッセージ
MESSAGE="窓を開けて空気を入れ換えましょう"

##音声メッセージ関数
function voice_message(){
  echo $1 | open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow /dev/stdout | aplay --quiet
}

##在宅の確認
STAY_HOME=$(pirm_sensor.py)

##開閉の確認
OPEN_CHECK=$(open_close.py)

##換気の通知
if [ ${STAY_HOME} == 1 -a ${OPEN_CHECK} == 0 ]; then
  voice_message ${MESSAGE}
  sleep 180
  if [ ${OPEN_CHECK} == 1 ]; then
    echo $(date +%Y%m%d-%H%M-%S) >> ${HOME}/ventilation.csv
  fi
fi

図9 spo2_sensor.pyのソースコード

#!/usr/bin/env python3

import max30102
import hrcalc

m = max30102.MAX30102()

red, ir = m.read_sequential()

hr_spo2 =hrcalc.calc_hr_and_spo2(ir, red)
print(hr_spo2[2], hr_spo2[3])

図10 spo2.shのソースコード

#!/bin/bash

##在宅状態の初期値
STAY_HOME=0

##メッセージ集
MESSAGE1="寝るときは血中酸素飽和度を測定しましょう"
MESSAGE2="酸素が不足しています。医療機器で正確な値を測定してください。同じ値を示せば、至急病院に連絡しましょう"

##音声メッセージ関数
function voice_message(){
  echo $1 | open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow /dev/stdout | aplay --quiet
}

##在宅の確認
While [ ${STAY_HOME} == 0 ]
do
  STAY_HOME=$(pirm_sensor.py)
  sleep 180
done

##血中酸素飽和度測定の通知
voice_message ${MESSAGE1}
sleep 300

##血中酸素飽和度の測定開始
while [ 1 ]
do
  SPO2=$(/usr/bin/python3 spo2_sensor.py)
  SPO2_VALUE=$(echo ${SPO2} | cut -d " " -f 1)
  SPO2_JUDGE=$(echo ${SPO2} | cut -d " " -f 2)
  if [ ${SPO2_JUDGE} == "True" ]; then
    echo "${SPO2_VALUE} $(date +%Y%m%d-%H%M)" >> ${HOME}/spo2.csv
    if [ ${SPO2_VALUE} -le 93 ]; then
      voice_message ${MESSAGE2}
      exit 0
    fi
  fi
  sleep 300
done