Initial user evaluation: https://www.slideshare.net/PietroSpadaccino/forests-safe-project-iot-sapienza-142816402
Minimum viable product: https://www.slideshare.net/LeonardoSalvucci1/forest-safe-mvp-148878834
Final product: https://www.slideshare.net/PietroSpadaccino/forest-safe-final-presentation-iotsapienza-148911701
1 OverviewOur project is aimed at all those people who, despite not having much money and time for maintenance, want to find a good solution for monitoring and preventing fires in small and medium areas.
The device is small, portable and cheap, able to communicate and warn you in real-time. It does not require any installation by specialized personnel, moreover, you can move it to your liking at any time. It has few sensors, it consumes very little battery, reducing maintenance.
We use a simple and reliable model to assess the risk of fire, communicating the degree of risk in real-time.
2 ArchitectureWe have chosen all reliable and stable technologies to offer a service up to expectations.
3 Prevention Model
3.1 Causes
There’re three elements that are essential for a fire to start. The first is Oxygen, which supply can increase in case of wind, however, this affects the danger level of a fire once started rather than the probability of the fire to start, so in our prevention model we'll not consider wind. Then, there are the fuel and the heat that brings the fuel to its ignition point.
DEAD FUEL MOISTURE
The dead fuel moisture level is very important because it conditions the ignition point. The dead fuel moisture, in turn, depends on the relative humidity of the air. The air and the fuel indeed exchange moisture until they reach equilibrium.
The velocity with which the moisture level changes depends also on the size of the dead fuel. For this purpose the US National Fire Danger Rating System introduced four classes based on time-lags, where each time-lag is identified by the time needed for that kind of fuel to reach 63% of equilibrium between its initial moisture level and the air moisture level:
- 1 hour → diameter < 0.6 cm (herbaceous)
- 10 hours → 0.6 < diameter < 2.5 cm (twigs)
- 100 hours → 2.5 < diameter < 8.0 cm (small branches)
- 1000 hours → 8.0 < diameter < 15.0 cm (big branches)
SOIL MOISTURE
Of course, also rain affects the soil moisture level. This effect can be computed using the Keetch–Byram drought index (KBDI), created by John Keetch and George Byram in 1968 for the United States Department of Agriculture's Forest Service.
This model computes the amount of rain (expressed in mm) needed to completely saturate the ground, so that a KBDI of 0 mm means that the soil is completely saturated, while a KBDI of 200 mm means that it's extremely drought.
The computational steps involved are: reducing the drought index by the net rain amount and increasing the drought index by a drought factor. In the picture below the formula proposed by John Keetch and George Byram and adapted to the S.I. by Crane (1982) to compute the drought factor.
3.2 Model
In the following pictures, we show the model that we use to predict wildfires combining the two indicators shown above.
The first formula is an estimation of the moisture content in the four categories of fuels. The Moisture content at time t is the sum of two terms. The first is obtained by linear interpolation, where the starting point is the Moisture content at time t-1 and the final point is the RH of the air and the slope of the interpolating line is scaled by a constant depending on the time-lag which the fuel we’re considering belongs to. The second depends on the millimeters of rain, if they’re equal to the current Q value, then the moisture level goes to one, if they’re equal to ½ of Q than at to the current moisture level it’s added one half of the gap between the current moisture level and one, and so on.
The second formula is the probability of starting the fire given a triggering cause, that could be a natural cause, like a thunder, or not, like a cigarette butt ( we know that fires do not start by their own, because there must be a cause that heats the fuel to its ignition point).
We’ll assume this probability depends only on the fuel moisture content. In particular, we assume the probability of the fire NOT to start is equal to the moisture content in the fuels, where at each fuel is assigned a weight. For example, the ignition point of the leaves is much lower that one of the big branches, so the contribution of the formers will count more than one of the latter. According to this model, if the moisture content is 0%, then the fire will certainly start given a cause, and vice versa.
4 Hardware and Internet connectivityNow that we have shown our predicting model, let's talk about how we implemented it.
To measure local relative humidity and temperature we used a X-NUCLEO-IKS01A shield, mounted on a STM B-L072Z-LRWAN1 board with embedded LoRa connectivity. For those who are not familiar with LoRa, here it is a great starting point.
To make it short, it is a communication medium designed for high range, extremely low energy requirements and low transfer data rate, perfect for our goal. Moreover, the board includes a battery compartment to host 3xAAA 1.5V batteries, which should provide enough energy to last for months. The board must host also the sensor shield, which must be mounted on top.
The development was entirely carried out on Mbed OS, and the code is publicly available here and can be imported in your project. The code to make it work is not complicated, below is shown part of the main loop, which consists only in reading data from the sensor shield and send them through LoRa, every hour.
Before talking about how to use this code, we need to introduce The Things Network: an open-source decentralized networks that use high-range gates to provide connectivity through LoRa. Indeed, when a message is sent through LoRa, it first gets received by a gateway, forwarded to The Things Network, which will take care of sending it to your application, we will see how to do it later.
For now, we need to create your application first: go to thethingsnetwork.org and create a new application, following the step-by-step instructions provided. Once your application is created you have to register your own device, leaving all the settings to default. Once finished you will have something like this:
where the parameters and the keys are generated on the creation of the application and on the registration of the device. Returning to the board code, these values must be inserted into the file mbed_app.json, which can be found in the Mbed repository linked above, which is a JSON file containing all the board settings, from the baud rate to communicate with a serial interface to your computer, to the LoRa PHY.
In the file go to the section "target_overrides" and change the fields "lora.application-eui","lora.device-eui" and "lora.application-key" according to the values of The Things Network and following the same syntax. Once done we are ready to go, just hit "Compile" on the Mbed OS web IDE and it will start compiling, finally downloading the firmware in a.bin file.
To flash it, connect the board to the computer via USB and just drag and drop the.bin file into it (the computer will recognize the board as an external drive). From here on the board will start executing the code.
It is a good idea to install a serial monitor (like the one included in Arduino IDE) to read the informations sent from the board via USB. To use it just launch it and (in the Arduino IDE case) select Tools -> Serial monitor, with baud rate set to 9600. You may want to reset the board and run your code from the beginning, which can be done by pressing the black button, while the blue button is user-programmable if you need it.
From the serial monitor, you may see that the board prints "Connection in progress..." and gets stuck there. This can be due to the fact that there isn't a LoRa gateway in range. If that's the case, you can buy one for less than 50-100$, like the Dragon's LG01 and LG02. While the second costs around 20$ more than the first, I would personally recommend it, since it is a dual channel and thus supports OTAA activation, which is a method to send data more secure and reliable than ABP, the other activation method available. To make it simple, you can think of ABP and OTAA like UDP and TCP respectively.
4.1 The Things Network and Security
All the data passing through LoRa, both with ABP and OTAA, is encrypted, to not give an attacker the possibility to craft arbitrary payloads. Nevertheless, one thing a malicious third party can do is to execute a so called replay attack. This attack consists of reading a packet transiting in the air and just re-transmit it, without knowing its content. While this attack does not seem like much, by doing so an attacker has the possibility to send faked data to your application, like reading of sensors of previous days.
To overcome this problem, each message sent by the board has a counter attached to it. A counter is also maintained by The Things Network, visible in your device page in the field "Frames up". What The Things Network does is just comparing the counter of each incoming message to its "Frames up": if it is greater then the message is accepted and delivered, otherwise the message gets discarded without any warning.
Now the "fun" part: when you reset your board, like disconnect and reconnect the USB cable, the counter of the message sent by the board also resets, starting from zero. This means that if you send some messages, let's say 50, then reboot your board and restart sending the messages, all the first 50 messages get discarded! On your side, this can be solved by clicking on the "Reset frame counter". Another option is to disable the frame check, in your device settings, but for the reason explained above this is not recommendable.
5 Cloud ArchitectureWe adopted a microservice-based architecture, which is shown in detail in the figure above alongside the data exchanged between every service.
The Main Server receives updates from each board every hour and sends those informations to the Model microservice. The Model microservice then collects the old data recorded in the past for that user, the current weather conditions from the weather APIs and merge them all together to make predictions, by running the model introduces in the first section.
In particular, the server computes the new fuel moisture content, the fire starts probability. While the fuel moisture content and the fire probability are updated each hour, the drought level (Q) is updated once in a day, according to the formula 1.1.
While the Model microservice implements the risk model, the Main Server acts as "glue" between components, handling the information flow from The Things Network, the data exchanged with the Model microservice, and pushing the result of the computations to Firebase.
We decided to host our application to an AWS EC2 instance, but it really depends on your needs. For example, you may want to check out also Google Cloud and its Always-free plan, which (at the moment of writing) offers a virtual server with one core and 600MB of RAM. While this is not much, our application is not demanding in terms of computational power, and Google Cloud can be a viable (and free) option.
The code for the server is available through this Github repository. By default, the application exposes the port 13746 on all internet interfaces, and port 5000 only on localhost. This can be changed in files model.py and server.py, at the last lines of both. When using AWS, make sure that the port 13746 is exposed by the firewall, under "Security groups" of the AWS console. Once launched your instance and the server and model services, a public IP will be assigned to your instance.
To finalize the setup, we need to tell The Things Network where to forward the incoming messages. Go to your application settings -> Integrations and create a new integration. An integration on The Things Network can be seen as an extension to your application that adds new functionalities. What we need is the "HTTP Integration", the most common installed one.
This extension makes possible to forward all the data incoming from your board to be forwarded to a remote server (in our case the AWS instance) via HTTP requests. When creating the integration, as HTTP endpoint insert "<your-AWS-IP>:13746/ttn_endpoint". where obviously <your-AWS-IP> must be replaced by your instance's public IP. The port 13746 is what we have put in the code, but as we told you are free to change it in the file server.py, as long that you change the port also in the AWS firewall (a.k.a. security group) and in the HTTP integration.
Now we will talk about how to configure Firebase and the mobile application, which will be our "presentation layer" to the user.
6 FirebaseFirebase is a platform for web and mobile applications who need to manage data in real-time. Firebase uses the triggers, so you can listen specifically for only creation, update, or deletion events, or you can listen for any change of any kind to a path.
It is very important for us because the callbacks are activated only when specific data changes, notifying only some users for a specific device.
We use Firebase to communicate with a mobile application developed for Android smartphones. For the first steps you can navigate the console and, after creating the project with basic information, you will be easily guided through the connection between your application and Firebase.
6.1 Firebase Authentication
Firebase Authentication provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, phone numbers, popular federated identity providers like Google, Facebook and more.
We have allowed access to the user via email and password, with the possibility of registering to the system and changing the password.
Everything is allowed by Firebase in just a few steps, let's see how from the application backend:
LOGIN
if(valid) {
prog.setVisibility(View.VISIBLE);
mAuth.signInWithEmailAndPassword(username, password ).addOnCompleteListener(Login.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
// If sign in fails, display a message to the user.
if (!task.isSuccessful()) {
Toast.makeText(Login.this, getString(R.string.auth_failed), Toast.LENGTH_LONG).show();
} else {
Intent intent = new Intent(getApplicationContext(), LandingPage.class);
startActivity(intent);
finish();
} }
});
}
SIGN IN
if(valid) {
prog.setVisibility(View.VISIBLE);
mAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(SignIn.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
// If sign in fails, display a message to the user.
if (!task.isSuccessful()) {
Toast.makeText(SignIn.this, "Authentication failed: " + task.getException(), Toast.LENGTH_SHORT).show();
} else {
DatabaseReference myRef = database.getReference("devices").child(device_id);
myRef.child("users").child(name).setValue(email);
Toast.makeText(SignIn.this, "Authentication successful", Toast.LENGTH_SHORT).show();
startActivity(new Intent(getApplicationContext(), Login.class));
finish();
}
}
});
The user when signing in on the application has to put also the device code to connect with it. Several users can share the same device.
CHANGE PASSWORD
forpass.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()){
email.setError("Insert a valid email");
}else {
FirebaseAuth.getInstance().sendPasswordResetEmail(username)).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Toast.makeText(Login.this, "Email sent", Toast.LENGTH_SHORT).show();
}
}
});
}
}});
FIREBASE AUTHENTICATION INTERFACE
6.2 Firebase Database
The Firebase Real-time Database is a cloud-hosted database. Data is stored as JSON and synchronized in real-time to every connected client.
We use it to store the data got by the server. You can follow the guide to connect and test the connection with the database.
FIREBASE DATABASE INTERFACE
How the data is written to the database was discussed in the previous section.
HOW THE DATA ARE DISPLAYED ON THE APPLICATION
DatabaseReference datRef = database.getReference("devices").child(device_id).child("surveys");
datRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
...........
risktrends.setText(snapshot.child("RISK").getValue().toString());
risk.setText(snapshot.child("RISK").getValue().toString());
temp.setText(snapshot.child("T").getValue().toString()+"°C")
air.setText(snapshot.child("A").getValue().toString()+"%");
dlr.setText(snapshot.child("DL").getValue().toString()+"%");
dtr.setText(snapshot.child("DT").getValue().toString()+"%");
dstr.setText(snapshot.child("DST").getValue().toString()+"%");
dbtr.setText(snapshot.child("DBT").getValue().toString()+"%");
........
}
}
The application establishes a bidirectional connection with the database and when the data inherent to a specific device changes, the callback is called and sends a notification to the application. As you can see by the code, the data got by the database update the data displayed in the application in real-time.
UPDATE THE DEVICE LOCATION
One of the features of our solution is the ability to move the device independently. The user can move the device to another area of the forest, he just needs to be close to the device and update the position so that the whole system can adapt to the new location.
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CheckPermission();
DatabaseReference datRef2 = database1.getReference("devices").child(device_id).child("location");
datRef2.child("latitude").setValue(Lati);
datRef2.child("longitude").setValue(Longi);
AlertDialog alertDialog = new AlertDialog.Builder(Settings.this).create();
alertDialog.setTitle("LOCATION UPDATED");
alertDialog.setMessage("\n" +"The device location is updated correctly");
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialogInterface.cancel();
}
});
alertDialog.show();
}
});
The last step of our project is the data visualization for woodlands monitoring and fire prevention. Thanks to the valuation experiments with the end user, we have created a minimal but exhaustive application that respects all the user's objectives.
Team
Comments