Processing data in byte form
This commit is contained in:
241
CommObd2Can.cpp
241
CommObd2Can.cpp
@@ -3,6 +3,8 @@
|
||||
#include "LiveData.h"
|
||||
#include <mcp_CAN.h>
|
||||
|
||||
//#include <string.h>
|
||||
|
||||
/**
|
||||
Connect CAN adapter
|
||||
*/
|
||||
@@ -28,6 +30,15 @@ void CommObd2Can::connectDevice() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (liveData->settings.carType == CAR_BMW_I3_2014) {
|
||||
//initialise mask and filter to allow only receipt of 0x7xx CAN IDs
|
||||
CAN->init_Mask(0, 0, 0x07000000); // Init first mask...
|
||||
CAN->init_Mask(1, 0, 0x07000000); // Init second mask...
|
||||
for (uint8_t i = 0; i < 6; ++i) {
|
||||
CAN->init_Filt(i, 0, 0x06000000); //Init filters
|
||||
}
|
||||
}
|
||||
|
||||
if (MCP2515_OK != CAN->setMode(MCP_NORMAL)) { // Set operation mode to normal so the MCP2515 sends acks to received data.
|
||||
Serial.println("Error: CAN->setMode(MCP_NORMAL) failed");
|
||||
board->displayMessage(" > CAN init failed", "");
|
||||
@@ -126,13 +137,38 @@ void CommObd2Can::sendPID(const uint16_t pid, const String& cmd) {
|
||||
uint8_t txBuf[8] = { 0 }; // init with zeroes
|
||||
String tmpStr;
|
||||
|
||||
txBuf[0] = cmd.length() / 2;
|
||||
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
tmpStr = cmd;
|
||||
tmpStr = tmpStr.substring(i * 2, ((i + 1) * 2));
|
||||
if (tmpStr != "") {
|
||||
txBuf[i + 1] = liveData->hexToDec(tmpStr, 1, false);
|
||||
if (liveData->settings.carType == CAR_BMW_I3_2014)
|
||||
{
|
||||
struct Packet_t
|
||||
{
|
||||
uint8_t startChar;
|
||||
uint8_t length;
|
||||
uint8_t data[6];
|
||||
};
|
||||
|
||||
Packet_t* pPacket = (Packet_t*)txBuf;
|
||||
|
||||
pPacket->startChar = 0x07;
|
||||
pPacket->length = cmd.length() / 2;
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(pPacket->data); i++) {
|
||||
tmpStr = cmd;
|
||||
tmpStr = tmpStr.substring(i * 2, ((i + 1) * 2));
|
||||
if (tmpStr != "") {
|
||||
pPacket->data[i] = liveData->hexToDec(tmpStr, 1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
txBuf[0] = cmd.length() / 2;
|
||||
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
tmpStr = cmd;
|
||||
tmpStr = tmpStr.substring(i * 2, ((i + 1) * 2));
|
||||
if (tmpStr != "") {
|
||||
txBuf[i + 1] = liveData->hexToDec(tmpStr, 1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +195,13 @@ void CommObd2Can::sendPID(const uint16_t pid, const String& cmd) {
|
||||
void CommObd2Can::sendFlowControlFrame() {
|
||||
|
||||
uint8_t txBuf[8] = { 0x30, requestFramesCount /*request count*/, 14 /*ms between frames*/ , 0, 0, 0, 0, 0 };
|
||||
|
||||
// insert 0x07 into beginning for BMW i3
|
||||
if (liveData->settings.carType == CAR_BMW_I3_2014) {
|
||||
memmove(txBuf + 1, txBuf, 7);
|
||||
txBuf[0] = 0x07;
|
||||
}
|
||||
|
||||
const uint8_t sndStat = CAN->sendMsgBuf(lastPid, 0, 8, txBuf); // 11 bit
|
||||
if (sndStat == CAN_OK) {
|
||||
Serial.print("Flow control frame sent ");
|
||||
@@ -173,17 +216,46 @@ void CommObd2Can::sendFlowControlFrame() {
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
//static void mockupReceiveCanBuf(INT32U *id, INT8U *len, INT8U buf[])
|
||||
//{
|
||||
// static uint8_t counter = 0;
|
||||
//
|
||||
// std::unordered_map<uint8_t, std::vector<uint8_t>> packets = {
|
||||
// { 0, { 0xF1, 0x05, 0x62, 0xDD, 0xB4, 0x92, 0xC2 } },
|
||||
// { 1, { 0xF1, 0x10, 34, 0xDD, 0xB4, 0x92, 0xC2 } },
|
||||
// { 2, { 0xF1, 0x21, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4 } },
|
||||
// { 3, { 0xF1, 0x22, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4 } },
|
||||
// { 4, { 0xF1, 0x23, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4 } },
|
||||
// { 5, { 0xF1, 0x24, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4 } },
|
||||
// { 6, { 0xF1, 0x25, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4 } },
|
||||
// { 7, { 0xF1, 0x26, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4 } }
|
||||
// };
|
||||
//
|
||||
// if (counter >= packets.size())
|
||||
// counter = 0;
|
||||
//
|
||||
// *id = 0x607;
|
||||
// *len = packets[counter].size();
|
||||
// //memset(buf, 0, 7);
|
||||
//
|
||||
//
|
||||
// memcpy(buf, packets[counter].data(), 7);
|
||||
//
|
||||
// counter++;
|
||||
//}
|
||||
|
||||
/**
|
||||
Receive PID
|
||||
*/
|
||||
uint8_t CommObd2Can::receivePID() {
|
||||
|
||||
|
||||
if (!digitalRead(pinCanInt)) // If CAN0_INT pin is low, read receive buffer
|
||||
{
|
||||
lastDataSent = millis();
|
||||
Serial.print(" CAN READ ");
|
||||
CAN->readMsgBuf(&rxId, &rxLen, rxBuf); // Read data: len = data length, buf = data byte(s)
|
||||
|
||||
// mockupReceiveCanBuf(&rxId, &rxLen, rxBuf);
|
||||
|
||||
if ((rxId & 0x80000000) == 0x80000000) // Determine if ID is standard (11 bits) or extended (29 bits)
|
||||
sprintf(msgString, "Extended ID: 0x%.8lX DLC: %1d Data:", (rxId & 0x1FFFFFFF), rxLen);
|
||||
else
|
||||
@@ -201,14 +273,161 @@ uint8_t CommObd2Can::receivePID() {
|
||||
}
|
||||
}
|
||||
|
||||
if (rxLen == 5) {
|
||||
Serial.println(" [Ignoring 5 bytes long packet]");
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
processFrame();
|
||||
processFrameBytes();
|
||||
//processFrame();
|
||||
} else {
|
||||
//Serial.println(" CAN NOT READ ");
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
return rxBuf[0];
|
||||
return rxBuf[0 + liveData->rxBuffOffset];
|
||||
}
|
||||
|
||||
static void printHexBuffer(uint8_t* pData, const uint16_t length, const bool bAddNewLine)
|
||||
{
|
||||
char str[8] = { 0 };
|
||||
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
sprintf(str, " 0x%.2X", pData[i]);
|
||||
Serial.print(str);
|
||||
}
|
||||
|
||||
if (bAddNewLine) {
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
static void buffer2string(String& out_targetString, uint8_t* in_pBuffer, const uint16_t in_length)
|
||||
{
|
||||
char str[8] = { 0 };
|
||||
|
||||
for (uint16_t i = 0; i < in_length; i++) {
|
||||
sprintf(str, "%.2X", in_pBuffer[i]);
|
||||
out_targetString += str;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Process can frame on byte level
|
||||
*/
|
||||
bool CommObd2Can::processFrameBytes() {
|
||||
|
||||
uint8_t* pDataStart = rxBuf + liveData->rxBuffOffset; // set pointer to data start based on specific offset of car
|
||||
const uint8_t frameType = (*pDataStart & 0xf0) >> 4;
|
||||
const uint8_t frameLenght = rxLen - liveData->rxBuffOffset;
|
||||
|
||||
switch (frameType) {
|
||||
case 0: // Single frame
|
||||
{
|
||||
struct SingleFrame_t
|
||||
{
|
||||
uint8_t size : 4;
|
||||
uint8_t frameType : 4;
|
||||
uint8_t pData[];
|
||||
};
|
||||
|
||||
SingleFrame_t* pSingleFrame = (SingleFrame_t*)pDataStart;
|
||||
mergedData.assign(pSingleFrame->pData, pSingleFrame->pData + pSingleFrame->size);
|
||||
|
||||
rxRemaining = 0;
|
||||
|
||||
Serial.print("---Processing SingleFrame payload: "); printHexBuffer(pSingleFrame->pData, pSingleFrame->size, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // First frame
|
||||
{
|
||||
struct FirstFrame_t
|
||||
{
|
||||
uint8_t sizeMSB : 4;
|
||||
uint8_t frameType : 4;
|
||||
uint8_t sizeLSB : 8;
|
||||
uint8_t pData[];
|
||||
|
||||
uint16_t lengthOfFullPacket() { return (256 * sizeMSB) + sizeLSB; }
|
||||
|
||||
};
|
||||
|
||||
FirstFrame_t* pFirstFrame = (FirstFrame_t*)pDataStart;
|
||||
|
||||
rxRemaining = pFirstFrame->lengthOfFullPacket(); // length of complete data
|
||||
|
||||
mergedData.clear();
|
||||
dataRows.clear();
|
||||
|
||||
const uint8_t framePayloadSize = frameLenght - sizeof(FirstFrame_t); // remove one byte of header
|
||||
dataRows[0].assign(pFirstFrame->pData, pFirstFrame->pData + framePayloadSize);
|
||||
rxRemaining -= framePayloadSize;
|
||||
|
||||
Serial.print("---Processing FirstFrame payload: "); printHexBuffer(pFirstFrame->pData, framePayloadSize, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Consecutive frame
|
||||
{
|
||||
struct ConsecutiveFrame_t
|
||||
{
|
||||
uint8_t index : 4;
|
||||
uint8_t frameType : 4;
|
||||
uint8_t pData[];
|
||||
};
|
||||
|
||||
const uint8_t structSize = sizeof(ConsecutiveFrame_t);
|
||||
Serial.print("[debug] sizeof(ConsecutiveFrame_t) is expected to be 1 and it's "); Serial.println(structSize);
|
||||
|
||||
ConsecutiveFrame_t* pConseqFrame = (ConsecutiveFrame_t*)pDataStart;
|
||||
const uint8_t framePayloadSize = frameLenght - sizeof(ConsecutiveFrame_t); // remove one byte of header
|
||||
dataRows[pConseqFrame->index].assign(pConseqFrame->pData, pConseqFrame->pData + framePayloadSize);
|
||||
rxRemaining -= framePayloadSize;
|
||||
|
||||
Serial.print("---Processing ConsecFrame payload: "); printHexBuffer(pConseqFrame->pData, framePayloadSize, true);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Serial.print("Unknown frame type within CommObd2Can::processFrameBytes(): "); Serial.println(frameType);
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (frameType == 0)
|
||||
{
|
||||
// single frame - process directly
|
||||
buffer2string(liveData->responseRowMerged, mergedData.data(), mergedData.size());
|
||||
liveData->vResponseRowMerged.assign(mergedData.begin(), mergedData.end());
|
||||
processMergedResponse();
|
||||
}
|
||||
else if (rxRemaining <= 0)
|
||||
{
|
||||
// multiple frames and no data remaining - merge everything to single packet
|
||||
//for(const auto& row : dataRows)
|
||||
for (int i = 0; i < dataRows.size(); i++)
|
||||
{
|
||||
Serial.print("---merging packet index ");
|
||||
Serial.print(i);
|
||||
Serial.print(" with length ");
|
||||
Serial.println(dataRows[i].size());
|
||||
|
||||
mergedData.insert(mergedData.end(), dataRows[i].begin(), dataRows[i].end());
|
||||
|
||||
}
|
||||
|
||||
buffer2string(liveData->responseRowMerged, mergedData.data(), mergedData.size());
|
||||
liveData->vResponseRowMerged.assign(mergedData.begin(), mergedData.end());
|
||||
processMergedResponse();
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user