@@ -22,6 +22,78 @@ TelemetryJet::TelemetryJet(Stream *transport, unsigned long transmitRate)
22
22
dimensions = (DataPoint**) malloc (sizeof (DataPoint*) * dimensionCacheLength);
23
23
}
24
24
25
+
26
+ /*
27
+ * StuffData byte stuffs "length" bytes of data
28
+ * at the location pointed to by "ptr", writing
29
+ * the output to the location pointed to by "dst".
30
+ *
31
+ * Returns the length of the encoded data.
32
+ * From https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
33
+ */
34
+ size_t StuffData (const uint8_t *ptr, size_t length, uint8_t *dst) {
35
+ uint8_t *start = dst;
36
+ uint8_t *code_ptr = dst++;
37
+
38
+ *code_ptr = 1 ;
39
+ while (length--) {
40
+ if (*ptr) {
41
+ *dst++ = *ptr++;
42
+ *code_ptr += 1 ;
43
+ } else {
44
+ code_ptr = dst++;
45
+ *code_ptr = 1 ;
46
+ ptr++;
47
+ }
48
+
49
+ if (*code_ptr == 0xFF && length > 0 ) {
50
+ code_ptr = dst++;
51
+ *code_ptr = 1 ;
52
+ }
53
+ }
54
+ *dst++ = 0 ;
55
+
56
+ return dst - start;
57
+ }
58
+
59
+ /*
60
+ * UnStuffData decodes "length" bytes of data at
61
+ * the location pointed to by "ptr", writing the
62
+ * output to the location pointed to by "dst".
63
+ *
64
+ * Returns the length of the decoded data
65
+ * (which is guaranteed to be <= length).
66
+ * From https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
67
+ */
68
+ size_t UnStuffData (const uint8_t *ptr, size_t length, uint8_t *dst) {
69
+ const uint8_t *start = dst, *end = ptr + length;
70
+ uint8_t code = 0xFF , copy = 0 ;
71
+ bool flag = true ;
72
+
73
+ for (; ptr < end; copy--) {
74
+ if (copy != 0 ) {
75
+ flag = false ;
76
+ *dst++ = *ptr++;
77
+ } else {
78
+ if (code != 0xFF ) {
79
+ flag = true ;
80
+ *dst++ = 0 ;
81
+ }
82
+ copy = code = *ptr++;
83
+ if (code == 0 ) {
84
+ break ;
85
+ }
86
+ }
87
+ }
88
+
89
+ if (flag) {
90
+ --dst;
91
+ }
92
+
93
+ return dst - start;
94
+ }
95
+
96
+
25
97
void TelemetryJet::update () {
26
98
if (isTextMode) {
27
99
// Text mode
@@ -127,6 +199,110 @@ void TelemetryJet::update() {
127
199
while (transport->available () > 0 ) {
128
200
uint8_t inByte = transport->read ();
129
201
}
202
+ if (millis () - lastSent >= transmitRate && numDimensions > 0 ) {
203
+ mpack_writer_t writer;
204
+ size_t packetLength;
205
+ for (uint16_t i = 0 ; i < numDimensions; i++) {
206
+ if (dimensions[i]->hasValue && (dimensions[i]->hasNewValue || !isDeltaMode)) {
207
+ dimensions[i]->hasNewValue = false ;
208
+ mpack_writer_init (&writer, messagePackBuffer, 32 );
209
+
210
+ // Write key and type headers
211
+ mpack_write_u16 (&writer, (uint16_t )dimensions[i]->key );
212
+ mpack_write_u8 (&writer, (uint8_t )dimensions[i]->type );
213
+
214
+ // Write data
215
+ switch (dimensions[i]->type ) {
216
+ case DataPointType::BOOLEAN: {
217
+ mpack_write_bool (&writer, dimensions[i]->value .v_bool );
218
+ break ;
219
+ }
220
+ case DataPointType::UINT8: {
221
+ mpack_write_u8 (&writer, dimensions[i]->value .v_uint8 );
222
+ break ;
223
+ }
224
+ case DataPointType::UINT16: {
225
+ mpack_write_u16 (&writer, dimensions[i]->value .v_uint16 );
226
+ break ;
227
+ }
228
+ case DataPointType::UINT32: {
229
+ mpack_write_u32 (&writer, dimensions[i]->value .v_uint32 );
230
+ break ;
231
+ }
232
+ case DataPointType::UINT64: {
233
+ mpack_write_u64 (&writer, dimensions[i]->value .v_uint64 );
234
+ break ;
235
+ }
236
+ case DataPointType::INT8: {
237
+ mpack_write_i8 (&writer, dimensions[i]->value .v_int8 );
238
+ break ;
239
+ }
240
+ case DataPointType::INT16: {
241
+ mpack_write_i16 (&writer, dimensions[i]->value .v_int16 );
242
+ break ;
243
+ }
244
+ case DataPointType::INT32: {
245
+ mpack_write_i32 (&writer, dimensions[i]->value .v_int32 );
246
+ break ;
247
+ }
248
+ case DataPointType::INT64: {
249
+ mpack_write_i64 (&writer, dimensions[i]->value .v_int64 );
250
+ break ;
251
+ }
252
+ case DataPointType::FLOAT32: {
253
+ mpack_write_float (&writer, dimensions[i]->value .v_float32 );
254
+ break ;
255
+ }
256
+ case DataPointType::FLOAT64: {
257
+ mpack_write_double (&writer, dimensions[i]->value .v_float64 );
258
+ break ;
259
+ }
260
+ }
261
+
262
+ mpack_writer_destroy (&writer);
263
+ packetLength = mpack_writer_buffer_used (&writer);
264
+
265
+ // Use COBS (Consistent Overhead Byte Stuffing)
266
+ // https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing
267
+ // to replace all 0x0 bytes in the packet.
268
+ // This way, we can use 0x0 as a packet frame marker.
269
+ packetLength = StuffData (messagePackBuffer, packetLength, txBuffer);
270
+
271
+ // Compute checksum and add to front of the packet
272
+ // We never want the checksum to == 0,
273
+ // because that would complicate the COBS & packet frame marker logic.
274
+ // If the checksum is going to be 0, add a single bit so that it won't be.
275
+ uint8_t checksum = 0 ;
276
+ for (uint16_t bufferIdx = 0 ; bufferIdx < packetLength; bufferIdx++) {
277
+ checksum += (uint8_t )txBuffer[bufferIdx];
278
+ }
279
+ checksum = 0xFF - (checksum + 0x01 );
280
+
281
+ uint8_t checksumCorrectionByte = 0x01 ;
282
+ if (checksum == 0x0 ) {
283
+ // Increment byte in the front of the packet to correct the checksum
284
+ // If the checksum was previously 0x0 (0), it will now be 0xFF (255).
285
+ checksumCorrectionByte += 1 ;
286
+ checksum = 0xFF ;
287
+ }
288
+
289
+ // Write checksum and checksum correction byte
290
+ transport->print ((uint8_t )checksum);
291
+ transport->print (' ' );
292
+ transport->print ((uint8_t )checksumCorrectionByte);
293
+ transport->print (' ' );
294
+
295
+ // Write buffer
296
+ for (uint16_t bufferIdx = 0 ; bufferIdx < packetLength; bufferIdx++) {
297
+ transport->print ((uint8_t )txBuffer[bufferIdx]);
298
+ transport->print (' ' );
299
+ }
300
+ transport->print ((uint8_t )0x0 );
301
+ transport->println ();
302
+ }
303
+ }
304
+ lastSent = millis ();
305
+ }
130
306
}
131
307
}
132
308
0 commit comments