Close

Programování webových rozhraní pro Arduino

Ovládání Arduina přes internet

V poslední době se u nás na webu čas od času objevovaly prosby typu:Komentář

A je pravda, že takovýto článek tu chyběl. Psali jsme sice již o Ethernet Shieldu (dokonce dvakrát) i o WiFi shieldu. Vždy jsme ale rozebírali spíše jak naprogramovat Arduino pro čtení senzorů, ovládání LED… O programování webového rozhraní vždy zaznělo jen několik zběžných informací. To bych chtěl nyní napravit.

Úvod

Jak už to tak bývá, máme prakticky neomezeně možností, co se použitých komponent týče. Ať už chceme měřit vlhkost, teplotu, či rychlost větru, máme na výběr ze spousty různých senzorů. Stejně tak existuje celá řada modulů a shieldů, které připojí Arduino k internetu (zběžně například Ethernet Shield, WiFi Shield, modul ESP8266 a další). I výstupních zařízení můžeme mít spoustu (LED, Motory, Bzučáky…). Celý systém by se dal symbolicky zakreslit takto:

Schéma systému Arduino na Internetu

Schéma systému

Arduino tedy komunikuje se sítí pomocí modulu „Připojení“. Dále ze senzorů získává hodnoty (vlhkost vzduchu, rychlost větru atd.) a může odesílat jiné hodnoty na výstupní zařízení (rychlost otáčení motoru, úhel servomotoru, jas LED atd.). Co mají tyto hodnoty společné?

Všechno jsou to čísla! Ať už desetinná nebo celá, pořád jsou to jenom číselné hodnoty. Proto se dnes nebudeme moc zabývat tím, jaké senzory a výstupy máme. Pro jednoduchost si zvolíme dva analogové senzory – potenciometry (na pinech A4, A5) – a jeden digitální – tlačítko (pin D2). Stejně tak si ale můžete představit že se jedná o teploměr nebo vlhkoměr. Jako výstupní zařízení nám poslouží obyčejná LED (pin D3).

Také se moc nebudeme zabývat částí „Připojení“. Její ovládání závisí na konkrétním použitém modulu. Často je ale práce s moduly velmi podobná (například Ethernet Shield a Wifi Shield). My použijeme Ethernet Shield.

Zapojení simulující senzory a výstupní zařízení Arduino

Naše zapojení

Výběr řešení

Nyní přichází na řadu rozhodnutí, jakým způsobem vytvoříme komunikační rozhraní. Existuje celá řada řešení třetích stran. Některé z nich si představíme na konci článku. Jako první si ale vyzkoušíme vše vytvořit od začátku.

Umístění webové stránky

Jak si možná pamatujete z článku o Ethernet a Wifi shieldu, může Arduino v síti vystupovat dvěma způsoby. Buďto jako server nebo jako klient. V případě prvním běží webová stránka pro ovládání přímo na Arduinu. Nemáme tak tolik možností, protože má Arduino omezenou paměť, ale na základní ovládání to stačí. Toto řešení použijeme v případě, že neplánujeme nad daty provádět analýzy, popřípadě složitější vizualizace.

Arduino jako Server

Základem je HTTP protokol

Základem komunikace mezi serverem a klientem je (většinou) HTTP protokol. Ten přenáší všechny potřebné informace, které klient od webu může očekávat a zároveň pomocí HTTP protokolu klient říká, jaká data od serveru požaduje. O HTTP jsem psal ve článku o Ethernet Shieldu, kde si můžete tuto problematiku připomenout.

Zběžně si připomeňme činnost Shieldu na příkladu z Examples > WebClient, který stáhne obsah webu www.google.com a vypíše jej přes sériovou linku (včetně HTTP hlavičky).

/*
  Web client

 This sketch connects to a website (http://www.google.com)
 using an Arduino Wiznet Ethernet shield.

 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13

 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe, based on work by Adrian McEwen

 */

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128);  // numeric IP for Google (no DNS)
char server[] = "www.google.com";    // name address for Google (using DNS)

// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192, 168, 0, 177);

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // try to congifure using IP address instead of DHCP:
    Ethernet.begin(mac, ip);
  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");

  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    client.println("GET /search?q=arduino HTTP/1.1");
    client.println("Host: www.google.com");
    client.println("Connection: close");
    client.println();
  } else {
    // if you didn't get a connection to the server:
    Serial.println("connection failed");
  }
}

void loop() {
  // if there are incoming bytes available
  // from the server, read them and print them:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
}

Když si otevřeme monitor sériové linky, vypíše se nám:

connecting...
connected
HTTP/1.1 302 Found
Location: http://www.google.cz/search?q=arduino&gws_rd=cr&ei=LP61VsHFHofjywOK2a3IDA
Cache-Control: private
Content-Type: text/html; charset=UTF-8
P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
Date: Sat, 06 Feb 2016 14:07:40 GMT
Server: gws
Content-Length: 278
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=76=ypwExw5cTiZ5fFfmeEwtEoGo1d8QLO14kjvx7WysrpCleRdBfNX8EhCYE6vkfHt56bneI6Lyi5utrZw7mLVjRBWJS2rj8Z2Jl2NsyobTCeRBUow3PfrL6C81CkeX4AzJPo7vwSiv; expires=Sun, 07-Aug-2016 14:07:40 GMT; path=/; domain=.google.com; HttpOnly
Connection: close

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.cz/search?q=arduino&gws_rd=cr&ei=LP61VsHFHofjywOK2a3IDA">here</A>.
</BODY></HTML>

disconnecting.

Rychlokurz HTML

Základem většiny webových stránek je HTML – HyperText Markup Language, tedy „hypertextový značkovací jazyk“. V češtině asi nejrozsáhlejší stránka zabývající se HTML je http://www.jakpsatweb.cz/, v angličtině je HTML velmi podrobně popsáno na stránkách W3CSchools. Základním stavebním prvkem stránky je značka (častěji se používá anglické označení tag). Tyto tagy se píší do špičatých závorek: <tag>. Mohou být párové – ty ohraničují nějakou část webové stránky, například <strong>Tučné písmo</strong> (ve stránce samozřejmě nejsou vidět, zde jsou pro názornost). Každý otevírací párový tag musí mít jemu odpovídající uzavírající tag (ten začíná lomítkem). Druhou možností jsou tagy nepárové – například nový řádek: <br /> (nepárovost je znázorněna tím, že končí lomítkem). Tagy je navíc možné do sebe vnořovat (jinak by HTML nemělo moc význam :)). <em>ABC<strong>DEF</strong></em> se tedy zobrazí jako ABCDEF.

Základní kostra stránky vypadá takto:

<html>
	<head>
		<title>Titulek - text v záložkách prohlížeče...</title>
		Tato část se nazývá hlavička. 
		Obsahuje například vložení skriptů, metadata pro vyhledávače, sociální sítě atd.
	</head>
	<body>
		Tato část se nazývá tělo. Sem se píše samotný obsah stránky. 
	</body>
</html>

My tedy potřebujeme, aby nám Arduino po připojení odeslalo webovou stránku, která bude obsahovat patřičné ovládací prvky. Začneme zvolna. Budeme chtít ovládat LED diodu pomocí odkazů vypnout a zapnout.

Ovládání LED

V HTML se odkaz vytvoří pomocí tagu <a href=“URL adresa“>Text odkazu</a>. Parametry budeme serveru předávat metodou GET (tak jako ve článku o Ethernet Shieldu). Když si tedy sestavíme odkaz <a href=“/?l=0″>VYPNI</a>, na který poté klikneme, HTTP request, který klient odešle serveru bude začínat následovně:

GET /?l=0 HTTP/1.1

Z toho my potřebujeme „vyextrahovat“ právě část l=0. Budeme tedy hledat první výskyt ‚?‘ v requestu a dále číst, co část GET obsahuje. Použijeme upravený kód z článku o Ethernet Shield. Všimněte si, že uvozovky, které jsou součástí odkazu před sebou mají zpětné lomítko: \“. To je zde nutné kvůli kompilátoru. Řekneme mu tím, že chceme pracovat se znakem uvozovek a že se nejedná o část programu (začátek/konec řetězce). Tag <meta charset=“UTF-8″> říká, že budeme pracovat se znakovou sadou UTF-8, která podporuje i české znaky.

#include <Ethernet.h>
#include <SPI.h>

boolean zacatekCteni = false;

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x9C, 0xB7}; //MAC adresa
IPAddress ip(10,0,0,3); //IP adresa
EthernetServer server = EthernetServer(80); //port

void setup(){
    pinMode(3, OUTPUT);

    Ethernet.begin(mac, ip); //vytvoření serveru
    server.begin(); //spuštění serveru
}

void loop(){
    EthernetClient client = server.available(); //načtení klienta
    
    if(client){
        boolean prazdnyRadek = true;
        boolean hlavickaPoslana = false;
        
        while(client.connected() && client.available()){
            if(!hlavickaPoslana){ //jednou pošleme hlavičku
                client.println("HTTP/1.1 200 OK");
                client.println("Content-Type: text/html");
                client.println();
                hlavickaPoslana = true;
                //dále pošleme obsah stránky
                client.println("<html>");
                client.println("<head><meta charset=\\"UTF-8\\"></head>");
                client.println("<body>");
                client.println("<a href=\\"/?l=0\\">VYPNI</a>");
                client.println(" - ");
                client.println("<a href=\\"/?l=1\\">ZAPNI</a>");
                client.println("<br />");
                client.println("</body>");
                client.println("</html>");
            }
            
            char c = client.read();
            
            if(zacatekCteni && c == ' '){ //ukončí čtení
                zacatekCteni = false;
            }
            
            if(c == '?'){ //začne čtení
                zacatekCteni = true;
            }
            
            if(zacatekCteni){                
                if(c == 'l'){
                    client.read(); //přeskočíme jeden znak (=)
                    c = client.read(); //přečteme další znak -> hodnota LED
                    if(c == '0'){
                        digitalWrite(3, LOW);
                    }
                    else if(c == '1'){
                        digitalWrite(3, HIGH);
                    }
                    break; //vyskočí z cyklu
                }
            }
            
            if (c == 'n') {
                prazdnyRadek = true;
            }
            
            else if (c != 'r'){
                prazdnyRadek = false;
            }
        }
        delay(1);
        client.stop();
    } 
}

Zobrazení informací

Přidání informací o stavu potenciometrů a tlačítka je velice jednoduché. Můžeme si vybrat, jakým způsobem data zobrazíme. Abychom si ukázali jednoduchost HTML, zobrazíme si je přehledně v tabulce. Použijeme stejný kód, jen přidáme několik řádek. Tagy pro vytvoření tabulky jsou <table> pro samotnou tabulku, <tr> pro řádek, <td> pro buňku. Všechny tři jsou párové. Kód stránky vypadá následovně:

client.println("<html>");
client.println("<head><meta charset=\"UTF-8\"></head>");
client.println("<body>");
client.println("<a href=\"/?l=0\">VYPNI</a>");
client.println(" - ");
client.println("<a href=\"/?l=1\">ZAPNI</a>");
client.println("<br />");
client.println("<table>");
client.println("<tr>"); //tlačítko
client.println("<td>Tlačítko<td>");
client.println("<td>");
client.println(digitalRead(2));
client.println("</td>");
client.println("</tr>");
client.println("<tr>"); // POT A5
client.println("<td>POT A5<td>");
client.println("<td>");
client.println(analogRead(A5));
client.println("</td>");
client.println("</tr>");
client.println("<tr>"); //POT A4
client.println("<td>POT A4<td>");
client.println("<td>");
client.println(analogRead(A4));
client.println("</td>");
client.println("</tr>");
client.println("</table>");
client.println("</body>");
client.println("</html>");

Mohli bychom pokračovat i dále. Často totiž nepotřebujete aktuální hodnotu, ale spíše průběh v čase. Hodnoty bychom si tedy museli logovat do Arduina a při připojení je zobrazit. Zobrazování hodnot se ale budeme věnovat později.

Poznámka pro zkušenější webaře: Zajímavé by mohlo být použití nějakého JS scriptu vloženého z externího zdroje pro hezké grafy a vizualizace. 

Arduino jako Klient

V tomto případě Arduino odesílá hodnoty na server, který je poté zpracovává. Tato možnost je podle mě daleko vhodnější, protože ulehčíte práci Arduinu. Nevýhodou je, že potřebujete zmíněný server. V našem případě to bude PHP server, který bude přijaté hodnoty zaznamenávat do MySQL databáze (pěkný tutoriál zabývající se PHP naleznete například na serveru ITnetwork). Můžete použít klidně i nějaký free hosting. My budeme hodnoty logovat na adrese https://bastlirna.hwkitchen.cz/data/logger.php. Zde umístěný program bude čekat na hodnoty, které po přijetí uloží do databáze společně s časovým údajem záznamu.

Arduino Datalogger

Vytvoření MySQL tabulky

V dostupném nástroji pro správu MySQL databáze (například phpMyAdmin) vytvořte tabulku arduino_data, která bude mít tři sloupce: id, timestamp, hodnota. V již zmíněném phpMyAdmin to po přihlášení provedeme následovně:

  1. Vybereme databázi
  2. V dolní části okna vyplníme část Vytvořit tabulku. Do Název zadáme arduino_data a do Počet polí zadáme 3.
  3. Klikneme na  tlačítko Proveď.

    Vytvoření MySQL tabulky - Část první - Ovládání Arduina přes internet

    Vytvoření MySQL tabulky – Část první

  4. Objeví se nastavení jednotlivých sloupců.
  5. Řádky nazveme po řadě: id, timestamp, hodnota.
  6. Typ nastavíme pořadě: INT, TIMESTAMP, INT.
  7. V prvním řádku zaškrtneme vlastnost A_I, tedy Auto Increment – automatické zvětšování.
  8. U druhého řádku nastavíme vlastnosti Výchozí na CURRENT_TIMESTAMP.
  9. Zmáčkneme tlačítko Uložit.

Logování hodnot do tabulky

Tak, jak jsme si tabulku vytvořili, nám stačí přidat hodnotu a id a timestamp se přidají automaticky. Nyní k PHP kódu – jednotlivé části jsou okomentovány. Takto vypadá obsah souboru logger.php.

<?php 
	$server = "localhost";
	$user = "uzivatel";
	$pass = "heslo";
	$db = "jmeno_databaze";
	
	$mysqli = mysqli_connect($server, $user, $pass, $db); //připojení k MySQL
	
	if($mysqli and isset($_GET['hodnota'])){ //pokud GET obsahuje 'hodnota', pokračuj
		$hodnota = sanitize($_GET['hodnota']);
		
		$sql = "INSERT INTO arduino_data (hodnota) VALUES (".$hodnota.")"; //sestavení SQL
		$doSql = $mysqli->query($sql); //vykonání SQL
		
		if($doSql){ //test úspěchu
			echo 'Zápis byl úspěšný';
		}
		else{
			echo 'Něco se nepovedlo';
		}
		
	}
	else{
		echo "Neco je špatně";
	}
	
	function sanitize($input){ //ořízne řetězec
		$input = htmlspecialchars($input);
		$input = htmlentities($input);
		$input = strip_tags($input);
		$input = trim($input);
		return $input;
	}
?>

Pokud nyní nahrajeme tento kód na server a otevřeme jej v prohlížeči přes https://bastlirna.hwkitchen.cz/data/logger.php/?hodnota=1000, objeví se nám v databázi nový záznam:

Záznam v databázi - Ovládání Arduina přes internet

Záznam v databázi

Arduino program

Nyní se přesuňme k Arduinu. Z něj potřebujeme odeslat naměřenou hodnotu.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x9C, 0xB7}; //MAC adresa
IPAddress ip(10,0,0,3); //IP adresa
char server[] = "bastlirna.hwkitchen.cz"; //URL adresa serveru   

EthernetClient client;

void setup() {
    Serial.begin(9600);
    
    if (Ethernet.begin(mac) == 0) {
        Ethernet.begin(mac, ip);
    }
    delay(1000);
}

void loop() {
    if(client.connect(server, 80)){
        delay(1000);
        Serial.println("OK");
        client.print("GET https://bastlirna.hwkitchen.cz/data/logger.php?hodnota=");
        client.println(analogRead(A5));
        client.println("Host: bastlirna.hwkitchen.cz");
        client.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        client.println("Connection: close");
        client.println();

        client.stop();
        delay(5000);
    }
}

Tento kód každých přibližně pět vteřin odešle hodnotu na server. Tabulka se nám postupně plní údaji.

Hodnoty v MySQL - Ovládání Arduina přes internet

Hodnoty v MySQL

Zobrazení naměřených hodnot

Pro zobrazení hodnot použijeme JavaScript knihovnu Chart.js. Stáhneme archiv s knihovnou a rozbalíme do do data/Chart. K práci nám stačí Chart.js a obsah složky src. Program, který bude data zobrazovat nazveme show.php.

<?php
	$server = "localhost";
	$user = "uzivatel";
	$pass = "heslo";
	$db = "jmeno_databaze";

	$mysqli = mysqli_connect($server, $user, $pass, $db); //připojení k MySQL
	
	//načtení hodnot z MySQL
	$sql = 'SELECT * FROM arduino_data ORDER BY timestamp';
	$doSql = $mysqli->query($sql);
	while($row = $doSql->fetch_assoc()){
		$popisky[] = $row['timestamp']; //načte popisky do pole
		$hodnoty[] = $row['hodnota'];    //načte hodnoty do pole
	}
	
	$json_popisky = json_encode($popisky);
	$json_hodnoty = json_encode($hodnoty);
?>

<html>
	<head>
		<script src="Chart/Chart.js"></script>
	</head>
	<body>
		<div style="width:50%">
			<div>
				<canvas id="canvas" height="100%" width="100%"></canvas>
			</div>
		</div>
		<script>
			var randomScalingFactor = function(){ return Math.round(Math.random()*100)};
			var lineChartData = {
				labels : <?php echo $json_popisky ?>,
				datasets : [
				{
					label: "My First dataset",
					fillColor : "rgba(220,220,220,0.2)",
					strokeColor : "rgba(220,220,220,1)",
					pointColor : "rgba(220,220,220,1)",
					pointStrokeColor : "#fff",
					pointHighlightFill : "#fff",
					pointHighlightStroke : "rgba(220,220,220,1)",
					data : <?php echo $json_hodnoty ?>
				}
				]
			}
			window.onload = function(){
				var ctx = document.getElementById("canvas").getContext("2d");
				window.myLine = new Chart(ctx).Line(lineChartData, {
					responsive: true
				});
			}
		</script>
	</body>
</html>

Na výsledek se můžete podívat na https://bastlirna.hwkitchen.cz/data/show.php. Chart.js nabízí celou řadu typů grafů. Spolu s přehledným popisem je naleznete v dokumentaci Chart.js.

Ovládání Arduina

Možná si říkáte, jak ovládat Arduino, které se ke stránce připojuje jako klient. I zde existuje více cest. My použijeme opět PHP a MySQL. V MySQL budeme mít uložené konfigurační hodnoty, které Arduino získá připojením na stránku sloužící jako prostředník mezi Arduinem a MySQL.

Vytvoření tabulky

Začneme vytvořením velice jednoduché tabulky, kterou nazveme arduino_ovladani a bude mít dva sloupce. První nazveme modul (co ovládáme) a druhý hodnota (jaký má stav). Zbytek nastavíme podle obrázku. (Ano, měli bychom nastavit klíč, ale pro jednoduchost to vynechávám.).

Konfigurační tabulka - Ovládání Arduina přes internet

Konfigurační tabulka

Konfigurační formulář

Nyní si vytvoříme formulář, který bude měnit hodnoty v tabulce. V našem případě budeme pracovat s jediným řádkem tabulky. Jeho hodnota modul bude led a bude mít hodnotu 0 nebo 1. Ve formuláři použijeme pro přepínání hodnoty mezi 0 a 1 tzv. radio button (který určitě znáte, jen možná nevíte, že se tak jmenuje). Kód bude obsahovat i část, která zjistí, zda řádek s názvem led existuje. Pokud neexistuje vytvoří jej. Soubor nazveme config.php.

<?php
	$server = "localhost";
	$user = "uzivatel";
	$pass = "heslo";
	$db = "jmeno_databaze";

	$mysqli = mysqli_connect($server, $user, $pass, $db); //připojení k MySQL
	
	$sql = 'SELECT * FROM arduino_ovladani WHERE modul="led"';
	$doSql = $mysqli->query($sql);
	if($doSql->num_rows == 0){
		$sql = 'INSERT INTO arduino_ovladani (modul, hodnota) VALUES ("led", 0)';
		$doSql = $mysqli->query($sql);
	}
	
	if(isset($_POST['odeslano'])){ //pokud byl formulář odeslán
		$hodnota = sanitize($_POST['stav']);
		
		$sql = 'UPDATE arduino_ovladani SET hodnota="'.$hodnota.'" WHERE modul="led"';
		$doSql = $mysqli->query($sql);
		
		if($hodnota == 1){
			echo 'Zapnuto';
		}
		else{
			echo 'Vypnuto';
		}
		echo '<br /><br />';
	}
	
	$sql = 'SELECT * FROM arduino_ovladani WHERE modul="led"';
	$doSql = $mysqli->query($sql);
	$hodnota = $doSql->fetch_assoc()['hodnota']; //načte hodnotu led z DB

	$zapnutoChecked = $hodnota == 1 ? 'checked' : ''; //nastaví výchozí hodnotu radio buttonu
	$vypnutoChecked = $hodnota == 0 ? 'checked' : '';

	echo '<form action="" method="POST" >';
		echo '<input type="hidden" value="1" name="odeslano" />';
		echo '<input type="radio" name="stav" value="1" '.$zapnutoChecked.' /> Zapnout<br>';
		echo '<input type="radio" name="stav" value="0" '.$vypnutoChecked.' /> Vypnout<br><br>';
		echo '<input type="submit" value="Odeslat">';
	echo '</form>';
	
	function sanitize($input){
		$input = htmlspecialchars($input);
		$input = htmlentities($input);
		$input = strip_tags($input);
		$input = trim($input);
		return $input;
	}
?>

Když se nyní podíváte na https://bastlirna.hwkitchen.cz/data/config.php, uvidíte následující formulář:

Konfigurační formulář - Ovládání Arduina přes internet

Konfigurační formulář

Formulář nemusí obsahovat pouze radio button, ale celou řadu různých vstupů. Jejich přehled si můžete zobrazit například zde. Nyní musíme vytvořit stránku, která Arduinu pošle údaje z databáze.

Stránka zobrazující konfiguraci

Soubor nazveme controller.php. Za úkol bude mít vypisovat obsah tabulky arduino_ovladani ve tvaru modul:hodnota: (zobrazí takto za sebou všechny případné řádky tabulky). Bude se jednat o velice jednoduchý program:

<?php
	$server = "localhost";
	$user = "uzivatel";
	$pass = "heslo";
	$db = "jmeno_databaze";

	$mysqli = mysqli_connect($server, $user, $pass, $db); //připojení k MySQL
	
	$sql = 'SELECT * FROM arduino_ovladani';
	$doSql = $mysqli->query($sql);
	while($row = $doSql->fetch_assoc()){
		echo $row['modul'].':'.$row['hodnota'].':';
	}
?>

Nyní zbývá vytvořit Arduino program, který se připojí ke stránce https://bastlirna.hwkitchen.cz/data/controller.php a podle toho nastaví stav LED.

Změna stavu LED

Závisí na projektu, jak často potřebujeme kontrolovat změnu stavu. Někdy stačí kontrolu provést jednou za hodinu a někdy je zase vteřina moc. My si zvolíme interval kontroly přibližně jednou za minutu.

#include <SPI.h>
#include <Ethernet.h>

#define BUFF_DELKA 255

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x9C, 0xB7}; //MAC adresa
IPAddress ip(10,0,0,3); //IP adresa
char server[] = "bastlirna.hwkitchen.cz"; //URL adresa serveru   

char buffer[BUFF_DELKA]; //zásobník na příchozí řetězec

EthernetClient client;

void setup() {
    pinMode(3, OUTPUT);
    
    Serial.begin(9600);
    
    if (Ethernet.begin(mac) == 0) {
        Ethernet.begin(mac, ip);
    }
    delay(1000);
}

void loop() {
    if(client.connect(server, 80)){
        delay(1000);
        client.println("GET https://bastlirna.hwkitchen.cz/data/controller.php");
        client.println("Host: bastlirna.hwkitchen.cz");
        client.println("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
        client.println("Connection: close");
        client.println();

        delay(1000);

        int inBuffer = 0;

        for(int i = 0; i < BUFF_DELKA; i++){ //vyprázdní buffer
            buffer[i] = '\\0'; //nastaví všechny prvky buffer na znak konce řetězce
        }
        
        while(client.available()){
            buffer[inBuffer] = client.read();    
            inBuffer++;
        }
        
        if(inBuffer == 6){
            if(buffer[0] == 'l' && buffer[1] == 'e' && buffer[2] == 'd'){
                if(buffer[4] == '1'){
                    digitalWrite(3, HIGH);
                }
                else{
                    digitalWrite(3, LOW);
                }
                Serial.println(buffer[4]);
            }
        }

        client.stop();
    }

    delay(60000);
}

Dobré je si uvědomit, že stránka, která Arduinu poskytuje údaje může být zároveň i stránka, která od Arduina hodnoty přijímá a zapisuje je do databáze.

Tímto jsme dokončili část, kdy jsme si vše programovali sami a můžeme se stručně podívat na některé existující služby, které můžeme využít.

Řešení třetích stran

Plotly

Jak už název napovídá, služba Plotly slouží primárně k vizualizaci dat. Nabízí neplacený program pro menší objemy dat. Naleznete jej na URL adrese plot.ly. Inspirovat se můžete například u projektů zobrazujících aktuální teplotu nebo teplotu a vlhkost.

Phant

Americká společnost Sparkfun, která prodává velmi povedené shieldy a komponenty pro Arduino i další desky je autorem projektu Phant. Ten naleznete na data.sparkfun.com. Výhodou je, že Phant běží na Node.js a je možné jej rozběhnout i na vlastním serveru. Jeho používání přehledně popisují v sérii Pushing Data to Data.SparkFun.com. Veřejné feedy si můžete prohlédnout na data.sparkfun.com/feeds.

IFTTT

Tuto službu možná znáte. Slouží k propojování API různých aplikací, které spolu normálně komunikovat neumí. Vytvoříte si předpis, který na základě akce spustí nějakou reakci (odsud také pochází název – IF This Then That – když to, tak ono). Například si můžete vytvořit předpis, který vám automaticky uloží všechny přílohy z Gmail do Skydrive, všechny Tweety o vás vám pošle na mail a podobně. Magie nastává, když k IFTTT připojíte Arduino. Co třeba vytvořit detektor otevření dveří s ESP8266 (za pomoci Adafruit.io), odeslat email po stisknutí tlačítka nebo zapnout WiFi zásuvku při detekci pohybu?

Thingspeak

Thingspeak je služba, který si klade za cíl propojit IoT zařízení. Vyzkoušejte například jednoduchý tutoriál zabývající se nahráváním dat nebo logováním vlhkosti.

IBM Bluemix

Poslední dva příklady patří spíše do kategorie „s kanonem na vrabce“. Jejich použití ale může přijít vhod, máte-li s těmito platformami nějaké zkušenosti. S IBM Bluemix můžete začít například v tutoriálu, se kterým k Bluemix připojíte teploměr. Ten využívá MQTT protokol, který má být náhražkou HTTP pro zařízení v internetu věcí.

Amazon Web Services

Amazon v srpnu minulého roku oznámil podporu SDK pro Arduino Yun. Více o AWS se můžete dočíst zde.

Závěr

Vidíte, že různých kombinací je nepřeberné množství, které není možné vtěsnat do jednoho článku. Doufám ale, že jsem vám poskytl dobrý vhled do probírané problematiky a že nabyté znalosti budou dostačující pro jednoduchý průchod vašimi projekty 🙂

Není vám z výkladu něco jasné, nebo máte jiné nápady, jak kterou část udělat? Neváhejte nám dát vědět v komentářích nebo na fóru!

Zbyšek Voda

48 Comments on “Programování webových rozhraní pro Arduino

wuufy
15.4.2020 at 22:48

Dobrý den… Skvělá práce pane Zbyšku! Z vašich článků čerpám neustále nové zkušenosti.Pokaždé jsem si dokázal kód upravit podle svých požadavků, ale teď jsem narazil. Jak prosím upravím kód v esp a v souboru logger.php abych byl schopen odeslat v jednom cyklu 2 proměnné a zapsat je do příslušných sloupců v databázi.Děkuji za odpověď….

Zbyšek Voda
16.4.2020 at 9:36

Dobrý den, jsem rád, že jsou pro vás články přínosné 🙂

První úpravou je vytvořit v databázi o jeden sloupec navíc – pro druhou hodnotu.
Řekněme, že máme dva sloupce – hodnota1 a hodnota2 – do kterých budeme zapisovat.

Poté upravíte logger.php. Tam by mělo fungovat něco na tento způsob:
if($mysqli and isset($_GET[‚hodnota1‘] and isset($_GET[‚hodnota2‘])){
$hodnota1 = sanitize($_GET[‚hodnota1‘]);
$hodnota2 = sanitize($_GET[‚hodnota2‘]);

$sql = „INSERT INTO arduino_data (hodnota1, hodnota2) VALUES („.$hodnota1.“,“.$hodnota2.“)“; //sestavení SQL
$doSql = $mysqli->query($sql); //vykonání SQL

if($doSql){ //test úspěchu
echo ‚Zápis byl úspěšný‘;
}
else{
echo ‚Něco se nepovedlo‘;
}
}

Třetí krok je odeslat správně pojmenovaná pole z ESP. Bude potřeba upravit HTTP dotaz.

client.print(„GET https://bastlirna.hwkitchen.cz/data/logger.php?hodnota1=„);
client.print(analogRead(A5));
client.print(„&hodnota2=“)
client.println(analogRead(A6));

Nemám teď čas to vyzkoušet, ale mělo by to alespoň naznačit směr 🙂

wuufy
16.4.2020 at 22:58

Děkuji za rychlou reakci na dotaz, ale bohužel mi to nefunguje.. Pokud opíši vámi navrhovaný kód, prohlížeč na dotaz /logger.php/?hodnota1=1000 vrátí chybu(nelze načíst).
Pokusil jsem se s kódem laborovat abych eliminoval chyby, ale přesto jsem se dostal maximálně ke zprávě „Něco je špatně“ na PHPčko mám v plánu se podívat blíže v budoucích měsících.Proto hledám řešení tohoto problému u ostatních. Děkuji

Zbyšek Voda
19.4.2020 at 17:43

Zkuste https://pastebin.com/QC8TpQ3H
Jsou tam správně uvozovky.

Musíte vždy zadat obě hodnoty. Tedy logger.php/?hodnota1=1000 nebude fungovat, ale logger.php/?hodnota1=1000&hodnota2=30 by mělo.

mpro
10.2.2020 at 9:09

Krásný článek, děkuji. Nedaří se mi ale zprovoznit zapínaní/vypínání dvou „zařízení“ led a fan. Php mi moc blízké není ale zkusil jsem to takto:
query($sql);
if($doSql->num_rows == 0){
$sql = ‚INSERT INTO arduino_ovladani (modul, hodnota) VALUES („led“, 0)‘;
$doSql = $mysqli->query($sql);
}

if(isset($_POST[‚odeslano‘])){ //pokud byl formulář odeslán
$hodnota = sanitize($_POST[‚stav‘]);

$sql = ‚UPDATE arduino_ovladani SET hodnota=“‚.$hodnota.'“ WHERE modul=“led“‚;
$doSql = $mysqli->query($sql);

if($hodnota == 1){
echo ‚Zapnuto led‘;
}
else{
echo ‚Vypnuto led‘;
}
echo “;
}

$sql = ‚SELECT * FROM arduino_ovladani WHERE modul=“led“‚;
$doSql = $mysqli->query($sql);
$hodnota = $doSql->fetch_assoc()[‚hodnota‘]; //načte hodnotu led z DB

$zapnutoChecked = $hodnota == 1 ? ‚checked‘ : “; //nastaví výchozí hodnotu radio buttonu
$vypnutoChecked = $hodnota == 0 ? ‚checked‘ : “;

echo “;
echo “;
echo ‚ Zapnout‘;
echo ‚ Vypnout‘;
echo “;
echo “;

function sanitize($input){
$input = htmlspecialchars($input);
$input = htmlentities($input);
$input = strip_tags($input);
$input = trim($input);
return $input;
}

$sql = ‚SELECT * FROM arduino_ovladani WHERE modul=“fan“‚;
$doSql = $mysqli->query($sql);
if($doSql->num_rows == 0){
$sql = ‚INSERT INTO arduino_ovladani (modul, hodnota) VALUES („fan“, 0)‘;
$doSql = $mysqli->query($sql);
}

if(isset($_POST[‚odeslano2‘])){ //pokud byl formulář odeslán
$hodnota2 = sanitize($_POST[‚stav2‘]);

$sql = ‚UPDATE arduino_ovladani SET hodnota2=“‚.$hodnota.'“ WHERE modul=“fan“‚;
$doSql = $mysqli->query($sql);

if($hodnota2 == 1){
echo ‚Zapnuto fan‘;
}
else{
echo ‚Vypnuto fan‘;
}
echo “;
}

$sql = ‚SELECT * FROM arduino_ovladani WHERE modul=“fan“‚;
$doSql = $mysqli->query($sql);
$hodnota2 = $doSql->fetch_assoc()[‚hodnota‘]; //načte hodnotu fan z DB

$zapnutoChecked = $hodnota2 == 1 ? ‚checked‘ : “; //nastaví výchozí hodnotu radio buttonu
$vypnutoChecked = $hodnota2 == 0 ? ‚checked‘ : “;

echo “;
echo “;
echo ‚ Zapnout fan‘;
echo ‚ Vypnout fan‘;
echo “;
echo “;

?>

mpro
10.2.2020 at 9:12

Tak se ten kod taky nejak zpitvořil, mohu to poslat jinam?

Zbyšek Voda
10.2.2020 at 14:24

V pohodě. Je to celkem čitelné 🙂
Případně můžete využít některou ze služeb jako Pastebin, popřípadě založit dotaz na našem fóru arduino-forum.cz

Popište prosím blíže, co konkrétné nefunguje.
Na kódu je zvláštní mj. část

echo “;
echo “;
echo ‚ Zapnout fan‘;
echo ‚ Vypnout fan‘;
echo “;
echo “;

Kliknutím na „Zapnout/Vypnout fan“ se nemůže nic stát, protože to vypisujete jen jako text.
Pokud chcete řídit stav, musíte vytvořit HTML formulář, jak je ukázáno na konci kódu v podkapitole „Konfigurační formulář“. Ta část začíná tagem

.
VladaA
17.12.2019 at 12:09

Možná se zeptám jako úplný primitiv, asi mi uniká základní princip. Jak je to s tou MAC a IP adresou zařízení? Abych mohl komunikaci přes internet používat, znamená to, že si musím někde (třeba na tom webzdarma.cz) založit stránku a k ní (k její IP adrese) se budu připojovat – to bych ještě pochopil.
Když ale přes toto webové rozhraní chci poslat příkaz do svého zařízení, které sedí na nějaké IP adrese přidělené dynamicky přes DHCP, tedy IP adresa může být každou chvíli jiná, jak tam něco pošlu, když tu adresu nemohu znát? Nebo to vždycky musí probíhat tak, že spojení nejdřív navážu z toho arduina na tu webovou stránku (její IP adresa je předpokládám vždycky pevná), pošlu tam dotaz a dostanu odpověď? Trochu mi to nesedí s pár let starou informací, že už všechna IP adresy byly vyčerpány a přešlo se na IPv6 a všude se stále objevují adresy ve formátu IPv4. Jakou roli v tomhle spojení hraje MAC adresa zařízení? Ta by měla být unikátní, to znamená že je někdo centrálně obhospodařuje a přiděluje? Nebo si ji mohu pro své zařízení zvolit libovolně?

Zbyšek Voda
18.12.2019 at 10:33

Odpověděl jsem Vám článkem 🙂

https://bastlirna.hwkitchen.cz/jak-je-to-s-ip-a-mac-adresami/

Na komentář by to bylo moc dlouhé 😀

Milan K
6.12.2018 at 22:00

Dobrý den
Měl bych dotaz ,když otevřu stránku config.php tak mě to hlásí chyby:
Warning: mysqli_connect(): (HY000/1044): Access denied for user ‚manwzcz4028’@’185.64.219.%‘ to database ‚arduino_ovladani‘ in /3w/wz.cz/m/man/config.php on line 6

Fatal error: Call to a member function query() on boolean in /3w/wz.cz/m/man/config.php on line 8

To též se děje i controller.php
Používám databáze u webzdarma.cz
A tyhle přihlašovací údaje do databáze:
$server = „sql2.webzdarma.cz“;
$user = „manwzcz****“;
$pass = „P4*****“;
$db = „arduino_ovladani“;
$mysqli = mysqli_connect($server, $user, $pass ,$db); //připojení k MySQL

Zkoušel jsem hledat chyby ,ale nevím jesli je chyba na straně skriptu nebo v databázi.
Děkuji za jakékoliv rady.
Kovář

Zbyšek Voda
10.12.2018 at 17:10

Dobrý den,
zdá se, že máte špatné přihlašovací údaje k databázi. Zkuste kouknout do administrace webhostingu a obnovit heslo k DB.
Popřípadě heslo k DB občas přijde emailem při zřizování hostingu, tak zkuste kouknoutdo emailu 🙂

h107
8.4.2018 at 18:51

Zdravím,
potreboval by som pomôcť s ovládaním arduina
(uno) cez internet (zmena stavu led) použil som tu uvedený návod, zmenil som len číslo pinu (3 na 8), php súbor mi v prehliadači vráti reťazec „led:1:“, vyzerá to tak, že arduino sa k serveru pripojí, ale nič sa nedeje, sériova linka nič nevypíše… neviem kde hľadať chybu.. Projekt meteostanice na rovnakom serveri s tým istým arduinom funguje bezproblémovo. Na čo sa zamerať. Vďaka za odpovede. H107

Zbyšek Voda
10.4.2018 at 15:22

Dobrý den, jestli máte na mysli ten poslední kód ve článku, tak bych si zkusil vypisovat hodnotu, kterou vrací client.read(); a uvidíte 🙂

h107
11.4.2018 at 22:19

Áno, ide o ten posledný kód..
Nemám veľa skúsenosti v tejto oblasti a aby som priblížil o čo ide – je to hobby projekt poskladaný podľa rôznych návodov z netu, mám na chalupe kameru z ktorej pravidelne aktualizované snímky si viem pozrieť cez web. K tomu som si vymyslel meteostanicu, aby som na stránke mal aj info o počasí a tak som sa dostal k arduinu (meteostanicu som rozbehal a funguje podľa očakávaní). Potom som si ešte vymyslel, že k tej meteostanici a hlavne kamere by bolo dobré mať svetlo, ktoré by som vedel cez web zapnúť/vypnúť (je tam síce niekoľko IR diód, ale v noci dosvietia len pár metrov) no tento kód mi už nefunguje..

Výstup z php stránky je ako v návode „led:1: resp. led:0:“ ale arduino nereaguje. Napadlo mi, či to nie je spôsobené free hostingom, ktorý na stránku pridáva reklamu a tým pádom to arduino neprečíta..

Potreboval by som poradiť polopate, čo konkrétne skontrolovať, vyskúšať. Teda ako a kam do kódu vložiť vypísanie client.read?

Neskôr by som oba kódy (meteostanica a ovládanie) chcel spojiť do jedného programu..

Zbyšek Voda
12.4.2018 at 8:41

Asi to bude tou reklamou, jak píšete.
Teď Arduino čeká, že mu přijde: „led:1“, ale ono kvůli reklamě dostane „<reklama>dalsi HTML&lt/reklama>led:1“ a je z toho zmatené.
Zkuste dát za: buffer[inBuffer] = client.read();
ještě: Serial.print(buffer[inBuffer]);

Po sériové lince to vypíše, co přišlo.

Jestli můžu poprosit, popište váš problém na arduino-forum.cz a dáme to tam nějak dokupy 🙂
Je to tam vhodnější na řešení větších problémů, než tady.

h107
12.4.2018 at 17:36

Tak som skúsil Serial.print(buffer[inBuffer]); ale nič sa nezobrazuje, písal som už aj na:

https://www.arduino-forum.cz/viewtopic.php?f=40&t=795&p=3369#p3369

circa
12.1.2018 at 12:29

Perfektní práce. Dlouho jsem hledal než jsem našel tento článek.
Díky moc
Milan

Joohanek
26.11.2017 at 18:59

Dobry den, je mozne zapsat do mysql vice udaju v jednom retezci. U „logger“ zapisujete udaj „hodnota“ a to sice takto: https://bastlirna.hwkitchen.cz/data/logger.php?hodnota=XXXX je mozno do toho retezce pridat vice udaju? napr: https://bastlirna.hwkitchen.cz/data/logger.php?hodnota=XXXXX?hodnota1=XXXXX?hodnota2=XXXX, Samozrejme, ze budu mit upravenou tabulku mysql a v arduinu to take zvladnu, ale netusim jaky by mel vypadat php soubor. pokud to vlozim zvlast, tak se mi vytvori vzdy radek pouze s jednim udajem a ja bych chtl do jednoho naspat vsechny 3 udaje naraz. Dekuji

Joohanek
26.11.2017 at 19:21

Uz jsem si vsiml, ze Tom v prispevku pode mnou pouziva oddelovac &. Snazim se editovat php script nejak takto, ale nedari se:

if($mysqli and isset($_GET[‚hodnota‘, ‚pocet‘])){ //pokud GET obsahuje ‚hodnota‘, pokračuj
$pocet = sanitize($_GET[‚pocet‘])
$hodnota = sanitize($_GET[‚hodnota‘]);
$sql = „INSERT INTO arduino_data (hodnota, pocet) VALUES („.$hodnota.“, „.$pocet.“)“; //sestavení SQL

Zbyšek Voda
26.11.2017 at 19:25

Když mate http://…/data.php?x=10&y=20

Tak hodnoty x a y zjistíte z
$_GET[“x”] a $_GET[“y”]

Zbyšek Voda
26.11.2017 at 19:28

Ta podmínka by pak musela být
if($mysqli and isset($_GET[“x”]) and isset($_GET[“y”])){

Joohanek
26.11.2017 at 19:40

Uz mi to jede. Dekuji moc za rychlo reakci. Ted se ucim s arduinem a zapojovat do toho jeste php uz zacina byt na me moc. 🙂 Diky

Zbyšek Voda
26.11.2017 at 20:57

Není zač, ať se daří 🙂

TomP
19.11.2017 at 11:14

Ahoj, řeším problém se kterým si už nevím rady. Pokud by se našel někdo kdo by mě nasměroval, budu velmi vděčný. Mám server NAS Synology, na něm běží PHP 5.6, webový server, MariaDB 5 a phpMydamin. Z arduin si po domácí síťi loguju spoustu věcí, jejichž hodnoty si pak zobrazuju na vytvořených www stránkách. Vše fungovalo……až do provedení aktualizace PHP, webového serveru, phpMydamin a MardiaDB 5. Od té do by se mi z arduin nezapsal žádný záznam. Pokud vložím záznam do DB tabulky pomocí www odkazu, např. „http://192.168.0.150/Arduino/Vysilac_01/logger.php?vysilac=1&teplota=20“, záznam se v pořádku zapíše. Kód v arduinu mám přesně takový jako je uvedený v čáti arduino – klient výše v článku. Díky za každou radu..

Zbyšek Voda
19.11.2017 at 11:24

Dobrý den,
teď mě nenapadá, čím by to mohlo být.
Začal bych tím, že se podíváte, jestli se Arduinu vůbec povede k serveru připojit (pošle se po sériové lince „OK“).

Každopádně zkuste ještě napsat na naše fórum arduino-forum.cz. Váš problém tam uvidí více lidí a třeba někdo bude vědět 🙂

TomP
19.11.2017 at 11:49

Arduino se k serveru připojí. Měl jsem za to, jestli není po aktualizaci v NASu problém v zápatí kódu pro poslání na server. Že něco co platilo již neplatí a je možná potřeba zápatí upravit.

if(client.connect(server2, 80)){
Serial.println(„Pripojeno k NASu“) ;
String postStr2 = kod;
postStr2 +=“&vysilac=“;
postStr2 += String(vysilac);
postStr2 +=“&teplota=“;
postStr2 += String(t);
postStr2 +=“&vlhkost=“;
postStr2 += String(h);
postStr2 +=“&baterie=“;
postStr2 += String(buffer);
client.print(postStr2);
client.println(„Host: http://192.168.0.103„);
client.println(„Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.9“);
client.println(„Connection: close“);
client.println();
client.stop();
}

Zkusím dát dotaz do zmiňovaného fóra. Díky

martinlinux
23.8.2017 at 15:13

Dobry den,
v priklade ovladanie LED(Arduino server) ma Arduino IDE problem s
ZAPNI pise toto:

sketch_aug23a:36: error: expected primary-expression before ‚?‘ token
client.println(„ZAPNI„);
^
sketch_aug23a:36: error: expected ‚:‘ before string constant
client.println(„ZAPNI„);

dakujem za odpovede.

Zbyšek Voda
23.8.2017 at 15:20

Dobrý den, zkuste si prosím znovu zkopírovat kód.
Při vkládání na web jsem špatně vyescapoval některé znaky. Teď už by to mělo být OK.

jiri.urban
14.12.2016 at 23:12

Ahoj pokouším se zprovoznit odesílání dat do databáze ale nějak se mi to nedaří chtěl jsme posílat jen obyčejně teplotu.

Zde je zdrojový kód arduina

#include
#include
#include

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x9C, 0xB7}; //MAC adresa
IPAddress ip(10,0,0,3); //IP adresa
char server[] = „arduinohome.8u.cz“; //URL adresa serveru
dht11 cidlo;
int dht11pin = 5;
int teplota;
int vlhkost;
EthernetClient client;

void setup() {
Serial.begin(9600);

if (Ethernet.begin(mac) == 0) {
Ethernet.begin(mac, ip);
}
delay(1000);
}

void loop() {

cidlo.read(dht11pin);
teplota = cidlo.temperature;
vlhkost = cidlo.humidity;

if(client.connect(server, 80)){
delay(1000);
Serial.println(„OK“);
client.print(„GET „);
client.println(teplota);
client.println(„Host: arduinohome.8u.cz“);
client.println(„Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8“);
client.println(„Connection: close“);
client.println();
Serial.println(teplota);
client.stop();
delay(5000);
}
}

snažím se s tím poprat už pár dní takže jsem vytvořil stejnou tabulku a vše abych eliminoval chybu ale stejně se mi to nepodařilo (tabulka má id, timestamp, hodnota)

když napíšu do prohlížeče tak se mi hodnota do databáze zapíše ale z arduina ne a ne zapsat.

Budu rád za jakoukoliv radu

Zbyšek Voda
14.12.2016 at 23:23

Dobrý den, jestli můžu z těchto informací soudit, tak problém bude v hostingu. To máte nějaký webhosting zdarma, že?
Nedávno jsem s jedním čtenářem řešil stejný problém. Řekl bych, že problém bude v tom, že při připojení na server dojde k přesměrování, se kterým si webový prohlížeč umí poradit, ale Arduino si s ním neporadí.
Web po připojení pravděpodobné vrátí HTTP odpověď s přesměrováním, kde je uvedeno i kam se dotaz má přesměrovat.

Řešením je buďto tuto odpověď serveru analyzovat (tedy zjistit tu koncovou adresu) a poslat dotaz až na koncovou adresu (toto by snad mělo stačit udělat jednou, čímž si zjistíte adresu přesměrování a potom už se z Arduina vždy dotazovat přímo na tuto adresu), nebo přejít na jiný hosting. V případě, který jsem zmiňoval dříve, se problém povedlo vyřešit přechodem na placený hosting, konkrétně Wedos, kde k žádnému přesměrování nedochází. Možná existuje i nějaký free hosting, který by fungoval, ale v tomto se moc neorientuji.

jiri.urban
15.12.2016 at 23:56

Zkoušel jsem to na localhostu a tam to jde. Takže děkuji za radu. Bylo to na endoře na free hostingu. Myslíš že na endoře u placeného hostingu to bude fungovat správně ?? nebo takov přesměrování nejspíše budou mít udělaný u free i u placeného hostingu.

Zbyšek Voda
17.12.2016 at 9:50

V tomto se nevyznám, takže nedokážu soudit a nerad bych vám kecal 🙂
Jak už jsem psal, vím, že na Wedosu to fungovalo.

Korčagin
29.10.2016 at 11:46

Dobrý den, dělám si podle návodu

https://bastlirna.hwkitchen.cz/programovani-webovych-rozhrani-pro-arduino/

meteostanici. Zatím ale nemohu rozchodit zápis hodnot do MySQL.
Nefunguje mi to volání „loggeru“. Když to dám ručně do prohlížeče, tak mi to hodnoty do MySql zapisuje. Např:

Nefunguje mi tato část programu na Arduinu: (IP a MAC jsou v pořádku – odzkoušeno PINgem atd…)
****************************************************************************************
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //MAC adresa
IPAddress ip(192, 168, 1, 78);
char server[] = „sazeni.borec.cz“; //URL adresa serveru
int tempe = 37;
int interval = 1;
int ijk;
EthernetClient client;

void setup() {
Serial.begin(9600);
interval = (interval*60-2);
Serial.print(„Interval zobrazovani je „);
Serial.print(interval/60+1);
Serial.println(“ minut“);
// ************************************************************************************************************
while(!Serial) {} // Wait
while(!bme.begin()){
Serial.println(„Could not find BME280 sensor!“);
delay(1000);
}
// *************************************************************************************************************
Ethernet.begin(mac, ip);
Serial.print(„Local IP „);
Serial.println(Ethernet.localIP());
delay(100);
}
void loop() {
printBME280Data(&Serial);
if(client.connect(server, 80)){
delay(1000);
Serial.println(“ –> OK“);
client.println(„GET http://sazeni.borec.cz/ARmetLogger1.php?teplo=40&tlak=980&vlhko=50„);
// client.println(tempe);
client.println(„Host: sazeni.borec.cz“);
client.println(„Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8“);
client.println(„Connection: close“);
client.println();
client.stop();
for(ijk=0;ijk<=interval;ijk++)
{
delay(1000);
}
}
else {
Serial.println("Spojeni se nepovedlo ");
client.stop();
delay(100);
}
}

Pokud na to bude mít někdo náladu a čas, můžete to vyzkoušet. Na stránce

http://www.sazeni.borec.cz si funkcí "Počasí na Tajchu"
zobrazím graf a tabulku počasí.

Poradí něko???
S pozdravem
==============================================
Pavel Pokorný
Liberec

Zbyšek Voda
30.10.2016 at 16:28

Dobrý den, můžete prosím k problému napsat ještě další info?
Jak se projevuje to, že program nefunguje? Nepodaří se připojit k síti, nevypisuje “ -> OK“, nebo se zdá, že funguje, jenom neloguje na web?

Zkoušel jste přímo ten program ze článku (s vaší URL) ?

Korčagin
30.10.2016 at 18:55

K síti připojený jsem. Na 192.168.1.78 si PINGnu. Když odpojim sítový kabell nebo když je Arduino bez napájení, tak PING nefunguje. Když jej opětovně připojím tak PING reaguje normálně. To “ -> OK“ mi to vypisuje. Nefunguje mi ten „… GET htttp://sazeni…“ – to volání ARmetLogger1.php. Když to zadám ručně do prohlížeče, tak to hodnoty do MySQL zapíše.

Korčagin
30.10.2016 at 20:16

Jo jo, program jsem dá se říci doslova okopíroval, pouze jsem změnil „bastlirna.hwkitchen.cz“ na „sazeni.borec.cz“ a jméno loggeru na ARmetLogger1.php

Zbyšek Voda
1.11.2016 at 19:30

Dobře. Pojďme od sebe zkusit odizolovat jednotlivé části a zjistit, kde je problém.

Podle chování shieldu při pingání v místní síti komunikuje.
Zkusil bych otestovat, jestli se mu podaří dostat i mimo síť 🙂

Co vám vypisuje sériová linka na tomto příkladu https://www.arduino.cc/en/Tutorial/WebClient?

wegac
6.9.2016 at 8:17

ahoj,
potreboval bych do tabulky zapisovat nejen cisla, ale i pismena, poradite prosim, co zmenit jak v kodu pro arduino, tak v PHP? databazi jsem nastavil na text
diky

Zbyšek Voda
6.9.2016 at 15:04

Dobrý den, url pro odeslání čísla vypadá takto:
https://bastlirna.hwkitchen.cz/data/logger.php/?hodnota=1000
pro odeslání textu bude tedy vypadat nějak takto:
https://bastlirna.hwkitchen.cz/data/logger.php/?hodnota='ahoj‚, což pokud se převede do tvaru validního url bude vypadat takto:
https://bastlirna.hwkitchen.cz/data/logger.php/?hodnota=%27ahoj%27

Miroslav
4.7.2016 at 7:15

Diky, tenhle clanek je uplne super navod

Honza
3.4.2016 at 8:56

Kromě načítání dat do myslq bežící na NASu Synology už delší dobu jsem se nyní pokus i druhý směr – ovládání arduina jako klienta pomocí dat v databázi jak je ukázáno v závěru článku s tím že jsem ti upravil pro svůj lokální server na NASu a vše fungovalo. Pak jsem však provedl ubdate Synolgy s DSM 5.2 na DSM 6 což v sobě má i update PHP z verze 5.5 na 5.6. Po tomto updatu však nastal problém-přestože při spuštění scriptu controller.php z prohlížeče dostanu správnou odezvu led:1: tak to arduina se načte do bufferu:
buffer_délka=226
buffer obsah:

400 Bad Request

Bad Request
Your browser sent a request that this server could not understand.

Pokud kód přesměruji na externí controller.php na bastlirna.hwkitchen.cz tak se správně vráti 6 znaku led:1:
Nemáte prosím tip jak tento problém napravit.
Děkuji

Honza
3.4.2016 at 8:59

v hlaviče načtené do bufferu (co se bohužel v předchozím příspěvku nezobrazilo) je ještě uvedeno DOCTYPE HTML PUBLIC „-//IETF//DTD HTML 2.0//EN“

vaseks0001
3.3.2016 at 17:14

Dobrý den,
Super článek, ale u posledního příkladu mi to hází chybu.

buffer[i] = “; //nastaví všechny prvky buffer na znak konce řetězce

a píše to :

test_Mysql:39: error: empty character constant

buffer[i] = “; //nastavĂ­ všechny prvky buffer na znak konce Ĺ™etÄ›zce

^

exit status 1
empty character constant

Pomohl by mi někdo s tímto problémem? Moc děkuji

Zbyšek Voda
4.3.2016 at 10:54

Dobrý den, omlouvám se, byla to moje chyba. V kódu už je to opraveno.
Nevšiml jsem si, že HTML také escapuje znak \0
Správný tvar je:
buffer[i] = ‚\0‘; (obě uvozovky nahoře, WordPress nějak sám dává tu první dolů :/)

Tomáš Jurman
9.2.2016 at 7:55
Pepepi
8.2.2016 at 18:39

Dobrý den,
perfektní .
Super, po přečtení mě začala spousta věcí do sebe zapadat 🙂 . Beru jako úvod do problematiky a podklady ke studiu 🙂 . Pouštím se do toho.

Děkuji

Honza
8.2.2016 at 10:44

Super článek, uvedené informace jsem dohledával po kouskách cca 14 dní a když jsem si to dal do kupy tak to autor servíruje na stříbrném podnose 🙂
Jen doplním ,že MYSQL lze bez potřeby dalších znalostí spustit na domácím NASu od Synology včetně phpMyAdmin a mít to tak pod jednou střechou kdy systém bude pracovat i při případném výpadku internetu. Uvedené kódy lze s drobnou úpravou použít i pro NodeMCU a přes wifi tak přípojit senzory i tam kde není kabel, navíc i levněji.

MIlan
13.2.2016 at 12:30

Veľmi dobrý článok. Za zmienku by stala aj aplikácia tretích strán a to Exosite portal https://portals.exosite.com/login dokonca pre arduino existuje hotová knižnica.

Napsat komentář