takeru が 2021年05月09日19時45分11秒 に編集
コメント無し
メイン画像の変更
本文の変更
# SwitchBot温湿度計 高くて2000円、セールなら1000円ぐらいで買えるこれ https://qiita.com/takeru@github/items/f42381e8482c3bf484e7 BLEで温度湿度を取れるので、Obnizでも温度湿度を取れるようにしました。
ObnizはBLEとWebにつなぐのが得意なようなので、BLEでデータ取得+ブラウザに表示します。
ObnizはBLEとWebにつなぐのが得意なので、BLEでデータ取得+ブラウザに表示します。
@[youtube](https://youtu.be/NJ9dZTrkrrg)
# 部品 - obniz Board 1Y https://amzn.to/2Ss7iBt - SwitchBot温湿度計 https://amzn.to/3tyvwaf
# ソースコード ```html:SwitchBot温湿度計 <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" /> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://unpkg.com/obniz@3.x/obniz.js" crossorigin="anonymous" ></script> <style> @font-face { font-family: "DESG"; src: url("data:application/font-woff; charset=utf-8; base64,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") format("woff2"); // Font "DSEG" by けしかん } .meter { display: inline-block; } .outer { border: black solid 3px; border-radius: 15px; width: 300px; height: 300px; padding: 40px; margin: 20px; background-color: aliceblue; } .inner .temperature { margin: 0 0 0 30px; } .inner .humidity { margin: 0 0 0 30px; } .inner .address { font-size: 6px; } .inner { border: black solid 3px; border-radius: 5px; height: 100%; background-color: darkseagreen; font-family: "DESG"; font-size: 60px; }; </style> </head> <body> <div id="obniz-debug"></div> <h4></h4> <div id="meters"> <div id="template" class="meter" style="display:none;"> <div class="outer"> <div class="inner"> <div class="temperature">12.3</div> <div class="line"></div> <div class="humidity">45</div> <span class="address">xxxx</span> </div> </div> </div> </div> <script> const obniz = new Obniz("OBNIZ_ID_HERE"); const known_meters = { "d6091889b956": "Meter02", "fffbc4aa4ff5": "Meter03", "ee33dc9c7261": "Meter01" }; const log = (s)=>{ console.log((new Date()).toISOString()+" "+s); }; const status = (s)=>{ $('h4').html(s); log(s); }; const data = {}; const onfind_meter = function(peripheral){ const find_servicedata = () => peripheral.advertise_data_rows.find(r => r[0]==22 && r[1]==0 && r[2]==13); let servicedata = find_servicedata(); if(servicedata){ servicedata = servicedata.slice(3); const battery = servicedata[2] & 0b01111111; const isTemperatureAboveFreezing = servicedata[4] & 0b10000000; let temperature = ( servicedata[3] & 0b00001111 ) / 10.0 + ( servicedata[4] & 0b01111111 ); if(!isTemperatureAboveFreezing){ temperature = -temperature; } const humidity = servicedata[5] & 0b01111111; const isEncrypted = ( servicedata[0] & 0b10000000 ) >> 7; const isDualStateMode = ( servicedata[1] & 0b10000000 ) >> 7; const isStatusOff = ( servicedata[1] & 0b01000000 ) >> 6; const isTemperatureHighAlert = ( servicedata[3] & 0b10000000 ) >> 7; const isTemperatureLowAlert = ( servicedata[3] & 0b01000000 ) >> 6; const isHumidityHighAlert = ( servicedata[3] & 0b00100000 ) >> 5; const isHumidityLowAlert = ( servicedata[3] & 0b00010000 ) >> 4; const isTemperatureUnitF = ( servicedata[5] & 0b10000000 ) >> 7; log(peripheral.address+" "+battery+" "+temperature+" "+humidity); data[peripheral.address] = {"a": peripheral.address, "t": temperature, "h": humidity, "b": battery}; if (!Obniz.App.isCloudRunning()) { updateUI(); } /* console.log("----\n"); console.log("address: %s\n", peripheral.address); console.log("battery: %d\n", battery); console.log("temperature: %.1f\n", temperature); console.log("humidity: %d\n", humidity); console.log("\n"); console.log("isEncrypted: %d\n", isEncrypted); console.log("isDualStateMode: %d\n", isDualStateMode); console.log("isStatusOff: %d\n", isStatusOff); console.log("isTemperatureHighAlert: %d\n", isTemperatureHighAlert); console.log("isTemperatureLowAlert: %d\n", isTemperatureLowAlert); console.log("isHumidityHighAlert: %d\n", isHumidityHighAlert); console.log("isHumidityLowAlert: %d\n", isHumidityLowAlert); console.log("isTemperatureUnitF: %d\n", isTemperatureUnitF); console.log("----\n"); */ } }; const scan_meter = async function(){ let target = null; // target = {"deviceAddress":[ // "d6091889b956", // Meter02 // "fffbc4aa4ff5", // Meter03 // ]}; let scanSeconds; if (Obniz.App.isCloudRunning()) { scanSeconds = 20; }else{ scanSeconds = null; } const setting = { duration: scanSeconds, duplicate: true, filterOnDevice: false }; status("Scanning"); const peripherals = await obniz.ble.scan.startAllWait(target, setting); //var peripherals = [await obniz.ble.scan.startOneWait(target, setting)]; status("Finished"); }; function uniq(array) { return [...new Set(array)]; } const updateUI = ()=>{ keys = uniq([...Object.keys(known_meters), ...Object.keys(data)]); keys.forEach((k)=>{ const d = data[k] || {"a": k, "t": "--", "h": "--"}; console.log(k + " " + JSON.stringify(d)); let m = $("#meters #address-"+k); if(m.length==0){ let e = $("#meters #template").clone().attr("id", "address-"+k); $("#meters").append(e); e.show(); m = $("#meters #address-"+k); } $(".address", m).html(d["a"]); $(".temperature", m).html(d["t"]); $(".humidity", m).html(d["h"]); }); }; obniz.onconnect = async function() { status("Obniz Connected"); await obniz.ble.initWait(); status("Init"); obniz.ble.scan.onfind = onfind_meter; updateUI(); } obniz.onloop = async function() { status("Loop"); await scan_meter(); if (Obniz.App.isCloudRunning()) { Obniz.App.done({ status: 'success', text: JSON.stringify(data) }) } //status("Wait"); //await obniz.wait(10 * 1000); }; </script> </body> </html> ```