Showing posts with label weekend projects with Stonez56. Show all posts
Showing posts with label weekend projects with Stonez56. Show all posts

2026/02/28

樹莓派 - 如何由 LAN PC 連回到 OpenClaw Web UI

 


如果OpenClaw 跑在樹莓派上,要怎麼在自己的電腦上安全地打開 OpenClaw 的控制界面? 其實很簡單,只要透過 SSH 安全隧道就能做到!


🔧 操作步驟: 在你的電腦上執行以下指令:

ssh -N -L 18789:127.0.0.1:18789 user@192.168.0.181

user → 你的樹莓派使用者帳號, 再輸入密碼


192.168.0.181 → 樹莓派的 LAN IP


打開瀏覽器,輸入:

http://localhost:18789/

就能直接看到 OpenClaw 的 Web 控制界面!

🛡️ 為什麼要用 SSH?

安全性:所有流量都經過 SSH 加密,不怕被攔截。

便利性:就像直接在 Pi 上操作一樣,但其實是透過隧道安全傳輸。


簡單來說,這個方法讓你在 LAN PC 上 安全地存取樹莓派上的服務,而且完全不需要額外安裝複雜工具。


#OpenClaw #SSH #安全隧道 #樹莓派 #LAN操作

2025/03/07

Raspberry Pi #25 跨網存取技巧 Tailscale 全球存取(1) - Internet access to your Raspberry Pi

⭐⭐大家好,歡迎來到 Stonez56 創客工坊!今天我們要來教大家一個超實用的技巧,

讓你隨時隨地都能安全地訪問家裡的樹莓派。 Tailscale 是一個非常方便的 VPN 工具, 它能讓你建立一個安全的私人網路,讓你從任何地方都能像在區域網路一樣訪問你的裝置。 而且設定非常簡單,即使是新手也能輕鬆上手。最重要的是,它非常安全, 不用擔心資料外洩的問題。

Tailscale 可以跨網回家使用:

  1. 資料庫:遠程管理或查詢 MySQL、PostgreSQL 或 MongoDB 等資料庫。

  2. MQTT 中介代理:訪問使用像 Mosquitto 的 MQTT 中介代理的物聯網設備或系統。

  3. 網頁伺服器:連接到託管網站或應用程序的網頁伺服器(如 Apache、Nginx)。

  4. 檔案共享服務:使用 SFTP 或 SMB 協議訪問共享檔案或目錄。

  5. 遠端桌面:使用 RDP 或 VNC 遠程控制設備。

  6. 媒體伺服器:從 Plex、Emby 或類似的媒體伺服器串流內容。

  7. 開發環境:訪問遠端的開發環境,例如 SSH 或代碼伺服器。

  8. 網絡附加存儲(NAS):管理或檢索 NAS 設備中的檔案。



首先,我們要在樹莓派上安裝 Tailscale。打開你的樹莓派終端機,然後輸入以下指令:

Bash curl -fsSSL https://tailscale.com/install.sh | sh


安裝完成後,我們需要啟用 Tailscale。輸入以下指令:

Bash sudo tailscale up



這時候你會看到一個 URL,用你的瀏覽器打開它,然後登入你的 Tailscale 帳號。

接下來,我們要在你的手機或電腦上也安裝 Tailscale。到 Tailscale 的官網下載

對應的應用程式,然後用剛剛在樹莓派上登入的同一個帳號登入。

現在,我們要找到樹莓派的 Tailscale IP。在樹莓派終端機輸入以下指令:

Bash tailscale ip -4


這個 IP 就是我們用來遠端訪問樹莓派的地址。


現在,我們要實際演示如何使用手機或電腦連線到樹莓派。這裡我會針對幾種常見的使用情境 做說明:

1. SSH 連線(用於遠端終端機操作):

  • 電腦 (Windows/macOS/Linux):

    • 打開終端機(Windows 使用 PowerShell 或 Windows Terminal,macOS/Linux 使用 Terminal)。

    • 輸入以下指令,並將 [樹莓派的 Tailscale IP] 替換成你剛剛找到的 IP:

    • Bash ssh pi@[樹莓派的 Tailscale IP]

  • 按下 Enter 後,系統會提示你輸入樹莓派的密碼。預設密碼通常是 raspberry, 但如果你已經更改過,請輸入你設定的密碼。

  • 成功登入後,你就可以在終端機中操作樹莓派了。

  • 手機 (iOS/Android):

    • 下載並安裝 SSH 客戶端應用程式,例如 Termius 或 JuiceSSH。

    • 在應用程式中新增一個連線,輸入樹莓派的 Tailscale IP、使用者名稱 (通常是 pi) 密碼。

    • 點擊連線,即可透過手機操作樹莓派的終端機。

2. MQTT 控制(用於物聯網應用):

  • 電腦/手機:

    • 安裝 MQTT 客戶端應用程式,例如 MQTT Explorer 或 MQTT Dash。

    • 在應用程式中新增一個連線,輸入樹莓派的 Tailscale IP 作為 Broker 地址, 並設定相應的 Port (預設為 1883)。

    • 訂閱或發布 MQTT 主題,即可與樹莓派上的 MQTT Broker 進行互動。

3. Web 服務):

  • 電腦/手機:

    • 打開瀏覽器,在網址列輸入 http://[樹莓派的 Tailscale IP]:[Port], 並將 [Port] 替換成你樹莓派上 Web 服務使用的 Port。 例如,如果你的 Web 服務使用 80 Port, 則輸入 http://[樹莓派的 Tailscale IP]

    • 按下 Enter,即可瀏覽樹莓派上的網頁。

成功連線到樹莓派後,你可以執行一些簡單的指令來測試連線是否正常。例如,在 SSH 連線中,你可以輸入 hostname 來查看樹莓派的主機名稱,或者輸入 uptime 來查看系統運行時間。對於網頁,可以查看網頁是否正常顯示。

對於MQTT可以發布一個簡單的測試資訊,然後讓樹莓派回覆。


為了讓 Tailscale 在每次樹莓派開機時自動啟動,我們需要啟用 systemd 服務。 在樹莓派終端機輸入以下指令:

Bash sudo systemctl enable tailscaled


這樣就設定完成啦!下次樹莓派開機,Tailscale 就會自動啟動,你就能隨時隨地訪問它了。

如果你想要驗證服務是否成功啟動,可以輸入:

Bash sudo systemctl is-enabled tailscaled


如果遇到問題,你可以使用以下命令來查看日誌:

Bash sudo journalctl -u tailscaled


恭喜你!現在你已經學會如何使用 Tailscale 遠端訪問你的樹莓派,並且設定了開機自動啟動。是不是很簡單呢?趕快試試看吧!如果你有任何問題,歡迎在下方留言。




如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可! 

00:00 開始

01:53 下載安裝 Tailscale 到樹莓派

05:17 手機上安裝 Tailscale App

07:12 Tailscale 免費使用額度

08:03 由外網連回樹莓派

12:32 設定 Tailscale 開機自動執行


資源:

 🍗Tailscale : https://tailscale.com 

 🍗 Setting up Tailscale on Pi: https://tailscale.com/kb/1174/install-debian-bookworm  



2024/06/13

Arduino #43使用LoRa模組,輕鬆實現長距離免費通訊!(How to use LoRa modules with ESP32 for long distance communication)

 歡迎來到本週的Weekend project with Stonez56!你準備好體驗超炫的科技應用了嗎?本週的主題是使用Arduino #43 LoRa模組,輕鬆實現長距離免費通訊!

這次的影片內容可謂豐富多元,包括以下精彩部分:


* 什麼是LoRa技術以及其應用

* 使用ESP32 LED燈顯示連線狀態,簡單易懂

* 深入探索LoRa模組,一步步教你如何使用

* 教你使用SSD1306 OLED顯示器,方便實用

* 帶你體驗DHT11溫濕度感測器,監測環境變化

* 最後還有程式碼解說,讓你輕鬆上手


這次的Weekend project一定不會讓你失望,絕對值得一看!快來點開影片,體驗科技的樂趣吧!


00:00 開始 00:16 本集影片概要 02:12 LoRa 適用的場合 02:42 RYLR998 LoRa 模組的特性 04:17 使用前所需之基本設定 07:12 AT Command 設定實作(以 VS Code做設定) 09:45 點對點連線實際運作展示 11:15 發射端程式解析 21:00 接收端程式解析


Source code:

2022/12/04

App Inventor #11自己來寫 App - 骰子遊戲 (Dice Game)

大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是 App Inventor 第10集 -  自己來寫 App - 骰子遊戲

這個影片適合稍進階同學來觀看&學習, 想要越級挑戰的朋也也歡迎拿來這個單元來學習 App Inventor 2! 

這是一個學習任意組件的好範例, Android, iPad 都可以使用!




本次教學你可以學到:

 * 本集會使用到:

 * 感測器 (Sensor)

 * 變數應用 (Variables)

 * 清單的應用 (List)

 * 圖片的應用 (Image)

 * 為APP加上音音效 (Audio)

 * 亂數的應用 (Randomized)

 * 用任意組件 (Any component)

 * 程序的應用 (Procedure)


參考資料: 

App inventor 語法 & 使用方式: http://ai2.appinventor.mit.edu/reference/blocks/ 

音效來源: https://pixabay.com/ 

圖片製作:  https://figma.com 


如果你時間不夠, 也可以從以下的時間軸挑選想看的部份即可! 


影片時間軸: 

00:00 開始

00:24 骰子 App 示範

01:20 App 畫面的配置 / 素材上傳

04:39 App 程式設計

05:18 如何使用變數/變數種子

06:31 設定音效

11:54 如何使用任意元件

15:22 使用任意組件來移除重複的運算

16:26 把骰子元件放入清單中

23:11 使用任意組件 vs 未使用任意組件


App Inventor 相關教學影片:


* App Inventor #11自己來寫 App - 骰子遊戲 (Dice Game)

https://youtu.be/2d6Si6u8FVE


* App Inventor #10 集 自己來寫 APP YouBike 2.0 (下). 

https://youtu.be/Cli-_lUPjgU


* App Inventor #9 集 - 自己來寫 APP YouBike 2.0 (上) 

https://youtu.be/D78-eDRFiXM


*App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧 (How to keep AI2 always connected for Android) https://youtu.be/_HeM9GyVmIE


* App Inventor #7 ESP32 語音辨識控制 IOT 專案, 使用 IoT Essential Library Example (CC available)  https://youtu.be/senjdb-cREY


* App Inventor #6 使用’ 繪圖動畫' 製作使用者介面 (App Inventor 2 UI design with Draw and Animation) https://youtu.be/RfYi8h9y6kE


* App Inventor #5 - “無線搖控 ESP32-CAM APP 下集 (Write ESP32-CAM remote APP 2/2) https://youtu.be/J8b3zWX1FXM


* App Inventor #4 無線搖控 ESP32-CAM APP 上集 (Write ESP32-CAM remote APP 1/2)

https://youtu.be/x545mFSZWgg


* App Inventor #3 “自己來寫APP 快篩何處買?” (How to process .csv files in App Inventor)

https://youtu.be/u5J4FJQ5UQQ


* App Inventor #2 “自己來寫mqtt APP Android & iOS都能用” (Create MQTT Apps with App Inventor 2)

https://youtu.be/kIONEfLO4sI


* MIT App Inventor 2 #1 - 語音辨識 (Voice Recognition)

https://youtu.be/msV4V6af6tA 

2022/11/06

Arduino #38 YouBike 2.0 餘車通知器 (Arduino #38 ESP32 1306 YouBik 2.0 remain notifier)

大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是Arduino 第38集 -  UBike 2.0 餘車通知器.



大多數坐捷運上下班的朋友, 一定有這樣的經驗:下班時,匆匆忙忙趕到捷運站,卻發現捷運站的Ubike已經都沒有了, 只好在那邊癡癡的等候.

如果下班之前, 看一下YouBike 2.0, 餘車通知器, 確定站點還有較多的Ubike, 這時候再過去牽車, 是不是很安心呢? 我們來看看怎麼做吧!


如果你時間不夠, 也可以從以下的時間軸挑選想看的部份即可! 

影片時間軸:

00:00 開始

00:43 UBike 2.0 餘車通知器使用方法

03:22 Google Sheet 設定

14:44 Google Sheet 發佈API設定

17:19 Google Script doPost(e) 程式解釋

20:27 Google Script doGet(e) 程式解釋

21:46 ESP32 程式解釋

26:51 ESP32 refreshYouBike2data (更新SHEET資料)

28:52 ESP32 goGetData 由Sheet取得資料

30:03 showUTF8String 顯示餘車資料


App Inventor 相關教學影片:

* App Inventor #11自己來寫 App - 骰子遊戲 (Dice Game)
https://youtu.be/2d6Si6u8FVE

* App Inventor #10 集 自己來寫 APP YouBike 2.0 (下).
https://youtu.be/Cli-_lUPjgU

* App Inventor #9 集 - 自己來寫 APP YouBike 2.0 (上)
https://youtu.be/D78-eDRFiXM

*App Inventor #8 AI2 Companion 一直斷線怎麼辦? AI2 小技巧 (How to keep AI2 always connected for Android) https://youtu.be/_HeM9GyVmIE

* App Inventor #7 ESP32 語音辨識控制 IOT 專案, 使用 IoT Essential Library Example (CC available)  https://youtu.be/senjdb-cREY

* App Inventor #6 使用’ 繪圖動畫' 製作使用者介面 (App Inventor 2 UI design with Draw and Animation) https://youtu.be/RfYi8h9y6kE

* App Inventor #5 - “無線搖控 ESP32-CAM APP 下集 (Write ESP32-CAM remote APP 2/2) https://youtu.be/J8b3zWX1FXM

* App Inventor #4 無線搖控 ESP32-CAM APP 上集 (Write ESP32-CAM remote APP 1/2)

https://youtu.be/x545mFSZWgg

* App Inventor #3 “自己來寫APP 快篩何處買?” (How to process .csv files in App Inventor)

https://youtu.be/u5J4FJQ5UQQ

* App Inventor #2 “自己來寫mqtt APP Android & iOS都能用” (Create MQTT Apps with App Inventor 2)   https://youtu.be/kIONEfLO4sI

* MIT App Inventor 2 #1 - 語音辨識 (Voice Recognition)
https://youtu.be/msV4V6af6tA 

2022/08/14

Android #36 IoT 基本程式庫 Wifimanager FOTA MQTT (IOT Essential Code base with wifimanager, ElegantOTA, & MQTT)

Hi, Welcome to weekend project with Stonez56

This week's Arduino episode #37, "Essential IoT Code Base- Wifimanager FOTA + MQTT"

Here is the source code: https://stonez56.blogspot.com/2022/08/android-36-iot-wifimanager-fota-mqtt.html 


Today, I will show how to combine three commonly used IoT libraries;

WiFimanager, AsyncElegantOTA, and MQTT To become a common IoT code base. So, for our future projects, ESP8266 or ESP32, would have these basic functions.

Let's first look at these three libraries:

  • Wifimanager = Wi-Fi password management, no need to re-burn the code to change the Wi-Fi SSID & password
  • FOTA = Use Wi-Fi to update ESP32 code, you can burn code without connecting to USB
  • MQTT = Streamlined and lightweight communication protocol (Message Queueing Telemetry Transport)


This episode will only introduce how to integrate MQTT into Wifimanager + AsyncElegantFOTA.

To learn how to start Wifimanager + AsyncElegantOTA, Please watch Android #27 Wifimanager + OTA for ESP32/ESP8266 (ESPAsyncWifimanager / ESPAsyncElegantOTA)) https://youtu.be/UlRLTvl4DRc 


==References==

Arduino Library URL:


==Sample code URL==

ESPAsync_WiFiManager minimal: https://github.com/khoih-prog/ESPAsync_WiFiManager/blob/master/examples/Async_AutoConnect_ESP32_minimal/Async_AutoConnect_ESP32_minimal.ino 


ESP32 Async OTA : https://github.com/ayushsharma82/AsyncElegantOTA/blob/master/examples/ESP32_Async_Demo/ESP32_Async_Demo.ino 


If you don't have enough time, you can also select the part you want to watch from the timeline below!

Video Timeline: 00:00 Start 01:39 Demonstration of project results 01:57 mqttgo.io MQTT server, free, fast, & stable 05:52 Install three libraries 07:14 Added two ESP32 PINs as MQTT example 07:41 Encrypt the firmware update (ElegantOTA) page 11:44 Explain how the MQTT callback function works 13:07 Control ESP32 I/O pins with MQTT 15:16 Future program can be written from here

=====中文版本======

大家好, 歡迎收看本週的Weekend project with Stonez56。 

本周要進行的是 Arduino 第36集,"IoT 基本程式庫 - Wifimanager FOTA + MQTT”

今天來跟大家介紹如何把 一般的 IoT 專案常用到的三個程式庫,  WiFiManager 以及WiFi 韌體更新FOTA (Firmware Over the Air), 再加上 MQTT 三個整合在一起, 變成一個常用的 Code base.  往後你的 ESP32 IoT 專案呢, 就可以俱備這些基本功能了! 


  • Wifimanager = WiFi 密碼管理, 不用重新燒 Code 改 Wifi SSID & 密碼
  • FOTA = 用Wi-Fi更新ESP32程式碼, 不用接USB就可以燒Code
  • MQTT = 精簡輕量化的通訊協定(Message Queueing Telemetry Transport)


本集僅會介紹如何把 MQTT 整合到 Wifimanager + AsyncElegantFOTA

若想了解如何整合 Wifimanager + AsyncElegantOTA, 

請觀看 Arduino #26 AsyncWifimanager ElegantOTA ESP32 (WiFi 密碼管理+ WiFi 韌體更新) https://youtu.be/zepkinJ46Zg  




==參考資料==

Arduino Library URL: 


==Sample code URL==


如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可! 

影片時間軸:

影片時間軸: 00:00 Start 01:39 專案成果示範 01:57 mqttgo.io 快速免費的 MQTT 伺服器 05:52 安裝三支程式庫 07:14 加入兩個 ESP32 PIN做為MQTT範例 07:41 為韌體更新(ElegantOTA)頁面加密 11:44 說明MQTT callback 函數運作方式 13:07 MQTT由此控制ESP32 PIN 15:16 把你的程式可以寫在這裡


IoT基本程式庫原始程式:


/** 
 * Arduino code base for IoT Projects
 * By: Stonez56 aka Kevin Chen 2022-08-16
 * 
 * This source code combined three most common Arduino libraries for IoT Projects, 
 * ESPAsync_Wifimanager, AsyncElegantOTA, & Pubsubclient MQTT Client.
 * 
 * 1. ESPAsync_WiFiManager: https://github.com/khoih-prog/ESPAsync_WiFiManager 
 * 2. AsyncElegantOTA: https://github.com/ayushsharma82/AsyncElegantOTA 
 * 3. Pubsubclient MQTT Client: https://github.com/knolleary/pubsubclient 
 * 
 * YouTube video: https://youtu.be/giFHp9RSMvQ
 * Source code is available my blog: https://stonez56.blogspot.com/2022/08/android-36-iot-wifimanager-fota-mqtt.html 
 **/

/*
 * Define Relay pins as examples to send/receive MQTT messages
 * **/
#define RELAY_PIN_1 12
#define RELAY_PIN_2 14

/** 
 * Perform OTAs for ESP8266 / ESP32 Elegantly with password protection! 
 * https://github.com/ayushsharma82/AsyncElegantOTA
 * **/
#include <AsyncElegantOTA.h>
const char *FOTA_USERNAME = "un";
const char *FOTA_PASSWORD = "pw";

/** 
 * Add MQTT client here` PubSubClient V2.8 by Nick O'Leary
 * https://github.com/knolleary/pubsubclient 
*/
#include <WiFiClient.h>
#include <PubSubClient.h>
#define MSG_BUFFER_SIZE (1024)
char msg[MSG_BUFFER_SIZE];

/** Taiwan No. 1 Free MQTT Server!! **/
const char *mqtt_server = "mqttgo.io";
const int mqtt_port = 1883;

/****************************************************************************************************************************
  Async_AutoConnect_ESP32_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !(defined(ESP32))
#error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h> 
AsyncWebServer webServer(80);

//Start DNS server
DNSServer dnsServer;

//MQTT - Start WiFi client and connect to MQTT server
WiFiClient espClient;
PubSubClient mqtt_client(espClient);

//Define device name
String DEVICE_NAME = "Dual_Relay_Switch";
String home_page_message = "";

void setup()
{
    Serial.begin(115200);
    pinMode(RELAY_PIN_1, OUTPUT);
    pinMode(RELAY_PIN_2, OUTPUT);

    while (!Serial)
        ;
    delay(200);
    Serial.print("\nAsyncWifimanager started on " + String(ARDUINO_BOARD) + "\n");

    //Initialize ESPAsyncWifimanager instance and assign Wi-Fi Client name "AsyncAutoConnect"!
    //This name and IP address can be checked from the router
    ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "Dual_Relay_Switch");

    //####### RESET SAVED WIFI SETTINGS #############
    //ESPAsync_wifiManager.resetSettings();   

    //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 132, 1), IPAddress(192, 168, 132, 1), IPAddress(255, 255, 255, 0));
    //ESPAsync_wifiManager.autoConnect("Stonez_ESP32S", "AP-NAME", "AP-PASSWORD");
    
    ESPAsync_wifiManager.autoConnect("Dual_Switch_ESP32S");
    if (WiFi.status() == WL_CONNECTED)
    {
        Serial.print(DEVICE_NAME);
        Serial.print(" is on Local IP: ");
        Serial.println(WiFi.localIP());
    }
    else
    {
        Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status()));
    }

    //Setup home page access content when visite
    home_page_message = "<!DOCTYPE html><html><head><title>" + DEVICE_NAME 
        + "</title></head><body><p><h2> Hi! This is " + DEVICE_NAME + "</h2>"
        + "To update firmware, <a href='/update'>Click here!!</a><br/><span>Username & Password required!</span></p><body></html>";

    webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
                 { request->send(200, "text/html", home_page_message); });

    //AsyncElegantOTA.begin(&webServer); // Start ElegantOTA WITHOUT username & password
    AsyncElegantOTA.begin(&webServer, FOTA_USERNAME, FOTA_PASSWORD); // Start ElegantOTA with username & password
    webServer.begin();
    Serial.println("AsyncElegantOTA server started @URL/update");

    //MQTT starts here!
    mqtt_client.setServer(mqtt_server, mqtt_port);
    mqtt_client.setCallback(callback);
}

/**
//When MQTT lost connection, this function will be called to reconnect MQTT//
 * Modified to accept multiple MQTT topics 
 * https://www.baldengineer.com/multiple-mqtt-topics-pubsubclient.html
 */
void callback(char *topic, byte *payload, unsigned int length)
{
    //Print message received
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    for (int i = 0; i < length; i++)
    {
        Serial.print((char)payload[i]);
    }
    Serial.println();

    //Process multiple topics here//
    payload[length] = '\0';
    String message = (char*)payload;
    
    if (strcmp(topic, "studio/humd_switch") == 0)
    {
      if(message == "true"){
        digitalWrite(RELAY_PIN_1, HIGH);
        Serial.println("humd_switch true");
      }
      if(message == "false"){
        digitalWrite(RELAY_PIN_1, LOW);
        Serial.println("humd_switch false");
      }
    }
    if (strcmp(topic, "studio/humd_switch2") == 0)
    {
      if(message == "true"){
        digitalWrite(RELAY_PIN_2, HIGH);
        Serial.println("humd_switch2 true");
      }
      if(message == "false"){
        digitalWrite(RELAY_PIN_2, LOW);
        Serial.println("humd_switch2 false");
      }
    }
}

//============= MQTT ===================
//When MQTT lost connection, this function will be called to reconnect MQTT//
void reconnect(){
    //Loop while MQTT connected
    while (!mqtt_client.connected())
    {
        Serial.print("Attempting MQTT connection... ");
        // Create a random client ID
        String clientId = "Stonez_ESP32Client-";
        clientId += String(random(0xffff), HEX);
        // Attempt to connect
        if (mqtt_client.connect(clientId.c_str()))
        {
            Serial.print("connected to ");
            Serial.print(mqtt_server);
            // Once connected, publish an announcement...
            mqtt_client.publish("outTopic", "Hello world");
            // ... and resubscribe
            mqtt_client.subscribe("studio/humd_switch");
            mqtt_client.subscribe("studio/humd_switch2");
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.print(mqtt_client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}
void loop() {
    //============= MQTT ===================
    //if can't connect to MQTT server, then re-connect
    if (!mqtt_client.connected())
        { reconnect(); }
    //constantly check MQTT to see for messages sending/receiving
    mqtt_client.loop();

    /**
     * Write your own code here....
     * 
     */
}

Async_AutoConnect_ESP32_minimal.ino

/****************************************************************************************************************************
  Async_AutoConnect_ESP32_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !(defined(ESP32) )
  #error This code is intended to run on the ESP32 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager
AsyncWebServer webServer(80);
DNSServer dnsServer;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200); while (!Serial); delay(200);
  Serial.print("\nStarting Async_AutoConnect_ESP32_minimal on " + String(ARDUINO_BOARD)); Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);
  ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP");
  //ESPAsync_wifiManager.resetSettings();   //reset saved settings
  ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192,168,132,1), IPAddress(192,168,132,1), IPAddress(255,255,255,0));
  ESPAsync_wifiManager.autoConnect("AutoConnectAP");
  if (WiFi.status() == WL_CONNECTED) { Serial.print(F("Connected. Local IP: ")); Serial.println(WiFi.localIP()); }
  else { Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); }
}

void loop() {  }

Async_AutoConnect_ESP8266_minimal.ino

/****************************************************************************************************************************
  Async_AutoConnect_ESP8266_minimal.ino
  For ESP8266 / ESP32 boards
  Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
  Licensed under MIT license
 *****************************************************************************************************************************/
#if !( defined(ESP8266) )
  #error This code is intended to run on ESP8266 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager
AsyncWebServer webServer(80);
DNSServer dnsServer;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200); while (!Serial); delay(200);
  Serial.print("\nStarting Async_AutoConnect_ESP8266_minimal on " + String(ARDUINO_BOARD)); Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);
  ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP");
  //ESPAsync_wifiManager.resetSettings();   //reset saved settings
  //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192,168,186,1), IPAddress(192,168,186,1), IPAddress(255,255,255,0));
  ESPAsync_wifiManager.autoConnect("AutoConnectAP");
  if (WiFi.status() == WL_CONNECTED) { Serial.print(F("Connected. Local IP: ")); Serial.println(WiFi.localIP()); }
  else { Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); }
}

void loop() {  }


2022/04/23

Android #34 用一塊ESP32來學IOT - Android手機也能通 (Learn IOT with an ESP32 / remote control w/ MQTTDash)

Android #34 用一塊ESP32來學IOT - Android手機也能通 Learn IOT with an ESP32 / remote control w/ MQTTDash

** ENGLISH closed captions is now available for this video ** Learn IOT with an ESP32 / remote control w/ MQTTDash APP

Video timeline:

00:58 Download MQTTDash App 01:29 Create an MQTT connection 03:20 Dashboard Design 04:17 Review subscriptions on MQTTLens 05:15 Enter subscription topics in MQTTDash 10:30 See the Demo on the phone 12:39 Modify ESP32 code accordingly 大家好, 歡迎收看本週的Weekend project with Stonez56。 本周是Android 第34集,"用一塊ESP32來學IOT - Android 手機也能通”。這個是一個專門為初學者來開發的一個系列。 繼上集之後, 有網友反應無法在手機上用 MQTTlens. 所以我們今天要把只能在電腦上使用的 MQTTLens 改成 MQTTDash 這支Android APP. 這樣子, 只要帶著手機, 我們就可真正隨時隨地的遠端控制IOT設備了~ 那我們就一起來學習吧。 Android MQTTDash App: https://play.google.com/store/apps/details?id=net.routix.mqttdash&hl=zh_TW&gl=US&showAllReviews=true 尚未看過這系列的朋友, 建議從這裡依序學習: * 用一塊ESP32來學 IOT https://youtu.be/rjPU4YZG338 * 溫溼度篇 https://youtu.be/x3k_dZXua1I * Android App 也能通 https://youtu.be/0IjQOxD2j48 如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可! 影片時間軸: 00:00 開始 00:58 下載 MQTTDash APP 01:29 建立 EMQX MQTT 連線 03:20 儀表板設計 04:17 查看之前 MQTTLens 上的訂閱/發佈主題 05:15 在 MQTTDash 中加入訂閱/發佈主題 10:30 看實際手機+ESP32 展示 12:39 如何修改 ESP32 相應代碼

Source code:

/*
 Basic ESP8266 MQTT example
 This sketch demonstrates the capabilities of the pubsub library in combination
 with the ESP8266 board/library.
 It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off
 It will reconnect to the server if the connection is lost using a blocking
 reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
 achieve the same result without blocking the main loop.
 To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"
*/

#include <WiFi.h>
#include <PubSubClient.h>
#include <EasyButton.h>
#define LED 2        //built-in LED on ESP32

#include "DHT.h"
#define DHTPIN 23     // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 // DHT11
DHT dht(DHTPIN, DHTTYPE); // Initialize DHT sensor.
// Set up the temp / humidity update cycle
const int updateCycle = 5000;

// Update these with values suitable for your network.
const char *ssid = "Wi-Fi SSID";
const char *password = "Wi-Fi Password";

// Define your client ID on EMQX
String mqtt_ClientID = "stonez56_IOT_Station_";

// Define your topics to subscribe / publish
const char* sub_topic = "stonez56/esp32s";
const char* pub_led_topic = "stonez56/esp32s_led_state";
const char* pub_init_topic = "stonez56/esp32s_is_back";
const char* pub_temp_topic = "stonez56/esp32s_temp";
const char* pub_humd_topic = "stonez56/esp32s_humd";

// EMQX broker parameters
const char *mqtt_server = "broker.emqx.io";
const char *mqtt_userName = "emqx";
const char *mqtt_password = "public";

WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
char msg1[MSG_BUFFER_SIZE];

int value = 0;

void setup_wifi()
{
    delay(10);
    // We start by connecting to a WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }

    randomSeed(micros());

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}

void callback(char *topic, byte *payload, unsigned int length)
{
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    for (int i = 0; i < length; i++)
    {
        Serial.print((char)payload[i]);
    }
    Serial.println();

    payload[length] = '\0';
    String message = (char *)payload;
    
    if (strcmp(topic, sub_topic) == 0)
    {
        if (message == "off")
        {
            digitalWrite(LED, LOW); //Turn off
            client.publish(pub_led_topic, "off");
        }
        if (message == "on")
        {
            digitalWrite(LED, HIGH); //Turn on
            client.publish(pub_led_topic, "on");
        }
    }

    /* Switch on the LED if an 1 was received as first character
    // if ((char)payload[0] == '1')
    // {
    //     digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
    //                                     // but actually the LED is on; this is because
    //                                     // it is active low on the ESP-01)
    // }
    // else
    // {
    //     digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
    // } */
}

void reconnect()
{
    // Loop until we're reconnected
    while (!client.connected())
    {

        Serial.println("Attempting EMQX MQTT connection...");
        // Create a random client ID
        mqtt_ClientID += String(random(0xffff), HEX);
        // Attempt to connect
        if (client.connect((mqtt_ClientID, mqtt_userName, mqtt_password)))
        {
            Serial.print(" connected with Client ID: ");
            Serial.println(mqtt_ClientID);
            // Once connected, publish an announcement...
            client.publish(pub_init_topic, "Hi, I'm online!");
            // ... and resubscribe
            client.subscribe(sub_topic);
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
}

void setup()
{
    //Start DH11 sensor
    dht.begin();

    pinMode(LED, OUTPUT); // Initialize the _LED pin as an output
    digitalWrite(LED, LOW); //default ESP32 LOW is turn off

    Serial.begin(115200);
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    client.setCallback(callback);
}

void loop()
{

    if (!client.connected())
    {
        reconnect();
    }
    client.loop();

    unsigned long now = millis();
    if (now - lastMsg > updateCycle)
    {
        lastMsg = now;
        float humidity = dht.readHumidity();
        float temperature = dht.readTemperature();
        // Check if any reads failed and exit early (to try again).
        if (isnan(humidity) || isnan(temperature))
        {
            Serial.println(F("Failed to read from DHT sensor!"));
            return;
        }else{ // publish the message
            snprintf(msg, MSG_BUFFER_SIZE, "%.1lf°", temperature);
            snprintf(msg1, MSG_BUFFER_SIZE,"%.0lf%%", humidity);
            Serial.print("Publish message: ");
            Serial.println(msg);
            client.publish(pub_temp_topic, msg);
            client.publish(pub_humd_topic, msg1);
            
        }

    }
}

;

2021/12/31

#10.1 如何開機自動連接Google 雲端硬碟/ How to auto-mount Google Drive on boot


 

如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可!

#10.1 如何開機自動連接Google 雲端硬碟/ How to auto-mount Google Drive on boot





大家好, 今天是2021的最後一天, 祝大家新年快樂!!

在今年的最後天天, 來和大家分享 “一起來學樹莓派” 系列之 “如何開機自動連接Google 雲端硬碟/ How to auto-mount Google Drive on boot”

之前的影片做了一片”#10 重要資料, 直接備份到Google雲端硬碟的影片https://youtu.be/GmyiPJ1cxvk , 卻忘了一個重要的程序, 就是如何開機後, 如何自動連接Google 雲端硬碟, 少了這個重要的步驟, 那每次重新開機都要下 rclone 指令來掛載Google drive 也是很麻煩的!  請務必先看之前的影片 #10, 不然會不容易了解此片的內容!

 參考資料: 


home-pi-mnt-gdrive.mount (千萬別照抄...要依你 Rclone 設定來修改)

[Unit]
After=network.target

[Mount]
Type=rclone
What=gdrive:rpi4
Where=/home/pi/mnt/gdrive
Options=rw,allow_other,args2env,vfs-cache-mode=writes,config=/home/pi/.config/rclone/rclone.conf,cache-dir=/tmp

[Install]
WantedBy = multi-user.target


  •  gdrive:rpi4: Google drive 上要掛載的資料夾
  • /home/pi/mnt/gdrive: 對應的樹莓派上的資料夾
  • /home/pi/.config/rclone/rclone.conf: rclone 設定檔的位置!


如果時間不夠的朋友, 也可以從以下的時間軸挑選想看的部份即可!

影片時間軸: 00:00 開始 00:52 先閱讀 Rclone 文件 01:30 使用 ssh 程式來下達命令 02:18 遵守嚴格的磁碟掛載命名規則 03:17 解釋掛載檔案內容 07:36 不要忘記掛載文件要以 .mount 結尾 09:17 重新啟動以驗證自動掛載是否成功 10:19 沒有自動掛載的原因 12:19 重新啟動以再次檢查自動掛載 13:12 教學內容總結