Skip to content

Commit 9aac8bb

Browse files
committed
Custom backend example
1 parent 1bd99e1 commit 9aac8bb

File tree

5 files changed

+569
-0
lines changed

5 files changed

+569
-0
lines changed

data/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Smart Citizen Data
2+
==================
3+
4+
**This is a basic example for creating your custom server backend for smartcitizen**
5+
6+
*Note this is aimed at learning, not production ready code.*
7+
8+
Check the complete documentation at http://docs.smartcitizen.me/#/start/how-to-store-data-in-your-own-database
9+

data/examples/add.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
5+
Smart Data - add.php
6+
7+
Basic example, reads SmartCitizen request and stored in a csv file.
8+
9+
You will need to set your end-point in the SCK firmware Constants.h (WEB[] in line 216)
10+
11+
Example curl:
12+
13+
$ curl -v -X PUT -H 'Host: data.smartcitizen.me' -H 'User-Agent: SmartCitizen' -H 'X-SmartCitizenMacADDR: 00:00:00:00:00:01' -H 'X-SmartCitizenVersion: 1.1-0.8.5-A' -H 'X-SmartCitizenData: [{"temp":"29090.6","hum":"6815.74","light":"30000","bat":"786","panel":"0","co":"112500","no2":"200000","noise":"2","nets":"10","timestamp":"2015-04-06 10:38:00"}]' 127.0.0.1/data/examples/add.php
14+
15+
*/
16+
17+
include('../sck_sensor_data.php');
18+
19+
$headers = getallheaders();
20+
21+
$data = $headers['X-SmartCitizenData'];
22+
23+
$datapoints = json_decode($data, true);
24+
25+
foreach ($datapoints as $datapoint) {
26+
$datapoint = SCKSensorData::SCK11Convert($datapoint);
27+
$csv .= implode(', ', $datapoint);
28+
}
29+
30+
$csv .= PHP_EOL;
31+
32+
file_put_contents('./data.csv', $csv, FILE_APPEND);
33+
34+
35+
?>

data/examples/data.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
2+
2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
3+
2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
4+
2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10

data/sck_sensor_data.php

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
<?php
2+
3+
4+
/**
5+
* SCKSensorData
6+
*
7+
* Authors: Smart Citizen Team
8+
*
9+
* SCKSensorData implements all the methods necessary for calibrating
10+
* and rescaling the data received from a Smart Citizen Kit 1.1.
11+
*
12+
*
13+
* TODO: Data validation based on each sensor ranges.
14+
*
15+
* Example usage (receive data, converted and store it in a csv file):
16+
*
17+
* <?php
18+
* include('../sck_sensor_data.php');
19+
*
20+
* $headers = getallheaders();
21+
*
22+
* $data = $headers['X-SmartCitizenData'];
23+
*
24+
* $datapoints = json_decode($data, true);
25+
*
26+
* foreach ($datapoints as $datapoint) {
27+
* $datapoint = SCKSensorData::SCK11Convert($datapoint);
28+
* $csv .= implode(', ', $datapoint);
29+
* }
30+
*
31+
* $csv .= PHP_EOL;
32+
*
33+
* file_put_contents('./data.csv', $csv, FILE_APPEND);
34+
* ?>
35+
*
36+
* SCKSensorData is free software: you can redistribute it and/or modify
37+
* it under the terms of the GNU Lesser General Public License as
38+
* published by the Free Software Foundation, either version 3 of
39+
* the License, or (at your option) any later version.
40+
*
41+
* SCKSensorData is distributed in the hope that it will be useful,
42+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
43+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44+
* GNU Lesser General Public License for more details.
45+
*
46+
* You should have received a copy of the GNU Lesser General Public
47+
* License along with SCKSensorData. If not, see
48+
* <http://www.gnu.org/licenses/>.
49+
*
50+
*/
51+
52+
53+
class SCKSensorData
54+
{
55+
56+
57+
/**
58+
* SCK11Calibration
59+
*
60+
* Calibrates to propper SI units an SCK datapoint
61+
*
62+
* @param array $rawBat Indexed array containing a SCK 1.1 datapoint
63+
* @return array Indexed arrary with a SCK datapoint calibrated
64+
*
65+
*/
66+
67+
public function SCK11Convert($rawData)
68+
{
69+
70+
$data = array();
71+
72+
if (self::isValidDateTimeString($rawData['timestamp'])) { //Check calibration....
73+
74+
$data['timestamp'] = $rawData['timestamp'];
75+
76+
$data['temp'] = self::tempConversion($rawData['temp']);
77+
$data['hum'] = self::humConversion($rawData['hum']);
78+
$data['noise'] = self::noiseConversion($rawData['noise']);
79+
$data['co'] = self::coConversion($rawData['co']);
80+
$data['no2'] = self::no2Conversion($rawData['no2']);
81+
$data['light'] = self::lightConversion($rawData['light']);
82+
$data['bat'] = self::batConversion($rawData['bat']);
83+
$data['panel'] = self::panelConversion($rawData['panel']);
84+
$data['nets'] = $rawData['nets'];
85+
86+
return $data;
87+
88+
} else {
89+
90+
return false;
91+
92+
}
93+
94+
}
95+
96+
/**
97+
* tempConversion
98+
*
99+
* Temperature calibration for SHT21 based on the datasheet:
100+
* https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/HTU-21D.pdf
101+
*
102+
* Formula can be tune depending on the SCK enclosure.
103+
*
104+
*
105+
* @param float $rawTemp
106+
* @return float Temperature in ºC
107+
*
108+
*/
109+
110+
public function tempConversion($rawTemp)
111+
{
112+
return round(-53 + 175.72 / 65536.0 * $rawTemp, 2);
113+
}
114+
115+
/**
116+
* humConversion
117+
*
118+
* Humidity calibration for SHT21 based on the datasheet:
119+
* https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/HTU-21D.pdf
120+
*
121+
* Formula can be tune depending on the SCK enclosure.
122+
*
123+
*
124+
* @param float $rawHum
125+
* @return float Rel. Humidity in %
126+
*
127+
*/
128+
129+
public function humConversion($rawHum)
130+
{
131+
return round(7 + 125.0 / 65536.0 * $rawHum, 2);
132+
}
133+
134+
/**
135+
* noiseConversion
136+
*
137+
* Noise calibration for SCK1.1 sound sensor. Converts mV in to dBs.
138+
* Based on a linear regresion from a lookup table (db.json) obtained after real measurements from our test facility.
139+
*
140+
*
141+
* @param float $rawSound
142+
* @return float noise as sound pressure in dB
143+
*
144+
*/
145+
146+
public function noiseConversion($rawSound)
147+
{
148+
$dbTable = json_decode(file_get_contents("./sensors/db.json"), true);
149+
return round(self::tableCalibration($dbTable, $rawSound), 2);
150+
}
151+
152+
/**
153+
* coConversion
154+
*
155+
* CO values rescaling. For obtaining ppm check:
156+
*
157+
* @param float $rawCO
158+
* @return float sensor resistance in KOhm
159+
*
160+
*/
161+
162+
public function coConversion($rawCO)
163+
{
164+
return round($rawCO / 1000, 2);
165+
}
166+
167+
/**
168+
* no2Conversion
169+
*
170+
* NO2 values rescaling. For obtaining ppm check:
171+
*
172+
* returns k0hm
173+
* @param float $rawNO2
174+
* @return float sensor resistance in KOhm
175+
*
176+
*/
177+
178+
public function no2Conversion($rawNO2)
179+
{
180+
return round($rawNO2 / 1000, 2);
181+
}
182+
183+
/**
184+
* lightConversion
185+
*
186+
* Light values rescaling.
187+
*
188+
* returns lux
189+
* @param float $rawLight
190+
* @return float light level in lux
191+
*
192+
*/
193+
194+
public function lightConversion($rawLight)
195+
{
196+
return round($rawLight / 10, 2);
197+
}
198+
199+
/**
200+
* batConversion
201+
*
202+
* Battery values rescaling.
203+
*
204+
* @param float $rawBat
205+
* @return float battery level in %
206+
*
207+
*/
208+
209+
210+
public function batConversion($rawBat)
211+
{
212+
return round($rawBat / 10, 2);
213+
}
214+
215+
/**
216+
* panelConversion
217+
*
218+
* Solar panel values rescaling.
219+
*
220+
* @param float $rawBat
221+
* @return float Tension in volts
222+
*
223+
*/
224+
225+
public function panelConversion($rawBat)
226+
{
227+
return round($rawBat / 100, 2);
228+
}
229+
230+
/**
231+
* isValidDateTimeString
232+
*
233+
* Check if a string is a valid time stamp
234+
*
235+
* @param string $str_dt
236+
* @return bool
237+
*
238+
*/
239+
240+
private function isValidDateTimeString($str_dt)
241+
{
242+
$date1 = DateTime::createFromFormat('Y-m-d G:i:s', $str_dt);
243+
$date2 = DateTime::createFromFormat('Y-m-d H:i:s', $str_dt);
244+
return $date1 && ($date1->format('Y-m-d G:i:s') == $str_dt || $date2->format('Y-m-d H:i:s') == $str_dt);
245+
}
246+
247+
/**
248+
* tableCalibration
249+
*
250+
* Calculates a point based on a linear regresion from a look up table
251+
*
252+
* @param array $refTable
253+
* @param float $rawValue
254+
* @return float
255+
*
256+
*/
257+
258+
private function tableCalibration($refTable, $rawValue)
259+
{
260+
for ($i = 0; $i < sizeof($refTable) - 1; $i++) {
261+
$prevValueRef = $refTable[$i][0];
262+
$nextValueRef = $refTable[$i + 1][0];
263+
if ($rawValue >= $prevValueRef && $rawValue < $nextValueRef) {
264+
$prevValueOutput = $refTable[$i][1];
265+
$nextValueOutput = $refTable[$i + 1][1];
266+
$result = self::linearRegression($rawValue, $prevValueOutput, $nextValueOutput, $prevValueRef, $nextValueRef);
267+
return $result;
268+
}
269+
}
270+
}
271+
272+
/**
273+
* linearRegression
274+
* *
275+
* @param float $valueInput
276+
* @param float $prevValueOutput
277+
* @param float $nextValueOutput
278+
* @param float $prevValueRef
279+
* @param float $nextValueRef
280+
* @return float
281+
*
282+
*/
283+
284+
private function linearRegression($valueInput, $prevValueOutput, $nextValueOutput, $prevValueRef, $nextValueRef)
285+
{
286+
$slope = ($nextValueOutput - $prevValueOutput) / ($nextValueRef - $prevValueRef);
287+
$result = $slope * ($valueInput - $prevValueRef) + $prevValueOutput;
288+
return $result;
289+
}
290+
291+
292+
293+
}
294+
295+
?>

0 commit comments

Comments
 (0)