Forskel mellem versioner af "WeMOS Web Publicering"

Fra Holstebro HTX Wiki
Skift til: navigering, søgning
(PHP-kode til indlæsning af data)
(PHP-kode til indlæsning af data)
(2 mellemliggende versioner af den samme bruger vises ikke)
Linje 158: Linje 158:
 
Når begge tabeller er oprettet, så skal man have oprettet noget server-kode, som kan modtage de værdier man ønsker at placere i databasen. I starten burde man have noget tjek for om man (i dette tilfælde WeMOS'en) var logget ind på serveren, men for ikke at komplicere dette eksempel yderligere, så er det udeladt.
 
Når begge tabeller er oprettet, så skal man have oprettet noget server-kode, som kan modtage de værdier man ønsker at placere i databasen. I starten burde man have noget tjek for om man (i dette tilfælde WeMOS'en) var logget ind på serveren, men for ikke at komplicere dette eksempel yderligere, så er det udeladt.
  
Nedenstående kode starter med at henvende sig til filen med login-oplysninger:
+
Nedenstående kode, som i eksemplet er placeret i en fil der hedder setValue.php, starter med at henvende sig til filen med login-oplysninger:
  
 
<source lang="PHP">
 
<source lang="PHP">
Linje 223: Linje 223:
 
Dette vil give følgende resultat, hvis ellers tingene virker som de skal:
 
Dette vil give følgende resultat, hvis ellers tingene virker som de skal:
  
[[fil:WeMOS-opret4-DB.png|Respons fra serveren, ved opdatering af value1|450px]]<br />
+
[[fil:WeMOS-opret4-DB.png|Respons fra serveren, ved opdatering af value1|350px]]<br />
 
''Respons fra serveren, ved opdatering af value1''
 
''Respons fra serveren, ved opdatering af value1''
 +
 +
Når man skal have WeMOS'en til at lægge noget op, så er det selvfølgelig denne URL man anvender, hvor man så kan henvende sig til de felter man har lavet i PHP-koden, i stedet for value1 og med de værdier der er relevante.
 +
 +
Det at man anvender GET-metoden i stedet for POST, gør igen at systemet ikke er så sikkert, men det er til gengæld simplere og lettere at forstå.
 +
 +
==PHP-kode til visning af data==
 +
Når man har fået det til at fungere med at opdatere og lægge noget ind i de relevante tabeller, så skal man have implementeret den side, som brugeren skal kunne se, nemlig der endelige resultat af anstrengelserne.
 +
 +
Dette eksempel er blot lavet til at få vist værdierne, hvor man i et endeligt produkt vil kunne lave siden, så den giver mere værdi for brugeren.
 +
 +
Nedenstående kode anvender igen db-info.php til at etablere forbindelsen til databasen.
 +
 +
Herefter trækker koden data ud af databasen ved hjælp af MySQL statementen SELECT<ref>[https://www.w3schools.com/php/func_mysqli_fetch_field.asp PHP objektorienteret måde at trække ud fra en MySQL database]</ref>.
 +
 +
Koden er placeret i index.php, så det er den side man får vist ved at henvende sig til roden af mappen på serven. Man kunne også placere det i en underside, hvor man så først skulle vær logget ind, inden man kan få vist siden. Denne del er ikke vist i dette eksempel.
 +
 +
<source lang="PHP">
 +
<?php
 +
/*
 +
* Bent Arnoldsen, Holstebro HTX 2020
 +
*
 +
* Aktiveres med domæne/path/index.php
 +
*/
 +
 +
/*
 +
  * Her kunne tjekkes for et login-system, hvor man kunne anvende sessions, så man ved at der
 +
  * er logget ind, og at brugeren må se det viste
 +
  */
 +
 +
include ("db-info.php");
 +
?>
 +
<html>
 +
<h2>Visnings-side for WeMOS dataopsamling</h2>
 +
<?php
 +
$tid = time();
 +
$sql = "SELECT * FROM ValueTabel";
 +
$result = $mysqli->query($sql);
 +
if ($result->num_rows > 0) {
 +
    $row = $result->fetch_assoc();
 +
    echo "Værdi: " . $row["value1"]. " - Opdateret: " . date("d-m-Y G:i:s", $row["tid"]) . " for " . ($tid - $row["tid"]) . " sekunder siden<br>";
 +
} else {
 +
    echo "Ikke noget indhold";
 +
}
 +
$sql = "SELECT * FROM OpsamlTabel";
 +
$result = $mysqli->query($sql);
 +
 +
if ($result->num_rows > 0) {
 +
    echo("<table border='1'><tr><th>ID</th><th>Værdi</th><th>Tid</th></tr>");
 +
    // output data of each row
 +
    while($row = $result->fetch_assoc()) {
 +
        echo "<tr><td>" . $row["ID"]. "</td><td>" . $row["value2"]. "</td><td>" . date("d-m-Y G:i:s", $row["tid"]) . "</td></tr>";
 +
    }
 +
    echo("</table>");
 +
} else {
 +
    echo "Ingen data i OpsamlTabel";
 +
}
 +
$mysqli->close();
 +
?>
 +
</html>
 +
</source>
 +
 +
Visningen af siden kommer ved at henvende sig til følgende URL:
 +
 +
htx-elev.ucholstebro.dk/klasse-mappe/user/
 +
 +
[[fil:WeMOS-vis-DB.png|Resultatet af den kode, som trækker værdierne ud af databasen|450px]]<br />
 +
''Resultatet af den kode, som trækker værdierne ud af databasen''
 +
 +
Det over tabellen er en visning af den post, som bare opdateres i databasen, mens det der er placeret i tabellen er fra de poster, hvor man tilføjer nye værdier løbende.
 +
 +
==Koden samlet==
 +
Koderne i eksemplet her kan hentes i [[media:WeMOS-Web-publ.zip|Denne ZIP-fil]], men kræver stadig at man skal oprette databasen manuelt, og at man tilretter efter sine ønsker.
  
 
==Referencer==
 
==Referencer==
 
<references />
 
<references />
 
[[Kategori:WeMOS]]
 
[[Kategori:WeMOS]]

Versionen fra 10. jan 2020, 07:12

Den grundlæggende ide i denne kode er at sende en kommando fra den serielle monitor, og via WeMOS WiFi sende en henvendelse til en webserver[1] med et lille PHP-script, der kan sende en mail, med et indhold bestem af det der er indtastet i Serial Monitor

Strukturen i systemet, der beskrives på denne side

Dette beskriver kort hvilke elementer der er i spil i dette eksempel, og hvilken rolle de har

Den overordnede ide er at kunne måle noget elektrisk og præsentere disse ting på nettet, mere eller mindre offentligt, alt efter hvad det er man præsenterer.

WeMOS Enhed

Der skal være en WeMOS enhed, som programmeres op med de funktioner, så den kan måle det er ønskes publiceret. Det kan i princippet være en enkelt kontakts værdi man vil kunne se, og i mere komplicerede tilfælde kan det være logning af et system med mange variable værdier, som et alarmsystem, en vejrstation, overvågning af et drivhus, eller hvad man har fantasi til.

Ud over at mål skal WeMOS enheden forbinde til en WiFi forbindelse.

Når den har forbindelse til WiFi skal den sende sine måledata til en web-server. Dette kræver en del sikkerhedsmæssige overvejelser, så man ikke umiddelbart gør den anvendte webserver sårbar over for spam og mere alvorlig indtrængen.

Ved anvendelser på Holstebro HTX's system kan det være en fordel at kunne tilgå den del af webserveren der ligger internt, men det kan også være problematisk, da man skal ind på skolens netværk for at kunne tilgå den, og det er ikke så enkelt med en WeMOS.

WiFi Netværk

For at WeMOS kan kommunikere skal den tilsluttes et WiFi netværk, som skal kunne give adgang til den server hvor data skal uploades.

Upload side

WeMOS enheden skal henvende sig til en Web-Server ved at den sender nogle værdier til et PHP-script, som PHP-scriptet så lagrer i en MySQL-database.

Database

Databasens, som i dette tilfælde er en MySQL-database, skal indeholde nogle tabeller der kan modtage de værdier man ønsker at offentliggøre.

Site til visning af værdier

Der skal opbygges et web-site, som kan vise de ønskede værdier - det kan være en simpel index.php, som det vises her i eksemplet, eller man kan opbygge et helt site med login og alle mulige andre funktioner, hvor man laver grafisk visning og evt. en tolkning af de målte værdier.

Forbindelse til WiFi

Selve forbindelsen til WiFi er lavet som beskrevet ved WeMOS Server Connection, og skal blot etablere forbindelsen til WiFi netværket.

For at den samlede kode kan fungere, så skal det netværk der forbindes til have forbindelse til internettet, så man kan komme i kontakt med webserveren med PHP-scriptet.

Opsætning til HTTP-request

For at man kan sende en besked til webserveren, så skal man have adgange til HTTP-request biblioteket, og der skal oprettes at HTTP-objekt.

Dette sker i følgende kode:

#include <ESP8266HTTPClient.h>

HTTPClient http;

int httpCode;

Webserver henvendelse

For at henvende sig til webserveren på simpel vis anvendes GET-metoden. Hvis man skulle gøre det med større sikkerhed, så skulle man anvende POST-metoden[2], og man burde også sikre webserveren med et login - det er ikke gjort i dette eksempel.

Selve webserveren har en http-adresse, der angives i en variabel som vist her:

const String serverAddress = "http://htx-elev.ucholstebro.dk/HX-class/user/";      // Webserverens URL

  String stringToSend = serverAddress;  // Serveradressen der skal henvendes til

På Holstebro HTX har vi webserver på adressen htx-elev.ucholstebro.dk, hvor man kan uploade sine scipts, når holdet er oprettet med de brugere der er på holdet. Serveren har installeret en mailserver, så man kan sende mails fra scriptet. Webserveren er nærmere beskrevet på Beskrivelse af htx-elev Webserver.

Man kan naturligvis også anvende andre webservere, hvis de understøtter PHP og har en mailserver tilknyttet.

Inde på webserveren ligger PHP-filen, som skal tilføjes henvendelsen som vist her:

  stringToSend += "sendMail.php?send="; // Filnavnet og parameter-navn

Der tilføjes også navnet på parameteren (send).

Endelig tages et input fra den serielle monitor, og der sikres at det kun er selve det indtastede man tager med. Dette tilføjes henvendelsen:

    String param = Serial.readStringUntil('\n');  // Læs en hel streng
    param.trim();                         // Fjern mellemrum og linjeskift fra start og slut
    stringToSend += param;                // Indholdet der skal sendes

Herefter foretages selve henvendelsen til webserveren med en HTTP-henvendelse:

    http.setTimeout(2000);                                 // Use 2 seconds timeout for HTTP connection
    http.begin(stringToSend);                              // Start HTTP connection and send HTTP header

Connection response

Henvendelsen til webserveren giver en respons, som man skal tjekke for at se om henvendelsen gik godt.

Dette returnerer en kode:

    httpCode = http.GET();                                 // Get response from HTTP request

Henvendelsen giver også en respons, der her udskrives til seriel monitor

    if(httpCode > 0)                                       // httpCode will be negative on error
    {      
      Serial.printf("[HTTP] GET... code: %d\n", httpCode); // Response from server is not an error
      if(httpCode == HTTP_CODE_OK) {                       // Response from server is HTTP CODE 200
        String payload = http.getString();
        Serial.println(payload);
      }
    } else {
      Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }
    http.end();

Efter endt henvendelse lukkes forbindelsen igen.

PHP-kode til indlæsning af data

Inde på webserveren placeres et lille PHP-script, laves ud fra følgende koncept. Scriptet udnytter at der ligger en MySQL database på serveren. Hjælp til kontakt til databasen og funktioner til at lægge noget ind stammer fra w3scholls[3].

For at gøre det enkelt at vedligeholde oprettes en lille simpel fil, som forbinder til databasen. Hvis man bruger HTX-serveren i Holstebro, så kan man finde disse oplysninger inde på ens private område af serveren i en readme-fil. HTX-serveren i Holstebro er nærmere beskrevet på Beskrivelse af htx-elev Webserver.

<?php
$mysqli = new mysqli("localhost","my_user","my_password","my_db");

if ($mysqli -> connect_errno) {
  echo "Failed to connect to MySQL: " . $mysqli -> connect_error;
  exit();
}
?>

Database til værdierne

For kunne lægge værdier ind i databasen skal der oprettes tabeller til det. Disse tabeller oprettes via phpMyAdmin. Til dette eksempel skal der oprettes to tabeller, hvor der i den ene tabel opdateres ind i en post, som også skal oprettes med phpMyAdmin, og den anden tabel skal bare oprettes. Til eksemplet her vil tabellerne skulle oprettes med følgende felter:

ValueTabel
Navn Type Egenskab Værdi
ID INT Auto Increment 1
value1 INT ingen tal
tid INT ingen 0
OpsamlTabel
Navn Type Egenskab
ID INT Auto Increment
value2 INT ingen
tid INT ingen

For at oprette disse tabeller vil man på Holstebros HTX-server skulle logge ind på phpMyAdmin som beskrevet i dokumentationen for webserveren.

Ved at vælge sin database (hedder det samme som brugernavnet, man har kun adgang til den ene database), så kan man oprette en tabel som vist her:

Oprettelse af tabel til at indeholde værdier
Oprettelse af tabel til at indeholde værdier

Tabellens felter navngives, som vist her, hvor der her er brugt eksempel-navne, men hvor det klart vil være en fordel for forståelsen af programmet, hvis man anvender nogle navne som siger noget om hvad felterne indeholder, som der fx er brugt navnet tid, hvilket indikerer et det er tidspunktet for opdateringen af værdien.

Angivelse af feltnavne og egenskaber til at indeholde værdier
Angivelse af feltnavne og egenskaber til at indeholde værdier

Læg mærke til at der er angivet at feltet ID skal være det primære felt, og at det skal Autoincremente - lige netop for denne tabel er det ikke så relevant, men normalt giver det en vigtig egenskab, nemlig at man får sat en ID på hver post i tabellen, så man senere kan henvende sig til lige netop denne post, ved at referere til ID'et.

For at koden der skal opdatere kan fungere, så er vi nødt til at have en enkelt post lagt ind i denne tabel. Det gør man ved at vælge tabellen, og bruge fanebaldet Indsæt, så man kan sætte et sæt værdier i posten, som senere kan opdateres, som vist her:

Oprettelse af post i tabellen med angivne værdier
Oprettelse af post i tabellen med angivne værdier

Kode til at lægge data ind i tabellen

Når begge tabeller er oprettet, så skal man have oprettet noget server-kode, som kan modtage de værdier man ønsker at placere i databasen. I starten burde man have noget tjek for om man (i dette tilfælde WeMOS'en) var logget ind på serveren, men for ikke at komplicere dette eksempel yderligere, så er det udeladt.

Nedenstående kode, som i eksemplet er placeret i en fil der hedder setValue.php, starter med at henvende sig til filen med login-oplysninger:

<?php
/* 
 * Bent Arnoldsen, Holstebro HTX 2020
 *
 * Aktiveres med domæne/path/setValue.php?valueName=Value
 */

 /*
  * Her bør der tjekkes for et login-system, hvor man kunne anvende sessions, så man ved at der
  * er logget ind, og at brugeren er autoriseret
  */

include ("db-info.php");
$message = "";

// Her opdateres en værdi value1 ind i en eksistrende tabel ValueTabel
if (isset($_GET['value1'])) {
    $value1 = $mysqli -> real_escape_string($_GET['value1']);  // Sikring mod SQL-injections
    $value1 = intval($value1);  // Konverter til heltal
    $tid = time();
    $sql = "UPDATE ValueTabel SET value1=$value1, tid=$tid WHERE ID=1";

    if ($mysqli->query($sql) === TRUE) {
        $message .= "Opdateret value1 til $value1<br />";
    } else {
        $message .= "Error updating record: " . $mysqli->error . "<br />";
    }
}

// Her lægges en ny værdi value2 ind som en ny post i en eksistrende tabel OpsamlTabel
if (isset($_GET['value2'])) {
    $value2 = $mysqli -> real_escape_string($_GET['value2']);  // Sikring mod SQL-injections
    $value2 = intval($value2);  // Konverter til heltal
    $tid = time();
    $sql = "INSERT INTO OpsamlTabel (value2, tid) VALUES ($value2, $tid)";

    if ($mysqli->query($sql) === TRUE) {
        $message .= "Opdateret value2 til $value2<br />";
    } else {
        $message .= "Error updating record: " . $mysqli->error . "<br />";
    }
}

$mysqli->close();
?>
<html>
<h2>Database-System</h2>
<p><?php echo $message; ?></p>
</html>

Når der er etableret en forbindelse til databasen, så tjekkes der hvilken værdi man vil henvende sig til, og alt efter værdien og indholdet man lægger ind, så laves der en behandling af data - en vigtig ting at tage med real_escape_string, som sikrer at man ikke kan sende ondsindede kommandoer til databasen, så man kan få den til at afsløre sig, og at man kun kan modtage de ting man ønsker.

Test af PHP-scriptet

For at teste om PHP-scriptet virker, og at det faktisk får fat i databasen, så kan man henvende sig til serveren direkte via en browser med følgende URL:

htx-elev.ucholstebro.dk/klasse-mappe/user/setValue.php?value1=123

Hvor man selvfølgelig anvende sin egen placering på HTX-serven i stedet for /klasse-mappe/user/.

Dette vil give følgende resultat, hvis ellers tingene virker som de skal:

Respons fra serveren, ved opdatering af value1
Respons fra serveren, ved opdatering af value1

Når man skal have WeMOS'en til at lægge noget op, så er det selvfølgelig denne URL man anvender, hvor man så kan henvende sig til de felter man har lavet i PHP-koden, i stedet for value1 og med de værdier der er relevante.

Det at man anvender GET-metoden i stedet for POST, gør igen at systemet ikke er så sikkert, men det er til gengæld simplere og lettere at forstå.

PHP-kode til visning af data

Når man har fået det til at fungere med at opdatere og lægge noget ind i de relevante tabeller, så skal man have implementeret den side, som brugeren skal kunne se, nemlig der endelige resultat af anstrengelserne.

Dette eksempel er blot lavet til at få vist værdierne, hvor man i et endeligt produkt vil kunne lave siden, så den giver mere værdi for brugeren.

Nedenstående kode anvender igen db-info.php til at etablere forbindelsen til databasen.

Herefter trækker koden data ud af databasen ved hjælp af MySQL statementen SELECT[4].

Koden er placeret i index.php, så det er den side man får vist ved at henvende sig til roden af mappen på serven. Man kunne også placere det i en underside, hvor man så først skulle vær logget ind, inden man kan få vist siden. Denne del er ikke vist i dette eksempel.

<?php
/* 
 * Bent Arnoldsen, Holstebro HTX 2020
 *
 * Aktiveres med domæne/path/index.php
 */

 /*
  * Her kunne tjekkes for et login-system, hvor man kunne anvende sessions, så man ved at der
  * er logget ind, og at brugeren må se det viste
  */

include ("db-info.php");
?>
<html>
<h2>Visnings-side for WeMOS dataopsamling</h2>
<?php
$tid = time();
$sql = "SELECT * FROM ValueTabel";
$result = $mysqli->query($sql);
if ($result->num_rows > 0) {
    $row = $result->fetch_assoc();
    echo "Værdi: " . $row["value1"]. " - Opdateret: " . date("d-m-Y G:i:s", $row["tid"]) . " for " . ($tid - $row["tid"]) . " sekunder siden<br>";
} else {
    echo "Ikke noget indhold";
}
$sql = "SELECT * FROM OpsamlTabel";
$result = $mysqli->query($sql);

if ($result->num_rows > 0) {
    echo("<table border='1'><tr><th>ID</th><th>Værdi</th><th>Tid</th></tr>");
    // output data of each row
    while($row = $result->fetch_assoc()) {
        echo "<tr><td>" . $row["ID"]. "</td><td>" . $row["value2"]. "</td><td>" . date("d-m-Y G:i:s", $row["tid"]) . "</td></tr>";
    }
    echo("</table>");
} else {
    echo "Ingen data i OpsamlTabel";
}
$mysqli->close();
?>
</html>

Visningen af siden kommer ved at henvende sig til følgende URL:

htx-elev.ucholstebro.dk/klasse-mappe/user/

Resultatet af den kode, som trækker værdierne ud af databasen
Resultatet af den kode, som trækker værdierne ud af databasen

Det over tabellen er en visning af den post, som bare opdateres i databasen, mens det der er placeret i tabellen er fra de poster, hvor man tilføjer nye værdier løbende.

Koden samlet

Koderne i eksemplet her kan hentes i Denne ZIP-fil, men kræver stadig at man skal oprette databasen manuelt, og at man tilretter efter sine ønsker.

Referencer