24#include <QNetworkRequest>
25#include <nlohmann/json.hpp>
29 const QString trimmed = type.trimmed();
30 if ( trimmed.compare( QLatin1String(
"Thing" ), Qt::CaseInsensitive ) == 0 )
32 if ( trimmed.compare( QLatin1String(
"Location" ), Qt::CaseInsensitive ) == 0 )
34 if ( trimmed.compare( QLatin1String(
"HistoricalLocation" ), Qt::CaseInsensitive ) == 0 )
36 if ( trimmed.compare( QLatin1String(
"Datastream" ), Qt::CaseInsensitive ) == 0 )
38 if ( trimmed.compare( QLatin1String(
"Sensor" ), Qt::CaseInsensitive ) == 0 )
40 if ( trimmed.compare( QLatin1String(
"ObservedProperty" ), Qt::CaseInsensitive ) == 0 )
42 if ( trimmed.compare( QLatin1String(
"Observation" ), Qt::CaseInsensitive ) == 0 )
44 if ( trimmed.compare( QLatin1String(
"FeatureOfInterest" ), Qt::CaseInsensitive ) == 0 )
57 return plural ? QObject::tr(
"Things" ) : QObject::tr(
"Thing" );
59 return plural ? QObject::tr(
"Locations" ) : QObject::tr(
"Location" );
61 return plural ? QObject::tr(
"Historical Locations" ) : QObject::tr(
"Historical Location" );
63 return plural ? QObject::tr(
"Datastreams" ) : QObject::tr(
"Datastream" );
65 return plural ? QObject::tr(
"Sensors" ) : QObject::tr(
"Sensor" );
67 return plural ? QObject::tr(
"Observed Properties" ) : QObject::tr(
"Observed Property" );
69 return plural ? QObject::tr(
"Observations" ) : QObject::tr(
"Observation" );
71 return plural ? QObject::tr(
"Features of Interest" ) : QObject::tr(
"Feature of Interest" );
78 const QString trimmed = type.trimmed();
79 if ( trimmed.compare( QLatin1String(
"Things" ), Qt::CaseInsensitive ) == 0 )
81 if ( trimmed.compare( QLatin1String(
"Locations" ), Qt::CaseInsensitive ) == 0 )
83 if ( trimmed.compare( QLatin1String(
"HistoricalLocations" ), Qt::CaseInsensitive ) == 0 )
85 if ( trimmed.compare( QLatin1String(
"Datastreams" ), Qt::CaseInsensitive ) == 0 )
87 if ( trimmed.compare( QLatin1String(
"Sensors" ), Qt::CaseInsensitive ) == 0 )
89 if ( trimmed.compare( QLatin1String(
"ObservedProperties" ), Qt::CaseInsensitive ) == 0 )
91 if ( trimmed.compare( QLatin1String(
"Observations" ), Qt::CaseInsensitive ) == 0 )
93 if ( trimmed.compare( QLatin1String(
"FeaturesOfInterest" ), Qt::CaseInsensitive ) == 0 )
104 fields.
append(
QgsField( QStringLiteral(
"id" ), QVariant::String ) );
105 fields.
append(
QgsField( QStringLiteral(
"selfLink" ), QVariant::String ) );
114 fields.
append(
QgsField( QStringLiteral(
"name" ), QVariant::String ) );
115 fields.
append(
QgsField( QStringLiteral(
"description" ), QVariant::String ) );
116 fields.
append(
QgsField( QStringLiteral(
"properties" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
121 fields.
append(
QgsField( QStringLiteral(
"name" ), QVariant::String ) );
122 fields.
append(
QgsField( QStringLiteral(
"description" ), QVariant::String ) );
123 fields.
append(
QgsField( QStringLiteral(
"properties" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
128 fields.
append(
QgsField( QStringLiteral(
"time" ), QVariant::DateTime ) );
133 fields.
append(
QgsField( QStringLiteral(
"name" ), QVariant::String ) );
134 fields.
append(
QgsField( QStringLiteral(
"description" ), QVariant::String ) );
135 fields.
append(
QgsField( QStringLiteral(
"unitOfMeasurement" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
136 fields.
append(
QgsField( QStringLiteral(
"observationType" ), QVariant::String ) );
137 fields.
append(
QgsField( QStringLiteral(
"properties" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
138 fields.
append(
QgsField( QStringLiteral(
"phenomenonTimeStart" ), QVariant::DateTime ) );
139 fields.
append(
QgsField( QStringLiteral(
"phenomenonTimeEnd" ), QVariant::DateTime ) );
140 fields.
append(
QgsField( QStringLiteral(
"resultTimeStart" ), QVariant::DateTime ) );
141 fields.
append(
QgsField( QStringLiteral(
"resultTimeEnd" ), QVariant::DateTime ) );
146 fields.
append(
QgsField( QStringLiteral(
"name" ), QVariant::String ) );
147 fields.
append(
QgsField( QStringLiteral(
"description" ), QVariant::String ) );
148 fields.
append(
QgsField( QStringLiteral(
"metadata" ), QVariant::String ) );
149 fields.
append(
QgsField( QStringLiteral(
"properties" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
154 fields.
append(
QgsField( QStringLiteral(
"name" ), QVariant::String ) );
155 fields.
append(
QgsField( QStringLiteral(
"definition" ), QVariant::String ) );
156 fields.
append(
QgsField( QStringLiteral(
"description" ), QVariant::String ) );
157 fields.
append(
QgsField( QStringLiteral(
"properties" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
162 fields.
append(
QgsField( QStringLiteral(
"phenomenonTimeStart" ), QVariant::DateTime ) );
163 fields.
append(
QgsField( QStringLiteral(
"phenomenonTimeEnd" ), QVariant::DateTime ) );
166 fields.
append(
QgsField( QStringLiteral(
"result" ), QVariant::String ) );
168 fields.
append(
QgsField( QStringLiteral(
"resultTime" ), QVariant::DateTime ) );
169 fields.
append(
QgsField( QStringLiteral(
"resultQuality" ), QVariant::StringList, QString(), 0, 0, QString(), QVariant::String ) );
170 fields.
append(
QgsField( QStringLiteral(
"validTimeStart" ), QVariant::DateTime ) );
171 fields.
append(
QgsField( QStringLiteral(
"validTimeEnd" ), QVariant::DateTime ) );
172 fields.
append(
QgsField( QStringLiteral(
"parameters" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
177 fields.
append(
QgsField( QStringLiteral(
"name" ), QVariant::String ) );
178 fields.
append(
QgsField( QStringLiteral(
"description" ), QVariant::String ) );
179 fields.
append(
QgsField( QStringLiteral(
"properties" ), QVariant::Map, QStringLiteral(
"json" ), 0, 0, QString(), QVariant::String ) );
200 return QStringLiteral(
"location" );
203 return QStringLiteral(
"feature" );
230 QString filterTarget;
231 switch ( entityType )
234 filterTarget = QStringLiteral(
"location/type" );
238 filterTarget = QStringLiteral(
"feature/type" );
254 return QStringLiteral(
"%1 eq 'Point'" ).arg( filterTarget );
256 return QStringLiteral(
"%1 eq 'Polygon'" ).arg( filterTarget );
259 return QStringLiteral(
"%1 eq 'LineString'" ).arg( filterTarget );
269 QNetworkRequest request = QNetworkRequest( QUrl( uri ) );
275 switch ( networkRequest.
get( request ) )
287 QString entityBaseUri;
291 auto rootContent = nlohmann::json::parse( content.
content().toStdString() );
292 if ( !rootContent.contains(
"value" ) )
294 QgsDebugError( QStringLiteral(
"No 'value' array in response" ) );
298 bool foundMatchingEntity =
false;
299 for (
const auto &valueJson : rootContent[
"value"] )
301 if ( valueJson.contains(
"name" ) && valueJson.contains(
"url" ) )
303 const QString name = QString::fromStdString( valueJson[
"name"].get<std::string>() );
305 if ( entityType == type )
307 const QString url = QString::fromStdString( valueJson[
"url"].get<std::string>() );
308 if ( !url.isEmpty() )
310 foundMatchingEntity =
true;
318 if ( !foundMatchingEntity )
324 catch (
const nlohmann::json::parse_error &ex )
326 QgsDebugError( QStringLiteral(
"Error parsing response: %1" ).arg( ex.what() ) );
330 auto getCountForType = [entityBaseUri, type, authCfg, feedback](
Qgis::GeometryType geometryType ) ->
long long
333 QString countUri = QStringLiteral(
"%1?$top=0&$count=true" ).arg( entityBaseUri );
336 if ( !typeFilter.isEmpty() )
337 countUri += QStringLiteral(
"&$filter=" ) + typeFilter;
339 const QUrl url( countUri );
341 QNetworkRequest request( url );
362 auto rootContent = nlohmann::json::parse( content.
content().toStdString() );
363 if ( !rootContent.contains(
"@iot.count" ) )
365 QgsDebugError( QStringLiteral(
"No '@iot.count' value in response" ) );
369 return rootContent[
"@iot.count"].get<
long long>();
371 catch (
const nlohmann::json::parse_error &ex )
373 QgsDebugError( QStringLiteral(
"Error parsing response: %1" ).arg( ex.what() ) );
379 QList<Qgis::GeometryType> types;
387 const long long matchCount = getCountForType( geometryType );
388 if ( matchCount < 0 )
390 else if ( matchCount > 0 )
391 types.append( geometryType );
SensorThingsEntity
OGC SensorThings API entity types.
@ Sensor
A Sensor is an instrument that observes a property or phenomenon with the goal of producing an estima...
@ ObservedProperty
An ObservedProperty specifies the phenomenon of an Observation.
@ Invalid
An invalid/unknown entity.
@ FeatureOfInterest
In the context of the Internet of Things, many Observations’ FeatureOfInterest can be the Location of...
@ Datastream
A Datastream groups a collection of Observations measuring the same ObservedProperty and produced by ...
@ Observation
An Observation is the act of measuring or otherwise determining the value of a property.
@ Location
A Location entity locates the Thing or the Things it associated with. A Thing’s Location entity is de...
@ Thing
A Thing is an object of the physical world (physical things) or the information world (virtual things...
@ HistoricalLocation
A Thing’s HistoricalLocation entity set provides the times of the current (i.e., last known) and prev...
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
WkbType
The WKB type describes the number of dimensions a geometry has.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
ErrorCode get(QNetworkRequest &request, bool forceRefresh=false, QgsFeedback *feedback=nullptr)
Performs a "get" operation on the specified request.
void setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
QString errorMessage() const
Returns the error message string, after a get(), post(), head() or put() request has been made.
@ NetworkError
A network error occurred.
@ ServerExceptionError
An exception was raised by the server.
@ NoError
No error was encountered.
@ TimeoutError
Timeout was reached before a reply was received.
QgsNetworkReplyContent reply() const
Returns the content of the network reply, after a get(), post(), head() or put() request has been mad...
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
Encapsulate a field in an attribute table or data source.
Container of fields for a vector layer.
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Encapsulates a network reply within a container which is inexpensive to copy and safe to pass between...
QByteArray content() const
Returns the reply content.
static QList< Qgis::GeometryType > availableGeometryTypes(const QString &uri, Qgis::SensorThingsEntity type, QgsFeedback *feedback=nullptr, const QString &authCfg=QString())
Returns a list of available geometry types for the server at the specified uri and entity type.
static Qgis::SensorThingsEntity stringToEntity(const QString &type)
Converts a string value to a Qgis::SensorThingsEntity type.
static Qgis::SensorThingsEntity entitySetStringToEntity(const QString &type)
Converts a string value corresponding to a SensorThings entity set to a Qgis::SensorThingsEntity type...
static QString filterForWkbType(Qgis::SensorThingsEntity entityType, Qgis::WkbType wkbType)
Returns a filter string which restricts results to those matching the specified entityType and wkbTyp...
static QString displayString(Qgis::SensorThingsEntity type, bool plural=false)
Converts a Qgis::SensorThingsEntity type to a user-friendly translated string.
static bool entityTypeHasGeometry(Qgis::SensorThingsEntity type)
Returns true if the specified entity type can have geometry attached.
static QString geometryFieldForEntityType(Qgis::SensorThingsEntity type)
Returns the geometry field for a specified entity type.
static QgsFields fieldsForEntityType(Qgis::SensorThingsEntity type)
Returns the fields which correspond to a specified entity type.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
#define BUILTIN_UNREACHABLE
#define QgsDebugError(str)
#define QgsSetRequestInitiatorClass(request, _class)