-
Notifications
You must be signed in to change notification settings - Fork 1
/
PressureSensor.cpp
202 lines (178 loc) · 4.91 KB
/
PressureSensor.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
* @file PressureSensor.cpp
* @Author BeeeOn team
* @date
* @brief
*/
#include <iostream>
#include <fstream>
#include "main.h"
#include "PressureSensor.h"
#include "Parameters.h"
using namespace std;
using Poco::AutoPtr;
#define REFRESH_MODULE_ID 0x01
#define SECONDS_IN_DAY 86400
PressureSensor::PressureSensor(IOTMessage _msg, shared_ptr<Aggregator> _agg) :
ModuleADT(_agg, "Adaapp-PS", MOD_PRESSURE_SENSOR, _msg),
wake_up_time(5)
{
sensor.euid = getEUI(msg.adapter_id);
sensor.pairs = 2;
sensor.device_id = 2;
send_wake_up_flag = false;
}
/**
* Main method of this thread.
* Periodically send "data" messages with current pressure sensor value.
*
* Naturally end when quit_global_flag is set to true,
* so the Adaapp is terminating.
*/
void PressureSensor::threadFunction(){
log.information("Starting Pressure sensor thread...");
//if obtaining failed, don't send refresh_time value
send_wake_up_flag = obtainRefreshTime();
while(!quit_global_flag) {
//try to get refresh value again
if (!send_wake_up_flag)
send_wake_up_flag = obtainRefreshTime();
pair<bool, Command> response;
if (createMsg()) {
response = agg->sendData(msg);
if (response.first) {
parseCmdFromServer(response.second);
}
}
else {
log.error("Can't load new value of pressure sensor, send terminated");
}
for (wake_up_counter = 0; wake_up_counter < wake_up_time; wake_up_counter++) {
if (quit_global_flag)
break;
sleep(1);
}
}
}
/**
* Function for generating 4B EUI of pressure sensor from adapter_id
* @param adapter_id adapter_id
* @return 4B EUI (hash) of pressure sensor
*/
long long int PressureSensor::getEUI(std::string adapter_id) {
std::string key = adapter_id + "0001";
uint32_t hash, i;
for (hash = i = 0; i < key.length(); ++i) {
hash += key.at(i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
hash = (((0xa2 << 24)) + (hash & 0xffffff)) & 0xffffffff;
return (long long int) hash;
}
/**
* Method create message with updated value from sensor.
*
* @return false if there was an error in creating message, else return true
*/
bool PressureSensor::createMsg() {
sensor.values.clear();
if (!refreshValue())
return false;
sensor.values.push_back({0, pressureValue});
if (send_wake_up_flag) {
sensor.values.push_back({1, (float)wake_up_time});
sensor.pairs = 2;
}
else {
sensor.pairs = 1;
}
msg.device = sensor;
msg.time = time(NULL);
return true;
}
/**
* Method for refreshing value from sensor.
*
* @return false if there was an error in refreshing value (e.g: non-existent file)
* else return true
*/
bool PressureSensor::refreshValue() {
std::fstream value_file(PRESSURE_SENSOR_PATH, std::ios_base::in);
pressureValue = 0;
value_file >> pressureValue;
if (pressureValue==0)
return false;
else {
pressureValue = pressureValue/100.0;
return true;
}
}
/**
* @brief Method for handling answer from server.
* Can't contain anything, but "update" or "set" command.
* Only log error if anything else will come.
* @param cmd command struct with incomming command from server and delivered to PS
*/
void PressureSensor::parseCmdFromServer(const Command& cmd){
if (cmd.state == "update") { // do nothing
return;
}
if (cmd.state == "set"){
for( unsigned int i =0; i < cmd.values.size(); i++){
if (cmd.values[i].first == 1) { //Change refresh time
setNewRefresh(cmd.values[i].second);
}
else {
log.error("Set unknown module id, module id = "+ std::to_string(cmd.values[i].first));
}
}
return;
}
log.error("Unexpected answer from server, received command: " + cmd.state);
}
void PressureSensor::setNewRefresh(int refresh)
{
if ((refresh < 1) || (refresh > SECONDS_IN_DAY)) {
log.error("Incorrect wakeup time set: " + to_string(refresh) + " seconds");
}
else {
log.information("Changed refresh time to " + to_string(refresh) + " seconds" );
wake_up_time = refresh;
wake_up_counter = refresh;
}
}
bool PressureSensor::obtainRefreshTime()
{
// Try to get refresh time from server
log.information("Getting last refresh value from server.");
Parameters parameters(*agg.get(), msg, log);
CmdParam request, answer;
request.euid = sensor.euid;
request.param_id = Parameters::GW_GET_DEV_MOD_LAST_VALUE;
request.module_id = REFRESH_MODULE_ID;
answer = parameters.askServer(request);
if (!answer.status) {
log.warning("Could not retrieve latest refresh time value from server, will try again");
return false;
}
if (answer.module_id == REFRESH_MODULE_ID) {
try {
int new_refresh = stoi(answer.value[0].first);
setNewRefresh(new_refresh);
}
catch(...) {
log.error("Received invalid refresh time value");
log.error("Value of refresh time: "+answer.value[0].first);
return false;
}
}
else {
log.information("No latest refresh value found on server, setting default");
return true; // this is Ok, sensor is new so there are no latest data.
}
return true;
}