问题描述
我正在实施 MQTT 通信。我想通过图形界面(在 python 中实现)通过 MQTT 发送 CAN 帧。我能够从 GUI 向一个主题发送消息,并且当我使用该板时,我能够看到到达同一主题的消息(使用 paho 库)。函数在下面,主题是diagnostic_request/topic:
void onMessageArrived
(
const char* topic,const uint8_t* payload,size_t payloadLen,void* context
)
{
//LE_FATAL("The publisher received a message!");
//GIMP
char payloadStr[payloadLen + 1];
memcpy(payloadStr,payload,payloadLen);
payloadStr[payloadLen] = '\0';
LE_INFO("Received message! topic: \"%s\",payload: \"%s\"",topic,payloadStr);
//GIMP principio di conversione
if (strcmp(subscribetopic,topic)==0)
LE_INFO("Sei sul topic di richiesta diagnostica!");
can_send();
}
在这一点上我有困难。我的 can_send 函数(有效!)是:
int can_send(void)
{
const char* subscribetopic = "diagnostic_request/topic";
LE_FATAL_IF(
mqtt_Subscribe(MQTTSession,subscribetopic,MQTT_QOS0_TRANSMIT_ONCE) != LE_OK,"Failed to subscribe to %s",subscribetopic);
LE_INFO("Subscribed to topic (%s)",subscribetopic);
int nbytesWrite;
// USE SEND STANDARD FRAME
frameWrite.can_id = 0x750; //codice identificativo di una richiesta diagnostica per centralina simulata
frameWrite.can_id &= CAN_SFF_MASK;
frameWrite.can_dlc = 8;
//strcpy((char *)frameWrite.data,"MGATE");
frameWrite.data[0] = 0x03;
frameWrite.data[1] = 0x22;
frameWrite.data[2] = 0xF1;
frameWrite.data[3] = 0x89;
frameWrite.data[4] = 0x00;
frameWrite.data[5] = 0x00;
frameWrite.data[6] = 0x00;
frameWrite.data[7] = 0x00;
if ((nbytesWrite = write(sdw,&frameWrite,sizeof(frameWrite))) != sizeof(frameWrite))
{
canwrite = false;
LE_INFO ("Writing error,nbytesWrite = %d",nbytesWrite);
return SOCK_WRITING_ERROR;
}
canwrite = true;
return 0;
}
所以当 is 语句正常时,我必须在 onMessageArrived 函数中调用 can_send。我可以看到我何时发送关于诊断请求/主题的发布。唯一的问题是将payloadStr 值发送到can_send 函数并在frameWrite.data[] 中解包。 有人可以帮我了解如何修改 can_send 函数以使值
frameWrite.data[0] = 0x03;
frameWrite.data[1] = 0x22;
frameWrite.data[2] = 0xF1;
frameWrite.data[3] = 0x89;
frameWrite.data[4] = 0x00;
frameWrite.data[5] = 0x00;
frameWrite.data[6] = 0x00;
frameWrite.data[7] = 0x00;
是我在 payloadStr 中通过 mqtt 发送的值吗?我发送了一个 8 字节的字符串,但无法解包。 任何帮助将不胜感激 问候
解决方法
采取“先写测试”的方法......
int convertNybble (char const hex)
{
if (hex >= '0' && hex <= '9')
{
return hex - '0';
}
else if (hex >= 'a' && hex <= 'f')
{
return 10 + (hex - 'a');
}
else if (hex >= 'A' && hex <= 'F')
{
return 10 + (hex - 'A');
}
return -1; // invalid hex character
}
#define ERR_NOT_EVEN_NUMBER_OF_DIGITS -1
#define ERR_STRING_TOO_LONG -2
#define ERR_INVALID_CHAR -3
int preparePayload(char const* hexString,unsigned char* canBuffer,size_t const bufLen)
{
size_t hexLen = strlen(hexString);
if (0 != (hexLen % 2))
{
// Expect an even number of digits.
return ERR_NOT_EVEN_NUMBER_OF_DIGITS;
}
size_t payloadLen = hexLen / 2;
// buffer will contain payload-length,followed by payload data.
// so payloadLen+1 must be able to fit into bufLen - fail if payloadLen+1 > bufLen,which is the same as payloadLen >= bufLen
if (payloadLen >= bufLen)
{
// will not be able to fit the decoded string into the payload buffer
return ERR_STRING_TOO_LONG;
}
unsigned char* bufEnd = canBuffer;
bufEnd += bufLen;
*canBuffer++ = (unsigned char)payloadLen;
while (payloadLen > 0)
{
payloadLen--;
int hexDigit[2];
hexDigit[0] = convertNybble(*hexString++);
hexDigit[1] = convertNybble(*hexString++);
if ((hexDigit[0] < 0) || (hexDigit[1] < 0))
{
return ERR_INVALID_CHAR;
}
*canBuffer++ = (hexDigit[0] << 4) | hexDigit[1];
}
// fill any leftovers with zero
while (canBuffer < bufEnd)
{
*canBuffer++ = 0;
}
return (0);
}
int performTests()
{
char const* testStr[5] =
{
"12345","0123456789ABCDEF","@ABC","0AF9","0123456789ABCD"
};
#define MARKER 0xFF
#define PAYLOAD_LEN 8
unsigned char payload[PAYLOAD_LEN+1];
payload[PAYLOAD_LEN] = MARKER;
int decodeResult = preparePayload(testStr[0],payload,PAYLOAD_LEN);
if (ERR_NOT_EVEN_NUMBER_OF_DIGITS != decodeResult) { return -1; } //not expected result
decodeResult = preparePayload(testStr[1],PAYLOAD_LEN);
if (ERR_STRING_TOO_LONG != decodeResult) { return -1; }
decodeResult = preparePayload(testStr[2],PAYLOAD_LEN);
if (ERR_INVALID_CHAR != decodeResult) { return -1; }
// here we are checking the character decoding
decodeResult = preparePayload(testStr[3],PAYLOAD_LEN);
if (0 != decodeResult) { return -1; }
if (payload[0] != 2) { return -1; }
if (payload[1] != 0x0A) { return -1; }
if (payload[2] != 0xF9) { return -1; }
if (payload[3] != 0) { return -1; }
if (payload[7] != 0) { return -1; }
// payload contains - 02 0a f9 00 00 00 00 00 00
// here we are checking the limit of the payload capacity
decodeResult = preparePayload(testStr[4],PAYLOAD_LEN);
if (0 != decodeResult) { return -1; }
// payload contains - 07 01 23 45 67 89 ab cd
// check we haven't overrun the buffer
if (payload[8] != MARKER) { return -1; }
// all tests pass
return 0;
}
int main()
{
int testResult = performTests();
return testResult;
}
然后您可以按如下方式实现解码器:
convertNybble,preparePayload etc as above....
int canbusSend(unsigned char const* canbusPayload)
{
//etc
// - copy payloadBytes to frameWrite.data....
//etc
}
void onMessageArrived
(
const char* topic,const uint8_t* mqttPayload,size_t payloadLen,void* context
)
{
#define CANBUS_PAYLOAD_BUFFER_LEN 8
unsigned char canbusPayload[CANBUS_PAYLOAD_BUFFER_LEN];
int decodeResult = preparePayload((char const*)mqttPayload,canbusPayload,CANBUS_PAYLOAD_BUFFER_LEN);
if (0 == decodeResult)
{
int canbusSendResult = canbusSend(canbusPayload);
// TODO : report error if failed
}
else
{
//TODO : report error
}
}