- はじめに:IoTスマートリモコンの総仕上げ!ラズパイPico WとLINEを連携させよう
- Pico W単体では外から操作できない?「GAS」を使ったネットワーク構築の仕組み
- 中継サーバー構築:Google Apps Script (GAS) の設定とデプロイ手順
- LINE BotとGASを紐付ける!Webhook URLとLINE応答機能の設定
- ラズパイPico Wに最終プログラムを書き込む(Pythonコード公開)
- スマホからエアコン遠隔操作!PC不要の完全スタンドアロン化テスト
- 最終ステップ:PC不要で完全自動化!Pico Wにmain.pyを保存して独立稼働させる方法
- おわりに:手作りIoTで実現する愛犬のための快適・安心なスマートホーム
- 他のシリーズ
はじめに:IoTスマートリモコンの総仕上げ!ラズパイPico WとLINEを連携させよう
こんにちは、ニンジンです🥕
本記事は「愛犬を守る!格安IoT温湿度見守りLINE Botの作り方」の第5回になります。これまでの連載をまだお読みでない方は、ぜひ以下の記事からチェックしてみてくださいね。
全5回にわたってお届けしてきた「愛犬を守る!格安IoT温湿度見守りLINE Botの作り方」も、いよいよ今回が最終回です。

前回の第4回では、Raspberry Pi Pico W(ラズパイPico W)に電子部品を組み込み、エアコンの赤外線信号をハック(学習・発信)するハードウェア改造を行いました。 今回は、その完成した赤外線送信機を外の世界(LINE)と繋ぎ、スマホからいつでもどこでもエアコンを遠隔操作できる「完全自作スマートリモコン」へと進化させます!
PCの呪縛から解き放たれ、単体で24時間動き続ける真のIoTデバイスが完成する感動の瞬間を、ぜひ一緒に味わいましょう。
Pico W単体では外から操作できない?「GAS」を使ったネットワーク構築の仕組み
本格的な作業に入る前に、少しだけ「通信の仕組み」について解説します。 現在、Pico WからLINEへ「暑いよ!」と通知を送ることはできています。しかし、逆にスマホのLINEから「冷房をつけて!」とPico Wに直接命令を送ることは、簡単にはできません。
なぜなら、ご自宅のWi-Fiルーターには強力なセキュリティ(ファイアウォール)があり、外からの見知らぬアクセスをすべて弾いてしまうからです。 VPNや専用のWebサーバーを立てる方法もありますが、ハードルが高すぎますよね。そこで今回は、無料で使えるGoogle Apps Script(GAS)を「インターネット上の私書箱(中継サーバー)」として利用し、疑似的な双方向通信を実現します!

【今回の通信の流れ(仕組み)】
- [スマホ] からLINEに「冷房ON」と送る。
- [LINEのサーバー] が、ネット上の私書箱 [GAS] に「冷房ONの命令が来たよ」とメモを残す(Webhook機能)。
- 家の中にいる [Pico W] が、10秒ごとに [GAS] を覗きに行き(ポーリング)、「あ、命令が来てる!」と受け取って赤外線を発射する。
この「GASを経由したバケツリレー方式」を使えば、ルーターの設定を一切いじることなく、安全かつ確実に遠隔操作が可能になります!
中継サーバー構築:Google Apps Script (GAS) の設定とデプロイ手順
1.Google Apps Script (GAS) の作成
それでは、中継サーバーとなるGASの準備を進めましょう。

Googleドライブ( https://drive.google.com/ )にアクセスします。
// スクリプトプロパティ(GASの簡易データベース)を使って状態を管理します
const PROPERTY_KEY = 'AIR_CON_SIGNAL';
// 1. LINEからメッセージを受け取る関数 (Webhook)
function doPost(e) {
try {
const jsonString = e.postData.contents;
const data = JSON.parse(jsonString);
// LINEからのイベントを取得
const event = data.events[0];
if (event && event.type === 'message' && event.message.type === 'text') {
const userMessage = event.message.text;
const properties = PropertiesService.getScriptProperties();
// 送られてきたメッセージの内容によって、保存する命令(ステータス)を変える
if (userMessage.includes("冷房")) {
properties.setProperty(PROPERTY_KEY, "COOL_ON");
} else if (userMessage.includes("停止")) {
properties.setProperty(PROPERTY_KEY, "COOL_OFF");
} else if (userMessage.includes("現在の温度は")) {
properties.setProperty(PROPERTY_KEY, "GET_TEMP");
}
}
return ContentService.createTextOutput(JSON.stringify({status: 'post_success'}))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) {
return ContentService.createTextOutput(JSON.stringify({status: 'error', message: error.toString()}))
.setMimeType(ContentService.MimeType.JSON);
}
}
// 2. Pico Wから「命令ある?」と確認しにくる関数
function doGet(e) {
const properties = PropertiesService.getScriptProperties();
const currentSignal = properties.getProperty(PROPERTY_KEY) || "NONE";
// Pico Wに現在のステータスを返す
const responseData = { signal: currentSignal };
// 何かしらの命令(NONE以外)があったら、確認されたのでリセット(消去)する
if (currentSignal !== "NONE") {
properties.setProperty(PROPERTY_KEY, "NONE");
}
return ContentService.createTextOutput(JSON.stringify(responseData))
.setMimeType(ContentService.MimeType.JSON);
}
2.GAS のデプロイ(インターネット上に公開)
このコードを世界中(LINEやPico W)からアクセスできるように公開します。

各項目を以下のように設定してください。
- 説明: v1(何でもOK)
- ウェブアプリを実行: 自分
- アクセスできるユーザー: 全員(※Pico WやLINEがアクセスできるようにするため)
- 「デプロイ」ボタンを押します。
※初回は「アクセスの承認」を求められるので、「アクセスを承認」ボタンを押し、
ご自身のアカウントを選んで、詳細リンクから「PicoW_IR_Chaser(安全ではないページ)に移動」をクリックして許可してください。
LINE BotとGASを紐付ける!Webhook URLとLINE応答機能の設定
次に、LINEにメッセージが来たら、先ほど作ったGASに情報が飛ぶように紐付けを行います。
3.LINE DevelopersでのWebhook設定

LINE Developersにアクセスします。


- 「Messaging API設定」 タブを開き、下の方にある 「Webhook設定」 を探します。
- 「Webhook URL」 の項目に、先ほどコピーした GASの「ウェブアプリのURL」 を貼り付けて保存します。
- 保存後、「Webhookの利用」のスイッチをON にします。
4.LINE Official Account Managerでの応答設定
LINE Official Account Manager( https://manager.line.biz/ )にアクセスしてログインします。
ここまでできたら、中継サーバーの準備は完了です。
ラズパイPico Wに最終プログラムを書き込む(Pythonコード公開)

いよいよ大詰めです。
以下のコードを貼り付け、上部の設定項目(Wi-Fi情報、LINEのトークン、USER_ID、先ほど取得したGASのURL)をあなた自身のものに書き換えてください。
また、前回取得したエアコンの赤外線データ(数字のリスト)も指定の箇所に貼り付けます。
#main.py
import machine
import dht
import network
import time
import urequests
import json
import gc
# 起動時のパーツ立ち上がりを待つ(超重要!)
time.sleep(3)
# --- 1. ご自身の環境に書き換えてください ---
WIFI_SSID = "あなたのWi-Fi_SSID"
WIFI_PASSWORD = "あなたのWi-Fi_パスワード"
LINE_TOKEN = "あなたのLINE_チャンネルアクセストークン"
USER_ID = "あなたのLINE_ユーザーID"
# 🔴 先ほど取得したGASのウェブアプリURL
GAS_URL = "https://script.google.com/macros/s/XXXXX/exec"
# --- 2. 見守りとピンの設定 ---
ALERT_TEMP = 28 # 警告温度
CHECK_INTERVAL = 10 # チェック間隔(秒)
TX_PIN = 17 # 赤外線LEDピン
# --- 3. エアコン信号データ(※前回取得した数字のリストに書き換えてください) ---
COOL_ON_DATA = [4307, 4535, 480, 1667, ...]
COOL_OFF_DATA = [4368, 4507, 476, 1605, ...]
sensor = dht.DHT11(machine.Pin(15))
wlan = network.WLAN(network.STA_IF)
def connect_wifi():
wlan.active(True)
if not wlan.isconnected():
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
timeout = 15
while not wlan.isconnected() and timeout > 0:
time.sleep(1)
timeout -= 1
if not wlan.isconnected():
machine.reset()
def send_ir(data):
pwm = machine.PWM(machine.Pin(TX_PIN))
pwm.freq(38000)
def pwm_on(): pwm.duty_u16(21845)
def pwm_off(): pwm.duty_u16(0)
is_on = True
for us in data:
if is_on: pwm_on()
else: pwm_off()
time.sleep_us(us)
is_on = not is_on
pwm_off()
pwm.deinit()
def send_line(message):
response = None
try:
connect_wifi()
url = "https://api.line.me/v2/bot/message/push"
headers = {"Content-Type": "application/json; charset=UTF-8", "Authorization": f"Bearer {LINE_TOKEN}"}
payload = {"to": USER_ID, "messages": [{"type": "text", "text": message}]}
response = urequests.post(url, data=json.dumps(payload).encode('utf-8'), headers=headers)
except Exception:
pass
finally:
if response:
try: response.close()
except: pass
def check_gas_command():
response = None
try:
connect_wifi()
response = urequests.get(GAS_URL)
if response.status_code in [301, 302, 303, 307, 308]:
redirect_url = response.headers.get('location') if hasattr(response, 'headers') else None
response.close()
response = None
if redirect_url: response = urequests.get(redirect_url)
else: return "NONE"
text_data = response.text
if text_data.startswith('<'): return "NONE"
return json.loads(text_data).get("signal", "NONE")
except Exception:
return "NONE"
finally:
if response:
try: response.close()
except: pass
# --- メイン処理 ---
send_line("遠隔エアコン操作システムが起動しました!監視と命令待ちを開始します。")
alert_sent = False
error_count = 0
while True:
try:
sensor.measure()
temp = sensor.temperature()
humidity = sensor.humidity()
if temp >= ALERT_TEMP:
if not alert_sent:
send_line(f"【警告】室温が{temp}°Cになりました!エアコンを確認してください。(湿度: {humidity}%)")
alert_sent = True
else:
if alert_sent:
send_line(f"室温が{temp}°Cに下がりました。安全圏内です。")
alert_sent = False
cmd = check_gas_command()
if cmd == "COOL_ON":
send_ir(COOL_ON_DATA)
send_line(f"エアコンに冷房ON信号を送信しました。(現在の室温: {temp}°C)")
elif cmd == "COOL_OFF":
send_ir(COOL_OFF_DATA)
send_line(f"冷房OFFの信号を発信しました。(現在の室温: {temp}°C)")
elif cmd == "GET_TEMP":
send_line(f"現在のお部屋の状況です。\n温度: {temp}°C\n湿度: {humidity}%")
error_count = 0
except Exception:
error_count += 1
time.sleep(5)
if error_count >= 5: machine.reset() # 連続エラー時はシステム再起動
finally:
gc.collect() # メモリ解放
time.sleep(CHECK_INTERVAL)
💡🥕のワンポイント解説:なぜ今回のコードには「print文」が一つも無いのか?
これまでテスト用に使っていたコードには、動作確認のために print("冷房ONを検知しました") のような記述がたくさんありました。しかし、今回の本番用 main.py では、あえてこれらをすべて削除しています。
実はこれ、PCから切り離して単体動作(スタンドアロン化)させた際の「フリーズ」を防ぐための、非常に重要な工夫なんです!
PC(Thonny)に繋いでいる時は、print で出力されたテキストをPC側が受け取って画面に表示してくれます。しかし、PCから抜いてコンセントから直接給電した場合、テキストの「受け先」がいなくなってしまいます。 受け先がないまま print で出力し続けると、Pico Wの内部メモリ(バッファ)に送信待ちのテキストがどんどん溜まり続け、やがてメモリを圧迫してシステム全体がフリーズしてしまいます。
本番運用では print を完全に無くし、エラー処理(except)も pass で綺麗に流してあげることで、Pico Wの限られたメモリを「温湿度計測」と「通信」だけに100%集中させることができ、長期間の安定稼働が実現します。
スマホからエアコン遠隔操作!PC不要の完全スタンドアロン化テスト
まずはThonnyの再生ボタンを押して、エラーが出ないかテストします。 LINEに起動メッセージが届いたら、スマホから 「冷房ON」 や「停止」や 「現在の温度は」 と送信してみてください。エアコンから「ピッ」と音が鳴り、完了通知が返ってきたら大成功です!

- 「冷房ON」とメッセージを送付します。
- 10秒以内に「LINEからの命令を受信し、エアコンに冷房ON信号を送信しました。」のメッセージが受信され、「エアコンから「ピッ」と音が鳴り冷房ON」されます。
※赤外線LEDの照射範囲にエアコンが来るように配置して下さい。

- 「停止」とメッセージを送付します。
- 10秒以内に「LINEからの命令を受信し、冷房OFF信号を発信しました。」のメッセージが受信され、「エアコンが停止」されます。
※赤外線LEDの照射範囲にエアコンが来るように配置して下さい。
🛠 もし上手く動かなかったら?(よくあるエラーと解決策)
テスト実行でエラーが出てしまっても焦らないでください!この連携システムで誰もが一度はハマる「定番の罠」と解決策をまとめました。
Q1. スマホのLINEから「冷房」と送っても、Pico Wが全く反応しない!
- 原因の90%はこれ!「Webhook URLの更新忘れ」です。
GASのコードを少しでも書き換えた場合、必ず「新しいデプロイ」を行ってURLを再発行する必要があります。古いURLのままLINE側(Webhook設定)を放置していると、命令が届きません。 - 対策: GASで再度「新しいデプロイ」を行い、発行された新しいURLを、Pico Wの
GAS_URLとLINE DevelopersのWebhook URLの両方に貼り直してみてください。
Q2. Thonnyの画面に「HTMLを受信しました」や「JSONエラー」と表示される
- 原因:GASのアクセス権限エラー Pico WがGASにアクセスした際、JSONデータではなく「Googleのログイン画面(HTML)」を返されてしまっている状態です。
- 対策: GASのデプロイ画面で「アクセスできるユーザー」が「全員」になっているか必ず確認してください。(※「Googleアカウントを持つ全員」ではないので注意!)
Q3. SyntaxError: invalid syntax と出てプログラムがすぐ止まる
- 原因:Python特有の「インデント(空白)のズレ」 Pythonは行の先頭の空白(スペース)の数でプログラムのまとまりを判断します。コードをコピペした際に、
ifやelifの縦のラインがズレていたり、最後の:(コロン)が消えていたりするとこのエラーになります。 - 対策: エラーが出た行番号の周辺を見て、スペースの数や記号の抜けがないか確認しましょう。
これらの壁を乗り越えて無事に動いたら、いよいよ最後の仕上げです!
最終ステップ:PC不要で完全自動化!Pico Wにmain.pyを保存して独立稼働させる方法
第3回の記事のおさらいですね
ここまではテストのために、PCを開いてThonnyから「実行」ボタンを押して動かしてきました。でも、実用的に使うためにPCを24時間繋ぎっぱなしにしておくわけにはいきませんよね。
そこで最後は、Pico WをPCから完全に切り離します!プログラムを本体に記憶させて、コンセントに挿すだけで自動的に監視を始めてくれる**「あなただけの小さなIoT見守り家電」**へと進化させましょう!
💡 なぜ main.py なのか?
Raspberry Pi Picoは、電源が入った瞬間に内部にある main.py という名前のファイルを自動で実行する仕様になっています。
保存できたら、Pico WからUSBケーブルを抜き、スマホの充電器など(5V ACアダプター)に繋いで部屋のコンセントに直接挿してみてください。
数秒後、Wi-Fiに自動接続し、スマホに「遠隔エアコン操作システムが起動しました!」と通知がくれば、見事「スタンドアロン(独立)化」の完了です。 これで、PCの電源が切れていても24時間365日、あなたのお部屋の温度を見守り、いつでもエアコンを操作できる最強のIoTデバイスが誕生です!
おわりに:手作りIoTで実現する愛犬のための快適・安心なスマートホーム
全5回にわたる記事を読んで頂き、本当にありがとうございました!
最初はただの小さな基板だったRaspberry Pi Pico Wが、電子パーツと配線で物理世界と繋がり、Pythonコードで脳を与えられ、Wi-FiとGASを経由してLINEというクラウドサービスと結びつきました。 これこそが、ハードウェアからソフトウェア、ネットワークまでを一気通貫で作り上げる「IoT(Internet of Things)開発」の醍醐味です。
市販のスマートリモコンを買えば数千円で済みますが、自分でトラブルシューティングを行いながら仕組みを理解して作り上げたこのシステムは、何事にも代えがたい「最高の生きたノウハウ」になったはずです。 ぜひ、このシステムを活用して、愛犬にとって快適な環境を整えてあげてください!
ニンジン🥕は、今後も「日々の課題をプログラムで解決する」楽しさと技術を発信していきます。次回作にもぜひご期待ください!
第2回:LINE Messaging APIの最新設定編はこちら





























コメント