ESP8266で収集したデータを表示させる(CanvasJS編)

ESP8266でBME280のデータを収集して、MQTTでWebARENAに送れるようになりました。となれば、もう表示するしかないです。

というわけで表示させてみたのがこちらです。(ホスト名は違いますからねー)

温度や湿度はエアコンの動作に伴って周期的に上下を繰り返しています。室温が高めに出ていますが、これはESP8266が載ったボード自体の発熱の影響です。BME280は離して取り付けるか、発熱を抑えるような工夫が必要です。

ESP8266からのデータは、MQTTをsubscribeしているPythonモジュールでデータを受け取って、MQTTのメッセージ(今回はJSONにしています)を解析、解析したデータを配列に入れたあと、その配列そのものを pickle モジュールでファイルに書き出しています。本来は負荷を考えるとデータベースにしたほうがいいのですが、基本的に外に公開する目的のものではないので、それでよしにしています。

hist  = {}	# 各端末ごとのデータを保持
hlen  = 24*60/4	# データを保持する数

def message(m):
	if m['mac'] not in hist :
		hist[m['mac']] = []
	hist[m['mac']].append((m['utime'],m['temp'],m['humidity'],m['pressure']))
	while len(hist[m['mac']]) > hlen :
		del(hist[m['mac']][0])

        # データをファイルに書き出し
	with open('bme280.pickle',mode='wb') as f:
		pickle.dump([hist,hlen],f)

def on_message(client, userdata, msg):
	s = msg.payload
	m = json.loads(s.decode('utf-8').replace('\'','"'))
	m['utime'] = int(m['utime'])
	m['temp'] = float(m['temp'])
	m['humidity'] = float(m['humidity'])
	m['pressure'] = float(m['pressure'])
	message(m)

表示については nginx から uWSGI 経由で要求を受け取ったら、Flask フレームワークを使って表示しています。冒頭のグラフは、個人のホビーユースでは無料で利用できる CanvasJS というモジュールで作ってみました。・・・が、よくよく見ると、メールで要求する必要があるとのこと。結構使い方簡単で良さげだったのですが・・・。

htmlテンプレートにデータの部分を除いたHTMLファイルを作成して、Flaskでデータの部分だけPythonで出力しています。もっといい方法があるのかもしれませんが、とりあえずこれで出しています。

Flaskで出力する部分はこんな感じです。

@bme280.route('/bme280')  # for BluePrint
def data():
	# データをファイルから読み出し
	def histimport():
		global hist,hlen
		with open('bme280/bme280.pickle',mode='rb') as f:
			[hist,hlen] = pickle.load(f)
	# 1枚分のデータ生成
	def makedata(idx):
		global hist,hlen
		# データ生成
		s = 'data: ['
		for k in hist :
			s += '{\n'
			s += 'name : "{}" ,\n'.format(k)
			s += 'showInLegend: true,\n'
			s += 'xValueType: "dateTime",\n'
			s += 'type: "line",\n'
			s += ('yValueFormatString : "#0.## °C",\n',
			      'yValueFormatString : "#0.## %",\n',
			      'yValueFormatString : "####.## hPa",\n')[idx]
			s += 'dataPoints : [\n'
			v = {}
			for t,v[0],v[1],v[2] in hist[k] :
				s += '{{ x: {} , y : {} }},'.format(t*1000,v[idx])
			s += ']},\n'
		s += ']'
		return(s)
	#
	histimport()
	html = render_template('bme280/bme280.html',	# for BluePrint
		data0 = makedata(0),
		data1 = makedata(1),
		data2 = makedata(2)
	)
	return html

意外に簡単にグラフ化することができました。

が、途中で書いたとおり、CanvasJSは個人のホビー利用でもメールでライセンス要求(だったかな?)が必要とのことで、使うのをやめました。(つづく)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)