AllWize Library
AllWize.cpp
1 /*
2 
3 AllWize Library
4 
5 Copyright (C) 2018 by AllWize <github@allwize.io>
6 
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16 
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 #include "AllWize.h"
23 #include <assert.h>
24 
25 // -----------------------------------------------------------------------------
26 // Init
27 // -----------------------------------------------------------------------------
28 
34 AllWize::AllWize(HardwareSerial * serial, uint8_t reset_gpio) : _stream(serial), _hw_serial(serial), _reset_gpio(reset_gpio) {
35  _init();
36 }
37 
43 #if not defined(ARDUINO_ARCH_SAMD) && not defined(ARDUINO_ARCH_ESP32)
44 AllWize::AllWize(SoftwareSerial * serial, uint8_t reset_gpio) : _stream(serial), _sw_serial(serial), _reset_gpio(reset_gpio) {
45  _init();
46 }
47 #endif
48 
55 AllWize::AllWize(uint8_t rx, uint8_t tx, uint8_t reset_gpio) : _rx(rx), _tx(tx), _reset_gpio(reset_gpio) {
56  #if defined(ARDUINO_ARCH_SAMD)
57  // Software serial not implemented for SAMD
58  assert(false);
59  #elif defined(ARDUINO_ARCH_ESP32)
60  _stream = _hw_serial = new HardwareSerial(HARDWARE_SERIAL_PORT);
61  #else
62  _stream = _sw_serial = new SoftwareSerial(_rx, _tx);
63  #endif
64  _init();
65 }
66 
67 void AllWize::_init() {
68  if (GPIO_NONE != _reset_gpio) {
69  pinMode(_reset_gpio, OUTPUT);
70  digitalWrite(_reset_gpio, HIGH);
71  }
72  randomSeed(analogRead(0));
73  _access_number = random(0,256);
74 }
75 
80  reset();
81  delay(200);
82  _append_rssi = _getMemory(MEM_RSSI_MODE) == 0x01;
83  _mbus_mode = _getMemory(MEM_MBUS_MODE);
84  _data_interface = _getMemory(MEM_DATA_INTERFACE);
85 }
86 
91 
92  if (_hw_serial) {
93 
94  _hw_serial->end();
95  #if defined(ARDUINO_ARCH_ESP32)
96  if ((_rx != -1) && (_tx != -1)) {
97  pinMode(_rx, FUNCTION_4);
98  pinMode(_tx, FUNCTION_4);
99  _hw_serial->begin(MODEM_BAUDRATE, SERIAL_8N1, _rx, _tx);
100  } else {
101  _hw_serial->begin(MODEM_BAUDRATE);
102  }
103  #else
104  _hw_serial->begin(MODEM_BAUDRATE);
105  #endif
106 
107  } else {
108 
109  #if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_SAMD)
110  // It should never hit this block
111  assert(false);
112  #else
113  _sw_serial->end();
114  _sw_serial->begin(MODEM_BAUDRATE);
115  #endif
116 
117  }
118 
119  _flush();
120 
121 }
122 
128  if (GPIO_NONE == _reset_gpio) {
129  _reset_serial();
130  delay(100);
131  _setMemory(MEM_CONFIG_INTERFACE, 1);
132  if (_setConfig(true)) {
133  _send('@');
134  _send('R');
135  _send('R');
136  _flush();
137  delay(100);
138  _config = false;
139  _reset_serial();
140  return true;
141  }
142  } else {
143  digitalWrite(_reset_gpio, LOW);
144  delay(1);
145  digitalWrite(_reset_gpio, HIGH);
146  delay(100);
147  _config = false;
148  _reset_serial();
149  return true;
150  }
151  return false;
152 }
153 
159  _reset_serial();
160  delay(100);
161  _setMemory(MEM_CONFIG_INTERFACE, 1);
162  if (_setConfig(true)) {
163  _send('@');
164  _send('R');
165  _send('C');
166  _flush();
167  delay(100);
168  _config = false;
169  _reset_serial();
170  return true;
171  }
172  return false;
173 }
174 
179  setMode(DEFAULT_MBUS_MODE, true);
180  setNetworkRole(NETWORK_ROLE_MASTER);
181  setInstallMode(INSTALL_MODE_HOST);
182  setSleepMode(SLEEP_MODE_DISABLE);
183  setPower(POWER_20dBm);
184  setDataRate(DATARATE_2400bps);
185  setDataInterface(DATA_INTERFACE_START_STOP);
186  setAppendRSSI(true);
187 }
188 
193  setMode(DEFAULT_MBUS_MODE, true);
194  setNetworkRole(NETWORK_ROLE_SLAVE);
195  setPower(POWER_20dBm);
196  setDataRate(DATARATE_2400bps);
197 }
198 
203  setMode(DEFAULT_MBUS_MODE, true);
204  setNetworkRole(NETWORK_ROLE_REPEATER);
205 }
206 
211  if (!_setConfig(true)) return;
212  _send(CMD_SLEEP);
213 }
214 
219  _send(CMD_AWAKE);
220  ready();
221 }
222 
227  bool response = _setConfig(true);
228  if (response) _setConfig(false);
229  return response;
230 }
231 
235 bool AllWize::waitForReady(uint32_t timeout) {
236  uint32_t start = millis();
237  while (millis() - start < timeout) {
238  if (ready()) return true;
239  delay(100);
240  }
241  return false;
242 }
243 
248 void AllWize::dump(Stream & debug) {
249 
250  _setConfig(true);
251  _send(CMD_TEST_MODE_0);
252 
253  char buffer[256];
254  if (256 == _readBytes(buffer, 256)) {
255 
256  char ch[10];
257  char ascii[17] = {0};
258  ascii[16] = 0;
259 
260  debug.println();
261  debug.print(" ");
262  for (uint16_t address = 0; address <= 0x0F; address++) {
263  snprintf(ch, sizeof(ch), "%02X ", address);
264  debug.print(ch);
265  }
266  debug.println();
267  debug.print("------------------------------------------------------");
268 
269  for (uint16_t address = 0; address <= 255; address++) {
270  if ((address % 16) == 0) {
271  if (address > 0) debug.print(ascii);
272  snprintf(ch, sizeof(ch), "\n0x%02X: ", address);
273  debug.print(ch);
274  }
275  if (31 < buffer[address] && buffer[address] < 127) {
276  ascii[address % 16] = (char) buffer[address];
277  } else {
278  ascii[address % 16] = ' ';
279  }
280  snprintf(ch, sizeof(ch), "%02X ", (uint8_t) buffer[address]);
281  debug.print(ch);
282  }
283 
284  debug.println();
285  debug.println();
286 
287  } else {
288  debug.println("Error doing memory dump...");
289  }
290 
291  _setConfig(false);
292 
293 }
294 
301 bool AllWize::send(uint8_t * buffer, uint8_t len) {
302 
303  if (_config) return false;
304  if (0 == len) return (1 == _send(0xFE));
305 
306  // length
307  if (1 != _send(len+1)) return false;
308 
309  // CI
310  if (1 != _send(_ci)) return false;
311 
312  // payload
313  if (len != _send(buffer, len)) return false;
314 
315  _access_number++;
316  return true;
317 
318 }
319 
325 bool AllWize::send(const char * buffer) {
326  return send((uint8_t *) buffer, strlen(buffer));
327 }
328 
335 
336  bool response = false;
337 
338  if (!_config) {
339 
340  static uint32_t when = millis();
341 
342  while (_stream->available() && _pointer < RX_BUFFER_SIZE) {
343  uint8_t ch = _stream->read();
344  _buffer[_pointer++] = ch;
345  when = millis();
346  #if defined(ARDUINO_ARCH_ESP8266)
347  yield();
348  #endif
349  }
350 
351  // Check if message finished and decode it
352  if ((_pointer > 0) && (millis() - when > 100)) {
353  response = _decode();
354  _pointer = 0;
355  }
356 
357  }
358 
359  return response;
360 
361 }
362 
368  return _message;
369 }
370 
371 // -----------------------------------------------------------------------------
372 // Configuration
373 // -----------------------------------------------------------------------------
374 
380  _ci = ci;
381 }
382 
388  return _ci;
389 }
390 
396 void AllWize::setChannel(uint8_t channel, bool persist) {
397  if (persist) {
398  _setMemory(MEM_CHANNEL, channel);
399  }
400  _sendCommand(CMD_CHANNEL, channel);
401 }
402 
408  return _getMemory(MEM_CHANNEL);
409 }
410 
416 void AllWize::setPower(uint8_t power, bool persist) {
417  if (0 < power && power < 6) {
418  if (persist) {
419  _setMemory(MEM_RF_POWER, power);
420  }
421  _sendCommand(CMD_RF_POWER, power);
422  }
423 }
424 
429 uint8_t AllWize::getPower() {
430  return _getMemory(MEM_RF_POWER);
431 }
432 
437 void AllWize::setDataRate(uint8_t dr) {
438  if (0 < dr && dr < 6 && dr != 3) {
439  _setMemory(MEM_DATA_RATE, dr);
440  }
441 }
442 
448  return _getMemory(MEM_DATA_RATE);
449 }
450 
456 void AllWize::setMode(uint8_t mode, bool persist) {
457  if (persist) {
458  _setMemory(MEM_MBUS_MODE, mode);
459  }
460  _sendCommand(CMD_MBUS_MODE, mode);
461  _mbus_mode = mode;
462 }
463 
468 uint8_t AllWize::getMode() {
469  return _mbus_mode;
470 }
471 
476 void AllWize::setSleepMode(uint8_t mode) {
477  _setMemory(MEM_SLEEP_MODE, mode);
478 }
479 
485  return _getMemory(MEM_SLEEP_MODE);
486 }
487 
492 void AllWize::setAppendRSSI(bool value) {
493  if (value == 1) {
494  _setMemory(MEM_RSSI_MODE, 1);
495  } else {
496  _setMemory(MEM_RSSI_MODE, 0);
497  }
498  _append_rssi = value;
499 }
500 
506  return _append_rssi;
507 }
508 
513 void AllWize::setPreamble(uint8_t preamble) {
514  if (PREAMBLE_FORMAT_A == preamble || PREAMBLE_FORMAT_B == preamble) {
515  _setMemory(MEM_PREAMBLE_LENGTH, preamble);
516  }
517 }
518 
524  return _getMemory(MEM_PREAMBLE_LENGTH);
525 }
526 
531 void AllWize::setTimeout(uint8_t timeout) {
532  _setMemory(MEM_TIMEOUT, timeout);
533 }
534 
540  return _getMemory(MEM_TIMEOUT);
541 }
542 
547 void AllWize::setNetworkRole(uint8_t role) {
548  _setMemory(MEM_NETWORK_ROLE, role);
549 }
550 
556  return _getMemory(MEM_NETWORK_ROLE);
557 }
558 
563 void AllWize::setLEDControl(uint8_t value) {
564  _setMemory(MEM_LED_CONTROL, value);
565 }
566 
572  return _getMemory(MEM_LED_CONTROL);
573 }
574 
579 void AllWize::setDataInterface(uint8_t value) {
580  if (value <= 0x0C) {
581  _setMemory(MEM_DATA_INTERFACE, value);
582  _data_interface = value;
583  }
584 }
585 
591  return _data_interface;
592 }
593 
599 void AllWize::setControlField(uint8_t value, bool persist) {
600  if (persist) {
601  _setMemory(MEM_CONTROL_FIELD, value);
602  }
603  _sendCommand(CMD_CONTROL_FIELD, value);
604 }
605 
611  return _getMemory(MEM_CONTROL_FIELD);
612 }
613 
619 void AllWize::setInstallMode(uint8_t mode, bool persist) {
620  if (mode <= 2) {
621  if (persist) {
622  _setMemory(MEM_INSTALL_MODE, mode);
623  }
624  _sendCommand(CMD_INSTALL_MODE, mode);
625  }
626 }
627 
633  return _getMemory(MEM_INSTALL_MODE);
634 }
635 
640 void AllWize::setEncryptFlag(uint8_t flag) {
641  if (0 == flag || 1 == flag || 3 == flag) {
642  _encrypt = (flag & 0x01) == 0x01;
643  _setMemory(MEM_ENCRYPT_FLAG, flag);
644  }
645 }
646 
652  return _getMemory(MEM_ENCRYPT_FLAG);
653 }
654 
659 void AllWize::setDecryptFlag(uint8_t flag) {
660  _setMemory(MEM_DECRYPT_FLAG, flag);
661 }
662 
668  return _getMemory(MEM_DECRYPT_FLAG);
669 }
670 
676 void AllWize::setKey(uint8_t reg, const uint8_t * key) {
677  if (0 < reg && reg < 65) {
678  uint8_t data[17];
679  data[0] = reg;
680  memcpy(&data[1], key, 16);
681  _sendCommand(CMD_KEY_REGISTER, data, 17);
682  }
683 }
684 
689 void AllWize::setDefaultKey(const uint8_t * key) {
690  _setMemory(MEM_DEFAULT_KEY, (uint8_t *) key, 16);
691 }
692 
697 void AllWize::getDefaultKey(uint8_t * key) {
698  _getMemory(MEM_DEFAULT_KEY, key, 16);
699 }
700 
701 // -----------------------------------------------------------------------------
702 
708 /*
709 float AllWize::getRSSI() {
710  uint8_t response = _sendCommand(CMD_RSSI);
711  if (response > 0) return -0.5 * _buffer[0];
712  return 0;
713 }
714 */
715 
721  uint8_t response = _sendCommand(CMD_TEMPERATURE);
722  uint8_t ret_val = 0;
723 
724  if (response > 0) {
725  ret_val = _buffer[0] - 128;
726  } else {
727  ret_val = 0;
728  }
729 
730  return ret_val;
731 }
732 
738  uint8_t response = _sendCommand(CMD_VOLTAGE);
739  uint16_t ret_val;
740  if (response > 0) {
741  ret_val = 30 * _buffer[0];
742  } else {
743  ret_val = 0;
744  }
745 
746  return ret_val;
747 }
748 
753 String AllWize::getMID() {
754  return _getMemoryAsHexString(MEM_MANUFACTURER_ID, 2);
755 }
756 
761 bool AllWize::setMID(uint16_t mid) {
762  uint8_t buffer[2];
763  buffer[0] = (mid >> 8) & 0xFF;
764  buffer[1] = (mid >> 0) & 0xFF;
765  return _setMemory(MEM_MANUFACTURER_ID, buffer, 2);
766 }
767 
772 String AllWize::getUID() {
773  return _getMemoryAsHexString(MEM_UNIQUE_ID, 4);
774 }
775 
780 bool AllWize::setUID(uint32_t uid) {
781  uint8_t buffer[4];
782  buffer[0] = (uid >> 24) & 0xFF;
783  buffer[1] = (uid >> 16) & 0xFF;
784  buffer[2] = (uid >> 8) & 0xFF;
785  buffer[3] = (uid >> 0) & 0xFF;
786  return _setMemory(MEM_UNIQUE_ID, buffer, 4);
787 }
788 
794  return _getMemory(MEM_VERSION);
795 }
796 
802  return _getMemory(MEM_DEVICE);
803 }
804 
810  _readModel();
811  return _model;
812 }
813 
819  _readModel();
820  return _hw;
821 }
822 
828  _readModel();
829  return _fw;
830 }
831 
837  return _getMemoryAsHexString(MEM_SERIAL_NUMBER_NEW, 8);
838 }
839 
840 // -----------------------------------------------------------------------------
841 // Protected
842 // -----------------------------------------------------------------------------
843 
850 bool AllWize::_setConfig(bool value) {
851  if (value != _config) {
852  _flush();
853  if (value) {
854  if (_sendAndReceive(CMD_ENTER_CONFIG) == 0) {
855  _config = true;
856  delay(2);
857  }
858  } else {
859  _send(CMD_EXIT_CONFIG);
860  _config = false;
861  delay(10);
862  }
863  }
864  return _config;
865 }
866 
874 int8_t AllWize::_sendCommand(uint8_t command, uint8_t * data, uint8_t len) {
875  int8_t response = -1;
876  if (!_setConfig(true)) return response;
877  if (_sendAndReceive(command) != -1) {
878  response = _sendAndReceive(data, len);
879  }
880  _setConfig(false);
881  return response;
882 }
883 
891 int8_t AllWize::_sendCommand(uint8_t command, uint8_t data) {
892  int8_t response = -1;
893  if (!_setConfig(true)) return response;
894  if (_sendAndReceive(command) != -1) {
895  response = _sendAndReceive(data);
896  }
897  _setConfig(false);
898  return response;
899 }
900 
907 int8_t AllWize::_sendCommand(uint8_t command) {
908  int8_t response = -1;
909  if (!_setConfig(true)) return response;
910  response = _sendAndReceive(command);
911  _setConfig(false);
912  return response;
913 }
914 
923 bool AllWize::_setMemory(uint8_t address, uint8_t * data, uint8_t len) {
924  uint8_t buffer[len*2+1];
925  for (uint8_t i=0; i<len; i++) {
926  buffer[i*2] = address + i;
927  buffer[i*2+1] = data[i];
928  }
929  buffer[len*2] = CMD_EXIT_MEMORY;
930  return (_sendCommand(CMD_WRITE_MEMORY, buffer, len*2+1) != -1);
931 }
932 
940 bool AllWize::_setMemory(uint8_t address, uint8_t value) {
941  uint8_t buffer[3] = {address, value, (uint8_t) CMD_EXIT_MEMORY};
942  return (_sendCommand(CMD_WRITE_MEMORY, buffer, 3) != -1);
943 }
944 
953 uint8_t AllWize::_getMemory(uint8_t address, uint8_t * buffer, uint8_t len) {
954  uint8_t count = 0;
955  if (_setConfig(true)) {
956  for (uint8_t i=0; i<len; i++) {
957  if (_sendAndReceive(CMD_READ_MEMORY) == -1) break;
958  if (_sendAndReceive(address + i) != 1) break;
959  count++;
960  buffer[i] = _buffer[0];
961  }
962  _setConfig(false);
963  }
964  return count;
965 }
966 
973 uint8_t AllWize::_getMemory(uint8_t address) {
974  uint8_t response = _sendCommand(CMD_READ_MEMORY, address);
975  if (response > 0) return _buffer[0];
976  return 0;
977 }
978 
986 String AllWize::_getMemoryAsHexString(uint8_t address, uint8_t len) {
987  uint8_t bin[len];
988  char hex[2*len+1];
989  hex[0] = 0;
990  if (len == _getMemory(address, bin, len)) {
991  _bin2hex(bin, hex, len);
992  }
993  return String(hex);
994 }
995 
1003 String AllWize::_getMemoryAsString(uint8_t address, uint8_t len) {
1004  uint8_t bin[len];
1005  char hex[len+1];
1006  hex[0] = 0;
1007  if (len == _getMemory(address, bin, len)) {
1008  memcpy(hex, bin, len);
1009  hex[len-1] = 0;
1010  }
1011  return String(hex);
1012 }
1013 
1018 
1019  if (_model.length() > 0) return;
1020  String line = _getMemoryAsString(MEM_PART_NUMBER_NEW, 32);
1021  if (line.indexOf("RC") != 0) String line = _getMemoryAsString(MEM_PART_NUMBER_OLD, 32);
1022 
1023  if (line.indexOf("RC") != 0) {
1024  _model = String("Unknown");
1025 
1026  } else {
1027 
1028  uint8_t start = 0;
1029  uint8_t end = line.indexOf(",", start);
1030  _model = line.substring(start, end);
1031 
1032  start = end + 1;
1033  end = line.indexOf(",", start);
1034  _hw = line.substring(start, end);
1035 
1036  start = end + 1;
1037  end = line.indexOf(",", start);
1038  _fw = line.substring(start, end);
1039  _fw.trim();
1040 
1041  }
1042 
1043 }
1044 
1072 
1073  #if defined(ALLWIZE_DEBUG_PORT)
1074  {
1075  char ch[4];
1076  ALLWIZE_DEBUG_PRINT("recv:");
1077  for (uint8_t i = 0; i < _pointer; i++) {
1078  snprintf(ch, sizeof(ch), " %02X", _buffer[i]);
1079  ALLWIZE_DEBUG_PRINT(ch);
1080  }
1081  ALLWIZE_DEBUG_PRINTLN();
1082  }
1083  #endif
1084 
1085  // Local copy of the buffer
1086  uint8_t _local[RX_BUFFER_SIZE];
1087  memcpy(_local, _buffer, RX_BUFFER_SIZE);
1088 
1089  // Get current values
1090  uint8_t mbus_mode = getMode();
1091  uint8_t data_interface = getDataInterface();
1092  bool has_start = (data_interface & 0x04) == 0x04;
1093  bool has_header = (mbus_mode != MBUS_MODE_OSP) & ((data_interface & 0x01) == 0x00);
1094  bool has_rssi = getAppendRSSI();
1095  bool has_crc = (data_interface & 0x08) == 0x08;
1096  uint8_t bytes_not_in_len = has_start ? 3 : 1;
1097  uint8_t bytes_not_in_app = (has_header ? 9 : 0) + 1 + (has_rssi ? 1 : 0) + (has_crc ? 2 : 0);
1098 
1099  // This variable will contain the pointer to the current reading position
1100  uint8_t in = 0;
1101 
1102  // Start byte
1103  if (has_start) {
1104  if (START_BYTE != _local[in]) return false;
1105  in += 1;
1106  };
1107 
1108  // Get and check buffer length
1109  uint8_t len = _local[in];
1110  if (_pointer != len + bytes_not_in_len) return false;
1111  in += 1;
1112 
1113  if (has_header) {
1114 
1115  // C-field
1116  _message.c = _local[in];
1117  in += 1;
1118 
1119  // Manufacturer
1120  unsigned int man = (_local[in+1] << 8) + _local[in];
1121  _message.man[0] = ((man >> 10) & 0x001F) + 64;
1122  _message.man[1] = ((man >> 5) & 0x001F) + 64;
1123  _message.man[2] = ((man >> 0) & 0x001F) + 64;
1124  _message.man[3] = 0;
1125  in += 2;
1126 
1127  // Address
1128  _message.address[0] = _local[in + 3];
1129  _message.address[1] = _local[in + 2];
1130  _message.address[2] = _local[in + 1];
1131  _message.address[3] = _local[in + 0];
1132 
1133  // Type
1134  _message.type = _local[in + 5];
1135 
1136  // Version
1137  _message.version = _local[in + 4];
1138 
1139  in += 6;
1140 
1141  } else {
1142  _message.c = 0xFF;
1143  _message.type = 0;
1144  _message.version = 0;
1145  _message.man[0] = 0;
1146  memset(_message.address, 0, 6);
1147  }
1148 
1149  // Control information
1150  _message.ci = _buffer[in];
1151  in += 1;
1152 
1153  // Application data
1154  _message.len = len - bytes_not_in_app;
1155  memcpy(_message.data, &_local[in], _message.len);
1156  _message.data[_message.len] = 0;
1157  in += _message.len;
1158 
1159  // RSSI
1160  if (has_rssi) {
1161  _message.rssi = _local[in];
1162  in += 1;
1163  } else {
1164  _message.rssi = 0xFF;
1165  }
1166 
1167  // CRC
1168  if (has_crc) {
1169  in += 2;
1170  }
1171 
1172  // Stop byte
1173  if (has_start) {
1174  if (STOP_BYTE != _local[in]) return false;
1175  }
1176 
1177  return true;
1178 
1179 }
1180 
1181 // -----------------------------------------------------------------------------
1182 
1188  _stream->flush();
1189 }
1190 
1197 uint8_t AllWize::_send(uint8_t ch) {
1198  #if defined(ALLWIZE_DEBUG_PORT)
1199  {
1200  char buffer[5];
1201  snprintf(buffer, sizeof(buffer), "w %02X", ch);
1202  ALLWIZE_DEBUG_PRINTLN(buffer);
1203  }
1204  #endif
1205  return _stream->write(ch);
1206 }
1207 
1215 uint8_t AllWize::_send(uint8_t * buffer, uint8_t len) {
1216  uint8_t n = 0;
1217  for (uint8_t i=0; i<len; i++) {
1218  if (_send(buffer[i])) n++;
1219  }
1220  return n;
1221 }
1222 
1229  return _readBytesUntil(END_OF_RESPONSE, (char*) _buffer, RX_BUFFER_SIZE);
1230 }
1231 
1239 int8_t AllWize::_sendAndReceive(uint8_t * buffer, uint8_t len) {
1240  if (_send(buffer, len) != len) return -1;
1241  return _receive();
1242 }
1243 
1250 int8_t AllWize::_sendAndReceive(uint8_t ch) {
1251  if (_send(ch) != 1) return -1;
1252  return _receive();
1253 }
1254 
1255 // -----------------------------------------------------------------------------
1256 // Utils
1257 // -----------------------------------------------------------------------------
1258 
1265  uint32_t _start = millis();
1266  while (millis() - _start < _timeout) {
1267  int ch = _stream->read();
1268  if (ch >= 0) return ch;
1269  #if defined(ARDUINO_ARCH_ESP8266)
1270  yield();
1271  #endif
1272  };
1273  return -1;
1274 }
1275 
1283 int AllWize::_readBytes(char * buffer, uint16_t len) {
1284  if (len < 1) return 0;
1285  uint16_t index = 0;
1286  while (index < len) {
1287  int ch = _timedRead();
1288  if (ch < 0) break;
1289 
1290  #if defined(ALLWIZE_DEBUG_PORT)
1291  {
1292  char buffer[5];
1293  snprintf(buffer, sizeof(buffer), "r %02X", ch);
1294  ALLWIZE_DEBUG_PRINTLN(buffer);
1295  }
1296  #endif
1297 
1298  *buffer++ = (char) ch;
1299  index++;
1300  }
1301  return index;
1302 }
1303 
1312 int AllWize::_readBytesUntil(char terminator, char * buffer, uint16_t len) {
1313  if (len < 1) return 0;
1314  uint16_t index = 0;
1315  while (index < len) {
1316 
1317  int ch = _timedRead();
1318  if (ch < 0) break;
1319  if (ch == terminator) break;
1320 
1321  #if defined(ALLWIZE_DEBUG_PORT)
1322  {
1323  char buffer[5];
1324  snprintf(buffer, sizeof(buffer), "r %02X", ch);
1325  ALLWIZE_DEBUG_PRINTLN(buffer);
1326  }
1327  #endif
1328 
1329  *buffer++ = (char) ch;
1330  index++;
1331  }
1332  return index;
1333 }
1334 
1342 void AllWize::_hex2bin(char * hex, uint8_t * bin, uint8_t len) {
1343  for (uint8_t i=0; i<len; i+=2) {
1344  bin[i/2] = ((hex[i] - '0') * 16 + (hex[i+1] - '0')) & 0xFF;
1345  }
1346 }
1347 
1355 void AllWize::_bin2hex(uint8_t * bin, char * hex, uint8_t len) {
1356  for (uint8_t i=0; i<len; i++) {
1357  sprintf(&hex[i*2], "%02X", bin[i]);
1358  }
1359 }
uint8_t getChannel()
Gets the channel stored in non-volatile memory.
Definition: AllWize.cpp:407
void setInstallMode(uint8_t mode, bool persist=false)
Sets the module in one of the available operations modes.
Definition: AllWize.cpp:619
bool setUID(uint32_t uid)
Saved the UID into the module memory uid UID to save.
Definition: AllWize.cpp:780
void setEncryptFlag(uint8_t flag)
Sets the encrypt flag setting.
Definition: AllWize.cpp:640
uint8_t getSleepMode()
Gets the sleep mode stored in non-volatile memory.
Definition: AllWize.cpp:484
uint8_t getLEDControl()
Gets the current LED control.
Definition: AllWize.cpp:571
uint8_t getPower()
Gets the RF power stored in non-volatile memory.
Definition: AllWize.cpp:429
int _readBytes(char *buffer, uint16_t len)
Reads the stream buffer up to a number of bytes.
Definition: AllWize.cpp:1283
bool _setMemory(uint8_t address, uint8_t *data, uint8_t len)
Sets non-volatile memory contents starting from given address.
Definition: AllWize.cpp:923
uint8_t getEncryptFlag()
Gets the encrypt flag setting.
Definition: AllWize.cpp:651
AllWize(HardwareSerial *serial, uint8_t reset_gpio=GPIO_NONE)
AllWize object constructor.
Definition: AllWize.cpp:34
void slave()
Sets the module in slave mode.
Definition: AllWize.cpp:192
void setPower(uint8_t power, bool persist=false)
Sets the RF power.
Definition: AllWize.cpp:416
void setNetworkRole(uint8_t role)
Sets the network role.
Definition: AllWize.cpp:547
String _getMemoryAsHexString(uint8_t address, uint8_t len)
Returns the contents of the memory from a certain address as an HEX String.
Definition: AllWize.cpp:986
bool getAppendRSSI()
Gets the current RSSI mode value.
Definition: AllWize.cpp:505
bool _decode()
Decodes the current RX buffer contents.
Definition: AllWize.cpp:1071
uint8_t getVersion()
Returns the module version from non-volatile memory.
Definition: AllWize.cpp:793
void setControlField(uint8_t value, bool persist=false)
Sets the control field value.
Definition: AllWize.cpp:599
int8_t _sendCommand(uint8_t command, uint8_t *data, uint8_t len)
Sends a command with the given data.
Definition: AllWize.cpp:874
void dump(Stream &debug)
Dumps the current memory configuration to the given stream.
Definition: AllWize.cpp:248
void setMode(uint8_t mode, bool persist=false)
Sets the module in one of the available MBus modes.
Definition: AllWize.cpp:456
void setPreamble(uint8_t preamble)
Sets the preamble length frame format.
Definition: AllWize.cpp:513
uint8_t getControlField()
Gets the control field value stored in non-volatile memory.
Definition: AllWize.cpp:610
uint8_t getTimeout()
Gets the current timeout for auto sleep modes.
Definition: AllWize.cpp:539
uint8_t getPreamble()
Gets the preamble length frame format.
Definition: AllWize.cpp:523
int8_t _receive()
Listens to incomming data from the module until timeout or END_OF_RESPONSE.
Definition: AllWize.cpp:1228
bool send(uint8_t *buffer, uint8_t len)
Sends a byte array.
Definition: AllWize.cpp:301
String getUID()
Returns the Unique ID string.
Definition: AllWize.cpp:772
uint8_t getTemperature()
Returns the RSSI of the last valid packet received TODO: values do not seem right and are not the sam...
Definition: AllWize.cpp:720
bool ready()
Test whether the radio module is ready or not.
Definition: AllWize.cpp:226
void setSleepMode(uint8_t mode)
Sets the sleep mode.
Definition: AllWize.cpp:476
uint8_t getDecryptFlag()
Gets the decrypt flag setting.
Definition: AllWize.cpp:667
void setControlInformation(uint8_t ci)
Sets the control information byte.
Definition: AllWize.cpp:379
void wakeup()
Wakes up the radio from sleep mode.
Definition: AllWize.cpp:218
void master()
Sets the module in master mode.
Definition: AllWize.cpp:178
bool available()
Returns true if a new message has been received and decoded This method has to be called in the main ...
Definition: AllWize.cpp:334
uint8_t getDevice()
Returns the device version from non-volatile memory.
Definition: AllWize.cpp:801
void setLEDControl(uint8_t value)
Sets the LED control.
Definition: AllWize.cpp:563
int8_t _sendAndReceive(uint8_t *buffer, uint8_t len)
Sends a binary buffer and waits for response. Returns the number of bytes received and stored in the ...
Definition: AllWize.cpp:1239
void setTimeout(uint8_t timeout)
Sets the timeout for auto sleep modes.
Definition: AllWize.cpp:531
uint8_t _getMemory(uint8_t address, uint8_t *buffer, uint8_t len)
Returns the contents of consecutive memory addresses.
Definition: AllWize.cpp:953
void setDecryptFlag(uint8_t flag)
Sets the decrypt flag setting.
Definition: AllWize.cpp:659
String getPartNumber()
Returns the module part number.
Definition: AllWize.cpp:809
void _reset_serial()
Resets the serial object.
Definition: AllWize.cpp:90
void repeater()
Sets the module in repeater mode.
Definition: AllWize.cpp:202
bool waitForReady(uint32_t timeout=DEFAULT_TIMEOUT)
Waits for timeout millis for the module to be ready.
Definition: AllWize.cpp:235
uint8_t getNetworkRole()
Gets the current network role.
Definition: AllWize.cpp:555
uint8_t getMode()
Gets the MBus mode stored in non-volatile memory.
Definition: AllWize.cpp:468
int _readBytesUntil(char terminator, char *buffer, uint16_t len)
Reads the stream buffer up to a certain char or times out.
Definition: AllWize.cpp:1312
void sleep()
Sets the radio module in sleep mode.
Definition: AllWize.cpp:210
String getFirmwareVersion()
Returns the module firmware revision.
Definition: AllWize.cpp:827
bool _setConfig(bool value)
Sets or unsets config mode.
Definition: AllWize.cpp:850
String getMID()
Returns the Manufacturer ID string.
Definition: AllWize.cpp:753
void setChannel(uint8_t channel, bool persist=false)
Sets the communications channel (for MBUS_MODE_R2 only)
Definition: AllWize.cpp:396
void setAppendRSSI(bool value)
Sets the RSSI mode value.
Definition: AllWize.cpp:492
String getSerialNumber()
Returns the module serial number.
Definition: AllWize.cpp:836
void getDefaultKey(uint8_t *key)
Gets the default encryption key.
Definition: AllWize.cpp:697
String _getMemoryAsString(uint8_t address, uint8_t len)
Returns the contents of the memory from a certain address as a String object.
Definition: AllWize.cpp:1003
void _readModel()
Reads and caches the module model & version.
Definition: AllWize.cpp:1017
uint8_t getControlInformation()
Gets the control information byte.
Definition: AllWize.cpp:387
void setDataInterface(uint8_t value)
Sets the data interface for receiving packets.
Definition: AllWize.cpp:579
int _timedRead()
Reads a byte from the stream with a timeout.
Definition: AllWize.cpp:1264
void setKey(uint8_t reg, const uint8_t *key)
Sets the default encryption key.
Definition: AllWize.cpp:676
void setDefaultKey(const uint8_t *key)
Sets the default encryption key.
Definition: AllWize.cpp:689
uint8_t getInstallMode()
Gets the install modevalue stored in non-volatile memory.
Definition: AllWize.cpp:632
bool reset()
Resets the radio module.
Definition: AllWize.cpp:127
bool setMID(uint16_t mid)
Sets the Manufacturer ID mid MID to save.
Definition: AllWize.cpp:761
String getRequiredHardwareVersion()
Returns the module hardware revision.
Definition: AllWize.cpp:818
void _bin2hex(uint8_t *bin, char *hex, uint8_t len)
Converts a binary buffer to an hex c-string.
Definition: AllWize.cpp:1355
uint8_t _send(uint8_t *buffer, uint8_t len)
Sends a binary buffer to the module UART. Returns the number of bytes actually sent.
Definition: AllWize.cpp:1215
void begin()
Inits the module communications.
Definition: AllWize.cpp:79
void _hex2bin(char *hex, uint8_t *bin, uint8_t len)
Converts a hex c-string to a binary buffer.
Definition: AllWize.cpp:1342
void _flush()
Flushes the serial line to the module.
Definition: AllWize.cpp:1187
uint8_t getDataInterface()
Gets the data interface for receiving packets.
Definition: AllWize.cpp:590
void setDataRate(uint8_t dr)
Sets the data rate.
Definition: AllWize.cpp:437
uint8_t getDataRate()
Gets the data rate stored in non-volatile memory.
Definition: AllWize.cpp:447
allwize_message_t read()
Returns latest received message.
Definition: AllWize.cpp:367
uint16_t getVoltage()
Returns the internal voltage of the module.
Definition: AllWize.cpp:737
bool factoryReset()
Resets the module to factory settings.
Definition: AllWize.cpp:158