วันอาทิตย์ที่ 18 ตุลาคม พ.ศ. 2558

ESP8266 : UDP ภาคต่อกับรูปแบบ Multicast

 

จากตอนที่แล้วพบว่าการเชื่อมต่อระหว่างสองบอร์ดจะไม่สะดวกนัก เนื่องจากต้องรู้หมายเลข IP และต้องทำการ upload ทุกครั้งที่ IP เปลี่ยนแปลง

สำหรับระบบสื่อสารจะคุ้นชินกับคำว่า Broadcast และ Multicast ทั้งสองเป็นการสื่อสารแบบกลุ่ม

โดย Broadcast จะเหมือนกับการกระจายเสียงของวิทยุสาธารณะ ที่จะส่งข้อมูลออกแบบกระจาย ใครที่อยู่ใน subgroup เดียวกันกับผู่ส่ง ก็จะได้รับข้อมูลพร้อมกัน

ส่วน Multicast จะจัดกลุ่มแคบลงมาโดยการส่งข้อมูลแบบ multicast จะถูกกำหนดให้ส่งในช่วง IP Address ที่ 224.0.0.1 ไปถึง 239.255.255.255 ซึ่ง device ที่อยู่ในกลุ่มเดียวกันจะต้องมี Multicast IP เดียวกัน และใช้ Port ในการรับข้อมูลตัวเดียวกัย

สำหรับตัวอย่างจะใช้ Multicast IP ที่ 239.0.0.57  และรับส่งด้วย Port หมายเลข 5555

ส่วนของการทำโปรแกรม จะเริ่มใช้งาน UDP ด้วยการระบุ เพื่อเข้าร่วมกลุ่ม ตามนี้

IPAddress ipMulti(239,0,0,57);
int portMulti = 5555;

Udp.beginMulticast(WiFi.localIP(), ipMulti, portMulti);

WiFI.localIP() คือหมายเลข IP ที่ได้รับจาก WiFi router ซึ่งจะถูกส่งไปพร้อมกับข้อมูล ผู้รับสามารถตอบกลับข้อมูลมาที่หมายเลข IP นี้ ด้วยการอ้างอิงกับ Udp.remoteIP()

สำหรับการส่งข้อมูลไปที่กลุ่ม ให้ใช้

Udp.beginPacketMulticast(ipMulti, portMulti, WiFi.localIP());

* ตัวอย่างไม่ได้ทำการ Comment ในส่วนการตอบกลับไว้ เนื่องจากจะมีการสะท้อนไปมาหลายรอบ ถ้าใครต้องการทดสอบก็นำเอา Comment ออก

เมื่อข้อมูลถูกส่งออกไป อุปกรณ์ที่เป็นสมาชิกในกลุ่ม Multicast จะได้รับข้อมูลที่ส่งออกมาพร้อมกัน สามารถทดสอบได้ถ้ามีบอร์ดมากกว่าสองบอร์ด ก็จะเห็นผลของการส่ง Multicast ได้ชัดเจนขึ้น

ส่วนการนำไปใช้งานก็ตามอัธยาศัย

จากตอนที่แล้วและตอนนี้จะต้องอาศัย WiFi router สำหรับการแจกจ่ายหมายเลข IP ให้อุปกรณ์แต่ละตัว ในส่วนของบอร์ด ESP8266 สามารถทำเป็น Access point ได้ ตอนต่อไปจะตัดการใช้งานกับ WiFi router และใช้คุณสมบัติ Access point มาทำงานแทน

#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
WiFiUDP Udp;
char packetBuffer[512];
IPAddress ipMulti(239,0,0,57);
int portMulti = 5555;

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID","PASS");
  int dotCount = 0;
  while(WiFi.status() != WL_CONNECTED){
    delay(500);
    Serial.print(".");
    if(++dotCount > 30){
      dotCount = 0;
      Serial.println();
    }
  }
  Serial.print("Connect to Wifi (");
  Serial.print(WiFi.localIP());
  Serial.println(")");
  Udp.beginMulticast(WiFi.localIP(), ipMulti, portMulti);
}

String sendText = "";

void loop() {
  int noBytes = Udp.parsePacket();
  if(noBytes){
    Udp.read(packetBuffer, noBytes);
    packetBuffer[noBytes] = '\0';
    Serial.print(millis() / 1000);
    Serial.print(" : ");
    Serial.print(packetBuffer);
    Serial.print(" (from : ");
    Serial.print(Udp.remoteIP());
    Serial.print(":");
    Serial.print(Udp.remotePort());
    Serial.println(" )");

    /* Remove comment out for feedback test
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.print(WiFi.localIP());
    Udp.print(" got info.");
    Udp.endPacket();
    */
  }

  while(Serial.available()){
    char ch = Serial.read();
    if(ch != '\n'){
      sendText += ch;
    }else{
      Serial.print(" info: ");
      Serial.print(sendText);
      Udp.beginPacketMulticast(ipMulti, portMulti, WiFi.localIP());
      Udp.print(sendText);
      Serial.print(" (Send status (0:error, 1:OK): ");
      Serial.print(Udp.endPacket());
      Serial.println(")");
      sendText = "";
    }
  }
}

1 ความคิดเห็น: