Project tutorial
Smart WildFire Extinguisher

Smart WildFire Extinguisher © GPL3+

A fire-monitoring and crowdsourcing tool that will allow local fire managers to respond to wildfires.

  • 1,772 views
  • 1 comment
  • 14 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)

Apps and online services

About this project

Uncontrolled blazes fueled by weather, wind, and dry underbrush, wildfires can burn acres of land—and consume everything in their paths—in mere minutes.

On average, more than 100,000 wildfires, also called wildland fires or forest fires, clear 4 million to 5 million acres (1.6 million to 2 million hectares) of land in the U.S. every year. In recent years, wildfires have burned up to 9 million acres (3.6 million hectares) of land. A wildfire moves at speeds of up to 14 miles an hour (23 kilometers an hour), consuming everything—trees, brush, homes, even humans—in its path.

The most important thing in the prevention of wildfires is:

  • early detection
  • extinguishing fires in the beginning stages

We still don't have the technology to extinguish largely spread fires, buy we are smart. We can prevent the from spreading in the early stages.

This problem solves our: SMART WILDFIRE EXTINGUISHER.

SMART WILDFIRE EXTINGUISHER

Using NASA's provided data:

FIRMS (Fire Information for Resource Management Systems)

I pinpointed the locations of wildfires that occurred before, in the USA. Those are the high risk areas, where the risk of forming fires is the highest. On those locations we place our SMART WILDFIRE EXTINGUISHER.

Here is the link if you want to see for yourself NASA's FIRMS website, and check if you live in a dangerous area:

https://firms.modaps.eosdis.nasa.gov/map/#z:4.0;c:-93.305, 36.738

Additionally we used another provided NASA website:

EOSDIS worldview

By adding layers you can analyze additional effects like:

or those important factors for fire formation:

here is the link to try it out yourself:

https://worldview.earthdata.nasa.gov/?p=geographic&l=MODIS_Aqua_SurfaceReflectance_Bands143, MODIS_Aqua_SurfaceReflectance_Bands721, MODIS_Terra_SurfaceReflectance_Bands143, MODIS_Terra_SurfaceReflectance_Bands721, VIIRS_SNPP_CorrectedReflectance_TrueColor, MODIS_Aqua_CorrectedReflectance_TrueColor, MODIS_Terra_CorrectedReflectance_TrueColor, Terra_Orbit_Dsc, Terra_Orbit_Asc, MODIS_Fires_Terra, MODIS_Fires_Aqua, VIIRS_SNPP_Fires_375m_Night, VIIRS_SNPP_Fires_375m_Day, MODIS_Fires_All, Reference_Labels, Reference_Features, Coastlines&t=2018-05-17-T00%3A00%3A00Z&z=3&v=-162.2716819378906, 12.476930105214791, -58.83012349633215, 62.25818010521479

When the locations are decided, the SMART WILDFIRE EXTINGUISHERS will be placed into clusters:

Where the green triangle is the main GPS, wifi module, which sends the location to the server. The blue circles are sensor modules with temperature, humidity, smoke sensors and an object filled with abc powder.

If a fire breaks out, and its detected by the sensor module, the object filled with ABC powder breaks and extinguishes the fire.

The sensor that detected the fire will be in "activated" state (shown above as the color "red"). Nearby sensors in the cluster will be switched into "warning" state (shown above as color "yellow"). The sensors that are in the warning state are at a high risk of fire breakouts.

With this use of clusters it is easy to predict where the fire will spread, where it probably won't spread, so that safety evacuation paths are more accessible.

Additionally, for places without the SMART WILDFIRE EXTINGUISHER, there is the online app / website for reporting location where fires have started.

You capture the fire with your camera, pinpoint your location, and report it to the website.

Online app

For credibility, I created a fire detection algorithm

When you take a picture, to inform our website where a fire has started, it analyzes the taken picture and detects if there truly is fire or not.

How it works you can see on the video shown.

Fire detection algorithm

The fire recognition algorithm is provided below in the code section.

Life is about creating a better and safer world.

Code

fire recognition algorithmC#
the following code detects fire on a picture
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.Cvb;
using Emgu.CV.CvEnum;

namespace Hakaton
{
    public partial class Form1 : Form
    {
        private VideoCapture videoCapture;
        private bool detectFire;
        private bool frameSkip = true;

        private double redThreshold = 220;
        private double whiteThreshold = 220;
        private int frameInterval = 1000 / 30;

        private Timer fpsTimer;

        public Form1()
        {
            InitializeComponent();
            Init();
        }

        private void Init()
        {
            picPreview.SizeMode = PictureBoxSizeMode.StretchImage;
            picRedFilter.SizeMode = PictureBoxSizeMode.StretchImage;
            picFinal.SizeMode = PictureBoxSizeMode.StretchImage;

            trbSeek.Enabled = false;
        }

        private void OpenVideo(string filename)
        {
            videoCapture = new VideoCapture(filename);

            int frameCount = (int) videoCapture.GetCaptureProperty(CapProp.FrameCount);
            trbSeek.Minimum = 0;
            trbSeek.Maximum = frameCount;
            trbSeek.Value = 0;
            trbSeek.Enabled = true;

            fpsTimer = new Timer();
            fpsTimer.Interval = frameInterval;
            fpsTimer.Tick += ProcessFrame;
            fpsTimer.Start();
        }

        private void OpenCamera()
        {
            videoCapture = new VideoCapture();
            trbSeek.Enabled = false;
            frameSkip = false;

            Application.Idle += ProcessFrame;
        }

        private void ProcessFrame(object sender, EventArgs e)
        {
            DateTime methodStart = DateTime.Now;

            Image<Bgr, Byte> redFiltered = null;
            Image<Bgr, Byte> ycbcrFiltered = null;
            Image<Gray, Byte> blobImage = null;

            Image<Bgr, Byte> rawFrame = videoCapture.QueryFrame().ToImage<Bgr, Byte>();
            rawFrame = rawFrame.Resize(320, 240, Emgu.CV.CvEnum.Inter.Cubic);
            rawFrame._EqualizeHist();
            
            if (detectFire)
            {
                redFiltered = redTreshhold(rawFrame);
                ycbcrFiltered = yCbCrThreshold(redFiltered);
                blobImage = binaryTreshold(ycbcrFiltered);

                CvBlobs blobs = new CvBlobs();
                CvBlobDetector blobDetector = new CvBlobDetector();
                uint blobCount = blobDetector.Detect(blobImage, blobs);

                int minArea = (int)(rawFrame.Width * rawFrame.Height * 0.002);

                foreach (KeyValuePair<uint, CvBlob> blobPair in blobs)
                {
                    if(blobPair.Value.Area > minArea)
                    {
                        Rectangle rect = blobPair.Value.BoundingBox;
                        rawFrame.Draw(rect, new Bgr(0, 255, 0), 5);
                    }
                }
            }

            picPreview.Image = rawFrame.Bitmap;
            if(detectFire)
            {
                picRedFilter.Image = redFiltered.Bitmap;
                picFinal.Image = blobImage.Bitmap;
            }
            else
            {
                picRedFilter.Image = null;
                picFinal.Image = null;
            }

            if(frameSkip)
            {
                int timePassed = (DateTime.Now - methodStart).Milliseconds;
                int framesToSkip = timePassed / frameInterval;
                for (int i = 0; i < framesToSkip; i++)
                    videoCapture.QueryFrame();

            }

            int currentFrame = (int) videoCapture.GetCaptureProperty(CapProp.PosFrames);
            int frameCount = (int) videoCapture.GetCaptureProperty(CapProp.FrameCount);
            if(currentFrame != -1  && frameCount != -1)
            {
                trbSeek.Value = currentFrame;
                if (currentFrame == frameCount)
                    CloseVideo();
            }
        }

        private void CloseVideo()
        {
            fpsTimer.Stop();
            picPreview.Image = null;
            picRedFilter.Image = null;
            picFinal.Image = null;
        }

        Image<Gray, Byte> binaryTreshold(Image<Bgr, Byte> originalImage)
        {
            Image<Gray, Byte> newImage = new Image<Gray, byte>(originalImage.Width, originalImage.Height);

            Bgr black = new Bgr(0, 0, 0);
            for (int y = 0; y < originalImage.Height; y++)
            {
                for (int x = 0; x < originalImage.Width; x++)
                {
                    if (originalImage[y, x].Equals(black))
                        newImage[y, x] = new Gray(0);
                    else
                        newImage[y, x] = new Gray(255);
                }
            }

            return newImage;
        }

        Image<Bgr, Byte> redTreshhold(Image<Bgr, Byte> originalImage)
        {
            Image<Bgr, Byte> newImage = new Image<Bgr, byte>(originalImage.Width, originalImage.Height);

            for (int y = 0; y < originalImage.Height; y++)
            {
                for (int x = 0; x < originalImage.Width; x++)
                {
                    double r = originalImage[y, x].Red;
                    double g = originalImage[y, x].Green;
                    double b = originalImage[y, x].Blue;

                    bool isFire = false;

                    if (r > g && r > b)
                        if (r > redThreshold)
                            isFire = true;

                    if (r > whiteThreshold && g > whiteThreshold && b > whiteThreshold)
                        isFire = true;

                    if (isFire)
                        newImage[y, x] = originalImage[y, x];
                    else
                        newImage[y, x] = new Bgr(0, 0, 0);
                }
            }

            return newImage;
        }

        Image<Bgr, Byte> yCbCrThreshold(Image<Bgr, Byte> originalImage)
        {
            Image<Bgr, Byte> newImage = new Image<Bgr, byte>(originalImage.Width, originalImage.Height);

            for (int Y = 0; Y < originalImage.Height; Y++)
            {
                for (int X = 0; X < originalImage.Width; X++)
                {
                    double rRaw = originalImage[Y, X].Red;
                    double gRaw = originalImage[Y, X].Green;
                    double bRaw = originalImage[Y, X].Blue;

                    double r = rRaw / 255;
                    double g = gRaw / 255;
                    double b = bRaw / 255;

                    double y = 0.299 * r + 0.587 * g + 0.114 * b;
                    double cB = -0.168736 * r + -0.331264 * g + 0.500 * b;
                    double cR = 0.500 * r + -0.418688 * g + -0.081312 * b;

                    bool isFire = false;

                    if(y >= cR  &&  cR >= cB)
                    {
                        double crcb = cR - cB;
                        double ycb = y - cB;
                        if (!((crcb >= -0.1 && ycb >= -0.1 && ycb <= 0.3) || (crcb >= 0 && crcb <= 0.4 && ycb >= 0 && ycb <= 0.8)))
                            isFire = true;
                    }

                    if (isFire)
                        isFire = !(cR - cB > -0.1 && y - cB > -0.1 && y - cB <= 0.6);
                    
                    if (isFire)
                        newImage[Y, X] = originalImage[Y, X];
                    else
                        newImage[Y, X] = new Bgr(0, 0, 0);
                }
            }

            return newImage;
        }

        private void chkDetect_CheckedChanged(object sender, EventArgs e)
        {
            detectFire = chkDetect.Checked;
        }

        private void trbSeek_Scroll(object sender, EventArgs e)
        {
            int frameIndex = trbSeek.Value;
            videoCapture.SetCaptureProperty(CapProp.PosFrames, frameIndex);
        }

        private void chkFrameSkip_CheckedChanged(object sender, EventArgs e)
        {
            frameSkip = chkFrameSkip.Checked;
        }

        private void btnCamera_Click(object sender, EventArgs e)
        {
            OpenCamera();
        }

        private void btnVideo_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            DialogResult result = dialog.ShowDialog();
            if(result.Equals(DialogResult.OK))
                if(dialog.FileName != null)
                    OpenVideo(dialog.FileName);
        }
    }
}
fire detection using sensorsC/C++
fire detection using sensors for humidity, smoke, temperature, if any of those values are over a critical range, it will activate the dispersion of the extinguishing powder
#include <RF24Network.h>
#include <RF24.h>

#include <OneWire.h>
#include <DallasTemperature.h>



#include <SPI.h>			//Bibloteka za SPI protokol koje NRF24 korist
#include <EEPROM.h>			//Biblioteka za EEPROM funkcije mikrokontrolera 
#include <DHT.h>            //Biblioteka za DHT senzor temperature i vlage

#define ONE_WIRE_BUS_1 2
#define DHTPIN 4
#define DHTVERZIJA DHT11	
#define CEPIN 9 
#define CSNPIN 10 
#define PROGRAMINGPIN 8 
#define RELAY 3

OneWire oneWire_in(ONE_WIRE_BUS_1);

DallasTemperature sensor_inhouse(&oneWire_in);

#define SERIALSPEED 9600



RF24 radio (CEPIN,CSNPIN);			//Kreiramo objekat radio koji prima parametre (CE pin , CSN pin)
RF24Network mreza(radio);			//Kreiramo objekat mreza kojem prosljedujemo objekat radio
DHT senzor(DHTPIN , DHTVERZIJA);	//Kreiramo objekat senzor koji prima parametre (DHTPIN  ,  DHTVERZIJA)

int adresa_trenutnog;						//Adresa ovog rutera ili end uredjaja
const uint16_t  adresa_kordinatora = 00;	//Adresa kordinatora (ESP8266)
byte sleep_interval;						//Vrijeme izmedju transmisija                
unsigned long tInterval;				   //Pomocna varijabla za tajmer
unsigned long tStart;                      //Pomocna varijabla za tajmer
bool timer = true ;						   //Bool kojim kontrolisemo interval slanja podataka	



 /* Varijable u koje spremamo sve podatke koje citamo sa senzora te ih prosljedujemo u strukturu paket i saljemo */
 
float temperatura;
float vlaga;
float indeks_topline;	


 
 
 /* Struktura koja cuva paket podataka koje saljemo kordinatoru (Node 00)  */
 
 struct paket_t
 {
	 float temperatura;			//Temperatura sa DHT11 senzora
	 float vlaga;				//Vlaga sa DHT11 senzora
	 float indeks_topline;		//Indeks topline sa DHT11 senzora
	 
 };

 

 /* Ova funkcija podesava sleep interval , izbor intervala je : 0 = 1 sec, 1 = 2 sec , 2 = 3 sec , 3 = 5 sec */
 
void podesiInterval(byte interval) 
{

	//postavljamo interval na 1 sekundu
	if(interval == 0)
	 { 
		tInterval = 1000; 
	}
	//postavljamo interval na 2 sekunde
	else if(interval == 1) 
	{ 
		tInterval = 2000;
	}
	//postavljamo interval na 3 sekunde
	else if(interval == 2)
	 {
		tInterval = 3000;
	}
	//postavljamo interval na 3 sekunde
	else 
	{
		tInterval = 5000;
	}
}



 /*	 Funkcija vraca true kada je vrijeme za slanje na osnovu postavljeni vrijednosti u EEPROM-u , a false u protivnom
     slucaju i za to vrijme dok je tajmer false mi prosljedujemo podatke od drugih nodeova prema  kordinatoru.        */

 
bool provjeriTajmer(void)
{
	unsigned long sada = millis(); // Zapocinjemo tajmer i spremamo vrjeme u varijablu sada
	if ( sada - tStart >= tInterval  ) //check to see if it is time to transmit based on set interval
	{
	 tStart = sada; // Resetujemo trenutno vrijednost tajmer na sadasnju
	 return true;
	}
	else 
	return false;
 }
 
 /*	 Funkcija koristi pointere , zahtjeva adrese koje prosljeudujemo koristeci operator '&' , a za izmjenu vrijednosti na adresi koristimo operator '*'      */
 
 void citajSenzore(float * temperatura , float * vlaga , float * indeks_topline  )
 {
	   *temperatura = senzor.readTemperature();
	   *vlaga = senzor.readHumidity();
	   *indeks_topline = senzor.computeHeatIndex(*temperatura , *vlaga , false); 
 }
 
 
		/* Ova funkcija nam omugucava programiranje nodeova putem serijske veze sa pc-om.Kada programiramo nesmjemo koristiti "Carige return " ili "Line Ending".
   U ovaj mod se ulazi tako sto se prvi put prikljuci i isprogramira node ili ukoliko pin za programiranje spojimo sa uzemljenjem.   */

void ucitajPostavke() 
{
	
	pinMode(PROGRAMINGPIN , INPUT); //Postavljamo pin za programiranje na stanje logicke jedinice , te ga postavljamo kao ulaz
	int adresa_nodea; //varijabla za spremanje adresse nodea
	byte adresa_praznog = 128; // Varijabla pomocu koje provjeravamo dali je cip bio prije programiran
	byte interval; //Vrijeme izmedju prenosa podataka
	
	//Ove stringove koristimo kako bi ustedjeli na memoriji 
	String potvrda = F("Unesi 'Y' za potvrdu ili bilo koji drugi karakter za odbijanje zahtjeva :");
	String greska  = F("Neispravan unost , postavljam na : ");
	String pitanje = F("Dali bi ste zeljeli promjeniti ");

	//Modul programiramo samoo ukoliko nije prije bio programiran ili je korisnik usao u mod za programiranje
	if(EEPROM.get(0,adresa_praznog)!= 128 || !digitalRead(PROGRAMINGPIN))
	 {
		Serial.begin(SERIALSPEED); //Zapocinjemo serijsku komunikaciju
		//Ovaj dio cita postavke trenutno spremljene u EEPROM , te ih prebacuje u lokalne varijable
		Serial.println(F("Trenutne postavke u EEPROM-u : "));
		Serial.print("Adresa node-a : ");
		Serial.println(EEPROM.get(1,adresa_nodea),OCT); 
		Serial.print("Sleep interval : ");
		Serial.println(EEPROM.get(3,interval));
		
		//Postavljanje Adrese node-a
		
		Serial.print(pitanje);
		Serial.print("adresu node-a ? ");
		Serial.println(potvrda);
			if (dajOdgovor())
			{
			Serial.println(F("Unesite novu adresu node-a :"));
			while (!Serial.available()) { }
			adresa_nodea = Serial.parseInt();
			if(adresa_nodea >= 0) {
				EEPROM.put(1, adresa_nodea);
			}
			else 
			{ 
				Serial.print(greska);
				Serial.println("01");
				adresa_nodea = 01;
				EEPROM.put(1, adresa_nodea);
			}
			}
			
		//Postavljanje vremenskog intervala node-a :
		
		Serial.print(pitanje);
		Serial.print("vremenski interval? ");
		Serial.println(potvrda);
		if(dajOdgovor()) 
		{
			Serial.println(F("Unesite : 0 za 1 sec, 1 za 2 sec, 2 za 3 sec , 3 za 5 sec"));
			while (!Serial.available()) { }
			interval = Serial.parseInt();
			if(interval >= 0 || interval < 4)
			 { 
				EEPROM.put(3, interval);
			 }
			else 
			{
				Serial.print(greska);
				Serial.println("3");
				interval = 3;
				EEPROM.put(3, interval);
			}
		}
		
		
		dajEEPROMvrjednosti(); //Sprema vrjednosti iz EEPROM-a u globalne varijable
		//Printamo vrjednosti spremljene u globalne varijable 
		Serial.print("Adresa nodea : ");
		Serial.println(adresa_trenutnog,OCT);
		Serial.print("Vremenski interval: ");
		Serial.println(sleep_interval);
		adresa_praznog = 128; //Pisemo '128' , kako nebi vise citao EEPROM kao prazan
		EEPROM.put(0, adresa_praznog);
		Serial.end(); //Prekid Serijske komunikacije
	}
	else 
	{
		//Ako nismo u modu za programiranje vadimo vrjednosti iz EEPROM-a i vracamo ih u globalne varijable
		dajEEPROMvrjednosti();
	}
}

/* Ova funkcija vraca podatke iz EEPROMA u globalne varijable na flash memoriji mikrokontrolera */

void dajEEPROMvrjednosti() 
	{
	EEPROM.get(1,adresa_trenutnog);
	EEPROM.get(3,sleep_interval);
	}

/* Ako korisnik pritisne 'Y' vraca true , za bilo koji slucaj je false */

bool dajOdgovor() 
{
	while (!Serial.available()) { }
	if(Serial.read() == 'Y')
	return true;
	else return false;
}

/* Ova funkcija vadi sleep interval i ispisuje ga na monitor */

String dajInterval() 
{
	byte i;
	EEPROM.get(3,i);
	if(i==0) 
	{
		return "1 sec";
	}
	else if (i==1) 
	{
		return ("2 sec");
	}
	else if (i==2) 
	{
		return ("3 sec");
	}
	else 
	{
		EEPROM.put(3,i);
		return ("5 sec");
	}
}

uint32_t detonated = 0;

void Detonate (void)
{
	detonated = millis();
	digitalWrite(RELAY , HIGH);
}

	
	
void setup(void)
{
	sensor_inhouse.begin();
	pinMode(RELAY,OUTPUT);
	
	digitalWrite(RELAY,LOW);
	ucitajPostavke(); //Ulazimo u mod za programiranje
	podesiInterval(sleep_interval);//Podesavamo vrijeme izmedju transmisija
	SPI.begin();	//Pocetak SPI komunikacije 
	radio.begin();	//Pocetak NRF24 komunikacije
	mreza.begin(90, adresa_trenutnog);  // Incijalizacija Mreze (prvi argument jeste kanal na kojem komuniciramo , drugi je adresa ovog modula)		
}

void loop(void)
{
	mreza.update();  // Provjerava dali ima podataka od drugih nodova za prosjljediti ka kordinatoru
	
	sensor_inhouse.requestTemperatures();
	float temp = sensor_inhouse.getTempCByIndex(0);
	Serial.println(temp);
	if(temp > 60)
		Detonate();
	if (timer) // Ako je vrijeme za slanje timer boolean je true
	{
		citajSenzore(&temperatura,&vlaga,&indeks_topline);
		paket_t paket = { temperatura , vlaga , indeks_topline  }; // Kreiramo paket za slanje
		RF24NetworkHeader header (adresa_kordinatora); //Pravimo Header koji ide u transmit paket kako bi nodovi znali na koju adresu trebaju prosljediti paket
		mreza.write(header,&paket,sizeof(paket)); //Slanje paketa
	}
	timer = provjeriTajmer(); // Osvjezavanja stanja tajmera pozivanjem funkcije provjeriTajmer koja vraca T ili F
	
}
communication between nodesC/C++
wireless communication between different sensors, micro-controllers and the GPS sensor
#include <RF24.h>			//Bilbioteka za NRF24
#include <SPI.h>			//Bibloteka za SPI protokol koje NRF24 koristi
#include <RF24Network.h>	//Biblioteka za kreiranje  Mesh mreza sa NRF24

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>

#define CEPIN 2
#define CSNPIN 15


 struct paket_t
 {
   float temperatura;     //Temperatura sa DHT11 senzora
   float vlaga;       //Vlaga sa DHT11 senzora
   float indeks_topline;    //Indeks topline sa DHT11 senzora
   
 };

RF24 radio (CEPIN,CSNPIN);			//Kreiramo objekat radio koji prima parametre (CE pin , CSN pin)
RF24Network mreza(radio);			//Kreiramo objekat mreza kojem prosljedujemo objekat radio

ESP8266WiFiMulti WiFiMulti;

const uint16_t  adresa_kordinatora = 00;	//Adresa kordinatora (ESP8266)

void setup()
{
    Serial.begin(9600);
    Serial.println("Incijalizacija uspjesna ! ");
    SPI.begin();	//Pocetak SPI komunikacije
    radio.begin();	//Pocetak NRF24 komunikacije
    mreza.begin(90, adresa_kordinatora);  // Incijalizacija Mreze (prvi argument jeste kanal na kojem komuniciramo , drugi je adresa ovog modula)
    WiFiMulti.addAP("KPM 1", "plamenmira");

    while(WiFiMulti.run() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
    }
}



void sendUpdate(int node, paket_t packet)
{
	char getRequest[255] = "http://192.168.2.190/hak/?";
	char* last = getRequest + strlen(getRequest);
	
	strcpy(last, "temperatura=");
	last = getRequest + strlen(getRequest);
	dtostrf(packet.temperatura, 255 - strlen(getRequest), 2, last);
	
	last = getRequest + strlen(getRequest);
	strcpy(last, "&vlaga=");
	last = getRequest + strlen(getRequest);
	dtostrf(packet.vlaga, 255 - strlen(getRequest), 2, last);
	
	last = getRequest + strlen(getRequest);
	strcpy(last, "&indeks_topline=");
	last = getRequest + strlen(getRequest);
	dtostrf(packet.indeks_topline, 255 - strlen(getRequest), 2, last);
	
	last = getRequest + strlen(getRequest);
	strcpy(last, "&node=");
	last = getRequest + strlen(getRequest);
	sprintf(last, "%d", node);
	
	HTTPClient http;
	http.begin(getRequest); //HTTP
	Serial.println(getRequest);
	int httpCode = http.GET();

	// httpCode will be negative on error
	if(httpCode > 0) {
		// HTTP header has been send and Server response header has been handled
		Serial.print("[HTTP] GET... code: ");
		Serial.println(httpCode);
	}

	http.end();
}



void loop()
{
	mreza.update();  // Provjerava dali ima podataka od drugih nodova 
	paket_t paket; // Kreiramo objekat paket
	RF24NetworkHeader header; //Pravimo Header varijablu1

	if (mreza.available())
	{
		mreza.read(header,&paket,sizeof(paket));
		sendUpdate(header.from_node, paket);
	}
 }

Custom parts and enclosures

object filled with ABC powder
hollow object, milled with a CNC machine, filled with ABC powder
after the detection of fire, the powder will be dispersed to extinguish it
Q2dhxlv vcptmxb8ds
object filled with ABC powder
Lyfdor9 ticsp2zai7

Schematics

schematics
014piuq knievifgid

Comments

Submitted to Contest

One Seeed Environmental Kit to each of the additional 10 top projects (one kit each, customs taxes not included. See list for product details). For team(s) who wins in this section, we offer one kit to the team(s).

Seeed for Earth 2018

Author

1781879 785355644859803 3105934284059800719 n ovv9h3uzux
Ajdin Nakičević
  • 1 project
  • 8 followers

Published on

August 29, 2018

Members who respect this project

DefaultPhotoProfilepicPhotoDefault23621428 1589456071119695 8108241818733601640 nInductor color code   copy

and 7 others

See similar projects
you might like

Similar projects you might like

RF BASED SMART HOME AUTOMATION SYSTEM

by Dennis Mwanza

  • 29,107 views
  • 4 comments
  • 46 respects

Health Band - A Smart Assistant for the Elderly

Project tutorial by Technovation

  • 20,058 views
  • 11 comments
  • 53 respects

IOT - Smart Jar Using ESP8266, Arduino and Ultrasonic Sensor

Project tutorial by Team Smazee

  • 6,214 views
  • 4 comments
  • 12 respects

Rampiot - Cool Smart Lock

Project tutorial by Robinson Mesino

  • 3,905 views
  • 1 comment
  • 24 respects

Nero: A Smart Glove That Controls Remote Devices

Project tutorial by Nero

  • 2,625 views
  • 4 comments
  • 76 respects
Add projectSign up / Login