MySensors Library & Examples  2.3.2-62-ge298769
LocalUDP.h
1 
2 /* LocalUDP is a Strategy for the PJON framework (included in version v5.2)
3  It supports delivering PJON packets over Ethernet UDP on local network (LAN).
4  Compliant with the PJON protocol layer specification v0.3
5  _____________________________________________________________________________
6 
7  LocalUDP strategy proposed and developed by Fred Larsen 02/10/2016
8 
9  Licensed under the Apache License, Version 2.0 (the "License");
10  you may not use this file except in compliance with the License.
11  You may obtain a copy of the License at
12 
13  http://www.apache.org/licenses/LICENSE-2.0
14 
15  Unless required by applicable law or agreed to in writing, software
16  distributed under the License is distributed on an "AS IS" BASIS,
17  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  See the License for the specific language governing permissions and
19  limitations under the License. */
20 
21 #pragma once
22 
23 #ifdef HAS_ETHERNETUDP
24 #include "../../interfaces/ARDUINO/UDPHelper_ARDUINO.h"
25 #else
26 #include "../../interfaces/LINUX/UDPHelper_POSIX.h"
27 #endif
28 
29 #include <PJONDefines.h>
30 
31 #define LUDP_DEFAULT_PORT 7100
32 #ifndef LUDP_RESPONSE_TIMEOUT
33 #define LUDP_RESPONSE_TIMEOUT (uint32_t) 100000
34 #endif
35 #define LUDP_MAGIC_HEADER (uint32_t) 0x0DFAC3D0
36 
37 // Recommended receive time for this strategy, in microseconds
38 #ifndef LUDP_RECEIVE_TIME
39 #define LUDP_RECEIVE_TIME 0
40 #endif
41 
42 class LocalUDP
43 {
44  bool _udp_initialized = false;
45  uint16_t _port = LUDP_DEFAULT_PORT;
46  UDPHelper udp;
47 
48  bool check_udp()
49  {
50  if(!_udp_initialized) {
51  udp.set_magic_header(htonl(LUDP_MAGIC_HEADER));
52  if (udp.begin(_port)) {
53  _udp_initialized = true;
54  }
55  }
56  return _udp_initialized;
57  };
58 
59 public:
60  /* Returns the suggested delay related to the attempts passed as parameter: */
61 
62  uint32_t back_off(uint8_t attempts)
63  {
64 #ifdef PJON_ESP
65  return 10000ul * attempts + PJON_RANDOM(10000);
66 #elif _WIN32
67  return 1000ul * attempts + PJON_RANDOM(1000);
68 #else
69  (void)attempts; // Avoid "unused parameter" warning
70  return 1;
71 #endif
72  };
73 
74 
75  /* Begin method, to be called on initialization:
76  (returns always true) */
77 
78  bool begin(uint8_t /*did*/ = 0)
79  {
80  return check_udp();
81  };
82 
83 
84  /* Check if the channel is free for transmission */
85 
86  bool can_start()
87  {
88  return check_udp();
89  };
90 
91 
92  /* Returns the maximum number of attempts for each transmission: */
93 
94  static uint8_t get_max_attempts()
95  {
96  return 10;
97  };
98 
99 
100  /* Returns the recommended receive time for this strategy: */
101 
102  static uint16_t get_receive_time()
103  {
104  return LUDP_RECEIVE_TIME;
105  };
106 
107 
108  /* Handle a collision (empty because handled on Ethernet level): */
109 
110  void handle_collision() { };
111 
112 
113  /* Receive a frame: */
114 
115  uint16_t receive_frame(uint8_t *data, uint16_t max_length)
116  {
117  return udp.receive_frame(data, max_length);
118  }
119 
120 
121  /* Receive byte response */
122 
123  uint16_t receive_response()
124  {
125  /* TODO: Improve robustness by ignoring packets not from the previous
126  receiver (Perhaps not that important as long as ACK/NAK responses are
127  directed, not broadcast) */
128  uint32_t start = PJON_MICROS();
129  uint8_t result[6];
130  uint16_t reply_length = 0;
131  do {
132  reply_length = receive_frame(result, sizeof result);
133  // We expect 1, if packet is larger it is not our ACK.
134  // When an ACK is received we know it is for us because an ACK
135  // will never be broadcast but directed.
136  if(reply_length == 1)
137  if(result[0] == PJON_ACK) {
138  return result[0];
139  }
140  } while ((uint32_t)(PJON_MICROS() - start) < LUDP_RESPONSE_TIMEOUT);
141  return PJON_FAIL;
142  };
143 
144 
145  /* Send byte response to package transmitter.
146  We have the IP so we can skip broadcasting and reply directly. */
147 
148  void send_response(uint8_t response) // Empty, PJON_ACK is always sent
149  {
150  udp.send_response(response);
151  };
152 
153 
154  /* Send a frame: */
155 
156  void send_frame(uint8_t *data, uint16_t length)
157  {
158  udp.send_frame(data, length);
159  };
160 
161 
162  /* Set the UDP port: */
163 
164  void set_port(uint16_t port = LUDP_DEFAULT_PORT)
165  {
166  _port = port;
167  };
168 };
data
char data[MAX_PAYLOAD_SIZE+1]
Buffer for raw payload data.
Definition: MyMessage.h:654
UDPHelper
Definition: UDPHelper_ARDUINO.h:21
LocalUDP
Definition: LocalUDP.h:42