├── .gitignore
├── Minimal (v0.1)
├── android
│ └── WeatherStation
│ │ ├── .idea
│ │ ├── .name
│ │ ├── copyright
│ │ │ └── profiles_settings.xml
│ │ ├── encodings.xml
│ │ ├── modules.xml
│ │ ├── compiler.xml
│ │ ├── misc.xml
│ │ └── workspace.xml
│ │ ├── res
│ │ ├── values
│ │ │ └── strings.xml
│ │ ├── drawable-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-ldpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ └── layout
│ │ │ └── main.xml
│ │ ├── gen
│ │ └── com
│ │ │ └── droid
│ │ │ └── ws
│ │ │ ├── R.java
│ │ │ ├── Manifest.java
│ │ │ └── BuildConfig.java
│ │ ├── WeatherStation.iml
│ │ ├── ant.properties
│ │ ├── AndroidManifest.xml
│ │ ├── build.xml
│ │ └── src
│ │ └── com
│ │ └── droid
│ │ └── ws
│ │ └── MainActivity.java
├── documents
│ ├── WeatherStation.fzz
│ └── media
│ │ ├── full_schematic.png
│ │ ├── android_full_screen.png
│ │ └── power_supply_schematic.svg
└── arduino
│ └── WeatherStation
│ └── WeatherStation.ino
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | out
2 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/.name:
--------------------------------------------------------------------------------
1 | WeatherStation
--------------------------------------------------------------------------------
/Minimal (v0.1)/documents/WeatherStation.fzz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/documents/WeatherStation.fzz
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/documents/media/full_schematic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/documents/media/full_schematic.png
--------------------------------------------------------------------------------
/Minimal (v0.1)/documents/media/android_full_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/documents/media/android_full_screen.png
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | WeatherStation
4 |
5 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/android/WeatherStation/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/android/WeatherStation/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/android/WeatherStation/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimircea/WeatherStation/HEAD/Minimal (v0.1)/android/WeatherStation/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/gen/com/droid/ws/R.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.droid.ws;
4 |
5 | /* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */
6 | public final class R {
7 | }
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/gen/com/droid/ws/Manifest.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.droid.ws;
4 |
5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
6 | public final class Manifest {
7 | }
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/gen/com/droid/ws/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.droid.ws;
4 |
5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
6 | public final class BuildConfig {
7 | public final static boolean DEBUG = Boolean.parseBoolean(null);
8 | }
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/WeatherStation.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/ant.properties:
--------------------------------------------------------------------------------
1 | # This file is used to override default values used by the Ant build system.
2 | #
3 | # This file must be checked into Version Control Systems, as it is
4 | # integral to the build system of your project.
5 |
6 | # This file is only used by the Ant script.
7 |
8 | # You can use this to override default values such as
9 | # 'source.dir' for the location of your java source folder and
10 | # 'out.dir' for the location of your output folder.
11 |
12 | # You can also use it define how the release builds are signed by declaring
13 | # the following properties:
14 | # 'key.store' for the location of your keystore and
15 | # 'key.alias' for the name of the key to use.
16 | # The password will be asked during the build when you use the 'release' target.
17 |
18 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WeatherStation
2 | Implement an Arduino based WiFi "WeatherStation" with Android user interface for less than 30 EUR.
3 |
4 | This project shows how to implement a cheap (under 30 EUR) Weather Station with the help of an Arduino board (as example we use Arduino Pro Mini but other Arduino boards work as well).
5 | We use the ESP8266 WiFi module, and Arduino Pro Mini, a DHT22 humidity and temperature sensor and a few other cheap components.
6 |
7 | ## Dependencies
8 | This project requires the [DHTLib](https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib) and [Arduino-ESP8266](https://github.com/dimircea/Arduino-ESP8266) Arduino libraries.
9 |
10 | ## Hardware Design
11 | The hardware design is made by using [Fritzing](fritzing.org). The Breadboard and Schematic is ready, but the PCB Layout (for etching) is currently work in progress. All the required files are available under the `documents` folder.
12 |
13 | ## Software Design
14 | The user interface is implemented as an Android application, and the sensors data is obtained via WiFi.
15 | We only tested it with Android 4.3.1 (API 18), 4.4.2 (API 19) and 5.0.1 (API 21), and we know that it does not work with Android 2.3.3 (API 10). You are welcome to test other Android versions and report if it works or not.
16 |
17 | The WeatherSensor node uses Arduino code.
18 |
19 | ## Want to Contribute ?
20 | You are welcome to contribute! Please contact me: dimircea[at]gmail.com.
21 |
22 | ## License
23 | All the code and examples are available under the [GNU General Public License](http://www.gnu.org/licenses/gpl.html)
24 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
29 |
30 |
31 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
56 |
57 |
69 |
70 |
71 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/arduino/WeatherStation/WeatherStation.ino:
--------------------------------------------------------------------------------
1 | // Arduino pin number used for the communication with DHT22 sensor.
2 | // A custom 1-Wire communication protocol is used for this module.
3 | // See: https://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
4 | #define DHT22_PIN 9
5 |
6 | // pins number for WiFi enabled/disabled LEDs
7 | #define WIFI_DISABLED_LED_PIN 7
8 | #define WIFI_ACTIVE_LED_PIN 8
9 | // arduino pin used to connect to CH_PD (Power Down) WiFi module pin
10 | #define WIFI_CH_PD_PIN 2
11 | // arduino pin used to connect to RESET WiFi module pin
12 | #define WIFI_RESET_PIN 3
13 | // interval-time (in ms) to check WiFi module (5s)
14 | #define WIFI_CHECK_TIME 5000
15 | // interval-time (in ms) to restart the WiFi ESP8266 module
16 | // in case that it become unresponsive (hardware reset required!)
17 | #define WIFI_RESTART_TIMEOUT 30000
18 |
19 | #include
20 | #include ;
21 |
22 | // keep tracking the average temperature and humidity
23 | // values, starting with last system reset
24 | float avgTemperature = 0;
25 | float avgHumidity = 0;
26 | // used to compute the averate temperature value
27 | unsigned long avgDhtStep = 1;
28 |
29 | // data template for sensors
30 | const char SENSORS_DATA_TEMPLATE[] PROGMEM =
31 | "{\"temperature\": %s, \"avgTemperature\": %s, \"humidity\": %s, \"avgHumidity\": %s, \"voltage\": %s, \"freeRam\": %d}";
32 |
33 | // DHT22 sensor controller class
34 | dht dht22;
35 |
36 | // ESP8266 WiFi module controller
37 | ESP8266 esp( Serial);
38 |
39 | enum class Command {
40 | GET_ALL_SENSORS_DATA = 97
41 | };
42 |
43 | /**
44 | * Check if ESP8266 (WiFi) module is active.
45 | */
46 | boolean checkWiFi() {
47 | // try to communicate with ESP8266 module
48 | if( esp.at() == ESP8266::Error::NONE) {
49 | digitalWrite( WIFI_DISABLED_LED_PIN, LOW);
50 | digitalWrite( WIFI_ACTIVE_LED_PIN, HIGH);
51 | return true;
52 | } else {
53 | digitalWrite( WIFI_ACTIVE_LED_PIN, LOW);
54 | digitalWrite( WIFI_DISABLED_LED_PIN, HIGH);
55 | return false;
56 | }
57 | }
58 |
59 | /**
60 | * Prepare Wifi Communication:
61 | * - prepare pins for the ESP8266 module
62 | * - hardware reset ESP8266 module
63 | */
64 | void setupWiFi() {
65 | // set pins used for WiFi status LEDs as OUTPUT
66 | pinMode( WIFI_ACTIVE_LED_PIN, OUTPUT);
67 | pinMode( WIFI_DISABLED_LED_PIN, OUTPUT);
68 | // Arduino pin connected to ESP8266 CH_PD pin is set to OUTPUT.
69 | // To keep the module active, this pin must be kept HIGH.
70 | pinMode( WIFI_CH_PD_PIN, OUTPUT);
71 | digitalWrite( WIFI_CH_PD_PIN, HIGH);
72 | // Arduino pin connected to ESP8266 RESET pin is set to OUTPUT.
73 | // To avoid random resents, we keep this HIGH.
74 | pinMode( WIFI_RESET_PIN, OUTPUT);
75 | digitalWrite( WIFI_RESET_PIN, HIGH);
76 | // perform a hardware reset (ESP8266 RESET pin goes LOW)
77 | digitalWrite( WIFI_RESET_PIN, LOW);
78 | delay( 200);
79 | // allow ESP8266 module to boot
80 | digitalWrite( WIFI_RESET_PIN, HIGH);
81 | // baud 115200, communication with ESP8266 module
82 | Serial.begin( 115200);
83 | // wait for the ESP8266 module to start, after the forced hardware reset.
84 | // We check the wifi state once a second, until the ESP8266 WiFi module responds.
85 | while( !checkWiFi()) {
86 | delay( 1000);
87 | };
88 | // start UDP connection - wait on all ports
89 | esp.atCipstartUdp();
90 | }
91 |
92 | /**
93 | * Read the voltage which powes the system on the 5V line.
94 | * This is possible by using the internal voltage reference
95 | * available in some ATmega MCUs such as ATmega328p
96 | */
97 | float getVcc() {
98 | long result;
99 | // read 1.1V reference against AVcc
100 | ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
101 | // wait for Vref to settle
102 | delay(2);
103 | // convert
104 | ADCSRA |= _BV(ADSC);
105 | while (bit_is_set(ADCSRA,ADSC));
106 | result = ADCL;
107 | result |= ADCH<<8;
108 | // Back-calculate AVcc in mV
109 | result = 1103700L / result;
110 | // return response in volts
111 | return result / 1000.0;
112 | }
113 |
114 | /**
115 | * Update the data (perform new reading) for
116 | * the DHT22 temperature and humidity sensor.
117 | * After calling this method, the temperature
118 | * and humidity values are available by reading
119 | * DHT.temperature and DHT.humidity.
120 | */
121 | void updateDHTData() {
122 | if ( dht22.read22( DHT22_PIN) == DHTLIB_OK) {
123 | avgTemperature = ( avgTemperature * (avgDhtStep - 1) + dht22.temperature) / (float)avgDhtStep;
124 | avgHumidity = ( avgHumidity * (avgDhtStep - 1) + dht22.humidity) / (float)avgDhtStep;
125 | }
126 | }
127 |
128 | /**
129 | * Get the data string using a pattern and the parameter values.
130 | */
131 | void createSensorsDataFromTemplate( char *&data) {
132 | char buffTemp[7] = {0}, buffAvgTemp[7] = {0}, buffAvgHum[7] = {0},
133 | buffHum[7] = {0}, buffVcc[5] = {0}, tmpl[140] = {0};
134 | char *pTmpl = tmpl;
135 | uint8_t templateLen = -1;
136 | // read template from PROGMEM
137 | getPMData( SENSORS_DATA_TEMPLATE, pTmpl, templateLen);
138 | // create data string from template by replacing
139 | // parameters with their actual values from sensors
140 | sprintf( data, pTmpl,
141 | dtostrf( dht22.temperature, 6, 1, buffTemp),
142 | dtostrf( avgTemperature, 6, 1, buffAvgTemp),
143 | dtostrf( dht22.humidity, 6, 1, buffHum),
144 | dtostrf( avgHumidity, 6, 1, buffAvgHum),
145 | dtostrf( getVcc(), 4, 2, buffVcc),
146 | getFreeMCUMemory());
147 | }
148 |
149 | /**
150 | * Process requests (with or without parameters).
151 | * The commands are defined as constants, and
152 | * have the pattern: CMD_command_name.
153 | * @param data
154 | * the data to be processed (+IPD:
155 | */
156 | void processRequest( char *data) {
157 | char progmemData[150] = {0};
158 | char *pData = progmemData;
159 | // first char represents the command
160 | char cmd = *(data);
161 | switch ( (Command)cmd) {
162 | case Command::GET_ALL_SENSORS_DATA:
163 | createSensorsDataFromTemplate( pData);
164 | esp.atCipsend( pData);
165 | break;
166 | default:
167 | // nothing to do ...
168 | break;
169 | }
170 | }
171 |
172 | /**
173 | * Prepare ths system. This method is called when the system starts.
174 | */
175 | void setup() {
176 | // setup WiFi - ESP8266 module
177 | setupWiFi();
178 | // Get initial data (temperature & humidity) from DHT22 sensor.
179 | // Add a 2 seconds delay to prevent timeouts from the sensor.
180 | delay( 2000);
181 | updateDHTData();
182 | }
183 |
184 | /**
185 | * Loop method which executes again and again.
186 | */
187 | void loop() {
188 | // Incomming real data via IPD is 1 byte (the command identifier byte).
189 | // The first bytes are: "+IPD,n:", followed by the real data
190 | char data[10] = {0}, *ipdData = data;
191 | // Incomming data from ESP8266 module
192 | // Lengt must be greater than 7 bytes ("+IPD,n:")
193 | if ( Serial.available() > 7) {
194 | // process request received from UDP port: (wait 50ms for data)
195 | if ( esp.ipd( ipdData) == ESP8266::Error::NONE) {
196 | // process the request
197 | processRequest( ipdData);
198 | }
199 | }
200 | // a small delay before checking againd for WiFi incomming data
201 | delay( 25);
202 | }
203 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/src/com/droid/ws/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.droid.ws;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import java.net.InetAddress;
6 | import android.net.wifi.WifiManager;
7 | import android.net.DhcpInfo;
8 | import java.io.IOException;
9 | import android.content.Context;
10 | import android.util.Log;
11 | import android.view.WindowManager;
12 | import android.view.Window;
13 |
14 | import java.net.DatagramSocket;
15 | import java.net.DatagramPacket;
16 | import java.text.SimpleDateFormat;
17 | import java.util.Date;
18 |
19 | import android.widget.*;
20 | import org.json.JSONException;
21 | import org.json.JSONObject;
22 | import android.view.View;
23 |
24 |
25 | public class MainActivity extends Activity {
26 | int udpPort = 1025;
27 | DatagramSocket socket;
28 |
29 | TextView sensorsDataReceivedTimeTextView;
30 | TextView temperatureValueTextView;
31 | TextView avgTemperatureValueTextView;
32 | TextView humidityValueTextView;
33 | TextView avgHumidityValueTextView;
34 | TextView voltageValueTextView;
35 | TextView freeRamValueTextView;
36 |
37 | Button refreshButton;
38 | Switch preventScreenLockSwitch;
39 |
40 | boolean appInBackground = false;
41 | boolean doneEditing = true;
42 |
43 | @Override
44 | protected void onResume() {
45 | super.onResume();
46 | appInBackground = false;
47 | }
48 |
49 | @Override
50 | protected void onPause() {
51 | super.onPause();
52 | appInBackground = true;
53 | }
54 |
55 | /**
56 | * Called when the activity is first created.
57 | */
58 | @Override
59 | public void onCreate( Bundle savedInstanceState) {
60 | super.onCreate(savedInstanceState);
61 | setContentView(R.layout.main);
62 | // disable auto turn screen off feature
63 | final Window window = getWindow();
64 | window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); // Turn screen on if off
65 | window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // Keep screen on
66 |
67 | sensorsDataReceivedTimeTextView = (TextView) findViewById(R.id.sensorsDataReceivedTimeTextView);
68 | temperatureValueTextView = (TextView) findViewById(R.id.temperatureValueTextView);
69 | avgTemperatureValueTextView = (TextView) findViewById(R.id.avgTemperatureValueTextView);
70 | humidityValueTextView = (TextView) findViewById(R.id.humidityValueTextView);
71 | avgHumidityValueTextView = (TextView) findViewById(R.id.avgHumidityValueTextView);
72 | voltageValueTextView = (TextView) findViewById(R.id.voltageValueTextView);
73 | freeRamValueTextView = (TextView) findViewById(R.id.freeRamValueTextView);
74 | refreshButton = (Button) findViewById(R.id.refreshButton);
75 | preventScreenLockSwitch = (Switch) findViewById(R.id.preventScreenLockSwitch);
76 |
77 | // request sensors data from WoT sensors node
78 | (new Thread(new Runnable() {
79 | @Override
80 | public void run() {
81 | try {
82 | socket = new DatagramSocket(udpPort);
83 | while (true) {
84 | if (appInBackground) {
85 | continue;
86 | }
87 | try {
88 | sendUdpData(Commands.GET_ALL_SENSORS_DATA, null);
89 | Thread.sleep(10000);
90 | } catch (Exception e) {
91 | e.printStackTrace();
92 | }
93 | }
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | }
97 | }
98 | })).start();
99 |
100 | // listen for data from requesting data from WoT sensors node
101 | (new Thread(new Runnable() {
102 | @Override
103 | public void run() {
104 | while (true) {
105 | if (appInBackground) {
106 | continue;
107 | }
108 | DatagramPacket udpPacket = receiveUdpData();
109 | if (udpPacket == null) {
110 | continue;
111 | }
112 | String udpPacketData = new String( udpPacket.getData());
113 | try {
114 | JSONObject jsonObj = new JSONObject(udpPacketData);
115 | updateUserInterface( jsonObj);
116 | } catch ( JSONException e) {
117 | e.printStackTrace();
118 | }
119 | }
120 | }
121 | })).start();
122 |
123 | refreshButton.setOnClickListener(new View.OnClickListener() {
124 | public void onClick(View v) {
125 | // request data from WoT sensors node
126 | (new Thread(new Runnable() {
127 | @Override
128 | public void run() {
129 | try {
130 | sendUdpData( Commands.GET_ALL_SENSORS_DATA, null);
131 | } catch (Exception e) {
132 | e.printStackTrace();
133 | }
134 | }
135 | })).start();
136 | }
137 | });
138 |
139 | preventScreenLockSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
140 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
141 | if (isChecked) {
142 | window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
143 | } else {
144 | getWindow().clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
145 | }
146 | }
147 | });
148 | }
149 |
150 | void updateUserInterface( final JSONObject jsonObj) {
151 | try {
152 | final double temperature = jsonObj.getDouble("temperature");
153 | final double avgTemperature = jsonObj.getDouble("avgTemperature");
154 | final double humidity = jsonObj.getDouble("humidity");
155 | final double avgHumidity = jsonObj.getDouble("avgHumidity");
156 | final double voltage = jsonObj.getDouble("voltage");
157 | final int freeRam = jsonObj.getInt("freeRam");
158 |
159 | sensorsDataReceivedTimeTextView.post(new Runnable() {
160 | public void run() {
161 | SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
162 | sensorsDataReceivedTimeTextView.setText(dateFormat.format(new Date()));
163 | }
164 | });
165 | temperatureValueTextView.post(new Runnable() {
166 | public void run() {
167 | temperatureValueTextView.setText(String.valueOf(temperature) + "°C");
168 | }
169 | });
170 | avgTemperatureValueTextView.post(new Runnable() {
171 | public void run() {
172 | avgTemperatureValueTextView.setText(String.valueOf(avgTemperature) + "°C");
173 | }
174 | });
175 | humidityValueTextView.post(new Runnable() {
176 | public void run() {
177 | humidityValueTextView.setText(String.valueOf(humidity) + "%");
178 | }
179 | });
180 | avgHumidityValueTextView.post(new Runnable() {
181 | public void run() {
182 | avgHumidityValueTextView.setText(String.valueOf(avgHumidity) + "%");
183 | }
184 | });
185 | voltageValueTextView.post(new Runnable() {
186 | public void run() {
187 | voltageValueTextView.setText(String.valueOf(voltage) + "V");
188 | }
189 | });
190 | freeRamValueTextView.post(new Runnable() {
191 | public void run() {
192 | freeRamValueTextView.setText(String.valueOf(freeRam) + "Bytes");
193 | }
194 | });
195 | } catch (JSONException e) {
196 | e.printStackTrace();
197 | }
198 | }
199 |
200 | InetAddress getBroadcastAddress() throws IOException {
201 | WifiManager wifi = (WifiManager)getSystemService( Context.WIFI_SERVICE);
202 | DhcpInfo dhcp = wifi.getDhcpInfo();
203 | // no DHCP info...can't do nothing more
204 | if ( dhcp == null) {
205 | return null;
206 | }
207 | int ipAddress = dhcp.gateway;
208 | byte[] ipQuads = new byte[4];
209 | ipQuads[0] = (byte)(ipAddress & 0xFF);;
210 | ipQuads[1] = (byte)((ipAddress >> 8) & 0xFF);
211 | ipQuads[2] = (byte)((ipAddress >> 16) & 0xFF);
212 | ipQuads[3] = (byte)((ipAddress >> 24) & 0xFF);
213 |
214 | /* 192.168.4.1 = [ -64, -88, 4, 1] */
215 | return InetAddress.getByAddress( ipQuads);
216 | }
217 |
218 | void sendUdpData( Commands cmd, byte[] params) {
219 | try {
220 | final DatagramPacket packet;
221 | int paramsLength = ( params != null ? params.length : 0);
222 | byte data[] = new byte[paramsLength + 1];
223 | byte command[] = new byte[1];
224 | command[0] = cmd.getValue();
225 | System.arraycopy( command, 0, data, 0, command.length);
226 | if ( params != null) {
227 | System.arraycopy(params, 0, data, 1, params.length);
228 | }
229 | packet = new DatagramPacket( data, data.length,
230 | getBroadcastAddress(), udpPort);
231 | socket.send( packet);
232 | } catch( IOException e){
233 | e.printStackTrace();
234 | }
235 | }
236 |
237 | DatagramPacket receiveUdpData() {
238 | try {
239 | byte[] data = new byte[1024];
240 | DatagramPacket packet = new DatagramPacket( data, data.length);
241 | if ( socket == null) {
242 | return null;
243 | }
244 | socket.receive(packet);
245 | Log.i("HD:receiveUdpData", new String( packet.getData()).trim());
246 | return packet;
247 | } catch( IOException e){
248 | Log.e("HD:receiveUdpData", "Error occurred when receiving UDP data on port: " + udpPort);
249 | e.printStackTrace();
250 | return null;
251 | }
252 | }
253 |
254 | /**
255 | * Define the set of commands which can be send to the WoT sensor(s) node.
256 | */
257 | enum Commands {
258 | GET_ALL_SENSORS_DATA ( (byte)97);
259 | private final byte id;
260 | Commands( byte id) { this.id = id; }
261 | public byte getValue() { return id; }
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 |
14 |
18 |
25 |
32 |
33 |
34 |
37 |
43 |
49 |
50 |
51 |
55 |
56 |
59 |
65 |
71 |
72 |
73 |
77 |
78 |
81 |
87 |
92 |
93 |
94 |
98 |
99 |
102 |
108 |
113 |
114 |
115 |
119 |
120 |
123 |
129 |
135 |
136 |
137 |
141 |
142 |
145 |
146 |
152 |
158 |
159 |
160 |
164 |
169 |
174 |
175 |
176 |
180 |
188 |
189 |
190 |
193 |
199 |
205 |
206 |
207 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/documents/media/power_supply_schematic.svg:
--------------------------------------------------------------------------------
1 |
2 |
1473 |
--------------------------------------------------------------------------------
/Minimal (v0.1)/android/WeatherStation/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | android-19
10 |
11 |
12 |
13 |
14 |
15 | @android:style/Theme.Holo
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 | true
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 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 | $PROJECT_DIR$
641 | true
642 |
643 | bdd
644 |
645 | DIRECTORY
646 |
647 | false
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 | 1450129596337
697 |
698 | 1450129596337
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
957 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
980 |
981 |
982 |
983 |
984 |
985 |
986 |
987 |
988 |
989 |
990 |
991 |
992 |
993 |
994 |
995 |
996 |
997 |
998 |
999 |
1000 |
1001 |
1002 |
1003 |
1004 |
1005 |
1006 |
1007 |
1008 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 |
1015 |
1016 | Android
1017 |
1018 |
1019 |
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 |
1028 |
1029 |
1030 |
1031 |
1032 |
1033 |
1034 |
1035 |
1036 |
1037 |
1038 |
1039 | Android 4.4.2 Google APIs
1040 |
1041 |
1042 |
1043 |
1044 |
1045 |
1046 |
1047 |
1048 |
1049 |
1050 |
1051 | Android|WeatherStation
1052 |
1053 |
1054 |
1055 |
1056 |
1057 |
1058 |
1059 |
1060 |
1061 |
1062 |
1063 | 1.7
1064 |
1065 |
1066 |
1067 |
1068 |
1069 |
1070 |
1071 |
1072 |
1073 |
1074 |
1075 |
1076 |
1077 |
1078 |
1079 |
1080 |
1081 |
1082 |
1083 |
1084 |
1085 |
1086 |
--------------------------------------------------------------------------------