18#include "moc_qgsiodevicesensor.cpp"
23#if defined( Q_OS_ANDROID ) || defined( Q_OS_LINUX )
24#include <sys/socket.h>
33 mIODevice.reset( device );
43 return mIODevice.get();
58 , mTcpSocket( new QTcpSocket() )
60 connect( mTcpSocket, &QAbstractSocket::stateChanged,
this, &QgsTcpSocketSensor::socketStateChanged );
61 connect( mTcpSocket, qOverload<QAbstractSocket::SocketError>( &QAbstractSocket::errorOccurred ),
this, &QgsTcpSocketSensor::handleError );
73 return QLatin1String(
"tcp_socket" );
104 if ( mHostName.isEmpty() || mPort == 0 )
110 mTcpSocket->connectToHost( mHostName, mPort, QTcpSocket::ReadOnly );
118void QgsTcpSocketSensor::handleError( QAbstractSocket::SocketError error )
122 case QAbstractSocket::HostNotFoundError:
125 case QAbstractSocket::NetworkError:
126 mErrorString = tr(
"Attempt to read or write from socket returned an error" );
128 case QAbstractSocket::ConnectionRefusedError:
129 mErrorString = tr(
"The connection was refused by the remote host" );
132 mErrorString = tr(
"%1" ).arg( QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey( error ) );
139void QgsTcpSocketSensor::socketStateChanged(
const QAbstractSocket::SocketState socketState )
141 switch ( socketState )
143 case QAbstractSocket::ConnectedState:
148 case QAbstractSocket::UnconnectedState:
160 element.setAttribute( QStringLiteral(
"hostName" ), mHostName );
161 element.setAttribute( QStringLiteral(
"port" ), QString::number( mPort ) );
168 mHostName = element.attribute( QStringLiteral(
"hostName" ) );
169 mPort = element.attribute( QStringLiteral(
"port" ) ).toInt();
178 , mUdpSocket( std::make_unique<QUdpSocket>() )
179 , mBuffer( new QBuffer() )
181#if defined( Q_OS_ANDROID ) || defined( Q_OS_LINUX )
182 int sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
184 setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR,
185 (
void * ) &optval,
sizeof( optval ) );
186 mUdpSocket->setSocketDescriptor( sockfd, QUdpSocket::UnconnectedState );
189 connect( mUdpSocket.get(), &QAbstractSocket::stateChanged,
this, &QgsUdpSocketSensor::socketStateChanged );
190 connect( mUdpSocket.get(), &QUdpSocket::readyRead,
this, [
this]()
193 while ( mUdpSocket->hasPendingDatagrams() )
195 datagram.resize( int( mUdpSocket->pendingDatagramSize() ) );
196 mUdpSocket->readDatagram( datagram.data(), datagram.size() );
198 mBuffer->buffer().clear();
200 mBuffer->write( datagram );
205 connect( mUdpSocket.get(), qOverload<QAbstractSocket::SocketError>( &QAbstractSocket::errorOccurred ),
this, &QgsUdpSocketSensor::handleError );
207 initIODevice( mBuffer );
217 return QLatin1String(
"udp_socket" );
248 if ( mHostName.isEmpty() || mPort == 0 )
254 mBuffer->open( QIODevice::ReadWrite );
255 mUdpSocket->bind( QHostAddress( mHostName ), mPort, QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint );
256 mUdpSocket->joinMulticastGroup( QHostAddress( mHostName ) );
265void QgsUdpSocketSensor::handleError( QAbstractSocket::SocketError error )
269 case QAbstractSocket::HostNotFoundError:
272 case QAbstractSocket::NetworkError:
273 mErrorString = tr(
"Attempt to read or write from socket returned an error" );
275 case QAbstractSocket::ConnectionRefusedError:
276 mErrorString = tr(
"The connection was refused by the remote host" );
279 mErrorString = tr(
"%1" ).arg( QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey( error ) );
286void QgsUdpSocketSensor::socketStateChanged(
const QAbstractSocket::SocketState socketState )
288 switch ( socketState )
290 case QAbstractSocket::ConnectedState:
291 case QAbstractSocket::BoundState:
296 case QAbstractSocket::UnconnectedState:
308 element.setAttribute( QStringLiteral(
"hostName" ), mHostName );
309 element.setAttribute( QStringLiteral(
"port" ), QString::number( mPort ) );
316 mHostName = element.attribute( QStringLiteral(
"hostName" ) );
317 mPort = element.attribute( QStringLiteral(
"port" ) ).toInt();
324#if defined( HAVE_QTSERIALPORT )
325QgsSerialPortSensor::QgsSerialPortSensor( QObject *parent )
327 , mSerialPort( new QSerialPort() )
329 connect( mSerialPort, qOverload<QSerialPort::SerialPortError>( &QSerialPort::errorOccurred ),
this, &QgsSerialPortSensor::handleError );
334QgsSerialPortSensor *QgsSerialPortSensor::create( QObject *parent )
336 return new QgsSerialPortSensor( parent );
339QString QgsSerialPortSensor::type()
const
341 return QLatin1String(
"serial_port" );
344QString QgsSerialPortSensor::portName()
const
349void QgsSerialPortSensor::setPortName(
const QString &portName )
351 if ( mPortName == portName )
354 mPortName = portName;
357QSerialPort::BaudRate QgsSerialPortSensor::baudRate()
const
362void QgsSerialPortSensor::setBaudRate(
const QSerialPort::BaudRate &baudRate )
364 if ( mBaudRate == baudRate )
367 mBaudRate = baudRate;
370QByteArray QgsSerialPortSensor::delimiter()
const
375void QgsSerialPortSensor::setDelimiter(
const QByteArray &delimiter )
377 if ( mDelimiter == delimiter )
380 mDelimiter = delimiter;
384void QgsSerialPortSensor::parseData()
386 if ( !mDelimiter.isEmpty() )
388 if ( mFirstDelimiterHit )
390 mDataBuffer += mSerialPort->readAll();
391 const auto lastIndex = mDataBuffer.lastIndexOf( mDelimiter );
392 if ( lastIndex > -1 )
395 data.
lastValue = mDataBuffer.mid( 0, lastIndex );
396 mDataBuffer = mDataBuffer.mid( lastIndex + mDelimiter.size() );
403 QByteArray data = mSerialPort->readAll();
404 const auto lastIndex = data.lastIndexOf( mDelimiter );
405 if ( lastIndex > -1 )
407 mFirstDelimiterHit =
true;
408 mDataBuffer = data.mid( lastIndex + mDelimiter.size() );
421void QgsSerialPortSensor::handleConnect()
423 mSerialPort->setPortName( mPortName );
424 mSerialPort->setBaudRate( mBaudRate );
425 mFirstDelimiterHit =
false;
427 if ( mSerialPort->open( QIODevice::ReadOnly ) )
437void QgsSerialPortSensor::handleDisconnect()
439 mSerialPort->close();
442void QgsSerialPortSensor::handleError( QSerialPort::SerialPortError error )
444 if ( error == QSerialPort::NoError )
451 case QSerialPort::DeviceNotFoundError:
452 mErrorString = tr(
"Could not find the serial port device" );
454 case QSerialPort::ReadError:
455 mErrorString = tr(
"Attempt to read from the serial port returned an error" );
457 case QSerialPort::PermissionError:
458 mErrorString = tr(
"The connection was refused due to not having enough permission" );
461 mErrorString = tr(
"%1" ).arg( QMetaEnum::fromType<QSerialPort::SerialPortError>().valueToKey( error ) );
465 emit errorOccurred( mErrorString );
468bool QgsSerialPortSensor::writePropertiesToElement( QDomElement &element, QDomDocument & )
const
470 element.setAttribute( QStringLiteral(
"portName" ), mPortName );
471 element.setAttribute( QStringLiteral(
"baudRate" ),
static_cast<int>( mBaudRate ) );
472 element.setAttribute( QStringLiteral(
"delimiter" ), QString( mDelimiter ) );
476bool QgsSerialPortSensor::readPropertiesFromElement(
const QDomElement &element,
const QDomDocument & )
478 mPortName = element.attribute( QStringLiteral(
"portName" ) );
479 mBaudRate =
static_cast< QSerialPort::BaudRate
>( element.attribute( QStringLiteral(
"baudRate" ) ).toInt() );
480 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 QIODevice-based sensor classes.
void initIODevice(QIODevice *device)
Initiates the I/O device.
virtual void parseData()
Parses the data read from the device when available.
QIODevice * iODevice() const
Returns the I/O device.
~QgsIODeviceSensor() override
A TCP socket sensor class.
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.
A UDP socket sensor class.
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.