Created
February 5, 2020 18:05
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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