我试图通过MQTT协议连续发送6个浮点数的数组。我使用sprintf函数将它们作为ASCII字符发送。我决定将它们作为原始字节发送。我将这些浮点数合并为一个联合,以将它们表示为未签名的char。问题是当这些浮点中的任何一个为整数值时,它们的字节表示形式在整数位置之后都为空。
union {
float array[6];
unsigned char bytes[6 * sizeof(float)];
} floatAsBytes;
如果所有floatAsBytes.array都包含浮点值,则完全没有问题。
如果我说floatAsBytes.array[0] = 0
,则floatAsBytes.bytes变为null。
如果我说floatAsBytes.array[3] = 4
,我可以看到前8个字节,但是这次最后16个字节为空。
我的客户端C代码的最小示例
#define QOS 0
#define TIMEOUT 1000L
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#include "MQTTClient.h"
union bitFloat{
float f[6];
unsigned char s[6*sizeof(float)];
};
void publish(MQTTClient client, char* topic, char* payload) {
MQTTClient_message pubmsg = MQTTClient_message_initializer;
pubmsg.payload = payload;
pubmsg.payloadlen = strlen(pubmsg.payload);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_deliveryToken token;
MQTTClient_publishMessage(client, topic, &pubmsg, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
}
int main(){
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
MQTTClient_create(&client, "MQTTADDRESS:MQTTPORT", "TestClient",
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}
int i;
while(1){
union bitFloat payload;
payload.f[0] = 4.53; payload.f[1] = 2.39; payload.f[2] = 28.96; payload.f[3] = -1.83; payload.f[4] = -27.0; payload.f[5] = 9.32;
publish(client, "MyTestTopic", payload.s);
sleep(1);
}
return 0;
}
用于接收消息并显示消息的Python脚本
# !/usr/bin/env python
import struct
import numpy as np
import paho.mqtt.client as mqtt
def on_message(client, userdata, message):
test1 = struct.unpack('<f', message.payload[0:4])[0]
test2 = struct.unpack('<f', message.payload[4:8])[0]
test3 = struct.unpack('<f', message.payload[8:12])[0]
test4 = struct.unpack('<f', message.payload[12:16])[0]
test5 = struct.unpack('<f', message.payload[16:20])[0]
test6 = struct.unpack('<f', message.payload[20:24])[0]
print(test1, test2, test3, test4, test5, test6)
client = mqtt.Client()
client.on_message = on_message
client.connect("MQTTADDRESS", MQTTPORT)
client.subscribe("MyTestTopic")
client.loop_forever()
答案 0 :(得分:1)
此行
pubmsg.payloadlen = strlen(pubmsg.payload);
是错误的。您在不是字符串的东西上使用strlen
。由于使用strlen
的长度是错误的,因为strlen
仅在看到字节为零之前才计数。
示例:
考虑payload.f[0] = 1;
。 1.0的二进制表示形式是3f800000
在小端系统上,该值将另存为00 00 80 3f,因此使用strlen
将得出0。
在大型字节序系统上,这将另存为3f 80 00 00,因此使用strlen
将得到2。
换句话说-strlen
是错误的函数。
您可能需要
pubmsg.payloadlen = 6 * sizeof(float);
答案 1 :(得分:0)
代码按预期工作。
这里是Minimal Complete Verifiable Example。我猜您正在为此做某事。当您提供自己的代码时,可能表明我误解了您的问题:
#include <stdio.h>
int main()
{
union {
float array[6];
unsigned char bytes[6 * sizeof(float)];
} floatAsBytes;
// load up array with some date
for(int i = 0; i < 6; i++) {
floatAsBytes.array[i] = 1.99 + i;
}
puts("\nfirst run:");
floatAsBytes.array[0] = 0;
// dump array
for(int i = 0; i< 6; i++) {
printf("float #%d: %f\n", i, floatAsBytes.array[i]);
}
// dump bytes
for(int i = 0; i < sizeof(float)*6; i++) {
if(i % sizeof(float) == 0)
printf("\n");
printf(" %2x",floatAsBytes.bytes[i]);
}
// second example
puts("\nSecond run:");
floatAsBytes.array[3] = 4;
// dump array
for(int i = 0; i< 6; i++) {
printf("float #%d: %f\n", i, floatAsBytes.array[i]);
}
// dump bytes
for(int i = 0; i < sizeof(float)*6; i++) {
if(i % sizeof(float) == 0)
printf("\n");
printf(" %2x",floatAsBytes.bytes[i]);
}
return 0;
}
以下是输出:
first run:
float #0: 0.000000
float #1: 2.990000
float #2: 3.990000
float #3: 4.990000
float #4: 5.990000
float #5: 6.990000
0 0 0 0
29 5c 3f 40
29 5c 7f 40
14 ae 9f 40
14 ae bf 40
14 ae df 40
Second run:
float #0: 0.000000
float #1: 2.990000
float #2: 3.990000
float #3: 4.000000
float #4: 5.990000
float #5: 6.990000
0 0 0 0
29 5c 3f 40
29 5c 7f 40
0 0 80 40
14 ae bf 40
14 ae df 40
Process finished with exit code 0
我没有看到您所描述的行为。该代码按预期工作。