diff --git a/esp32/frozen/Pybytes/_mqtt_core.py b/esp32/frozen/Pybytes/_mqtt_core.py index c9adf917f0..d9fa9253e7 100644 --- a/esp32/frozen/Pybytes/_mqtt_core.py +++ b/esp32/frozen/Pybytes/_mqtt_core.py @@ -78,7 +78,7 @@ def connect(self, clean_session=True): self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) print("Using MQTT over TLS") else: - print("WARNING: consider enabling TLS by using \"ssl\": true in pybytes_config.json") + print("WARNING: consider enabling TLS by using pybytes.enable_ssl()") premsg = bytearray(b"\x10\0\0\0\0\0") msg = bytearray(b"\x04MQTT\x04\x02\0\0") diff --git a/esp32/frozen/Pybytes/_pybytes.py b/esp32/frozen/Pybytes/_pybytes.py index f9ef105260..e55e26f2d1 100644 --- a/esp32/frozen/Pybytes/_pybytes.py +++ b/esp32/frozen/Pybytes/_pybytes.py @@ -1,9 +1,5 @@ import os from machine import Timer -try: - from pybytes_protocol import PybytesProtocol -except: - from _pybytes_protocol import PybytesProtocol try: from pybytes_connection import PybytesConnection except: @@ -222,14 +218,14 @@ def get_config(self, key=None): else: return self.__conf.get(key) - def set_config(self, key=None, value=None, permanent=True): + def set_config(self, key=None, value=None, permanent=True, silent=False): if key is None and value is not None: self.__conf = value elif key is not None: self.__conf[key] = value else: raise ValueError('You need to either specify a key or a value!') - if permanent: self.write_config() + if permanent: self.write_config(silent=silent) def read_config(self, file='/flash/pybytes_config.json'): try: @@ -259,7 +255,8 @@ def enable_ssl(self, ca_file='/flash/cert/pycom-ca.pem', dump_ca = True): self.set_config('dump_ca', dump_ca, permanent=False) if ca_file is not None: self.set_config('ssl_params', {'ca_certs': ca_file}, permanent=False) - self.set_config('ssl', True) + self.set_config('ssl', True, silent=True) + print('Please reset your module to apply the new settings.') def dump_ca(self, ca_file='/flash/cert/pycom-ca.pem'): try: diff --git a/esp32/frozen/Pybytes/_pybytes_config.py b/esp32/frozen/Pybytes/_pybytes_config.py index 14c580cb00..f329630e4e 100644 --- a/esp32/frozen/Pybytes/_pybytes_config.py +++ b/esp32/frozen/Pybytes/_pybytes_config.py @@ -108,23 +108,29 @@ def read_config(self, file='/flash/pybytes_config.json'): band = None apn = None reset = False + type = None + + if len(extra_preferences[index + 1]) > 0 and extra_preferences[index + 1].lower() != 'none': + carrier = extra_preferences[index + 1] if len(extra_preferences[index + 2]) > 0 and extra_preferences[index + 2].isdigit(): cid = int(extra_preferences[index + 2]) if len(extra_preferences[index + 3]) > 0 and extra_preferences[index + 3].isdigit(): band = int(extra_preferences[index + 3]) - if len(extra_preferences[index + 1]) > 0 and extra_preferences[index + 1].lower() != 'none': - carrier = extra_preferences[index + 1] if len(extra_preferences[index + 4]) > 0 and extra_preferences[index + 4].lower() != 'none': apn = extra_preferences[index + 4] if len(extra_preferences[index + 5]) > 0 and extra_preferences[index + 5].lower() == 'true': reset = True + if len(extra_preferences[index + 6]) > 0 and extra_preferences[index + 6].lower() != 'none': + type = extra_preferences[index + 6] + lte_config = { 'lte': { 'carrier': carrier, 'cid': cid, 'band': band, 'apn': apn, - 'reset': reset + 'reset': reset, + 'type': type } } except: diff --git a/esp32/frozen/Pybytes/_pybytes_connection.py b/esp32/frozen/Pybytes/_pybytes_connection.py index 1743227043..b7c3f49f90 100644 --- a/esp32/frozen/Pybytes/_pybytes_connection.py +++ b/esp32/frozen/Pybytes/_pybytes_connection.py @@ -21,6 +21,7 @@ import socket import struct import binascii +from machine import WDT class PybytesConnection: def __init__(self, config, message_callback): @@ -42,7 +43,7 @@ def __init__(self, config, message_callback): self.lte = None self.wlan = None self.__network_type = None - + self.__wifi_lte_watchdog = None def lte_ping_routine(self, delay): while True: @@ -56,8 +57,17 @@ def print_pretty_response(self, rsp): if line not in ['OK']: print(line) + def __initialise_watchdog(self): + if self.__conf.get('connection_watchdog', True): + self.__wifi_lte_watchdog = WDT(timeout=constants.__WDT_TIMEOUT_MILLISECONDS) + print('Initialized watchdog for WiFi and LTE connection with timeout {} ms'.format(constants.__WDT_TIMEOUT_MILLISECONDS)) + else: + print('Watchdog for WiFi and LTE was disabled, enable with "connection_watchdog": true in pybytes_config.json') + + # Establish a connection through WIFI before connecting to mqtt server def connect_wifi(self, reconnect=True, check_interval=0.5): - """Establish a connection through WIFI before connecting to mqtt server""" + self.__initialise_watchdog() + if self.__connection_status != constants.__CONNECTION_STATUS_DISCONNECTED: print("Error connect_wifi: Connection already exists. Disconnect First") return False @@ -110,8 +120,10 @@ def connect_wifi(self, reconnect=True, check_interval=0.5): print("Exception connect_wifi: {}".format(ex)) return False + # Establish a connection through LTE before connecting to mqtt server def connect_lte(self, reconnect=True, check_interval=0.5): - """Establish a connection through LTE before connecting to mqtt server""" + self.__initialise_watchdog() + lte_cfg = self.__conf.get('lte') if lte_cfg is not None: if (os.uname()[0] not in ['FiPy', 'GPy']): diff --git a/esp32/frozen/Pybytes/_pybytes_constants.py b/esp32/frozen/Pybytes/_pybytes_constants.py index 38ab6b7257..9fdbec01f4 100644 --- a/esp32/frozen/Pybytes/_pybytes_constants.py +++ b/esp32/frozen/Pybytes/_pybytes_constants.py @@ -25,6 +25,7 @@ class constants: __TYPE_BATTERY_INFO = 0x04 __TYPE_OTA = 0x05 __TYPE_FCOTA = 0x06 + __TYPE_PONG = 0x07 __TYPE_PYBYTES = 0x0E __PYBYTES_PROTOCOL = ">B%ds" __PYBYTES_PROTOCOL_PING = ">B" @@ -65,3 +66,7 @@ class constants: __SIGFOX_WARNING = """WARNING! Your sigfox radio configuration (RC) is currently using the default (1) You can set your RC with command (ex: RC 3): pybytes.set_config('sigfox', {'RCZ': 3}) See all available zone options for RC at https://support.sigfox.com/docs/radio-configuration """ + + __KEEP_ALIVE_PING_INTERVAL = 600 # in seconds + # set watch dog timeout one minute after __KEEP_ALIVE_PING_INTERVAL + __WDT_TIMEOUT_MILLISECONDS = (__KEEP_ALIVE_PING_INTERVAL + 60) * 1000 diff --git a/esp32/frozen/Pybytes/_pybytes_library.py b/esp32/frozen/Pybytes/_pybytes_library.py index 7906207d2c..89f74b231f 100644 --- a/esp32/frozen/Pybytes/_pybytes_library.py +++ b/esp32/frozen/Pybytes/_pybytes_library.py @@ -13,6 +13,7 @@ import re from network import WLAN from time import sleep +import binascii try: from network import LoRa @@ -29,10 +30,12 @@ def pack_user_message(self, message_type, body): return self.__pack_message(message_type, body) def pack_pybytes_message(self, command, pin, value): + print_debug(5, "This is pack_pybytes_message({}, {}, {})".format(command, pin, value)) body = struct.pack(constants.__PYBYTES_INTERNAL_PROTOCOL, command, pin, value) return self.__pack_message(constants.__TYPE_PYBYTES, body) def pack_pybytes_message_variable(self, command, pin, parameters): + print_debug(5, "This is pack_pybytes_message_variable({}, {}, {})".format(command, pin, parameters)) body = struct.pack(constants.__PYBYTES_INTERNAL_PROTOCOL_VARIABLE % len(parameters), command, pin, parameters) return self.__pack_message(constants.__TYPE_PYBYTES, body) @@ -152,7 +155,7 @@ def __pack_message(self, message_type, body): header = header | (message_type & constants.__TYPE_MASK) if body is not None: - print_debug(3, '__pack_message: %s' % struct.pack(constants.__PYBYTES_PROTOCOL % len(body), header, body)) + print_debug(3, '__pack_message: %s' % binascii.hexlify(struct.pack(constants.__PYBYTES_PROTOCOL % len(body), header, body))) return struct.pack(constants.__PYBYTES_PROTOCOL % len(body), header, body) return struct.pack(constants.__PYBYTES_PROTOCOL_PING, header) diff --git a/esp32/frozen/Pybytes/_pybytes_protocol.py b/esp32/frozen/Pybytes/_pybytes_protocol.py index dfdef3bae7..ae709fd0c8 100644 --- a/esp32/frozen/Pybytes/_pybytes_protocol.py +++ b/esp32/frozen/Pybytes/_pybytes_protocol.py @@ -28,6 +28,7 @@ from machine import PWM from machine import Timer from machine import reset +from machine import WDT import os import sys @@ -35,6 +36,8 @@ import time import socket import struct +import machine +import binascii class PybytesProtocol: def __init__(self, config, message_callback, pybytes_connection): @@ -83,12 +86,14 @@ def __start_recv_mqtt(self): _thread.stack_size(self.__thread_stack_size) _thread.start_new_thread(self.__check_mqtt_message, ()) - self.__connectionAlarm = Timer.Alarm(self.__keep_connection, 60 * 10, periodic=True) + self.__connectionAlarm = Timer.Alarm(self.__keep_connection, constants.__KEEP_ALIVE_PING_INTERVAL, periodic=True) + + def __wifi_or_lte_connection(self): + return self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI or self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE def __check_mqtt_message(self): print_debug(5, "This is PybytesProtocol.__check_mqtt_message()") - while(self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI - or self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE): + while self.__wifi_or_lte_connection(): try: self.__pybytes_connection.__connection.check_msg() time.sleep(self.__mqtt_check_interval) @@ -99,8 +104,7 @@ def __check_mqtt_message(self): def __keep_connection(self, alarm): print_debug(5, "This is PybytesProtocol.__keep_connection(alarm={})".format(alarm)) - if (self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI - or self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE): + if self.__wifi_or_lte_connection(): self.send_ping_message() def __check_lora_messages(self): @@ -132,6 +136,10 @@ def __process_recv_message(self, message): if (message_type == constants.__TYPE_PING): self.send_ping_message() + elif message_type == constants.__TYPE_PONG and self.__conf.get('connection_watchdog', True): + print_debug(1,'message type pong received, feeding watchdog...') + self.__pybytes_connection.__wifi_lte_watchdog.feed() + elif (message_type == constants.__TYPE_INFO): self.send_info_message() @@ -331,9 +339,8 @@ def __send_message(self, message, topic=None): try: finalTopic = self.__mqtt_upload_topic if topic is None else self.__mqtt_upload_topic + "/" + topic - print_debug(2, "Sending message:[{}] with topic:[{}] and finalTopic: [{}]".format(message, topic, finalTopic)) - if (self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_WIFI - or self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_MQTT_LTE): + print_debug(2, "Sending message:[{}] with topic:[{}] and finalTopic: [{}]".format(binascii.hexlify(message), topic, finalTopic)) + if self.__wifi_or_lte_connection(): self.__pybytes_connection.__connection.publish(finalTopic, message) elif (self.__pybytes_connection.__connection_status == constants.__CONNECTION_STATUS_CONNECTED_LORA): with self.__pybytes_connection.lora_lock: @@ -390,14 +397,13 @@ def send_pybytes_digital_value(self, pin_number, pull_mode): if (not pin_number in self.__pins): self.__configure_digital_pin(pin_number, Pin.IN, pull_mode) pin = self.__pins[pin_number] - self.__send_pybytes_message(constants.__COMMAND_DIGITAL_WRITE, pin_number, pin()) + self.send_pybytes_custom_method_values(pin_number, [pin()]) def send_pybytes_analog_value(self, pin_number): if (not pin_number in self.__pins): self.__configure_analog_pin(pin_number) pin = self.__pins[pin_number] - - self.__send_pybytes_message(constants.__COMMAND_ANALOG_WRITE, pin_number, pin()) + self.send_pybytes_custom_method_values(pin_number, [pin()]) def send_pybytes_custom_method_values(self, method_id, parameters): diff --git a/esp32/pycom_version.h b/esp32/pycom_version.h index a1d0dd3ce5..3510040a92 100644 --- a/esp32/pycom_version.h +++ b/esp32/pycom_version.h @@ -10,14 +10,14 @@ #ifndef VERSION_H_ #define VERSION_H_ -#define SW_VERSION_NUMBER "1.20.0.rc11" +#define SW_VERSION_NUMBER "1.20.0.rc11.1" #define LORAWAN_VERSION_NUMBER "1.0.2" #define SIGFOX_VERSION_NUMBER "1.0.1" #if (VARIANT == PYBYTES) -#define PYBYTES_VERSION_NUMBER "0.9.7" +#define PYBYTES_VERSION_NUMBER "0.9.12" #endif #endif /* VERSION_H_ */