/** * Holen und Schreiben der XDR-Telegramme vom/an Can-Bus * $Id$ * $HeadURL$ * $Author$ */ #include "connection_handler_tcp_ttci.h" #include #include #include #include #include using namespace NGL; namespace TrainingAreaBaseOC { ConnectionHandlerTcpTtci::ConnectionHandlerTcpTtci() : m_messageDataStart(true) , m_wirkfeldDataStart(true) , m_wirkfeldMultiplex(0) , m_sendingData(false) , m_segmentToggle(0) , m_canDevice(new Device(this)) , m_canChannel(new Channel(QLatin1Char('@'), true, this)) , m_logger(getLogger("TTCI")) { connect(m_canChannel, &Channel::dataAvailable, this, &ConnectionHandlerTcpTtci::slotReadCanFrame); connect(m_canChannel, &Channel::disconnectedFromEq, this, &ConnectionHandlerTcpTtci::disconnectedFromEq); } ConnectionHandlerTcpTtci::~ConnectionHandlerTcpTtci() { delete m_canChannel; delete m_canDevice; qDeleteAll(m_sfmMessages); } bool ConnectionHandlerTcpTtci::init() { initCanSocket(); return true; } void ConnectionHandlerTcpTtci::initCanSocket() { ERROR_LOG(m_logger) << "InitCantSOcket"; m_canChannel->setDevice(m_canDevice); m_canDevice->open(); } bool ConnectionHandlerTcpTtci::findNextSyncByte(int &iCurReadPos) const { if (iCurReadPos == m_buffer.size()) { DEBUG_LOG(m_logger) << "No more data available"; return false; } DEBUG_LOG(m_logger) << "Searching for next sync byte, start at: " << iCurReadPos; NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Debug, m_buffer); while (iCurReadPos < m_buffer.size()) { static const unsigned char syncByte = 0xAA; const unsigned char curByte = m_buffer.at(iCurReadPos); if (curByte == syncByte) break; ++iCurReadPos; } // wir brauchen mind. 4 Bytes (Sync, Can Header1+2, CRC) if (m_buffer.size() < 4 + iCurReadPos) { DEBUG_LOG(m_logger) << "Could not find sync byte in stream"; return false; } return true; } void ConnectionHandlerTcpTtci::slotReadCanFrame(const QByteArray &data) { m_buffer += data; int iCurReadPos = 0; while (findNextSyncByte(iCurReadPos)) { DEBUG_LOG(m_logger) << "Found Sync byte at " << iCurReadPos; // die ersten 4 Bits sind die Datenlänge unsigned int len = (m_buffer.at(iCurReadPos + 1) & 0xF0) >> 4; DEBUG_LOG(m_logger) << "Payload size: " << len; if (len > 8) { // spezielle Daten switch (len) { case 9: // Status-Informationen (3.3.1.2) DEBUG_LOG(m_logger) << "Read status data - skipping "; iCurReadPos += 4; break; case 11: // Komm SFM - PAN (3.3.2) DEBUG_LOG(m_logger) << "Read communication SFM - PAN - skipping "; iCurReadPos += 5; break; case 12: // Parameterabfrage (3.3.1.3) DEBUG_LOG(m_logger) << "Read parameter request - skipping "; iCurReadPos += 5; break; default: // wahrscheinlich kein korrekter Sync WARNING_LOG(m_logger) << "Invalid payload size (" << len << " - skipping"; ++iCurReadPos; break; } continue; } // 1 Byte sync // 2 Byte header // len Byte nutzdaten // 1 Byte crc int neededBytes = 4 + len + iCurReadPos; if (m_buffer.size() < neededBytes) { INFO_LOG(m_logger) << "To few bytes in buffer - waiting for more (want: " << neededBytes << " have: " << m_buffer.size() << ")"; // zu wenig Daten -> warten break; } unsigned int id = (m_buffer.at(iCurReadPos + 1) & 0x07); unsigned char id2 = m_buffer.at(iCurReadPos + 2); id = ((id << 8) + id2); bool rtr = ((m_buffer.at(iCurReadPos + 1) & 0x08) == 0x08); DEBUG_LOG(m_logger) << "CAN ID: " << id << " rtr: " << rtr; // calc crc (über alles bis zur CRC) unsigned char crc = 0; for (unsigned int i = 0; i < len + 3; ++i) crc += m_buffer.at(iCurReadPos + i); crc = ~crc; unsigned char crcSent = m_buffer.at(iCurReadPos + len + 3); if (crc != crcSent) { // CRC passt nicht - ggf. kein korrekter Sync WARNING_LOG(m_logger) << "CRC checksum missmatch (is: " << crcSent << " - calculated: " << crc << ") - skipping"; iCurReadPos++; continue; } QByteArray data2(m_buffer.data() + iCurReadPos + 3, len); //LtsUtils::SfmMessage msg; LtsUtils::SfmMessage msg; msg.setId(id); msg.setPayload(data2); msg.setRtr(rtr); emit received(msg); // und weiter zum nächsten Paket iCurReadPos += 4 + len; } m_buffer = m_buffer.mid(iCurReadPos); } bool ConnectionHandlerTcpTtci::isOpen() { return m_canDevice->isOpen(); } bool ConnectionHandlerTcpTtci::send(const LtsUtils::SfmMessage &message) { if (message.payload().size() > 8) return false; INFO_LOG(m_logger) << "start write"; NGL::NGLLoggerHelper::hexDumpHelper(m_logger, NGL::LogLevel::Debug, message.payload()); QByteArray data(message.payload().size() + 4, Qt::Uninitialized); data[0] = 0xAA; data[1] = (message.payload().size() << 4) | ((message.rtr() & 0x1) << 3) | ((message.id() & 0x700) >> 8); data[2] = (message.id() & 0xFF); for (int i = 0; i < message.payload().size(); ++i) data[i + 3] = message.payload().at(i); unsigned char crc = 0; for (int i = 0; i < data.size() - 1; ++i) crc += data.at(i); crc = ~crc; data[message.payload().size() + 3] = crc; INFO_LOG(m_logger) << "end write "; if (!m_canChannel->writeData(data)) ERROR_LOG(m_logger) << "Error writing data to can channel"; return true; } } // namespace TrainingAreaBaseOC