Bana gerisini ver – Bölüm 2: Müşteri

semaver

New member


  1. Bana gerisini ver – Bölüm 2: Müşteri

Arduino kartları veya diğer mikro denetli kartlar veya dahil edilen sistemler veya tek devre bilgisayarlar, bir WiFi veya Ethernet bağlantısını entegre ederseniz artık bir uygulama ile iletişim kurabilir. Esas olarak sensörlerle sunulan ölçümler gibi tipik bir uygulama, gerçek bir saat (RTC) bir avantaj olarak kanıtlar. Ölçüm verilerine ek olarak, bu, daha sonra tarihsel bir analize, örneğin belirli bir süre için sıcaklığın seyrine izin veren ölçüm verilerine (tarih ve saat) eklenebilir.








Dr. Michael Stal, 1991 yılından bu yana Siemens teknolojisi üzerinde çalışmaktadır. Yazılım mimarisi sorunları hakkında iş alanları önermektedir ve Siemens'in kıdemli yazılım mimarlarının mimari oluşumundan sorumludur.







Arduino Giga burada konuşulsa bile, uygulama bu kartla sınırlı değildir, ancak WiFi, WiFiudp ve HTTPClient gibi işlevsel olarak benzer kitapçılar için veya Platform-Plug-in ile görsel çalışma kodunda diğer Arduino, STM veya ESP kartları için nispeten kolay uyarlanabilir.

BME ailesinin (BME68X, BME58X, BME38X, BME28X) bir Bosch sensortec sensörü, üreticiyi I2C veya SPI aracılığıyla bağlayın. Örneğin, Pomoroni veya Adafruit gibi çeşitli üreticilerin koparma kartı olarak mevcut olan bir BME688 kullanılmıştır. İsterseniz, bir Bosch geliştirme kiti de satın alabilirsiniz. Bu tavsiye, bir tüy Adafruit Huzzah32 (ESP32) kartında piggyback'te bulunan bir BME688 adaptöründen oluşur. Bu yaklaşık 100 Euro'ya mal oluyor, ancak ücretsiz BME-AI yazılımı eğitmek için cazibesi var. Sensör, kahve, co₂ veya klor gibi bir sinir ağı aracılığıyla havadaki farklı gaz moleküllerini tanımayı öğrenir. Moleküller için, ohmlardaki dirençleri belirler ve gazların elektriksel özelliklerini sınıflandırabilir. Bu spesifik ML eğitim seansları koparma kartları ile mümkün değildir: kullanıcı sadece somut bir moleküle atama yapmadan gazın direncini öğrenir. Basit kartlar sadece 20 ila 30 Euro arasındadır.

İlk bölümde daha önce de belirtildiği gibi, örnekler için kaynak kodu GitHub deposunda mevcuttur.

Önceden bir not: Burada sunulan entegrasyon için olası bir alternatif olarak, örneğin, müşteri ve sunucu arasında olay odaklı bir iletişim veya haberlere izin veren MQTT kullanımı sorgulanacaktır. Birçok durumda, belki de burada mevcut olanlar için, SQMTT mükemmel bir seçenektir. Bununla birlikte, makalelerin iki kısmı özellikle iletişim ve Backndend'in API REST ile entegrasyonuna odaklanmaktadır. Backand tarafından yönetilen bir mikro hizmet genellikle kalan bir EPE sağlar.

Donanım Yapılandırması


Belirli devrede aşağıdaki bağlantılar gereklidir:

Arduino ........ BME688

3.3V ............ Vin

GND ............. GND

SCL ............. SCK

SDA ............. SDI

Aşağıdaki fritzing diyagramı şunları göstermektedir:








BME688 sensörü ve Arduino'nun bağlantısı I2C veya SPI aracılığıyla çalışır. Mevcut davada, I2C seçim aracıdır



Arduino uygulaması


Arduino yazılımı geliştiğinde, aşağıdaki sorumluluklar gözlemlenmelidir:

İlk Kurulum:

  • WiFi Ağı ile bir bağlantı kurun
  • Mevcut saati NTP sunucusu üzerinden okuyun ve saati gerçek zamanlı olarak ayarlayın (RTC)
  • I2C BME688 Sensörüne Bağlantı Oluşturun
Sürekli Döngü:

  • BME688'den ölçümlerin sonuçlarını okuyun
  • RTC aracılığıyla yerel saati belirleyin
  • JSON mesajını birleştirin
  • WiFi/HTTP aracılığıyla kalan sunucuya bağlanın
  • Posta Mesajı Gönder
  • Paketin başarılı olup olmadığını kontrol edin
Ayrıca, taslak test ve gözlem amaçları için seri monitör hakkında bilgi sağlamalıdır.

WLAN ile bağlantı


Arduino'nun taslağı aynı dizindeki bir dosya bekliyor arduino_secrets.hİstenen WLAN, özellikle SSID ve WLAN anahtarı için tanımlar. Arduino-wifis kullanımı için, ilgili bir WiFi kitapçısı gereklidir, örneğin eklediğimiz başlık: #include <WiFi.h>. Ayrıca, kütüphaneye ihtiyacımız var ArduinoHttpClientArduino Kimliği veya VS Code & Platformio Kütüphanesi'nin yöneticisi aracılığıyla yükliyoruz.

WLAN ile bağlantı aşağıdaki kodun kontrolünü ele geçirir:



void setup() {
// Seriellen Stream starten
Serial.begin(9600);

// Verbindungsaufbau WiFi
while (status != WL_CONNECTED) {
Serial.print("Versuche Verbindungsaufbau zum WLAN-Netz: ");
Serial.println(ssid); // print the network name (SSID);

// Verbinden mit WPA/WPA2 Netzwerk:
status = WiFi.begin(ssid, pass);
}

// Name des WLANs nach erfolgtem Verbindungsaufbau:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());


NTP protokolü


Bu nedenle, bir NTP sunucusuna erişim saati gerçek zamanlı olarak ayarlamaya yardımcı olmalıdır.

Giga R1 sekmesi için aşağıdaki başlık dosyaları gereklidir:

#include <WiFiUdp.h> // zum Versenden von NTP-Paketen notwendig

#include <mbed_mktime.h>

Tabii ki, diğer kartlarda farklı görünüyor ve bu anlamda değişmiş olmalı.

Kraliyet saatinin ayarlanması için gerçek kodu setNtpTime()bu da yerel bir kapı ile bir UDP bağlantısı açar, istenen zaman sunucusuna bir istek paketi gönderir (sendNTPacket()) Sonra bu arada cevap parseNtpPacket() Kraliyet saatini mevcut saatle almak ve ayarlamak için. Başarılı bir şekilde çalıştı, o zamandan beri yöntemi kullanılarak kullanılabilir getLocalTime() Kraliyet saatinden daima mevcut saati okuyun. Bir teslim edildi Datetime-String, tarih ve saatten oluşan: „2023-06-05 12:31:45“.


// NTP-Anfrage senden, Antwort erhalten und parsen
void setNtpTime()
{
status = WL_IDLE_STATUS;
Udp.begin(localPort);
sendNTPpacket(timeServer);
delay(1000);
parseNtpPacket();
}

// Rufe einen Zeitserver auf
unsigned long sendNTPpacket(const char * address)
{
memset(packetBuffer, 0, NTP_PACKET_SIZE);
packetBuffer[0] = 0b11100011; // LI, Version, Modus
packetBuffer[1] = 0; // Stratum, Art der Uhr
packetBuffer[2] = 6; // Abfrageintervall
packetBuffer[3] = 0xEC; // Präzision der Uhr
// 8 Bytes von Nullen für Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;

Udp.beginPacket(address, 123); // NTP Aufrufe erfolgen über Port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}

// Hier wird das NTP-Antwortobjekt empfangen und geparst:
unsigned long parseNtpPacket()
{
if (!Udp.parsePacket())
return 0;

Udp.read(packetBuffer, NTP_PACKET_SIZE); // Paket vom NTP-Server empfangen
const unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
const unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
const unsigned long secsSince1900 = highWord << 16 | lowWord;
constexpr unsigned long seventyYears = 2208988800UL;
const unsigned long epoch = secsSince1900 - seventyYears;
set_time(epoch);

// Folgende ausführliche Beschreibung lässt sich ausgeben,
// sobald man DETAILS definiert
#if defined(DETAILS)
Serial.print("Sekunden seit Jan 1 1900 = ");
Serial.println(secsSince1900);

// NTP time in "echte" Zeit umwandeln:
Serial.print("Unix Zeit = ");
// Ausgabe der Unix time:
Serial.println(epoch);

// Stunde, Minute, Sekunde ausgeben:
Serial.print("Die UTC Zeit ist "); // UTC entspricht Greenwich Meridian (GMT)
Serial.print((epoch % 86400L) / 3600); // Stunde ausgeben (86400 sind die Sekunden pro Tag)
Serial.print(':');
if (((epoch % 3600) / 60) < 10) {
// In den ersten 10 Minuten einer Stunde brauchen wir eine führende Null
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // Minute ausgeben (3600 = Sekunden pro Stunde)
Serial.print(':');
if ((epoch % 60) < 10) {
// In den ersten 10 Minuten einer Stunde brauchen wir eine führende Null
Serial.print('0');
}
Serial.println(epoch % 60); // Sekunde ausgeben
#endif

return epoch;
}

// Lokale Zeit mittels RTC (Real Time Clock) ermitteln:
String getLocaltime()
{
char buffer[32];
tm t;
_rtc_localtime(time(NULL), &t, RTC_FULL_LEAP_YEAR_SUPPORT);
strftime(buffer, 32, "%Y-%m-%d %k:%M:%S", &t);
return String(buffer);
}




NTP (Ağ Zamanı Protokolü) hakkında daha fazla bilgi edinmek isteyen ilgili taraflar için, bir NTP paketinin kurulmasını gösteren sonraki açıklamalarla bir örnek:







NTP protokolü ile, oluşturulmuş sistemler saatlerini gerçek zamanlı olarak ayarlayabilir



Bir NTP paketinin başlık öğeleri aşağıdaki gibi tasarlanmıştır:

Orada

Atlama Göstergesi (2 bit)

Bu özellik, şu anki günün son dakikasının bir saniye daha ihtiyacı olup olmadığını gösterir.

0: İkinci ayar gerekmez

1: Son dakikada 61 saniye olmalı

2: Son dakikada 59 saniye olmalı

15:00 senkronize değil

A

NTP sürüm numarası (3 bit) (yaklaşık sürüm 4).

moda

NTP Paket Modu (3 bit)

0: Ayrılmış

1: simetrik olarak aktif

2: simetrik pasif

3: Müşteri

4: Sunucu

5: İletim

6: NTP kontrol mesajı

7: Özel kullanım için ayrılmış

Katman

Zaman kaynağının katmanı seviyesi (8 bit)

0: belirtilmedi veya geçerli değil

1: Birincil Sunucu

2–15: İkincil sunucu

16: senkronize değil

17-255: ayrılmış

Anket

Araştırma aralığı (bir işaretli 8 -Bit integral sayıları), saniyeler içinde tanımlayan, bu ardışık NTP mesajları arasında maksimum zaman aralığı olmalıdır.

Kesinlik

Saat hassasiyeti (işaretli 8 -bit tam numara)

Radice Gecikmesi

Birincil zaman kaynağındaki sunucudan dönme gecikmesi. Saniyeleri tanımlayan 32 -Bit kaydırma numarasıdır. Ondalık nokta, 15 ve 16 bitleri arasındadır. Yalnızca sunucu mesajları ile ilgilidir.

Radikal dağılım

Saat frekansıyla ilgili tolerans nedeniyle maksimum hata. Saniyeleri tanımlayan 32 -Bit kaydırma numarasıdır. Ondalık nokta, 15 ve 16 bitleri arasındadır. Sadece sunucunun haberleri ile ilgilidir

Referans tanımlayıcı

Starum-1 sunucuları için bu değer (4 baytlı bir ASCII değeri) harici referans kaynaklarını tanımlar. İkincil sunucular için, değer (4 bayt), senkronizasyon kaynağının IPv4 adresini veya senkronizasyon sunucusunun IPv6 adresinin ilk 32 bit MDA hashes (MDA = Mesaj Özeti Algoritması 5) açıklar.

Sensör


BME688 sensörünü I2C aracılığıyla kontrol etmek için kitaplık yönetimi aracılığıyla kitaplıkları Adafruit'ten yüklemeliyiz: Kod, SPI kullanacak şekilde kolayca değiştirilebilir. Adofruit BME680 kitapçıları ve Adafruit Birleşik Sensörünü içe aktarmanız gerekir. Tabii ki, BME280'inki gibi BME ailesinin başka bir sensörünün kütüphanesi de olabilir.

Sensörün başlatılması setup() entegre. İşte BME projesinin anlaşması:

Adafruit_BME680 bme; // Vereinbarung der Variablen bme

Ve işte gerçek başlatma:


// Verbindung mit Sensor BME680 etablieren
if (!bme.begin()) {
Serial.println(F("Konnte keinen Sensor finden. Bitte Schaltung überprüfen!"));
while (1);
}

// Oversampling-Werte setzen und IIR-Filter initialisieren
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C für 150 ms
}


Postasız

Yöntem createJSONString() Ölçüm ve zaman damgası verilerinden bir JSON nesnesi oluşturdu. Burada manuel yaratımı kasıtlı olarak seçtim ArduinoJson kullanmak için çaba çok açık kalıyor:


// Hier wird ein String generiert, der ein JSON-Objekt enthält
String createJSONString(double temp, double humi, double pres, double resi, String date, String time) {
String result = "{";
const String up = """;
const String delim = ",";
const String colon = ":";

result += up + "temperature" + up + colon + String(temp,2) + delim;
result += up + "humidity" + up + colon + String(humi,2) + delim;
result += up + "pressure" + up + colon + String(pres,2) + delim;
result += up + "resistance" + up + colon + String(resi,2) + delim;
result += up + "date" + up + colon + up + date + up + delim;
result += up + "time" + up + colon + up + time + up;
result += "}";
return result;
}


Bu ölçüm verilerinin bazılarını içermeyen bir sensörünüz varsa, JSON nesnesi ortaya çıkacaktır. Sunucu veritabanında, teslim edilmeyen her öznitelik için, bu sadece bir null eklendi.

HTTP Post aracılığıyla ölçüm verilerini göndermek callAPIPost() Bu nedenle, Durum Kodu ile başarı durumunda 200 Yanıtlar:


// Hier erfolgt die Vorbereitung und die eigentliche Durchführung des POST-Aufrufes / REST-PUSH
void callAPIPost(double temperature, double humidity, double pressure, double resistance, const String& date, const String& time){
Serial.println("Durchführung eines neuen REST API POST Aufrufs:");
String contentType = "application/json"; // Wir übergeben ein JSON-Objekt

// JSON Nutzlast (Body) kreieren
String postData = createJSONString(temperature, humidity, pressure, resistance, date, time);
Serial.println(postData); // ... und ausgeben

// Per WiFi-Verbindung POST aufrufen und dabei "application/json" und das JSON-Objekt übergeben
client.post("/measurements/api", contentType, postData);

// Status und Body aus Antwort extrahieren
int statusCode = client.responseStatusCode();
String response = client.responseBody();

// Ausgabe der Ergebnisse:
Serial.print("Status code: ");
Serial.println(statusCode);
Serial.print("Antwort: ");
Serial.println(response);
}


Yukarıda belirtilen yöntemlerin çağrıları loop()-Yöntem, elbette, programın başlamasının başlatılması hariç.







Eskiz gerçekleştirilirse, WiFi aracılığıyla WiFi'ye bağlanır, BME688'den gelen verileri sürekli olarak ölçer ve bir JSON nesnesi olarak bir tapınak olarak yayınlanır.



Çözüm


Arduino eskiz, 1 yeni ölçümden kalan sunucuyu sağlayan hazırdır. Tabii ki, her zaman olduğu gibi, genişleme seçenekleri var:

  • İlgili ölçülen değerlerini yayan bir OLED SSD1306 ekranı ekleyebilirsiniz. Veya SD kartlarına dayalı bir veri kaydedici. Bir OLED ekranının IIC bağlantısı ile ek entegrasyonunun bir örneği, yukarıda belirtilen GitHub deposunda da bulunabilir. I2C sensörü ve ekran, zincir Daisy aracılığıyla bir satıra bağlanır. Gerekirse, yapılandırması için IIC adresini (varsayılan ayar: 0x3c) ve çözünürlüğü (varsayılan ayar: 128×64) değiştirmek gerekir.






IIC veri yoluna bağlı olan SSD1306 ekranı (128 x 64), geçerli ölçüm verilerini yayınlar



Burada 3.3 V, GND, SDA, SCL dell'arduino bağlantısı, IIC ekranına ve IIC sensörüne dokunmanın mümkün olduğu bir mola verilir.

  • BME280, BME580 veya diğer sensör türleri gibi diğer iklim sensörlerinin avantajı düşünülebilir. Bu, hem istemci kodunda hem de sunucuda değişiklikler gerektirir.
  • Sensörlerle farklı kartlarınız varsa, veri şemasının kartların ve GPS verilerinin algılanması gibi özelliklerini sağlayabilirsiniz.
  • Raspberry Pi Pios, ESP32 kartları gibi alternatif kartlar kullanılabilir. Bir BME688'in Mac OS/Windows/Linux bilgisayarına doğrudan bağlantısı, bir GPIO Uzantısı sekmesi ile de mümkündür.
  • Cep telefonu veya tablet için bir uygulama, geçerli ölçüm işlemini grafiksel olarak görüntüleyebilir.
Ve bu henüz bayrak direğinin sonu değil. Olasılıklar neredeyse sonsuzdur. Örneğin istemci ve sunucu uygulamaları prosedürü iyi göstermeli ve deneylerini teşvik etmelidir. Müşteri ve sunucular için uygulamalar buna göre ayarlanabilir.

Her durumda, burada sunulan vitrin birçok fayda sunar ve eğlencelidir.


(RME)
 
Üst