IoT Hub转PowerBI数据流遇InputDeserializerError问题求助
解决IoT Hub到PowerBI数据流的InputDeserializerError.InvalidData问题
核心问题出在JSON序列化格式不合法——你的字符串字段没有被正确包裹双引号,导致PowerBI的反序列化器无法解析消息。只保留数字时能正常工作,正好验证了这点:数字类型在JSON里不需要引号,而字符串必须用双引号包裹才符合规范。
问题根源
你原有的MSG_TXT模板里,Bin1Grower和Bin1Variety这两个字符串字段的占位符%s没有被双引号包裹。比如如果b1grower的值是"Grower001",原代码生成的JSON会是:
{"Bin1Load": 50,"Bin1Grower": Grower001,"Bin1Variety": Apple,...}
这种写法不符合JSON语法,PowerBI的反序列化器自然会抛出InvalidData错误。
修正后的代码方案
我帮你调整了JSON模板,同时修正了代码里变量名不一致的小问题(原代码定义了b1load,但格式化时误用了b1loads,会导致运行报错):
# 修正JSON模板:给字符串字段的占位符添加双引号 MSG_TXT = "{\"Bin1Load\": %s,\"Bin1Grower\": \"%s\",\"Bin1Variety\": \"%s\",\"Bin1StatedTn\": %.2f,\"Bin1S\": %.3f,\"Bin1CalcV\": %.2f}" def send_confirmation_callback(message, result, user_context): print ( "IoT Hub responded to message with status: %s" % (result) ) def iothub_client_init(): # Create an IoT Hub client client = IoTHubClient(CONNECTION_STRING, PROTOCOL) return client def iothub_client_telemetry_sample_run(): try: client = iothub_client_init() print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" ) while True: # Build the message with telemetry values from PLC b1load = comm.Read('Bin01.Content.Load') b1grower = comm.Read('Bin01.Content.Grower') b1variety = comm.Read('Bin01.Content.Variety') b1statedton = comm.Read('Bin01.Content.Stated_Tn') b1s = comm.Read('Bin01.Content.SG') b1calcvol = comm.Read('Bin01.Content.Calc_Vol') # 修正变量名:与前面定义的变量保持一致 msg_txt_formatted = MSG_TXT % (b1load, b1grower, b1variety, b1statedton, b1s, b1calcvol) message = IoTHubMessage(msg_txt_formatted) # 补充发送消息的逻辑(原代码遗漏了这一步) client.send_event_async(message, send_confirmation_callback, None) time.sleep(1) # 根据业务需求调整发送间隔 except KeyboardInterrupt: print ( "IoTHubClient sample stopped" )
更可靠的优化方案
手动拼接JSON字符串容易出现格式疏漏,推荐用Python内置的json模块来序列化数据,它会自动处理字符串引号、特殊字符转义等问题,代码也更易维护:
import json def iothub_client_telemetry_sample_run(): try: client = iothub_client_init() print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" ) while True: # 用字典组织遥测数据,自动处理类型格式 telemetry_data = { "Bin1Load": comm.Read('Bin01.Content.Load'), "Bin1Grower": comm.Read('Bin01.Content.Grower'), "Bin1Variety": comm.Read('Bin01.Content.Variety'), "Bin1StatedTn": round(comm.Read('Bin01.Content.Stated_Tn'), 2), "Bin1S": round(comm.Read('Bin01.Content.SG'), 3), "Bin1CalcV": round(comm.Read('Bin01.Content.Calc_Vol'), 2) } # 序列化JSON,自动处理格式合规性 msg_txt_formatted = json.dumps(telemetry_data) message = IoTHubMessage(msg_txt_formatted) client.send_event_async(message, send_confirmation_callback, None) time.sleep(1) except KeyboardInterrupt: print ( "IoTHubClient sample stopped" )
内容的提问来源于stack exchange,提问作者RedGhost
相关产品推荐
相关产品推荐

