C
Event Sender: Sending Messages to Applications
// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial // This file is part of the Qt Safe Renderer module #include <QHostAddress> #include <QSettings> #include <QTimer> #include <QProcess> #include <QNetworkInterface> #include "tcpdatacontrol.h" #include <QtSafeRenderer/qsafestring.h> TCPDataControl::TCPDataControl(QObject *parent) : DataControlInterface(parent) { const QString items[] = { "turnleft", "turnright", "iconCoolant", "iconFuel", "iconParkingBrake", "iconTyre", "iconBattery", "iconSeatbelt", "iconLamp", "iconLowBeam" }; for (const QString& item : items) { m_stringList.append(item); } // Connect the stateChanged signal of sockets to the ConnectionStateChanged slots connect(&m_telltalesSocket, &QAbstractSocket::stateChanged, this, &TCPDataControl::onTelltalesConnectionStateChanged); connect(&m_tcpSocket, &QAbstractSocket::stateChanged, this, &TCPDataControl::onClusterConnectionStateChanged); } bool TCPDataControl::checkConnection(const QString &ip, int port) { QTcpSocket testSocket; testSocket.connectToHost(ip, port); if (testSocket.waitForConnected(3000)) { testSocket.disconnectFromHost(); return true; } return false; } TCPDataControl::~TCPDataControl() { m_tcpSocket.close(); m_telltalesSocket.close(); } void TCPDataControl::establishConnection(const QStringList &ips, int port) { // Get environment variables for IP and port QString envIp = QString::fromLocal8Bit(qgetenv("QT_SAFERENDER_HOST")); int envPort = QString::fromLocal8Bit(qgetenv("QT_SAFERENDER_PORT")).toInt(); // Use the environment port if set, otherwise use the provided port int finalPort = (envPort == 0) ? port : envPort; // Check if the port is valid before entering the loop if (finalPort != TELLTALES_HOST_PORT && finalPort != TELLTALES_TARGET_PORT && finalPort != CLUSTER_PORT) { qInfo() << "Invalid port. Use one of the following:"; qInfo() << "Telltales on host environment:" << TELLTALES_HOST_PORT; qInfo() << "Telltales on target device:" << TELLTALES_TARGET_PORT; qInfo() << "Qt Cluster:" << CLUSTER_PORT; return; } // Iterate over the list of IP addresses for (const auto &ip : ips) { // Use the environment IP if set, otherwise use the current IP from the list QString finalIp = envIp.isEmpty() ? ip : envIp; // Check if the port is for Telltales if (finalPort == TELLTALES_HOST_PORT || finalPort == TELLTALES_TARGET_PORT) { m_telltalesService = "Telltales"; // Check if the IP is for a host environment if (isHostEnvironment(finalIp)) { finalPort = TELLTALES_HOST_PORT; } else { finalPort = TELLTALES_TARGET_PORT; } // Check if already connected if (m_telltalesSocket.state() == QAbstractSocket::ConnectedState) { qInfo() << "Already connected to" << finalIp << ":" << finalPort; break; } // Attempt to establish a connection if (!checkConnection(finalIp, finalPort)) { qWarning() << "Failed to connect to" << finalIp << ":" << finalPort; continue; } else { qInfo() << "Connected to" << finalIp << ":" << finalPort; } m_telltalesSocket.connectToHost(finalIp, finalPort); emit telltalesRunningServiceChanged(m_telltalesService); } else if (finalPort == CLUSTER_PORT) { m_clusterService = "Cluster"; // Check if already connected if (m_tcpSocket.state() == QAbstractSocket::ConnectedState) { qInfo() << "Already connected to" << finalIp << ":" << finalPort; break; } // Attempt to establish a connection if (!checkConnection(finalIp, finalPort)) { qWarning() << "Failed to connect to" << finalIp << ":" << finalPort; continue; } else { qInfo() << "Connected to" << finalIp << ":" << finalPort; } m_tcpSocket.connectToHost(finalIp, finalPort); emit clusterRunningServiceChanged(m_clusterService); } } } void TCPDataControl::onTelltalesConnectionStateChanged(QAbstractSocket::SocketState socketState) { ConnectionState connectionState = Disconnected; if (socketState == QAbstractSocket::UnconnectedState) { connectionState = Disconnected; setConnectionBool(false); } else if (socketState == QAbstractSocket::ConnectedState) { connectionState = Connected; setConnectionBool(true); } else if (socketState == QAbstractSocket::ConnectingState) { connectionState = Connecting; } emit telltalesConnectionStateChanged(connectionState); } void TCPDataControl::onClusterConnectionStateChanged(QAbstractSocket::SocketState socketState) { ConnectionState connectionState = Disconnected; if (socketState == QAbstractSocket::UnconnectedState) { connectionState = Disconnected; } else if (socketState == QAbstractSocket::ConnectedState) { connectionState = Connected; setConnectionBool(true); } else if (socketState == QAbstractSocket::ConnectingState) { connectionState = Connecting; } emit clusterConnectionStateChanged(connectionState); } bool TCPDataControl::isHostEnvironment(const QString &ip) const { // Check if the IP is explicitly 127.0.0.1 or localhost if (ip == "127.0.0.1" || ip == "localhost") { return true; } const QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces(); // Iterate through each network interface and check if the // given IP matches any of the interface's IP addresses for (const QNetworkInterface &interface : interfaces) { const QList<QNetworkAddressEntry> entries = interface.addressEntries(); for (const QNetworkAddressEntry &entry : entries) { if (entry.ip().toString() == ip) { return true; } } } // Return false if no match was found return false; } TCPDataControl::ConnectionState TCPDataControl::mapSocketState(QAbstractSocket::SocketState socketState) { switch (socketState) { case QAbstractSocket::UnconnectedState: // If the socket is not connected, return 'Disconnected' return TCPDataControl::Disconnected; case QAbstractSocket::HostLookupState: case QAbstractSocket::ConnectingState: // If the socket is looking up the host or connecting, return 'Connecting' return TCPDataControl::Connecting; case QAbstractSocket::ConnectedState: // If the socket is connected, return 'Connected' return TCPDataControl::Connected; default: // As default, return 'Disconnected' return TCPDataControl::Disconnected; } } TCPDataControl::ConnectionState TCPDataControl::telltalesConnectionState() const { return mapSocketState(m_telltalesSocket.state()); } TCPDataControl::ConnectionState TCPDataControl::clusterConnectionState() const { return mapSocketState(m_tcpSocket.state()); } void TCPDataControl::setAddress(const QString &ip, int port) { if (ip.isEmpty()) { return; } if (ip != m_address) { m_address = ip; } if (port != m_port) { m_port = port; } } void TCPDataControl::handleTcpError(QAbstractSocket::SocketError socketError) { Q_UNUSED(socketError); qWarning() << "TCP Error:" << m_tcpSocket.errorString(); } int TCPDataControl::carId() const { return m_carId; } bool TCPDataControl::headLight() const { return m_headLight; } bool TCPDataControl::parkLight() const { return m_parkLight; } bool TCPDataControl::rightTurnLight() const { return m_rightTurnLight; } bool TCPDataControl::leftTurnLight() const { return m_leftTurnLight; } int TCPDataControl::gear() const { return m_gear; } bool TCPDataControl::lightFailure() const { return m_lightFailure; } bool TCPDataControl::frontLeftDoorOpen() const { return m_frontLeftDoorOpen; } bool TCPDataControl::frontRightDoorOpen() const { return m_frontRightDoorOpen; } bool TCPDataControl::rearLeftDoorOpen() const { return m_rearLeftDoorOpen; } bool TCPDataControl::rearRightDoorOpen() const { return m_rearRightDoorOpen; } bool TCPDataControl::hoodOpen() const { return m_hoodOpen; } bool TCPDataControl::trunkOpen() const { return m_trunkOpen; } bool TCPDataControl::flatTire() const { return m_flatTire; } double TCPDataControl::direction() const { return m_direction; } double TCPDataControl::longitude() const { return m_longitude; } double TCPDataControl::latitude() const { return m_latitude; } double TCPDataControl::vehicleSpeed() const { return m_vehicleSpeed; } bool TCPDataControl::hazardSignal() const { return m_hazardSignal; } bool TCPDataControl::brake() const { return m_brake; } double TCPDataControl::oilTemp() const { return m_oilTemp; } int TCPDataControl::oilPressure() const { return m_oilPressure; } double TCPDataControl::batteryPotential() const { return m_batteryPotential; } double TCPDataControl::gasLevel() const { return m_gasLevel; } int TCPDataControl::rpm() const { return m_rpm; } int TCPDataControl::engineTemp() const { return m_engineTemp; } bool TCPDataControl::crashArg() const { return m_crash; } bool TCPDataControl::connectionBool() const { return m_connection; } void TCPDataControl::setVehicleSpeed(double vehicleSpeed) { if (m_vehicleSpeed == vehicleSpeed) { return; } QString msg("vehicleSpeed:" + QString::number(vehicleSpeed) + " "); write(msg.toLatin1()); m_vehicleSpeed = vehicleSpeed; emit vehicleSpeedChanged(vehicleSpeed); } void TCPDataControl::setLatitude(double latitude) { if (m_latitude == latitude) { return; } QString msg("latitude:" + QString::number(latitude) + " "); write(msg.toLatin1(), msg.length()); m_latitude = latitude; emit latitudeChanged(latitude); } void TCPDataControl::setLongitude(double longitude) { if (m_longitude == longitude) { return; } QString msg("longitude:" + QString::number(longitude) + " "); write(msg.toLatin1()); m_longitude = longitude; emit longitudeChanged(longitude); } void TCPDataControl::setDirection(double direction) { if (m_direction == direction) { return; } QString msg("direction:" + QString::number(direction) + " "); write(msg.toLatin1()); m_direction = direction; emit directionChanged(direction); } void TCPDataControl::setFlatTire(bool flatTire) { if (m_flatTire == flatTire) { return; } QString msg("flatTire:" + QString::number(flatTire) + " "); write(msg.toLatin1()); m_flatTire = flatTire; emit flatTireChanged(flatTire); } void TCPDataControl::setFrontLeftDoorOpen(bool doorOpen) { if (m_frontLeftDoorOpen == doorOpen) { return; } QString msg("frontLeftDoorOpen:" + QString::number(doorOpen) + " "); write(msg.toLatin1()); m_frontLeftDoorOpen = doorOpen; emit frontLeftDoorOpenChanged(doorOpen); } void TCPDataControl::setFrontRightDoorOpen(bool doorOpen) { if (m_frontRightDoorOpen == doorOpen) { return; } QString msg("frontRightDoorOpen:" + QString::number(doorOpen) + " "); write(msg.toLatin1()); m_frontRightDoorOpen = doorOpen; emit frontRightDoorOpenChanged(doorOpen); } void TCPDataControl::setRearLeftDoorOpen(bool doorOpen) { if (m_rearLeftDoorOpen == doorOpen) { return; } QString msg("rearLeftDoorOpen:" + QString::number(doorOpen) + " "); write(msg.toLatin1()); m_rearLeftDoorOpen = doorOpen; emit rearLeftDoorOpenChanged(doorOpen); } void TCPDataControl::setHoodOpen(bool doorOpen) { if (m_hoodOpen == doorOpen) { return; } QString msg("hoodOpen:" + QString::number(doorOpen) + " "); write(msg.toLatin1()); m_hoodOpen = doorOpen; emit hoodOpenChanged(doorOpen); } void TCPDataControl::setTrunkOpen(bool doorOpen) { if (m_trunkOpen == doorOpen) { return; } QString msg("trunkOpen:" + QString::number(doorOpen) + " "); write(msg.toLatin1()); m_trunkOpen = doorOpen; emit rearRightDoorOpenChanged(doorOpen); } void TCPDataControl::setRearRightDoorOpen(bool doorOpen) { if (m_rearRightDoorOpen == doorOpen) { return; } QString msg("rearRightDoorOpen:" + QString::number(doorOpen) + " "); write(msg.toLatin1()); m_rearRightDoorOpen = doorOpen; emit rearRightDoorOpenChanged(doorOpen); } void TCPDataControl::setLightFailure(bool lightFailure) { if (m_lightFailure == lightFailure) { return; } QString msg("lightFailure:" + QString::number(lightFailure) + " "); write(msg.toLatin1()); m_lightFailure = lightFailure; emit lightFailureChanged(lightFailure); } void TCPDataControl::setGear(int gear) { if (m_gear == gear) { return; } QString msg("gear:" + QString::number(gear) + " "); write(msg.toLatin1()); m_gear = gear; emit gearChanged(gear); } void TCPDataControl::setLeftTurnLight(bool leftTurnLight) { if (m_leftTurnLight == leftTurnLight) { return; } QString msg("leftTurnLight:" + QString::number(leftTurnLight) + " "); write(msg.toLatin1()); m_leftTurnLight = leftTurnLight; emit leftTurnLightChanged(leftTurnLight); } void TCPDataControl::setRightTurnLight(bool rightTurnLight) { if (m_rightTurnLight == rightTurnLight) { return; } QString msg("rightTurnLight:" + QString::number(rightTurnLight) + " "); write(msg.toLatin1()); m_rightTurnLight = rightTurnLight; emit rightTurnLightChanged(rightTurnLight); } void TCPDataControl::setHeadLight(bool headLight) { if (m_headLight == headLight) { return; } QString msg("headLight:" + QString::number(headLight) + " "); write(msg.toLatin1()); m_headLight = headLight; emit headLightChanged(headLight); } void TCPDataControl::setParkLight(bool parkLight) { if (m_parkLight == parkLight) { return; } QString msg("parkLight:" + QString::number(parkLight) + " "); write(msg.toLatin1()); m_parkLight = parkLight; emit parkLightChanged(parkLight); } void TCPDataControl::setCarId(int carId) { if (m_carId == carId) { return; } QString msg("carId:" + QString::number(carId) + " "); write(msg.toLatin1()); m_carId = carId; emit carIdChanged(carId); } void TCPDataControl::setHazardSignal(bool hazardSignal) { if (m_hazardSignal == hazardSignal) { return; } QString msg("hazardSignal:" + QString::number(hazardSignal) + " "); write(msg.toLatin1()); m_hazardSignal = hazardSignal; emit hazardSignalChanged(hazardSignal); } void TCPDataControl::setBrake(bool brake) { if (m_brake == brake) { return; } QString msg("brake:" + QString::number(brake) + " "); write(msg.toLatin1()); m_brake = brake; emit brakeChanged(brake); } void TCPDataControl::setOilTemp(double oilTemp) { if (m_oilTemp == oilTemp) { return; } QString msg("oilTemp:" + QString::number(oilTemp) + " "); write(msg.toLatin1()); m_oilTemp = oilTemp; emit oilTempChanged(oilTemp); } void TCPDataControl::setOilPressure(int oilPressure) { if (m_oilPressure == oilPressure) { return; } QString msg("oilPressure:" + QString::number(oilPressure) + " "); write(msg.toLatin1()); m_oilPressure = oilPressure; emit oilPressureChanged(oilPressure); } void TCPDataControl::setBatteryPotential(double batteryPotential) { if (m_batteryPotential == batteryPotential) { return; } QString msg("batteryPotential:" + QString::number(batteryPotential) + " "); write(msg.toLatin1()); m_batteryPotential = batteryPotential; emit batteryPotentialChanged(batteryPotential); } void TCPDataControl::setGasLevel(double gasLevel) { if (m_gasLevel == gasLevel) { return; } QString msg("gasLevel:" + QString::number(gasLevel) + " "); write(msg.toLatin1()); m_gasLevel = gasLevel; emit gasLevelChanged(gasLevel); } void TCPDataControl::setRpm(int rpm) { if (m_rpm == rpm) { return; } QString msg("rpm:" + QString::number(rpm) + " "); write(msg.toLatin1()); m_rpm = rpm; emit rpmChanged(rpm); } void TCPDataControl::setEngineTemp(int engineTemp) { if (m_engineTemp == engineTemp) { return; } QString msg("engineTemp:" + QString::number(engineTemp) + " "); write(msg.toLatin1()); m_engineTemp = engineTemp; emit engineTempChanged(engineTemp); } void TCPDataControl::setCrash(bool crashArg) { if (m_crash == crashArg) { return; } QString msg("crash:" + QString::number(crashArg) + " "); write(msg.toLatin1()); m_crash = crashArg; emit crashChanged(crashArg); m_crash = false; } void TCPDataControl::write(const char *data, qint64 length) { if ((m_tcpSocket.state() == QTcpSocket::ConnectedState)) { m_tcpSocket.write(data, length); } } void TCPDataControl::write(const char *data) { if ((m_tcpSocket.state() == QTcpSocket::ConnectedState)) { m_tcpSocket.write(data); } } void TCPDataControl::setConnectionBool(bool b) { m_connection = b; emit myConnectionChanged(); } QVariantList TCPDataControl::getStringList() const { return m_stringList; } QString TCPDataControl::telltalesHostPort() const { return QString::number(TELLTALES_HOST_PORT); } QString TCPDataControl::clusterPort() const { return QString::number(CLUSTER_PORT); }