Serwer Flask, Arduino client i REST API

https://flask.palletsprojects.com/en/2.2.x/

O REST API sztuczna inteligencja napisała tak: “REST API (Representational State Transfer Application Programming Interface) to styl architektury sieciowej oraz zestaw reguł, które pozwalają na tworzenie interfejsów programowania aplikacji, umożliwiających komunikację między różnymi systemami lub usługami internetowymi. REST API umożliwia klientom na zapytanie serwera o dane lub na wykonanie akcji poprzez standardowe protokoły internetowe, takie jak HTTP i protokół SSL/TLS, zazwyczaj zwracając dane w formacie JSON lub XML. REST API jest często stosowany w aplikacjach internetowych, takich jak sklepy internetowe, media społecznościowe, systemy płatności online, a także w aplikacjach mobilnych.

Poniżej kod napisany w Arduino, którym płytka ESP32 kontaktuje się z serwerem napisanym w pythonie z użyciem modułu flask. Musiałem użyć Arduino, zamiast prostszego Micropython, bo jak dotąd brak dobrej biblioteki dla mojego wyświetlacza e-Paper 4.2″ w tym języku.

Arduino IDE, ESP32 klient

/*
 *  Arduino IDE, ESP32 klient 
 */

#include <WiFi.h>

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

const char* host = "*******"; // wpisz adres serwera z którym się łączysz na przykład "192.168.1.23"

void setup()
{
    Serial.begin(115200);
    delay(10);

    // We start by connecting to a WiFi network

    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}

int value = 0;

void loop()
{
    delay(20000);
    ++value;

    Serial.print("connecting to ");
    Serial.println(host);

    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = ****; // wpisać numer portu serwera z którym się komunikujemy
    if (!client.connect(host, httpPort)) {
        Serial.println("connection failed");
        return;
    }

    String url = "/epd";    // ścieżka do strony. jeśli kierujemy na główną piszemy "/"

    Serial.print("Requesting URL: ");
    Serial.println(url);

    // This will send the request to the server
    client.print(String("POST ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");
    unsigned long timeout = millis();
    while (client.available() == 0) {
        if (millis() - timeout > 5000) {
            Serial.println(">>> Client Timeout !");
            client.stop();
            return;
        }
    }

    // Read all the lines of the reply from server and print them to Serial
    while(client.available()) {
        String line = client.readStringUntil('\r');
        Serial.print(line);
    }

    Serial.println();
    Serial.println("closing connection");
}


Drugi przykład, tym razem ESP8266 z Arduino. Zamiast języka MicroPython użyłem Arduino, ponieważ miałem problem z komunikacją między czujnikiem balkonowym działającym w oparciu o procesor ATmega328 i moduł radiowy nrf24L01, a esp8266 na MicroPythonie, który odbierałby dane i przekazywał do serwera. Za diabła nie chciały się widzieć. Poniżej kod wysyłający JSON do serwera oparty o bibliotekę ESP8266HTTPClient.h. Część odpowiadającą za nRF24 i tworzenie obiektu JSON pominąłem. Zwróćcie uwagę, że zastosowałem metodę POST, która pozwala wysyłać dane na serwer w dyskretny sposób.

Arduino IDE, ESP8266 HTTP klient —> flask serwer

/**
   PostHTTPClient.ino

    Created on: 21.11.2016

    https://www.bot-thoughts.com/2021/11/make-esp8266-wifi-temperature-sensor.html


*/

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

#define SERVER_IP "192.168.1.104:8080" // adres mojego lokalnego serwera flask

#ifndef STASSID
#define STASSID "*******"
#define STAPSK "********"
#endif

void setup() {

  Serial.begin(115200);

  Serial.println();
  Serial.println();
  Serial.println();

  WiFi.begin(STASSID, STAPSK);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    WiFiClient client;
    HTTPClient http;

    Serial.print("[HTTP] begin...\n");
    // configure traged server and url
    http.begin(client, "http://" SERVER_IP "/balkon");  // HTTP
    http.addHeader("Content-Type", "application/json");

    Serial.print("[HTTP] POST...\n");
    // start connection and send HTTP header and body
    int httpCode = http.POST("{\"temp\":\"22.30\", \"humi\":\"55\"}");

    // httpCode will be negative on error
    if (httpCode > 0) {
      // HTTP header has been send and Server response header has been handled
      Serial.printf("[HTTP] POST... code: %d\n", httpCode);

      // file found at server
      if (httpCode == HTTP_CODE_OK) {
        const String& payload = http.getString();
        Serial.println("received payload:\n<<");
        Serial.println(payload);
        Serial.println(">>");
      }
    } else {
      Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }

    http.end();
  }

  delay(10000);
}

Serwer flask, kod:

Sztuczna inteligencja o flask-u pisze tak: “Flask to lekki i minimalistyczny framework dla języka Python, który umożliwia tworzenie aplikacji webowych i API z łatwością i szybkością. Flask dostarcza wiele wbudowanych funkcjonalności, takich jak routing, obsługa formularzy, autoryzacja, obsługa baz danych oraz wsparcie dla różnych rozszerzeń. Dzięki swojej prostocie i elastyczności, Flask jest bardzo popularnym narzędziem w świecie programowania webowego.”

Poniżej kod najprostszego serwera flask. U mnie działa nawet na starym Mac-u z 2009 roku. Oczywiście żeby współdziałał z ESP32 i kodem zapisanym wyżej należałoby dodać @app.route('/epd', methods=['POST']) z funkcją coś zwracającą.

# Podziękowania dla twórców za filmy na YouTube:
# https://youtu.be/9sG0xjGwIMM
# https://www.youtube.com/watch?v=zT8FrCVjKjU&t=8s

from flask import Flask, jsonify, render_template, request

app = Flask(__name__)


@app.route('/balkon', methods=['GET', 'POST'])
def balkon():
    if request.method == 'GET':
        return jsonify('witaj na stronie!')
    else:
        data = request.get_json()
        print(data)    
    return jsonify('flask pozdrawia!')

@app.route('/epd', methods=['GET', 'POST'])
def epd():
    print("EPD")
    temp = 3.20
    time_stamp = '12:30'
    hum = 55
    return jsonify(f'Temp. {temp} st.C, Wilgotnosc {hum} %, Czas {time_stamp}')


if __name__ == '__main__':
    app.run(host='192.168.1.104', port=8080, debug=True) 

Dodaj komentarz