温度センサーDS18B20の測定値をブラウザで表示

温度センサーで測定したデータを、スマホやパソコンのブラウザで表示するためWebIOPiをインストールしました。WebIOPiをRaspberry Piにインストールして実行するとwebサーバが立ち上がり、ブラウザからGPIOの操作や、Raspberry Pi内のPythonプログラムを実行できるようになります。

WebIOPiのインストール

http://webiopi.trouch.com/ にアクセスし、ヘッダーメニューのDownloadをクリック

Original WebIOPi-0.7.1.tar.gz (full sources download)をクリックしてダウンロードします。ダウンロードしたファイルは、ユーザーpiのホームにある「Downloads」または「ダウンロード」フォルダにあります。WebIOPi-0.7.1.tar.gzを確認したら、ユーザーpiのホームに移動します。

次に、ターミナルを起動して次のコマンドを順番に入力します。

  • tar zxf WebIOPi-0.7.1.tar.gz
  • cd WebIOPi-0.1.7/
  • wget https://raw.githubusercontent.com/doublebind/raspi/master/webiopi-pi2bplus.patch
  • patch -p1 -i webiopi-pi2bplus.patch
  • sudo ./setup.sh

完了すると、Do you want to access WebIOPi over Internet?[y/n] と聞いてきますので、「n」をタイプします。(家の中だけで使う設定です。家の外ではこのままでは使えません。)

次に、2つのコマンドを入力してください。

  • wget https://raw.githubusercontent.com/neuralassembly/raspri/master/webiopi.service
  • sudo mv webiopi.service /etc/systemd/system/

これで、インストールは終了です。

WebIOPiの起動と停止

ターミナルから次のコマンドを入力すると起動と停止ができます。

  • sudo service webiopi start     (起動)
  • sudo service webiopi stop    (停止)

起動しているか停止しているかを調べるのは、

  • ps ax | grep webiopi

を実行してください。起動している場合は、複数行が、起動していない場合は、1行のみ表示されます。(数字は時と場合により異なります。)

WebIOPiの自動起動

WebIOPiを自動起動するときは、

  • sudo systemctl enable webiopi

自動起動が不要になったときは、

  • sudo systemctl disable webiopi

とターミナルから入力します。

設定ファイルの変更

ターミナルで、sudo leafpad /etc/webiopi/config と入力し、[SCRIPTS]セクションのmyscriptを次のように書き換えます。コメントアウト # も外してください。1行追加する様になると思います。(下の赤線部分)

黄色センのpasswd-fileをコメントアウトすると、ウェブアクセスしたときにパスワードは聞かれなくなります。

ファイルの配置

/usr/share/webiopi/htdocs/bme280 の中に「index.html」「javascript.js」「script.py」「styles.css」の各ファイルを保存します。jsフォルダには、「require.js」が保存してあります。

 

 

index.html

 
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no">
		<title>温度センサ(DS20B18)による温度の取得</title>
		<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22js%2Frequire.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
		<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3E%0A%09%09%09require(%5B%22%2Fwebiopi.js%22%2C%20%22javascript.js%22%5D%2C%20function()%7B%0A%20%20%20%20%09%09%09webiopi().ready(%20initialize_webiopi%20)%3B%0A%09%09%09%7D)%3B%0A%09%09%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
	</head>
	<body>
		<div align="center">
		<h4>温度センサ(DS20B18)により取得した温度を表示しています</h4>
		温度センサー0: <input type="text" id="temp_text_0">℃<br><br>
		温度センサー1: <input type="text" id="temp_text_1">℃
	    </div>
	</body>
</html>

styles.css

#temp_text_0{
    width: 4em;
	/*height:3em;*/
	font-size: 2em;
}
#temp_text_1{
    width: 4em;
	/*height:3em;*/
	font-size: 2em;
}
body {
	background-color: #fffac2
}

javascript.js

// millisミリ秒ごとに温度を取得する関数
function getTempPeriodic(millis){
    // responseに温度が格納されている
    var drawTemp = function(macro, args, response){
        var temp = response.split(',');               // response は文字型 "*.???,*.???" ','で文字列を分割
        $("#temp_text_0").val(temp[0]);               // temp_text_0 にtemp[0]を代入し表示
		$("#temp_text_1").val(temp[1]);               // temp_text_1 にtemp[1]を代入し表示
    }
	

    // script.py内のgetTemp関数を実行。終了後にdrawTemp関数を呼ぶ
    webiopi().callMacro("getTemp", [] , drawTemp);

    // millisミリ秒後に自分自身を呼び出す
    setTimeout(function(){ getTempPeriodic(millis); }, millis);
}

function initialize_webiopi(){
    // webiopiの準備が終わってからstyles.cssを適用する
    applyCustomCss('styles.css');
    // 2秒ごとに温度を取得して描画
    getTempPeriodic(2000);
    // GPIOの状態を監視しない(自分で作成した関数で温度を定期的に取得するため)
    webiopi().refreshGPIO(false);
}

function applyCustomCss(custom_css){
    var head = document.getElementsByTagName('head')[0];
    var style = document.createElement('link');
    style.rel = "stylesheet";
    style.type = 'text/css';
    style.href = custom_css;
    head.appendChild(style);
}

script.py

# -*- coding: utf-8 -*-
import webiopi
import os
import glob
import time
import subprocess

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

webiopi.setDebug()

#temp_c=0.00


base_dir = '/sys/bus/w1/devices/'                   #DS18B20のデータが保存されるディレクトリー
#device_folder = glob.glob(base_dir + '28*')[0]
device_folder = glob.glob(base_dir + '28*')         #センサーごとのディレクトリーをリスト形式で取得 センサーが複数ある可能性があるため
ch_length = len(device_folder)                      #センサーの個数を取得
temp= [0.00]*ch_length                              #センサーの個数分のリスト形式のtempを作成
#device_file = device_folder + '/w1_slave'

#-----/sys/bus/w1/devices/28*/w1_slave の中身---------------------
#    b1 01 4b 46 7f ff 0f 10 8d : crc=8d YES
#    b1 01 4b 46 7f ff 0f 10 8d t=27062
#-----------------------------------------------------------------

def read_temp_raw(ch):                              #センサーごとに作成されるファイルの読み取り chは0,1,2,3,...
    device_file = device_folder[ch] + '/w1_slave'   #センサーごとに作成されるファイル名の取得
    catdata = subprocess.Popen(['cat',device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)   #Linuxのコマンド cat を使ってファイルの中身を取得 サブプロセス
    out,err = catdata.communicate()                 #サブプロセスの終了を待って標準出力と標準エラー出力を取得
    out_decode = out.decode('utf-8')                #バイト列を文字列に変換
    lines = out_decode.split('\n')                  #改行で区切り、lines リスト型に代入
    return lines                                    #戻り値 リスト型

def read_temp(ch):                                  #linesから温度を読み取る関数 chは0,1,2,3,...
    lines = read_temp_raw(ch)                       #linesの取得
    while lines[0].strip()[-3:] != 'YES':           #linesの最初のデータの空白を取り除き最後の3文字が'YES'でないとき
        time.sleep(0.2)                             #0.2秒待つ
        lines = read_temp_raw(ch)                   #再度linesを取得
    equals_pos = lines[1].find('t=')                #2行目の't='の位置を取得
    if equals_pos != -1:                            #'t='の位置が-1でなければ 見つかった時
        temp_string = lines[1][equals_pos+2:]       #'t='の位置の2文字目以降の文字列を取得
        temp_c = float(temp_string) / 1000.0        #浮動小数点型に変換して、1000で除算 摂氏温度に変換
        #temp_f = temp_c * 9.0 / 5.0 + 32.0
        #return temp_c, temp_f
        return temp_c                               #戻り値 摂氏温度
    
def setup():
    webiopi.debug("Script with macros - Setup")     #デバッグ出力を利用
    
def loop():                                         # WebIOPiが起動している間、繰り返し呼ばれる関数
    #global temp_c
    #temp_c=read_temp(0)
    webiopi.sleep(1)
    
def destroy():                                      # WebIOPi終了時に呼ばれる関数
    webiopi.debug("Script with macros - Destroy")

@webiopi.macro                                      #Javascriptから呼ばれる関数
def getTemp():
    temp_c = "{0:.3f},{1:.3f}".format(read_temp(0),+read_temp(1))     #0チャンネンルと1チャンネルを小数点以下3桁に整えて','で区切る 文字列としてtemp_cに代入
    return temp_c                                   #戻り値

最後にターミナルから、ifconfig でラズパイのIPアドレスを調べ、ブラウザから、

http://192.168.1.23:8000/bme280/

と入力してください。IPアドレスはifconfigで調べた数値です。ポートもデフォルトが8000です。

スマホのスクリーンショットです。