
なぜ「手動の温度管理」はあなたのビジネス(人生)を密かに破壊するのか?
「今日も現場の温度、大丈夫だろうか…」
この記事を開いたあなたは、おそらくそんな微かな不安を毎日、無意識に抱えているはずです。 「今のところ問題は起きていない。でも、もし異常が起きたとき、自分は真っ先に気づけるだろうか?」
その「見えないリスクへの予期不安」が、あなたの貴重な集中力を少しずつ削っています。
実は、多くの一流経営者や現場責任者が、あなたと同じ悩みを抱えていました。そして、彼らが最後に行き着いた答えが、この記事で公開する「デバイス代だけで構築できる、プロに頼めば効果なデバイスとシステムの構築で数十万クラスの管理システム」です!
アプリ確認の「1日3分」が奪い去る、年間18時間の集中力

「アプリを開いて確認するだけ」という行為は、実は脳に大きな負荷をかけています。確認を忘れた時のリスク、そして「異常に気づけない」という不安。これらはすべて、あなたのパフォーマンスを低下させるノイズです。
SwitchBotの標準アプリも優秀ですが、複数の拠点を一気に、かつグラフや詳細な指標で確認するには不向きです。
「わざわざ見に行く」から「勝手にお知らせが届く」へ。 このスイッチひとつで、あなたの自由時間は劇的に増えます。
SwitchBot温度・湿度計プラス×APIが「最強の投資」と言い切れる理由

他社製品が数万円する中、数千円でこの「精度」と「API開放」は異常です。本記事では、この家庭用ガジェットを「工場の心臓部」に変える魔法を教えます。
LINE Notifyの限界を突破!「新バージョン」の圧倒的付加価値
他社製の業務用センサーが数万円〜十数万円する中、数千円の「SwitchBot温湿度計プラス」の精度と、API(システムの窓口)が開放されている点は、もはや異常とも言えるコスパです。
LINE Notifyの終焉、そして「Messaging API」への進化
これまで多くのブログで紹介されていた「LINE Notify」は、2025年3月31日をもってサービスが終了します。今から作るなら、LINE Messaging API(公式アカウント)一択です。
本ガイドでは、最新規格に対応した「一生モノ」のシステムを構築します。
スマホで見惚れる「ダッシュボード型レポート」

文字だけの機械的な通知はもう終わりです。 スマホを開いた瞬間、Looker Studioを彷彿とさせる「針が動くメーター」と「24時間の時系列推移表」が目に飛び込んできます。
さらに、プロの現場で必須の指標である「絶対湿度(g/m³)」と「飽差(VPD)」も自動計算して表示。
カビの発生リスクやウイルスの生存率、植物の成長環境まで、0.1秒で状況を判断できる視認性。これこそが、真のDXです。
ちなみに細かいレポートはLooker Studioで見るようにしています。
【知識不要!コピペで実装】Switchbot APIで実現する温湿度管理の自動化 | Google連携からLINE通知までAIを活用してIoT化でシステム構築
【完全図解】LINE Messaging APIと連携するための3ステップ
ここからは、実際の操作画面をイメージしながら進めてください。
LINE公式アカウントの作成とAPIの有効化
LINE Developers にアクセスし、個人のLINEアカウントでログインします。
「プロバイダー」を新規作成(名前は「MyDX」など何でもOK)。
「Messaging API」を新規作成。チャネル名(Botの名前)を決めます。
作成後、「Messaging API設定」タブの一番下にある「チャネルアクセストークン(長期)」を発行してメモ(コピー)してください。これがコードの LINE_TOKEN になります。

SwitchBot APIの解放
SwitchBot APIの解放
アプリの「プロフィール」>「設定」>「アプリバージョン」を10回連打して開発者モードを出現。
「開発者オプション」から「トークン」と「シークレット」をコピー。
ついでに、管理したいデバイスのデバイスIDもここで確認しておきます。
【秘策】「グループID」を一瞬で特定する
LINE Notifyと違い、送り先のIDを特定するのが少し大変ですが、本記事のコードには「IDを自動返信してくれるデバッグ機能」を盛り込んでいます。Botをグループに招待して一言しゃべれば、IDが届きます。これが
LINE_DESTです。
SwitchBot API v1.1の認証設定
最新のv1.1では「シークレットトークン」が必要です。
隠しメニュー「開発者モード」を解放する
SwitchBotアプリの「プロフィール」>「設定」>「アプリバージョン」を10回連打します。
出現した「開発者オプション」を開き、「トークン」と「シークレット」をメモします。
【コピペで完成】GAS(Google Apps Script)の実装
用意したGoogleスプレッドシートを開きます。
上部メニューの 「拡張機能」>「Apps Script」 をクリック。
最初から入力されている文字をすべて消して、記事末尾にある 「黄金コード」 をすべて上書きで貼り付け、保存(Ctrl+S)してください。
/* ==========================================
1. 設定エリア(ここをご自身の情報に書き換えるだけ!)
========================================== */
const LINE_TOKEN = '取得したLINEトークンをここに';
const LINE_DEST = '最初は空でOK(下記の手順で特定します)';
const SB_TOKEN = 'SwitchBotトークンをここに';
const SB_SECRET = 'SwitchBotシークレットをここに';
const SPREADSHEET_ID = 'スプレッドシートのIDをここに';
const SHEET_NAME = 'シート名'; // 例:エリア1
// 管理したいデバイスの名前とIDを登録(何台でもOK)
const DEVICE_LIST = [
{ name: "エリア1", id: "デバイスID" },
{ name: "エリア2", id: "デバイスID" }
];
/* ==========================================
2. 魔法のセットアップ(1回実行するだけでOK)
========================================== */
/**
* これを実行すると、1分おきのデータ収集と、毎朝の定期レポート通知が予約されます。
*/
function setupSystem() {
const triggers = ScriptApp.getProjectTriggers();
triggers.forEach(t => ScriptApp.deleteTrigger(t));
// 1分ごとにデータを取得して記録
ScriptApp.newTrigger('getSwitchBotData').timeBased().everyMinutes(1).create();
// 毎日朝8時にLINEレポートを送信(時間は自由に変えられます)
ScriptApp.newTrigger('sendPremiumDashboard').timeBased().atHour(8).nearMinute(0).everyDays(1).create();
console.log("セットアップ完了!監視の旅が始まりました。");
}
/* ==========================================
3. データ収集 & プロ用指標の計算
========================================== */
function getSwitchBotData() {
const ss = SpreadsheetApp.openById(SPREADSHEET_ID);
const sheet = ss.getSheetByName(SHEET_NAME);
const now = new Date();
const dateStr = Utilities.formatDate(now, "Asia/Tokyo", "yyyy/MM/dd");
const timeStr = Utilities.formatDate(now, "Asia/Tokyo", "HH:mm");
const rows = [];
DEVICE_LIST.forEach(device => {
try {
const status = getDeviceStatusFromAPI(device.id);
if (!status) return;
const temp = status.temperature;
const humi = status.humidity;
const vpd = calculateVPD(temp, humi); // 飽差(kPa)
const absHumi = calculateAbsHumi(temp, humi); // 絶対湿度(g/m3)
rows.push([device.name, device.id, dateStr, timeStr, temp, humi, absHumi, vpd, status.battery || 100]);
} catch (e) { console.log(device.name + "取得失敗"); }
});
if (rows.length > 0) {
sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, rows[0].length).setValues(rows);
}
}
// 絶対湿度の計算ロジック
function calculateAbsHumi(t, h) {
const e = 6.11 * Math.pow(10, (7.5 * t) / (t + 237.3));
return (217 * e / (t + 273.15) * (h / 100)).toFixed(2);
}
// 飽差(VPD)の計算ロジック
function calculateVPD(t, h) {
const svp = 0.61078 * Math.exp((17.27 * t) / (t + 237.3));
return (svp * (1 - h / 100)).toFixed(2);
}
/* ==========================================
4. LINE Flex Message送信(デザインの核心)
========================================== */
function sendPremiumDashboard() {
const sheet = SpreadsheetApp.openById(SPREADSHEET_ID).getSheetByName(SHEET_NAME);
const allData = sheet.getDataRange().getValues();
DEVICE_LIST.forEach(device => {
const deviceRows = allData.filter(row => String(row[0]).trim() === device.name);
if (deviceRows.length === 0) return;
const current = deviceRows[deviceRows.length - 1]; // 最新データ
const dateStr = Utilities.formatDate(current[2], "Asia/Tokyo", "yyyy/MM/dd");
// 1時間ごとの履歴を生成
const hourlyMap = {};
deviceRows.filter(r => Utilities.formatDate(r[2], "Asia/Tokyo", "yyyy/MM/dd") === dateStr).forEach(r => {
const h = getHHmm(r[3]).split(":")[0] + ":00";
if (!hourlyMap[h]) hourlyMap[h] = r;
});
const history = Object.keys(hourlyMap).sort().map(k => hourlyMap[k]).slice(-24);
// メーター画像生成(QuickChart API)
const chart = (v, c, t) => `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify({
type: 'radialGauge', data: { datasets: [{ data: [v], backgroundColor: c }] },
options: { centerPercentage: 75, title: { display: true, text: t, fontSize: 18 } }
}))}`;
const flex = {
"type": "bubble", "size": "giga",
"header": { "type": "box", "layout": "vertical", "contents": [
{ "type": "box", "layout": "horizontal", "contents": [
{ "type": "text", "text": device.name + "管理", "weight": "bold", "color": "#f1c40f" },
{ "type": "text", "text": dateStr, "align": "end", "size": "xxs", "color": "#aaaaaa" }
]},
{ "type": "text", "text": "24時間 状況推移レポート", "weight": "bold", "size": "lg", "margin": "md" }
]},
"body": { "type": "box", "layout": "horizontal", "spacing": "md", "contents": [
{ "type": "box", "layout": "vertical", "flex": 4, "contents": [
{ "type": "image", "url": chart(current[4], '#ff7675', `温 ${current[4]}℃`), "size": "full", "aspectRatio": "1:1" },
{ "type": "image", "url": chart(current[5], '#3498db', `湿 ${current[5]}%`), "size": "full", "aspectRatio": "1:1" },
{ "type": "box", "layout": "vertical", "margin": "md", "contents": [
{ "type": "text", "text": "VPD / 絶対湿度", "size": "xxs", "color": "#aaaaaa", "align": "center" },
{ "type": "text", "text": `${current[7]}kPa / ${current[6]}g`, "weight": "bold", "size": "sm", "align": "center" }
]}
]},
{ "type": "box", "layout": "vertical", "flex": 6, "backgroundColor": "#f8f9fa", "paddingAll": "8px", "cornerRadius": "md", "contents": [
{ "type": "box", "layout": "horizontal", "contents": [
{ "type": "text", "text": "時刻", "size": "xxs", "color": "#999999", "flex": 3 },
{ "type": "text", "text": "温度", "size": "xxs", "color": "#999999", "align": "center", "flex": 3 },
{ "type": "text", "text": "湿度", "size": "xxs", "color": "#999999", "align": "end", "flex": 3 }
]},
{ "type": "separator", "margin": "xs" },
{ "type": "box", "layout": "vertical", "spacing": "xs", "margin": "sm", "contents":
history.map(r => ({
"type": "box", "layout": "horizontal", "contents": [
{ "type": "text", "text": getHHmm(r[3]), "size": "xxs", "flex": 3 },
{ "type": "text", "text": r[4] + "℃", "size": "xxs", "color": "#d63031", "align": "center", "flex": 3 },
{ "type": "text", "text": r[5] + "%", "size": "xxs", "color": "#0984e3", "align": "end", "flex": 3 }
]
}))
}
]}
]}
};
UrlFetchApp.fetch('https://api.line.me/v2/bot/message/push', {
method: 'post', contentType: 'application/json',
headers: { Authorization: 'Bearer ' + LINE_TOKEN },
payload: JSON.stringify({ to: LINE_DEST, messages: [{ type: "flex", altText: "定期レポ", contents: flex }] })
});
});
}
/** ユーティリティ系関数 */
function getDeviceStatusFromAPI(id) {
const t = Date.now().toString(), nonce = Utilities.getUuid();
const data = SB_TOKEN + t + nonce;
const sign = Utilities.base64Encode(Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_256, data, SB_SECRET)).toUpperCase();
const res = UrlFetchApp.fetch(`https://api.switch-bot.com/v1.1/devices/${id}/status`, {
headers: { "Authorization": SB_TOKEN, "sign": sign, "nonce": nonce, "t": t }
});
const json = JSON.parse(res.getContentText());
return (json.statusCode === 100) ? json.body : null;
}
function getHHmm(v) {
if (v instanceof Date) return Utilities.formatDate(v, "Asia/Tokyo", "HH:mm");
const m = String(v).match(/\d{1,2}:\d{2}/);
return m ? m[0] : "00:00";
}ここからが本番!「3ステップ」ボタン操作ガイド
貼り付けたあと、画面上部の「実行」ボタンの左側にあるドロップダウンメニュー(初期状態では setupSystem などと書かれている場所)に注目してください。
① まずは「トークン」だけ貼り付ける
コードの最初の数行にある、以下の場所にあなたのトークンを貼り付け、一度保存してください。
SPREADSHEET_ID(スプレッドシートのURLから抜き出した英数字)
LINE_TOKEN(LINE公式アカウントのもの)
SB_TOKEN / SB_SECRET(SwitchBotアプリで取得したもの)
② 【実行1】checkMyIDs を選んで「実行」する
メニューから checkMyIDs を選んで実行ボタンを押してください。※初回は「承認」を求められるので、すべて許可してください。
すること: 表示されたIDをコピーし、コード内の DEVICE_LIST という場所に貼り付け直して保存します。
何が起きる?: 画面下の「実行ログ」に、あなたの持っているすべての温湿度計の名前とIDが一覧表示されます。
③ 【実行2】Botに「テスト」と送って送信先IDを特定する
LINE公式アカウントを自分のLINEに追加し、そのグループやトークで一言「テスト」などと送ってください。
すること: その文字をコピーして、コード内の LINE_DEST に貼り付けて保存します。
何が起きる?: Botが即座に「このチャットのIDです:Ccf5…」という暗号のような文字を返信してくれます。
④ 【実行3】setupSystem を選んで「実行」する
最後に、メニューから setupSystem を選んで実行ボタンを1回だけ押してください。
何が起きる?
1分おきにSwitchBotのデータを記録し続ける設定(監視開始)
毎日決まった時間に豪華なデザインレポートを送る設定
これらすべてが自動的に予約されます。
あなたがGASの画面やコードを見る必要はありません。 1分ごとにスプレッドシートには「温度・湿度・絶対湿度・飽差」のプロ級データが蓄積され続け、毎朝決まった時間にあなたのスマホへ、見惚れるような美しいレポートが届きます。
万が一、自動実行を止めたいときは?
メニューから stopAllTriggers を選んで実行してください。すべての予約が安全に解除されます。
まとめ
「自分には難しそう」と感じましたか? ご安心ください。コードを貼り付け、「実行」ボタンをクリックした瞬間、あなたのスマホは「24時間、不眠不休で現場を見守る有能な部下」に変わります。
数千円の投資で手に入る「安心感」と、自動化によって生まれる新しい「時間」。 さあ、あなたも今すぐSwitchBotを手に入れて、次世代の管理システムをその手にしてください!












