当前位置:   article > 正文

用ESP8266连接ONENET做远程控制开关(内置定时)_onenet实现定时功能

onenet实现定时功能

        物联网的硬件已经越来越便宜了,ESP8266虽已被淘汰,但价格便宜,做智能开关还是非常不错的。中国移动旗下的ONENET物联网平台优点是服务器稳定快速,对个人爱好者很大方,注册后即可免费创建100个设备,如果个人实名认证可免费创建1000个设备。缺点是开发复杂,难度大。网上的教程版本落后,很多不能用,需要自己花大量时间去摸索。下面就自己做开关的经历简单记录下,也给后面想做远程控制定时开关的友友们一个少走弯路的参考。

      由于手机端APP用ONENET的API控制的,场景控制里不能控制定时功能,所以本设备端包含内置的定时远程控制接口,便于手机端设置定时控制(设置后即使断网也能定时控制)。先说一下设备开发端比一般开关增加的功能:1.内置局域网服务控制;2.内置远程定时控制功能;3.设备端将WIFI信息上传。下面是设备代码部分,根据自己的修改即可使用:

#include <ESP8266WebServer.h>

#include <PubSubClient.h>

#include <WiFiUDP.h>

#include <NTPClient.h>

#include <Ticker.h>

const char *WiFi_SSID = "XXXXX";//连接的路由名称,替换成你的

const char *WiFi_Password = "XXXXX";//路由密码,替换成你的

const char *Device_ID = "KaiGuan";//设备名称id,替换成你的

const char *Product_ID = "XXXXXX"; //平台分配的产品ID ,替换成你的

const char *Api_KEY = "XXXXXXXXXXX";//填写经过 key 计算的 token

const char* mqttServer = "mqtts.heclouds.com";

const uint16_t mqttPort = 1883;

#define WIFI_NAME "OneNet_KG"//设备无线名称,可换

struct TimeTaskStruct

{

  int on;//定时任务是否开启,0关1开

  int min;//分钟,如20表示20分钟

  int hour;//小时,如23表示23点

  char week[7];//星期,7个字符分别表示每周的一天,0不执行1执行,如0111111表示周日不执行其它时间执行

  int state;//执行动作,0断开,1闭合,2重启设备

};

TimeTaskStruct Timetask[4];//内部的定时器结构,可设置4个定时器

int num=0;

Ticker ticker;

#define ONENET_POST "$sys/产品ID/KaiGuan/thing/property/post"//产品ID,设备ID要换

#define ONENET_SCRIBE "$sys/产品ID/KaiGuan/thing/property/set"//产品ID,设备ID要换

#define ONENET_GETDESIRED "$sys/产品ID/KaiGuan/thing/property/desired/get"//产品ID,设备ID要换

#define ONENET_DESIRED "$sys/产品ID/KaiGuan/thing/property/desired/get/reply"//产品ID,设备ID要换

#define ONENET_FORMAT "{\"id\": \"1\",\"params\": {\"switch1\": {\"value\": %d}}}"//根据这个在ONENET平台设置设备的属性值

#define ONENET_FORMAT_WIFI "{\"id\": \"2\",\"params\": {\"wifi_ip\": {\"value\":{\"ip\":\"%s\",\"Signal\":\"%ld\",\"ssid\":\"%s\"}}}}"//上传WIFI信息,便于手机端显示

#define ONENET_FORMAT_TIMER "{\"id\":\"3\",\"params\":{\"timer\":{\"value\":[\"%s\",\"%s\",\"%s\",\"%s\"]}}}"//根据这个在ONENET平台设置定时器的属性


 

char Upload_Package[150];

uint32_t Last_Updata_Time = 0;

uint32_t Updata_Time = 0;

const int MQTTping = 58;

int stat=0;

int GPIO=0;

String WifiIP="";

ESP8266WebServer server(80);

String html="<!DOCTYPE html><html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'/><title>ESP8266 WEB控制</title><style type='text/css'>.login-box { width: 400px;margin: 0 auto;background-color: #F7F7F7;  border-radius: 10px;  padding-top: 5px; padding-right: 5px; padding-bottom: 5px;  padding-left: 5px;  }.login-box h2 {  color: #444;  text-align: center;}.login-box input[type='password']{  width: 50%;  height:40px;  padding: 2px;  border: none;  border-radius: 3px;  background-color: #EFEFEF;  font-size: 14px;  color: #444;  margin-left: 26px;}.login-box input[type='password']:focus{  outline: none;  box-shadow: 0 0 5px #1E90FF;}.login-box button[type='button'] {  width: 25%; border: none; border-radius: 3px; padding: 12px;  background-color: #1E90FF;  color: #FFF;  cursor: pointer;  transition: background-color 0.3s;  margin-left: 20px;}.login-box button[type='button']:disabled{      color: #ccc;      background-color: #f5f5f5;      cursor: not-allowed;  }.progress-bar {        height: 15px;  padding: 5px;      border-radius: 5px;        overflow: hidden;      }  .bar {        height: 100%;     background: linear-gradient(to right, red, yellow, green);       width: 0;       transition: width 0.5s ease-in-out;     }   input[type='checkbox']{appearance: none;width: 64px;height: 32px;position: relative;border-radius: 16px;cursor: pointer;background-color: #777;}input[type='checkbox']:before{        content: '';        position: absolute;        width: 28px;        height: 28px;        background: white;        left: 2px;        top: 2px;border-radius:50%;        transition: left cubic-bezier(0.3, 1.5, 0.7, 1) 0.3s;   background: linear-gradient(#fdfdfd, #afaaaa);}input[type='checkbox']:after {        content: '开 关';        text-indent: 12px;        word-spacing: 4px;        display: inline-block;        white-space: nowrap;color:white;        font: 14px/30px monospace;        font-weight: bold;    }input[type='checkbox']:checked {background-color:#FF3300;background:linear-gradient(to right,red, #fac000);}input[type='checkbox']:checked:before{left: 34px;}input[type='checkbox']:checked:after {color: black;}</style><script src='https://code.jquery.com/jquery-3.5.1.min.js'></script><script>function showBlock(){var password=$('#pass0').val();event.preventDefault();$.ajax({url: '/password',type:'POST',data:{pass0:password},success: function(result) {if(result=='1') {document.getElementById('stat').style.display = 'none';document.getElementById('hidden-switch').style.display = 'block';document.getElementById('hidden-update').style.display = 'block';}else alert('密码错误!请重新输入');}});}function checkbox_button(){var tmp_check=document.getElementById('checkbox1').checked;  if(true==tmp_check)   {document.getElementById('text_stat').innerHTML='已打开';$.ajax({url: '/led/on',success: function(result) {console.log(result);}});} else    {document.getElementById('text_stat').innerHTML='已关闭';$.ajax({url: '/led/off',success: function(result) {console.log(result);}});}}$(document).ready(function(){var result;$.ajax({url: '/ledstate',success: function(result) {if(result==='state:on') {document.getElementById('text_stat').innerHTML='已打开';document.getElementById('checkbox1').checked=true;} if(result=== 'state:off') {console.log('off');document.getElementById('text_stat').innerHTML='已关闭';document.getElementById('checkbox1').checked=false;}}});})</script><script>var progress = 0;  var xhr = new XMLHttpRequest();var state=document.getElementById('update_stat'); function updateFirmware(){        var formData = new FormData();  document.getElementById('upbutton').disabled = true;      formData.append('firmware', document.getElementById('firmwareFile').files[0]);        xhr.open('POST', '/update', true);        xhr.upload.onprogress = function(e) {          if (e.lengthComputable) {            progress = (e.loaded / e.total) * 100;            document.getElementById('bar').style.width = progress + '%';       if (progress === 100) {            document.getElementById('update_stat').innerHTML = '已完成100%,正在重启中,1分钟后请刷新页面!';          document.getElementById('upbutton').disabled = false;          }       else {document.getElementById('update_stat').innerHTML = '已更新'+Math.round(progress) +'%'; }       }        };     xhr.send(formData);      }</script></head><body><div class='login-box'><h2>EPS8266 WEB控制</h2><form id='stat' action='/password' method='post' ><input class='input-box' type='password' id='pass0' placeholder='请输入密码'><button type='button' onClick=\"showBlock();\">登录</button></form><div style='margin-top:40px;height:60;display:none' id='hidden-switch'><div style='position:absolute;margin-left:20px;width:80px'><p id='text_stat'>已关闭</p></div><div style='position:absolute;margin-left:130px; margin-top:10px'><input name='checkbox' type='checkbox' id='checkbox1' class='switch'  οnchange=\"checkbox_button()\"></div></div>  <div style='border-style:solid;border-width:1px;border-color:red; padding:10px;margin-top:120px;display:none' id='hidden-update' ><form method='POST' action='/update' enctype='multipart/form-data' id='upload_form'>    <input type='file' id='firmwareFile'>   <button type='button' id='upbutton' onClick=\"updateFirmware();\">更新</button></form><div class='progress-bar'><div class='bar' id='bar'></div></div><div style='text-align: center'><p id='update_stat'> </p></div>  </div></div></body></html>";

WiFiClient espClient;

PubSubClient client(espClient);

WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "time1.cloud.tencent.com",60*60*8, 20*1000);

void WiFi_Init(void);

void MQTT_Init(void);

void MQTT_Reconnection(void);

void MQTT_Callback(char *MQTT_Topic, byte *MQTT_Payload, uint16_t MQTT_Payload_Len);

void CrontoDate(char *t);

void PayloadtotimeTask(char *t,int types);

void RESET();

void handleRoot()

{

     server.send ( 200, "text/html", html);

 }

void handleLedOn()

{

 digitalWrite(GPIO,LOW);

  stat=1;

  Kaigun_stat(stat);

}

void handleLedOff()

{

  digitalWrite(GPIO, HIGH);

  stat=0;

  Kaigun_stat(stat);

}

void handlestate()

{

char strtmp[4] = {0};

itoa(stat,strtmp,10);

String tmp="state:";

tmp+=strtmp;

tmp+="SSID:";

tmp+=WiFi.SSID().c_str();

tmp+="RSSI:"+WiFi.RSSI();

server.send(200,"text/state",tmp);

}

void handlepassword()

{

    String password =server.arg("pass0");

    if (password=="wang") {server.send(200,"text/plain","1");}

    else  { server.send(200,"text/plain","0");}

}

void setup()

{

  Serial.begin(115200);

    pinMode(GPIO, OUTPUT);

    digitalWrite(GPIO, HIGH);

for(int i=0;i<4;i++)

{Timetask[i].on=Timetask[i].state=0;

Timetask[i].min=Timetask[i].hour=0;

for(int a=0;a<7;a++)

Timetask[i].week[a]='0';

}

memset(Upload_Package, 0, 150);

  WiFi_Init();

  timeClient.begin();

  MQTT_Init();

  server.on("/", handleRoot);

  server.on("/led/on", handleLedOn);

  server.on("/led/off", handleLedOff);

  server.on("/state", handlestate);

  server.on("/password", handlepassword);

server.on("/update", HTTP_POST, []() {

      server.sendHeader("Connection", "close");

      server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");

      ESP.restart();

    }, []() {

      HTTPUpload& upload = server.upload();

      if (upload.status == UPLOAD_FILE_START) {

        Serial.setDebugOutput(true);

        WiFiUDP::stopAll();

        Serial.printf("Update: %s\n", upload.filename.c_str());

        uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;

        if (!Update.begin(maxSketchSpace)) {

          Update.printError(Serial);

        }

      } else if (upload.status == UPLOAD_FILE_WRITE) {

        if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {

          Update.printError(Serial);

        }

      } else if (upload.status == UPLOAD_FILE_END) {

        if (Update.end(true)) {

          Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);

        } else {

          Update.printError(Serial);

        }

        Serial.setDebugOutput(false);

      }

      yield();

    });

  server.begin();

}

void Kaigun_stat(int stat)

{

  sprintf(Upload_Package,ONENET_FORMAT,stat);

  client.publish(ONENET_POST,Upload_Package);

}

void loop()

{

  server.handleClient();

if(WiFi.status() != WL_CONNECTED)  {    delay(500);}

  if (!client.connected()) {client.disconnect();

                          delay(5000);MQTT_Init();}

 if (millis() - Last_Updata_Time >= 60000)

  {

    Last_Updata_Time = millis();

   WifiIP=WiFi.localIP().toString().c_str();

   sprintf(Upload_Package,ONENET_FORMAT_WIFI,WifiIP.c_str(),WiFi.RSSI(),WiFi.SSID().c_str());

  client.publish(ONENET_POST,Upload_Package);

   }

  client.loop();

if(millis() -Updata_Time>=3000)

  {

  Updata_Time = millis();

  num++;

  if(num<10)    timeClient.update();    

   

    for(int i=0;i<4;i++)

    {

    if(Timetask[i].on==1)

      {  int day=timeClient.getDay();

       

        if(Timetask[i].week[day]=='1')

        {

          if(Timetask[i].hour==timeClient.getHours()&&Timetask[i].min==timeClient.getMinutes())

          {

            if(Timetask[i].state==1)

              {if(stat==0)

                {;stat=1;digitalWrite(GPIO,LOW);Kaigun_stat(stat);}

              }

            else if(Timetask[i].state==0)

              {

                if(stat==1) {stat=0;digitalWrite(GPIO,HIGH); Kaigun_stat(stat);}

              }    

            else if(Timetask[i].state==2) {ticker.attach(59, RESET);}

          }

        }

      }

    }

 }

wifi_set_sleep_type(LIGHT_SLEEP_T);

delay(100);

}

void WiFi_Init(void)

{

  Serial.print("\r\n\r\nConnecting to ");

  Serial.print(WiFi_SSID);

  WiFi.mode(WIFI_STA);

  WiFi.setHostname(WIFI_NAME);

  WiFi.begin(WiFi_SSID, WiFi_Password);

  while (WiFi.status() != WL_CONNECTED)

  {

    delay(500);

    Serial.print(".");

  }

  Serial.println(WiFi.localIP());

}

void MQTT_Init(void)

{

  client.setServer(mqttServer, mqttPort);

  client.setCallback(MQTT_Callback);

   client.setKeepAlive(MQTTping);

  if (client.connect(Device_ID, Product_ID, Api_KEY))

  {

     Serial.printf("MQTT link suss!\r\n");

    client.subscribe(ONENET_SCRIBE);

    client.subscribe(ONENET_DESIRED);

  Kaigun_stat(stat);

 client.publish(ONENET_GETDESIRED,"{\"id\":\"3\",\"params\":[\"switch1\",\"timer\"]}");

  }

}

void MQTT_Callback(char *MQTT_Topic, byte *MQTT_Payload, uint16_t MQTT_Payload_Len)

{

  Serial.printf("Topic: %s[%d]:\r\n", MQTT_Topic, MQTT_Payload_Len);

  for(uint16_t i=0; i<MQTT_Payload_Len; i++) Serial.print((char)MQTT_Payload[i]);

  MQTT_Payload[MQTT_Payload_Len]='\0';

  char *payloadtmp=(char *)MQTT_Payload;

  if(strstr(MQTT_Topic,"set")!= NULL)      PayloadtotimeTask(payloadtmp,0);

  if(strstr(MQTT_Topic,"get/reply")!= NULL)      PayloadtotimeTask(payloadtmp,1);

   

}

void PayloadtotimeTask(char *t,int types)

{

    char *strtmp=strstr(t,"switch1");

    if(strtmp!=NULL)

   { char ctmp='0';

     if(types==0)

        {ctmp=*(strtmp+9);          }

    if(types==1)

       {strtmp=strstr(strtmp,"value");      ctmp=*(strtmp+7);}

   

    if(ctmp=='1') {stat=1;digitalWrite(GPIO,LOW);Kaigun_stat(stat);}

    else if(ctmp=='2') {RESET();}

    else {stat=0;digitalWrite(GPIO,HIGH); Kaigun_stat(stat);}

     

   }  

   char *strtmp1=strstr(t,"[");

   if(strtmp1!=NULL)

     {

          char* end = strstr(strtmp1 + 1, "]");

          if (end != NULL)

          {

          char time[end - strtmp1 ];  

          strncpy(time, strtmp1 + 1, end - strtmp1-1);

          time[end - strtmp1-1] = '\0';

          CrontoDate(time);

          }

      }

   

}

void CrontoDate(char *t)

{

  char *tmp=t;

  char *strtmp;

  char subtime[4][18];

  for(int i=0;i<4;i++)

  { strtmp=strstr(tmp,"\"");

   char* end = strstr(strtmp + 1, "\"");

    if(end!=NULL){

      char time[end - strtmp ];  

        strncpy(time, strtmp + 1, end - strtmp-1);

        time[end - strtmp-1] = '\0';

        int s=sscanf(time,"%1d%1d %d %d %s",&Timetask[i].on,&Timetask[i].state,&Timetask[i].min,&Timetask[i].hour,Timetask[i].week);

        if(s<1) {Timetask[i].on=0;}

        strcpy(subtime[i],time);

        tmp=end+1;

      }

  }

  sprintf(Upload_Package,ONENET_FORMAT_TIMER,subtime[0],subtime[1],subtime[2],subtime[3]);

  client.publish(ONENET_POST,Upload_Package);

}

void RESET(){

  ESP.reset();

}

后面有空继续完善ESP8266的开关教程。可加入QQ群:199183673,一起学习,共同提高!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/398041
推荐阅读
相关标签
  

闽ICP备14008679号