Blog

  • Node-RED on RaspberryPi

    MP3 파일을 직접

    재생하면, 신뢰할 수 있는 알람이 될 것 같았다. 그보다는 알람이 어떨 때 발송되는지 좀 더

    우선 라즈베리파이에 npm을 설치한다.

    sudo apt install npm

    그 다음 다운 받은 Node.js 를 설치한다. 최신 버전이 아니면 Node-RED에서 추가 node가 설치 안되는 경우가 있다.

    tar -xvf node-v18.16.0-linux-armv7l.tar.xz
    cd node-v18.16.0-linux-armv7l
    cp -R * /usr/local/

    적당한 CLI 기반의 플레이어를 하나 설치한다. mpg321 를 설치했다.

    sudo apt -y install mpg321

    Node-RED를 설치한다.

    sudo npm install -g --unsafe-perm node-red
    

    모듈을 설치한다.

    cd ~/.node-red/node_modules
    npm install node-red-contrib-play-soundfile
    

    Flow 를 만든다.

    잡음이 살짝 들리는데 소리는 잘 들린다. 이어폰으로는 너무 작아서 들리지 않아 저렴한 스피커를 하나 구입하는 것이 좋을 것 같다.

    그리고 부팅할 때 실행될 수 있도록 설정해 준다.

  • Contact point 추가

    Node-RED를 이용해서 webhook 으로 알림을 보내기 위해서는 다음과 같이 설정한다.

    Add contact point를 선택한다.

    URL은 Grafana 설치된 컨테이너에서 실행 가능한 그런 경로로 입력해야 하는 것 같다. HTTP Method에 POST를 선택한다.

  • Node-RED 설치하기

    Grafana에서 Alert을 보내는 방법은 여러가지가 있다. 그런데 대부분 메세지 기반의 서비스 들이다. 병원에서 쓰려면 소리가 나야 하는 법. 그래서 찾아봤더니 Node-RED를 이용해서 구현할 수 있는 것 같았다.

    그래서 Node-RED를 설치해 보았다. 오늘의 목표는 소리가 나게 하는 것이다. 다음과 같이 Node-RED를 도커로 설치한다.

    sudo docker run -it \
    -p 1880:1880 \
    --name mynodered \
    nodered/node-red

    방화벽에서도 1880을 포워딩 시켜준다.

    add action=dst-nat chain=dstnat comment=node_red dst-port=1880 protocol=tcp src-address-list=trusted_source to-addresses=10.10.10.184 to-ports=1880

    웹브라우저에서 소리가 나는 것을 구현하기 위해서 필요한 Node-RED의 라이브러리는 다음과 같다. 도커에서 실행시키기 위해서는 다음과 같이 한다.

    $ sudo docker exec -it mynodered /bin/bash

    이렇게 하면 bash 창이 나온다. 다음의 명령어를 이용하여 라이브러리를 설치한다. dashboard도 같이 설치해 준다.

    npm install node-red-dashboard
    npm install node-red-contrib-play-audio

    다음과 같이 하면 된다. chime.mp3 와 관련된 부분을 지정할 때에는 ‘file in’을 선택하고, 경로는 가능하면 절대 경로로 한다. Output에는 Buffer라고 되어 있는 2개중 하나를 선택하면 된다.

    그리고 Deploy 시킨다. curl 을 이용하여 확인해 보려면 다음과 같이 한다.

    $ curl -v -X POST localhost:1880/hello

  • Flux 작성하기

    InfluxDB v2.0 부터 Flux 라는 형식으로 데이터를 추출하도록 해야 한다고 한다.

    ICU03번으로 입력된 SpO2 1일치 자료는 다음과 같이 입력하면 깔끔하게 출력된다. map 부분을 저렇게 해주지 않으면 예쁘지 않은 label로 보인다.

    from(bucket: "measurements")
    |> range(start:-1d)
    |> filter(fn: (r) => r._measurement == "vital" and r.bed  == "ICU03" and r._field == "spo2")
    |>  map(fn: (r) => ({ _value:r._value, _time:r._time, _field:"SpO2" }))