Ending. The previous part .
Table of contents:
Let's talk about the software behind the window sensor. After that you will have a complete system with which you can already experiment.
Let me remind you that the server is a central, home unit that can communicate with the Internet via WiFi, and the client is a remote, out-of-window sensor that transmits data to the server via radio.
The source code for both server and client is here .
Source texts are provided with detailed comments.
Almost nothing needs to be configured on the client.
The radio transmitter nRF24L01 +, or rather the RadioHead library, requires specifying the server and client addresses. Addresses are provided in case you have more than one server and client. An address is just any integer. When a client sends a packet with data to the server, it indicates for which server the packet is intended. The server, knowing its own address, in turn, determines whether this packet is intended for it.
Therefore, SERVER_ADDRESS
on the server and on the client must match, but the CLIENT_ADDRESS
for different clients must be different. In other words, if in the future you connect another new sensor to our system, then CLIENT_ADDRESS
will need to be changed for it.
// #define SERVER_ADDRESS 10 #define CLIENT_ADDRESS 20 // !!!
Radio number RF_CHANNEL
should be the same for all. The default is 2. I changed the default number, you can choose any other.
// . #define RF_CHANNEL 73
The settings of the voltmeter to measure the battery supply voltage must be changed:
// , const float r1 = 100400; // 100K const float r2 = 9960; // 10K // // http://localhost/arduino-secret-true-voltmeter/ const float typVbg = 1.082; // 1.0 -- 1.2
To save energy, the Lightweight low power library for Arduino is used .
Here are my measurements of actual consumption for the Arduino Pro Mini with this one:
The client makes measurements of temperature, humidity and voltage, packs it all into a data structure, sends data to the server and “falls asleep”. If there were errors during the transfer, then the transfer is immediately repeated.
The server (central, home unit), in turn, receives data, acknowledges receipt and processes it.
After the work done, we have a fully functional construction of the weather station. But now such meteorological stations are a dime a dozen, local crafts, this is no longer fashionable. We have the internet of things.
Therefore, let's talk about how to access these your Internet sites, attach to our weather station a database and a web-face to it.
Task setting for "webcam":
In this case, we need a hosting with support for Apache, PHP and MySQL with the module mysqli. And these conditions are satisfied by almost any hosting on planet Earth. Or, instead of hosting, your computer will play the role of a server, connected to a home network router and having Internet access.
Let's start from the very beginning, namely from designing and creating a database.
The database is your world and you can study it for a long time, so we will only briefly touch on those things that are directly necessary for us.
All SQL scripts are in the weather-station/server/php-sql/
directory
Where does the design of the database begin? With a logical and physical representation.
Logical representation or database schema:
The physical scheme is based on a specific DBMS and data types. Easier to sort on a specific example. The SQL script make_tables.sql
reveals the logical and physical schemes.
Each table should have a type field
id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT
The field name may differ in different databases, but the meaning is the same - it is a unique identifier, a record key. For the future, if you see a database in the tables of which there is no such counter, you should know that this database was designed by a person who is very far from programming, most likely a humanist.
Data from the same type of sensors is stored in one table, for sensors of another type we create another table. This slightly complicates the database and PHP binding to it, but it simplifies the expansion or modification of the entire system in the future.
Our project has two tables. The arduino_dht
table stores data from the DHT type sensor (s) (temperature, humidity), and the data from the BMP type sensor (temperature, pressure) is stored in the arduino_bmp
table. If you want to have, for example, a gas sensor or a motion detector in the future, then create additional tables, do not be lazy. If you connect another sensor like DHT11 or DHT22, then you do not need to create an additional table, use the table arduino_dht
. I hope the principle is clear: a separate physical entity - a separate table.
If data from several sensors of the same type are stored in the table, how can they be distinguished? For this, a field is entered in each table.
idSensor INTEGER
In fact, this is the CLIENT_ADDRESS
that we CLIENT_ADDRESS
in the client/client.ino
for each instance of the remote client sensor and in server/server.ino
for the sensor that is connected directly to the server - the central unit.
In industrial systems, there must be another table — the correspondences of idSensor
and its verbal, human-readable description. For example, a sensor with idSensor
= 2 is “Temperature, humidity in the apartment” , etc. But in our project we will not complicate, just remember that:
idSensor
, it is CLIENT_ADDRESS
, equal to 11 - this is the home sensor on the server - the central unit,idSensor
, also CLIENT_ADDRESS
as CLIENT_ADDRESS
, equal to 20 is the first (in our project and the only) remote sensor client.Further. The following data is stored in the tables:
As you can see the tables arduino_dht
and arduino_bmp
very similar, the only difference is in the fields of pressure and humidity, and there is a desire to dump everything in one pile (table). But the first normal form does not allow it to do so, a lot of novice programmers tried to get around it, but none of them succeeded, and we will not. This is how not to notice the law of the world, for the time being it may well turn out.
The arduino_error_log
table arduino_error_log
useful when debugging - this is a log of errors and other system messages.
Creating a database and its user with the rights described in make_db.sql
-- . config.php -- CREATE DATABASE IF NOT EXISTS db_weather; -- CREATE USER 'u_weather'@'localhost' IDENTIFIED BY '***PASSWORD***'; GRANT ALL ON db_weather.* TO 'u_weather'@'localhost';
This is done once, the database name and user name can come up with your own. And what exactly needs to be done is to set your password.
All web interface settings are stored in config.php
. Modify it according to your database settings.
Set your time zone in PHP format
date_default_timezone_set('Europe/Prague');
All available time zones are described here .
Set your secret key for access (as a number) which must match the SOURCE_KEY
constant from the SOURCE_KEY
sketch
$access_key = '***KEY***';
In our web server there is no authorization, login by password, this would complicate the whole structure. For the prototype, this is not necessary. Therefore, all protection is based on the robots.txt
file, the absence of index.php
and this secret key for access.
The main PHP script, weather.php
accepts a simple HTTP GET request with data and stores it in the appropriate database tables. If the $access_key
key $access_key
not match, then the request will be rejected.
The weather-view.php
used to view data tables and contains hyperlinks to other web interface scripts. Call him like this
http:// / /weather-view.php?k= access_key
for example
http://yourhost/iot/weather-view.php?k=12345
weather-view.php
displays simple weather-view.php
where you need to remember that:
The function.php
script contains functions common to all PHP scripts.
The script chart-dht.php
is responsible for drawing charts using Google Charts . Here, for example, is a graph of the power supply voltage of an out-of-window sensor. The voltage rises on a sunny day at the expense of the solar battery and then the power supply on batteries gradually discharges.
export-dht.php
exports data from MySQL database tables to a CSV file. For further import and analysis in spreadsheets.
export-voltage.php
exports the power supply voltage of the window sensor from the MySQL database to a CSV file. Useful for debugging.
truncate.php
clears all tables, i.e. deletes all our data. Useful for debugging. There are no references to this script from weather-view.php
, so you need to call it via a direct link in the address bar of the browser indicating $access_key
.
When receiving data, the mysqli_real_escape_string()
function is commonly used to prevent incorrect values ​​from getting into the database.
Do not forget to put a robots.txt
in the root of your site to prevent it from entering the search engines.
And now we return to the server.ino
sketch, to the part that connects to the WiFi access point and sends the data to the web server.
As I already wrote, I could not find a normal library for Arduino to control the ESP8266 module using AT commands, I had to “collective farm” myself. Let me remind you also that you will have to flash the firmware of a certain version in ESP8266-01. And now that everything is ready, let us analyze how it works.
To access the web server in a server.ino
sketch, server.ino
need to change these constants.
const String DEST_HOST = " "; // habr.com const String DEST_PORT = " "; // 80 const String DEST_URL = "/ /weather.php"; const String SOURCE_KEY= " "; // $access_key config.php
In server.ino
in the void setup()
function, the ESP8266 is first switched to Station mode, i.e. he starts working as a wifi client
espSendCmd(«AT+CWMODE_CUR=1», «OK», 3000);
and then follows the connection to the access point
espState = espConnectToWiFi();
If the connection does not occur, the attempt is repeated (once)
if ( espState != ESP_SUCCESS ) { delay(5000); Serial.println("WiFi not connected! Try again ..."); espConnectToWiFi(); }
Then select a single TCP / IP connection mode.
espSendCmd("AT+CIPMUX=0", "OK", 2000);
When sending data from DHT type sensors to a web server, a function is used indicating the type of data as type=dht
espSendData( "type=dht&t=" + String(dhtData.temperature) + "&h=" + String(dhtData.humidity) + "&v=" + String(dhtData.voltage) + "&s=" + String(CLIENT_ADDRESS) );
When sending data from BMP sensors to a web server, the same function is used with the indication of the data type=bmp
as type=bmp
espSendData( "type=bmp&t=" + String(temperature_bmp) + "&p=" + String(pressure_bmp) + "&s=" + String(CLIENT_ADDRESS) );
At the input, the espSendData()
function takes an HTTP GET request string and sends it to its destination to a web server.
Inside itself, espSendData()
checks the availability of the ESP module by sending it an “AT” command, then it checks the connection to WiFi and reconnects if necessary. Then the data is sent and the TCP connection is closed.
Nowadays, when everyone can already blink an LED, no meteorological station will surprise anyone. But if the odd job is able to communicate with the server via WiFi, has a web-muzzle and a mobile application, then this is already something! The server here means of course the application server, i.e. in our case, this is PHP binding and MySQL. Not getting the cherries on the cake, namely the application for Android writing of which we now deal with.
The architecture of the entire weather station software platform is simple:
On the Android device screen, we will display the current, most recent sensor readings.
The question that needs to be resolved first is how the data will be transferred from the web server to the Android application.
There is no need to invent anything, everything has already been invented for us - this is HTTP GET and JSON.
In our case, a simple GET request to the web server can be compiled and debugged manually, while the Android application is not yet ready.
Java and Android have ready-made libraries for processing data in JSON format. JSON text format is readable by humans, which is useful for debugging.
In order to generate the current data from the weather station sensors, create a new last-data-to-json.php script on the web server on the web server.
Calling the script:
http://<>/last-data-to-json.php?k=<access_key>
where <access_key>
, as we remember, is the secret key to access the database.
Sample response in JSON format:
{ "DHT 11":{ "idSensor":"11", "dateCreate":"2016-04-20 18:06:03", "temperature":"19", "humidity":"26", "voltage":"5.01" }, "DHT 20":{ "idSensor":"20", "dateCreate":"2016-04-18 07:36:26", "temperature":"10", "humidity":"26", "voltage":"3.7" }, "BMP 11":{ "idSensor":"11", "dateCreate":"2016-04-20 18:06:22", "temperature":"19", "pressure":"987.97" } }
It is necessary to remind that we have 3 sensors. Their ID and type (DHT or BMP) are hard-coded throughout the weather station code. This way of hardcore coding is ideologically incorrect, but for a kneeled prototype (where a quick and easy solution is needed) this is a reasonable compromise.
$idSensor = 11; // DHT $idSensor = 11; // BMP $idSensor = 20; // DHT
The last-data-to-json.php
takes from the database the latest data from these different types of sensors and packs it in JSON format. A sample of data from the database "from the end" is performed in this way:
SELECT <> FROM <> ORDER BY id DESC LIMIT 1;
Now we will write a simple application for Android, which requests, receives, decodes JSON-data and displays information on the screen.
Our Android application will be as simple as possible, only the very essence of the technology. Further around this "skeleton" it will already be possible to turn various "prettiness".
Here is a screenshot of what should end up.
As you can see, the UI is just spartan, based on LinearLayout, nothing superfluous.
At the top of the TextView shows the ID of the sensors and their meteorological data. The “Refresh” button initiates a repeated request to the web server. Next in EditText is the only setting of the program - this is the URL of the request
http://< >/last-data-to-json.php?k=<access_key>
What should be noted?
In the manifest, add lines that allow the Internet and check the status of the network connection:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
Working with the network and receiving data from the website is as follows.
Use AsyncTask to create a background task separately from the main user interface thread. This background task takes the request URL and uses it to create an HttpURLConnection
.
After the connection is established, AsyncTask loads the contents of the web page (JSON) as an InputStream. Next, the InputStream is converted to a string, which is decoded using JSONObject and displayed in the user interface by the onPostExecute()
method.
In MainActivity.java, change the URL to your:
private static final String defUrl = "http://host/dir/last-data-to-json.php?k=< >";
It will be used by default when you first start the Android application.
Well, something has already earned. Then you can optimize something, replace something, you can throw everything out, but also borrow something.
A separate big sore point is energy consumption . I recommend reading comments on posts where there are a lot of practical advice.
To infinity ... and beyond.
Source: https://habr.com/ru/post/426019/
All Articles