Azure IoT 中心设备孪生报告 属性 中的 8 字节数字自动转换为浮点数
8-byte number in reported property of Azure IoT hub device twin automatically converted to float
我想通过设备孪生向 IoT 中心报告 属性 报告的确切 8 字节数字。但是,在 Azure 门户中查看值时,我只看到科学格式的浮点数。
https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-device-twins 页面上的 Azure 文档说:JSON 对象中的所有值都可以是以下 JSON 类型:布尔值、数字、字符串、对象。
当我从 Azure 门户转换回数字时,例如python:
打印(格式(int(浮动(“7.26238597903829E + 16”),“016x”))
数字不正确,我猜是由于不精确的浮点数格式。
我在这里 https://www.w3schools.com/js/js_json_datatypes.asp 读到 JSON 数字可以是整数或浮点数。因此我认为 int 数字应该不是问题。
我的 C 代码中序列化程序的结构声明如下所示:
DECLARE_STRUCT(NodeType,
int64_t, addr,
uint8_t, status
);
是否可以从报告的设备孪生中检索准确的 64 位数字 属性?
编辑:为了重现问题,我在 IoT 中心创建了一个设备 ID 为 "car" 的新设备。我下载了当前的 azure-iot-c-sdk 并修改了序列化程序示例中的 devicetwin_simplesample。这是差异:
diff --git a/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c b/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c
index 7da717c..4f9e28d 100644
--- a/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c
+++ b/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c
@@ -14,7 +14,7 @@
/*String containing Hostname, Device Id & Device Key in the format: */
/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>" */
-static const char* connectionString = "HostName=...";
+static const char* connectionString = "HostName=XXX.azure-devices.net;DeviceId=car;SharedAccessKey=XXXX";
// Define the Model - it is a car.
BEGIN_NAMESPACE(Contoso);
@@ -31,7 +31,7 @@ DECLARE_STRUCT(Geo,
);
DECLARE_MODEL(CarState,
- WITH_REPORTED_PROPERTY(int32_t, softwareVersion),
+ WITH_REPORTED_PROPERTY(int64_t, softwareVersion),
WITH_REPORTED_PROPERTY(uint8_t, reported_maxSpeed),
WITH_REPORTED_PROPERTY(ascii_char_ptr, vanityPlate)
);
@@ -125,7 +125,7 @@ void device_twin_simple_sample_run(void)
car->maker.style = "sedan";
car->maker.year = 2014;
car->state.reported_maxSpeed = 100;
- car->state.softwareVersion = 1;
+ car->state.softwareVersion = 0x0102030405060708;
car->state.vanityPlate = "1I1";
/*sending the values to IoTHub*/
开始此示例后,我在我的 Azure 门户中的设备孪生(此处部分显示)中获得了软件版本号的浮点数:
{
"deviceId": "car",
"etag": "AAAAAAAAAAE=",
"properties": {
"desired": {
"$metadata": {
"$lastUpdated": "2017-08-14T14:03:24.5887488Z"
},
"$version": 1
},
"reported": {
"state": {
"softwareVersion": 72623859790382848.0,
"reported_maxSpeed": 100,
"vanityPlate": "1I1"
},
...
此问题是由 JSON 类型表示您的 int64 值引起的:数字和数字类型是 JavaScript 中的双精度浮点格式。
对于double- precision floating-point:
- 符号位:1位
- 指数:11位
- 有效位数精度:53 位(显式存储 52 位)
所以它可以表示的最大整数是2^52,十六进制是0xFFFFFFFFFFFFF,十进制是4503599627370495。
因为你的 softwareVersion
值扩展了它可以表示的范围所以它削减了冗余位,所以你得到了错误的值。
对于您的情况,您可以在发送方将 64 位值拆分为两个 32 位值,并在接收方将两个 32 位值重新组合为一个 64 位值。
我想通过设备孪生向 IoT 中心报告 属性 报告的确切 8 字节数字。但是,在 Azure 门户中查看值时,我只看到科学格式的浮点数。 https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-devguide-device-twins 页面上的 Azure 文档说:JSON 对象中的所有值都可以是以下 JSON 类型:布尔值、数字、字符串、对象。
当我从 Azure 门户转换回数字时,例如python: 打印(格式(int(浮动(“7.26238597903829E + 16”),“016x”)) 数字不正确,我猜是由于不精确的浮点数格式。
我在这里 https://www.w3schools.com/js/js_json_datatypes.asp 读到 JSON 数字可以是整数或浮点数。因此我认为 int 数字应该不是问题。
我的 C 代码中序列化程序的结构声明如下所示:
DECLARE_STRUCT(NodeType,
int64_t, addr,
uint8_t, status
);
是否可以从报告的设备孪生中检索准确的 64 位数字 属性?
编辑:为了重现问题,我在 IoT 中心创建了一个设备 ID 为 "car" 的新设备。我下载了当前的 azure-iot-c-sdk 并修改了序列化程序示例中的 devicetwin_simplesample。这是差异:
diff --git a/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c b/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c
index 7da717c..4f9e28d 100644
--- a/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c
+++ b/serializer/samples/devicetwin_simplesample/devicetwin_simplesample.c
@@ -14,7 +14,7 @@
/*String containing Hostname, Device Id & Device Key in the format: */
/* "HostName=<host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>" */
-static const char* connectionString = "HostName=...";
+static const char* connectionString = "HostName=XXX.azure-devices.net;DeviceId=car;SharedAccessKey=XXXX";
// Define the Model - it is a car.
BEGIN_NAMESPACE(Contoso);
@@ -31,7 +31,7 @@ DECLARE_STRUCT(Geo,
);
DECLARE_MODEL(CarState,
- WITH_REPORTED_PROPERTY(int32_t, softwareVersion),
+ WITH_REPORTED_PROPERTY(int64_t, softwareVersion),
WITH_REPORTED_PROPERTY(uint8_t, reported_maxSpeed),
WITH_REPORTED_PROPERTY(ascii_char_ptr, vanityPlate)
);
@@ -125,7 +125,7 @@ void device_twin_simple_sample_run(void)
car->maker.style = "sedan";
car->maker.year = 2014;
car->state.reported_maxSpeed = 100;
- car->state.softwareVersion = 1;
+ car->state.softwareVersion = 0x0102030405060708;
car->state.vanityPlate = "1I1";
/*sending the values to IoTHub*/
开始此示例后,我在我的 Azure 门户中的设备孪生(此处部分显示)中获得了软件版本号的浮点数:
{
"deviceId": "car",
"etag": "AAAAAAAAAAE=",
"properties": {
"desired": {
"$metadata": {
"$lastUpdated": "2017-08-14T14:03:24.5887488Z"
},
"$version": 1
},
"reported": {
"state": {
"softwareVersion": 72623859790382848.0,
"reported_maxSpeed": 100,
"vanityPlate": "1I1"
},
...
此问题是由 JSON 类型表示您的 int64 值引起的:数字和数字类型是 JavaScript 中的双精度浮点格式。
对于double- precision floating-point:
- 符号位:1位
- 指数:11位
- 有效位数精度:53 位(显式存储 52 位)
所以它可以表示的最大整数是2^52,十六进制是0xFFFFFFFFFFFFF,十进制是4503599627370495。
因为你的 softwareVersion
值扩展了它可以表示的范围所以它削减了冗余位,所以你得到了错误的值。
对于您的情况,您可以在发送方将 64 位值拆分为两个 32 位值,并在接收方将两个 32 位值重新组合为一个 64 位值。