Skip to content

Instantly share code, notes, and snippets.

@rafalw
Created February 5, 2020 18:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rafalw/3350c6378983932e23c8ae79cee0f16f to your computer and use it in GitHub Desktop.
Save rafalw/3350c6378983932e23c8ae79cee0f16f to your computer and use it in GitHub Desktop.
Arduino + MQTT + gBridge.io + Google Home = Smart Home (cz. 1 – sterowanie przekaźnikiem)
/*
SmartHome by Rafał ;)
Przełącznik (przekaźnik) sterowany przez WiFi (MQTT, Google Home).
Cechy:
– obsługa protokołu MQTT (biblioteka PubSubClient: https://pubsubclient.knolleary.net/);
– podłączenie do Google Home realizowane przez gBridge (https://gbridge.kappelt.net/device) z wykorzystaniem lokalnego mostka
(RaspberryPi 1 + Mosquitto 1.4) ze względu na brak obsługi TLS w Arduino (patrz: dokumentacja gBridge);
– platforma sprzętowa: Arduino UNO + Ethernet Shield (W5100) + moduł DIY z przekaźnikiem RM96P-5-W;
– sterowanie przełącznikiem (przekaźnikiem NO).
*/
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <Timer.h> // https://github.com/JChristensen/Timer/
// Zakomentować, jeśli chcemy wyłączyć komunikację przez port szeregowy
#define DEBUG
// Wyprowadzenia dwukolorowej diody (wspólna katoda) sygnalizującej (po)łączenie i przekaźnika
#define LED_RED 7
#define LED_GREEN 3
#define RELAY 5
// Wyprowadzenia konfiguracyjne Ethernet Shield
#define W5100_CS 10
#define SDCARD_CS 4
// Konfiguracja sieciowa Arduino w formacie zgodnym z biblioteką Arduino Ethernet
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; // dowolny MAC adres...
IPAddress ip ( 192, 168, 1, 80); // Adresacja zgodna z siecią domową
IPAddress dns ( 1, 1, 1, 1);
IPAddress gateway ( 192, 168, 1, 100);
IPAddress subnet ( 255, 255, 255, 0);
IPAddress server ( 192, 168, 1, 2);
// Dane uwierzytelniające dla brokera
const char* user_id = "gbridge-uXXXX-XXXXXXXXX"; // user_id unikatowy, w oparciu o user_name
const char* user_name = "gbridge-uXXXX"; // user_name zdefiniowane w serwisie gBridge
const char* user_passwd = "*************"; // user_passwd jak wyżej
// Zmienna przechowująca lokalnie informację o stanie przycisku, odczytywaną przez aplikację sterującą, np. Google Home
char state[] = "0";
// Połączenie sieciowe i połączenie z brokerem MQTT
EthernetClient ethClient;
PubSubClient client(server, 1883, ethClient); // połączenie z mostkiem nr 1 (RPi) - nieszyfrowane
// Timer do obsługi próby (ponownego) połączenia z brokerem oraz obsługi sygnalizacji stanu (po)łączenia diodą świecącą
Timer t;
// Aktualny stan diody sygnalizacyjnej
int led_state = 0;
// Funkcja zwrotna, wywoływana przez obiekt PubSubClient po odebraniu informacji z zasubskrybowanego tematu
void callback(char* topic, byte* payload, unsigned int length) {
// Lokalna kopia informacji zwrotnej – ważne!!! (potrzebny jest tylko pierwszy element ciągu, bo mamy w temacie
// tylko jedną cechę "onoff" – bedzie miała wartość 1 lub 0)
char payload_tmp = payload[0];
#ifdef DEBUG
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.print(payload_tmp);
Serial.println();
#endif
// W zależności od wartości odebranej z brokera – włączenie lub wyłączenie przekaźnika
if (payload_tmp == 49) { // '1' w ASCII
digitalWrite(RELAY, HIGH);
state[0] = '1';
} else if (payload_tmp == 48) { // '0' w ASCII
digitalWrite(RELAY, LOW);
state[0] = '0';
}
// Publikacja aktualnego stanu przekaźnika – '1' oznacza włączony.
client.publish("gBridge/uXXXX/dXXXXX/onoff/set", state);
}
// Nawiązywanie (ponowne) połączenia z brokerem (funkcja wywoływana przez timer co 5 sek.)
void reconnect() {
if (!client.connected()) {
#ifdef DEBUG
Serial.print("Attempting MQTT connection...");
#endif
// Próba połączenia
if (client.connect(user_id, user_name, user_passwd)) {
#ifdef DEBUG
Serial.println("connected");
#endif
// Po uzyskaniu połączenia – publikacja aktualnego stanu przekaźnika
client.publish("gBridge/uXXXX/dXXXXX/onoff/set", state);
// ...i ponowna subskrypcja stanu przełącznika sterującego (cecha tematu – w wolnym tłumaczeniu opisu protokołu MQTT)
client.subscribe("gBridge/uXXXX/dXXXXX/onoff");
} else {
#ifdef DEBUG
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
#endif
}
}
}
// Miganie LED jeśli nie ma połączenia z brokerem (funkcja wywoływana przez timer co 200ms)
void ledBlink() {
if (!client.connected()) {
digitalWrite(LED_GREEN, LOW);
if (led_state == 0) {
led_state = 1;
digitalWrite(LED_RED, HIGH);
} else {
led_state = 0;
digitalWrite(LED_RED, LOW);
}
} else {
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
}
}
void setup() {
// Wyprowadzenia dla LED
pinMode(LED_RED, OUTPUT);
digitalWrite(LED_RED, LOW);
pinMode(LED_GREEN, OUTPUT);
digitalWrite(LED_GREEN, LOW);
// Wyprowadzenie dla przekaźnika
pinMode(RELAY, OUTPUT);
digitalWrite(RELAY, LOW);
// Wyłączamy obsługę czytnika kart SD (element Ethernet Shielda)
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
#ifdef DEBUG
Serial.begin(115200);
#endif
client.setCallback(callback);
Ethernet.begin(mac, ip, dns, gateway, subnet);
// Chwila dla sprzętu... W drodze wyjątku funkcja delay() – tutaj akurat doskonale się sprawdza.
delay(1500);
// Co 5 sek. próba nawiązania połączenia z brokerem (jeśli to konieczne)
t.every(5000, reconnect);
// Co 200 ms zapalanie LED gdy nie ma połączenia z brokerem (gdy połączenie zostanie nawiązane, LED świeci ciągle)
t.every(200, ledBlink);
}
void loop() {
if (client.connected()) {
client.loop();
}
t.update();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment