C
Qt Cluster: Rendering and Recovery from Main UI Failure
// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial // This file is part of the Qt Safe Renderer module #include "clusterdatabackend.h" #include "crasher.h" #include <QDebug> #include <QtGlobal> #include <QHostAddress> #include <QNetworkInterface> #ifdef QT_SERIALBUS_LIB // #define DEBUG_CAN #include <QtMath> #include <QCanBus> #define SOCKETCAN "socketcan" #define CANINTERFACE "can0" // J1939 PGNs #define PGN_65268 0xFEF4 // Tire Condition - TIRE #define PGN_64933 0xFDA5 // Door Control 2 - DC2 #define PGN_64972 0xFDCC // Light Control #define PGN_61445 0xF005 // Electronic Transmission Controller 2 - ETC2 #define PGN_65265 0xFEF1 // Cruise Control/Vehicle Speed - CCVS #define PGN_65267 0xFEF3 // vehicle position - VP #define PGN_65256 0xFEE8 // vehicle direction/speed #define PGN_65262 0xFEEE // Engine Temperature 1 - ET1 #define PGN_65263 0xFEEF // Engine Fluid Level/Pressure 1 - EFL/P1 #define PGN_65271 0xFEF7 // Vehicle Electrical Power - VEP #define PGN_65276 0xFEFC // Dash Display - DD #define PGN_61444 0xF004 // Electronic Engine Controller 1 - EEC1 #define PGN_60928 0xEE00 // Address Calimed - ACL #endif // door defines #define OPEN_DOOR_1 0x400000000000000 #define OPEN_DOOR_2 0x1000000000000 #define OPEN_DOOR_3 0x40000000000000 #define OPEN_DOOR_4 0x100000000000 #define OPEN_DOOR_5 0x400000000 #define OPEN_DOOR_6 0x1000000 // light defines #define HEAD_LIGHT 0x200000000000000 #define PARK_LIGHT 0x100000000000000 #define LIGHT_ERROR 0x400000000000000 #define LEFT_TURN_SIGNAL 0x10000000000000 #define RIGHT_TURN_SIGNAL 0x20000000000000 #define HAZARD_SIGNAL 0x4000000000000 #define LEFT_BLINK_ON 0x01 #define RIGHT_BLINK_ON 0x02 #define HAZARD_ON 0x4 // Current gear defines #define GEAR_PARK 0xFB #define GEAR_REVERSE 0x7C #define GEAR_NEUTRAL 0x7D // #define GEAR_1 0x7E // #define GEAR_2 0x7F // #define GEAR_3 0x80 // #define GEAR_4 0x81 // #define GEAR_5 0x82 // #define GEAR_6 0x83 ClusterDataBackend::ClusterDataBackend(QObject* parent) : QObject(parent), #ifdef QT_SERIALBUS_LIB m_canDevice(Q_NULLPTR), #endif m_vehicleSpeed(0.0), m_latitude(0.0), m_longitude(0.0), m_direction(0.0), m_flatTire(false), m_lightFailure(false), m_gear(1), m_signalLights(0x0), m_headLight(false), m_parkLight(false), m_carId(2), m_brake(false), m_engineTemp(60), m_oilTemp(0.0), m_oilPressure(0), m_batteryPotential(80.0), m_gasLevel(67.0), m_rpm(4000) { m_doorOpen.insert("frontLeft", false); m_doorOpen.insert("frontRight", false); m_doorOpen.insert("rearLeft", false); m_doorOpen.insert("rearRight", false); m_doorOpen.insert("trunk", false); m_doorOpen.insert("hood", false); #ifdef QT_SERIALBUS_LIB QCanBus* canBus(QCanBus::instance()); const auto plugins(canBus->plugins()); if (plugins.contains(SOCKETCAN)) { m_canDevice = canBus->createDevice(SOCKETCAN, CANINTERFACE); if (m_canDevice) { connect(m_canDevice, SIGNAL(errorOccurred(QCanBusDevice::CanBusError)), this, SLOT(canError(QCanBusDevice::CanBusError))); connect(m_canDevice, SIGNAL(framesReceived()), this, SLOT(canFramesReceived())); #ifdef DEBUG_CAN connect(m_canDevice, SIGNAL(stateChanged(QCanBusDevice::CanBusDeviceState)), this, SLOT(canStateChanged(QCanBusDevice::CanBusDeviceState))); qDebug() << "ClusterDataBackend::ClusterDataBackend - connectDevice:" << #endif // DEBUG_CAN m_canDevice->connectDevice(); } else { qWarning("Could not create QCanBus socketcan device 'can0'"); } } else { qWarning("Could not find QCanBus plugin 'socketcan'"); } #endif // QT_SERIALBUS_LIB } ClusterDataBackend::~ClusterDataBackend() { #ifdef QT_SERIALBUS_LIB if (m_canDevice) { m_canDevice->disconnectDevice(); } #endif if (m_tcpServerConnection) m_tcpServerConnection->close(); m_tcpServer.close(); } QStringList ClusterDataBackend::availableZones() const { return m_doorOpen.keys(); } QMap<QString, QVariantMap> ClusterDataBackend::zoneMap() const { return m_zonedFeatures; } void ClusterDataBackend::initializeAttributes() { emit vehicleSpeedChanged(m_vehicleSpeed); emit latitudeChanged(m_latitude); emit longitudeChanged(m_longitude); emit directionChanged(m_direction); emit flatTireChanged(m_flatTire); foreach (QString zone, m_doorOpen.keys()) { emit doorOpenChanged(m_doorOpen.value(zone), zone); } emit lightFailureChanged(m_lightFailure); emit reverseChanged(m_gear < 0); emit leftTurnLightChanged(m_signalLights & LEFT_BLINK_ON); emit rightTurnLightChanged(m_signalLights & RIGHT_BLINK_ON); emit headLightChanged(m_headLight); emit carIdChanged(m_carId); emit crashChanged(m_crash); QByteArray simu = qgetenv("QT_CLUSTER_SIMU"); QHostAddress simuAddr("127.0.0.1"); if (!simu.isEmpty()) { if (!simuAddr.setAddress(QString(simu))) { qWarning("Failed to set simulator address! Falling back to localhost"); } simuAddr.setAddress("127.0.0.1"); } else { foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost)) simuAddr.setAddress(address.toString()); } if (m_tcpServer.listen(QHostAddress::Any, 32124)) { connect(&m_tcpServer, SIGNAL(newConnection()), this, SLOT(acceptConnection())); qDebug() << "ClusterData server listening " << simuAddr << m_tcpServer.serverPort(); } else { qWarning() << m_tcpServer.errorString(); } } void ClusterDataBackend::acceptConnection() { m_tcpServerConnection = m_tcpServer.nextPendingConnection(); connect(m_tcpServerConnection, &QTcpSocket::readyRead, this, &ClusterDataBackend::updateServerProgress); } void ClusterDataBackend::updateServerProgress() { Crasher crasher; QString msg(m_tcpServerConnection->readAll()); foreach (QString msgAttr, msg.split(" ",Qt::SkipEmptyParts)) { QString attribute = msgAttr.section(':',0,0); QString value = msgAttr.section(':',1,1); if (attribute == "vehicleSpeed") { emit vehicleSpeedChanged(value.toDouble()); } else if (attribute == "latitude") { emit latitudeChanged(value.toDouble()); } else if (attribute == "longitude") { emit longitudeChanged(value.toDouble()); } else if (attribute == "direction") { emit directionChanged(value.toDouble()); } else if (attribute == "headLight") { emit headLightChanged((bool)value.toInt()); } else if (attribute == "lightFailure") { emit lightFailureChanged((bool)value.toInt()); } else if (attribute == "flatTire") { emit flatTireChanged((bool)value.toInt()); } else if (attribute == "reverse") { emit reverseChanged((bool)value.toInt()); } else if (attribute == "leftTurnLight") { emit leftTurnLightChanged((bool)value.toInt()); } else if (attribute == "rightTurnLight") { emit rightTurnLightChanged((bool)value.toInt()); } else if (attribute == "headLight") { emit headLightChanged((bool)value.toInt()); } else if (attribute == "parkLight") { emit parkLightChanged((bool)value.toInt()); } else if (attribute == "carId") { emit carIdChanged(value.toInt()); } else if (attribute == "frontLeftDoorOpen") { emit doorOpenChanged((bool)value.toInt(), "frontLeft"); } else if (attribute == "frontRightDoorOpen") { emit doorOpenChanged((bool)value.toInt(), "frontRight"); } else if (attribute == "rearLeftDoorOpen") { emit doorOpenChanged((bool)value.toInt(), "rearLeft"); } else if (attribute == "rearRightDoorOpen") { emit doorOpenChanged((bool)value.toInt(), "rearRight"); } else if (attribute == "hoodOpen") { emit doorOpenChanged((bool)value.toInt(), "hood"); } else if (attribute == "trunkOpen") { emit doorOpenChanged((bool)value.toInt(), "trunk"); } else if (attribute == "hazardSignal") { // TODO: Should replace this hack with actual hazardSignal emit leftTurnLightChanged((bool)value.toInt()); emit rightTurnLightChanged((bool)value.toInt()); } else if (attribute == "brake") { emit brakeChanged((bool)value.toInt()); } else if (attribute == "engineTemp") { emit engineTempChanged(value.toInt()); } else if (attribute == "oilTemp") { emit oilTempChanged(value.toDouble()); } else if (attribute == "oilPressure") { emit oilPressureChanged(value.toInt()); } else if (attribute == "batteryPotential") { emit batteryPotentialChanged(value.toDouble()); } else if (attribute == "gasLevel") { emit gasLevelChanged(value.toDouble()); } else if (attribute == "rpm") { emit rpmChanged(value.toInt()); } else if (attribute == "gear") { emit gearChanged(value.toInt()); } else if (attribute == "crash") { emit crashChanged((bool)value.toInt()); } else { qWarning() << "Unknown msg" << msg; } } } #ifdef QT_SERIALBUS_LIB // Tire Condition - TIRE void ClusterDataBackend::handlePGN65268(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { // char tireId(data.at(0)); // char pressure(data.at(1)); // quint16 temperatureData(data.at(2) << 8); // temperatureData |= data.at(3); // double tireTemperature((0.03125 * (double)temperatureData) - 273); m_flatTire = (data.at(4) & 0x30); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65268 - m_flatTire: %s", (m_flatTire ? "true" : "false")); #endif // DEBUG_CAN emit flatTireChanged(m_flatTire); } } // Door Control 2 - DC2 void ClusterDataBackend::handlePGN64933(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { quint64 doorData((quint64)data.at(0) << 56); doorData |= ((quint64)data.at(1) << 48); doorData |= ((quint64)data.at(2) << 40); doorData |= ((quint64)data.at(3) << 32); doorData |= ((quint64)data.at(4) << 24); doorData |= ((quint64)data.at(5) << 16); doorData |= ((quint64)data.at(6) << 8); doorData |= (quint64)data.at(7); bool frontLeft(doorData & OPEN_DOOR_1); bool frontRight(doorData & OPEN_DOOR_2); bool rearLeft(doorData & OPEN_DOOR_3); bool rearRight(doorData & OPEN_DOOR_4); bool trunk(doorData & OPEN_DOOR_5); bool hood(doorData & OPEN_DOOR_6); if (m_doorOpen.value("frontLeft") != frontLeft) { m_doorOpen.insert("frontLeft", frontLeft); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, frontLeft: %s", (frontLeft ? "true" : "false")); #endif // DEBUG_CAN emit doorOpenChanged(frontLeft, "frontLeft"); } if (m_doorOpen.value("frontRight") != frontRight) { m_doorOpen.insert("frontRight", frontRight); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, frontRight: %s", (frontRight ? "true" : "false")); #endif // DEBUG_CAN emit doorOpenChanged(frontRight, "frontRight"); } if (m_doorOpen.value("rearLeft") != rearLeft) { m_doorOpen.insert("rearLeft", rearLeft); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, rearLeft: %s", (rearLeft ? "true" : "false")); #endif // DEBUG_CAN emit doorOpenChanged(rearLeft, "rearLeft"); } if (m_doorOpen.value("rearRight") != rearRight) { m_doorOpen.insert("rearRight", rearRight); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, rearRight: %s", (rearRight ? "true" : "false")); #endif // DEBUG_CAN emit doorOpenChanged(rearRight, "rearRight"); } if (m_doorOpen.value("trunk") != trunk) { m_doorOpen.insert("trunk", trunk); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, trunk: %s", (trunk ? "true" : "false")); #endif // DEBUG_CAN emit doorOpenChanged(trunk, "trunk"); } if (m_doorOpen.value("hood") != hood) { m_doorOpen.insert("hood", hood); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64933 - doorOpenChanged, hood: %s", (hood ? "true" : "false")); #endif // DEBUG_CAN emit doorOpenChanged(hood, "hood"); } } } // Light Control void ClusterDataBackend::handlePGN64972(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { quint64 lightData((quint64)data.at(0) << 56); lightData |= ((quint64)data.at(1) << 48); lightData |= ((quint64)data.at(2) << 40); lightData |= ((quint64)data.at(3) << 32); lightData |= ((quint64)data.at(4) << 24); lightData |= ((quint64)data.at(5) << 16); lightData |= ((quint64)data.at(6) << 8); lightData |= data.at(7); if (m_headLight != (lightData & HEAD_LIGHT)) { m_headLight = (lightData & HEAD_LIGHT); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - m_headLight: %s", (m_headLight ? "true" : "false")); #endif // DEBUG_CAN emit headLightChanged(m_headLight); } if (m_parkLight != (lightData & PARK_LIGHT)) { m_parkLight = (lightData & PARK_LIGHT); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - m_parkLight: %s", (m_parkLight ? "true" : "false")); #endif // DEBUG_CAN emit parkLightChanged(m_parkLight); } if (m_lightFailure != (lightData & LIGHT_ERROR)) { m_lightFailure = (lightData & LIGHT_ERROR); #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - m_lightFailure: %s", (m_lightFailure ? "true" : "false")); #endif // DEBUG_CAN emit lightFailureChanged(m_lightFailure); } if ((bool)(m_signalLights & LEFT_BLINK_ON) != (bool)(lightData & LEFT_TURN_SIGNAL)) { if (lightData & LEFT_TURN_SIGNAL) { m_signalLights |= LEFT_BLINK_ON; } else { m_signalLights &= ~LEFT_BLINK_ON; } #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - leftTurnLight: %s", ((lightData & LEFT_TURN_SIGNAL) ? "true" : "false")); #endif // DEBUG_CAN emit leftTurnLightChanged(lightData & LEFT_TURN_SIGNAL); } if ((bool)(m_signalLights & RIGHT_BLINK_ON) != (bool)(lightData & RIGHT_TURN_SIGNAL)) { if (lightData & RIGHT_TURN_SIGNAL) { m_signalLights |= RIGHT_BLINK_ON; } else { m_signalLights &= ~RIGHT_BLINK_ON; } #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - rightTurnLight: %s", ((lightData & RIGHT_TURN_SIGNAL) ? "true" : "false")); #endif // DEBUG_CAN emit rightTurnLightChanged(lightData & RIGHT_TURN_SIGNAL); } if ((bool)(m_signalLights & HAZARD_ON) != (bool)(lightData & HAZARD_SIGNAL)) { if (lightData & HAZARD_SIGNAL) { m_signalLights |= HAZARD_ON; if (!(m_signalLights & LEFT_BLINK_ON)) { #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - hazard ON, leftTurnLight: true"); #endif // DEBUG_CAN emit leftTurnLightChanged(true); } if (!(m_signalLights & RIGHT_BLINK_ON)) { #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - hazard ON, rightTurnLight: true"); #endif // DEBUG_CAN emit rightTurnLightChanged(true); } } else { m_signalLights &= ~HAZARD_ON; if (!(m_signalLights & LEFT_BLINK_ON)) { #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - hazard OFF, leftTurnLight: false"); #endif // DEBUG_CAN emit leftTurnLightChanged(false); } if (!(m_signalLights & RIGHT_BLINK_ON)) { #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN64972 - hazard OFF, rightTurnLight: false"); #endif // DEBUG_CAN emit rightTurnLightChanged(false); } } } } } // Electronic Transmission Controller 2 - ETC2 void ClusterDataBackend::handlePGN61445(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { char gear(data.at(3)); if (gear == (char)GEAR_PARK) { m_gear = 0xff; } else if (m_gear == -1 && gear != (char)GEAR_REVERSE) { m_gear = (gear - GEAR_NEUTRAL); emit reverseChanged(false); } else if (m_gear != -1 && gear == (char)GEAR_REVERSE) { m_gear = -1; emit reverseChanged(true); } else { m_gear = (gear - GEAR_NEUTRAL); } #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN61445 - gear: %d", m_gear); #endif // DEBUG_CAN emit gearChanged(m_gear); } } // Cruise Control/Vehicle Speed - CCVS void ClusterDataBackend::handlePGN65265(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { qint16 speed((data.at(1) << 8)); speed |= data.at(2); double vehicleSpeed(0.00390625 * (double)speed); if (m_vehicleSpeed != vehicleSpeed) { m_vehicleSpeed = vehicleSpeed; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65265 - vehicle speed: %f", m_vehicleSpeed); #endif // DEBUG_CAN emit vehicleSpeedChanged(m_vehicleSpeed); } bool brakeOn(data.at(3) & 0x10); if (m_brake != brakeOn) { m_brake = brakeOn; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65265 - m_brake: %s", (m_brake ? "true" : "false")); #endif // DEBUG_CAN emit brakeChanged(m_brake); } } } // vehicle position - VP void ClusterDataBackend::handlePGN65267(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { quint32 lat((data.at(0) << 24)); lat |= ((data.at(1) << 16)); lat |= ((data.at(2) << 8)); lat |= data.at(3); quint32 lon(data.at(4) << 24); lon |= (data.at(5) << 16); lon |= (data.at(6) << 8); lon |= data.at(7); double latitude((((double)lat) * 1e-7) - 210); double longitude((((double)lon) * 1e-7) - 210); bool positionChanged(false); if (m_latitude != latitude) { m_latitude = latitude; positionChanged = true; } if (m_longitude != longitude) { m_longitude = longitude; positionChanged = true; } if (positionChanged) { #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN129025 - lat: %f, lon: %f", m_latitude, m_longitude); #endif // DEBUG_CAN emit latitudeChanged(m_latitude); emit longitudeChanged(m_longitude); } } } // vehicle direction/speed void ClusterDataBackend::handlePGN65256(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { quint16 directionData((data.at(0) << 8)); directionData |= data.at(1); double direction(0.0078125 * (double)directionData); // 1/128 deg/bit if (m_direction != direction) { m_direction = direction; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65256 - m_direction: %f", m_direction); #endif // DEBUG_CAN emit directionChanged(m_direction); } } } // Engine Temperature 1 - ET1 void ClusterDataBackend::handlePGN65262(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { qint8 engineTemp(data.at(0) - 40); if (m_engineTemp != engineTemp) { m_engineTemp = engineTemp; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65262 - m_engineTemp: %d", m_engineTemp); #endif // DEBUG_CAN emit engineTempChanged(m_engineTemp); } quint16 oilTempData(data.at(2) << 8); oilTempData |= data.at(3); double oilTemp(0.03125 * ((double)oilTempData) - 273.0); if (m_oilTemp != oilTemp) { m_oilTemp = oilTemp; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65262 - m_oilTemp: %f", m_oilTemp); #endif // DEBUG_CAN emit oilTempChanged(m_oilTemp); } } } // Engine Fluid Level/Pressure 1 - EFL/P1 void ClusterDataBackend::handlePGN65263(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { int oilPressure(4 * data.at(3)); if (m_oilPressure != oilPressure) { m_oilPressure = oilPressure; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65263 - m_oilPressure: %d", m_oilPressure); #endif // DEBUG_CAN emit oilPressureChanged(m_oilPressure); } } } // Vehicle Electrical Power - VEP void ClusterDataBackend::handlePGN65271(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { quint16 batteryPotentialData(data.at(6) << 8); batteryPotentialData |= data.at(7); double batteryPotential(0.05 * (double)batteryPotentialData); if (m_batteryPotential != batteryPotential) { m_batteryPotential = batteryPotential; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65271 - m_batteryPotential: %f", m_batteryPotential); #endif // DEBUG_CAN emit batteryPotentialChanged(m_batteryPotential); } } } // Dash Display - DD void ClusterDataBackend::handlePGN65276(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { double gasLevel(0.4 * (double)data.at(1)); if (m_gasLevel != gasLevel) { m_gasLevel = gasLevel; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN65276 - m_gasLevel: %f", m_gasLevel); #endif // DEBUG_CAN emit gasLevelChanged(m_gasLevel); } } } // Electronic Engine Controller 1 - EEC1 void ClusterDataBackend::handlePGN61444(const QCanBusFrame& frame) { QByteArray data(frame.payload()); if (data.size() == 8) { quint16 rpmData(data.at(3) << 8); rpmData |= data.at(4); int rpm(0.125 * (double)rpmData); if (m_rpm != rpm) { m_rpm = rpm; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN61444 - m_rpm: %d", m_rpm); #endif // DEBUG_CAN emit rpmChanged(m_rpm); } } } // Address Claimed - ACL void ClusterDataBackend::handlePGN60928(const QCanBusFrame &frame) { QByteArray data(frame.payload()); if (data.size() == 8) { // only 21 bits allowed (0x0 - 0x1FFFFF), pos 1.1 - 3.5 in message quint16 carIdData((data.at(0) & 0xff) << 13); carIdData |= ((data.at(1) & 0xff) << 5); carIdData |= ((data.at(2) & 0xf8) >> 3); if (m_carId != (int)carIdData) { m_carId = carIdData; #ifdef DEBUG_CAN qDebug("ClusterDataBackend::handlePGN60928 - carId: %d", m_carId); #endif // DEBUG_CAN emit carIdChanged(m_carId); } } } void ClusterDataBackend::canError(QCanBusDevice::CanBusError error) { if (m_canDevice) { qWarning("ClusterDataBackend::canError - code: %d, error: %s", (int)error, qPrintable(m_canDevice->errorString())); m_canDevice->disconnectDevice(); } } void ClusterDataBackend::canFramesReceived() { while (m_canDevice && m_canDevice->framesAvailable() > 0) { QCanBusFrame frame(m_canDevice->readFrame()); quint32 frameId(frame.frameId()); switch (frameId) { case PGN_65268 : handlePGN65268(frame); break; // Tire Condition - TIRE case PGN_64933 : handlePGN64933(frame); break; // Door Control 2 - DC2 case PGN_64972 : handlePGN64972(frame); break; // Light Control case PGN_61445 : handlePGN61445(frame); break; // Electronic Transmission Controller 2 - ETC2 case PGN_65265 : handlePGN65265(frame); break; // Cruise Control/Vehicle Speed - CCVS case PGN_65267 : handlePGN65267(frame); break; // vehicle position - VP case PGN_65256 : handlePGN65256(frame); break; // vehicle direction/speed case PGN_65262 : handlePGN65262(frame); break; // Engine Temperature 1 - ET1 case PGN_65263 : handlePGN65263(frame); break; // Engine Fluid Level/Pressure 1 - EFL/P1 case PGN_65271 : handlePGN65271(frame); break; // Vehicle Electrical Power - VEP case PGN_65276 : handlePGN65276(frame); break; // Dash Display - DD case PGN_61444 : handlePGN61444(frame); break; // Electronic Engine Controller 1 - EEC1 case PGN_60928 : handlePGN60928(frame); break; // Address Claimed - ACL default: qWarning("canFramesReceived - unknown frame id: %d", frameId); } #ifdef DEBUG_CAN QByteArray data(frame.payload()); const char* constData(data.constData()); int payLoadSize(data.size()); QString dataString; for (int i(0); i < payLoadSize; i++) { if (!dataString.isEmpty()) dataString.append("."); dataString.append(QString::fromLatin1("%1").arg((int)constData[i], 2, 16, QChar('0'))); } qDebug() << "ClusterDataBackend::canFramesReceived - id:" << frameId << "- data:" << dataString.toLatin1().constData(); #endif // DEBUG_CAN } } void ClusterDataBackend::canStateChanged(QCanBusDevice::CanBusDeviceState state) { #ifdef DEBUG_CAN qDebug() << "ClusterDataBackend::canStateChanged - state:" << state; #else Q_UNUSED(state) #endif // DEBUG_CAN } #endif