如何用Link Develop开发一个智能厕所

概述

由于阿里云悬殊的男女比例,以及厕所占地面积的限制,各位男同胞每天都要在特殊味道的包围下等待有限的坑位。我们在想能不能利用物联网技术做一个低成本的解决方案,让男同胞们不需要亲自去现场的情况下也能得知坑位的空余情况(像停车场一样),基于我们IoT事业部的一站式开发平台——Link Develop,做一个IoT的智能厕所。

技术架构

如何用Link Develop开发一个智能厕所

前期准备

硬件

NodeMCU x9,PIR传感器 x9,1800mAh LiPo电池 x9,防水盒子 x9,usb mini 连接线 x1

软件

Arduino IDE

平台

阿里云账号,Link Develop平台权限开通

具体实施

建立设备模型

设备模型可以理解为一个类,或者一个模板。它规定了某种设备下的共有属性,并且允许你批量实例化设备。
如何用Link Develop开发一个智能厕所
如何用Link Develop开发一个智能厕所

进入Link Develop平台,跟其他云产品一样,需要先完成基本的入驻信息填写。
如何用Link Develop开发一个智能厕所

接下来我们会进入到一个项目空页面,我们需要在页面顶部点击“新建设备模型”。打开设备模型弹窗,输入名称以及定义类别,这里我们选择“自定义类型”即可。然后进入到设备模型的详情页之后,添加标准功能——输入红外——选择红外检测状态。我们就完成了一个可以上报红外检测数据的设备模型了。这个模型已经满足我们的需求。
如何用Link Develop开发一个智能厕所

然后我们需要实例化我们的厕所监控设备,在设备模型详情页里点击“测试设备”tab。然后依次创建9个不同设备名称(deviceName)的测试设备。每个设备建立完成后都有一个ProductKey,DeviceName和DeviceSecret,我们简称为“三元组”,接下来我们还会用到这个。
如何用Link Develop开发一个智能厕所

做完这些步骤之后,设备模型的建立与实例化就OK了。接下来我们进入Arduino代码编写。

硬件开发

PIR只有三个口,分别是VCC,GND和输出口。接线方法如下(NodeMCU的D7相当于arduino里的Pin 13)
如何用Link Develop开发一个智能厕所

然后接上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为例,具体操作方法见下图:
如何用Link Develop开发一个智能厕所

修改WiFi

#define WIFI_SSID         "yourssid"
#define WIFI_PASSWD       "yourwifipassword"

这里要输入你家的wifi SSID(即wifi名称)和密码。如下图红框内wifi,SSID即“TOM”(注意大小写),密码是“123456”
如何用Link Develop开发一个智能厕所

修改三元组

/* 产品的三元组信息,根据9个测试设备的三元组,每个设备都烧录不同的*/
#define PRODUCT_KEY       "yourproductKey"
#define DEVICE_NAME       "yourdeviceName"
#define DEVICE_SECRET     "yourdeviceSecret"

这里就是之前说的三元组,把不同设备的对应三元组填入即可。
如何用Link Develop开发一个智能厕所

修改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为密钥。见下图:
如何用Link Develop开发一个智能厕所

可以得到如下的密文:
e30657f36e7ded9a2781bba97b0dee79e8fa31b6
然后替换掉MQTT_PASSWD原来的字段即可。

完成代码编译之后,选择好对应的开发板和烧录线即可进行上传。通电之后可以查看串口以及Link Develop上的测试设备列表看看有否成功上线。
如何用Link Develop开发一个智能厕所
如何用Link Develop开发一个智能厕所

应用开发

点击左侧栏的Web应用开发,选择“可视化应用”并输入名称。然后就进入可视化开发Web应用的工作台了。
如何用Link Develop开发一个智能厕所

然后我们需要文字组件用来表示标题等。需要指示灯用来表示当前坑位有没有人的状态。
如何用Link Develop开发一个智能厕所

接下来以坑位1为例举例如何将组件绑定设备。点击右侧面板的“数据”,选择关联设备。这里会显示出所有已经创建的测试设备。选择对应坑位的传感器,之后选择展示的数据(布尔型的红外监测状态)。这样就完成了绑定数据了。
如何用Link Develop开发一个智能厕所

可以通过模拟上线看看是否成功关联。另外有一些个性化的样式也可以自己配置。
如何用Link Develop开发一个智能厕所

接下来就是发挥创造力的时候了。可以上传各种背景图,加各种小样式,做成如图的看板。最后点击右上角预览即可。
如何用Link Develop开发一个智能厕所

这样就完成了一个看板了!不用忍气吞声,直接查看厕所有没有空余坑位!
钉钉推送的教程后续会跟进同步~

部署

这是实体装机的盒子。为了更好的用户体验,我们在盒子上加了一个字条“只检测有人,没有摄像头”,以免用户产生隐私方面的担忧。
如何用Link Develop开发一个智能厕所
如何用Link Develop开发一个智能厕所

部署的时候用了树莓派+显示屏。
如何用Link Develop开发一个智能厕所

造福90%飞天园区一号楼四楼员工的智能厕所解决方案,完成!

欢迎使用Link Develop

Link Develop(物联网开发平台)是阿里云针对物联网领域提供的端到端一站式开发服务平台,可覆盖各个物联网行业应用场景,主要解决物联网开发领域开发链路长、技术栈复杂、协同成本高、方案移植困难的问题,提供了从硬件开发、服务编排、Web应用开发到移动APP开发全链路的开发流程、框架/引擎和调试工具,并可将成熟的开发产出物对接阿里云云市场进行售卖,为开发者实现商业收益。
这篇文章的两个作者,一位是学法律出身的运营同学,一位是学设计出身的UED同学,两位都不是专业的工程师,却能在短短一天之内基于Link Develop完成整个智能厕所的解决方案搭建。相信大家认识到了Link Develop平台的开发能力之后,会有更多更新奇的idea出现,并且借助Link Develop快速实现物联网应用开发!
欢迎访问:https://linkdevelop.aliyun.com

上一篇:设计满足预期的用户体验


下一篇:锐捷网络:让“店商”感知“大数据”的力量