Integracja Arduino Mega + Ethernet Shield z HA przez MQTT

Integracja Arduino Mega + Ethernet Shield z HA przez MQTT.
Co jest potrzebne:

  1. Arduino Mega 2560 ze względu na dużą ilość wejść/wyjść i większą pamięcią na kod i zmienne. Zakupiłem klona Arduino do zabawy.
  2. Ethernet Shield do Arduino
  3. Kabel USB A-B
  4. Kabel Ethernet
  5. Kable połączeniowe do czujnika
    np. taki zestaw:

https://www.aliexpress.com/item/4000166882902.html?spm=a2g0s.9042311.0.0.8c234c4duluEmr

  1. Czujnik temperatury i wilgotności np. AM 2302, może być dowolny DHT11, DHT22, itp…

https://www.aliexpress.com/item/32950372305.html?spm=a2g0s.9042311.0.0.14fe4c4d1Mt61x

Na początku łączymy Arduino z Ethernet Shield - pamiętając o zaizolowaniu elementów metalowych taśmą. Moja wersja jest tak skonstruowana, że po wpięciu w Arduino piny od gniazda ethernet zwierają się z obudową od gniazda USB.

Pobieramy i instalujemy środowisko programowania Arduino IDE
https://www.arduino.cc/download_handler.php?f=/arduino-1.8.11-windows.exe

Wybieramy wersję Arduino którą posiadamy:

Doinstalowujemy bibliotekę do obsługi czunika DHT
Narzędzia zarządzaj bibliotekami: Wpisujemy DHT i instalujemy np. Grove Temperature And Humidity Sensor.

Podłączamy Czujnik temperatury np AM2302 do Arduino GND, 5V, Data do pinu 2.

Podłączamy Arduino do komputera kablem USB. Powinno zostać wykryte i zainstalowane oraz dodany zostanie port COM. Podłączamy Arduino do sieci Ethernet. (jeśli ktoś woli Wifi to należy zastosować Wifi Shield do Arduino)

Wgrywamy poniższy wsad do edytora Zweryfikuj , Wgraj
Czekamy na zakończenie wgrywania. Resetujemy Arduino.

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22 //21 or 22 also an option
#define humidity_topic "arduino01/humidity"
#define temperature_topic "arduino01/temperature"

DHT dht(DHTPIN, DHTTYPE);
unsigned long readTime;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
IPAddress ip(192, 168, 2, 225);
IPAddress server(192, 168, 2, 1);
char message_buff[100];
EthernetClient ethClient;
PubSubClient client(ethClient);
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void setup()
{
Serial.begin(9600);
client.setServer("192.168.2.1", 1883); // can be replaced by: client.setServer(server, 1883);
client.setCallback(callback);
Ethernet.begin(mac);
dht.begin();
// Start sensor

Serial.println(Ethernet.localIP());
readTime = 0;
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
         (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diff = 0.1;

void loop()
{
if (!client.connected()) {
reconnect();
}

client.loop();
 long now = millis();
  if (now - lastMsg > 1000) {
    lastMsg = now;
    float newTemp = dht.readTemperature();
    float newHum = dht.readHumidity();
    if (checkBound(newTemp, temp, diff)) {
      temp = newTemp;
      Serial.print("New temperature:");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }
    if (checkBound(newHum, hum, diff)) {
      hum = newHum;
      Serial.print("New humidity:");
      Serial.println(String(hum).c_str());
      client.publish(humidity_topic, String(hum).c_str(), true);
    }
  }
}  

Klikając na lupę w prawym górnym narożniku możemy podejrzeć co zostaje wysłane na port szeregowy.

arduino

W kodzie adres IP 192.168.2.225 to nasze arduino
192.168.2.1 adres bramki z MQTT brokerem.
Program jest tak skonstruowany, że wysyła w topicu tylko zmianę temperatury i wilgotności aby nie obciążać MQTT brokera.
Użyty topic:
arduino01/temperature
arduino01/humidity

Możemy w bramce włączyć nasłuchiwanie powyższych topiców
/developer-tools/mqtt
Odpowiedzią powinna być temperatura albo wilgotność.

Teraz możemy dodać sensory do konfiguracji HA.
edytujemy sesnsors.yaml lub configuration.yaml

- platform: mqtt
  name: "Temperatura"
  state_topic: "arduino01/temperature"
  qos: 0
  unit_of_measurement: "ºC"
  value_template: '{{ value | round(1) }}'

- platform: mqtt
  name: "Wilgotność"
  state_topic: "arduino01/humidity"
  qos: 0
  unit_of_measurement: "%"

Konfiguracja interfejsu ui-lovelace.yaml:

 - entity: sensor.temperatura
    unit: '°C'  
    attribute: current_temperature
    scale: 50px
    max: 100
    min: 0
    severity:
      green: 10
      red: 59
      yellow: 52
    theme: Backend-selected
    type: gauge

  - entity: sensor.wilgotnosc
    unit: '%'
    attribute: current_humidity
    scale: 50px
    max: 100
    min: 0
    severity:
      green: 10
      red: 59
      yellow: 52
    theme: Backend-selected
    type: gauge

A oto efekt finalny:

W przykładzie był użyty tylko jeden czujnik. Możemy zastosować ich dużo więcej.
Tutaj kilka z sensorów które możemy użyć z Arduino:

Podobną funkcjonalność można uzyskać korzystając z WEMOS lub innego modelu Arduino.

6 polubień

Ekstra projekt, czegoś takiego szukałem, tylko jak byś jeszcze do tego dołożył przyciski mono i bi + przekaźniki. Osobiście moje arduino docelowo by zastąpiło 2x elektrozawory (soft dla rolet), 10xDS18B20, 6xprzekaźnik, 2xlicznik impulsów, 4x kontaktron. Da się?

1 polubienie

Mówisz i masz :slight_smile:

Zmodyfikowałem trochę program aby odczyt Wilgotności był co 1% a nie co 0,10, dodałem obsługę kontaktronu. Kontaktron podpinamy np. pod PIN 3 Arduino, drugi przewód do GND.
Topic do nasłuchu “arduino01/door”.

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <DHT.h>
#define DHTPIN 2 // 2 Pin Arduino do ktorego podlaczony jest czujnik
#define DHTTYPE DHT22 //21 or 22 w zaleznosci od czujnika
#define humidity_topic "arduino01/humidity"
#define temperature_topic "arduino01/temperature"
#define contactron_topic "arduino01/door"
#define KONTAKTRON 3 //3 pin Arduino do kontaktronu

DHT dht(DHTPIN, DHTTYPE);
unsigned long readTime;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
IPAddress ip(192, 168, 2, 225); // Adres IP Arduino
IPAddress server(192, 168, 2, 1); // Adres IP bramki z serwerem MQTT
char message_buff[100];
EthernetClient ethClient;
PubSubClient client(ethClient);
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  for (int i = 0; i < length; i++) {
  Serial.print((char)message[i]);
  messageTemp += (char)message[i];
  }
}

void reconnect() {
  // Oczekowani na polaczenie z serwerem
  while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
 Serial.println("connected");
} else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  // Czekaj 5 sekund przed ponownym polaczeniem
  delay(5000);
}
  }
}

void setup()
{
  Serial.begin(9600);
  client.setServer("192.168.2.1", 1883); // Adres serwera MQTT - bramka
  client.setCallback(callback);
  Ethernet.begin(mac);
  dht.begin(); // Start sensor DHT
  pinMode(KONTAKTRON, INPUT_PULLUP); //Kontaktron jako wejście
  Serial.println(Ethernet.localIP()); //Wyswietlenie adresu IP Arduino
  readTime = 0;
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
     (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diffhum = 1.0; // częstotliwość odswierzania co 1 %
float diff = 0.1;
int KONT = 2; // stan 2 przy pierwszym odczycie

void loop()
{
  if (!client.connected()) {
  reconnect();
  }

  client.loop();
  long now = millis();
  if (now - lastMsg > 1000) {
lastMsg = now;
float newTemp = dht.readTemperature();
float newHum = dht.readHumidity();
int newKONT = digitalRead(KONTAKTRON);

// ODCZYT TEMPERATURY
if (checkBound(newTemp, temp, diff)) {
  temp = newTemp;
  Serial.print("Temperatura: ");
  Serial.println(String(temp).c_str());
  client.publish(temperature_topic, String(temp).c_str(), true);
}
// ODCZYT WILGOTNOSCI
if (checkBound(newHum, hum, diffhum)) {
  hum = newHum;
  Serial.print("Wilgotność: ");
  Serial.println(String(hum).c_str());
  client.publish(humidity_topic, String(hum).c_str(), true);
}
// STAN KONTAKTRONU PRZY URUCHOMIENIU
if (KONT == 2) {     
  if (newKONT == 0){
    Serial.println("Stan kontaktronu: ZAMKNIETY");
    client.publish(contactron_topic, "close", true);
  }
  if (newKONT == 1){
    Serial.println("Stan kontaktronu: OTWARTY");
    client.publish(contactron_topic, "open", true);
  }  
}
// STAN KONTAKTRONU PRZY ZMIANIE
if (newKONT != KONT) {     
  KONT = newKONT;
  if (KONT == 0){
    Serial.println("Stan kontaktronu: ZAMKNIETY");
    client.publish(contactron_topic, "close", true);
  }
  if (KONT == 1){
    Serial.println("Stan kontaktronu: OTWARTY");
    client.publish(contactron_topic, "open", true);
  }
}
  }
}  

Jeśli chodzi o sterowanie przekaźnikiem to jak ogarnę wysyłanie MQTT payload z bramki do Arduino to dołożę do projektu i tutaj pytanie jak wysłać z bramki określony topic do konkretnego klienta? Jest Opublikuj pakiet MQTT w narzędziach deweloperskich ale nie za bardzo czaję jak wysłać do konkretnego klienta.

3 polubienia

Myślę, że się da… :slight_smile: Wszystkie 10 czujników DS18B20 można pod jeden pin podpiąć gdyż ich stany odczytuje się po adresie. Tutaj jest manual: https://majsterkowo.pl/forum/odczyt-z-kilku-czujnikow-ds18b20-t1010.html

Pozostałe rzeczy bez problemu da się zintegrować tak jak w moim projekcie.

2 polubienia

Dodałem kolejny czujnik do mojego projektu tym razem detektor światła na LM393.
Co prawda ma on tylko stan 0 lub 1 (jasno/ciemno) ale potencjometrem można sterować czułość przy jakim natężeniu światła czujnik zadziała.
Czujnik przyda się w automatyzacjach np. jeśli jest ciemno zapal lampy. Koszt sensora to aż 2,90 zł :wink:
Czujnik podpiamy do Arduino do 3,3V lub 5V, GND, Pin 5.

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <DHT.h>
#define humidity_topic "arduino01/humidity"
#define temperature_topic "arduino01/temperature"
#define contactron_topic "arduino01/door"
#define light_topic "arduino01/light"
#define DHTPIN 2 // 2 Pin Arduino do ktorego podlaczony jest czujnik
#define DHTTYPE DHT22 //21 or 22 w zaleznosci od czujnika
#define KONTAKTRON 3 //3 pin Arduino do kontaktronu
#define CZUJNIKSWIATLA 5 //5 pin Arduino do czujnika światła

DHT dht(DHTPIN, DHTTYPE);
unsigned long readTime;

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
IPAddress ip(192, 168, 2, 225); // Adres IP Arduino
IPAddress server(192, 168, 2, 1); // Adres IP bramki z serwerem MQTT
char message_buff[100];
EthernetClient ethClient;
PubSubClient client(ethClient);
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  for (int i = 0; i < length; i++) {
  Serial.print((char)message[i]);
  messageTemp += (char)message[i];
  }
}

void reconnect() {
  // Oczekowani na polaczenie z serwerem
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
     Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Czekaj 5 sekund przed ponownym polaczeniem
      delay(5000);
    }
  }
}

void setup()
{
  Serial.begin(9600);
  client.setServer("192.168.2.1", 1883); // Adres serwera MQTT - bramka
  client.setCallback(callback);
  Ethernet.begin(mac);
  dht.begin(); // Start sensor DHT
  pinMode(KONTAKTRON, INPUT_PULLUP); //Kontaktron jako wejście
  pinMode(CZUJNIKSWIATLA, INPUT); // Czujnik światła
  Serial.println(Ethernet.localIP()); //Wyswietlenie adresu IP Arduino
  readTime = 0;
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
         (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diffhum = 1.0; // częstotliwość odswierzania co 1 %
float diff = 0.1;
int KONT = 2; // stan 2 przy pierwszym odczycie
int light = 2; // stan 2 przy pierwszym odczycie

void loop()
{
  if (!client.connected()) {
  reconnect();
  }

  client.loop();
  long now = millis();
  if (now - lastMsg > 1000) {
    lastMsg = now;
    float newTemp = dht.readTemperature();
    float newHum = dht.readHumidity();
    int newKONT = digitalRead(KONTAKTRON);
    int newlight = digitalRead(CZUJNIKSWIATLA);
     
    // ODCZYT TEMPERATURY
    if (checkBound(newTemp, temp, diff)) {
      temp = newTemp;
      Serial.print("Temperatura: ");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }
    // ODCZYT WILGOTNOSCI
    if (checkBound(newHum, hum, diffhum)) {
      hum = newHum;
      Serial.print("Wilgotność: ");
      Serial.println(String(hum).c_str());
      client.publish(humidity_topic, String(hum).c_str(), true);
    }
    // STAN KONTAKTRONU PRZY URUCHOMIENIU
    if (KONT == 2) {     
      if (newKONT == 0){
        Serial.println("Stan kontaktronu: ZAMKNIETY");
        client.publish(contactron_topic, "close", true);
      }
      if (newKONT == 1){
        Serial.println("Stan kontaktronu: OTWARTY");
        client.publish(contactron_topic, "open", true);
      }  
    }
    // STAN KONTAKTRONU PRZY ZMIANIE
    if (newKONT != KONT) {     
      KONT = newKONT;
      if (KONT == 0){
        Serial.println("Stan kontaktronu: ZAMKNIETY");
        client.publish(contactron_topic, "close", true);
      }
      if (KONT == 1){
        Serial.println("Stan kontaktronu: OTWARTY");
        client.publish(contactron_topic, "open", true);
      }
    }
    // ODCZYT NATEZENIA SWIATLA
    if (light == 2) {     
      if (newlight == 0){
        Serial.println("Swiatlo: JASNO");
        client.publish(light_topic, "light", true);
      }
      if (newlight == 1){
        Serial.println("Swialo: CIEMNO");
        client.publish(light_topic, "dark", true);
      }  
    }
    // STAN CZUJNIKA PRZY ZMIANIE
    if (newlight != light) {     
      light = newlight;
      if (light == 0){
        Serial.println("Swiatlo: JASNO");
        client.publish(light_topic, "light", true);
      }
      if (light == 1){
        Serial.println("Swiatlo: CIEMNO");
        client.publish(light_topic, "dark", true);
      }
    }
   
  }
} 

image


Mam jeszcze kilka czujników :slight_smile: wkrótce ciąg dalszy…

3 polubienia

Oczywiście powyższe linie w programie są zbędne (wszystkie komendy Serial.print i Serial.println) jeśli używamy połączenia Ethernet i MQTT a służą jedynie do diagnostyki jakie dane są wysyłane z Arduino. Finalnie możemy je usunąć z programu a wysyłanie do Jolki nadal będzie działać gdyż realizuje to komenda client.publish(light_topic, "dark", true);

Fachowców w dziedzinie programowania w c++ proszę o wyrozumiałości gdyż są to moje początki z Arduino IDE. Efekt finalny osiągnięty i to jest najważniejsze :slight_smile:
Część kodu zaczerpnięta jest z innych projektów dostępnych w necie.

Kolejna wersja projektu MultiSensorsJolka v0.0.3 :slight_smile:

Co nowego doszło:

  • dodałem sterowanie dwoma przekaźnikami “arduino01/cmnd/POWER1” ON/OFF
  • dodałem wysyłanie statusu Arduino “arduino01/tele/LWT” Aktywny/Nieaktywny
  • dodałem ustawianie statusu przekaźników “arduino01/stat/POWER1” po odbiorze komendy ON / OFF wykorzystywane do ustalenia ostatniego stanu przekaźników
  • dodałem wysyłanie statusu do HASS “arduino01/tele/HASS_STATE” z wersją projektu.

Co planuję w kolejnych wersjach:

  • Zrobienie MultiSensora bardziej HA i Sonoff/tasmota friendly :slight_smile: tzn. używanie podobnych nazw wysyłanych/odbieranych komend MQTT;
  • Zrobienie funkcji autodiscovery tak jak mają Sonoffy z oprogramowaniem Tasmota, tzn. wysyłanie informacji jakie czujniki posiada i jakie mają zostać utworzone w HA;
  • Dodanie webservera do Arduino wyświetlającego stan czujników i przekaźników oraz możliwość przełączania (wersja beta serwera web już w trakcie testów);
  • Odczyt ostatniego stanu przekaźników z homeassistant i przekazanie do Arduino;
  • Dodanie kolejnych czujników np. Miernik energii, detektor gazu/czadu itp…
  • Zrobienie bramki do odbioru kodów RF 433 jako odpowiednik Sonoff RF Bridge i wysyłanie ich do Jolki;
  • Jeśli kody odbiera to może i wysyłać i sterować urządzeniami RF 433 :slight_smile:
  • Może i obsługa IRda odbiór i wysyłanie ?
  • Dodanie zmiennej debug on/off - włączającej i wyłączającej wysyłanie komunikatów do portu szeregowego;
  • Zapis loga na kartę MicroSD w Ethernet Shield;
  • sugestie mile widziane :slight_smile:
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <DHT.h>
#define SoftVersion "MultiSensorsJolka v0.0.3 by Iron "
#define SoftBuildDate "2020-02-04T21:09:00"
#define ModuleType "Arduino Mega 2560+Ethernet Shield"
#define humidity_topic "arduino01/tele/SENSORhumidity"
#define temperature_topic "arduino01/tele/SENSORtemperature"
#define contactron_topic "arduino01/tele/SENSORdoor"
#define light_topic "arduino01/tele/SENSORlight"
#define availability_topic "arduino01/tele/LWT" // Aktywny / Nieaktywny
#define state_topic "arduino01/tele/HASS_STATE" 
#define statestatus_topic "arduino01/stat/STATUS"
#define statepower1_topic "arduino01/stat/POWER1" // ON/OFF
#define statepower2_topic "arduino01/stat/POWER2" // ON/OFF
#define command1_topic "arduino01/cmnd/POWER1"
#define command2_topic "arduino01/cmnd/POWER2"
#define DHTPIN 2 // 2 Pin Arduino do ktorego podlaczony jest czujnik
#define DHTTYPE DHT22 //21 or 22 w zaleznosci od czujnika
#define KONTAKTRON 3 //3 pin Arduino do kontaktronu
#define CZUJNIKSWIATLA 5 //5 pin Arduino do czujnika światła
#define PRZEKAZNIK1 6 //6 pin Arduino do przekaźnika 1
#define PRZEKAZNIK2 7 //7 pin Arduino do przekaźnika 2
volatile byte relayState = LOW;

DHT dht(DHTPIN, DHTTYPE);
unsigned long readTime;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
IPAddress ip(192, 168, 2, 225); // Adres IP Arduino
IPAddress server(192, 168, 2, 1); // Adres IP bramki z serwerem MQTT
char message_buff[100];
String AddIP;
String AddMAC;
EthernetClient ethClient;
PubSubClient client(ethClient);

void callback(char* topic, byte* payload, unsigned int length) {
  String payloadmsg;
  for (int i=0;i<length;i++) {
    payloadmsg += (char)payload[i];
  }
  // Zalaczenie przekaznika 1   
  if (strcmp (topic, command1_topic) == 0) {
    Serial.print("Przekaźnik 1 = ");
    if (payloadmsg == "ON") {
      Serial.println("ZAŁĄCZ");
      digitalWrite(PRZEKAZNIK1, LOW); // Załącz przekaźnik 1
      client.publish(statepower1_topic, "ON", true);    
    }
    if (payloadmsg == "OFF") {
      Serial.println("WYŁĄCZ");
      digitalWrite(PRZEKAZNIK1, HIGH); // Wyłącz przekaźnik 1
      client.publish(statepower1_topic, "OFF", true);    
    }
  }
  // Zalaczenie przekaznika 2
  if (strcmp (topic, command2_topic) == 0) {
    Serial.print("Przekaźnik 2 = ");
    if (payloadmsg == "ON") {
      Serial.println("ZAŁĄCZ");
      digitalWrite(PRZEKAZNIK2, LOW); // Załącz przekaźnik 2
      client.publish(statepower2_topic, "ON", true);    
    }
    if (payloadmsg == "OFF") {
      Serial.println("WYŁĄCZ");
      digitalWrite(PRZEKAZNIK2, HIGH); // Wyłącz przekaźnik 2
      client.publish(statepower2_topic, "OFF", true);    
    }
  }
}
void reconnect() {
  // Oczekowani na polaczenie z serwerem
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("arduinoClient")) {
     Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Czekaj 5 sekund przed ponownym polaczeniem
      delay(5000);
    }
  }
}

void setup()
{
  Serial.begin(9600);
  client.setServer("192.168.2.1", 1883); // Adres serwera MQTT - bramka
  client.setCallback(callback);
  Ethernet.begin(mac, ip);
  dht.begin(); // Start sensor DHT
  pinMode(KONTAKTRON, INPUT_PULLUP); //Kontaktron jako wejście
  pinMode(CZUJNIKSWIATLA, INPUT); // Czujnik światła
  pinMode(PRZEKAZNIK1, OUTPUT); // Ustawienie Pinu przekaznika 1 jako Wyjscie
  pinMode(PRZEKAZNIK2, OUTPUT); // Ustawienie Pinu przekaznika 2 jako Wyjscie
  digitalWrite(PRZEKAZNIK1, HIGH); // Wyłacz przekaźnik 1 przy starcie , HIGH - wyłącz, LOW = włącz
  digitalWrite(PRZEKAZNIK2, HIGH); // Wyłacz przekaźnik 2 przy starcie , HIGH - wyłącz, LOW = włącz
  Serial.println(Ethernet.localIP()); //Wyswietlenie adresu IP Arduino
  AddIP = String(Ethernet.localIP()).c_str();

  byte macBuffer[6];  // create a buffer to hold the MAC address
  //Ethernet.MACAddress(macBuffer); // fill the buffer
  Ethernet.MACAddress(macBuffer); //Wyswietlenie MAC Arduino
  for (byte octet = 0; octet < 6; octet++) {
    AddMAC += macBuffer[octet], HEX;
    Serial.print(macBuffer[octet], HEX); 
    if (octet < 5) {
      Serial.print('-');
    }
  }
  Serial.println();  
  readTime = 0;
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
         (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
long lastMsg = 0;
long lastMsg1 = 0;
float temp = 0.0;
float hum = 0.0;
float diffhum = 1.0; // częstotliwość odswierzania co 1 %
float diff = 0.1;
int KONT = 2; // stan 2 przy pierwszym odczycie
int light = 2; // stan 2 przy pierwszym odczycie

void loop()
{
  if (!client.connected()) {
  reconnect();
  }
  client.loop();
  long now1 = millis();
  if (now1 - lastMsg1 > 40000) {
    lastMsg1 = now1;   
   //Wyslij status
    String statemsg = "";
    statemsg += "{\"Version\":\"";
    statemsg += SoftVersion;
    statemsg += "\",\"BuildDateTime\":\"";
    statemsg += SoftBuildDate;
    statemsg += "\"}";
    client.publish(state_topic, String(statemsg).c_str(), true);
    Serial.println(String(statemsg).c_str());
    client.publish(statestatus_topic, "{\"Status\":{\"Module\":0,\"FriendlyName\":[\"Arduino01_lampa1\",\"Arduino01_lampa2\"],\"Topic\":\"Arduino01\"}}", true);
    client.publish(availability_topic, "Aktywny", true);
  }   
  long now = millis();
  if (now - lastMsg > 1000) {
    lastMsg = now;
    float newTemp = dht.readTemperature();
    float newHum = dht.readHumidity();
    int newKONT = digitalRead(KONTAKTRON);
    int newlight = digitalRead(CZUJNIKSWIATLA);
    boolean rc1 = client.subscribe(command1_topic); // Oczykiwanie na topic dla przekaźnika 1
    boolean rc2 = client.subscribe(command2_topic); // Oczykiwanie na topec dla przekaźnika 2    
    // ODCZYT TEMPERATURY
    if (checkBound(newTemp, temp, diff)) {
      temp = newTemp;
      Serial.print("Temperatura: ");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }
    // ODCZYT WILGOTNOSCI
    if (checkBound(newHum, hum, diffhum)) {
      hum = newHum;
      Serial.print("Wilgotność: ");
      Serial.println(String(hum).c_str());
      client.publish(humidity_topic, String(hum).c_str(), true);
    }
    // STAN KONTAKTRONU PRZY ZMIANIE
    if (newKONT != KONT) {     
      KONT = newKONT;
      if (KONT == 0){
        Serial.println("Stan kontaktronu: ZAMKNIETY");
        client.publish(contactron_topic, "close", true);
      }
      if (KONT == 1){
        Serial.println("Stan kontaktronu: OTWARTY");
        client.publish(contactron_topic, "open", true);
      }
    }
    // STAN KONTAKTRONU PRZY URUCHOMIENIU
    if (KONT == 2) {     
      if (newKONT == 0){
        Serial.println("Stan kontaktronu: ZAMKNIETY");
        client.publish(contactron_topic, "close", true);
      }
      if (newKONT == 1){
        Serial.println("Stan kontaktronu: OTWARTY");
        client.publish(contactron_topic, "open", true);
      }  
        client.publish(availability_topic, "online", true);
    } 
    // STAN CZUJNIKA PRZY ZMIANIE
    if (newlight != light) {     
      light = newlight;
      if (light == 0){
        Serial.println("Swiatlo: JASNO");
        client.publish(light_topic, "light", true);
      }
      if (light == 1){
        Serial.println("Swiatlo: CIEMNO");
        client.publish(light_topic, "dark", true);
      }
    }
    // ODCZYT NATEZENIA SWIATLA
    if (light == 2) {     
      if (newlight == 0){
        Serial.println("Swiatlo: JASNO");
        client.publish(light_topic, "light", true);
      }
      if (newlight == 1){
        Serial.println("Swiatlo: CIEMNO");
        client.publish(light_topic, "dark", true);
      }  
    }
  }
}  

Sensors.yaml

  • platform: mqtt
    name: “Arduino01 Status”
    state_topic: “arduino01/tele/HASS_STATE”
    availability_topic: “arduino01/tele/LWT”
    expire_after: 1000
    payload_available: “Aktywny”
    payload_not_available: “Nieaktywny”
    qos: 0
    json_attributes_topic: “arduino01/tele/HASS_STATE”
    value_template: “{{ value_json.Version }}”
- platform: mqtt
  name: "Arduino01 Temp test"
  state_topic: "arduino01/tele/SENSORtemperature"
  availability_topic: "arduino01/tele/LWT"
  payload_available: "Aktywny"
  payload_not_available: "Nieaktywny"
  qos: 0
  unit_of_measurement: "°C"
  value_template: '{{ value | round(1) }}'

- platform: mqtt
  name: "Arduino01 Wilgotność test"
  state_topic: "arduino01/tele/SENSORhumidity"
  availability_topic: "arduino01/tele/LWT"
  payload_available: "Aktywny"
  payload_not_available: "Nieaktywny"
  qos: 0
  unit_of_measurement: "%"

binary_sensors.yaml

  • platform: mqtt
    name: ‘JasnoCiemno’
    state_topic: ‘arduino01/tele/SENSORlight’
    availability_topic: “arduino01/tele/LWT”
    payload_on: “light”
    payload_off: “dark”
    device_class: light
    payload_available: “Aktywny”
    payload_not_available: “Nieaktywny”
- platform: mqtt
  name: 'Drzwi'
  state_topic: 'arduino01/tele/SENSORdoor'
  availability_topic: "arduino01/tele/LWT"
  payload_on: "open"
  payload_off: "close"
  device_class: door
  payload_available: "Aktywny"
  payload_not_available: "Nieaktywny"

switch,yaml

- platform: mqtt
  name: "Arduino Switch1"
  command_topic: "arduino01/cmnd/POWER1"
  payload_on: "ON"
  payload_off: "OFF"
  state_topic: "arduino01/stat/POWER1"
  state_on: "ON"
  state_off: "OFF"
  optimistic: true
  qos: 0
  retain: false
  availability_topic: "arduino01/tele/LWT"
  payload_available: "Aktywny"
  payload_not_available: "Nieaktywny"

- platform: mqtt
  name: "Arduino Switch2"
  command_topic: "arduino01/cmnd/POWER2"
  payload_on: "ON"
  payload_off: "OFF"
  state_topic: "arduino01/stat/POWER2"
  state_on: "ON"
  state_off: "OFF"
  optimistic: true
  qos: 0
  retain: false
  availability_topic: "arduino01/tele/LWT"
  payload_available: "Aktywny"
  payload_not_available: "Nieaktywny"
2 polubienia

Znalazłem ciekawy projekt http://cactus.io/

Bez problemu można by wykorzystać mój projekt do integracji stacji pogodowej z Jolką :slight_smile: pewnie w przyszłości zrobię taką stację pogodową .

2 polubienia

Z takich pomysłów co by można jeszcze przydatnego zrobić :slight_smile:

  • Zrobienie bramki do odbioru kodów RF 433 jako odpowiednik Sonoff RF Bridge i wysyłanie ich do Jolki;
  • Jeśli kody odbiera to może i wysyłać i sterować urządzeniami RF 433 - zastąpi to Broadlink RM Pro który do tanich nie należy :slight_smile:
  • Może i obsługa IRda odbiór i wysyłanie ? Tego nie ma ani Sonoff RF Bridge ani Broadlink RM Pro żeby sterować urządzeniami dowolnymi pilotami IRda :slight_smile:
    Broadlink może sam wysyłać kody IRda i uczyć się ich ale nie ma możliwości w trybie ciągłym odbioru kodów IRda a Sonoff RF Bridge nie obsługuje odbioru kodów IRda.
1 polubienie

Kolejna wersja projektu tym razem z autowykrywaniem sensorów przez Home Assistant. Nie ma już potrzeby definiowania w plikach sensor,switch,binary_sensor. Po uruchomieniu Arduino - Jolka automatycznie wykryje sensory i przełączniki.

image

temp wilg

/* 
 ====== MultiSensorsJolka by Iron ======
 ======      Testing platform     ======
 Arduino Mega 2560 + Ethernet Shield

 ====== Changelog ======
 v0.0.8
 - optymalizacja programu;
 v0.0.7
 - poprawa kilku features związanych z nowym HA 105;
 v0.0.6
 - autoDiscovery Home Assistant;
 v0.0.5
 - zmiana precyzji do 1 mijsca po przecinku;
 - dodanie zmiennej int SerialPrint = 0 - wyłącza debug do portu szeregowego, int WebServer = 0 - wyłącza WebServer;
 v0.0.4
 - dodanie webservera do Arduino
 - odczyt ostatniego stanu przekaźników z homeassistant
 v0.0.3
 - sterowanie dwoma przekaźnikami "arduino01/cmnd/POWER1" ON/OFF;
 - wysyłanie statusu Arduino "arduino01/tele/LWT" Aktywny/Nieaktywny;
 - ustawianie statusu przekaźników “arduino01/stat/POWER1” po odbiorze komendy ON / OFF wykorzystywane do ustalenia ostatniego stanu przekaźników;
 - porządek w topicach według struktury by tasmota: "arduino01/tele/SENSORtemperature", "arduino01/tele/SENSORhumidity", "arduino01/tele/SENSORdoor", "arduino01/tele/SENSORlight", 
 - wysyłanie statusu do HASS "arduino01/tele/HASS_STATE" z wersją projektu;
 v0.0.2
 - odczyt wilgotności co 1% a nie co 0.10 - ustawienie można zmienić w float diffhum = 1.0; // częstotliwość odswierzania co 1 %, float diff = 0.1; - tempratura co 0.1 stopień
 - dodanie obsługi kontaktronu (Kontaktron podpinamy pod PIN 3 Arduino, drugi przewód do GND. - #define KONTAKTRON 3)
 - wysyłanie statusu otwarte/zamknięte w topicu "arduino01/door"
 - dodanie obsługi czujnika/detektora światła LM393 -  Czujnik podpiamy do Arduino do Pinu 5 oraz 5V i GND;
 - czujnik ma on tylko stan 0 lub 1 (jasno/ciemno) ale potencjometrem można sterować czułość przy jakim natężeniu światła czujnik zadziała.
 v0.0.1
 - dodanie obsługi czujnika temperatury i wilgotności AM2302 lub DHT21, DHT22 (Czujnik podłączamy pod 2 pin Arduino oraz 5V i GND - #define DHTPIN 2) #define DHTTYPE DHT22 //21 or 22 w zaleznosci od czujnika
 - odczyt temperatury i wilgotności i publiowanie w topicu arduino01/tempertura, arduino01/humidity;
 - przesyłanie tylko różnicy wartości wcześniej odczytej
 ====== ToDo List ======
 - dodanie kolejnych czujników np. Miernik energii, detektor gazu/czadu itp…
 - zapis loga na kartę MicroSD w Ethernet Shield;
 ================================================================================================================================================================================================*/
#include <SPI.h>
#include <Ethernet.h>
#define MQTT_KEEPALIVE 10
#include <PubSubClient.h>
#include <DHT.h>
#define SoftVersion "MultiSensorsJolka v0.0.8 by Iron"
#define SoftBuildDate "2020-02-10T21:20:00"
#define ModuleType "Arduino Mega 2560+Ethernet Shield"
#define sensors_topic "dom-88fd54db6487cd19_arduino01/tele/SENSOR"
#define contactron_topic "dom-88fd54db6487cd19_arduino01/tele/SENSORdoor01"
#define light_topic "dom-88fd54db6487cd19_arduino01/tele/SENSORlight01"
#define availability_topic "dom-88fd54db6487cd19_arduino01/tele/LWT" // Aktywny / Nieaktywny
#define state_topic "dom-88fd54db6487cd19_arduino01/tele/HASS_STATE"
#define statestatus_topic "dom-88fd54db6487cd19_arduino01/stat/STATUS"
#define statepower1_topic "dom-88fd54db6487cd19_arduino01/tele/POWER1" // ON/OFF
#define statepower2_topic "dom-88fd54db6487cd19_arduino01/tele/POWER2" // ON/OFF
#define command1_topic "dom-88fd54db6487cd19_arduino01/cmnd/POWER1"
#define command2_topic "dom-88fd54db6487cd19_arduino01/cmnd/POWER2"
#define autodiscovery_send_topic "dom/cmnd/SetOption19"
#define autodiscovery_light_topic "homeassistant/light/arduino01/light/config"
#define autodiscovery_switch1_topic "homeassistant/switch/arduino01_RL_1/config"
#define autodiscovery_switch2_topic "homeassistant/switch/arduino01_RL_2/config"
#define autodiscovery_binary1_topic "homeassistant/binary_sensor/arduino01_BTN_1/config"
#define autodiscovery_binary2_topic "homeassistant/binary_sensor/arduino01_BTN_2/config"
#define autodiscovery_sensor1_topic "homeassistant/sensor/arduino01_AM2302_Temperature/config"
#define autodiscovery_sensor2_topic "homeassistant/sensor/arduino01_AM2302_Humidity/config"
#define autodiscovery_status_topic "homeassistant/sensor/arduino01_status/config"
#define DHTPIN 8 // 8 Pin Arduino do ktorego podlaczony jest czujnik
#define DHTTYPE DHT22 //21 or 22 w zaleznosci od czujnika lub AM2302 = DTH22
#define KONTAKTRON 3 //3 pin Arduino do kontaktronu
#define CZUJNIKSWIATLA 5 //5 pin Arduino do czujnika światła
#define PRZEKAZNIK1 6 //6 pin Arduino do przekaźnika 1
#define PRZEKAZNIK2 7 //7 pin Arduino do przekaźnika 2
#define PRZEKAZNIK3 8 //8 pin Arduino do przekaźnika 3
#define PRZEKAZNIK4 9 //9 pin Arduino do przekaźnika 4
//USE PIN Mega Ethernet Shield 0,1, 4,10, 50,51,52,53
//USE PIN UNO  Ethernet Shield 0,1, 4,10, 11,12,13

int SerialPrint = 1; // 0 - nie wysyłaj nic do portu szeregowego, 1 - debug log do portu szeregowego
int WebServer = 0;   // 0 - nie uruchamiaj WebServera, 1 - uruchom webserver
int AutoRestart = 0; // 0 - bez restaru, 1 - autorestart
int RestartTime = 1800000; // 1800000 = 30 minut
volatile byte relayState = LOW;

DHT dht(DHTPIN, DHTTYPE);
unsigned long readTime;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAD };
IPAddress ip(192, 168, 2, 225); // Adres IP Arduino
IPAddress server(192, 168, 2, 1); // Adres IP bramki z serwerem MQTT
char message_buff[100];
String AddIP;
String AddMAC;
String przekaznik1stan;
String przekaznik2stan;
int startprg = 1;
long MQTTread;

void callback(char* topic, byte* payload, unsigned int length);
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
//EthernetServer serverweb(80);

void callback(char* topic, byte* payload, unsigned int length) {
  String payloadmsg;
  for (int i=0;i<length;i++) {
    payloadmsg += (char)payload[i];
  }
 if (SerialPrint == 1) {
        Serial.print("topic received = ");
        Serial.println(topic);}
    // Autodiscovery po starcie HA
  if (strcmp (topic, autodiscovery_send_topic) == 0) { autodiscoveryHA(); }
  
  // Pierwsze włączenie arduino - odczyt stanów przekaźników z HA
  if (startprg == 1 || startprg == 2){
    if (strcmp (topic, statepower1_topic) == 0) {
      startprg = 2;
      MQTTread += 1;
      if (SerialPrint == 1) {
        Serial.print("Stan przekaźnika 1 = ");
        Serial.println(payloadmsg);}
      if (payloadmsg == "ON") {
        przekaznik1stan = "ZAŁĄCZONY";
        digitalWrite(PRZEKAZNIK1, LOW); // Załącz przekaźnik 1
      }else {
        przekaznik1stan = "WYŁĄCZONY";
        digitalWrite(PRZEKAZNIK1, HIGH); // Wyłącz przekaźnik 1
      }
    }
    if (strcmp (topic, statepower2_topic) == 0) {
      startprg = 3;
      MQTTread += 1;
      if (SerialPrint == 1) { Serial.print("Stan przekaźnika 2 = ");
        Serial.println(payloadmsg);}
      if (payloadmsg == "ON") {
        przekaznik2stan = "ZAŁĄCZONY";
        digitalWrite(PRZEKAZNIK2, LOW); // Załącz przekaźnik 1
      }else {
        przekaznik2stan = "WYŁĄCZONY";
        digitalWrite(PRZEKAZNIK2, HIGH); // Wyłącz przekaźnik 1
      }
    }
  }
    // Zalaczenie przekaznika 1   
    if (strcmp (topic, command1_topic) == 0) {
      MQTTread += 1;
      if (SerialPrint == 1) {Serial.print("Przekaźnik 1 = ");}
      if (payloadmsg == "ON") {
        przekaznik1stan = "ZAŁĄCZONY";
        if (SerialPrint == 1) {Serial.println("ZAŁĄCZ");}
        digitalWrite(PRZEKAZNIK1, LOW); // Załącz przekaźnik 1
        client.publish(statepower1_topic, "ON", true);
      }
      if (payloadmsg == "OFF") {
        przekaznik1stan = "WYŁĄCZONY";
        if (SerialPrint == 1) {Serial.println("WYŁĄCZ");}
        digitalWrite(PRZEKAZNIK1, HIGH); // Wyłącz przekaźnik 1
        client.publish(statepower1_topic, "OFF", true);    
      }
    }
  
    // Zalaczenie przekaznika 2
    if (strcmp (topic, command2_topic) == 0) {
      MQTTread += 1;
      if (SerialPrint == 1) {Serial.print("Przekaźnik 2 = ");}
      if (payloadmsg == "ON") {
        przekaznik2stan = "ZAŁĄCZONY";
        if (SerialPrint == 1) {Serial.println("ZAŁĄCZ");}
        digitalWrite(PRZEKAZNIK2, LOW); // Załącz przekaźnik 2
        client.publish(statepower2_topic, "ON", true);    
      }
      if (payloadmsg == "OFF") {
        przekaznik2stan = "WYŁĄCZONY";
        if (SerialPrint == 1) {Serial.println("WYŁĄCZ");}
        digitalWrite(PRZEKAZNIK2, HIGH); // Wyłącz przekaźnik 2
        client.publish(statepower2_topic, "OFF", true);    
      }
    }
  } 



void reconnect() {
  // Oczekowani na polaczenie z serwerem
  while (!client.connected()) {
    if (SerialPrint == 1) {Serial.print("Attempting MQTT connection...");}
    // Attempt to connect
    if (client.connect("dom-88fd54db6487cd19_arduino01","dom-88fd54db6487cd19_arduino01/tele/LWT",1,true,"Nieaktywny")) {
    if (SerialPrint == 1) {Serial.println("connected");}
    autodiscoveryHA(); // Przedstawienie się autodiscovery przy starcie
    boolean rc1 = client.subscribe(command1_topic); // Oczykiwanie na topic dla przekaźnika 1
    boolean rc2 = client.subscribe(command2_topic); // Oczykiwanie na topic dla przekaźnika 2
    boolean rcst1 = client.subscribe(statepower1_topic); // Oczekiwanie na topic ze statusem dla przekaźnika 1
    boolean rcst2 = client.subscribe(statepower2_topic); // Oczekiwanie na topic ze statusem dla przekaźnika 2
    boolean rcst3 = client.subscribe(autodiscovery_send_topic); // Oczykiwanie na topic ze statusem dla przekaźnika 2
    } else {
      if (SerialPrint == 1) {Serial.print("failed, rc=");
        Serial.print(client.state());
        Serial.println(" try again in 5 seconds");}
      // Czekaj 5 sekund przed ponownym polaczeniem
      delay(500);
    }
  }
}

void setup()
{
  if (SerialPrint == 1) {Serial.begin(9600);}
  client.setServer("192.168.2.1", 1883); // Adres serwera MQTT - bramka
  client.setCallback(callback);
  Ethernet.begin(mac, ip);
  //if (WebServer==1){  serverweb.begin();}
  dht.begin(); // Start sensor DHT
  pinMode(KONTAKTRON, INPUT_PULLUP); //Kontaktron jako wejście
  pinMode(CZUJNIKSWIATLA, INPUT); // Czujnik światła
  pinMode(PRZEKAZNIK1, OUTPUT); // Ustawienie Pinu przekaznika 1 jako Wyjscie
  pinMode(PRZEKAZNIK2, OUTPUT); // Ustawienie Pinu przekaznika 2 jako Wyjscie
  digitalWrite(PRZEKAZNIK1, HIGH); // Wyłacz przekaźnik 1 przy starcie , LOW = włącz
  digitalWrite(PRZEKAZNIK2, HIGH); // Wyłacz przekaźnik 2 przy starcie , LOW = włącz       
  if (SerialPrint == 1) {Serial.println(Ethernet.localIP());} //Wyswietlenie adresu IP Arduino
  AddIP = String(Ethernet.localIP()).c_str();
  byte macBuffer[6];  // create a buffer to hold the MAC address
  //Ethernet.MACAddress(macBuffer); // fill the buffer
  Ethernet.MACAddress(macBuffer); //Wyswietlenie MAC Arduino
  for (byte octet = 0; octet < 6; octet++) {
    AddMAC += macBuffer[octet], HEX;
    if (SerialPrint == 1) {Serial.print(macBuffer[octet], HEX);}
    if (octet < 5) {
      if (SerialPrint == 1) {Serial.print('-');}
    }
  }
  if (SerialPrint == 1) {Serial.println();}
  readTime = 0;

}

bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
         (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
  long lastMsg = 0;
  long lastMsg1 = 0;
  float temp = 0.0;
  float hum = 0.0;
  float diffhum = 1.0; // częstotliwość odswierzania co 1 %
  float diff = 0.1;
  int newKONT = 0; //
  int KONT = 2; // stan 2 przy pierwszym odczycie
  int newlight = 0; //
  int light = 2; // stan 2 przy pierwszym odczycie

void loop()
{
  if (!client.connected()) {
  reconnect();
  }
  client.loop();
  
  long now1 = millis();
  long czekaj;
  if (light == 2 ) {czekaj = 100;} else {czekaj = 60000;}
  if (now1 - lastMsg1 > czekaj) {
    lastMsg1 = now1;
    if (SerialPrint == 1) {Serial.print("Free RAM: "); Serial.println(freeRam());}
    if (SerialPrint == 1) {Serial.print("Minutes : "); Serial.println(millis()*0.000016666666666667);}
    
   //Wyslij status
    String statemsg = "";
    statemsg += "{\"Version\":\"";
    statemsg += SoftVersion;
    statemsg += "\",\"BuildDateTime\":\"";
    statemsg += SoftBuildDate;
    statemsg += "\",\"MqttReadCount\":";
    statemsg += MQTTread;
    statemsg += ",\"UptimemSec\":";
    statemsg += millis();
    statemsg += ",\"Module\":\"";
    statemsg += ModuleType;
    //statemsg += "\",\"IPAddress\":\"";
    //statemsg += String(AddIP).c_str();
    //statemsg += "\",\"MACAddress\":\"";
    //statemsg += String(AddMAC).c_str();
    statemsg += "\"}";
     client.publish(state_topic, String(statemsg).c_str(), true);
    if (SerialPrint == 1) {Serial.println(String(statemsg).c_str());}
    client.publish(availability_topic, "Aktywny", true);
 }
    
  long now = millis();
  if (now - lastMsg > 1000) {
    lastMsg = now;
    float newTemp = dht.readTemperature();
    float newHum  = dht.readHumidity();
    int newKONT = digitalRead(KONTAKTRON);
    int newlight = digitalRead(CZUJNIKSWIATLA);
    String msgSendMQT;
    int changeTEHU = 0;
    
    // ODCZYT TEMPERATURY
    if (checkBound(newTemp, temp, diff)) {
      temp = newTemp;
      changeTEHU = 1;
      if (SerialPrint == 1) {Serial.print("Temperatura: ");
        Serial.println(newTemp,1);}
    }
    // ODCZYT WILGOTNOSCI
    if (checkBound(newHum, hum, diffhum)) {
      hum = newHum;
      changeTEHU = 1;
      if (SerialPrint == 1) {Serial.print("Wilgotność: ");
        Serial.println(newHum,1);}
      //client.publish(humidity_topic, String(newHum,1).c_str(), true);
    }
      if (changeTEHU == 1 ) {
        msgSendMQT = "{\"Time\":\"\",\"AM2302\":{\"Temperature\":"+String(newTemp)+",\"Humidity\":"+String(newHum)+"},\"TempUnit\":\"C\"}";
        client.publish(sensors_topic, String(msgSendMQT).c_str(), true);
      }
    
    // STAN KONTAKTRONU PRZY ZMIANIE
    if (newKONT != KONT) {     
      KONT = newKONT;
      if (KONT == 0){
        if (SerialPrint == 1) {Serial.println("Stan kontaktronu: ZAMKNIETY");}
        client.publish(contactron_topic, "off", true);
      }
      if (KONT == 1){
        if (SerialPrint == 1) {Serial.println("Stan kontaktronu: OTWARTY");}
        client.publish(contactron_topic, "on", true);
      }
    }
    // STAN KONTAKTRONU PRZY URUCHOMIENIU
    if (KONT == 2) {     
      if (newKONT == 0){
        if (SerialPrint == 1) {Serial.println("Stan kontaktronu: ZAMKNIETY");}
        client.publish(contactron_topic, "off", true);
      }
      if (newKONT == 1){
        if (SerialPrint == 1) {Serial.println("Stan kontaktronu: OTWARTY");}
        client.publish(contactron_topic, "on", true);
      }  
        client.publish(availability_topic, "online", true);
    } 

    // STAN CZUJNIKA PRZY ZMIANIE
    if (newlight != light) {     
      light = newlight;
      if (light == 0){
        if (SerialPrint == 1) {Serial.println("Swiatlo: JASNO");}
        client.publish(light_topic, "on", true);
      }
      if (light == 1){
        if (SerialPrint == 1) {Serial.println("Swiatlo: CIEMNO");}
        client.publish(light_topic, "off", true);
      }
    }
    // ODCZYT NATEZENIA SWIATLA
    if (light == 2) {     
      if (newlight == 0){
        if (SerialPrint == 1) {Serial.println("Swiatlo: JASNO");}
        client.publish(light_topic, "on", true);
      }
      if (newlight == 1){
        if (SerialPrint == 1) {Serial.println("Swiatlo: CIEMNO");}
        client.publish(light_topic, "off", true);
      }  
    }  
  }

  if (Serial.available() > 0)
  {
    if (Serial.read() == '@')
    {
      if (SerialPrint == 1) {Serial.println("Rebooting. . .");}
      client.publish(availability_topic, "Nieaktywny", true);
      delay(100); // Give the computer time to receive the "Rebooting. . ." message, or it won't show up
      void (*reboot)(void) = 0; // Creating a function pointer to address 0 then calling it reboots the board.
      reboot();
    }
  }
 if ( AutoRestart == 1 ) {
    if (millis() >= RestartTime){
      if (SerialPrint == 1) {Serial.println("Rebooting. . .");}
      void (*reboot)(void) = 0;
      reboot();
    }
 }
  
  /* WEB SERVER
  if (WebServer==1){
    EthernetClient client = serverweb.available();
    if (client) {
      if (SerialPrint == 1) {Serial.println("new client");}
      // an http request ends with a blank line
      boolean currentLineIsBlank = true;
      while (client.connected()) {
        if (client.available()) {
          char c = client.read();
          if (SerialPrint == 1) {Serial.write(c);}
            if (c == '\n' && currentLineIsBlank) {
            // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            // add a meta refresh tag, so the browser pulls again every 10 seconds:
            client.println("<meta http-equiv=\"refresh\" content=\"10\">");
            client.print("Temperatura: ");
            client.print(String(temp).c_str());
            client.print("<BR>Wilgotnosc: ");
            client.print(String(hum).c_str());
  
            if (KONT == 0) {client.print("<BR>Kontaktron: ZAMKNIETY");}
            if (KONT == 1) {client.print("<BR>Kontaktron: OTWARTY");}
            if (light == 0) {client.print("<BR>Swiatlo: JASNO");}
            if (light == 1) {client.print("<BR>Swiatlo: CIEMNO");}
  
            client.print("<BR>Przekaznik1: ");
            client.print(przekaznik1stan);
            client.print("<BR>Przekaznik2: ");
            client.print(przekaznik2stan);
            client.println("<br />");       
            client.println("</html>");
            break;
          }
          if (c == '\n') {
            // you're starting a new line
            currentLineIsBlank = true;
          } 
          else if (c != '\r') {
            // you've gotten a character on the current line
            currentLineIsBlank = false;
          }
        }
      }
      // give the web browser time to receive the data
      delay(1);
      // close the connection:
      client.stop();
      if (SerialPrint == 1) {Serial.println("client disonnected");}
    }
  }
  delay(100);*/
}

void autodiscoveryHA() {
    // Autodiscovery HomeAssistant
    if (SerialPrint == 1) {Serial.println("Sending autodiscovery to HA");Serial.println("Send @ to restart Arduino"); }
    client.publish(autodiscovery_status_topic, "{\"name\":\"Arduino01 status\",\"stat_t\":\"~HASS_STATE\",\"avty_t\":\"~LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"json_attributes_topic\":\"~HASS_STATE\",\"unit_of_meas\":\" \",\"val_tpl\":\"{{value_json['MqttReadCount']}}\",\"ic\":\"mdi:information-outline\",\"uniq_id\":\"arduino01_status\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]],\"name\":\"arduino01\",\"model\":\"arduino01\",\"sw_version\":\"0.0.8\",\"manufacturer\":\"Iron\"},\"~\":\"dom-88fd54db6487cd19_arduino01/tele/\"}", true);
    client.publish(autodiscovery_sensor1_topic, "{\"name\":\"AM2302 Temperature Arduino01\",\"stat_t\":\"~SENSOR\",\"avty_t\":\"~LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"uniq_id\":\"Arduino01_AM2302_Temperature\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]]},\"~\":\"dom-88fd54db6487cd19_arduino01/tele/\",\"unit_of_meas\":\"°C\",\"val_tpl\":\"{{value_json['AM2302'].Temperature}}\",\"dev_cla\":\"temperature\"}", true);
    client.publish(autodiscovery_sensor2_topic, "{\"name\":\"AM2302 Humidity Arduino01\",\"stat_t\":\"~SENSOR\",\"avty_t\":\"~LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"uniq_id\":\"Arduino01_AM2302_Humidity\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]]},\"~\":\"dom-88fd54db6487cd19_arduino01/tele/\",\"unit_of_meas\":\"%\",\"val_tpl\":\"{{value_json['AM2302'].Humidity}}\",\"dev_cla\":\"humidity\"}", true);
    client.publish(autodiscovery_switch1_topic, "{\"name\":\"Arduino01 Switch 01\",\"cmd_t\":\"~cmnd/POWER1\",\"stat_t\":\"~tele/POWER1\",\"pl_off\":\"OFF\",\"pl_on\":\"ON\",\"avty_t\":\"~tele/LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"uniq_id\":\"arduino01_RL_1\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]]},\"~\":\"dom-88fd54db6487cd19_arduino01/\"}", true);
    client.publish(autodiscovery_switch2_topic, "{\"name\":\"Arduino01 Switch 02\",\"cmd_t\":\"~cmnd/POWER2\",\"stat_t\":\"~tele/POWER2\",\"pl_off\":\"OFF\",\"pl_on\":\"ON\",\"avty_t\":\"~tele/LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"uniq_id\":\"arduino01_RL_2\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]]},\"~\":\"dom-88fd54db6487cd19_arduino01/\"}", true);
    client.publish(autodiscovery_binary1_topic, "{\"name\":\"Arduino01 Drzwi 01\",\"stat_t\":\"~tele/SENSORdoor01\",\"avty_t\":\"~tele/LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"uniq_id\":\"arduino01_BTN_1\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]]},\"~\":\"dom-88fd54db6487cd19_arduino01/\",\"device_class\":\"door\",\"pl_on\":\"on\",\"pl_off\":\"off\"}", true);
    client.publish(autodiscovery_binary2_topic, "{\"name\":\"Arduino01 Światło 01\",\"stat_t\":\"~tele/SENSORlight01\",\"avty_t\":\"~tele/LWT\",\"pl_avail\":\"Aktywny\",\"pl_not_avail\":\"Nieaktywny\",\"uniq_id\":\"arduino01_BTN_2\",\"device\":{\"identifiers\":[\"arduino01\"],\"connections\":[[\"mac\",\"DE:AD:BE:EF:FE:AD\"]]},\"~\":\"dom-88fd54db6487cd19_arduino01/\",\"device_class\":\"light\",\"pl_on\":\"on\",\"pl_off\":\"off\"}", true);
}

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
1 polubienie

Dałeś to na github?
I pytanie czy działa przez USB?

Jeszcze nie wstawiałem na Gita bo to na razie wersja beta. Jak przejdzie testy to wtedy zamieszczę :slight_smile:
Założenie było takie żeby działało przez sieć LAN. Tak jak w opisie Arduino komunikuje się z HA przez MQTT. Nie ma potrzeby łączenia Arduino przez USB bo to ogranicza zasięg/długość kabla a z reguły kable od czujników układa się w inne miejsce niż jest zlokalizowana bramka z MQTT, dlatego po sieci LAN jest wygodniej. Dla rozwiązania po USB jest gotowiec mySensors.

Zamieść na github przyspiesza to rozwój projektu.
Ja proponuję opis funkcji aby np wiedzieć wy zahashowac aby nie mieć gdy ktoś chce mieć tylko np kontaktrony.
Oraz
Też opis aby wiedzieć jak dodać więcej danych urządzeń z danego typu.

Kolejna wersja 0.0.8 - poprawione wysyłanie autodiscovery po restarcie HA, optymailizacja programu.

1 polubienie

co myślicie o takim czymś zamiast dokładać ethernet shield? https://allegro.pl/oferta/mega2560-klon-wifi-esp8266-32mb-flash-arduino-ide-8486046925?fromVariant=8459105042

1 polubienie

Projekt dotyczy wersji przewodowej bo takie było jego założenie żeby z HA było połączenie po kablu, a to co zaproponowałeś to ma tylko WiFi. Jeśli chodzi o wifi to można to taniej zrobić na Wemos które maja więcej pamięci niż Arduino oraz na całej masie innych modułów z WiFi np. Sonoff, ESP32, ESP8266, NodeMCU, itp… To ja znalazłem ciekawsze rozwiązanie :slight_smile: https://www.olimex.com/Products/IoT/ESP32/ESP32-POE/open-source-hardware

1 polubienie

(wpis wycofany przez autora, zostanie automatycznie usunięty za 24 godziny, chyba że zostanie oflagowany)

Kurde jestem zielony w tym. Mam pi4 a chce zrobić sterowanie oświetleniem przez HA jak również sterowanie zwykłymi klawiszami. Więc muszę połączyć Pi4 z Andruino mega plus chyba takie coś np moduł 8 przekaźnikowy
[/quote]

To rozwiązanie z Ethernet Shield nie wymaga łączenia Arduino z Rpi czy AIS wystarczy tylko wpiąć Arduino w sieć Ethernet i komunikacja jest po MQTT który jest zainstalowany na RPi czy AIS. W programie dla Arduino wystarczy tylko podać adres serwera MQTT na bramce. No i do mojego projektu dodać dwa wyjścia przekaźnikowe analogicznie jak switch1 i switch2. W sumie to mam właśnie taki moduł 4 przekaźnikowy jak widać na fotkach z optoizolacją podłączony do Arduino.

Dokładnie ten: https://botland.com.pl/pl/przekazniki/2579-modul-przekaznikow-4-kanaly-z-optoizolacja-styki-10a250vac-cewka-5v.html

No tak tylko 4 kanałowego to ja mogę sonoffa kupić. Minimum 16 kanałów do oświetlenia potrzebuję plus do tego odczyty temp i wilg. z dht22 z 4szt by mi stykło. Andruino mega z wifi kosztuje tyle co andruino+ethernet shield ale tego z wifi chyba jeszcze nikt nie testował więc nie wiadomo czy będzie działał. Więc teraz pytanie czy iść obecnym tematem i będe pewny że wszystko będzie działać bez problemu? Tylko czy napewno te 16 przekaźników obsłuży.
Coś takiego: https://botland.com.pl/pl/przekazniki/6941-modul-przekaznikow-16-kanalow-z-optoizolacja-styki-10a250vac-cewka-12v.html

Albo takie 2 moduły nawet taniej wychodzi: https://botland.com.pl/pl/przekazniki/2966-modul-przekaznikow-8-kanalow-z-optoizolacja-styki-10a250vac-cewka-5v-niebieski.html