物联网技术
直播中

李波

7年用户 1399经验值
私信 关注
[问答]

如何使用EDP协议通过ESP8266 WIFI模块接入OneNET服务器来实现远程控制LED灯?

本项目完成了Arduino使用EDP协议通过ESP8266 WIFI模块接入OneNET服务器,并通过在接入设备中创建的应用来实现远程控制LED灯。

回帖(1)

李皓圳

2021-6-16 16:05:17
  Arduino是许多智能硬件爱好者的首选,使用简单快捷,而ESP8266模块也是当前最为热门的WIFI模块。本项目完成了Arduino使用EDP协议通过ESP8266 WIFI模块接入OneNET服务器,并通过在接入设备中创建的应用来实现远程控制LED灯。
  【1】硬件连接:
  准备元件:
  Arduino UNO
  ESP8266 WIFI模块
  USB转TTL连接线
  硬件连线:
  Arduino UNO USB转TTL
  D2-----------------RX
  D3-----------------TX
  GND---------------GND
  Arduino UNO ESP8266
  RX-----------------TX
  TX-----------------RX
  GND---------------GND
  其中USB转TTL连接电脑用于调试打印输出,然后Arduino的串口连接ESP8266的串口。
  实物连接如下如图所示:
  【2】ESP8266配置和EDP上传数据介绍:
  选用ESP8266串口WIFI模块,通过AT指令控制WIFI模块接入互联网,依次完成与接入互联网、与OneNet服务器建立TCP连接、传输数据等操作。
  1)配置WIFI模块;
  模块配置接入OneNet,依次发送如下几个命令到WIFI模块:
  AT+CWMODE=3
  AT+RST
  AT+CIFSR
  AT+CWJAP=“your ssid”,“password”
  2)和OneNet服务器建立TCP连接,依次发送命令:
  AT+CIPSTART=“TCP”,“183.230.40.39”,876 //和服务器建立TCP连接
  AT+CIPMODE=1 //进入透明传输模式
  AT+CIPSEND //开始传输
  命令执行结果如下图所示:
  【3】创建设备和应用:
  添加产品并创建接入设备,详细创建步骤请查看:http://open.iot.10086.cn/doc/art243.html#66。其中数据传输协议选择EDP。
  在设备中添加应用,创建一个开关控件,在右侧的属性中选择对应设备的switch0数据流 ·注意到属性中有开关开值和开关关值两个属性,分别默认为1,0,这里不做修改(因为代码中1为开,非1则为关) ·修改EDP命令内容为switch0:{v}(与代码对应,代码中会将冒号前的部分作为上传的数据流ID,而将冒号之后的部分作为上传是数据值) 这里的{v}是通配符当下发命令的时候,他将会被开关的开/关值取代,稍后我们将看到命令的内容。
  编辑完成后点击保存应用。
  【4】软件代码:
  其中Arduino开发板的D13作为被控制的LED灯,在程序中添加设备ID和APIKey。
  /*
  采用外接电源单独供电,2 3口作为软串口接PC机作为调试端
  1 0为串口,连接WIFI模块
  */
  #include
  #include “edp.c”
  #define KEY “XpAhYrqhsZbk9eVqESnMJznDb3A=” //APIkey
  #define ID “4051313” //设备ID
  //#define PUSH_ID “680788”
  #define PUSH_ID NULL
  // 串口
  #define _baudrate 115200
  #define _rxpin 3
  #define _txpin 2
  #define WIFI_UART Serial
  #define DBG_UART dbgSerial //调试打印串口
  SoftwareSerial dbgSerial( _rxpin, _txpin ); // 软串口,调试打印
  edp_pkt *pkt;
  /*
  * doCmdOk
  * 发送命令至模块,从回复中获取期待的关键字
  * keyword: 所期待的关键字
  * 成功找到关键字返回true,否则返回false
  */
  bool doCmdOk(String data, char *keyword)
  {
  bool result = false;
  if (data != “”) //对于tcp连接命令,直接等待第二次回复
  {
  WIFI_UART.println(data); //发送AT指令
  DBG_UART.print(“SEND: ”);
  DBG_UART.println(data);
  }
  if (data == “AT”) //检查模块存在
  delay(2000);
  else
  while (!WIFI_UART.available()); // 等待模块回复
  delay(200);
  if (WIFI_UART.find(keyword)) //返回值判断
  {
  DBG_UART.println(“do cmd OK”);
  result = true;
  }
  else
  {
  DBG_UART.println(“do cmd ERROR”);
  result = false;
  }
  while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
  delay(500); //指令时间间隔
  return result;
  }
  void setup()
  {
  char buf[100] = {0};
  int tmp;
  pinMode(13, OUTPUT); //WIFI模块指示灯
  pinMode(8, OUTPUT); //用于连接EDP控制的发光二极管
  WIFI_UART.begin( _baudrate );
  DBG_UART.begin( _baudrate );
  WIFI_UART.setTimeout(3000); //设置find超时时间
  delay(3000);
  DBG_UART.println(“hello world!”);
  delay(2000);
  while (!doCmdOk(“AT”, “OK”));
  digitalWrite(13, HIGH); // 使Led亮
  while (!doCmdOk(“AT+CWMODE=3”, “OK”)); //工作模式
  while (!doCmdOk(“AT+CWJAP=”PDCN“,”1234567890“”, “OK”));
  while (!doCmdOk(“AT+CIPSTART=”TCP“,”183.230.40.39“,876”, “CONNECT”));
  while (!doCmdOk(“AT+CIPMODE=1”, “OK”)); //透传模式
  while (!doCmdOk(“AT+CIPSEND”, “》”)); //开始发送
  }
  void loop()
  {
  static int edp_connect = 0;
  bool trigger = false;
  edp_pkt rcv_pkt;
  unsigned char pkt_type;
  int i, tmp;
  char num[10];
  /* EDP 连接 */
  if (!edp_connect)
  {
  while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
  packetSend(packetConnect(ID, KEY)); //发送EPD连接包
  while (!WIFI_UART.available()); //等待EDP连接应答
  if ((tmp = WIFI_UART.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) 》 0 )
  {
  rcvDebug(rcv_pkt.data, tmp);
  if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
  {
  edp_connect = 1;
  DBG_UART.println(“EDP connected.”);
  }
  else
  DBG_UART.println(“EDP connect error.”);
  }
  packetClear(&rcv_pkt);
  }
  while (WIFI_UART.available())
  {
  readEdpPkt(&rcv_pkt);
  if (isEdpPkt(&rcv_pkt))
  {
  pkt_type = rcv_pkt.data[0];
  switch (pkt_type)
  {
  case CMDREQ:
  char edp_command[50];
  char edp_cmd_id[40];
  long id_len, cmd_len, rm_len;
  char datastr[20];
  char val[10];
  memset(edp_command, 0, sizeof(edp_command));
  memset(edp_cmd_id, 0, sizeof(edp_cmd_id));
  edpCommandReqParse(&rcv_pkt, edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);
  DBG_UART.print(“rm_len: ”);
  DBG_UART.println(rm_len, DEC);
  delay(10);
  DBG_UART.print(“id_len: ”);
  DBG_UART.println(id_len, DEC);
  delay(10);
  DBG_UART.print(“cmd_len: ”);
  DBG_UART.println(cmd_len, DEC);
  delay(10);
  DBG_UART.print(“id: ”);
  DBG_UART.println(edp_cmd_id);
  delay(10);
  DBG_UART.print(“cmd: ”);
  DBG_UART.println(edp_command);
  //数据处理与应用中EDP命令内容对应
  //本例中格式为 datastream:[1/0]
  sscanf(edp_command, “%[^:]:%s”, datastr, val);
  if (atoi(val) == 1)
  digitalWrite(13, HIGH); // 使Led亮
  else
  digitalWrite(13, LOW); // 使Led灭
  packetSend(packetDataSaveTrans(NULL, datastr, val)); //将新数据值上传至数据流
  break;
  default:
  DBG_UART.print(“unknown type: ”);
  DBG_UART.println(pkt_type, HEX);
  break;
  }
  }
  //delay(4);
  }
  if (rcv_pkt.len 》 0)
  packetClear(&rcv_pkt);
  delay(150);
  }
  /*
  * readEdpPkt
  * 从串口缓存中读数据到接收缓存
  */
  bool readEdpPkt(edp_pkt *p)
  {
  int tmp;
  if ((tmp = WIFI_UART.readBytes(p-》data + p-》len, sizeof(p-》data))) 》 0 )
  {
  rcvDebug(p-》data + p-》len, tmp);
  p-》len += tmp;
  }
  return true;
  }
  /*
  * packetSend
  * 将待发数据发送至串口,并释放到动态分配的内存
  */
  void packetSend(edp_pkt* pkt)
  {
  if (pkt != NULL)
  {
  WIFI_UART.write(pkt-》data, pkt-》len); //串口发送
  WIFI_UART.flush();
  free(pkt); //回收内存
  }
  }
  void rcvDebug(unsigned char *rcv, int len)
  {
  int i;
  DBG_UART.print(“rcv len: ”);
  DBG_UART.println(len, DEC);
  for (i = 0; i 《 len; i++)
  {
  DBG_UART.print(rcv[i], HEX);
  DBG_UART.print(“ ”);
  }
  DBG_UART.println(“”);
  }
  【5】功能测试:
  设备上电后,可以看到电脑串口打印输出的内容,首先连接OneNET服务器:
  连接成功后,可以看到设备在线状态:
  点击设备应用中的开关按钮,发送开关命令给设备:
  设备接收命令后进行解析,并在串口打印输出:
  当解析到数据流switch0的值为1时设备开灯,Arduino 开发板的D13被点亮,相反为0时灯灭。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分