This is the 14th of my Blogs for the Bluetooth Unleashed Design Challenge
It is technically after the Challenge has ended, but is here for completeness.
The other posts are here :-
Concept
The idea is to detect the bluetooth transmitted from the vehicle and signal other Home Automation functions.
If the vehicle is known then it can open the garage door, and inform the home owner that xx is home.
Hardware
The detection point needs to be at the start of the driveway, and because there is no power source, this will need to be low power with solar charging.
The PSOC range seems a very good fit, but because of the timeline and my need to upskill, the inital design will be Arduino based and some form of RF transmitter/transceiver.
Adding a vehicle detection loop or beam is necessary to ensure those vehicles without bluetooth will also trigger the system.
ESP8266
I decided to use the ESP8266 as the Indoor Notification device.
As I thought about it, it seemed that I could use the MQTT to control the External Lights and the Garage Door.
The original plan was to use NodeRed and the Sonof devices.
These contain a ESP device and have fewer GPIO, but work exactly the same.
In my summary made the comment that " .. I needed to add a timer so that the Indoor Notification display returned to showing the time, after 60 secs... "
But while I was thinking about the other clients, it struck me that they all used most of the same code, with a few bits changed here and there.
The topic doesn't need to change, but each purpose just needs to drive the GPIO and adjust the "ON" time to suit.
The broker will register each connection, so it needs to be unique.
The sketch then becomes one piece of code and you comment out depending on the purpose.
With that in mind, I made the changes and the code is here :-
/* Sketch to run a ESP3266 driven by time. This displays on a 12 x neopixel ring The colors of the 'hands' are: RED = Hours GREEN = Minutes BLUE = Seconds credit to https://www.hackster.io/thearduinoguy/esp8266-neopixel-ring-clock-a9cc74 TimeClient.h can be obtained from https://github.com/squix78/esp8266-weather-station Extract the TimeClient.h and TimeClient.cpp files and add them into the sketch folder (hence the "TimeClient.h") It also connects to a MQTT broker and receives information back to either drive the display and operate a GPIO pin This allows a Garage Door or External light control. Mark Beckett */ #include <Adafruit_NeoPixel.h> #include <ESP8266WiFi.h> #include "TimeClient.h" #include <PubSubClient.h> // Pin definition based on ESP8266 Witty // see https://www.element14.com/community/community/design-challenges/bluetoothunleashed/blog/2018/07/11/btsentry-notifications#comment-135458 #define PIN D5 // Neopixel pin #define LED D4 // Inbuilt LED (LOW = ON) #define Relay D3 // Relay pin int ledsInString = 12; long lastUpdate = millis(); long lastSecond = millis(); long lastMQTTMessage; //note the time the last mqtt message was received. long OnTime = 60000; // set the time the display (60 secs)is on for. //long OnTime = 2000; // When relay controls Garage Door (2 secs) //long OnTime = 300000; // When relay controls Outdoor Lights (5 minutes) String hours, minutes, seconds; int currentSecond, currentMinute, currentHour; int StatusColour[] = {0,0,0}; //used to set the colour of the pixels when not an hour, min or sec. String MessagePayload = ""; const char ssid[] = "Your SSID"; // your network SSID (name) const char pass[] = "Your Password"; // your network password const char* mqttServer = "Broker IP"; const int mqttPort = 1883; const char* mqttUser = ""; const char* mqttPassword = ""; const char* mqtt_topic = "OpenHAB_mqtt"; // topic is OpenHAB_mqtt const float UTC_OFFSET = 12; TimeClient timeClient(UTC_OFFSET); Adafruit_NeoPixel strip = Adafruit_NeoPixel(ledsInString, PIN); WiFiClient espClient; PubSubClient client(espClient); void setup() { pinMode(LED, OUTPUT); // Initialize the LED_BUILTIN pin as an output pinMode(Relay, OUTPUT); // Initialize the Relay pin as an output Serial.begin(115200); Serial.println(); Serial.println(); strip.begin(); strip.setBrightness(128); strip.show(); // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, pass); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); timeClient.updateTime(); updateTime() ; lastUpdate = millis(); lastSecond = millis(); delay(1000); // give system time client.setServer(mqttServer, mqttPort); client.setCallback(callback); while (!client.connected()) { Serial.println("Connecting to MQTT..."); //if (client.connect("Roller1")) // use this if the relay drives the Garage Door //if (client.connect("Lights1")) // use this if the relay controls Outdoor Lights if (client.connect("Indoor1")) { Serial.println("connected"); } else { Serial.print("failed with state "); Serial.print(client.state()); delay(2000); } } client.subscribe(mqtt_topic); } void loop() { if ((millis() - lastUpdate) > 1800000) updateTime(); if ((millis() - lastMQTTMessage) > OnTime) // 60 secs { StatusColour[0] = 0; StatusColour[1] = 0; StatusColour[2] = 0; // set back to zero. // the display will update on the next second, so no need to call updateDisplay() digitalWrite(LED, HIGH); // Inverted LOW = ON) digitalWrite(Relay, HIGH); // inverting relay drive LOW = ON } if ((millis() - lastSecond) > 1000) { strip.setPixelColor((currentHour * 1), StatusColour[0],StatusColour[1],StatusColour[2]); strip.setPixelColor((currentMinute / 5), StatusColour[0],StatusColour[1],StatusColour[2]); strip.setPixelColor((currentSecond / 5), StatusColour[0],StatusColour[1],StatusColour[2]); strip.show(); lastSecond = millis(); currentSecond++; if (currentSecond > 59) { currentSecond = 0; currentMinute++; if (currentMinute > 59) { currentMinute = 1; currentHour++; if (currentHour > 12) currentHour = 0; } } String currentTime = String(currentHour) + ':' + String(currentMinute) + ':' + String(currentSecond); Serial.println(currentTime); updateDisplay(); } client.loop(); } void updateTime() { hours = timeClient.getHours(); minutes = timeClient.getMinutes(); seconds = timeClient.getSeconds(); currentHour = hours.toInt(); if (currentHour >= 12) currentHour = currentHour - 12; currentMinute = minutes.toInt(); currentSecond = seconds.toInt(); lastUpdate = millis(); } void updateDisplay() { for (int j = 0; j < ledsInString; j++) { strip.setPixelColor(j,StatusColour[0],StatusColour[1],StatusColour[2] ); } strip.setPixelColor((currentHour * 1), 255, 0, 0); strip.setPixelColor((currentMinute / 5), 0, 255, 0); strip.setPixelColor((currentSecond / 5), 0, 0, 255); strip.show(); } void callback(char* topic, byte* payload, unsigned int length) { char incoming[length]; Serial.print("Message arrived in topic: "); Serial.println(topic); Serial.print("Message:"); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); MessagePayload = MessagePayload + (char)payload[i]; } Serial.println(); Serial.println("-----------------------"); //MessagePayload = incoming; //Serial.print("MessagePayLoad = : "); if (MessagePayload == "Known Visitor") { StatusColour[0] = 0; StatusColour[1] = 255; digitalWrite(LED, LOW); // LOW = ON digitalWrite(Relay, LOW); // LOW = ON lastMQTTMessage = millis(); updateDisplay(); } else { if (MessagePayload == "UnKnown Visitor") { StatusColour[0] = 255; StatusColour[1] = 0; // If the ESP8266 client is for the Garage Door, then comment out the next two lines digitalWrite(LED, LOW); // LOW = ON digitalWrite(Relay, LOW); // LOW = ON lastMQTTMessage = millis(); updateDisplay(); } } MessagePayload = ""; }
The bits that change are :-
long OnTime = 60000; // set the time the display (60 secs)is on for. //long OnTime = 2000; // When relay controls Garage Door (2 secs) //long OnTime = 300000; // When relay controls Outdoor Lights (5 minutes)
If it is an Indoor Notification then 60 seconds seems long enough as a warning.
In my application they would be knocking on the door shortly after that.
Each client needs to have a unique ID when it registers with the broker
//if (client.connect("Roller1")) // use this if the relay drives the Garage Door //if (client.connect("Lights1")) // use this if the relay controls Outdoor Lights if (client.connect("Indoor1"))
If you have more than 1 Indoor Notification, then Indoor2, Indoor3 etc seems appropriate.
Obviously opening the Garage Door for some stranger is not a good idea.
So comment out line 218 and 219
// If the ESP8266 client is for the Garage Door, then comment out the next two lines digitalWrite(LED, LOW); // LOW = ON digitalWrite(Relay, LOW); // LOW = ON
Outdoor Lights
I have enabled the Lights regardless of day or night.
I envisage that there would also be a daylight sensor, but you could utilise an LDR and feed that into another GPIO.
You could also use a different topic and have the script decide if it was dark enough to turn on lights.
I imagine when I connect this to the Lights (that I don't currently have), then one or other daylight sensing arrangement will be added.
Proof
I offer the two images below to show it works.
The onboard LED is driven at the same time as the Relay, and you can see the display going red to signify an "Unknown Visitor".
After 60 seconds it returns to the normal time display
You can see the Red Relay LED is out and the blue Onboard LED is OFF.
Do I need the Neopixel ring.
I have discovered that if the ESP8266 does not connect with the broker, then the time doesn't function.
This is done in Lines 102 to 117 where it stays inside the
while (!client.connected())
So it provides some sort of assurance that it is connected.
You may want to use a LED to show connection, but I'd suggest that you blink it to show you are connected to the broker and the wifi is still up.
With the time being updated every second, it still only grabs it every 30 mins, so it isn't exactly a real time indication.
Timeclient.h runs off to Google, so trying to grab that every minute is probably going to get tiring, and likely to end up on some sort of list.
If your router can provide NTP, then there could be some merit in modifying the library.
(BTW you add TimeClient.h and TimeClient.cpp into the same directory as your sketch ... hence the quotes #include "TimeClient.h" )
You could change the colour of the neopixels to indicate the Wifi is connected, but the broker isn't.
There are a few more tweaks to make this a bit more polished.
So there is my version of mqtt clients of the system.
I have always been keen to utilise this simple method of sending messages and status, but never really got around to trying it.
I can see more projects using these or the big brother ESP32
ESP32 and Mongoose OS - Discoveries
Mark
Top Comments