-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathApplication.cpp
163 lines (148 loc) · 6.96 KB
/
Application.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
* Copyright 2022 Wolkabout Technology s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "core/utilities/Logger.h"
#include "wolk/WolkBuilder.h"
#include "wolk/WolkSingle.h"
#include "wolk/api/ParameterHandler.h"
/**
* This is the place where user input is required for running the example.
* In here, you can enter the device credentials to successfully identify the device on the platform.
* And also, the target platform path, and the SSL certificate that is used to establish a secure connection.
*/
const std::string DEVICE_KEY = "<DEVICE_KEY>";
const std::string DEVICE_PASSWORD = "<DEVICE_PASSWORD>";
const std::string PLATFORM_HOST = "ssl://INSERT_HOSTNAME:PORT";
const std::string CA_CERT_PATH = "/INSERT/PATH/TO/YOUR/CA.CRT/FILE";
/**
* This is a structure definition that is a collection of all information/feeds the device will have.
*/
struct DeviceData
{
bool toggle;
std::chrono::seconds heartbeat;
};
/**
* This is an implementation of a class that is able to receive new feed values from the platform.
* When the device is going to pull feed values, this object is going to receive the values.
*/
class FeedChangeHandler : public wolkabout::connect::FeedUpdateHandler
{
public:
/**
* Default constructor with the reference to the object in which the values are going to be stored.
*
* @param deviceData The device data instance in which feed values are going to be written in.
*/
explicit FeedChangeHandler(DeviceData& deviceData) : m_deviceData(deviceData) {}
/**
* This is the overridden method from the `wolkabout::FeedUpdateHandler` interface. This method will be invoked once
* new feed values have been received.
*
* @param readings The map containing all the new feed values. Feed values are sent out grouped by their timestamp,
* so the key in this map is going to be time at which values have been sent, and in the value is the vector of
* values that have been set at that particular time.
*/
void handleUpdate(const std::string& deviceKey,
const std::map<std::uint64_t, std::vector<wolkabout::Reading>>& readings) override
{
// Go through all the timestamps - since the `std::map` sorts by key, this will always go from the oldest to
// newest.
for (const auto& pair : readings)
{
// Take the readings, check if any of them interest us, and set the values in our object.
for (const auto& reading : pair.second)
{
// Check the reference on the readings to check if we want to read values of them.
// Reading values can always be extracted as `getStringValue()` (or `getStringValues()` for vectors).
// If the value can be parsed into, for example, boolean, you can also do `getBoolValue()`.
if (reading.getReference() == "SW")
{
LOG(INFO) << "Received update for feed '" << reading.getReference() << "' - Value: '"
<< reading.getStringValue() << "' | Time = " << pair.first << ".";
m_deviceData.toggle = reading.getBoolValue();
}
else if (reading.getReference() == "HB")
{
LOG(INFO) << "Received update for feed '" << reading.getReference() << "' - Value: '"
<< reading.getStringValue() << "' | Time = " << pair.first << ".";
m_deviceData.heartbeat = std::chrono::seconds(reading.getUIntValue());
}
}
}
}
private:
// This is where we're going to store the reference to the object in which we're going to store feed values.
DeviceData& m_deviceData;
};
/**
* This is an implementation of a class that can receive parameter value updates, in the same way FeedChangeHandler can
* receive feed updates. When the device decides to pull the values, this object will receive the values.
*/
class ParameterChangeHandler : public wolkabout::connect::ParameterHandler
{
public:
/**
* This is the overridden method from the `wolkabout::ParameterHandler` interface. This method will be invoked once
* new parameter values have been received.
*
* @param parameters This is a vector containing all parameter that have been changed. Since the device pulls
* parameters, the device will receive all updates to values since the last time it has pulled values.
*/
void handleUpdate(const std::string& deviceKey, const std::vector<wolkabout::Parameter>& parameters) override
{
for (const auto& parameter : parameters)
LOG(INFO) << "Received update for parameter '" << wolkabout::toString(parameter.first) << "' - Value: '"
<< parameter.second << "'.";
}
};
int main(int /* argc */, char** /* argv */)
{
// This is the logger setup. Here you can set up the level of logging you would like enabled.
wolkabout::Logger::init(wolkabout::LogLevel::INFO, wolkabout::Logger::Type::CONSOLE);
// Here we create the device that we are presenting as on the platform.
auto device = wolkabout::Device(DEVICE_KEY, DEVICE_PASSWORD, wolkabout::OutboundDataMode::PULL);
auto data = DeviceData{};
// And now we can create the handlers
auto feedHandler = std::make_shared<FeedChangeHandler>(data);
auto parameterHandler = std::make_shared<ParameterChangeHandler>();
// And here we create the wolk session
// Here we will set the feed value and parameter handler
auto wolk = wolkabout::connect::WolkSingle::newBuilder(device)
.host(PLATFORM_HOST)
.caCertPath(CA_CERT_PATH)
.feedUpdateHandler(feedHandler)
.parameterHandler(parameterHandler)
.buildWolkSingle();
// And now we will periodically connect, pull values, maybe even send some of our own, and then disconnect
while (true)
{
// So we connect
wolk->connect();
// We request some values
wolk->pullFeedValues();
wolk->pullParameters();
// Sleep a bit, and wait to send some of our own
std::this_thread::sleep_for(std::chrono::seconds(2));
wolk->addReading("SW", false);
wolk->publish();
// And then we disconnect
std::this_thread::sleep_for(std::chrono::seconds(8));
wolk->disconnect();
std::this_thread::sleep_for(std::chrono::milliseconds(60));
}
wolk->disconnect();
return 0;
}