MySensors Library & Examples  2.3.2-62-ge298769
UDPHelper_ARDUINO.h
1 #pragma once
2 
3 #ifdef PJON_ESP
4 #if defined(ESP32)
5 #include <WiFi.h>
6 #else
7 #include <ESP8266WiFi.h>
8 #endif
9 #include <WiFiUdp.h>
10 #define PJON_ESP
11 #else
12 #ifdef PJON_ETHERNET2
13 #include <Ethernet2.h>
14 #include <EthernetUdp2.h>
15 #else
16 #include <Ethernet.h>
17 #include <EthernetUdp.h>
18 #endif
19 #endif
20 
21 class UDPHelper
22 {
23  uint16_t _port;
24  uint32_t _magic_header;
25 
26 #ifdef PJON_ESP
27  WiFiUDP udp;
28 #else
29  EthernetUDP udp;
30 #endif
31  uint8_t _broadcast[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
32 
33 public:
34 
35  bool begin(uint16_t port)
36  {
37  _port = port;
38  return udp.begin(_port);
39  }
40 
41  uint16_t receive_frame(uint8_t *data, uint16_t max_length)
42  {
43  uint16_t result = PJON_FAIL;
44  int16_t packet_size = udp.parsePacket();
45  if(packet_size > 0) {
46  uint32_t header = 0;
47  int16_t len = udp.read((char *) &header, 4), remaining = packet_size - len;
48  if (len == -1) {
49  return result;
50  }
51  if(len == 4 && header == _magic_header && (unsigned)packet_size <= 4 + max_length) {
52  len = udp.read(data, packet_size - 4);
53  if (len == -1) {
54  return result;
55  }
56  if (len == packet_size - 4) {
57  result = packet_size - 4;
58  }
59  remaining -= len;
60  }
61  if (remaining > 0) {
62  // We must still read every byte because some implementations
63  // (like ESP32) will not clear the receive buffer and therefore will
64  // not receive any more packets otherwise.
65  while (remaining > 0 && len > 0) {
66  len = udp.read(data, (unsigned)remaining <= max_length ? remaining : max_length);
67  if (len > 0) {
68  remaining -= len;
69  }
70  }
71  }
72  }
73  return result;
74  }
75 
76  void send_frame(uint8_t *data, uint16_t length, IPAddress remote_ip, uint16_t remote_port)
77  {
78  if(length > 0) {
79  udp.beginPacket(remote_ip, remote_port);
80 #if defined(ESP32)
81  udp.write((const unsigned char*) &_magic_header, 4);
82 #else
83  udp.write((const char*) &_magic_header, 4);
84 #endif
85  udp.write(data, length);
86  udp.endPacket();
87  }
88  }
89 
90  void send_response(uint8_t *data, uint16_t length)
91  {
92  send_frame(data, length, udp.remoteIP(), udp.remotePort());
93  }
94 
95  void send_response(uint8_t response)
96  {
97  send_frame(&response, 1, udp.remoteIP(), udp.remotePort());
98  }
99 
100  void send_frame(uint8_t *data, uint16_t length, uint8_t remote_ip[], uint16_t remote_port)
101  {
102  IPAddress address(remote_ip);
103  send_frame(data, length, address, remote_port);
104  }
105 
106  void send_frame(uint8_t *data, uint16_t length)
107  {
108  // Broadcast on local subnet, global broadcast may not be accepted
109  IPAddress broadcastIp;
110 #ifdef PJON_ESP
111  // 255.255.255.255 may not work, be more specific
112  broadcastIp = ~(uint32_t)WiFi.subnetMask() | (uint32_t)WiFi.localIP();
113 #else
114  broadcastIp = _broadcast;
115 #endif
116  send_frame(data, length, broadcastIp, _port);
117  }
118 
119  void set_magic_header(uint32_t magic_header)
120  {
121  _magic_header = magic_header;
122  }
123 
124  void get_sender(uint8_t *ip, uint16_t &port)
125  {
126  uint32_t ip_address = udp.remoteIP();
127  memcpy(ip, &ip_address, 4);
128  port = udp.remotePort();
129  }
130 };
data
char data[MAX_PAYLOAD_SIZE+1]
Buffer for raw payload data.
Definition: MyMessage.h:654
IPAddress
A class to make it easier to handle and pass around IP addresses.
Definition: IPAddress.h:32
UDPHelper
Definition: UDPHelper_ARDUINO.h:21