概述
由于阿裡雲懸殊的男女比例,以及廁所占地面積的限制,各位男同胞每天都要在特殊味道的包圍下等待有限的坑位。我們在想能不能利用物聯網技術做一個低成本的解決方案,讓男同胞們不需要親自去現場的情況下也能得知坑位的空餘情況(像停車場一樣),基于我們IoT事業部的一站式開發平台——Link Develop,做一個IoT的智能廁所。
技術架構
前期準備
硬體
NodeMCU x9,PIR傳感器 x9,1800mAh LiPo電池 x9,防水盒子 x9,usb mini 連接配接線 x1
軟體
Arduino IDE
平台
阿裡雲賬号,Link Develop平台權限開通
具體實施
建立裝置模型
裝置模型可以了解為一個類,或者一個模闆。它規定了某種裝置下的共有屬性,并且允許你批量執行個體化裝置。
進入Link Develop平台,跟其他雲産品一樣,需要先完成基本的入駐資訊填寫。
接下來我們會進入到一個項目空頁面,我們需要在頁面頂部點選“建立裝置模型”。打開裝置模型彈窗,輸入名稱以及定義類别,這裡我們選擇“自定義類型”即可。然後進入到裝置模型的詳情頁之後,添加标準功能——輸入紅外——選擇紅外檢測狀态。我們就完成了一個可以上報紅外檢測資料的裝置模型了。這個模型已經滿足我們的需求。
然後我們需要執行個體化我們的廁所監控裝置,在裝置模型詳情頁裡點選“測試裝置”tab。然後依次建立9個不同裝置名稱(deviceName)的測試裝置。每個裝置建立完成後都有一個ProductKey,DeviceName和DeviceSecret,我們簡稱為“三元組”,接下來我們還會用到這個。
做完這些步驟之後,裝置模型的建立與執行個體化就OK了。接下來我們進入Arduino代碼編寫。
硬體開發
PIR隻有三個口,分别是VCC,GND和輸出口。接線方法如下(NodeMCU的D7相當于arduino裡的Pin 13)
然後接上usb線。打開arduino IDE。複制以下代碼:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#define SENSOR_PIN 13
/* 連接配接您的WIFI SSID和密碼,這個9個裝置可以一緻 */
#define WIFI_SSID "yourssid"
#define WIFI_PASSWD "yourwifipassword"
/* 産品的三元組資訊,根據9個測試裝置的三元組,每個裝置都燒錄不同的*/
#define PRODUCT_KEY "yourproductKey"
#define DEVICE_NAME "yourdeviceName"
#define DEVICE_SECRET "yourdeviceSecret"
/* LD線上環境域名和端口号,不需要改 */
#define MQTT_SERVER PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com"
#define MQTT_PORT 1883
#define MQTT_USRNAME DEVICE_NAME "&" PRODUCT_KEY
// TODO: MQTT連接配接的簽名資訊,哈希加密請以"clientIdtestdeviceName"+裝置名稱+"productKey"+裝置模型辨別+“timestamp123456789”前往http://tool.oschina.net/encrypt?type=2進行加密
// HMACSHA1_SRC clientIdtestdeviceNamehuman04productKeya1rezUVs103timestamp123456789
#define CLIENT_ID "test|securemode=3,timestamp=123456789,signmethod=hmacsha1|"
#define MQTT_PASSWD "e0748281f8db36e12cac478801318f95ae821ba7"
#define ALINK_BODY_FORMAT "{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"
#define ALINK_TOPIC_PROP_POSTRSP "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post_reply"
#define ALINK_TOPIC_PROP_SET "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/service/property/set"
#define ALINK_METHOD_PROP_POST "thing.event.property.post"
unsigned long lastMs = 0;
WiFiClient espClient;
PubSubClient client(espClient);
void callback(char *topic, byte *payload, unsigned int length)
{
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
payload[length] = '\0';
Serial.println((char *)payload);
if (strstr(topic, ALINK_TOPIC_PROP_SET))
{
StaticJsonBuffer<100> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(payload);
if (!root.success())
{
Serial.println("parseObject() failed");
return ;
}
}
}
void wifiInit()
{
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWD);
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.println("WiFi not Connect");
}
Serial.println("Connected to AP");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
client.setServer(MQTT_SERVER, MQTT_PORT); /* 連接配接WiFi之後,連接配接MQTT伺服器 */
client.setCallback(callback);
}
void mqttCheckConnect()
{
while (!client.connected())
{
Serial.println("Connecting to MQTT Server ...");
if (client.connect(CLIENT_ID, MQTT_USRNAME, MQTT_PASSWD))
{
Serial.println("MQTT Connected!");
// client.subscribe(ALINK_TOPIC_PROP_POSTRSP);
client.subscribe(ALINK_TOPIC_PROP_SET);
Serial.println("subscribe done");
}
else
{
Serial.print("MQTT Connect err:");
Serial.println(client.state());
delay(5000);
}
}
}
void mqttIntervalPost()
{
char param[32];
char jsonBuf[128];
sprintf(param, "{\"MotionAlarmState\":%d}", digitalRead(13));
sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);
Serial.println(jsonBuf);
client.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
}
void setup()
{
pinMode(SENSOR_PIN, INPUT);
/* initialize serial for debugging */
Serial.begin(115200);
Serial.println("Demo Start");
wifiInit();
}
// the loop function runs over and over again forever
void loop()
{
if (millis() - lastMs >= 5000)
{
lastMs = millis();
mqttCheckConnect();
/* 上報 */
mqttIntervalPost();
}
client.loop();
if (digitalRead(SENSOR_PIN) == HIGH){
Serial.println("Motion detected!");
delay(2000);
}
else {
Serial.println("Motion absent!");
delay(2000);
}
}
這裡有幾段代碼需要解釋一下:
引用庫
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
如果之前沒有使用過arduino,這些庫不是arduino自帶的,需要去import一下。以ArduinoJson為例,具體操作方法見下圖:
修改WiFi
#define WIFI_SSID "yourssid"
#define WIFI_PASSWD "yourwifipassword"
這裡要輸入你家的wifi SSID(即wifi名稱)和密碼。如下圖紅框内wifi,SSID即“TOM”(注意大小寫),密碼是“123456”
修改三元組
/* 産品的三元組資訊,根據9個測試裝置的三元組,每個裝置都燒錄不同的*/
#define PRODUCT_KEY "yourproductKey"
#define DEVICE_NAME "yourdeviceName"
#define DEVICE_SECRET "yourdeviceSecret"
這裡就是之前說的三元組,把不同裝置的對應三元組填入即可。
修改HashMAC密鑰
// TODO: MQTT連接配接的簽名資訊,哈希加密請以"clientIdtestdeviceName"+裝置名稱+"productKey"+裝置模型辨別+“timestamp123456789”前往http://tool.oschina.net/encrypt?type=2進行加密
// HMACSHA1_SRC clientIdtestdeviceNamehuman04productKeya1rezUVs103timestamp123456789
#define CLIENT_ID "test|securemode=3,timestamp=123456789,signmethod=hmacsha1|"
#define MQTT_PASSWD "e0748281f8db36e12cac478801318f95ae821ba7"
Link Develop平台為了保證安全性,裝置上傳資料的時候需要驗證身份。是以需要為每個裝置配置不同的Hmac值。方法是先組合一段字段:
"clientIdtestdeviceName"+裝置名稱+"productKey"+裝置模型辨別+“timestamp123456789”
例如剛才截圖的三元組,字段是
clientIdtestdeviceNamehuman01productKeya1rezUVs103timestamp123456789
寫完這個字段之後,前往
這裡進行加密。選擇HmacSHA1方法,以上面的字段為明文,deviceSecret為密鑰。見下圖:
可以得到如下的密文:
e30657f36e7ded9a2781bba97b0dee79e8fa31b6
然後替換掉MQTT_PASSWD原來的字段即可。
完成代碼編譯之後,選擇好對應的開發闆和燒錄線即可進行上傳。通電之後可以檢視序列槽以及Link Develop上的測試裝置清單看看有否成功上線。
應用開發
點選左側欄的Web應用開發,選擇“可視化應用”并輸入名稱。然後就進入可視化開發Web應用的工作台了。
然後我們需要文字元件用來表示标題等。需要訓示燈用來表示目前坑位有沒有人的狀态。
接下來以坑位1為例舉例如何将元件綁定裝置。點選右側面闆的“資料”,選擇關聯裝置。這裡會顯示出所有已經建立的測試裝置。選擇對應坑位的傳感器,之後選擇展示的資料(布爾型的紅外監測狀态)。這樣就完成了綁定資料了。
可以通過模拟上線看看是否成功關聯。另外有一些個性化的樣式也可以自己配置。
接下來就是發揮創造力的時候了。可以上傳各種背景圖,加各種小樣式,做成如圖的看闆。最後點選右上角預覽即可。
這樣就完成了一個看闆了!不用忍氣吞聲,直接檢視廁所有沒有空餘坑位!
釘釘推送的教程後續會跟進同步~
部署
這是實體裝機的盒子。為了更好的使用者體驗,我們在盒子上加了一個字條“隻檢測有人,沒有攝像頭”,以免使用者産生隐私方面的擔憂。
部署的時候用了樹莓派+顯示屏。
造福90%飛天園區一号樓四樓員工的智能廁所解決方案,完成!
歡迎使用Link Develop
Link Develop(物聯網開發平台)是阿裡雲針對物聯網領域提供的端到端一站式開發服務平台,可覆寫各個物聯網行業應用場景,主要解決物聯網開發領域開發鍊路長、技術棧複雜、協同成本高、方案移植困難的問題,提供了從硬體開發、服務編排、Web應用開發到移動APP開發全鍊路的開發流程、架構/引擎和調試工具,并可将成熟的開發産出物對接阿裡雲雲市場進行售賣,為開發者實作商業收益。
這篇文章的兩個作者,一位是學法律出身的營運同學,一位是學設計出身的UED同學,兩位都不是專業的工程師,卻能在短短一天之内基于Link Develop完成整個智能廁所的解決方案搭建。相信大家認識到了Link Develop平台的開發能力之後,會有更多更新奇的idea出現,并且借助Link Develop快速實作物聯網應用開發!
歡迎通路:
https://linkdevelop.aliyun.com