23#include "moc_qgsiodevicesensor.cpp"
25#if defined( Q_OS_ANDROID ) || defined( Q_OS_LINUX )
26#include <sys/socket.h>
35 mIODevice.reset( device );
45 return mIODevice.get();
51 data.lastValue = mIODevice->readAll();
52 data.lastTimestamp = QDateTime::currentDateTime();
60 , mTcpSocket( new QTcpSocket() )
62 connect( mTcpSocket, &QAbstractSocket::stateChanged,
this, &QgsTcpSocketSensor::socketStateChanged );
63 connect( mTcpSocket, qOverload<QAbstractSocket::SocketError>( &QAbstractSocket::errorOccurred ),
this, &QgsTcpSocketSensor::handleError );
75 return QLatin1String(
"tcp_socket" );
106 if ( mHostName.isEmpty() || mPort == 0 )
112 mTcpSocket->connectToHost( mHostName, mPort, QTcpSocket::ReadOnly );
120void QgsTcpSocketSensor::handleError( QAbstractSocket::SocketError error )
124 case QAbstractSocket::HostNotFoundError:
127 case QAbstractSocket::NetworkError:
128 mErrorString = tr(
"Attempt to read or write from socket returned an error" );
130 case QAbstractSocket::ConnectionRefusedError:
131 mErrorString = tr(
"The connection was refused by the remote host" );
134 mErrorString = tr(
"%1" ).arg( QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey( error ) );
141void QgsTcpSocketSensor::socketStateChanged(
const QAbstractSocket::SocketState socketState )
143 switch ( socketState )
145 case QAbstractSocket::ConnectedState:
150 case QAbstractSocket::UnconnectedState:
162 element.setAttribute( QStringLiteral(
"hostName" ), mHostName );
163 element.setAttribute( QStringLiteral(
"port" ), QString::number( mPort ) );
170 mHostName = element.attribute( QStringLiteral(
"hostName" ) );
171 mPort = element.attribute( QStringLiteral(
"port" ) ).toInt();
180 , mUdpSocket( std::make_unique<QUdpSocket>() )
181 , mBuffer( new QBuffer() )
183#if defined( Q_OS_ANDROID ) || defined( Q_OS_LINUX )
184 int sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
186 setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
187 (
void * ) &optval,
sizeof( optval ) );
188 mUdpSocket->setSocketDescriptor( sockfd, QUdpSocket::UnconnectedState );
191 connect( mUdpSocket.get(), &QAbstractSocket::stateChanged,
this, &QgsUdpSocketSensor::socketStateChanged );
192 connect( mUdpSocket.get(), &QUdpSocket::readyRead,
this, [
this]()
195 while ( mUdpSocket->hasPendingDatagrams() )
197 datagram.resize( int( mUdpSocket->pendingDatagramSize() ) );
198 mUdpSocket->readDatagram( datagram.data(), datagram.size() );
200 mBuffer->buffer().clear();
202 mBuffer->write( datagram );
207 connect( mUdpSocket.get(), qOverload<QAbstractSocket::SocketError>( &QAbstractSocket::errorOccurred ),
this, &QgsUdpSocketSensor::handleError );
209 initIODevice( mBuffer );
219 return QLatin1String(
"udp_socket" );
250 if ( mHostName.isEmpty() || mPort == 0 )
256 mBuffer->open( QIODevice::ReadWrite );
257 mUdpSocket->bind( QHostAddress( mHostName ), mPort, QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint );
258 mUdpSocket->joinMulticastGroup( QHostAddress( mHostName ) );
267void QgsUdpSocketSensor::handleError( QAbstractSocket::SocketError error )
271 case QAbstractSocket::HostNotFoundError:
274 case QAbstractSocket::NetworkError:
275 mErrorString = tr(
"Attempt to read or write from socket returned an error" );
277 case QAbstractSocket::ConnectionRefusedError:
278 mErrorString = tr(
"The connection was refused by the remote host" );
281 mErrorString = tr(
"%1" ).arg( QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey( error ) );
288void QgsUdpSocketSensor::socketStateChanged(
const QAbstractSocket::SocketState socketState )
290 switch ( socketState )
292 case QAbstractSocket::ConnectedState:
293 case QAbstractSocket::BoundState:
298 case QAbstractSocket::UnconnectedState:
310 element.setAttribute( QStringLiteral(
"hostName" ), mHostName );
311 element.setAttribute( QStringLiteral(
"port" ), QString::number( mPort ) );
318 mHostName = element.attribute( QStringLiteral(
"hostName" ) );
319 mPort = element.attribute( QStringLiteral(
"port" ) ).toInt();
326#if defined( HAVE_QTSERIALPORT )
327QgsSerialPortSensor::QgsSerialPortSensor( QObject *parent )
329 , mSerialPort( new QSerialPort() )
331 connect( mSerialPort, qOverload<QSerialPort::SerialPortError>( &QSerialPort::errorOccurred ),
this, &QgsSerialPortSensor::handleError );
336QgsSerialPortSensor *QgsSerialPortSensor::create( QObject *parent )
338 return new QgsSerialPortSensor( parent );
341QString QgsSerialPortSensor::type()
const
343 return QLatin1String(
"serial_port" );
346QString QgsSerialPortSensor::portName()
const
351void QgsSerialPortSensor::setPortName(
const QString &portName )
353 if ( mPortName == portName )
356 mPortName = portName;
359QSerialPort::BaudRate QgsSerialPortSensor::baudRate()
const
364void QgsSerialPortSensor::setBaudRate(
const QSerialPort::BaudRate &baudRate )
366 if ( mBaudRate == baudRate )
369 mBaudRate = baudRate;
372QByteArray QgsSerialPortSensor::delimiter()
const
377void QgsSerialPortSensor::setDelimiter(
const QByteArray &delimiter )
379 if ( mDelimiter == delimiter )
382 mDelimiter = delimiter;
386void QgsSerialPortSensor::parseData()
388 if ( !mDelimiter.isEmpty() )
390 if ( mFirstDelimiterHit )
392 mDataBuffer += mSerialPort->readAll();
393 const auto lastIndex = mDataBuffer.lastIndexOf( mDelimiter );
394 if ( lastIndex > -1 )
397 data.
lastValue = mDataBuffer.mid( 0, lastIndex );
398 mDataBuffer = mDataBuffer.mid( lastIndex + mDelimiter.size() );
405 QByteArray data = mSerialPort->readAll();
406 const auto lastIndex = data.lastIndexOf( mDelimiter );
407 if ( lastIndex > -1 )
409 mFirstDelimiterHit =
true;
410 mDataBuffer = data.mid( lastIndex + mDelimiter.size() );
423void QgsSerialPortSensor::handleConnect()
425 mSerialPort->setPortName( mPortName );
426 mSerialPort->setBaudRate( mBaudRate );
427 mFirstDelimiterHit =
false;
429 if ( mSerialPort->open( QIODevice::ReadOnly ) )
439void QgsSerialPortSensor::handleDisconnect()
441 mSerialPort->close();
444void QgsSerialPortSensor::handleError( QSerialPort::SerialPortError error )
446 if ( error == QSerialPort::NoError )
453 case QSerialPort::DeviceNotFoundError:
454 mErrorString = tr(
"Could not find the serial port device" );
456 case QSerialPort::ReadError:
457 mErrorString = tr(
"Attempt to read from the serial port returned an error" );
459 case QSerialPort::PermissionError:
460 mErrorString = tr(
"The connection was refused due to not having enough permission" );
463 mErrorString = tr(
"%1" ).arg( QMetaEnum::fromType<QSerialPort::SerialPortError>().valueToKey( error ) );
467 emit errorOccurred( mErrorString );
470bool QgsSerialPortSensor::writePropertiesToElement( QDomElement &element, QDomDocument & )
const
472 element.setAttribute( QStringLiteral(
"portName" ), mPortName );
473 element.setAttribute( QStringLiteral(
"baudRate" ),
static_cast<int>( mBaudRate ) );
474 element.setAttribute( QStringLiteral(
"delimiter" ), QString( mDelimiter ) );
478bool QgsSerialPortSensor::readPropertiesFromElement(
const QDomElement &element,
const QDomDocument & )
480 mPortName = element.attribute( QStringLiteral(
"portName" ) );
481 mBaudRate =
static_cast< QSerialPort::BaudRate
>( element.attribute( QStringLiteral(
"baudRate" ) ).toInt() );
482 mDelimiter = element.attribute( QStringLiteral(
"delimiter" ) ).toLocal8Bit();
@ Connected
Device is successfully connected.
@ Disconnected
Device is disconnected.
QgsAbstractSensor::SensorData data() const
Returns the latest captured data from the sensor.
void setStatus(Qgis::DeviceConnectionStatus status)
Sets the current sensor status.
void errorOccurred(const QString &errorString)
Emitted when an error has occurred. The errorString describes the error.
void setData(const QgsAbstractSensor::SensorData &data)
Sets the latest captured data from the sensor.
An abstract class for QIODevice-based sensors.
void initIODevice(QIODevice *device)
Initiates the I/O device.
QgsIODeviceSensor(QObject *parent=nullptr)
Constructor for a abstract QIODevice-based sensor, bound to the specified parent.
virtual void parseData()
Parses the data read from the device when available.
QIODevice * iODevice() const
Returns the I/O device.
~QgsIODeviceSensor() override
QgsTcpSocketSensor(QObject *parent=nullptr)
Constructor for a TCP socket sensor, bound to the specified parent.
void setHostName(const QString &hostName)
Sets the host name the socket connects to.
int port() const
Returns the port the socket connects to.
void handleConnect() override
Handles the connection to the sensor.
QString type() const override
Returns the sensor type.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document) const override
Write specific sensor type properties into a DOM element.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document) override
Restores specific sensor type properties from a DOM element.
void handleDisconnect() override
Handles the disconnection from the sensor.
static QgsTcpSocketSensor * create(QObject *parent)
Returns a new TCP socket sensor.
void setPort(int port)
Sets the port the socket connects to.
QString hostName() const
Returns the host name the socket connects to.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document) override
Restores specific sensor type properties from a DOM element.
static QgsUdpSocketSensor * create(QObject *parent)
Returns a new UDP socket sensor.
QString type() const override
Returns the sensor type.
void handleDisconnect() override
Handles the disconnection from the sensor.
QgsUdpSocketSensor(QObject *parent=nullptr)
Constructor for a UDP socket sensor, bound to the specified parent.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document) const override
Write specific sensor type properties into a DOM element.
void setHostName(const QString &hostName)
Sets the host name the socket connects to.
int port() const
Returns the port the socket connects to.
void handleConnect() override
Handles the connection to the sensor.
void setPort(int port)
Sets the port the socket connects to.
QString hostName() const
Returns the host name the socket connects to.
Contains details of a sensor data capture.
QVariant lastValue
Last captured sensor value stored as a QVariant.
QDateTime lastTimestamp
Timestamp of last captured sensor value.