Overenie kradnutých vozidiel - Arduino + Ethernet / ESP32 / ESP8266

15.11.2020

Prehlásenie: Predmetom článku je ukázať možnosť web scrapingu mikrokontrolérovou platformou na webstránkach poskytujúcich verejné údaje. Všetky údaje stiahnuté z webovej stránky bežia iba v RAM pamäti mikrokontroléru a sú ukladané do databáz, pamätí tretích strán. Údaje v RAM pamäti existujú iba po dobu výpisu na UART rozhranie - max. do 250 ms.

Stránka https://www.minv.sk/?odcudzene-mot-vozidla Ministerstva vnútra Slovenskej republiky poskytuje verejné údaje informatívneho charakteru o kradnutých vozidlách. Využíva HTML formulár, do ktorého je možné zadať EVČ (Evidenčné číslo) vozidla, alebo jeho VIN kód.

Po spracovaní formulára je výstupom informácia o počte nájdených záznamov: Podmienke vyhovuje: 0 záznamov, prípadne Podmienke vyhovuje: 1 záznam. V prípade jedného záznamu sa dané EVČ, alebo VIN kód nachádza v databáze kradnutých vozidiel, stránka vypíše aj ďalšie doplnkové informácie o vozidle do HTML tabuľky a to:

  • Druh vozidla
  • Značka
  • Obchodný názov
  • Farba
  • EČ (Evidenčné číslo)
  • Číslo duplikátu
  • Štát registrácie
  • VIN
  • Dátum a čas odcudzenia od
  • Dátum a čas odcudzenia do

Pre získanie týchto informácii môžeme využiť mikrokontróler ako parser a zároveň scraper. Parser dokáže prečítať HTML stránku po jednotlivých riadkoch a scraper z nich dokáže získať konkrétne informácie. Mikrokontroléry, ktoré využijeme (Arduino + Ethernet, ESP8266, ESP32) budú stránku používať rovnako, ako človek prostredníctvom prehliadača, ktorý do formulárov zadá informáciu pre hľadanie v podobe EVČ, alebo VIN kódu a načíta si výstup.

V prvom kroku je nutné vyhotoviť HTTP spojenie, prípadne šifrovaný variant - HTTPS. Nakoľko Arduino v spojení s Ethernet modulom / shieldom nepodporuje HTTPS spojenie, vzorovo si ukážeme pripojenie iba pre HTTP pre všetky tri spomenuté platformy . Od mája roka 2020 je na stránke dostupné aj HTTPS variant. Pre toto spojenie je nutné použiť fingerprint certifikátu webservera v SHA1 formáte pre mikrokontróler ESP8266, alebo Root CA certifikát v .pem formáte (CA Disig Root R2) pre mikrokontróler ESP32.

Pre spojenie je možné využiť vstavané príklad pre Webclienta, ktorý umožňuje vytvoriť GET request a získať informácie zo stránky. Pri bližšej analýze kódu HTML stránky je zrejmé, že formulár prijíma dáta POST metódou. Pre EVČ využíva parameter ec, pre VIN kód parameter vin.

Pôvodný sketch je tak nutné poupraviť na prenos dát POST metódou a pridať parameter s hodnotou, ktorú budeme posielať. Potrebné je tiež poupraviť Content-Type na form encoded. Dĺžka requestu závisí od dĺžky payloadu, ktorý posielame. Premenná my_datas obsahuje dáta s EVČ, napríklad "AA123ZZ". 

Odpoveďou webservera (v response) je HTTP hlavička a celá HTML stránka, ktorú je možné parsovať po riadkoch a vykonať akciu. V prípade, že mikrokontróler narazí na riadok HTML stránky obsahujúci hodnotu Podmienke vyhovuje: 0 záznamov, informuje mikrokontróler o tom, že po vozidle nie je vyhlásené pátranie a ingoruje zvyšok HTML stránky.

V prípade, že narazí scraper na hodnotu Podmienke vyhovuje: 1 záznam, vypíše o tejto skutočnosti aj informáciu na UART monitor a informuje o hľadanom vozidle. Následne scraper dokáže zo zdrojového kódu vytiahnuť spomínané informácie o vozidle, ktoré sú na HTML stránku vypísané. Scraper očakáva informáciu na určitých miestach zdrojového kódu v HTML tabuľke v jednotlivých riadkoch tabuľky na základe preddefinovaných textov, ktoré obsahujú. 

Aby bolo možné zadávať rôzne EVČ na overenie priamo počas bežiacej aplikácie mikrokontroléra, finálna aplikácia využíva UART monitor aj pre vstup a tým umožňuje načítanie informácie o EVČ, ktoré chce používateľ preveriť. Po prijatí dát mikrokontróler vykoná jednorázový request na predmetnú HTML stránku, kde spustí formulár so zadaným EVČ (odosielaný parameter ec s hodnotou EVČ).

Zároveň je však možné zadať aj viacero EVČ. Mikrokontróler načítava EVČ po koniec riadia, t.j. po ukončovací znak '\n'. Ukončenie riadku je nastavené na zadaný reťazec automaticky. Zadaním EVČ v tvare: AA123AA\nXX123XX\nYY123YY\nZZ123ZZ je tak možné zadať 4 EVČ zároveň a mikrokontróler vykoná 4 samostatné requesty s každým zo zadaných EVČ jednotlivo. UART má samostatný buffer. Teda, informáciu príjme aj v prípade, že UART neobsluhuje programovo (neustálym načítaním). Dáta, ktoré sú v buffri obsiahnuté sa tak postupne vykonajú (overí sa každé zadané evidenčné číslo samostatne).

Pri Arduine Uno má UART buffer veľkosť 64B. Celkovo je tak možné zadať 7 EVČ s ukončovacími znakmi zároveň. Platforma ESP8266 má buffer veľkosti 128B a ESP32 dokáže emulovať buffer softvérovo až na veľksoť 1024B. Zadať je okrem štandardných EVČ aj iné, napríklad C, F značky. Odozva systému závisí aj od použitej platformy. Arduino s Ethernet shieldom stiahne spracovať celú HTML stránku za cca 7 sekúnd od vykonania requestu (načíta 458 riadkov kódu postupne riadok-po-riadku, ktoré prepisuje v RAM pamäti v dynamickej premennej).

Fragment zdrojového kódu, - scraping Druhu vozidla (osobné, nákladné vozidlo) z dvojriadku riadku HTML kódu:

  • Arduino načíta HTML kód: <TD><STRONG>Druh vozidla: &nbsp;</STRONG></TD>
  • Ak zistí, že riadok obsahuje reťazec Druh vozidla: &nbsp;
  • Načíta ďalší rok - <TD width="75%">OSOBNÉ VOZIDLO</TD> 
  • Vyparsuje (substring orezaním) obsah medzi HTML tagmi <td> </td>, vypíše obsah na UART.

Informácia z HTML stránky je vypísané a jej premenná zaniká ukončením podmienky. HTML riadok sa prepisuje v slučke cyklickom načítaní. Projekt je možné využiť napríklad s platformou ESP-CAM, ktorá je vybavená kamerou. Načítaním EVČ v reálnom čase je možné vytvoriť POST požiadavku a vypísať si prípadnú informáciu o odcudzení vozidla priamo v premávke. Tento článok má výlučne informatívny charakter a programovú implementáciu scrapera neobsahuje.

Základom pripojenia je WebClient program, ktorý dokáže vytvoriť TCP spojenie po HTTP a vypísať payload webservera s ktorým je možné pracovať a implementovať si vlastný scraper.

WebClient Arduino + Ethernet: https://www.arduino.cc/en/Tutorial/LibraryExamples/WebClient

WebClient ESP8266:
https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino

WebClient ESP32:
https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/examples/WiFiClient/WiFiClient.ino

Testovacie dáta pre vstup do mikrokontroléru boli použité z:
https://www.cas.sk/spravy/krimi/kradeze-aut/

Jednoduchá programová implementácia pre mikrokontróler ESP8266 s EVČ obsiahnutým v zdrojovom kóde (výpis o pozitívnom / negatívnom náleze - BEZ SCRAPERA - single request):

/*|----------------------------------------------------------|*/
/*|OVERENIE ŠPZ - ESP8266 (NodeMCU)  */                     
/*|----------------------------------------------------------|*/
#include <ESP8266WiFi.h>

const char * ssid = "WIFI_MENO";
const char * password = "WIFI_HESLO";

const char* host = "www.minv.sk";
String my_datas = "BAXXXZZ"; //Hľadané EČV --> Možno hľadať aj C značky
const int serverPort = 80; //http port
WiFiClient client;
String url = "/?odcudzene-mot-vozidla";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi uspesne pripojene");
  Serial.println("IP adresa: ");
  Serial.println(WiFi.localIP());
  delay(2000);
  Serial.println("Ready");
  send_datas();
}
void send_datas() {
  String data = "ec=" + my_datas;
  if (client.connect(host, serverPort)) {
    client.println("POST " + url + " HTTP/1.0");
    client.println("Host: " + (String)host);
    client.println("User-Agent: ESP32");
    client.println("Connection: close");
    client.println("Content-Type: application/x-www-form-urlencoded;");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line.indexOf("Podmienke vyhovuje: 1 záznam") > 0) {
        Serial.println("Po vozidle s EČV " + my_datas + " je vyhlásené pátranie!");
        break;
      }
      if (line.indexOf("Podmienke vyhovuje: 0 záznamov") > 0) {
        Serial.println("Po vozidle s EČV " + my_datas + " nie je vyhlásené pátranie");
        break;
      }
    }

  } else {
    Serial.println("Problem s pripojenim na stránku Minv!");
  }
  client.stop();
}
void loop() {

}

Jednoduchá programová implementácia pre mikrokontróler ESP32 s EVČ obsiahnutým v zdrojovom kóde (výpis o pozitívnom / negatívnom náleze - BEZ SCRAPERA - single request):

/*|----------------------------------------------------------|*/
/*|OVERENIE ŠPZ - ESP32 (DevKit)  */                    
/*|----------------------------------------------------------|*/
#include <WiFi.h>

const char * ssid = "WIFI_MENO";
const char * password = "WIFI_HESLO";

const char* host = "www.minv.sk";
String my_datas = "BAXXXZZ"; //Hľadané EČV --> Možno hľadať aj C značky
const int serverPort = 80; //http port
WiFiClient client;
String url = "/?odcudzene-mot-vozidla";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi uspesne pripojene");
  Serial.println("IP adresa: ");
  Serial.println(WiFi.localIP());
  delay(2000);
  Serial.println("Ready");
  send_datas();
}
void send_datas() {
  String data = "ec=" + my_datas;
  if (client.connect(host, serverPort)) {
    client.println("POST " + url + " HTTP/1.0");
    client.println("Host: " + (String)host);
    client.println("User-Agent: ESP32");
    client.println("Connection: close");
    client.println("Content-Type: application/x-www-form-urlencoded;");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line.indexOf("Podmienke vyhovuje: 1 záznam") > 0) {
        Serial.println("Po vozidle s EČV " + my_datas + " je vyhlásené pátranie!");
        break;
      }
      if (line.indexOf("Podmienke vyhovuje: 0 záznamov") > 0) {
        Serial.println("Po vozidle s EČV " + my_datas + " nie je vyhlásené pátranie");
        break;
      }
    }

  } else {
    Serial.println("Problem s pripojenim na stránku Minv!");
  }
  client.stop();
}
void loop() {

}

Jednoduchá programová implementácia pre mikrokontróler Arduino + Ethernet (Wiznet W5100) s EVČ obsiahnutým v zdrojovom kóde (výpis o pozitívnom / negatívnom náleze - BEZ SCRAPERA - single request):

/*|----------------------------------------------------------|*/
/*|OVERENIE ŠPZ - Arduino (Ethernet)  */                    
/*|----------------------------------------------------------|*/
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xAA, 0xBB, 0xCC, 0xAA, 0xBB, 0xCC };
IPAddress ip(192, 168, 1, 200);
IPAddress gateway(192, 168, 1, 1);
char serverName[] = "www.minv.sk"; //doména Ministerstva vnútra SR
String my_datas = "BAXXXZZ"; //Hľadané EČV --> Možno hľadať aj C značky
int serverPort = 80;
EthernetClient client;
String url = "/?odcudzene-mot-vozidla";
void setup() {
  Serial.begin(115200);
  Ethernet.begin(mac);
  Serial.println("IP adresa Ethernet shieldu:");
  Serial.println(Ethernet.localIP());
  delay(2000);
  Serial.println("Ready");
  send_datas();
}

void send_datas() {
  String data = "ec=" + my_datas;
  if (client.connect(serverName, serverPort)) {
    client.println("POST " + url + " HTTP/1.0");
    client.println("Host: " + (String)serverName);
    client.println("User-Agent: ArduinoEthernetWiznet");
    client.println("Connection: close");
    client.println("Content-Type: application/x-www-form-urlencoded;");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line.indexOf("Podmienke vyhovuje: 1 záznam") > 0) {
        Serial.println("Po vozidle s EČV " + my_datas + " je vyhlásené pátranie!");
        break;
      }
      if (line.indexOf("Podmienke vyhovuje: 0 záznamov") > 0) {
        Serial.println("Po vozidle s EČV " + my_datas + " nie je vyhlásené pátranie");
        break;
      }
    }

  } else {
    Serial.println("Problem s pripojenim na stránku Minv!");
  }
  client.stop();
}

void loop() {

}
© 2024-2025 Arduino Blog - Všetky práva vyhradené.
Vytvorené službou Webnode Cookies
Vytvorte si webové stránky zdarma! Táto stránka bola vytvorená pomocou služby Webnode. Vytvorte si vlastný web zdarma ešte dnes! Vytvoriť stránky