MySensors Library & Examples  2.3.2-62-ge298769
ThroughLora.h
1 
2 /* ThroughLora data link
3  Proposed and developed by Matheus Eduardo Garbelini 2017-2018
4  ____________________________________________________________________________
5 
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 
18  To use this strategy, please download the LoRa third party Library from
19  https://github.com/sandeepmistry/arduino-LoRa/ */
20 
21 #pragma once
22 
23 #include <LoRa.h>
24 #include "Timing.h"
25 
26 // Recommended receive time for this strategy, in microseconds
27 #ifndef TL_RECEIVE_TIME
28 #define TL_RECEIVE_TIME 0
29 #endif
30 
32 {
33 public:
34  /* Returns the suggested delay related to the attempts
35  passed as parameter: */
36 
37  uint32_t back_off(uint8_t attempts)
38  {
39  uint32_t result = attempts;
40  for(uint8_t d = 0; d < TL_BACK_OFF_DEGREE; d++) {
41  result *= (uint32_t)(attempts);
42  }
43  return result;
44  };
45 
46  int packetRssi()
47  {
48  return LoRa.packetRssi();
49  };
50 
51  float packetSnr()
52  {
53  return LoRa.packetSnr();
54  };
55 
56  bool setFrequency(uint32_t frequency)
57  {
58  return LoRa.begin(frequency);
59  };
60 
61  void setSignalBandwidth(uint32_t bandwidth)
62  {
63  LoRa.setSignalBandwidth(bandwidth);
64  };
65 
66  void setPins(uint8_t cs_pin, uint8_t reset_pin, uint8_t dio0_pin)
67  {
68  LoRa.setPins(cs_pin, reset_pin, dio0_pin);
69  };
70 
71  void setSpreadingFactor(uint8_t spreadingFactor)
72  {
73  LoRa.setSpreadingFactor(spreadingFactor);
74  };
75 
76  void setCodingRate4(uint8_t codingRate)
77  {
78  LoRa.setCodingRate4(codingRate);
79  };
80 
81  void setPreambleLength(uint16_t preambleLength)
82  {
83  LoRa.setPreambleLength(preambleLength);
84  };
85 
86  void setSyncWord(uint8_t syncWord)
87  {
88  LoRa.setSyncWord(syncWord);
89  };
90 
91  void setCRC(bool enableCRC)
92  {
93  if (enableCRC) {
94  LoRa.enableCrc();
95  } else {
96  LoRa.disableCrc();
97  }
98  };
99 
100  void setTxPower(uint8_t txPower)
101  {
102  LoRa.setTxPower(txPower);
103  };
104 
105  void setTxPower(uint8_t txPower, uint8_t boostPin)
106  {
107  LoRa.setTxPower(txPower, boostPin);
108  };
109 
110  void idle()
111  {
112  LoRa.idle();
113  };
114 
115  void sleep()
116  {
117  LoRa.sleep();
118  };
119 
120  uint8_t getRandom()
121  {
122  return LoRa.random();
123  };
124 
125  /* Begin method, to be called on initialization:
126  (returns always true) */
127 
128  bool begin(uint8_t did = 0)
129  {
130  PJON_DELAY_MICROSECONDS(PJON_RANDOM(TL_INITIAL_DELAY) + did);
131  return true;
132  };
133 
134  /* Check if the channel is free for transmission: */
135 
136  bool can_start()
137  {
138  if(LoRa.parsePacket() > 0) {
139  return false;
140  }
141  return true;
142  };
143 
144  /* Returns the maximum number of attempts for each transmission: */
145 
146  static uint8_t get_max_attempts()
147  {
148  return TL_MAX_ATTEMPTS;
149  };
150 
151  /* Returns the recommended receive time for this strategy: */
152 
153  static uint16_t get_receive_time()
154  {
155  return TL_RECEIVE_TIME;
156  };
157 
158  /* Handle a collision: */
159 
160  void handle_collision()
161  {
162  PJON_DELAY_MICROSECONDS(PJON_RANDOM(TL_COLLISION_DELAY));
163  };
164 
165  /* The last 5 bytes of the frame are used as a unique identifier within
166  the response. PJON has CRC8 or CRC32 at the end of the packet, encoding
167  a CRC (that is a good hashing algorithm) and using 40 bits looks enough
168  to provide a relatively safe response that should be nearly flawless
169  (yield few false positives per millennia). */
170 
171  void prepare_response(const uint8_t *buffer, uint16_t position)
172  {
173  for(int8_t i = 0; i < TL_RESPONSE_LENGTH; i++)
174  _response[i] =
175  buffer[(position - ((TL_RESPONSE_LENGTH - 1) - i)) - 1];
176  };
177 
178  /* Receive byte response (not supported) */
179 
180  uint16_t receive_response()
181  {
182  uint32_t time = PJON_MICROS();
183  while((uint32_t)(PJON_MICROS() - time) < TL_RESPONSE_TIME_OUT) {
184  uint8_t frame_size = LoRa.parsePacket();
185  if(frame_size == TL_RESPONSE_LENGTH) {
186  for(uint8_t i = 0; i < TL_RESPONSE_LENGTH; i++)
187  if(LoRa.read() != _response[i]) {
188  return PJON_FAIL;
189  }
190  return PJON_ACK;
191  }
192  }
193  return PJON_FAIL;
194  };
195 
196  /* Receive a frame: */
197 
198  uint16_t receive_frame(uint8_t *data, uint16_t max_length)
199  {
200  uint8_t frameSize = LoRa.parsePacket();
201  /* Filter frames if too short to contain a PJON packet
202  or if too long to be received */
203  if((frameSize > 5) && (frameSize <= max_length)) {
204  while(LoRa.available()) {
205  *data = LoRa.read();
206  data++;
207  }
208  prepare_response(data, frameSize);
209  return frameSize;
210  } else {
211  return PJON_FAIL;
212  }
213  };
214 
215  /* Send a byte and wait for its transmission end */
216 
217  void send_byte(uint8_t b)
218  {
219  LoRa.write(b);
220  };
221 
222  /* Send byte response to the packet's transmitter (not supported) */
223 
224  void send_response(uint8_t response)
225  {
226  if(response == PJON_ACK) {
227  start_tx();
228  for(uint8_t i = 0; i < TL_RESPONSE_LENGTH; i++) {
229  send_byte(_response[i]);
230  }
231  end_tx();
232  }
233  };
234 
235  /* Send a frame: */
236 
237  void send_frame(uint8_t *data, uint8_t length)
238  {
239  start_tx();
240  for(uint8_t b = 0; b < length; b++) {
241  send_byte(data[b]);
242  }
243  prepare_response(data, length);
244  end_tx();
245  };
246 
247  void start_tx()
248  {
249  LoRa.beginPacket();
250  };
251 
252  void end_tx()
253  {
254  LoRa.endPacket();
255  };
256 
257 private:
258  uint32_t _last_reception_time;
259  uint8_t _response[TL_RESPONSE_LENGTH];
260 };
data
char data[MAX_PAYLOAD_SIZE+1]
Buffer for raw payload data.
Definition: MyMessage.h:654
ThroughLora
Definition: ThroughLora.h:31