SinricPro Library
Loading...
Searching...
No Matches
SinricProUDP.h
1/*
2 * Copyright (c) 2019 Sinric. All rights reserved.
3 * Licensed under Creative Commons Attribution-Share Alike (CC BY-SA)
4 *
5 * This file is part of the Sinric Pro (https://github.com/sinricpro/)
6 */
7
8#pragma once
9
10#if defined(ESP8266)
11 #include <ESP8266WiFi.h>
12 #define SINRICPRO_UDP_LWIP
13#elif defined(ESP32)
14 #include <WiFi.h>
15 #define SINRICPRO_UDP_ESP32
16#elif defined(ARDUINO_ARCH_RP2040)
17 #include <WiFi.h>
18 #define SINRICPRO_UDP_LWIP
19#endif
20
21#include <WiFiUdp.h>
22#include "SinricProQueue.h"
23#include "SinricProConfig.h"
24#include "SinricProDebug.h"
25
26#include "SinricProNamespace.h"
27namespace SINRICPRO_NAMESPACE {
28
29class UdpListener {
30 public:
31 void begin(SinricProQueue_t* receiveQueue);
32 void handle();
33 void sendMessage(String &message, const IPAddress& remoteIP, uint16_t remotePort);
34 void stop();
35
36 private:
37 WiFiUDP _udp;
38 SinricProQueue_t* receiveQueue;
39};
40
41void UdpListener::begin(SinricProQueue_t* receiveQueue) {
42 this->receiveQueue = receiveQueue;
43
44 // beginMulticast() leaves no socket listening if the IGMP join fails.
45 uint8_t started = 0;
46
47#if defined(SINRICPRO_UDP_LWIP)
48 started = _udp.beginMulticast(WiFi.localIP(), UDP_MULTICAST_IP, UDP_MULTICAST_PORT);
49
50#elif defined(SINRICPRO_UDP_ESP32)
51 started = _udp.beginMulticast(UDP_MULTICAST_IP, UDP_MULTICAST_PORT);
52#endif
53
54 if (started) {
55 DEBUG_SINRIC("[SinricPro:UDP]: listening on port %d\r\n", UDP_MULTICAST_PORT);
56 } else {
57 DEBUG_SINRIC("[SinricPro:UDP]: could not listen on port %d, local control unavailable\r\n", UDP_MULTICAST_PORT);
58 }
59}
60
61void UdpListener::handle() {
62 int len = _udp.parsePacket();
63 if (!len) return;
64
65 char* buf = (char*) malloc(len + 1);
66 if (!buf) return;
67 memset(buf, 0, len + 1);
68 _udp.read(buf, len);
69 const IPAddress peerIP = _udp.remoteIP();
70 const uint16_t peerPort = _udp.remotePort();
71 SinricProMessage* request = new SinricProMessage(IF_UDP, buf, peerIP, peerPort);
72 DEBUG_SINRIC("[SinricPro:UDP]: receiving request\r\n%s\r\n", buf);
73 free(buf);
74 receiveQueue->push(request);
75}
76
77void UdpListener::sendMessage(String &message, const IPAddress& remoteIP, uint16_t remotePort) {
78 if (!remotePort) {
79 DEBUG_SINRIC("[SinricPro:UDP]: message has no peer to answer, dropping\r\n");
80 return;
81 }
82#if defined(SINRICPRO_UDP_LWIP) || defined(SINRICPRO_UDP_ESP32)
83 // Reply on the listening socket. A separate send-only WiFiUDP does not
84 // transmit on ESP8266 lwIP -- endPacket() returns success and sends nothing.
85 const int begun = _udp.beginPacket(remoteIP, remotePort);
86 _udp.print(message);
87 const int sent = _udp.endPacket();
88
89 if (!begun || !sent) {
90 DEBUG_SINRIC("[SinricPro:UDP]: reply to %s failed (begin=%d send=%d)\r\n",
91 remoteIP.toString().c_str(), begun, sent);
92 }
93#else
94 (void)message;
95 (void)remoteIP;
96#endif
97}
98
99void UdpListener::stop() {
100 _udp.stop();
101}
102
103} // SINRICPRO_NAMESPACE