|
6 | 6 |
|
7 | 7 | #include "knx/bits.h" |
8 | 8 |
|
| 9 | + |
| 10 | +#include <string.h> |
| 11 | + |
9 | 12 | // #ifndef KNX_SERIAL |
10 | 13 | // #define KNX_SERIAL Serial1 |
11 | 14 | // #pragma warn "KNX_SERIAL not defined, using Serial1" |
@@ -73,117 +76,184 @@ void Esp32Platform::setupMultiCast(uint32_t addr, uint16_t port) |
73 | 76 | println("No network interface initialized"); |
74 | 77 | fatalError(); |
75 | 78 | } |
76 | | - IPAddress mcastaddr(htonl(addr)); |
77 | | - IPAddress mcastaddr2(htonl(addr+1)); |
| 79 | + |
| 80 | + _udpSockMulticastAddr.sin_family = AF_INET; |
| 81 | + _udpSockMulticastAddr.sin_addr.s_addr = htonl(addr); |
| 82 | + _udpSockMulticastAddr.sin_port = htons(port); |
78 | 83 |
|
79 | | - println("Initializing KNX multicast."); |
80 | | - print(" Bind "); |
81 | | - print(mcastaddr.toString().c_str()); |
82 | | - print(":"); |
83 | | - println(port); |
84 | | - uint8_t result = _udp.beginMulticast(mcastaddr, port); |
85 | | -#ifdef TEST_MC_ONESOCKET |
86 | | - _udp.beginMulticast(mcastaddr2, port); |
87 | | -#else |
88 | | - _udp2.beginMulticast(mcastaddr2, port); |
89 | | -#endif |
| 84 | + // Create multicast socket |
| 85 | + int _udpSockMulticast = socket(AF_INET, SOCK_DGRAM, 0); |
| 86 | + if (_udpSockMulticast < 0) |
| 87 | + { |
| 88 | + println("Failed to create multicast socket"); |
| 89 | + } |
90 | 90 |
|
91 | | - |
| 91 | + // Set socket options for multicast |
| 92 | + int opt = 1; |
| 93 | + setsockopt(_udpSockMulticast, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); |
92 | 94 |
|
| 95 | + // Bind the socket to the multicast address |
| 96 | + if (bind(_udpSockMulticast, (struct sockaddr*)&_udpSockMulticastAddr, sizeof(_udpSockMulticastAddr)) < 0) |
| 97 | + { |
| 98 | + println("Failed to bind multicast socket"); |
| 99 | + close(_udpSockMulticast); |
| 100 | + } |
93 | 101 |
|
| 102 | + // Join multicast group |
| 103 | + ip_mreq mreq; |
| 104 | + mreq.imr_multiaddr.s_addr = htonl(addr); |
| 105 | + mreq.imr_interface.s_addr = INADDR_ANY; |
| 106 | + if (setsockopt(_udpSockMulticast, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) |
| 107 | + { |
| 108 | + println("Failed to join multicast group"); |
| 109 | + close(_udpSockMulticast); |
| 110 | + } |
94 | 111 |
|
| 112 | + // Create unicast socket |
| 113 | + int _udpSockUnicast = socket(AF_INET, SOCK_DGRAM, 0); |
| 114 | + if (_udpSockUnicast < 0) |
| 115 | + { |
| 116 | + println("Failed to create unicast socket"); |
| 117 | + } |
95 | 118 |
|
| 119 | + // Bind the unicast socket to the same port |
| 120 | + struct sockaddr_in unicast_addr; |
| 121 | + unicast_addr.sin_family = AF_INET; |
| 122 | + unicast_addr.sin_addr.s_addr = INADDR_ANY; // or specific unicast address |
| 123 | + unicast_addr.sin_port = htons(port); // use the same port as multicast |
| 124 | + if (bind(_udpSockUnicast, (struct sockaddr*)&unicast_addr, sizeof(unicast_addr)) < 0) |
| 125 | + { |
| 126 | + println("Failed to bind unicast socket"); |
| 127 | + close(_udpSockUnicast); |
| 128 | + } |
96 | 129 |
|
97 | | - (void)result; // Suppress unused variable warning |
98 | | - // KNX_DEBUG_SERIAL.printf("result %d\n", result); |
| 130 | + println("Initializing KNX multicast."); |
| 131 | + print(" Bind "); |
| 132 | + print(IPAddress(htonl(addr)).toString().c_str()); |
| 133 | + print(":"); |
| 134 | + println(port); |
99 | 135 | } |
100 | 136 |
|
101 | 137 | void Esp32Platform::closeMultiCast() |
102 | 138 | { |
103 | | - _udp.stop(); |
| 139 | + if (_udpSockMulticast >= 0) |
| 140 | + { |
| 141 | + close(_udpSockMulticast); |
| 142 | + _udpSockMulticast = -1; // Mark as closed |
| 143 | + println("Multicast socket closed"); |
| 144 | + } |
| 145 | + |
| 146 | + if (_udpSockUnicast >= 0) |
| 147 | + { |
| 148 | + close(_udpSockUnicast); |
| 149 | + _udpSockUnicast = -1; // Mark as closed |
| 150 | + println("Unicast socket closed"); |
| 151 | + } |
104 | 152 | } |
105 | 153 |
|
106 | 154 | bool Esp32Platform::sendBytesMultiCast(uint8_t * buffer, uint16_t len) |
107 | 155 | { |
108 | | - //printHex("<- ",buffer, len); |
109 | | - _udp.beginMulticastPacket(); |
110 | | - _udp.write(buffer, len); |
111 | | - _udp.endPacket(); |
| 156 | + if (_udpSockMulticast < 0) |
| 157 | + { |
| 158 | + println("Multicast socket not initialized"); |
| 159 | + return false; |
| 160 | + } |
| 161 | + |
| 162 | + ssize_t sentBytes = sendto(_udpSockMulticast, buffer, len, 0, (struct sockaddr*)&_udpSockMulticastAddr, sizeof(_udpSockMulticastAddr)); |
| 163 | + if (sentBytes < 0) |
| 164 | + { |
| 165 | + println("Failed to send multicast data"); |
| 166 | + return false; |
| 167 | + } |
| 168 | + |
112 | 169 | return true; |
113 | 170 | } |
114 | 171 |
|
115 | 172 | int Esp32Platform::readBytesMultiCast(uint8_t * buffer, uint16_t maxLen, uint32_t& src_addr, uint16_t& src_port) |
116 | 173 | { |
117 | | - int len = _udp.parsePacket(); |
118 | | - if (len == 0) |
| 174 | + struct sockaddr_in src_addr_struct; |
| 175 | + socklen_t addrlen = sizeof(src_addr_struct); |
| 176 | + ssize_t len = recvfrom(_udpSockMulticast, buffer, maxLen, 0, (struct sockaddr*)&src_addr_struct, &addrlen); |
| 177 | + |
| 178 | + if (len < 0) |
119 | 179 | { |
120 | | - // check second socket for test purposes |
121 | | -#ifndef TEST_MC_ONESOCKET |
122 | | - len = _udp2.parsePacket(); |
123 | | - if (len == 0) |
124 | | - { |
125 | | - return 0; |
126 | | - } |
127 | | - else |
128 | | - { |
129 | | - _remoteIP = _udp2.remoteIP(); |
130 | | - _remotePort = _udp2.remotePort(); |
131 | | - src_addr = htonl(_remoteIP); |
132 | | - src_port = _remotePort; |
133 | | - |
134 | | - print("Receive UDP2 "); |
135 | | - print(_udp2.remoteIP().toString().c_str()); |
136 | | - print(":"); |
137 | | - println(_udp2.remotePort()); |
138 | | - printHex("-> ", buffer, len); |
139 | | - _udp2.read(buffer, len); |
140 | | - return len; |
141 | | - } |
142 | | -#else |
143 | 180 | return 0; |
144 | | -#endif |
145 | 181 | } |
146 | 182 |
|
147 | 183 | if (len > maxLen) |
148 | 184 | { |
149 | 185 | println("Unexpected UDP data packet length - drop packet"); |
150 | | - for (size_t i = 0; i < len; i++) |
151 | | - _udp.read(); |
152 | 186 | return 0; |
153 | 187 | } |
154 | 188 |
|
155 | | - _udp.read(buffer, len); |
156 | | - _remoteIP = _udp.remoteIP(); |
157 | | - _remotePort = _udp.remotePort(); |
158 | | - src_addr = htonl(_remoteIP); |
159 | | - src_port = _remotePort; |
| 189 | + src_addr = ntohl(src_addr_struct.sin_addr.s_addr); |
| 190 | + src_port = ntohs(src_addr_struct.sin_port); |
160 | 191 |
|
161 | | - print("Receive UDP "); |
162 | | - print(_udp.remoteIP().toString().c_str()); |
| 192 | + _remoteIP = src_addr; |
| 193 | + _remotePort = src_port; |
| 194 | + |
| 195 | + print("Receive Multicast UDP "); |
| 196 | + print(IPAddress(src_addr).toString().c_str()); |
163 | 197 | print(":"); |
164 | | - println(_udp.remotePort()); |
| 198 | + println(src_port); |
165 | 199 | printHex("-> ", buffer, len); |
166 | 200 |
|
167 | 201 | return len; |
168 | 202 | } |
169 | 203 |
|
170 | | -bool Esp32Platform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) |
| 204 | +int Esp32Platform::readBytesUniCast(uint8_t * buffer, uint16_t maxLen, uint32_t& src_addr, uint16_t& src_port) |
171 | 205 | { |
172 | | - IPAddress ucastaddr(htonl(addr)); |
| 206 | + struct sockaddr_in src_addr_struct; |
| 207 | + socklen_t addrlen = sizeof(src_addr_struct); |
| 208 | + ssize_t len = recvfrom(_udpSockUnicast, buffer, maxLen, 0, (struct sockaddr*)&src_addr_struct, &addrlen); |
| 209 | + |
| 210 | + if (len < 0) |
| 211 | + { |
| 212 | + return 0; |
| 213 | + } |
173 | 214 |
|
174 | | - if(!addr) |
175 | | - ucastaddr = _remoteIP; |
| 215 | + if (len > maxLen) |
| 216 | + { |
| 217 | + println("Unexpected UDP data packet length - drop packet"); |
| 218 | + return 0; |
| 219 | + } |
| 220 | + |
| 221 | + src_addr = ntohl(src_addr_struct.sin_addr.s_addr); |
| 222 | + src_port = ntohs(src_addr_struct.sin_port); |
| 223 | + |
| 224 | + _remoteIP = src_addr; |
| 225 | + _remotePort = src_port; |
| 226 | + |
| 227 | + print("Receive Unicast UDP "); |
| 228 | + print(IPAddress(src_addr).toString().c_str()); |
| 229 | + print(":"); |
| 230 | + println(src_port); |
| 231 | + printHex("-> ", buffer, len); |
| 232 | + |
| 233 | + return len; |
| 234 | +} |
| 235 | + |
| 236 | +bool Esp32Platform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) |
| 237 | +{ |
| 238 | + struct sockaddr_in dest_addr; |
| 239 | + dest_addr.sin_family = AF_INET; |
| 240 | + dest_addr.sin_addr.s_addr = htonl(addr); |
176 | 241 |
|
177 | | - if(!port) |
| 242 | + if (!addr) |
| 243 | + dest_addr.sin_addr.s_addr = htonl(_remoteIP); |
| 244 | + |
| 245 | + if (!port) |
178 | 246 | port = _remotePort; |
179 | 247 |
|
180 | | - if(_udp.beginPacket(ucastaddr, port) == 1) |
| 248 | + dest_addr.sin_port = htons(port); |
| 249 | + |
| 250 | + ssize_t sentBytes = sendto(_udpSockUnicast, buffer, len, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); |
| 251 | + if (sentBytes < 0) |
181 | 252 | { |
182 | | - _udp.write(buffer, len); |
183 | | - if(_udp.endPacket() == 0) println("sendBytesUniCast endPacket fail"); |
| 253 | + println("Failed to send unicast data"); |
| 254 | + return false; |
184 | 255 | } |
185 | | - else |
186 | | - println("sendBytesUniCast beginPacket fail"); |
| 256 | + |
187 | 257 | return true; |
188 | 258 | } |
189 | 259 |
|
|
0 commit comments