MQTT ve Uygulama üzerinden ilk girişte mevcut durumu göstermeme sorunu

rsimsek

Profesyonel Üye
Katılım
3 Haz 2010
Mesajlar
3,975
Puanları
731
Konum
Anadolu yakası
Merhaba arkadaşlar,

Bir süredir ESP8266 serisinden NodeMCU ve ESP-01 ile denemeler yapmaktayım. Malum Ardiuno'da ilk yapılan "merhaba dünya" veya led yakma söndürme misali, ben de akıllı ev sistemlerine ilk giriş niteliğinde uzaktan röle açıp kapatma, sıcaklık ve nem sensörü bilgilerini okumayı yaptım. MQTT protokolu üzerinden adafruit.com sitesi üzerinden (Blynk ve RemoteXY'de de çalıştırdım. Bir yerde takıldım.



Görseldeki gibi web'den io.adafruit.com üzerinden girdiğimde hem PC üzerinden hem de telefonla senkronize/eş zamanlı olarak röleleri kontrol edebiliyorum. Yani, birinde açtığımda diğeri de güncelleniyor. Aynı durum MQTT Dash uygulamasında da oluyor. Fakat sorun şu ki; uygulamayı ilk açtığımda rölelerin mevcut durumlarını (uygulama kapalıyken web'den değiştirdiğimde) değil de son kaldığı ekranı getiriyor. Ayarlarından da bir çözüm bulamadım. Belki atladığım bir şey vardır. Daha yeni yeni bu MQTT olayını hazmetmeye ve sindirmeye çalışıyorum. Bir kaç MQTT uygulaması denedim, henüz bir çzöüm bulamadım. Bu konuda tecrübesi olanlar yardımcı olursa sevinirim.

MQTT Dash uygulaması.
 
Adafruit de var mı bilmiyorum ama qos diye bi seçenek oması lazım onu 2 yaptığın zaman sürekli etkileşim halinde olur. qos 1 yaparsan veriyi sadece 1 kere iletir ve kontrol eder. qos 0 olur ise direk veriyi iletir verinin gidip gitmediğini kontrol etmez. Heralde senin sorununu bu çözebilir.
 
@rufneck, QoS0, QoS1 ve QoS2 var. Sorun verinin gidip gelmesi değil. Uygulamayı ilk açtığımda uzaktaki rölenin o anki durumunu okumuyor. Dolaysıyla web üzerinde durumu değişen bir röleyi uygulama ilk açılışta okumuyor. Dediğim gibi bir ayarı vardır muhtemelen. Yoksa da başka bir uygulamaya geçeceğim.
 
Ben 30 liraya bi hosting aldım kendi iot serverimi kendim yaptım.
 

Ekli dosyalar

  • Screenshot_2021-02-01-13-58-31-689_com.vifratek.buzdolabi.jpg
    23.9 KB · Görüntüleme: 14
  • IMG_20210201_135926.jpg
    48.9 KB · Görüntüleme: 12
Doğrusu kontrolün kendinizde olduğu bir broker/sunucu kurmak tabi. Ama şu an deneme aşaması olunca ek bir masrafa gerek görmeden ücretsiz olanlarla denemelerimi yapıyorum. Ayrıca Raspberry Pi ile sunucuyu kendi evinde kurmak da mümkün. Tabi bunun için Elektrik kesintilerine karşı yedek/backup besleme seçenekleri ile desteklemek gerekiyor. Gerçi haricen bir sunucu/broker olsa bile sistemin şebekeden bağımsız yedek beslemesi olmalıdır.

Bugün aklıma bir şey geldi. Yukarıda bahsettiğim sorunda sadece publish olan bağlantının güncellenmediğini fark ettim. Yani sıcaklık ve nem bilgileri uygulamayı açtığımda güncelleniyordu. Bu aklıma role'ler hem subcribe hem publish yapılabilir mi sorusunu getirdi? Arduino'da benzer şeyler arıyorum henüz bulamadım. MQTT protokolu ve yapısı o kadar da basit değil sonucuna vardım. Öğrendikçe ve ihtiyaç duydukça derinliklerine inmek gerektiği anlaşılıyor.

@rufneck, söylediğin QoS değerleri, iletiğim ve ihtiyaç aciliyetine göre sadece veriyi göndermede kullanılıyor. Mesela ortam sıcaklık değeri her 5 dakikada bir güncellenebilir, bunu QoS0 ile teyitsiz göndermek mantıklıdır gelebilir. Fakat diyelim bir kalorifer kazanının basınç ve sıcaklık bilgisi kesinlikle teyitli ve QoS2 ile gönderilmelidir. Ben QoS yöntemini bu şekilde anladım.
http://www.steves-internet-guide.com/understanding-mqtt-qos-levels-part-1/
 
Son düzenleme:
Bugün aynı model prototip üzerinden hem Blynk, hem de RemoteXY ile aynı denemeyi yaptım. İletişim kopunca bir sonraki uygulamayı açınca rölenin en son durumunu kaybediyor. Bir iki defa uygulama üzerinden düğmeye basıp uyumlu hale getirmek gerekiyor. Yani uygulamada açık görünüyorsa kapalı, kapalı görünüyorsa açık görünebiliyor. Yazılıma bağlı olarak kapalı kalıyor. İletişim varken her defasında esp'nin eeprom'una röle durumu kaydedilerek, sunucu üzerinden yapabilmek varken her açışta da kaydedilen durumu okutularak bir çözüm bulunabilir.
 
Bir kaç gündür uğraştığım konu ile ilgili şöyle bir çözüm buldum. Konudaki sorun, uygulama uyumsuzluğunu irdeledikçe, iletişim kopukluğunda modül/devre üzerindeki rölelerin tekrar iletişim kurulduğunda son durumlarını koruması, bunun için de son durumlarını/değerlerini MQTT sunucusundan geri okunması gerekiyor.
Feeds ->Last value diye değer sunucuda tutulsa da bu değeri henüz okuyamadım. Onun yerine EEPROM'da 101 nolu adrese kaydedip, her iletişim kesildiğinde ve tekrar iletişim kurulduğunda aynı bilgiyi okuyup röle durumunu muhafaza etmek gibi bir çözüm bulabildim. Umarım MQTT sunucu->feed listesi içinde tutulan Last value değerine bir şekilde ulaşabilirim.

Kod:
//void setup()
  EEPROM.begin(512); //Initialasing EEPROM
//...
  digitalWrite(PIN_ROLE1, EEPROM.read(101)); // kaydedilen değeri oku ve set et.

//void loop()
    EEPROM.write(101, digitalRead(PIN_ROLE1)); // mqtt ile rölenin değeri değiştikten sonra kaydet.
    EEPROM.commit();

Sonunda Feeds Last value'ye erişebildim. Mesele, aynı röleyi Publish olarak da _get eki ile tekrar tanımlamakmış ve devamı.
Kod:
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client; // or... use WiFiClientSecure for SSL

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);


Adafruit_MQTT_Subscribe role1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME"/feeds/Role1", MQTT_QOS_1);

Adafruit_MQTT_Publish role1_get = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Role1/get");

#define PIN_ROLE1 D2 // Röle 1
#define ROLE_AC LOW
#define ROLE_KAPAT HIGH

Sonrasında ise;
Kod:
void setup()
//...
  Serial.begin(115200);
  delay(100);
  Serial.println(F("Adafruit MQTT demo"));

  mqtt.subscribe(&role1);

  MQTT_connect();

  Adafruit_MQTT_Publish *publishion;

  role1_get.publish(0); // last value. Bu kısım pek anlamasam da mqtt sunucusundaki son değeri alıp digitalWrite ile PIN_ROLE1'e yazıyor. Çin atasözü, "çalışana dokunma".;)
  delay(150);
  pinMode(PIN_ROLE1, OUTPUT);

//...

void MQTT_connect()
{
  int16_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);  // wait 5 seconds
    retries--;
    if (retries == 0) {
      // basically die and wait for WDT to reset me
      while (1);
    }
  }
  Serial.println("MQTT Connected.");
}

void loop()
{
  MQTT_connect();

  Adafruit_MQTT_Publish *publishion;

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(5000))) // veri için 5 saniye bekle. Değişen veri varsa bloğu işle.
  {
    if (subscription == &role1)
    {
      Serial.print(F("\nRole-1 durumu: "));
      Serial.println((char *)role1.lastread);

      if (strcmp((char *)role1.lastread, "AÇ") == 0)
        digitalWrite(PIN_ROLE1, ROLE_AC);
      if (strcmp((char *)role1.lastread, "KAPAT") == 0)
        digitalWrite(PIN_ROLE1, ROLE_KAPAT);
    }
}
 
Son düzenleme:
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için onları kabul etmelisiniz. Daha fazla bilgi edin…