Azure / azure-iot-sdk-python

A Python SDK for connecting devices to Microsoft Azure IoT services
MIT License
417 stars 374 forks source link

async_hub fails #1157

Open LaudixGit opened 8 months ago

LaudixGit commented 8 months ago

Context

Raspberry Pi4B Linux RPi4-Alpha 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64 GNU/Linux iotedge 1.4.16 Python 3.9.2 pip 23.2.1 from /usr/local/lib/python3.9/dist-packages/pip (python 3.9)

Package             Version
------------------- ---------
azure-iot-device    2.12.0
certifi             2020.6.20
chardet             4.0.0
colorzero           1.1
deprecation         2.1.0
distro              1.5.0
gpiozero            1.6.2
idna                2.10
janus               1.0.0
numpy               1.19.5
packaging           23.2
paho-mqtt           1.6.1
picamera2           0.3.12
pidng               4.0.9
piexif              1.1.3
Pillow              8.1.2
pip                 23.2.1
PySocks             1.7.1
python-apt          2.2.1
python-prctl        1.7
requests            2.25.1
requests-unixsocket 0.3.0
RPi.GPIO            0.7.0
setuptools          52.0.0
simplejpeg          1.6.4
six                 1.16.0
spidev              3.5
ssh-import-id       5.10
toml                0.10.1
typing_extensions   4.8.0
urllib3             1.26.5
v4l2-python3        0.3.2
wheel               0.34.2

Description of the issue

With Edge agents halted sudo iotedge system stop this sample works launched from the command line. Tested by this command in cloudshell: az iot hub invoke-device-method --device-id "Alpha" --hub-name "hub2" --method-name "method1"

With the Edge agent restored (either reboot or sudo iotedge config apply -c '/etc/aziot/config.toml'), similar code based on this sample never triggers the on_method_request_received call_back.

There are no errors in the logs, however the cloudshell command fails with Error occurred in request., ReadTimeout: HTTPSConnectionPool(host='edge2.azure-devices.net', port=443): Read timed out. (read timeout=30)

There are no errors in sudo iotedge check --verbose The container successfully writes to the logs - which correctly show in Azure Portal "Troubleshooting'. image

Command used to create the container: sudo docker build --rm -f "./modules/App/Dockerfile.arm64v8" -t iotedge.azurecr.io/app:2023.10.12.16.10-arm64 "./modules/App/"

Code sample exhibiting the issue

A simplification of this sample

import asyncio
import sys
import signal
import threading
from azure.iot.device.aio import IoTHubModuleClient
from datetime import datetime

# Event indicating client stop
stop_event = threading.Event()

def create_client():
    client = IoTHubModuleClient.create_from_edge_environment()

    # Define behavior for receiving methods
    async def method_handler(method_request):
        print("method request received: {}".format(method_request.name))
        method_response = MethodResponse.create_from_method_request(method_request, 400, None)
        await client.send_method_response(method_response)

    # set the received data handlers on the client
    client.on_method_request_received = method_handler

    return client

async def run_sample(client):
    await client.connect()
    while not stop_event.is_set():
        now = datetime.now()
        current_time = now.strftime("%H:%M:%S")
        print(current_time, "   heartbeat")

        await asyncio.sleep(15)

def main():
    if not sys.version >= "3.5.3":
        raise Exception( "The sample requires python 3.5.3+. Current version of Python: %s" % sys.version )
    print ( "IoT Hub Client for Python" )

    # NOTE: Client is implicitly connected due to the handler being set on it
    client = create_client()

    # Define a handler to cleanup when module is is terminated by Edge
    def module_termination_handler(signal, frame):
        print ("IoTHubClient sample stopped by Edge")
        stop_event.set()

    # Set the Edge termination handler
    signal.signal(signal.SIGTERM, module_termination_handler)

    # Run the sample
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(run_sample(client))
    except Exception as e:
        print("Unexpected error %s " % e)
        raise
    finally:
        print("Shutting down IoT Hub Client...")
        loop.run_until_complete(client.shutdown())
        loop.close()

if __name__ == "__main__":
    main()

Console log of the issue

No error in the log

LaudixGit commented 8 months ago

Note: the device appears to have the latest versions installed image

LaudixGit commented 8 months ago

This seems to imply that running as a container cannot work since Docker already has the connection https://github.com/Azure/azure-iot-sdk-python/issues/445#issuecomment-579489769

the docker container for your module probably has a process that's has it's own network connection for the module

LaudixGit commented 8 months ago

Apparently, the simulated sensor also implements the Direct method. (line 84) This is failing too.

The container is successfully running and telemetry is received in Azure IoT Hub. Module twin is processed successfully. image

When 'reset' is sent to the device another line should appear in the log: "Received direct...". This fails to appear, and the message times out. image

For reference, this is the code that show process the Direct request. image