Skip to content

Commit b1fc403

Browse files
Add getObservations, createObservation
1 parent 430ad5d commit b1fc403

14 files changed

Lines changed: 737 additions & 20 deletions

CSAPI-lib/CSAPI-lib.vcxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,13 @@
160160
<ClInclude Include="DataModels\Component\Vector.h" />
161161
<ClInclude Include="DataModels\DataStream.h" />
162162
<ClInclude Include="DataModels\DataStreamBuilder.h" />
163+
<ClInclude Include="DataModels\Data\DataBlock.h" />
164+
<ClInclude Include="DataModels\Data\DataBlockMixed.h" />
165+
<ClInclude Include="DataModels\Data\DataType.h" />
166+
<ClInclude Include="DataModels\Data\DataValue.h" />
163167
<ClInclude Include="DataModels\Link.h" />
168+
<ClInclude Include="DataModels\Observation.h" />
169+
<ClInclude Include="DataModels\ObservationBuilder.h" />
164170
<ClInclude Include="DataModels\ObservationSchema.h" />
165171
<ClInclude Include="DataModels\ObservationSchemaBuilder.h" />
166172
<ClInclude Include="DataModels\ObservedProperty.h" />
@@ -169,8 +175,10 @@
169175
<ClInclude Include="DataModels\System.h" />
170176
<ClInclude Include="DataModels\SystemBuilder.h" />
171177
<ClInclude Include="DataModels\TimeExtent.h" />
178+
<ClInclude Include="DataModels\TimeInstant.h" />
172179
<ClInclude Include="DataStreamsAPI.h" />
173180
<ClInclude Include="framework.h" />
181+
<ClInclude Include="ObservationsAPI.h" />
174182
<ClInclude Include="Query\DataStreamsOfSystemQuery.h" />
175183
<ClInclude Include="Query\DataStreamsQuery.h" />
176184
<ClInclude Include="Query\QueryParameters.h" />

CSAPI-lib/CSAPI-lib.vcxproj.filters

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
<Filter Include="Header Files\DataModels\Component">
2626
<UniqueIdentifier>{f6e2dae1-77d1-44c3-b6b7-50b98264f96e}</UniqueIdentifier>
2727
</Filter>
28+
<Filter Include="Header Files\DataModels\Data">
29+
<UniqueIdentifier>{ca8d78de-8bfd-41db-9426-a48aa14cb287}</UniqueIdentifier>
30+
</Filter>
2831
</ItemGroup>
2932
<ItemGroup>
3033
<ClInclude Include="framework.h">
@@ -168,5 +171,29 @@
168171
<ClInclude Include="DataModels\Component\BooleanBuilder.h">
169172
<Filter>Header Files\DataModels\Component</Filter>
170173
</ClInclude>
174+
<ClInclude Include="ObservationsAPI.h">
175+
<Filter>Header Files</Filter>
176+
</ClInclude>
177+
<ClInclude Include="DataModels\Observation.h">
178+
<Filter>Header Files\DataModels</Filter>
179+
</ClInclude>
180+
<ClInclude Include="DataModels\Data\DataBlock.h">
181+
<Filter>Header Files\DataModels\Data</Filter>
182+
</ClInclude>
183+
<ClInclude Include="DataModels\Data\DataType.h">
184+
<Filter>Header Files\DataModels\Data</Filter>
185+
</ClInclude>
186+
<ClInclude Include="DataModels\Data\DataBlockMixed.h">
187+
<Filter>Header Files\DataModels\Data</Filter>
188+
</ClInclude>
189+
<ClInclude Include="DataModels\Data\DataValue.h">
190+
<Filter>Header Files\DataModels\Data</Filter>
191+
</ClInclude>
192+
<ClInclude Include="DataModels\TimeInstant.h">
193+
<Filter>Header Files\DataModels</Filter>
194+
</ClInclude>
195+
<ClInclude Include="DataModels\ObservationBuilder.h">
196+
<Filter>Header Files\DataModels</Filter>
197+
</ClInclude>
171198
</ItemGroup>
172199
</Project>

CSAPI-lib/ConnectedSystemsAPI.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
#pragma once
22

3-
#include <curl/curl.h>
43
#include <string>
5-
#include <iostream>
6-
#include "APIRequest.h"
7-
#include "SystemsAPI.h"
4+
85
#include "DataStreamsAPI.h"
9-
#include "RegistryInit.h"
6+
#include "ObservationsAPI.h"
7+
#include "SystemsAPI.h"
108

119
namespace ConnectedSystemsAPI {
1210
class ConSysAPI {
@@ -15,6 +13,7 @@ namespace ConnectedSystemsAPI {
1513
std::string authHeader;
1614
SystemsAPI systemsAPI;
1715
DataStreamsAPI dataStreamsAPI;
16+
ObservationsAPI observationsAPI;
1817

1918
public:
2019
/// <param name="apiRoot">e.g. "localhost:8181/sensorhub/api"</param>
@@ -30,6 +29,7 @@ namespace ConnectedSystemsAPI {
3029
}
3130
systemsAPI = SystemsAPI(apiRoot, authHeader);
3231
dataStreamsAPI = DataStreamsAPI(apiRoot, authHeader);
32+
observationsAPI = ObservationsAPI(apiRoot, authHeader);
3333
}
3434

3535
/// <param name="apiRoot">e.g. "localhost:8181/sensorhub/api"</param>
@@ -43,6 +43,7 @@ namespace ConnectedSystemsAPI {
4343
const std::string& getAuthHeader() const { return authHeader; }
4444
SystemsAPI& getSystemsAPI() { return systemsAPI; }
4545
DataStreamsAPI& getDataStreamsAPI() { return dataStreamsAPI; }
46+
ObservationsAPI getObservationsAPI() { return observationsAPI; }
4647
private:
4748
std::string base64_encode(const std::string& in) {
4849
static const std::string base64_chars =

CSAPI-lib/DataModels/Component/DataRecord.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
#include <string>
44
#include <ostream>
55
#include <nlohmann/json.hpp>
6+
67
#include "DataComponent.h"
78
#include "DataComponentRegistry.h"
9+
#include "DataModels/Data/DataBlockMixed.h"
810

911
namespace ConnectedSystemsAPI {
1012
namespace DataModels {
@@ -56,6 +58,29 @@ namespace ConnectedSystemsAPI {
5658
void setFields(std::vector<std::unique_ptr<DataComponent>> f) noexcept { fields = std::move(f); }
5759
void clearFields() noexcept { fields.clear(); }
5860
void addField(std::unique_ptr<DataComponent> field) { if (field) fields.push_back(std::move(field)); }
61+
62+
DataModels::Data::DataBlockMixed createDataBlock() const {
63+
DataModels::Data::DataBlockMixed dataBlock;
64+
for (const auto& field : fields) {
65+
auto fieldName = field->getName().value_or("");
66+
auto fieldValue = DataModels::Data::DataValue();
67+
if (field->getType() == "Boolean") {
68+
fieldValue = DataModels::Data::DataValue(false);
69+
}
70+
else if (field->getType() == "Count") {
71+
fieldValue = DataModels::Data::DataValue(int64_t(0));
72+
}
73+
else if (field->getType() == "Quantity") {
74+
fieldValue = DataModels::Data::DataValue(0.0);
75+
}
76+
else if (field->getType() == "Text") {
77+
fieldValue = DataModels::Data::DataValue(std::string(""));
78+
}
79+
if (fieldName.empty()) continue;
80+
dataBlock.setField(fieldName, fieldValue);
81+
}
82+
return dataBlock;
83+
}
5984
};
6085

6186
inline DataComponent::Registrar<DataRecord> registerDataRecord{ "DataRecord" };
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include "DataModels/Data/DataType.h"
4+
5+
namespace ConnectedSystemsAPI {
6+
namespace DataModels {
7+
namespace Data {
8+
class DataBlock {
9+
public:
10+
virtual ~DataBlock() = default;
11+
12+
virtual DataType getDataType() const noexcept = 0;
13+
};
14+
}
15+
}
16+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#pragma once
2+
3+
#include "DataBlock.h"
4+
#include "DataType.h"
5+
#include "DataValue.h"
6+
7+
#include <string>
8+
#include <unordered_map>
9+
10+
namespace ConnectedSystemsAPI {
11+
namespace DataModels {
12+
namespace Data {
13+
class DataBlockMixed : public DataBlock {
14+
private:
15+
std::vector<std::pair<std::string, DataValue>> values;
16+
std::unordered_map<std::string, std::size_t> valuesIndex;
17+
18+
public:
19+
DataBlockMixed() = default;
20+
DataBlockMixed(const DataBlockMixed&) = default;
21+
DataBlockMixed(DataBlockMixed&&) noexcept = default;
22+
DataBlockMixed& operator=(const DataBlockMixed&) = default;
23+
DataBlockMixed& operator=(DataBlockMixed&&) noexcept = default;
24+
~DataBlockMixed() override = default;
25+
26+
DataType getDataType() const noexcept override {
27+
return DataType::Mixed;
28+
}
29+
30+
bool hasField(const std::string& name) const noexcept {
31+
return valuesIndex.find(name) != valuesIndex.end();
32+
}
33+
34+
const DataValue* getField(const std::string& name) const noexcept {
35+
auto it = valuesIndex.find(name);
36+
if (it == valuesIndex.end()) return nullptr;
37+
return &values[it->second].second;
38+
}
39+
40+
void setField(const std::string& name, const DataValue& value) {
41+
if (hasField(name)) {
42+
values[valuesIndex[name]].second = value;
43+
}
44+
else {
45+
values.emplace_back(name, value);
46+
valuesIndex[name] = values.size() - 1;
47+
}
48+
}
49+
50+
friend void from_json(const nlohmann::ordered_json& j, DataBlockMixed& v);
51+
friend void to_json(nlohmann::ordered_json& j, const DataBlockMixed& v);
52+
};
53+
54+
inline void from_json(const nlohmann::ordered_json& j, DataBlockMixed& v) {
55+
v.values.clear();
56+
v.valuesIndex.clear();
57+
58+
if (!j.is_object()) return;
59+
60+
for (auto it = j.begin(); it != j.end(); ++it) {
61+
const std::string key = it.key();
62+
DataValue dv = it.value().get<DataValue>();
63+
v.values.emplace_back(key, std::move(dv));
64+
v.valuesIndex[key] = v.values.size() - 1;
65+
}
66+
}
67+
68+
inline void to_json(nlohmann::ordered_json& j, const DataBlockMixed& v) {
69+
j = nlohmann::ordered_json::object();
70+
for (const auto& pair : v.values) {
71+
j[pair.first] = pair.second;
72+
}
73+
}
74+
}
75+
}
76+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
namespace ConnectedSystemsAPI {
4+
namespace DataModels {
5+
namespace Data {
6+
enum class DataType {
7+
Boolean,
8+
Byte,
9+
Short,
10+
Int,
11+
Long,
12+
UByte,
13+
UShort,
14+
UInt,
15+
ULong,
16+
Float,
17+
Double,
18+
String,
19+
Instant,
20+
DateTime,
21+
Other,
22+
Discard,
23+
Mixed
24+
};
25+
}
26+
}
27+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <variant>
5+
6+
namespace ConnectedSystemsAPI {
7+
namespace DataModels {
8+
namespace Data {
9+
struct DataValue {
10+
using ValueType = std::variant<
11+
bool,
12+
int64_t,
13+
uint64_t,
14+
double,
15+
std::string
16+
>;
17+
ValueType value;
18+
19+
DataValue() = default;
20+
DataValue(const DataValue&) = default;
21+
DataValue(DataValue&&) noexcept = default;
22+
DataValue& operator=(const DataValue&) = default;
23+
DataValue& operator=(DataValue&&) noexcept = default;
24+
~DataValue() = default;
25+
26+
DataValue(bool v) : value(v) {}
27+
DataValue(int64_t v) : value(v) {}
28+
DataValue(uint64_t v) : value(v) {}
29+
DataValue(double v) : value(v) {}
30+
DataValue(const std::string& v) : value(v) {}
31+
DataValue(std::string&& v) : value(std::move(v)) {}
32+
DataValue(const char* s) : value(std::string(s)) {}
33+
34+
std::string toString() const {
35+
if (std::holds_alternative<bool>(value)) {
36+
return std::holds_alternative<bool>(value) && std::get<bool>(value) ? "true" : "false";
37+
}
38+
else if (std::holds_alternative<int64_t>(value)) {
39+
return std::to_string(std::get<int64_t>(value));
40+
}
41+
else if (std::holds_alternative<uint64_t>(value)) {
42+
return std::to_string(std::get<uint64_t>(value));
43+
}
44+
else if (std::holds_alternative<double>(value)) {
45+
return std::to_string(std::get<double>(value));
46+
}
47+
else if (std::holds_alternative<std::string>(value)) {
48+
return std::get<std::string>(value);
49+
}
50+
else {
51+
return "";
52+
}
53+
}
54+
55+
friend void from_json(const nlohmann::json& j, DataValue& v);
56+
friend void to_json(nlohmann::ordered_json& j, const DataValue& v);
57+
};
58+
59+
inline void from_json(const nlohmann::json& j, DataValue& v) {
60+
if (j.is_boolean()) {
61+
v.value = j.get<bool>();
62+
}
63+
else if (j.is_number_integer()) {
64+
v.value = j.get<int64_t>();
65+
}
66+
else if (j.is_number_unsigned()) {
67+
v.value = j.get<uint64_t>();
68+
}
69+
else if (j.is_number_float()) {
70+
v.value = j.get<double>();
71+
}
72+
else if (j.is_string()) {
73+
v.value = j.get<std::string>();
74+
}
75+
}
76+
77+
inline void to_json(nlohmann::ordered_json& j, const DataValue& v) {
78+
if (std::holds_alternative<bool>(v.value)) {
79+
j = std::get<bool>(v.value);
80+
}
81+
else if (std::holds_alternative<int64_t>(v.value)) {
82+
j = std::get<int64_t>(v.value);
83+
}
84+
else if (std::holds_alternative<uint64_t>(v.value)) {
85+
j = std::get<uint64_t>(v.value);
86+
}
87+
else if (std::holds_alternative<double>(v.value)) {
88+
j = std::get<double>(v.value);
89+
}
90+
else if (std::holds_alternative<std::string>(v.value)) {
91+
j = std::get<std::string>(v.value);
92+
}
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)