0

我正在实现 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 字节的字符串,但我无法解包它。 任何帮助将不胜感激

4

1 回答 1

0

采取“先写测试”的方式......

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, PAYLOAD_LEN);

    if (ERR_STRING_TOO_LONG != decodeResult) { return -1; }

    decodeResult = preparePayload(testStr[2], payload, PAYLOAD_LEN);

    if (ERR_INVALID_CHAR != decodeResult) { return -1; }

    // here we are checking the character decoding
    decodeResult = preparePayload(testStr[3], payload, 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, 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
    }
}
于 2021-06-04T10:31:33.593 回答