温度センサー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="<script>" title="<script>" /> <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="<script>" title="<script>" /> </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アドレスを調べ、ブラウザから、
と入力してください。IPアドレスはifconfigで調べた数値です。ポートもデフォルトが8000です。
スマホのスクリーンショットです。