azureazure-functionsazureservicebusazure-iot-hub

Azure functions decoding error for IotHub device connection state message schema


I've a Azure function in Python 3.11 and Linux hosting. It is throwing an error when trigger is service bus queue message, which is having IoTHub device connection state message with schema like this

schema.Result: Failure Exception: ValueError: cannot convert value of field 'SequenceNumber' in trigger metadata into int: invalid literal for int() with base 10: '000000000000000001dummy100000004000000000000000000, File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py", line 570, in _handle__invocation_request args[pb.name] = bindings.from_incoming_proto

function code

@app.service_bus_queue_trigger(arg_name="azservicebus", queue_name="iothub-device-lifecycle-events",
                               connection="ServiceBusConnection")
def genaiot_servicebus_dlm_queue_trigger(azservicebus: func.ServiceBusMessage):
    logging.info('Python ServiceBus Queue trigger processed a message: %s',
                azservicebus.get_body().decode('utf-8'))

Solution

  • I could see the same issue when trying to trigger a Python Function App based off the message body generated by Device Connect/Disconnect status event originating from IoT Hub.

    The message body generated by this event consists only a sequenceNumber property in the base 10 format which the causing the function processing to fail because of a formatting error which happens as the backend before entering the function code block.

    Here is a sample message body generated by the event enter image description here

    Instead of using IoT Hub routing, use Events under IoT Hub and filter Device Connected and Device Disconnected Events` to track the event types. Choose your Service Bus Queue as an end point. Refer the following image for set up.

    enter image description here

    Disable the route set up using IoT Hub. The events generated with this approach will have a different template. Here is a sample message body generated by such event

    enter image description here

    You can then process the event generated using the below code and get the desired data

    @app.service_bus_queue_trigger(arg_name="azservicebus", queue_name="lsayanaiot",
                               connection="lsayanaservicebus_SERVICEBUS") 
    def lsayana_servicebus_queue_trigger(azservicebus: func.ServiceBusMessage):
        message_body = json.loads(azservicebus.get_body().decode('utf-8'))
        logging.info('Message body is %s', message_body)
        sequence_number = message_body['data']['deviceConnectionStateEventInfo']['sequenceNumber']
        logging.info('Python ServiceBus Queue trigger processed a message: %s',
                    sequence_number)