前回の続き
hemus.hatenablog.com
開発
プログラム改修
要点
cron で毎時 0, 15, 30, 45 分に実行するよう変更
sheet1 にデータを蓄積
最終行に追加する手間がかかるため3行目に行追加するよう変更。2行目は数式が埋め込んであるためあえて3行目にしている。
sheet2 に最新のデータを登録
cron
0,15,30,45 * * * * /root/develop/run.sh
import sys
import datetime
import logging
import binascii
from bluepy.btle import Scanner, DefaultDelegate, BTLEDisconnectError
import requests
import gspread
from oauth2client.service_account import ServiceAccountCredentials
logging.basicConfig(level=logging.ERROR)
key_name = '{ jsonファイルを指定 }'
book_name = '{ Spreadsheet のファイル名 }'
sheet_name = '{ Spredsheet のシート名 }'
sheet_name2 = '{ Spredsheet のシート名2 }'
scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name(key_name, scope)
gc = gspread.authorize(credentials)
worksheet = gc.open(book_name).worksheet(sheet_name)
worksheet2 = gc.open(book_name).worksheet(sheet_name2)
class ScanDelegate(DefaultDelegate):
def __init__(self, addr, name, no):
DefaultDelegate.__init__(self)
self.addr = addr
self.name = name
self.no = no
self.processed_devices = set()
def handleDiscovery(self, dev, isNewDev, isNewData):
if dev.addr != self.addr:
return
if dev.addr in self.processed_devices:
return
for (adtype, desc, value) in dev.getScanData():
if(adtype == 22):
servicedata = binascii.unhexlify(value[4:])
battery = servicedata[2] & 0b01111111
self.writeSpreadsheet(self.name, timestamp, battery, temp,
humid, self.no)
self.processed_devices.add(dev.addr)
return
elif(adtype == 255):
madata = binascii.unhexlify(value[16:])
humid = madata[4] & 0b01111111
temp = (madata[2] & 0b00001111) / 10 + (madata[3] & 0b01111111)
isOverZero=(madata[3]&0b10000000)
if not isOverZero:
temp = -temp
continue
else :
continue
def writeSpreadsheet(self, name, timestamp, battery, temp, humid, no):
worksheet.insert_row([name, timestamp, temp, humid], 3)
worksheet2.update_cell(1 + no, 1, name)
worksheet2.update_cell(1 + no, 2, timestamp)
worksheet2.update_cell(1 + no, 3, battery)
worksheet2.update_cell(1 + no, 4, temp)
worksheet2.update_cell(1 + no, 5, humid)
def scan(addr, name, no):
scanner = Scanner().withDelegate(ScanDelegate(addr, name, no))
try:
scanner.scan(20)
except BTLEDisconnectError as e:
pass
except Exception as e:
logging.error("Error during scanning: %s", e)
def main():
global timestamp
timestamp = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:00")
scan("xx:xx:xx:xx:xx:x1", "名称1")
scan("xx:xx:xx:xx:xx:x2", "名称2")
scan("xx:xx:xx:xx:xx:x3", "名称3")
if __name__ == "__main__":
main()
sheet1
蓄積データ。列 E,F,G はグラフ表示用に数式を設定。
sheet2
最新データ
グラフの作成
蓄積データについては気温、湿度それぞれでピボットテーブルを作ってグラフを作成する。
最新データも同様。
グラフのサイズを良い感じにし、インタラクティブに公開できるので設定、iframe を取得する。
Google ChartsをQuickにStartする https://www.i-ryo.com/entry/2018/12/10/073520
「スプレッドシートのグラフは簡単に埋め込みできる」の項目を採用。
「Google ChartsをQuickにStart」の項目は、複数のチャートを表示することができず諦めた。
html の作成
取得した iframe を配置し、キャッシュなし、自動リロード設定。
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="refresh" content="300">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SwitchBot Meter</title>
</head>
<body style="background-color:#2c2f38;">
<iframe width="299" height="106" seamless frameborder="0" scrolling="no" src="hogehoge"></iframe>
~省略~
</body>
</html>
完成