おうちでウエザーステーション


mruby on YABMなモジュールからThingSpeakに投げていたデータを宅内のFreeBSD/mipsで動かしているsqlite3に入れてChart.js 2.xで表示できるようにしてみました。

sqlite3に入れるcgiはこんな感じです。

#!/usr/local/bin/mruby

params = {}
que = ENV['QUERY_STRING']
para = que.to_s.split('&')
para.each do |p|
  a = p.split('=')
  params[a[0]] = a[1]
end

t = params["field2"].to_f
a = params["field3"].to_f
h = params["field4"].to_f

db = SQLite3::Database.new('/tmp/ouchi2.db')
tc =  db.execute('select count(*) from sqlite_master where type="table" and name="wsmst"').next[0]
if tc == 0
  db.execute_batch('create table wsmst(date TEXT, time TEXT, temp REAL, atmo REAL, humi REAL)')
end
db.execute_batch('insert into wsmast(date, time, temp, atmo, humi) values(?, ?, ?)', t.to_s, a.to_s, h.to_s)

print "Content-type: text/html\n\n"

print "OK"

1分おきにuploadしているのですが、1時間毎に平均を取って別のテーブルに移すようにしてみました。ストレージはメモリディスクで小さいので元のデータは消します。


#!/usr/local/bin/mruby

sql = 'select date, time,round(avg(temp), 2),round(avg(atmo), 2) ,round(avg(humi), 2)  from ws where substr(time(time), 1, 2) != ? group by substr(time, 1, 2) order by date'

val = Array.new

now = Time.now.utc.hour
if now < 10
nowstr = "0" + now.to_s
else
nowstr = now.to_s
end

i = 0
db = SQLite3::Database.new('/tmp/ouchi2.db')
db.execute(sql, nowstr) do |row, fields|
val[i] = row
i = i + 1
end

tc =  db.execute('select count(*) from sqlite_master where type="table" and name="wsmst"').next[0]
if tc == 0
  db.execute_batch('create table wsmst(date TEXT, time TEXT, temp REAL, atmo REAL, humi REAL)')
end


i = 0
while val[i] != nil
  db.execute_batch('insert into wsmst(date, time, temp, atmo, humi) values(?, ?, ?, ?, ?)', val[i][0], val[i][1][0,2] + ":00:00", val[i][2].to_s, val[i][3].to_s, val[i][4].to_s)
i = i + 1
end

db.execute_batch('delete from ws where substr(time(time), 1, 2) != ?', nowstr)

これをjsonにしてchart.jsで表示します。集計済みのデータに現在の時間の平均値を足しています。

#!/usr/local/bin/mruby

db = SQLite3::Database.new('/tmp/ouchi2.db')

val = Array.new

i = 0
sel = "select date(datetime(date,time,'localtime')),time(datetime(date,time,'localtime')),temp,atmo,humi from (select * from wsmst order by date desc, time desc limit 48) as A order by date, time"
db.execute(sel) do |row, fields|
  val[i] = row
  i = i + 1
end

print "Content-type: text/html\n\n"

i = 0
print "["
while val[i] != nil do
  if i != 0
    print ","
  end
  print "{"
  print "\"time\":\"" + val[i][1][0,5] + "\",\"temp\":" + val[i][2].to_s
  print ",\"humi\":" + val[i][3].to_s + ",\"atmo\":" + val[i][4].to_s
  print "}"
  i = i + 1
end

cval = Array.new

i = 0
sel = "select date(datetime(date,time,'localtime')),time(datetime(date,time,'localtime')),round(avg(temp), 2),round(avg(atmo), 2) ,round(avg(humi), 2) from ws"
db.execute(sel) do |row, fields|
  cval[i] = row
  i = i + 1
end

i = 0
while cval[i] != nil do
  print ",{"
  print "\"time\":\"" + cval[i][1][0,5] + "\",\"temp\":" + cval[i][2].to_s
  print ",\"humi\":" + cval[i][3].to_s + ",\"atmo\":" + cval[i][4].to_s
  print "}"
  i = i + 1
end

print "]"

湿度のプロットも入れてみました。

日付は下に入れたかったのですが、わからなかったので、とりあえずtitleで入れました。

Chart.jsバージョン2.9からサポートされたfloat barで最高最低気温と平均気温をグラフにしてみました。

行き過ぎたIoTには懐疑的で、データーも地産地消が正しいと思います。