WiFi - Klient cz17

Tworząc Klienta na Arduino może nam otworzyć wiele ścieżek do integracji z innymi urządzeniami i systemami. Klient wysyła zapytania z parametrami lub bez na które dostaje odpowiedzi od serwera. Przykładem zastosowania takiego klienta może być np. pobranie informacji o prognozie pogody z serwisu pogodowego, które posiada API.

Zadanie

Stworzyć klienta, który będzie wysyłał zapytania do API. Dane otrzymane z API muszą być w formacie JSON oraz przejść deserializacje.
Pomocna będzie biblioteka ArduinoJson dla deserializacji danych JSON.

Do zbudowania użyję:
  • Arduino MKR1010 wifi
  • Serwera REST API z poprzedniego rozdziału kursu
Kod programu:
#include <SPI.h>
#include <WiFiNINA.h>
#include <ArduinoJson.h>

char ssid[] = "SSID";   // SSID Twojej sieci WiFi
char pass[] = "HASLO"; // Hasło Twojej sieci WiFi

int status = WL_IDLE_STATUS; // status połączenia

// Zainicjuj klienta WiFi
WiFiClient client;

// adres serwera
IPAddress server(192,168,8,105);

unsigned long lastConnectionTime = 0; // ostatni raz łączyłeś się z serwerem, w milisekundach
const unsigned long postingInterval = 5L * 1000L; // opóźnienie między aktualizacjami, w milisekundach

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

  enable_WiFi();  // Sprawdź moduł WiFi
  connect_WiFi(); // Próba połączenia z siecią Wi-Fi
  printWifiStatus(); // Wyświetl status połączenia
}

void loop() {

  // jeśli od ostatniego połączenia minęło 5 sekund, 
  // połącz się ponownie i wyślij dane:
  if (millis() - lastConnectionTime > postingInterval) {
    httpRequest();

    // odczyt Json
    String payload = client.readString(); // Odpowiedz z serwera
    int start = payload.indexOf('{'); 
    int endd = payload.lastIndexOf('}');
    payload = payload.substring(start, endd + 1); // wycinanie części z danymi JSON
    // Serial.println(payload);

    // deserializacja JSON
    DynamicJsonDocument doc(1024);
    deserializeJson(doc, payload);
    float temperature    = doc["variables"]["temperature"];
    int pressure   = doc["variables"]["pressure"];
    // Wyswietlanie danych
    Serial.print("Temperatura: ");
    Serial.println(temperature);
    Serial.print("Cisnienie: ");
    Serial.println(pressure);
  }

}

// metoda nawiązująca połączenie HTTP z serwerem:
void httpRequest() {
  // zamknij jakiekolwiek połączenie przed wysłaniem nowego żądania. 
  // zwolni gniazdo w module NINA
  client.stop();

  if (client.connect(server, 80)) { // jeśli istnieje udane połączenie:
    Serial.println("laczenie...");
    // wyślij żądanie HTTP GET:
    client.println("GET / ");
    client.println("Host: 192.168.8.105");
    client.println("User-Agent: ArduinoMKRWiFi1010/1.1");
    client.println("Connection: close");
    client.println();

    lastConnectionTime = millis(); // zanotuj czas nawiązania połączenia:
  } else { // jeśli nie mogłeś nawiązać połączenia:
    Serial.println("blad polaczenia"); 
  }
}

void enable_WiFi() {
  // Sprawdź moduł WiFi:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Komunikacja z modułem WiFi sie nie powiodła!");
    // nie kontynuuj
    while (true);
  }

  // Sprawdz wersje
   String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Zaktualizuj oprogramowanie");
  }
}

void connect_WiFi() {
  // Próba połączenia z siecią Wi-Fi:
  while (status != WL_CONNECTED) {
    Serial.print("Proba połaczenia z SSID: ");
    Serial.println(ssid);
    // Połącz się z siecią WPA/WPA2. Zmień tę linię, jeśli używasz sieci otwartej lub WEP:
    status = WiFi.begin(ssid, pass);
    // Poczekaj 10 sekund na połączenie:
    delay(5000);
  }
}

void printWifiStatus() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  
  long rssi = WiFi.RSSI();
  Serial.print("sila sygnalu (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Po w graniu programu na płytkę otrzymamy w monitorze portu szeregowego informację o połączniu. Następnie  w interwale co 5 sekund Arduino będzie wysyłało żądanie do API i czekało na odpowiedz w postaci JSON, którą zdeserializuje i wyświetli nam w monitorze.

Monitor portu szeregowego