pycom / pycom-micropython-sigfox

A fork of MicroPython with the ESP32 port customized to run on Pycom's IoT multi-network modules.
MIT License
196 stars 167 forks source link

Cannot deploy new wifi configuration via Pybytes to GPy board #550

Open jandillmann opened 3 years ago

jandillmann commented 3 years ago

Please include the following information when submitting a bug report:

gijsio commented 3 years ago

Hi, I was not able to reproduce your issue, of provisioning a device with only LTE, and then deploying a new network configuration with Wifi through the device's configuration tab in Pybytes. Perhaps you could try to enable Pybytes debugging on your device using import pycom; pycom.nvs_set('pybytes_debug', 99); import machine; machine.reset().

I did have a short look in the code, and it seems your device is trying to do a firmware update over the air using WiFi (perhaps Im mistaken), where the WiFi credentials are missing (KeyError: wifi). Though the additional log might indicate what is going on exactly

jandillmann commented 3 years ago

If I enable Pybytes debugging this is the console output:

entry 0x400a05bc
{'wlan_antenna': 0, 'ssl': False, 'ota_server': {'port': 443, 'domain': 'software.pycom.io'}, 'server': 'mqtt.pybytes.pycom.io', 'cfg_msg': 'Pybytes configuration read from /flash/pybytes_config.json', 'lte': {'apn': 'em', 'cid': 1, 'reset': False, 'carrier': 'standard', 'band': 20, 'type': 'IP'}, 'device_id': '00000000-0000-0000-0000-000000000000', 'network_preferences': ['lte'], 'pybytes_autostart': True, 'dump_ca': False, 'username': 'email@example.org'}
 ssl_params={'ca_certs': '/flash/cert/pycom-ca.pem'} 
LIS2HH12 not imported
 ssl_params={'ca_certs': '/flash/cert/pycom-ca.pem'} 
WMAC: 840D8E122018
Firmware: 1.20.2.r4
Pybytes: 1.6.1
{'wlan_antenna': 0, 'ssl': False, 'ota_server': {'port': 443, 'domain': 'software.pycom.io'}, 'server': 'mqtt.pybytes.pycom.io', 'cfg_msg': 'Pybytes configuration read from /flash/pybytes_config.json', 'lte': {'apn': 'em', 'cid': 1, 'reset': False, 'carrier': 'standard', 'band': 20, 'type': 'IP'}, 'device_id': '00000000-0000-0000-0000-000000000000', 'network_preferences': ['lte'], 'pybytes_autostart': True, 'dump_ca': False, 'username': 'email@example.org'}
Attempting to connect with network lte
Initialized watchdog for WiFi and LTE connection with timeout 1260000 ms
LTE init(carrier=None, cid=1)
LTE attach(band=20, apn=em, type=IP)
LTE connect()
LTE is_connected()
LTE connection established
connect_lte with start_mqtt is now removed please call communication_protocol or start_mqtt directly
MQTT Protocol
Packet sent. (Length: 114)
This is PybytesProtocol.start_MQTT
Packet sent. (Length: 44)
Connected to MQTT mqtt.pybytes.pycom.io
Pybytes connected successfully (using the built-in pybytes library)
This is pack_info_message()
__pack_message: b'310504a00584000000'
MQTT Protocol
Packet sent. (Length: 50)
Pybytes configuration read from /flash/pybytes_config.json
Pycom MicroPython 1.20.2.r4 [v1.11-ffb0e1c] on 2021-01-12; GPy with ESP32
Pybytes Version: 1.6.1
Type "help()" for more information.
>>> This is PybytesProtocol.__process_recv_message()
This is PybytesLibrary.unpack_message(message=b'\x0c')
header: 12 body: b''
network_type: 0
message_type: 12
Unhandled exception in thread started by <bound_method>
Traceback (most recent call last):
  File "_msg_handl.py", line 259, in _io_thread_func
  File "_msg_handl.py", line 197, in _receive_packet
  File "_mqtt_core.py", line 398, in _recv_callback
  File "_mqtt_core.py", line 368, in _parse_publish
  File "_mqtt_core.py", line 341, in _notify_message
  File "_mqtt.py", line 91, in set_callback
  File "_pybytes_protocol.py", line 188, in __process_recv_message
KeyError: wifi

Interestingly, the string This is Pybytes appears three times just before output from the Pybytes MQTT code…

gijsio commented 3 years ago

Hi, Thanks for the elaboration. I was able to get my sample to work, but I forgot to save my own debuging output, so I'll have to get back to you with that after the weekend. In the meantime, I'm assuming the first part ( before Pycom MicroPython 1.20.2.r4 [v1.11-ffb0e1c]) is the connection part, and after that is the 'deploy network configuration' section? What I was able to find, is message_type = 12 is a __TYPE_DEVICE_NETWORK_DEPLOY (as we expect, I think), which is indeed where the code stops working, as it expects the 'wifi' key to be available. Now Im not sure why mine worked, as I was sure to only select the LTE network upon provisioning, but again, I'll get back to you with that.

Btw. The This is Pybytes is the correct printing and part of the actual debug information string.

jandillmann commented 3 years ago

Thanks for your answer. Everything until >>> is from the start / boot process of the GPy, and after the >>> is the deployment of the new network configuration.

I tested some more and have the same error when I deploy with Wifi and LTE (GPy boots and connects to Wifi), then disable Wifi in Pybytes and deploy (GPy reboots and connects to LTE), and then enable Wifi in Pybytes again and deploy the configuration.

gijsio commented 3 years ago

Hi, Thanks for your patience. I cannot get it to work for me anymore either and I get the same error as you. Probably I had a Pybytes configuration with WiFi listed on the device already, which might be why it worked for me before, sorry about that.

I was able to fix the issue, but have to test some regressions. It might be some time before it gets released in a new firmware. I can already inform you of the differences:

in esp32/frozen/Pybytes/_pybytes_protocol.py Comment lines 188 and 189, as we dont have the wifi credentials yet

# self.__conf['wifi']['ssid'],
# self.__conf['wifi']['password'],

in esp32/frozen/Pybytes/_OTA.py Replace line 227 with the following, to allow the WiFi configuration to be undefined

def __init__(self, ip, port, ssid=None, password=None):
jandillmann commented 3 years ago

Thank you for finding the bug so quickly!

Any estimate on when the next firmware version will be shipped?

gijsio commented 3 years ago

I cannot give you any certainty there unfortunately. In the meantime I was able to improve the solution somewhat, with the only change required: in esp32/frozen/Pybytes/_pybytes_protocol.py Change lines 188 and 189, as we dont have the wifi credentials yet, to 'None'

None,
None,

and figure that, as a temporary fix, if you initially provision the device with LTE as priority 1, and set WiFi in the configuration as priority 2 (you could even use credentials that do not work) , there is no issue, and the device will connect over LTE by default (which, if no connection is possible after the timeout is reached, will eventually switch over to WiFi if available). This means you will not need to edit the firmware.

jandillmann commented 3 years ago

I added a quick fix to my boot.py, which reads the pybytes_config.json file and adds a wifi key with empty ssid and password if it is missing. This way the deployment of new network credentials won't fail if no wifi is is found.

from _pybytes import Pybytes
import ujson

with open("pybytes_config.json") as file:
    pybytes_config = ujson.load(file)

if not "wifi" in pybytes_config:
    print("Fix: Add empty 'wifi' configuration to pybytes_config.json")
    pybytes = Pybytes(pybytes_config)
    pybytes.set_config("wifi", value={"ssid": None, "password": None}, permanent=True, silent=True, reconnect=False)