You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决IoT设备消息体无法被本地Azure Functions接收处理的问题

问题:Azure Functions读取IoT Hub消息体时抛出TypeError错误

问题描述

传感器检测到人员并向云端发送数据后,本地VSCode中的Azure Functions无法正确读取消息体,抛出TypeError: list indices must be integers or slices, not str错误。日志显示接收到的消息体为列表类型,其中data.body是Base64编码的业务数据,但代码中直接按字典取值(如date = body['date'])导致索引错误。

期望实现:Azure Functions读取设备发送的消息体,并将数据写入本地MySQL数据库的notifications表。

原代码

import logging
import azure.functions as func
import mysql.connector
import time
from datetime import datetime
import json
import os
from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import CloudToDeviceMethod

def main(event: func.EventHubEvent):
    # Connect database MySQL
    dbconnection = mysql.connector.connect(
        host = "127.0.0.1",
        user = "root",
        password = "",
        database = "roomdb"
    )
    cursor = dbconnection.cursor()

    body = json.loads(event.get_body().decode('utf-8'))
    device_id = event.iothub_metadata.get('automate-device-id')

    # logging.info(f'Received message: {body} from {device_id}')

    id = 1
    date = body['date']
    time = body['time']
    temperature = body['temperature']
    people = body['people']
    detect_time = body['last_detected_time']
    notification_type = ""
    message = "You can view more via website"
    room_id = 1
    sql = ""

    # Insert into database using the notifications
    sql = "insert into notifications (id, date, time, value_temperature, number_of_people, notification_type, message, room_id) values (%s, %s, %s, %s, %s, %s, %s, %s)"
    value = (id, date, time, temperature, people, notification_type, message, room_id)

    cursor.execute(sql, value)
    dbconnection.commit()
    print(cursor.rowcount, 'Data Saved Successfully')

    cursor.close()
    dbconnection.close()

错误日志

[2024-01-10T09:57:10.295Z] Executing 'Functions.AutomateHubTrigger' (Reason='(null)', Id=d286be5c-f5e8-4260-9c9e-a6e27de9b87c)
[2024-01-10T09:57:10.300Z] Trigger Details: PartionId: 1, Offset: 4294979360, EnqueueTimeUtc: 2024-01-10T09:55:47.2540000+00:00, SequenceNumber: 110, Count: 1
[2024-01-10T09:57:10.306Z] Type of body: <class 'list'>, Content of body: [{'id': 'f6acfe2e-8725-2b54-777d-79b477db2796', 'topic': '/SUBSCRIPTIONS/D0E3660E-537C-4385-89F5-B2B0646AF52A/RESOURCEGROUPS/AUTOMATE/PROVIDERS/MICROSOFT.DEVICES/IOTHUBS/AUTOMATE-HUB', 'subject': 'devices/automate-device-id', 'eventType': 'Microsoft.Devices.DeviceTelemetry', 'data': {'properties': {}, 'systemProperties': {'iothub-connection-device-id': 'automate-device-id', 'iothub-connection-auth-method': '{"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}', 'iothub-connection-auth-generation-id': '638364984370269801', 'iothub-enqueuedtime': '2024-01-10T09:55:47.0870000Z', 'iothub-message-source': 'Telemetry'}, 'body': 'eyJkYXRlIjogIjIwMjQtMDEtMTAiLCAidGltZSI6ICIxNjo1NTo0NiIsICJ0ZW1wZXJhdHVyZSI6IDM0LjAsICJwZW9wbGUiOiAwfQ=='}, 'dataVersion': '', 'metadataVersion': '1', 'eventTime': '2024-01-10T09:55:47.087Z'}]
[2024-01-10T09:57:10.310Z] Executed 'Functions.AutomateHubTrigger' (Failed, Id=d286be5c-f5e8-4260-9c9e-a6e27de9b87c, Duration=15ms)
[2024-01-10T09:57:10.314Z] System.Private.CoreLib: Exception while executing function: Functions.AutomateHubTrigger. System.Private.CoreLib: Result: Failure
Exception: TypeError: list indices must be integers or slices, not str
Stack:   File "C:\Users\Viqram Wataf\AppData\Roaming\nvm\v10.24.0\node_modules\azure-functions-core-tools\bin\workers\python\3.9\WINDOWS\X64\azure_functions_worker\dispatcher.py", line 406, in _handle__invocation_request
call_result = await self._loop.run_in_executor(
File "C:\Program Files\Python 3.9.0\lib\concurrent\futures\thread.py", line 52, in run
result = self.fn(*self.args, **self.kwargs)
File "C:\Users\Viqram Wataf\AppData\Roaming\nvm\v10.24.0\node_modules\azure-functions-core-tools\bin\workers\python\3.9\WINDOWS\X64\azure_functions_worker\dispatcher.py", line 648, in _run_sync_func
return ExtensionManager.get_sync_invocation_wrapper(context,
File "C:\Users\Viqram Wataf\AppData\Roaming\nvm\v10.24.0\node_modules\azure-functions-core-tools\bin\workers\python\3.9\WINDOWS\X64\azure_functions_worker\extension.py", line 215, in _raw_invocation_wrapper
result = function(**args)
File "C:\xampp\htdocs\tugas-akhir-project\Tugas-Akhir\azure_function\AutomateHubTrigger___init___.py", line 29, in main
date = body['date']

解决方法

错误原因

解析后的消息体是列表类型,列表中包含IoT Hub封装的事件对象,真实业务数据被Base64编码后存储在事件对象的data.body字段中,直接用字典索引访问列表会触发类型错误。

修改后的代码

import logging
import azure.functions as func
import mysql.connector
import time
from datetime import datetime
import json
import os
import base64  # 新增:用于Base64解码
from azure.iot.hub import IoTHubRegistryManager
from azure.iot.hub.models import CloudToDeviceMethod

def main(event: func.EventHubEvent):
    # Connect database MySQL
    dbconnection = mysql.connector.connect(
        host = "127.0.0.1",
        user = "root",
        password = "",
        database = "roomdb"
    )
    cursor = dbconnection.cursor()

    # 修正:解析消息体为列表,取出第一个事件对象
    event_list = json.loads(event.get_body().decode('utf-8'))
    event_data = event_list[0]
    # 提取Base64编码的业务数据并解码
    raw_business_data = base64.b64decode(event_data['data']['body']).decode('utf-8')
    business_data = json.loads(raw_business_data)
    
    device_id = event.iothub_metadata.get('automate-device-id')

    # logging.info(f'Received message: {business_data} from {device_id}')

    id = 1
    date = business_data['date']
    time = business_data['time']
    temperature = business_data['temperature']
    people = business_data['people']
    detect_time = business_data.get('last_detected_time', '')  # 增加容错,避免字段缺失报错
    notification_type = ""
    message = "You can view more via website"
    room_id = 1

    # Insert into database using the notifications
    sql = "insert into notifications (id, date, time, value_temperature, number_of_people, notification_type, message, room_id) values (%s, %s, %s, %s, %s, %s, %s, %s)"
    value = (id, date, time, temperature, people, notification_type, message, room_id)

    cursor.execute(sql, value)
    dbconnection.commit()
    print(cursor.rowcount, 'Data Saved Successfully')

    cursor.close()
    dbconnection.close()

关键修改点

  1. 新增base64模块导入,用于解码Base64格式的业务数据
  2. 调整消息体解析逻辑:先获取事件列表中的第一个对象,再提取并解码data.body中的真实业务数据
  3. 所有业务字段的取值改为从解码后的business_data字典获取
  4. 增加business_data.get('last_detected_time', '')容错处理,避免字段缺失导致报错

内容的提问来源于stack exchange,提问作者VIQRAM ANANTA WATAF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 19:34:58