├── .gitignore ├── Arduino Uno Programmer ├── Breadboard.fzz └── Breadboard.jpg ├── Getting Started ├── ArduinoCode │ └── Blink │ │ └── Blink.ino ├── GettingStarted.fzz └── GettingStarted.jpg ├── Home Automation ├── HAP-NodeJS Accessories │ ├── RGBLight_accessory.js │ └── simpleLight_accessory.js ├── Part 1 │ ├── Breadboard.fzz │ ├── Breadboard.jpg │ └── ESP8266_SimpleMQTT │ │ └── ESP8266_SimpleMQTT.ino ├── Part 2 │ ├── Fritzing │ │ ├── Both on one breadboard.fzz │ │ ├── Both on one breadboard.jpg │ │ ├── Button Board.fzz │ │ ├── Button Board.jpg │ │ ├── Relay Board.fzz │ │ └── Relay Board.jpg │ ├── MQTT_Logger.py │ ├── buttonNode │ │ └── buttonNode.ino │ └── lightNode │ │ └── lightNode.ino ├── Part 3 │ ├── Breadboard Layouts │ │ ├── ESP Nodes.fzz │ │ ├── ESP Nodes.png │ │ ├── Teensy Monitor.fzz │ │ └── Teensy Monitor.png │ ├── ESP_Conduit │ │ └── ESP_Conduit.ino │ ├── doorNode │ │ └── doorNode.ino │ ├── teensyCode │ │ └── teensyCode.ino │ └── tempNode │ │ └── tempNode.ino ├── Part 4 │ ├── Breadboard Layouts │ │ ├── ESP Nodes.fzz │ │ ├── ESP Nodes.png │ │ ├── Teensy Monitor.fzz │ │ └── Teensy Monitor.png │ ├── ESP_Conduit │ │ └── ESP_Conduit.ino │ ├── HomeAssistant │ │ └── configuration.yaml │ ├── doorNode │ │ └── doorNode.ino │ ├── lightNode │ │ └── lightNode.ino │ ├── teensyCode │ │ └── teensyCode.ino │ └── tempNode │ │ └── tempNode.ino ├── Part 5 │ ├── Breadboard Layouts │ │ ├── ESP Nodes.fzz │ │ ├── ESP Nodes.png │ │ ├── Teensy Monitor.fzz │ │ └── Teensy Monitor.png │ ├── ESP_Conduit │ │ └── ESP_Conduit.ino │ ├── HomeAssistant │ │ └── configuration.yaml │ ├── homeSecPi.py │ └── teensyCode │ │ └── teensyCode.ino ├── Part 6 │ ├── Breadboard Layouts │ │ ├── RGBlight.fzz │ │ └── RGBlight.png │ └── wifiRGB │ │ ├── myTypes.h │ │ └── wifiRGB.ino ├── Part 7 │ ├── Install HAP-NodeJS.txt │ └── RGBLight_accessory.js ├── Part 8 │ └── relayLight_accessory.js └── Sketches │ ├── RGBLight │ └── RGBLight.ino │ └── RelayControl │ └── RelayControl.ino ├── LICENSE ├── README.md ├── Relay Control ├── Breadboard.fzz ├── Breadboard.jpg └── relayControl │ └── relayControl.ino └── Serial Breakout Test ├── espNode └── espNode.ino └── teensyNode └── teensyNode.ino /.gitignore: -------------------------------------------------------------------------------- 1 | Home Automation/Part 2/logs 2 | -------------------------------------------------------------------------------- /Arduino Uno Programmer/Breadboard.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Arduino Uno Programmer/Breadboard.fzz -------------------------------------------------------------------------------- /Arduino Uno Programmer/Breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Arduino Uno Programmer/Breadboard.jpg -------------------------------------------------------------------------------- /Getting Started/ArduinoCode/Blink/Blink.ino: -------------------------------------------------------------------------------- 1 | int led = 2; 2 | 3 | // the setup routine runs once when you press reset: 4 | void setup() { 5 | // initialize the digital pin as an output. 6 | pinMode(led, OUTPUT); 7 | } 8 | 9 | // the loop routine runs over and over again forever: 10 | void loop() { 11 | digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level) 12 | delay(1000); // wait for a second 13 | digitalWrite(led, LOW); // turn the LED off by making the voltage LOW 14 | delay(1000); // wait for a second 15 | } -------------------------------------------------------------------------------- /Getting Started/GettingStarted.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Getting Started/GettingStarted.fzz -------------------------------------------------------------------------------- /Getting Started/GettingStarted.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Getting Started/GettingStarted.jpg -------------------------------------------------------------------------------- /Home Automation/HAP-NodeJS Accessories/RGBLight_accessory.js: -------------------------------------------------------------------------------- 1 | var Accessory = require('../').Accessory; 2 | var Service = require('../').Service; 3 | var Characteristic = require('../').Characteristic; 4 | var uuid = require('../').uuid; 5 | 6 | 7 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 8 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 9 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 10 | 11 | //These 3 values MUST be unique for every accessory you make. If they are not then IOS may have issues and mess 12 | //the entire homekit setup and you will have to reset homekit on IOS. 13 | var NAME = "YOUR ACCESSORY NAME"; //give you accessory a name! 14 | var USERNAME = "11:22:33:44:55:66"; //this is like a mac address for the accessory 15 | var SERIAL = '123456789abc' //unique serial address for the accessory 16 | 17 | var MQTT_ID = 'homekit' + SERIAL 18 | var MQTT_IP = 'YOUR.MQTT.IP.ADDRESS' 19 | 20 | var relayTopic = '/your/mqtt/topic' //this will be the topic that you publish to, to update the accessory 21 | var statusTopic = relayTopic + "/status"; //this will the topic that this script subscribes to in order to get updates on the current status of the accessory 22 | 23 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 24 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 25 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 26 | 27 | 28 | // MQTT Setup 29 | var mqtt = require('mqtt'); 30 | var options = { 31 | port: 1883, 32 | host: MQTT_IP, 33 | clientId: MQTT_ID 34 | }; 35 | var client = mqtt.connect(options); 36 | client.on('message', function(topic, message) { 37 | //incoming MQTT parse here 38 | if(topic == statusTopic){ 39 | if(message != 'p1' || message != 'p0'){ //ignore 'p0' and 'p1' moodlight activate/disable statuses 40 | var messageParsed = message.toString().split(","); //split the message into strings 41 | //console.log("Message = " + messageParsed); 42 | 43 | //parse the current HSB values from the status message 44 | var hue = Math.round(parseFloat(messageParsed[0].slice(1)) * 360); 45 | var sat = Math.round(parseFloat(messageParsed[1]) * 100); 46 | var bri = Math.round(parseFloat(messageParsed[2]) * 100); 47 | 48 | //set the power state of the light based on the brightness being not zero 49 | if(bri != 0){ 50 | LightController.power = true; 51 | } 52 | else{ 53 | LightController.power = false; 54 | } 55 | 56 | //set the HSB values 57 | LightController.brightness = bri; 58 | LightController.hue = hue; 59 | LightController.saturation = sat; 60 | 61 | //update the IOS device 62 | LightController.updateIOS(); 63 | } 64 | } 65 | 66 | }); 67 | 68 | 69 | client.subscribe(statusTopic, {qos: 1}); 70 | 71 | 72 | var LightController = { 73 | name: NAME, //name of accessory 74 | pincode: "031-45-154", 75 | username: USERNAME, // MAC like address used by HomeKit to differentiate accessories. 76 | manufacturer: "HAP-NodeJS", //manufacturer (optional) 77 | model: "v1.0", //model (optional) 78 | serialNumber: SERIAL, //serial number (optional) 79 | 80 | power: false, //curent power status 81 | brightness: 100, //current brightness 82 | hue: 0, //current hue 83 | saturation: 0, //current saturation 84 | 85 | lastSaturation: 0, 86 | lastHue: 0, 87 | lastBrightness: 100, 88 | 89 | savedBrightness: 100, //this is what the power switch will return to when flipped on 90 | 91 | outputLogs: false, //output logs 92 | 93 | //set power state of accessory 94 | setPower: function(status) { 95 | 96 | if((status == true && this.power == false) || (status == false && this.power == true) ){ 97 | 98 | //if turned on set the brightness to the last brightness before it was turned off 99 | if(status == true){ 100 | this.brightness = this.savedBrightness; 101 | this.updateLight(); 102 | this.power = true; 103 | } 104 | 105 | //if turned off set the brightness to 0 and update the light 106 | else{ 107 | this.brightness = 0; 108 | this.updateLight(); 109 | this.power = false; 110 | } 111 | } 112 | 113 | }, 114 | 115 | //get power of accessory 116 | getPower: function() { 117 | if(this.outputLogs) console.log("'%s' is in %s mode.", this.name, this.power ? "mood" : "set"); 118 | return this.power; 119 | }, 120 | 121 | 122 | 123 | //RGB ONLY 124 | 125 | //set the brightness of the accessory 126 | setBrightness: function(brightness) { //set brightness 127 | if(this.outputLogs) console.log("Setting '%s' brightness to %s", this.name, brightness); 128 | 129 | this.brightness = brightness; 130 | this.savedBrightness = brightness; 131 | 132 | //if the brightness is above 0 then set the power state to on otherwise set it to off 133 | if(brightness > 0){this.power = true;} 134 | else{this.power = false;} 135 | 136 | this.updateLight(); 137 | }, 138 | 139 | //get the current brightness of the light 140 | getBrightness: function() { //get brightness 141 | if(this.outputLogs) console.log("'%s' brightness is %s", this.name, this.brightness); 142 | return this.brightness; 143 | }, 144 | 145 | //set the saturation value of the light 146 | setSaturation: function(saturation) { 147 | if(this.outputLogs) console.log("Setting '%s' saturation to %s", this.name, saturation); 148 | this.saturation = saturation; 149 | this.updateLight(); 150 | }, 151 | 152 | //get the saturation of the light 153 | getSaturation: function() { 154 | if(this.outputLogs) console.log("'%s' saturation is %s", this.name, this.saturation); 155 | return this.saturation; 156 | }, 157 | 158 | //set the hue of the light 159 | setHue: function(hue) { 160 | if(this.outputLogs) console.log("Setting '%s' hue to %s", this.name, hue); 161 | this.hue = hue; 162 | this.updateLight(); 163 | }, 164 | 165 | //get the hue of the light 166 | getHue: function() { 167 | if(this.outputLogs) console.log("'%s' hue is %s", this.name, this.hue); 168 | return this.hue; 169 | }, 170 | 171 | //uodate the values on the IOS device all at once 172 | updateIOS: function(){ 173 | lightAccessory 174 | .getService(Service.Lightbulb) 175 | .getCharacteristic(Characteristic.On) 176 | .updateValue(this.power); 177 | 178 | lightAccessory 179 | .getService(Service.Lightbulb) 180 | .getCharacteristic(Characteristic.Brightness) 181 | .updateValue(this.brightness); 182 | 183 | lightAccessory 184 | .getService(Service.Lightbulb) 185 | .getCharacteristic(Characteristic.Hue) 186 | .updateValue(this.hue); 187 | 188 | lightAccessory 189 | .getService(Service.Lightbulb) 190 | .getCharacteristic(Characteristic.Saturation) 191 | .updateValue(this.saturation); 192 | }, 193 | 194 | 195 | identify: function() { //identify the accessory 196 | if(this.outputLogs) console.log("Identify the '%s'", this.name); 197 | }, 198 | 199 | //Sends an mqtt update to the light if needed 200 | updateLight: function(){ 201 | if(this.lastSaturation != this.saturation || this.lastHue != this.hue || this.lastBrightness != this.brightness){ 202 | 203 | pubBrightness = this.brightness / 100; 204 | pubHue = this.hue / 360; 205 | pubSaturation = this.saturation / 100; 206 | 207 | toPublish = 'h' + pubHue.toFixed(3).toString() + ',' + pubSaturation.toFixed(3).toString() + ',' + pubBrightness.toFixed(3).toString(); 208 | 209 | client.publish(lightTopic, toPublish); 210 | 211 | this.lastBrightness = this.brightness; 212 | this.lastHue = this.hue; 213 | this.lastSaturation = this.saturation; 214 | } 215 | } 216 | } 217 | 218 | // Generate a consistent UUID for our light Accessory that will remain the same even when 219 | // restarting our server. We use the `uuid.generate` helper function to create a deterministic 220 | // UUID based on an arbitrary "namespace" and the word "light". 221 | var lightUUID = uuid.generate('hap-nodejs:accessories:light' + LightController.name); 222 | 223 | // This is the Accessory that we'll return to HAP-NodeJS that represents our light. 224 | var lightAccessory = exports.accessory = new Accessory(LightController.name, lightUUID); 225 | 226 | // Add properties for publishing (in case we're using Core.js and not BridgedCore.js) 227 | lightAccessory.username = LightController.username; 228 | lightAccessory.pincode = LightController.pincode; 229 | 230 | // set some basic properties (these values are arbitrary and setting them is optional) 231 | lightAccessory 232 | .getService(Service.AccessoryInformation) 233 | .setCharacteristic(Characteristic.Manufacturer, LightController.manufacturer) 234 | .setCharacteristic(Characteristic.Model, LightController.model) 235 | .setCharacteristic(Characteristic.SerialNumber, LightController.serialNumber); 236 | 237 | // listen for the "identify" event for this Accessory 238 | lightAccessory.on('identify', function(paired, callback) { 239 | LightController.identify(); 240 | callback(); 241 | }); 242 | 243 | // Add the actual Lightbulb Service and listen for change events from iOS. 244 | // We can see the complete list of Services and Characteristics in `lib/gen/HomeKitTypes.js` 245 | lightAccessory 246 | .addService(Service.Lightbulb, LightController.name) // services exposed to the user should have "names" like "Light" for this case 247 | .getCharacteristic(Characteristic.On) 248 | .on('set', function(value, callback) { 249 | LightController.setPower(value); 250 | 251 | // Our light is synchronous - this value has been successfully set 252 | // Invoke the callback when you finished processing the request 253 | // If it's going to take more than 1s to finish the request, try to invoke the callback 254 | // after getting the request instead of after finishing it. This avoids blocking other 255 | // requests from HomeKit. 256 | callback(); 257 | }) 258 | // We want to intercept requests for our current power state so we can query the hardware itself instead of 259 | // allowing HAP-NodeJS to return the cached Characteristic.value. 260 | .on('get', function(callback) { 261 | callback(null, LightController.getPower()); 262 | }); 263 | 264 | 265 | 266 | 267 | 268 | 269 | /*** 270 | RGB ONLY 271 | */ 272 | 273 | 274 | // also add an "optional" Characteristic for Brightness 275 | lightAccessory 276 | .getService(Service.Lightbulb) 277 | .addCharacteristic(Characteristic.Brightness) 278 | .on('set', function(value, callback) { 279 | LightController.setBrightness(value); 280 | callback(); 281 | }) 282 | .on('get', function(callback) { 283 | callback(null, LightController.getBrightness()); 284 | }); 285 | 286 | // also add an "optional" Characteristic for Saturation 287 | lightAccessory 288 | .getService(Service.Lightbulb) 289 | .addCharacteristic(Characteristic.Saturation) 290 | .on('set', function(value, callback) { 291 | LightController.setSaturation(value); 292 | callback(); 293 | }) 294 | .on('get', function(callback) { 295 | callback(null, LightController.getSaturation()); 296 | }); 297 | 298 | // also add an "optional" Characteristic for Hue 299 | lightAccessory 300 | .getService(Service.Lightbulb) 301 | .addCharacteristic(Characteristic.Hue) 302 | .on('set', function(value, callback) { 303 | LightController.setHue(value); 304 | callback(); 305 | }) 306 | .on('get', function(callback) { 307 | callback(null, LightController.getHue()); 308 | }); -------------------------------------------------------------------------------- /Home Automation/HAP-NodeJS Accessories/simpleLight_accessory.js: -------------------------------------------------------------------------------- 1 | var Accessory = require('../').Accessory; 2 | var Service = require('../').Service; 3 | var Characteristic = require('../').Characteristic; 4 | var uuid = require('../').uuid; 5 | 6 | 7 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 8 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 9 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 10 | 11 | //These 3 values MUST be unique for every accessory you make. If they are not then IOS may have issues and mess 12 | //the entire homekit setup and you will have to reset homekit on IOS. 13 | var NAME = "YOUR ACCESSORY NAME"; //give you accessory a name! 14 | var USERNAME = "11:22:33:44:55:66"; //this is like a mac address for the accessory 15 | var SERIAL = '123456789abc' //unique serial address for the accessory 16 | 17 | var MQTT_ID = 'homekit' + SERIAL 18 | var MQTT_IP = 'YOUR.MQTT.IP.ADDRESS' 19 | 20 | var relayTopic = '/your/mqtt/topic' //this will be the topic that you publish to, to update the accessory 21 | var statusTopic = relayTopic + "/status"; //this will the topic that this script subscribes to in order to get updates on the current status of the accessory 22 | 23 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 24 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 25 | //////////////// CHANGE THESE VALUES FOR EVERY ACCESSORY !!!!!!!!!!!!!////////////////////////// 26 | 27 | 28 | 29 | // MQTT Setup 30 | var mqtt = require('mqtt'); 31 | var options = { 32 | port: 1883, 33 | host: MQTT_IP, 34 | clientId: MQTT_ID 35 | }; 36 | 37 | //connect to MQTT 38 | var client = mqtt.connect(options); 39 | 40 | //on new message from the status topic take action if needed on IOS 41 | client.on('message', function(topic, message) { 42 | 43 | if(topic == statusTopic){ 44 | 45 | if(parseInt(message) == 1 && LightController.power != true){ 46 | //console.log("recieved new status on"); 47 | LightController.setPower(true); 48 | } 49 | 50 | else if(parseInt(message) == 0 && LightController.power != false){ 51 | //console.log("recieved new status off"); 52 | LightController.setPower(false); 53 | } 54 | 55 | } 56 | 57 | }); 58 | 59 | //subscribe to the status topic 60 | client.subscribe(statusTopic, {qos: 1}); 61 | 62 | 63 | 64 | 65 | var LightController = { 66 | name: NAME, //name of accessory 67 | pincode: "031-45-154", 68 | username: USERNAME, // MAC like address used by HomeKit to differentiate accessories. 69 | manufacturer: "HAP-NodeJS", //manufacturer (optional) 70 | model: "v1.0", //model (optional) 71 | serialNumber: SERIAL, //serial number (optional) 72 | 73 | power: false, //curent power status 74 | 75 | outputLogs: false, //output logs 76 | 77 | setPower: function(status) { //set power of accessory 78 | 79 | //only publish a new state if the new state and current state are different 80 | if((status == true && this.power == false) || (status == false && this.power == true) ){ 81 | 82 | //console.log("Setting new outlet state: " + status.toString()); 83 | if(status == true){ 84 | client.publish(relayTopic, '1'); 85 | this.power = true; 86 | } 87 | else{ 88 | client.publish(relayTopic, '0'); 89 | this.power = false; 90 | } 91 | 92 | this.updateIOS(); 93 | } 94 | 95 | 96 | if(this.outputLogs) console.log("Turning the '%s' %s", this.name, status ? "on" : "off"); 97 | this.power = status; 98 | }, 99 | 100 | //get power of accessory 101 | getPower: function() { 102 | if(this.outputLogs) console.log("'%s' is %s.", this.name, this.power ? "on" : "off"); 103 | return this.power ? true : false; 104 | }, 105 | 106 | //update the IOS device with the current state of the accessory 107 | updateIOS: function(){ 108 | lightAccessory 109 | .getService(Service.Lightbulb) 110 | .getCharacteristic(Characteristic.On) 111 | .updateValue(this.power); 112 | }, 113 | 114 | identify: function() { //identify the accessory 115 | if(this.outputLogs) console.log("Identify the '%s'", this.name); 116 | } 117 | } 118 | 119 | // Generate a consistent UUID for our light Accessory that will remain the same even when 120 | // restarting our server. We use the `uuid.generate` helper function to create a deterministic 121 | // UUID based on an arbitrary "namespace" and the word "light". 122 | var lightUUID = uuid.generate('hap-nodejs:accessories:light' + LightController.serialNumber); 123 | 124 | // This is the Accessory that we'll return to HAP-NodeJS that represents our light. 125 | var lightAccessory = exports.accessory = new Accessory(LightController.name, lightUUID); 126 | 127 | // Add properties for publishing (in case we're using Core.js and not BridgedCore.js) 128 | lightAccessory.username = LightController.username; 129 | lightAccessory.pincode = LightController.pincode; 130 | 131 | // set some basic properties (these values are arbitrary and setting them is optional) 132 | lightAccessory 133 | .getService(Service.AccessoryInformation) 134 | .setCharacteristic(Characteristic.Manufacturer, LightController.manufacturer) 135 | .setCharacteristic(Characteristic.Model, LightController.model) 136 | .setCharacteristic(Characteristic.SerialNumber, LightController.serialNumber); 137 | 138 | // listen for the "identify" event for this Accessory 139 | lightAccessory.on('identify', function(paired, callback) { 140 | LightController.identify(); 141 | callback(); 142 | }); 143 | 144 | // Add the actual Lightbulb Service and listen for change events from iOS. 145 | // We can see the complete list of Services and Characteristics in `lib/gen/HomeKitTypes.js` 146 | lightAccessory 147 | .addService(Service.Lightbulb, LightController.name) // services exposed to the user should have "names" like "Light" for this case 148 | .getCharacteristic(Characteristic.On) 149 | .on('set', function(value, callback) { 150 | LightController.setPower(value); 151 | 152 | // Our light is synchronous - this value has been successfully set 153 | // Invoke the callback when you finished processing the request 154 | // If it's going to take more than 1s to finish the request, try to invoke the callback 155 | // after getting the request instead of after finishing it. This avoids blocking other 156 | // requests from HomeKit. 157 | callback(); 158 | }) 159 | 160 | // We want to intercept requests for our current power state so we can query the hardware itself instead of 161 | // allowing HAP-NodeJS to return the cached Characteristic.value. 162 | .on('get', function(callback) { 163 | callback(null, LightController.getPower()); 164 | }); 165 | -------------------------------------------------------------------------------- /Home Automation/Part 1/Breadboard.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 1/Breadboard.fzz -------------------------------------------------------------------------------- /Home Automation/Part 1/Breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 1/Breadboard.jpg -------------------------------------------------------------------------------- /Home Automation/Part 1/ESP8266_SimpleMQTT/ESP8266_SimpleMQTT.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 Simple MQTT light controller 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | //LED on ESP8266 GPIO2 19 | const int lightPin = 2; 20 | 21 | char* lightTopic = "/test/light1"; 22 | 23 | 24 | WiFiClient wifiClient; 25 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 26 | 27 | void setup() { 28 | //initialize the light as an output and set to LOW (off) 29 | pinMode(lightPin, OUTPUT); 30 | digitalWrite(lightPin, LOW); 31 | 32 | //start the serial line for debugging 33 | Serial.begin(115200); 34 | delay(100); 35 | 36 | 37 | //start wifi subsystem 38 | WiFi.begin(ssid, password); 39 | //attempt to connect to the WIFI network and then connect to the MQTT server 40 | reconnect(); 41 | 42 | //wait a bit before starting the main loop 43 | delay(2000); 44 | } 45 | 46 | 47 | 48 | void loop(){ 49 | 50 | //reconnect if connection is lost 51 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 52 | 53 | //maintain MQTT connection 54 | client.loop(); 55 | 56 | //MUST delay to allow ESP8266 WIFI functions to run 57 | delay(10); 58 | } 59 | 60 | 61 | void callback(char* topic, byte* payload, unsigned int length) { 62 | 63 | //convert topic to string to make it easier to work with 64 | String topicStr = topic; 65 | 66 | //Print out some debugging info 67 | Serial.println("Callback update."); 68 | Serial.print("Topic: "); 69 | Serial.println(topicStr); 70 | 71 | //turn the light on if the payload is '1' and publish to the MQTT server a confirmation message 72 | if(payload[0] == '1'){ 73 | digitalWrite(lightPin, HIGH); 74 | client.publish("/test/confirm", "Light On"); 75 | 76 | } 77 | 78 | //turn the light off if the payload is '0' and publish to the MQTT server a confirmation message 79 | else if (payload[0] == '0'){ 80 | digitalWrite(lightPin, LOW); 81 | client.publish("/test/confirm", "Light Off"); 82 | } 83 | 84 | } 85 | 86 | 87 | 88 | 89 | void reconnect() { 90 | 91 | //attempt to connect to the wifi if connection is lost 92 | if(WiFi.status() != WL_CONNECTED){ 93 | //debug printing 94 | Serial.print("Connecting to "); 95 | Serial.println(ssid); 96 | 97 | //loop while we wait for connection 98 | while (WiFi.status() != WL_CONNECTED) { 99 | delay(500); 100 | Serial.print("."); 101 | } 102 | 103 | //print out some more debug once connected 104 | Serial.println(""); 105 | Serial.println("WiFi connected"); 106 | Serial.println("IP address: "); 107 | Serial.println(WiFi.localIP()); 108 | } 109 | 110 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 111 | if(WiFi.status() == WL_CONNECTED){ 112 | // Loop until we're reconnected to the MQTT server 113 | while (!client.connected()) { 114 | Serial.print("Attempting MQTT connection..."); 115 | 116 | // Generate client name based on MAC address and last 8 bits of microsecond counter 117 | String clientName; 118 | clientName += "esp8266-"; 119 | uint8_t mac[6]; 120 | WiFi.macAddress(mac); 121 | clientName += macToStr(mac); 122 | 123 | //if connected, subscribe to the topic(s) we want to be notified about 124 | if (client.connect((char*) clientName.c_str())) { 125 | Serial.print("\tMTQQ Connected"); 126 | client.subscribe(lightTopic); 127 | } 128 | 129 | //otherwise print failed for debugging 130 | else{Serial.println("\tFailed."); abort();} 131 | } 132 | } 133 | } 134 | 135 | //generate unique name from MAC addr 136 | String macToStr(const uint8_t* mac){ 137 | 138 | String result; 139 | 140 | for (int i = 0; i < 6; ++i) { 141 | result += String(mac[i], 16); 142 | 143 | if (i < 5){ 144 | result += ':'; 145 | } 146 | } 147 | 148 | return result; 149 | } 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /Home Automation/Part 2/Fritzing/Both on one breadboard.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 2/Fritzing/Both on one breadboard.fzz -------------------------------------------------------------------------------- /Home Automation/Part 2/Fritzing/Both on one breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 2/Fritzing/Both on one breadboard.jpg -------------------------------------------------------------------------------- /Home Automation/Part 2/Fritzing/Button Board.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 2/Fritzing/Button Board.fzz -------------------------------------------------------------------------------- /Home Automation/Part 2/Fritzing/Button Board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 2/Fritzing/Button Board.jpg -------------------------------------------------------------------------------- /Home Automation/Part 2/Fritzing/Relay Board.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 2/Fritzing/Relay Board.fzz -------------------------------------------------------------------------------- /Home Automation/Part 2/Fritzing/Relay Board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 2/Fritzing/Relay Board.jpg -------------------------------------------------------------------------------- /Home Automation/Part 2/MQTT_Logger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import sys 3 | import os 4 | import paho.mqtt.client as mqtt 5 | import string 6 | import datetime 7 | import time 8 | import logging 9 | 10 | #keeps track of when we last turned the light on 11 | onStartTime = 0 12 | 13 | ############################## 14 | 15 | #Create and setup the logging subsystem 16 | logger = None 17 | 18 | logger = logging.getLogger(__name__) 19 | logger.setLevel(logging.INFO) 20 | 21 | # create a file handler 22 | timeFormat = "%a %b %d %Y %H.%M.%S" 23 | today = datetime.datetime.today() 24 | timestamp = today.strftime(timeFormat) 25 | logFile = 'logs/logs' + timestamp + '.log' 26 | handler = logging.FileHandler(logFile) 27 | handler.setLevel(logging.INFO) 28 | 29 | # create a logging format 30 | formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') 31 | handler.setFormatter(formatter) 32 | 33 | # add the handlers to the logger 34 | logger.addHandler(handler) 35 | 36 | ############################## 37 | 38 | 39 | 40 | def on_message(mqttc, obj, msg): 41 | 42 | #define our global vars for logger and the start time tracker 43 | global onStartTime 44 | global logger 45 | 46 | #get the local time in an easy to read format 47 | localtime = time.asctime( time.localtime(time.time()) ) 48 | 49 | #print the message topic and payload for debugging 50 | print msg.topic + " - " + msg.payload 51 | 52 | #check to see that the topic is our light1confirm 53 | #- not needed in this example because we are only subscribed to 1 topic as it is 54 | #- but I prefer to play it safe 55 | if (msg.topic == "/house/light1confirm"): 56 | 57 | #to do if the message said that we turned the light On 58 | if(msg.payload == "On"): 59 | #take note of when we turned the light on 60 | onStartTime = time.time() 61 | 62 | #log the light on time and print 63 | logMessage = "Light turned on at: " + localtime 64 | print logMessage 65 | logger.info(logMessage) 66 | 67 | #to do if the message said that we turned the light Off 68 | else: 69 | #take note of the total run time 70 | runTime = time.time() - onStartTime 71 | 72 | #log & print when the light turned off 73 | logMessage = "Light turned off at: " + localtime 74 | print logMessage 75 | logger.info(logMessage) 76 | 77 | #log & print the total time the light was on for 78 | logMessage = "The light was on for a total of " + str(int(runTime)) + " seconds" 79 | print logMessage 80 | logger.info(logMessage) 81 | 82 | 83 | 84 | 85 | 86 | #create our MQTT client 87 | mqttc = mqtt.Client() 88 | 89 | #tell it what to do when we recieve a message 90 | mqttc.on_message = on_message 91 | 92 | #connect to the broker (most likely it is localhost if running MQTT lotcally) 93 | mqttc.connect("127.0.0.1", 1883, 60) 94 | 95 | #subscribe to our light confirmation topic 96 | mqttc.subscribe("/house/light1confirm", 0) 97 | 98 | #start the MQTT client loop in a separate thread 99 | mqttc.loop_start() 100 | 101 | 102 | 103 | #just loop a bunch - yeah I know this is not the best way to do things 104 | while(True): 105 | time.sleep(1) 106 | -------------------------------------------------------------------------------- /Home Automation/Part 2/buttonNode/buttonNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 Simple MQTT light controller 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | //EDIT THESE LINES TO MATCH YOUR SETUP 15 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 16 | const char* ssid = "YOUR_SSID"; 17 | const char* password = "YOUR_PASSWORD"; 18 | 19 | //LED on ESP8266 GPIO2 20 | const int buttonPin = 2; 21 | 22 | //topic to publish to for controlling the other ESP module 23 | char* lightTopic = "/house/light1"; 24 | 25 | 26 | //create an instance of the bounce class 27 | Bounce myButton = Bounce(); 28 | 29 | 30 | WiFiClient wifiClient; 31 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 32 | 33 | void setup() { 34 | //initialize the button pin as an input 35 | pinMode(buttonPin, INPUT); 36 | 37 | myButton.attach(buttonPin); 38 | myButton.interval(5); 39 | 40 | //start the serial line for debugging 41 | Serial.begin(115200); 42 | delay(100); 43 | 44 | 45 | //start wifi subsystem 46 | WiFi.begin(ssid, password); 47 | 48 | //attempt to connect to the WIFI network and then connect to the MQTT server 49 | reconnect(); 50 | 51 | //wait a bit before starting the main loop 52 | delay(2000); 53 | } 54 | 55 | 56 | 57 | void loop(){ 58 | 59 | //reconnect if connection is lost 60 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 61 | 62 | //maintain MQTT connection 63 | client.loop(); 64 | 65 | //monitor the button 66 | checkButton(); 67 | 68 | //MUST delay to allow ESP8266 WIFI functions to run 69 | delay(10); 70 | } 71 | 72 | 73 | //MQTT callback 74 | void callback(char* topic, byte* payload, unsigned int length) { 75 | //we're not subscribed to any topics so we dont need to have anything here 76 | } 77 | 78 | 79 | 80 | void checkButton(){ 81 | static boolean isOn = false; //static var to keep track of the intended current light state 82 | 83 | if(myButton.update() && myButton.read() == HIGH){ //update the button and check for HIGH or LOW state 84 | 85 | //on false, the light is off so tell it to turn on and set the internal var to true 86 | if(isOn == false){ 87 | client.publish(lightTopic, "1"); 88 | isOn = true; 89 | } 90 | 91 | //else (on true), the light is on so tell it to turn off and set the internal var to false 92 | else{ 93 | client.publish(lightTopic, "0"); 94 | isOn = false; 95 | } 96 | } 97 | } 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | //networking functions 107 | 108 | void reconnect() { 109 | 110 | //attempt to connect to the wifi if connection is lost 111 | if(WiFi.status() != WL_CONNECTED){ 112 | //debug printing 113 | Serial.print("Connecting to "); 114 | Serial.println(ssid); 115 | 116 | //loop while we wait for connection 117 | while (WiFi.status() != WL_CONNECTED) { 118 | delay(500); 119 | Serial.print("."); 120 | } 121 | 122 | //print out some more debug once connected 123 | Serial.println(""); 124 | Serial.println("WiFi connected"); 125 | Serial.println("IP address: "); 126 | Serial.println(WiFi.localIP()); 127 | } 128 | 129 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 130 | if(WiFi.status() == WL_CONNECTED){ 131 | // Loop until we're reconnected to the MQTT server 132 | while (!client.connected()) { 133 | Serial.print("Attempting MQTT connection..."); 134 | 135 | // Generate client name based on MAC address and last 8 bits of microsecond counter 136 | String clientName; 137 | clientName += "esp8266-"; 138 | uint8_t mac[6]; 139 | WiFi.macAddress(mac); 140 | clientName += macToStr(mac); 141 | 142 | //if connected, subscribe to the topic(s) we want to be notified about 143 | if (client.connect((char*) clientName.c_str())) { 144 | Serial.print("\tMTQQ Connected"); 145 | client.subscribe(lightTopic); 146 | } 147 | 148 | //otherwise print failed for debugging 149 | else{Serial.println("\tFailed."); abort();} 150 | } 151 | } 152 | } 153 | 154 | //generate unique name from MAC addr 155 | String macToStr(const uint8_t* mac){ 156 | 157 | String result; 158 | 159 | for (int i = 0; i < 6; ++i) { 160 | result += String(mac[i], 16); 161 | 162 | if (i < 5){ 163 | result += ':'; 164 | } 165 | } 166 | 167 | return result; 168 | } 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Home Automation/Part 2/lightNode/lightNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 Simple MQTT light controller 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | //LED on ESP8266 GPIO2 19 | const int lightPin = 2; 20 | 21 | //topic to subscribe to for the light 22 | char* lightTopic = "/house/light1"; 23 | 24 | //topic to publish to confirm that the light has been turned on for the python script to log 25 | char* lightConfirmTopic = "/house/light1confirm"; 26 | 27 | 28 | WiFiClient wifiClient; 29 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 30 | 31 | void setup() { 32 | //initialize the light as an output and set to LOW (off) 33 | pinMode(lightPin, OUTPUT); 34 | digitalWrite(lightPin, LOW); 35 | 36 | //start the serial line for debugging 37 | Serial.begin(115200); 38 | delay(100); 39 | 40 | 41 | //start wifi subsystem 42 | WiFi.begin(ssid, password); 43 | 44 | //attempt to connect to the WIFI network and then connect to the MQTT server 45 | reconnect(); 46 | 47 | //wait a bit before starting the main loop 48 | delay(2000); 49 | } 50 | 51 | 52 | 53 | void loop(){ 54 | 55 | //reconnect if connection is lost 56 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 57 | 58 | //maintain MQTT connection 59 | client.loop(); 60 | 61 | //MUST delay to allow ESP8266 WIFI functions to run 62 | delay(10); 63 | } 64 | 65 | 66 | //MQTT callback 67 | void callback(char* topic, byte* payload, unsigned int length) { 68 | 69 | //convert topic to string to make it easier to work with 70 | String topicStr = topic; 71 | 72 | //Print out some debugging info 73 | Serial.println("Callback update."); 74 | Serial.print("Topic: "); 75 | Serial.println(topicStr); 76 | 77 | //turn the light on if the payload is '1' and publish to the confirmation topic so the python script can log it 78 | if(payload[0] == '1'){ 79 | digitalWrite(lightPin, HIGH); 80 | client.publish(lightConfirmTopic, "On"); 81 | } 82 | 83 | //turn the light off if the payload is '0' and publish to the confirmation topic so the python script can log it 84 | else if (payload[0] == '0'){ 85 | digitalWrite(lightPin, LOW); 86 | client.publish(lightConfirmTopic, "Off"); 87 | } 88 | 89 | } 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | //networking functions 99 | 100 | void reconnect() { 101 | 102 | //attempt to connect to the wifi if connection is lost 103 | if(WiFi.status() != WL_CONNECTED){ 104 | //debug printing 105 | Serial.print("Connecting to "); 106 | Serial.println(ssid); 107 | 108 | //loop while we wait for connection 109 | while (WiFi.status() != WL_CONNECTED) { 110 | delay(500); 111 | Serial.print("."); 112 | } 113 | 114 | //print out some more debug once connected 115 | Serial.println(""); 116 | Serial.println("WiFi connected"); 117 | Serial.println("IP address: "); 118 | Serial.println(WiFi.localIP()); 119 | } 120 | 121 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 122 | if(WiFi.status() == WL_CONNECTED){ 123 | // Loop until we're reconnected to the MQTT server 124 | while (!client.connected()) { 125 | Serial.print("Attempting MQTT connection..."); 126 | 127 | // Generate client name based on MAC address and last 8 bits of microsecond counter 128 | String clientName; 129 | clientName += "esp8266-"; 130 | uint8_t mac[6]; 131 | WiFi.macAddress(mac); 132 | clientName += macToStr(mac); 133 | 134 | //if connected, subscribe to the topic(s) we want to be notified about 135 | if (client.connect((char*) clientName.c_str())) { 136 | Serial.print("\tMTQQ Connected"); 137 | client.subscribe(lightTopic); 138 | } 139 | 140 | //otherwise print failed for debugging 141 | else{Serial.println("\tFailed."); abort();} 142 | } 143 | } 144 | } 145 | 146 | //generate unique name from MAC addr 147 | String macToStr(const uint8_t* mac){ 148 | 149 | String result; 150 | 151 | for (int i = 0; i < 6; ++i) { 152 | result += String(mac[i], 16); 153 | 154 | if (i < 5){ 155 | result += ':'; 156 | } 157 | } 158 | 159 | return result; 160 | } 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /Home Automation/Part 3/Breadboard Layouts/ESP Nodes.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 3/Breadboard Layouts/ESP Nodes.fzz -------------------------------------------------------------------------------- /Home Automation/Part 3/Breadboard Layouts/ESP Nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 3/Breadboard Layouts/ESP Nodes.png -------------------------------------------------------------------------------- /Home Automation/Part 3/Breadboard Layouts/Teensy Monitor.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 3/Breadboard Layouts/Teensy Monitor.fzz -------------------------------------------------------------------------------- /Home Automation/Part 3/Breadboard Layouts/Teensy Monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 3/Breadboard Layouts/Teensy Monitor.png -------------------------------------------------------------------------------- /Home Automation/Part 3/ESP_Conduit/ESP_Conduit.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT serial conduit 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | 19 | //topic to subscribe to for the door 20 | char* doorTopic = "/house/door1"; 21 | 22 | //topic to subscribe to for the temperature 23 | char* tempTopic = "/house/temp1"; 24 | 25 | 26 | 27 | WiFiClient wifiClient; 28 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 29 | 30 | void setup() { 31 | 32 | //start the serial line for debugging 33 | Serial.begin(115200); 34 | delay(100); 35 | 36 | 37 | //start wifi subsystem 38 | WiFi.begin(ssid, password); 39 | 40 | //attempt to connect to the WIFI network and then connect to the MQTT server 41 | reconnect(); 42 | 43 | //wait a bit before starting the main loop 44 | delay(2000); 45 | } 46 | 47 | 48 | 49 | void loop(){ 50 | 51 | //reconnect if connection is lost 52 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 53 | 54 | //maintain MQTT connection 55 | client.loop(); 56 | 57 | //MUST delay to allow ESP8266 WIFI functions to run 58 | delay(10); 59 | } 60 | 61 | 62 | //MQTT callback 63 | void callback(char* topic, byte* payload, unsigned int length) { 64 | 65 | //convert topic to string to make it easier to work with 66 | String topicStr = topic; 67 | char byteToSend = 0; 68 | 69 | //handle doorTopic updates 70 | if(topicStr.equals(doorTopic)){ 71 | 72 | if(payload[0] == '1'){ 73 | byteToSend = 1; 74 | } 75 | 76 | else if (payload[0] == '0'){ 77 | byteToSend = 0; 78 | } 79 | 80 | Serial.write("d"); //send a unique header - d 81 | Serial.write(byteToSend); //send the current state 82 | 83 | } 84 | 85 | //handle tempTopic updates 86 | else if(topicStr.equals(tempTopic)){ 87 | 88 | byteToSend = char(*payload); //set byte to send to the payload 89 | 90 | Serial.write("t"); //send a unique header - t 91 | Serial.write(byteToSend); //send the current temp 92 | } 93 | 94 | } 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | //networking functions 104 | 105 | void reconnect() { 106 | 107 | //attempt to connect to the wifi if connection is lost 108 | if(WiFi.status() != WL_CONNECTED){ 109 | 110 | //loop while we wait for connection 111 | while (WiFi.status() != WL_CONNECTED) { 112 | delay(500); 113 | } 114 | 115 | } 116 | 117 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 118 | if(WiFi.status() == WL_CONNECTED){ 119 | // Loop until we're reconnected to the MQTT server 120 | while (!client.connected()) { 121 | 122 | // Generate client name based on MAC address and last 8 bits of microsecond counter 123 | String clientName; 124 | clientName += "esp8266-"; 125 | uint8_t mac[6]; 126 | WiFi.macAddress(mac); 127 | clientName += macToStr(mac); 128 | 129 | //if connected, subscribe to the topic(s) we want to be notified about 130 | if (client.connect((char*) clientName.c_str())) { 131 | client.subscribe(doorTopic); 132 | client.subscribe(tempTopic); 133 | } 134 | } 135 | } 136 | } 137 | 138 | //generate unique name from MAC addr 139 | String macToStr(const uint8_t* mac){ 140 | 141 | String result; 142 | 143 | for (int i = 0; i < 6; ++i) { 144 | result += String(mac[i], 16); 145 | 146 | if (i < 5){ 147 | result += ':'; 148 | } 149 | } 150 | 151 | return result; 152 | } 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /Home Automation/Part 3/doorNode/doorNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT door sensor node 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | //input pin for the reed switch used to detect the door state 19 | const int doorPin = 2; 20 | 21 | //var to keep the door state in so we can compare it to the most recent reading 22 | //- this is to prevent us from constantly publishing the state but only publish changes 23 | bool isOpen = false; 24 | 25 | //topic to publish to for the door 26 | char* doorTopic = "/house/door1"; 27 | 28 | 29 | WiFiClient wifiClient; 30 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 31 | 32 | void setup() { 33 | //initialize the light as an output and set to LOW (off) 34 | pinMode(doorPin, INPUT); 35 | 36 | //start the serial line for debugging 37 | Serial.begin(115200); 38 | delay(100); 39 | 40 | 41 | //start wifi subsystem 42 | WiFi.begin(ssid, password); 43 | 44 | //attempt to connect to the WIFI network and then connect to the MQTT server 45 | reconnect(); 46 | 47 | //wait a bit before starting the main loop 48 | delay(2000); 49 | } 50 | 51 | 52 | 53 | void loop(){ 54 | 55 | //grab the current door state 56 | bool doorState = digitalRead(doorPin); //LOW is closed HIGH is open 57 | 58 | if(!doorState && !isOpen){ //if door is open and the state closed, publish 59 | client.publish(doorTopic,"0"); //send closed 60 | isOpen = true; 61 | delay(500); 62 | } 63 | else if(doorState && isOpen){ //if door is closed and the state is open, publish 64 | client.publish(doorTopic,"1"); //send closed 65 | isOpen = false; 66 | delay(500); 67 | } 68 | 69 | 70 | 71 | 72 | //reconnect if connection is lost 73 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 74 | //maintain MQTT connection 75 | client.loop(); 76 | //MUST delay to allow ESP8266 WIFI functions to run 77 | delay(10); 78 | } 79 | 80 | 81 | //MQTT callback 82 | void callback(char* topic, byte* payload, unsigned int length) {} 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | //networking functions 92 | 93 | void reconnect() { 94 | 95 | //attempt to connect to the wifi if connection is lost 96 | if(WiFi.status() != WL_CONNECTED){ 97 | 98 | //loop while we wait for connection 99 | while (WiFi.status() != WL_CONNECTED) { 100 | delay(500); 101 | } 102 | 103 | } 104 | 105 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 106 | if(WiFi.status() == WL_CONNECTED){ 107 | // Loop until we're reconnected to the MQTT server 108 | while (!client.connected()) { 109 | 110 | // Generate client name based on MAC address and last 8 bits of microsecond counter 111 | String clientName; 112 | clientName += "esp8266-"; 113 | uint8_t mac[6]; 114 | WiFi.macAddress(mac); 115 | clientName += macToStr(mac); 116 | 117 | //if connected, subscribe to the topic(s) we want to be notified about 118 | if (client.connect((char*) clientName.c_str())) { 119 | //subscribe to topics here 120 | } 121 | } 122 | } 123 | } 124 | 125 | //generate unique name from MAC addr 126 | String macToStr(const uint8_t* mac){ 127 | 128 | String result; 129 | 130 | for (int i = 0; i < 6; ++i) { 131 | result += String(mac[i], 16); 132 | 133 | if (i < 5){ 134 | result += ':'; 135 | } 136 | } 137 | 138 | return result; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /Home Automation/Part 3/teensyCode/teensyCode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Teensy monitor node 5 | 6 | //change these to match what you want for temperature range 7 | //note that there is no LOW_TEMP because anything under MID_TEMP 8 | //is to be considered LOW_TEMP 9 | #define HIGH_TEMP 72 10 | #define MID_TEMP 70 11 | 12 | 13 | //LED pins for temperature monitor 14 | const int tempLowPin = 14; 15 | const int tempMidPin = 13; 16 | const int tempHighPin = 12; 17 | 18 | //LED pin for door monitor 19 | const int doorPin = 10; 20 | 21 | 22 | 23 | void setup(){ 24 | //setup pins as outputs 25 | pinMode(tempHighPin, OUTPUT); 26 | pinMode(tempMidPin, OUTPUT); 27 | pinMode(tempLowPin, OUTPUT); 28 | pinMode(doorPin, OUTPUT); 29 | 30 | //begin the serial lines 31 | Serial1.begin(115200); //com to ESP 32 | Serial.begin(115200); //com to computer 33 | 34 | delay(100); 35 | } 36 | 37 | void loop(){ 38 | 39 | //if we have data & the next byte isn't one of our header bytes, read until we get to a good header value 40 | //-we can assume that if its not a valid header byte that the data is garbage 41 | while(Serial1.available() && (Serial1.peek() != 'd' && Serial1.peek() != 't')){ 42 | Serial1.read(); 43 | } 44 | 45 | //our "packets" are 2 bytes in size (1 header + 1 payload) so if we have 2 byte we have a potential valid packet 46 | if(Serial1.available() >= 2){ 47 | char headerByte = Serial1.read(); //read the header byte 48 | char payloadByte = Serial1.read(); //read the payload byte 49 | 50 | //handle door state packet 51 | if(headerByte == 'd'){ 52 | if(payloadByte == 1){ 53 | digitalWrite(doorPin, HIGH); 54 | } 55 | else if(payloadByte == 0){ 56 | digitalWrite(doorPin, LOW); 57 | } 58 | } 59 | 60 | //handle temperature packet 61 | else if(headerByte == 't'){ 62 | 63 | //high temp - red light on 64 | if(payloadByte > HIGH_TEMP){ 65 | digitalWrite(tempHighPin, HIGH); 66 | digitalWrite(tempMidPin, LOW); 67 | digitalWrite(tempLowPin, LOW); 68 | } 69 | 70 | //mid temp - green light on 71 | else if(payloadByte >= MID_TEMP){ 72 | digitalWrite(tempHighPin, LOW); 73 | digitalWrite(tempMidPin, HIGH); 74 | digitalWrite(tempLowPin, LOW); 75 | } 76 | 77 | //low temp - blue light on 78 | else{ 79 | digitalWrite(tempHighPin, LOW); 80 | digitalWrite(tempMidPin, LOW); 81 | digitalWrite(tempLowPin, HIGH); 82 | } 83 | } 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /Home Automation/Part 3/tempNode/tempNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT temp sensor node 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | //create 1-wire connection on pin 2 and connect it to the dallasTemp library 15 | OneWire oneWire(2); 16 | DallasTemperature sensors(&oneWire); 17 | 18 | 19 | //EDIT THESE LINES TO MATCH YOUR SETUP 20 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 21 | const char* ssid = "YOUR_SSID"; 22 | const char* password = "YOUR_PASSWORD"; 23 | 24 | 25 | //topic to publish to for the temperature 26 | char* tempTopic = "/house/temp1"; 27 | char currentTemp[2]; 28 | 29 | 30 | WiFiClient wifiClient; 31 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 32 | 33 | void setup() { 34 | 35 | //null terminate the temp string to be published 36 | currentTemp[1] = '\0'; 37 | 38 | //start the serial line for debugging 39 | Serial.begin(115200); 40 | delay(100); 41 | 42 | 43 | //start wifi subsystem 44 | WiFi.begin(ssid, password); 45 | 46 | //attempt to connect to the WIFI network and then connect to the MQTT server 47 | reconnect(); 48 | 49 | //start the temperature sensors 50 | sensors.begin(); 51 | 52 | //wait a bit before starting the main loop 53 | delay(2000); 54 | } 55 | 56 | 57 | 58 | void loop(){ 59 | 60 | // Send the command to update temperatures 61 | sensors.requestTemperatures(); 62 | 63 | //get the new temperature 64 | float currentTempFloat = sensors.getTempCByIndex(0); 65 | currentTemp[0] = currentTempFloat; 66 | 67 | //publish the new temperature 68 | client.publish(tempTopic, currentTemp); 69 | 70 | 71 | 72 | 73 | //reconnect if connection is lost 74 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 75 | //maintain MQTT connection 76 | client.loop(); 77 | //MUST delay to allow ESP8266 WIFI functions to run 78 | delay(5000); 79 | } 80 | 81 | 82 | //MQTT callback 83 | void callback(char* topic, byte* payload, unsigned int length) {} 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | //networking functions 93 | 94 | void reconnect() { 95 | 96 | //attempt to connect to the wifi if connection is lost 97 | if(WiFi.status() != WL_CONNECTED){ 98 | 99 | //loop while we wait for connection 100 | while (WiFi.status() != WL_CONNECTED) { 101 | delay(500); 102 | } 103 | 104 | } 105 | 106 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 107 | if(WiFi.status() == WL_CONNECTED){ 108 | // Loop until we're reconnected to the MQTT server 109 | while (!client.connected()) { 110 | 111 | // Generate client name based on MAC address and last 8 bits of microsecond counter 112 | String clientName; 113 | clientName += "esp8266-"; 114 | uint8_t mac[6]; 115 | WiFi.macAddress(mac); 116 | clientName += macToStr(mac); 117 | 118 | //if connected, subscribe to the topic(s) we want to be notified about 119 | if (client.connect((char*) clientName.c_str())) { 120 | //subscribe to topics here 121 | } 122 | } 123 | } 124 | } 125 | 126 | //generate unique name from MAC addr 127 | String macToStr(const uint8_t* mac){ 128 | 129 | String result; 130 | 131 | for (int i = 0; i < 6; ++i) { 132 | result += String(mac[i], 16); 133 | 134 | if (i < 5){ 135 | result += ':'; 136 | } 137 | } 138 | 139 | return result; 140 | } 141 | 142 | 143 | -------------------------------------------------------------------------------- /Home Automation/Part 4/Breadboard Layouts/ESP Nodes.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 4/Breadboard Layouts/ESP Nodes.fzz -------------------------------------------------------------------------------- /Home Automation/Part 4/Breadboard Layouts/ESP Nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 4/Breadboard Layouts/ESP Nodes.png -------------------------------------------------------------------------------- /Home Automation/Part 4/Breadboard Layouts/Teensy Monitor.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 4/Breadboard Layouts/Teensy Monitor.fzz -------------------------------------------------------------------------------- /Home Automation/Part 4/Breadboard Layouts/Teensy Monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 4/Breadboard Layouts/Teensy Monitor.png -------------------------------------------------------------------------------- /Home Automation/Part 4/ESP_Conduit/ESP_Conduit.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT serial conduit 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | 19 | //topic to subscribe to for the door 20 | char* doorTopic = "/house/door1"; 21 | 22 | //topic to subscribe to for the temperature 23 | char* tempTopic = "/house/temp1"; 24 | 25 | //topic to subscribe to for the light 26 | char* lightTopic = "/house/light1confirm"; 27 | 28 | 29 | 30 | WiFiClient wifiClient; 31 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 32 | 33 | void setup() { 34 | 35 | //start the serial line for debugging 36 | Serial.begin(115200); 37 | delay(100); 38 | 39 | 40 | //start wifi subsystem 41 | WiFi.begin(ssid, password); 42 | 43 | //attempt to connect to the WIFI network and then connect to the MQTT server 44 | reconnect(); 45 | 46 | //wait a bit before starting the main loop 47 | delay(2000); 48 | } 49 | 50 | 51 | 52 | void loop(){ 53 | 54 | //reconnect if connection is lost 55 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 56 | 57 | //maintain MQTT connection 58 | client.loop(); 59 | 60 | //MUST delay to allow ESP8266 WIFI functions to run 61 | delay(10); 62 | } 63 | 64 | 65 | //MQTT callback 66 | void callback(char* topic, byte* payload, unsigned int length) { 67 | 68 | //convert topic to string to make it easier to work with 69 | String topicStr = topic; 70 | String payloadStr = (char*)payload; 71 | 72 | char byteToSend = 0; 73 | 74 | //handle doorTopic updates 75 | if(topicStr.equals(doorTopic)){ 76 | 77 | if(payload[0] == '1'){ 78 | byteToSend = 1; 79 | } 80 | 81 | else if (payload[0] == '0'){ 82 | byteToSend = 0; 83 | } 84 | 85 | Serial.write("d"); //send a unique header - d 86 | Serial.write(byteToSend); //send the current state 87 | 88 | } 89 | 90 | //handle tempTopic updates 91 | else if(topicStr.equals(tempTopic)){ 92 | 93 | byteToSend = (char)payloadStr.toInt(); //convert payload String into an int (cast as char) to be sent to the Teensy via serial 94 | 95 | Serial.write("t"); //send a unique header - t 96 | Serial.write(byteToSend); //send the current temp 97 | } 98 | 99 | //handle lightTopic updates 100 | else if(topicStr.equals(lightTopic)){ 101 | 102 | if(payload[0] == '1'){ 103 | byteToSend = 1; 104 | } 105 | 106 | else if(payload[0] == '0'){ 107 | byteToSend = 0; 108 | } 109 | 110 | Serial.write("l"); //send a unique header - l 111 | Serial.write(byteToSend); //send the current state 112 | 113 | } 114 | 115 | 116 | } 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | //networking functions 126 | 127 | void reconnect() { 128 | 129 | //attempt to connect to the wifi if connection is lost 130 | if(WiFi.status() != WL_CONNECTED){ 131 | 132 | //loop while we wait for connection 133 | while (WiFi.status() != WL_CONNECTED) { 134 | delay(500); 135 | } 136 | 137 | } 138 | 139 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 140 | if(WiFi.status() == WL_CONNECTED){ 141 | // Loop until we're reconnected to the MQTT server 142 | while (!client.connected()) { 143 | 144 | // Generate client name based on MAC address and last 8 bits of microsecond counter 145 | String clientName; 146 | clientName += "esp8266-"; 147 | uint8_t mac[6]; 148 | WiFi.macAddress(mac); 149 | clientName += macToStr(mac); 150 | 151 | //if connected, subscribe to the topic(s) we want to be notified about 152 | if (client.connect((char*) clientName.c_str())) { 153 | client.subscribe(doorTopic); 154 | client.subscribe(tempTopic); 155 | client.subscribe(lightTopic); 156 | } 157 | } 158 | } 159 | } 160 | 161 | //generate unique name from MAC addr 162 | String macToStr(const uint8_t* mac){ 163 | 164 | String result; 165 | 166 | for (int i = 0; i < 6; ++i) { 167 | result += String(mac[i], 16); 168 | 169 | if (i < 5){ 170 | result += ':'; 171 | } 172 | } 173 | 174 | return result; 175 | } 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /Home Automation/Part 4/HomeAssistant/configuration.yaml: -------------------------------------------------------------------------------- 1 | homeassistant: 2 | # Name of the location where Home Assistant is running 3 | name: Home 4 | # Location required to calculate the time the sun rises and sets 5 | # latitude: 6 | # longitude: 7 | 8 | # C for Celcius, F for Fahrenheit 9 | temperature_unit: F 10 | # Pick yours from here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones 11 | time_zone: EST 12 | 13 | # Show links to resources in log and frontend 14 | # introduction: 15 | 16 | # View all events in a logbook 17 | logbook: 18 | 19 | # Track the sun 20 | #sun: 21 | 22 | # Enables support for tracking state changes over time. 23 | history: 24 | 25 | # Checks for available updates 26 | updater: 27 | 28 | # Allows you to issue voice commands from the frontend 29 | conversation: 30 | 31 | # Enables the frontend 32 | frontend: 33 | 34 | # Discover some devices automatically 35 | # discovery: 36 | 37 | http: 38 | api_password: yourPasswordHere 39 | 40 | mqtt: 41 | broker: 127.0.0.1 42 | port: 1883 43 | client_id: home-assistant-1 44 | keepalive: 60 45 | 46 | 47 | 48 | sensor 1: 49 | - platform: mqtt 50 | state_topic: "/house/temp1" 51 | unit_of_measurement: "°F" 52 | name: "Temperature" 53 | 54 | 55 | 56 | binary_sensor 1: 57 | platform: mqtt 58 | state_topic: "/house/door1" 59 | name: "Door Sensor" 60 | qos: 0 61 | payload_on: "1" 62 | payload_off: "0" 63 | 64 | 65 | 66 | 67 | switch 1: 68 | platform: mqtt 69 | name: "Outlet 1" 70 | state_topic: "/house/light1confirm" 71 | command_topic: "/house/light1" 72 | payload_on: "1" 73 | payload_off: "0" 74 | qos: 0 75 | retain: true 76 | 77 | 78 | 79 | group: 80 | Home Sensors: 81 | - binary_sensor.door_sensor 82 | - sensor.temperature 83 | - switch.outlet_1 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /Home Automation/Part 4/doorNode/doorNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT door sensor node 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | //input pin for the reed switch used to detect the door state 19 | const int doorPin = 2; 20 | 21 | //var to keep the door state in so we can compare it to the most recent reading 22 | //- this is to prevent us from constantly publishing the state but only publish changes 23 | bool isOpen = false; 24 | 25 | //topic to publish to for the door 26 | char* doorTopic = "/house/door1"; 27 | 28 | 29 | WiFiClient wifiClient; 30 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 31 | 32 | void setup() { 33 | //initialize the light as an output and set to LOW (off) 34 | pinMode(doorPin, INPUT); 35 | 36 | //start the serial line for debugging 37 | Serial.begin(115200); 38 | delay(100); 39 | 40 | 41 | //start wifi subsystem 42 | WiFi.begin(ssid, password); 43 | 44 | //attempt to connect to the WIFI network and then connect to the MQTT server 45 | reconnect(); 46 | 47 | //wait a bit before starting the main loop 48 | delay(2000); 49 | } 50 | 51 | 52 | 53 | void loop(){ 54 | 55 | //grab the current door state 56 | bool doorState = digitalRead(doorPin); //LOW is closed HIGH is open 57 | 58 | if(!doorState && !isOpen){ //if door is open and the state closed, publish 59 | client.publish(doorTopic,"0"); //send closed 60 | isOpen = true; 61 | delay(500); 62 | } 63 | else if(doorState && isOpen){ //if door is closed and the state is open, publish 64 | client.publish(doorTopic,"1"); //send closed 65 | isOpen = false; 66 | delay(500); 67 | } 68 | 69 | 70 | 71 | 72 | //reconnect if connection is lost 73 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 74 | //maintain MQTT connection 75 | client.loop(); 76 | //MUST delay to allow ESP8266 WIFI functions to run 77 | delay(10); 78 | } 79 | 80 | 81 | //MQTT callback 82 | void callback(char* topic, byte* payload, unsigned int length) {} 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | //networking functions 92 | 93 | void reconnect() { 94 | 95 | //attempt to connect to the wifi if connection is lost 96 | if(WiFi.status() != WL_CONNECTED){ 97 | 98 | //loop while we wait for connection 99 | while (WiFi.status() != WL_CONNECTED) { 100 | delay(500); 101 | } 102 | 103 | } 104 | 105 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 106 | if(WiFi.status() == WL_CONNECTED){ 107 | // Loop until we're reconnected to the MQTT server 108 | while (!client.connected()) { 109 | 110 | // Generate client name based on MAC address and last 8 bits of microsecond counter 111 | String clientName; 112 | clientName += "esp8266-"; 113 | uint8_t mac[6]; 114 | WiFi.macAddress(mac); 115 | clientName += macToStr(mac); 116 | 117 | //if connected, subscribe to the topic(s) we want to be notified about 118 | if (client.connect((char*) clientName.c_str())) { 119 | //subscribe to topics here 120 | } 121 | } 122 | } 123 | } 124 | 125 | //generate unique name from MAC addr 126 | String macToStr(const uint8_t* mac){ 127 | 128 | String result; 129 | 130 | for (int i = 0; i < 6; ++i) { 131 | result += String(mac[i], 16); 132 | 133 | if (i < 5){ 134 | result += ':'; 135 | } 136 | } 137 | 138 | return result; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /Home Automation/Part 4/lightNode/lightNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT Light Node 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | //LED on ESP8266 GPIO2 19 | const int lightPin = 2; 20 | 21 | //topic to subscribe to for the light 22 | char* lightTopic = "/house/light1"; 23 | 24 | //topic to publish to confirm that the light has been turned on for the python script to log 25 | char* lightConfirmTopic = "/house/light1confirm"; 26 | 27 | 28 | WiFiClient wifiClient; 29 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 30 | 31 | void setup() { 32 | //initialize the light as an output and set to LOW (off) 33 | pinMode(lightPin, OUTPUT); 34 | digitalWrite(lightPin, LOW); 35 | 36 | //start the serial line for debugging 37 | Serial.begin(115200); 38 | delay(100); 39 | 40 | 41 | //start wifi subsystem 42 | WiFi.begin(ssid, password); 43 | 44 | //attempt to connect to the WIFI network and then connect to the MQTT server 45 | reconnect(); 46 | 47 | //wait a bit before starting the main loop 48 | delay(2000); 49 | } 50 | 51 | 52 | 53 | void loop(){ 54 | 55 | //reconnect if connection is lost 56 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 57 | 58 | //maintain MQTT connection 59 | client.loop(); 60 | 61 | //MUST delay to allow ESP8266 WIFI functions to run 62 | delay(10); 63 | } 64 | 65 | 66 | //MQTT callback 67 | void callback(char* topic, byte* payload, unsigned int length) { 68 | 69 | //convert topic to string to make it easier to work with 70 | String topicStr = topic; 71 | 72 | //Print out some debugging info 73 | Serial.println("Callback update."); 74 | Serial.print("Topic: "); 75 | Serial.println(topicStr); 76 | 77 | //turn the light on if the payload is '1' and publish to the confirmation topic so the python script can log it 78 | if(payload[0] == '1'){ 79 | digitalWrite(lightPin, HIGH); 80 | client.publish(lightConfirmTopic, "1"); 81 | } 82 | 83 | //turn the light off if the payload is '0' and publish to the confirmation topic so the python script can log it 84 | else if (payload[0] == '0'){ 85 | digitalWrite(lightPin, LOW); 86 | client.publish(lightConfirmTopic, "0"); 87 | } 88 | 89 | } 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | //networking functions 99 | 100 | void reconnect() { 101 | 102 | //attempt to connect to the wifi if connection is lost 103 | if(WiFi.status() != WL_CONNECTED){ 104 | //debug printing 105 | Serial.print("Connecting to "); 106 | Serial.println(ssid); 107 | 108 | //loop while we wait for connection 109 | while (WiFi.status() != WL_CONNECTED) { 110 | delay(500); 111 | Serial.print("."); 112 | } 113 | 114 | //print out some more debug once connected 115 | Serial.println(""); 116 | Serial.println("WiFi connected"); 117 | Serial.println("IP address: "); 118 | Serial.println(WiFi.localIP()); 119 | } 120 | 121 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 122 | if(WiFi.status() == WL_CONNECTED){ 123 | // Loop until we're reconnected to the MQTT server 124 | while (!client.connected()) { 125 | Serial.print("Attempting MQTT connection..."); 126 | 127 | // Generate client name based on MAC address and last 8 bits of microsecond counter 128 | String clientName; 129 | clientName += "esp8266-"; 130 | uint8_t mac[6]; 131 | WiFi.macAddress(mac); 132 | clientName += macToStr(mac); 133 | 134 | //if connected, subscribe to the topic(s) we want to be notified about 135 | if (client.connect((char*) clientName.c_str())) { 136 | Serial.print("\tMTQQ Connected"); 137 | client.subscribe(lightTopic); 138 | } 139 | 140 | //otherwise print failed for debugging 141 | else{Serial.println("\tFailed."); abort();} 142 | } 143 | } 144 | } 145 | 146 | //generate unique name from MAC addr 147 | String macToStr(const uint8_t* mac){ 148 | 149 | String result; 150 | 151 | for (int i = 0; i < 6; ++i) { 152 | result += String(mac[i], 16); 153 | 154 | if (i < 5){ 155 | result += ':'; 156 | } 157 | } 158 | 159 | return result; 160 | } 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /Home Automation/Part 4/teensyCode/teensyCode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Teensy monitor node 5 | 6 | //change these to match what you want for temperature range 7 | //note that there is no LOW_TEMP because anything under MID_TEMP 8 | //is to be considered LOW_TEMP 9 | #define HIGH_TEMP 72 10 | #define MID_TEMP 70 11 | 12 | 13 | //LED pins for temperature monitor 14 | const int tempLowPin = 14; 15 | const int tempMidPin = 13; 16 | const int tempHighPin = 12; 17 | 18 | //LED pin for door monitor 19 | const int doorPin = 10; 20 | 21 | //LED pin for the light monitor 22 | const int lightPin = 9; 23 | 24 | 25 | void setup(){ 26 | //setup pins as outputs 27 | pinMode(tempHighPin, OUTPUT); 28 | pinMode(tempMidPin, OUTPUT); 29 | pinMode(tempLowPin, OUTPUT); 30 | pinMode(doorPin, OUTPUT); 31 | pinMode(lightPin, OUTPUT); 32 | 33 | //begin the serial lines 34 | Serial1.begin(115200); //com to ESP 35 | Serial.begin(115200); //com to computer 36 | 37 | delay(100); 38 | } 39 | 40 | void loop(){ 41 | 42 | //if we have data & the next byte isn't one of our header bytes, read until we get to a good header value 43 | //-we can assume that if its not a valid header byte that the data is garbage 44 | while(Serial1.available() && (Serial1.peek() != 'd' && Serial1.peek() != 't' && Serial1.peek() != 'l')){ 45 | Serial1.read(); 46 | } 47 | 48 | //our "packets" are 2 bytes in size (1 header + 1 payload) so if we have 2 byte we have a potential valid packet 49 | if(Serial1.available() >= 2){ 50 | char headerByte = Serial1.read(); //read the header byte 51 | char payloadByte = Serial1.read(); //read the payload byte 52 | Serial.println(headerByte); 53 | 54 | //handle door state packet 55 | if(headerByte == 'd'){ 56 | if(payloadByte == 1){ 57 | digitalWrite(doorPin, HIGH); 58 | } 59 | else if(payloadByte == 0){ 60 | digitalWrite(doorPin, LOW); 61 | } 62 | } 63 | 64 | //handle temperature packet 65 | else if(headerByte == 't'){ 66 | 67 | //high temp - red light on 68 | if(payloadByte > HIGH_TEMP){ 69 | digitalWrite(tempHighPin, HIGH); 70 | digitalWrite(tempMidPin, LOW); 71 | digitalWrite(tempLowPin, LOW); 72 | } 73 | 74 | //mid temp - green light on 75 | else if(payloadByte >= MID_TEMP){ 76 | digitalWrite(tempHighPin, LOW); 77 | digitalWrite(tempMidPin, HIGH); 78 | digitalWrite(tempLowPin, LOW); 79 | } 80 | 81 | //low temp - blue light on 82 | else{ 83 | digitalWrite(tempHighPin, LOW); 84 | digitalWrite(tempMidPin, LOW); 85 | digitalWrite(tempLowPin, HIGH); 86 | } 87 | } 88 | 89 | //handle light state packet 90 | else if(headerByte == 'l'){ 91 | if(payloadByte == 1){ 92 | digitalWrite(lightPin, HIGH); 93 | } 94 | else if(payloadByte == 0){ 95 | digitalWrite(lightPin, LOW); 96 | } 97 | } 98 | } 99 | 100 | } -------------------------------------------------------------------------------- /Home Automation/Part 4/tempNode/tempNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT temp sensor node 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | //create 1-wire connection on pin 2 and connect it to the dallasTemp library 15 | OneWire oneWire(2); 16 | DallasTemperature sensors(&oneWire); 17 | 18 | 19 | //EDIT THESE LINES TO MATCH YOUR SETUP 20 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 21 | const char* ssid = "YOUR_SSID"; 22 | const char* password = "YOUR_PASSWORD"; 23 | 24 | 25 | //topic to publish to for the temperature 26 | char* tempTopic = "/house/temp1"; 27 | 28 | 29 | WiFiClient wifiClient; 30 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 31 | 32 | void setup() { 33 | 34 | //start the serial line for debugging 35 | Serial.begin(115200); 36 | delay(100); 37 | 38 | 39 | //start wifi subsystem 40 | WiFi.begin(ssid, password); 41 | 42 | //attempt to connect to the WIFI network and then connect to the MQTT server 43 | reconnect(); 44 | 45 | //start the temperature sensors 46 | sensors.begin(); 47 | 48 | //wait a bit before starting the main loop 49 | delay(2000); 50 | } 51 | 52 | 53 | 54 | void loop(){ 55 | 56 | // Send the command to update temperatures 57 | sensors.requestTemperatures(); 58 | 59 | //get the new temperature 60 | float currentTempFloat = sensors.getTempCByIndex(0); 61 | 62 | //convert the temp float to a string and publish to the temp topic 63 | char temperature[10]; 64 | dtostrf(currentTempFloat,4,1,temperature); 65 | client.publish(tempTopic, temperature); 66 | 67 | 68 | 69 | 70 | //reconnect if connection is lost 71 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 72 | //maintain MQTT connection 73 | client.loop(); 74 | //MUST delay to allow ESP8266 WIFI functions to run 75 | delay(5000); 76 | } 77 | 78 | 79 | //MQTT callback 80 | void callback(char* topic, byte* payload, unsigned int length) {} 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | //networking functions 90 | 91 | void reconnect() { 92 | 93 | //attempt to connect to the wifi if connection is lost 94 | if(WiFi.status() != WL_CONNECTED){ 95 | 96 | //loop while we wait for connection 97 | while (WiFi.status() != WL_CONNECTED) { 98 | delay(500); 99 | } 100 | 101 | } 102 | 103 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 104 | if(WiFi.status() == WL_CONNECTED){ 105 | // Loop until we're reconnected to the MQTT server 106 | while (!client.connected()) { 107 | 108 | // Generate client name based on MAC address and last 8 bits of microsecond counter 109 | String clientName; 110 | clientName += "esp8266-"; 111 | uint8_t mac[6]; 112 | WiFi.macAddress(mac); 113 | clientName += macToStr(mac); 114 | 115 | //if connected, subscribe to the topic(s) we want to be notified about 116 | if (client.connect((char*) clientName.c_str())) { 117 | //subscribe to topics here 118 | } 119 | } 120 | } 121 | } 122 | 123 | //generate unique name from MAC addr 124 | String macToStr(const uint8_t* mac){ 125 | 126 | String result; 127 | 128 | for (int i = 0; i < 6; ++i) { 129 | result += String(mac[i], 16); 130 | 131 | if (i < 5){ 132 | result += ':'; 133 | } 134 | } 135 | 136 | return result; 137 | } 138 | 139 | 140 | -------------------------------------------------------------------------------- /Home Automation/Part 5/Breadboard Layouts/ESP Nodes.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 5/Breadboard Layouts/ESP Nodes.fzz -------------------------------------------------------------------------------- /Home Automation/Part 5/Breadboard Layouts/ESP Nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 5/Breadboard Layouts/ESP Nodes.png -------------------------------------------------------------------------------- /Home Automation/Part 5/Breadboard Layouts/Teensy Monitor.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 5/Breadboard Layouts/Teensy Monitor.fzz -------------------------------------------------------------------------------- /Home Automation/Part 5/Breadboard Layouts/Teensy Monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 5/Breadboard Layouts/Teensy Monitor.png -------------------------------------------------------------------------------- /Home Automation/Part 5/ESP_Conduit/ESP_Conduit.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 MQTT serial conduit 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | //EDIT THESE LINES TO MATCH YOUR SETUP 14 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 15 | const char* ssid = "YOUR_SSID"; 16 | const char* password = "YOUR_PASSWORD"; 17 | 18 | 19 | //topic to subscribe to for the door 20 | char* doorTopic = "/house/door1"; 21 | 22 | //topic to subscribe to for the temperature 23 | char* tempTopic = "/house/temp1"; 24 | 25 | //topic to subscribe to for the light 26 | char* lightTopic = "/house/light1confirm"; 27 | 28 | //topic to subscribe to for the security system enabled state 29 | char* secTopic = "/house/secStatus"; 30 | 31 | 32 | 33 | WiFiClient wifiClient; 34 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 35 | 36 | void setup() { 37 | 38 | //start the serial line for debugging 39 | Serial.begin(115200); 40 | delay(100); 41 | 42 | 43 | //start wifi subsystem 44 | WiFi.begin(ssid, password); 45 | 46 | //attempt to connect to the WIFI network and then connect to the MQTT server 47 | reconnect(); 48 | 49 | //wait a bit before starting the main loop 50 | delay(2000); 51 | } 52 | 53 | 54 | 55 | void loop(){ 56 | 57 | //reconnect if connection is lost 58 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 59 | 60 | //maintain MQTT connection 61 | client.loop(); 62 | 63 | //MUST delay to allow ESP8266 WIFI functions to run 64 | delay(10); 65 | } 66 | 67 | 68 | //MQTT callback 69 | void callback(char* topic, byte* payload, unsigned int length) { 70 | 71 | //convert topic to string to make it easier to work with 72 | String topicStr = topic; 73 | 74 | //this is a fix because the payload passed to the callback isn't null terminated 75 | //so we create a new string with a null termination and then turn that into a string 76 | char payloadFixed[100]; 77 | memcpy(payloadFixed, payload, length); 78 | payloadFixed[length] = '\0'; 79 | String payloadStr = (char*)payloadFixed; 80 | 81 | char byteToSend = 0; 82 | 83 | //handle doorTopic updates 84 | if(topicStr.equals(doorTopic)){ 85 | 86 | if(payload[0] == '1'){ 87 | byteToSend = 1; 88 | } 89 | 90 | else if (payload[0] == '0'){ 91 | byteToSend = 0; 92 | } 93 | 94 | Serial.write("d"); //send a unique header - d 95 | Serial.write(byteToSend); //send the current state 96 | 97 | } 98 | 99 | //handle tempTopic updates 100 | else if(topicStr.equals(tempTopic)){ 101 | 102 | byteToSend = (char)payloadStr.toInt(); //convert payload String into an int (cast as char) to be sent to the Teensy via serial 103 | 104 | Serial.write("t"); //send a unique header - t 105 | Serial.write(byteToSend); //send the current temp 106 | } 107 | 108 | //handle lightTopic updates 109 | else if(topicStr.equals(lightTopic)){ 110 | 111 | if(payload[0] == '1'){ 112 | byteToSend = 1; 113 | } 114 | 115 | else if(payload[0] == '0'){ 116 | byteToSend = 0; 117 | } 118 | 119 | Serial.write("l"); //send a unique header - l 120 | Serial.write(byteToSend); //send the current state 121 | } 122 | 123 | else if(topicStr.equals(secTopic)){ 124 | if(payloadStr.equals("disarmed")){ 125 | byteToSend = 0; 126 | } 127 | else if(payloadStr.equals("armed_away")){ 128 | byteToSend = 1; 129 | } 130 | else if(payloadStr.equals("triggered")){ 131 | byteToSend = 2; 132 | } 133 | 134 | Serial.write("s"); 135 | Serial.write(byteToSend); 136 | } 137 | 138 | 139 | } 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | //networking functions 149 | 150 | void reconnect() { 151 | 152 | //attempt to connect to the wifi if connection is lost 153 | if(WiFi.status() != WL_CONNECTED){ 154 | 155 | //loop while we wait for connection 156 | while (WiFi.status() != WL_CONNECTED) { 157 | delay(500); 158 | } 159 | 160 | } 161 | 162 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 163 | if(WiFi.status() == WL_CONNECTED){ 164 | // Loop until we're reconnected to the MQTT server 165 | while (!client.connected()) { 166 | 167 | // Generate client name based on MAC address and last 8 bits of microsecond counter 168 | String clientName; 169 | clientName += "esp8266-"; 170 | uint8_t mac[6]; 171 | WiFi.macAddress(mac); 172 | clientName += macToStr(mac); 173 | 174 | //if connected, subscribe to the topic(s) we want to be notified about 175 | if (client.connect((char*) clientName.c_str())) { 176 | client.subscribe(doorTopic); 177 | client.subscribe(tempTopic); 178 | client.subscribe(lightTopic); 179 | client.subscribe(secTopic); 180 | } 181 | } 182 | } 183 | } 184 | 185 | //generate unique name from MAC addr 186 | String macToStr(const uint8_t* mac){ 187 | 188 | String result; 189 | 190 | for (int i = 0; i < 6; ++i) { 191 | result += String(mac[i], 16); 192 | 193 | if (i < 5){ 194 | result += ':'; 195 | } 196 | } 197 | 198 | return result; 199 | } 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /Home Automation/Part 5/HomeAssistant/configuration.yaml: -------------------------------------------------------------------------------- 1 | homeassistant: 2 | # Name of the location where Home Assistant is running 3 | name: Home 4 | # Location required to calculate the time the sun rises and sets 5 | # latitude: 6 | # longitude: 7 | 8 | # C for Celcius, F for Fahrenheit 9 | temperature_unit: F 10 | # Pick yours from here: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones 11 | time_zone: EST 12 | 13 | # Show links to resources in log and frontend 14 | # introduction: 15 | 16 | # View all events in a logbook 17 | logbook: 18 | 19 | # Track the sun 20 | #sun: 21 | 22 | # Enables support for tracking state changes over time. 23 | history: 24 | 25 | # Checks for available updates 26 | updater: 27 | 28 | # Allows you to issue voice commands from the frontend 29 | conversation: 30 | 31 | # Enables the frontend 32 | frontend: 33 | 34 | # Discover some devices automatically 35 | # discovery: 36 | 37 | http: 38 | api_password: yourPasswordHere 39 | 40 | mqtt: 41 | broker: 127.0.0.1 42 | port: 1883 43 | client_id: home-assistant-1 44 | keepalive: 60 45 | 46 | 47 | 48 | sensor 1: 49 | - platform: mqtt 50 | state_topic: "/house/temp1" 51 | unit_of_measurement: "°F" 52 | name: "Temperature" 53 | 54 | 55 | 56 | binary_sensor 1: 57 | platform: mqtt 58 | state_topic: "/house/door1" 59 | name: "Door Sensor" 60 | qos: 0 61 | payload_on: "1" 62 | payload_off: "0" 63 | 64 | 65 | 66 | 67 | switch 1: 68 | platform: mqtt 69 | name: "Outlet 1" 70 | state_topic: "/house/light1confirm" 71 | command_topic: "/house/light1" 72 | payload_on: "1" 73 | payload_off: "0" 74 | qos: 0 75 | retain: true 76 | 77 | alarm_control_panel 1: 78 | platform: mqtt 79 | state_topic: "/house/secStatus" 80 | command_topic: "/house/secEn" 81 | name: "Security" 82 | qos: 0 83 | payload_disarm: "0" 84 | payload_arm_away: "1" 85 | 86 | 87 | 88 | group: 89 | Home Sensors: 90 | - binary_sensor.door_sensor 91 | - sensor.temperature 92 | - switch.outlet_1 93 | - alarm_control_panel.security 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Home Automation/Part 5/homeSecPi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import os 5 | import paho.mqtt.client as mqtt 6 | import smtplib 7 | import string 8 | 9 | #var to track the current status of the system (armed or disarmed) 10 | securityEnStatus = None 11 | 12 | #enable/disable email notifications - disable when testing/enable when in normal use 13 | sendEmail = False 14 | 15 | #This is like the confirm topic for the security system - it notifies other nodes about the status of the system 16 | statusTopic = "/house/secStatus" 17 | 18 | #this is the control topic that this script listens to for messages telling it to arm or disarm 19 | enableTopic = "/house/secEn" 20 | 21 | 22 | 23 | def on_connect(mqttc, obj, flags, rc): 24 | print("rc: "+str(rc)) 25 | 26 | def on_message(mqttc, obj, msg): 27 | global securityEnStatus 28 | global breachesSinceReset 29 | 30 | #if the topic is the enable topic and its to enable the system (1) 31 | #publish to the state topic that the system is armed and enable status to on 32 | if(str(msg.topic) == enableTopic and int(msg.payload) == 1): 33 | securityEnStatus = True 34 | mqttc.publish(statusTopic, "armed_away") 35 | print("Security Enabled") 36 | 37 | 38 | #if the topic is the enable topic and its to disable the system (0) 39 | #then set the enable status to off 40 | #and publish to the state topic that were disabled and publish the number of breaches 41 | elif(str(msg.topic) == enableTopic and int(msg.payload) == 0): 42 | securityEnStatus = False 43 | mqttc.publish(statusTopic, "disarmed") 44 | print("Security Disabled") 45 | 46 | 47 | #all other topics are detector nodes such as motion detectors and door sensors 48 | #so as long as the security system is enabled (armed), if one of the detector nodes is triggered 49 | #send out an alert 50 | elif(securityEnStatus == True and int(msg.payload) == 1): 51 | mqttc.publish(statusTopic, "triggered") 52 | securityAlert(str(msg.topic)) 53 | 54 | 55 | def on_publish(mqttc, obj, mid): 56 | print("mid: "+str(mid)) 57 | def on_subscribe(mqttc, obj, mid, granted_qos): 58 | print("Subscribed: "+str(mid)+" "+str(granted_qos)) 59 | def on_log(mqttc, obj, level, string): 60 | print(string) 61 | 62 | 63 | 64 | 65 | def securityAlert(alertLoc): 66 | global sendEmail 67 | 68 | 69 | print("Breach at: " + alertLoc) 70 | print("Sending Alert!\n") 71 | 72 | 73 | if(sendEmail == True): 74 | 75 | #to and from addresses 76 | fromaddr = '-----YOUR EMAIL ADDRESS-----' 77 | toaddrs = '-----EMAIL ADDRESS TO ALERT-----' 78 | 79 | #form the email header+body 80 | header = 'To:' + toaddrs + '\n' + 'From: ' + fromaddr + '\n' + 'Subject:Home Security Breach! \n' 81 | msg = header + "\nBreach Location: " + alertLoc + "\n\n" 82 | 83 | 84 | #login credentials 85 | username = '-----YOUR EMAIL ADDRESS USERNAME-----' 86 | password = '-----YOUR EMAIL ADDRESS PASSWORD-----' 87 | 88 | # send the email 89 | server = smtplib.SMTP('smtp.gmail.com:587') 90 | server.ehlo() 91 | server.starttls() 92 | server.ehlo() 93 | server.login(username,password) 94 | server.sendmail(fromaddr, toaddrs, msg) 95 | server.quit() 96 | 97 | 98 | 99 | 100 | mqttc = mqtt.Client() 101 | mqttc.on_message = on_message 102 | mqttc.on_connect = on_connect 103 | mqttc.on_publish = on_publish 104 | mqttc.on_subscribe = on_subscribe 105 | 106 | mqttc.connect("127.0.0.1", 1883, 60) 107 | 108 | #Enable Monitor 109 | mqttc.subscribe(enableTopic, 0) 110 | 111 | #detector nodes 112 | mqttc.subscribe("/house/door1", 0) 113 | 114 | 115 | mqttc.loop_forever() 116 | 117 | 118 | -------------------------------------------------------------------------------- /Home Automation/Part 5/teensyCode/teensyCode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Teensy monitor node 5 | 6 | //change these to match what you want for temperature range 7 | //note that there is no LOW_TEMP because anything under MID_TEMP 8 | //is to be considered LOW_TEMP 9 | #define HIGH_TEMP 72 10 | #define MID_TEMP 70 11 | 12 | #define SEC_OFF 0 13 | #define SEC_ARMED 1 14 | #define SEC_TRIGGERED 2 15 | 16 | 17 | //LED pins for temperature monitor 18 | const int tempLowPin = 14; 19 | const int tempMidPin = 13; 20 | const int tempHighPin = 12; 21 | 22 | //LED pin for door monitor 23 | const int doorPin = 10; 24 | 25 | //LED pin for the light monitor 26 | const int lightPin = 9; 27 | 28 | const int secOffPin = 6; 29 | const int secArmedPin = 5; 30 | const int secTriggeredPin = 4; 31 | 32 | 33 | void setup(){ 34 | //setup pins as outputs 35 | pinMode(tempHighPin, OUTPUT); 36 | pinMode(tempMidPin, OUTPUT); 37 | pinMode(tempLowPin, OUTPUT); 38 | pinMode(doorPin, OUTPUT); 39 | pinMode(lightPin, OUTPUT); 40 | pinMode(secOffPin, OUTPUT); 41 | pinMode(secArmedPin, OUTPUT); 42 | pinMode(secTriggeredPin, OUTPUT); 43 | 44 | //initially assume that the security system is disarmed 45 | digitalWrite(secOffPin, HIGH); 46 | 47 | 48 | //begin the serial lines 49 | Serial1.begin(115200); //com to ESP 50 | Serial.begin(115200); //com to computer 51 | 52 | delay(100); 53 | } 54 | 55 | void loop(){ 56 | 57 | //if we have data & the next byte isn't one of our header bytes, read until we get to a good header value 58 | //-we can assume that if its not a valid header byte that the data is garbage 59 | while(Serial1.available() && (Serial1.peek() != 'd' && Serial1.peek() != 't' && Serial1.peek() != 'l' && Serial1.peek() != 's')){ 60 | Serial1.read(); 61 | } 62 | 63 | //our "packets" are 2 bytes in size (1 header + 1 payload) so if we have 2 byte we have a potential valid packet 64 | if(Serial1.available() >= 2){ 65 | char headerByte = Serial1.read(); //read the header byte 66 | char payloadByte = Serial1.read(); //read the payload byte 67 | Serial.println(headerByte); 68 | 69 | //handle door state packet 70 | if(headerByte == 'd'){ 71 | if(payloadByte == 1){ 72 | digitalWrite(doorPin, HIGH); 73 | } 74 | else if(payloadByte == 0){ 75 | digitalWrite(doorPin, LOW); 76 | } 77 | } 78 | 79 | //handle temperature packet 80 | else if(headerByte == 't'){ 81 | 82 | //high temp - red light on 83 | if(payloadByte > HIGH_TEMP){ 84 | digitalWrite(tempHighPin, HIGH); 85 | digitalWrite(tempMidPin, LOW); 86 | digitalWrite(tempLowPin, LOW); 87 | } 88 | 89 | //mid temp - green light on 90 | else if(payloadByte >= MID_TEMP){ 91 | digitalWrite(tempHighPin, LOW); 92 | digitalWrite(tempMidPin, HIGH); 93 | digitalWrite(tempLowPin, LOW); 94 | } 95 | 96 | //low temp - blue light on 97 | else{ 98 | digitalWrite(tempHighPin, LOW); 99 | digitalWrite(tempMidPin, LOW); 100 | digitalWrite(tempLowPin, HIGH); 101 | } 102 | } 103 | 104 | //handle light state packet 105 | else if(headerByte == 'l'){ 106 | if(payloadByte == 1){ 107 | digitalWrite(lightPin, HIGH); 108 | } 109 | else if(payloadByte == 0){ 110 | digitalWrite(lightPin, LOW); 111 | } 112 | } 113 | 114 | //handle security system packet 115 | else if(headerByte == 's'){ 116 | //system has been disabled 117 | if(payloadByte == SEC_OFF){ 118 | digitalWrite(secOffPin, HIGH); 119 | digitalWrite(secArmedPin, LOW); 120 | digitalWrite(secTriggeredPin, LOW); 121 | } 122 | 123 | //system has been armed 124 | else if(payloadByte == SEC_ARMED){ 125 | digitalWrite(secOffPin, LOW); 126 | digitalWrite(secArmedPin, HIGH); 127 | digitalWrite(secTriggeredPin, LOW); 128 | } 129 | 130 | //system has been triggered 131 | else if(payloadByte == SEC_TRIGGERED){ 132 | digitalWrite(secOffPin, LOW); 133 | digitalWrite(secArmedPin, LOW); 134 | digitalWrite(secTriggeredPin, HIGH); 135 | } 136 | } 137 | 138 | 139 | 140 | 141 | } 142 | 143 | } -------------------------------------------------------------------------------- /Home Automation/Part 6/Breadboard Layouts/RGBlight.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 6/Breadboard Layouts/RGBlight.fzz -------------------------------------------------------------------------------- /Home Automation/Part 6/Breadboard Layouts/RGBlight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Home Automation/Part 6/Breadboard Layouts/RGBlight.png -------------------------------------------------------------------------------- /Home Automation/Part 6/wifiRGB/myTypes.h: -------------------------------------------------------------------------------- 1 | #ifndef myTypes_h 2 | #define myTypes_h 3 | 4 | typedef struct lightState{ 5 | double hue; //HSB values 6 | double saturation; 7 | double brightness; 8 | 9 | int red; //RGB values 10 | int green; 11 | int blue; 12 | 13 | int redRate; //fade Rates 14 | int greenRate; 15 | int blueRate; 16 | 17 | int fadePeriod; //total fade period 18 | 19 | int updateType; //type of update (RGB, HSB, etc.) 20 | }; 21 | 22 | typedef struct timer { 23 | unsigned long previousTime; 24 | int interval; 25 | }; 26 | 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /Home Automation/Part 6/wifiRGB/wifiRGB.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | //Requires HSBColor Library found here: https://github.com/julioterra/HSB_Color/blob/master/HSBColor.h 6 | // 7 | //ESP8266 Simple MQTT RGB light controller 8 | // 9 | //MQTT commands should look like this: 10 | // 11 | //HSB Update: hX.XXX,Y.YYY,Z.ZZZ 12 | //RGB Update: rRRR,GGG.BBB 13 | //Power (mode control) Update: p1 or p0 14 | 15 | 16 | 17 | #include 18 | #include 19 | #include 20 | #include "myTypes.h" 21 | 22 | //EDIT THESE LINES TO MATCH YOUR SETUP 23 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 24 | const char* ssid = "YOUR_SSID"; 25 | const char* password = "YOUR_PASSWORD"; 26 | 27 | 28 | 29 | const int redPin = 14; 30 | const int greenPin = 16; 31 | const int bluePin = 12; 32 | 33 | 34 | enum mainModes {SET, MOOD}; //SET for siri/network control - MOOD for auto color rotation 35 | enum moodColors{RED, GREEN, BLUE}; //colors to rotate through for mood light 36 | enum LEDmodes {NORMAL, FADING}; //fading modes either fading or none/normal 37 | enum updateTypes{HSB, RGB, POWER}; //different kinds of network commands 38 | 39 | lightState nextState; //the next state (usually updated from MQTT) 40 | 41 | int mainMode = SET; //overall mode of the light (moodlight, network controlled, etc) 42 | boolean newCommand = false; //informs the LED task of a new command waiting 43 | 44 | unsigned long currentMillis = 0; //current time in milliseconds for multitasking purposes 45 | 46 | char* lightTopic = "/house/RGBlight1"; //topic to subscribe to for the light 47 | 48 | int timeout = 0; //timeout timer to fail to standard moodlight when no known wifi is found within 10 seconds 49 | 50 | 51 | WiFiClient wifiClient; 52 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 53 | 54 | void setup() { 55 | //initialize the light as an output and set to LOW (off) 56 | pinMode(redPin, OUTPUT); 57 | pinMode(bluePin, OUTPUT); 58 | pinMode(greenPin, OUTPUT); 59 | digitalWrite(redPin, LOW); //all off 60 | digitalWrite(greenPin, LOW); 61 | digitalWrite(bluePin, LOW); 62 | 63 | delay(1000); 64 | 65 | colorTest(); 66 | 67 | 68 | 69 | Serial.begin(115200); 70 | 71 | 72 | //start wifi subsystem 73 | WiFi.begin(ssid, password); 74 | 75 | //attempt to connect to the WIFI network and then connect to the MQTT server 76 | reconnect(); 77 | 78 | //wait a bit before starting the main loop 79 | delay(2000); 80 | } 81 | 82 | 83 | 84 | void loop(){ 85 | 86 | //reconnect if connection is lost 87 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 88 | 89 | //increment wifi timeout whenever there is no wifi and after 10 seconds (2ms * 5000 loops) fail to moodlight 90 | if(WiFi.status() != WL_CONNECTED){timeout++;} 91 | if(timeout == 5000){ 92 | mainMode = MOOD; 93 | nextState.fadePeriod = 5000; 94 | newCommand = true; 95 | timeout = 0; 96 | } 97 | 98 | //maintain MQTT connection 99 | client.loop(); 100 | 101 | currentMillis = millis(); 102 | 103 | lightHandler(); 104 | 105 | //MUST delay to allow ESP8266 WIFI functions to run 106 | delay(2); 107 | } 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | void lightHandler(){ 118 | static lightState newState; //lightState to hold whatever new light state we may recieve (from MQTT or moodlight changer) 119 | static lightState currentState; //the current state of the LEDs 120 | static int currentMoodColor = 0; //if using the moodlight, this keeps track of which color we are current on (referenced from the moodColors enum at the top) 121 | 122 | static boolean isFading = false; //keeps track of whether the lights are currently fading to a new color or not 123 | 124 | 125 | if(mainMode == MOOD && !isFading){ //change the moodlight color if the mode is current set to MOOD and the lights are done fading from the last color 126 | 127 | if(currentMoodColor == RED){ //change the next state information to go from red to green 128 | nextState.red = 0; 129 | nextState.green = 1023; 130 | nextState.blue = 0; 131 | nextState.updateType = RGB; 132 | newCommand = true; 133 | currentMoodColor = GREEN; 134 | 135 | } 136 | else if(currentMoodColor == GREEN){ //change the next state information to go from green to blue 137 | nextState.red = 0; 138 | nextState.green = 0; 139 | nextState.blue = 1023; 140 | nextState.updateType = RGB; 141 | newCommand = true; 142 | currentMoodColor = BLUE; 143 | } 144 | else if(currentMoodColor == BLUE){ //change the next state information to go from blue to green 145 | nextState.red = 1023; 146 | nextState.green = 0; 147 | nextState.blue = 0; 148 | nextState.updateType = RGB; 149 | newCommand = true; 150 | currentMoodColor = RED; 151 | } 152 | } 153 | 154 | lightUpdater(&newState, currentState); //do new calculations for the updated light state (if there are any) 155 | 156 | isFading = lightChanger(newState, ¤tState); //change the lights 157 | 158 | } 159 | 160 | 161 | //Change the current light values and keep track of how much time has been spent fading 162 | boolean lightChanger(lightState newState, lightState *currentState){ 163 | static timer changeTimer; //timer for handling light changes 164 | changeTimer.interval = 2; //light changes should happen once every 2ms 165 | 166 | static int changeMode = NORMAL; //initialize changeMode to normal (not fading) 167 | static int currentPeriod = 0; //keep track of the total time the lights have been fading 168 | 169 | if(checkTimer(&changeTimer.previousTime, changeTimer.interval)){ //check to see whether it's time to do something 170 | 171 | if(newCommand){ //look for a new command and if so change the mode to FADING 172 | newCommand = false; 173 | changeMode = FADING; 174 | } 175 | 176 | 177 | if(changeMode == FADING){ //change the lights if we are in FADING mode 178 | 179 | //run when the current color states dont match the new color states or that the current fade period is not over 180 | if((newState.red != currentState->red || newState.blue != currentState->blue || newState.green != currentState->green) || (currentPeriod <= currentState->fadePeriod)){ 181 | 182 | if(currentPeriod % newState.redRate == 0){ //update red 183 | if(newState.red > currentState->red){currentState->red++;} //fade up 184 | else if (newState.red < currentState->red){currentState->red--;} //fade down 185 | } 186 | 187 | if(currentPeriod % newState.greenRate == 0){ //update green 188 | if(newState.green > currentState->green){currentState->green++;} //fade up 189 | else if (newState.green < currentState->green){currentState->green--;} //fade down 190 | } 191 | 192 | if(currentPeriod % newState.blueRate == 0){ //update blue 193 | if(newState.blue > currentState->blue){currentState->blue++;} //fade up 194 | else if (newState.blue < currentState->blue){currentState->blue--;} //fade down 195 | } 196 | 197 | //Write the new fade values to the lights 198 | analogWrite(redPin, currentState->red); 199 | analogWrite(greenPin, currentState->green); 200 | analogWrite(bluePin, currentState->blue); 201 | 202 | //increment the current period 203 | currentPeriod++; 204 | return true; //true on fading 205 | } 206 | else{ 207 | currentPeriod = 0; //reset the current period 208 | changeMode = NORMAL; //set mode back to normal 209 | return false; //fase on not fading 210 | } 211 | 212 | } 213 | 214 | 215 | else if (changeMode == NORMAL){ //if mode is normal already - return false, not fading 216 | return false; 217 | } 218 | 219 | 220 | } 221 | 222 | } 223 | 224 | //do new calculations for lights 225 | void lightUpdater (lightState *newState, lightState currentState){ 226 | 227 | if (newCommand){ //check for new LED command 228 | 229 | if(nextState.updateType == HSB){ //calculate for HSB command 230 | 231 | //convert HSB to RGB 232 | int newRGB[3]; 233 | H2R_HSBtoRGBfloat(nextState.hue, nextState.saturation, nextState.brightness, newRGB); 234 | newState->red = newRGB[0]; 235 | newState->green = newRGB[1]; 236 | newState->blue = newRGB[2]; 237 | 238 | //calculcate the difference in current LED brightnesses to the new brightnesses 239 | int redDiff = abs(newState->red - currentState.red); 240 | int greenDiff = abs(newState->green - currentState.green); 241 | int blueDiff = abs(newState->blue - currentState.blue); 242 | 243 | 244 | //calculate how long each light will take to fade to the new value 245 | if(redDiff > 0){newState->redRate = (nextState.fadePeriod / redDiff) + 1;} //dont allow dividing by 0 246 | else{newState->redRate = nextState.fadePeriod;} 247 | 248 | if(greenDiff > 0){newState->greenRate = (nextState.fadePeriod / greenDiff) + 1;} //dont allow dividing by 0 249 | else{newState->greenRate = nextState.fadePeriod;} 250 | 251 | if(blueDiff > 0){newState->blueRate = (nextState.fadePeriod / blueDiff) + 1;} //dont allow dividing by 0 252 | else{newState->blueRate = nextState.fadePeriod;} 253 | 254 | newState->fadePeriod = nextState.fadePeriod; //set the new fade period 255 | 256 | } 257 | 258 | else if(nextState.updateType == RGB){ //calculate for RGB command 259 | 260 | //grab the new RGB values 261 | newState->red = nextState.red; 262 | newState->green = nextState.green; 263 | newState->blue = nextState.blue; 264 | 265 | //calculcate the difference in current LED brightnesses to the new brightnesses 266 | int redDiff = abs(newState->red - currentState.red); 267 | int greenDiff = abs(newState->green - currentState.green); 268 | int blueDiff = abs(newState->blue - currentState.blue); 269 | 270 | //calculate how long each light will take to fade to the new value 271 | if(redDiff > 0){newState->redRate = (nextState.fadePeriod / redDiff) + 1;} //dont allow dividing by 0 272 | else{newState->redRate = nextState.fadePeriod;} 273 | 274 | if(greenDiff > 0){newState->greenRate = (nextState.fadePeriod / greenDiff) + 1;} //dont allow dividing by 0 275 | else{newState->greenRate = nextState.fadePeriod;} 276 | 277 | if(blueDiff > 0){newState->blueRate = (nextState.fadePeriod / blueDiff) + 1;} //dont allow dividing by 0 278 | else{newState->blueRate = nextState.fadePeriod;} 279 | 280 | newState->fadePeriod = nextState.fadePeriod; //set the new fade period 281 | 282 | } 283 | } 284 | 285 | } 286 | 287 | 288 | 289 | 290 | 291 | void colorTest(){ 292 | digitalWrite(redPin, HIGH); //red on 293 | delay(500); 294 | digitalWrite(redPin, LOW); //green on 295 | digitalWrite(greenPin, HIGH); 296 | delay(500); 297 | digitalWrite(greenPin, LOW); //blue on 298 | digitalWrite(bluePin, HIGH); 299 | delay(500); 300 | 301 | digitalWrite(redPin, HIGH); //all on 302 | digitalWrite(greenPin, HIGH); 303 | digitalWrite(bluePin, HIGH); 304 | delay(500); 305 | digitalWrite(redPin, LOW); //all off 306 | digitalWrite(greenPin, LOW); 307 | digitalWrite(bluePin, LOW); 308 | } 309 | 310 | 311 | char *ftoa(char *a, double f, int precision){ 312 | long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; 313 | 314 | char *ret = a; 315 | long heiltal = (long)f; 316 | itoa(heiltal, a, 10); 317 | while (*a != '\0') a++; 318 | *a++ = '.'; 319 | long desimal = abs((long)((f - heiltal) * p[precision])); 320 | itoa(desimal, a, 10); 321 | return ret; 322 | } 323 | 324 | 325 | 326 | 327 | 328 | 329 | //networking functions 330 | 331 | //MQTT callback 332 | void callback(char* topic, byte* payload, unsigned int length) { 333 | 334 | //create a new version of the payload that is null terminated so atoi and atof dont break 335 | char newPayload[50]; 336 | memcpy(newPayload, payload, length); 337 | newPayload[length] = '\0'; 338 | 339 | 340 | //new HSB command 341 | if(payload[0] == 'h'){ 342 | //grab the HSB values from the string 343 | nextState.hue = atof(&newPayload[1]); 344 | nextState.saturation = atof(&newPayload[7]); 345 | nextState.brightness = atof(&newPayload[13]); 346 | 347 | 348 | nextState.updateType = HSB; //set the fade type of HSB 349 | nextState.fadePeriod = 1050; //fade period of 1050 350 | newCommand = true; //tell the lighthandler that there is a new command waiting 351 | mainMode = SET; //make sure the mode is set to SET and not MOOD 352 | 353 | } 354 | 355 | //new RGB command 356 | else if (payload[0] == 'r'){ 357 | //grab the RGB values from the string 358 | int newRed = atoi(&newPayload[1]); 359 | int newGreen = atoi(&newPayload[5]); 360 | int newBlue = atoi(&newPayload[9]); 361 | 362 | nextState.red = newRed; 363 | nextState.green = newGreen; 364 | nextState.blue = newBlue; 365 | 366 | nextState.updateType = RGB; //set the fade type of RGB 367 | nextState.fadePeriod = 1050; //fade period of 1050 368 | newCommand = true; //tell the lighthandler that there is a new command waiting 369 | mainMode = SET; //make sure the mode is set to SET and not MOOD 370 | } 371 | 372 | //new "power" command - moodlight vs set changer. 373 | //Apple homekit doesnt have any other light setting so in this case the power switch in homekit changes the 374 | //light from normal to moodlight 375 | else if(payload[0] == 'p'){ 376 | 377 | if(payload[1] == '1'){ //power is set to MOOD 378 | mainMode = MOOD; 379 | nextState.fadePeriod = 5000; 380 | newCommand = true; 381 | } 382 | else if(payload[1] == '0'){ //power is set to SET 383 | mainMode = SET; 384 | nextState.fadePeriod = 1050; 385 | newCommand = true; 386 | } 387 | } 388 | 389 | } 390 | 391 | void reconnect() { 392 | Serial.println("Attempting Reconnect"); 393 | 394 | //attempt to connect to the wifi if connection is lost 395 | if(WiFi.status() != WL_CONNECTED){ 396 | 397 | while (WiFi.status() != WL_CONNECTED) { 398 | delay(500); 399 | Serial.print("."); 400 | } 401 | } 402 | 403 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 404 | if(WiFi.status() == WL_CONNECTED){ 405 | Serial.println("---WIFI Connected!---"); 406 | 407 | while (!client.connected()) { 408 | Serial.print("Attemping MQTT connection"); 409 | 410 | // Generate client name based on MAC address and last 8 bits of microsecond counter 411 | String clientName; 412 | clientName += "esp8266-"; 413 | uint8_t mac[6]; 414 | WiFi.macAddress(mac); 415 | clientName += macToStr(mac); 416 | 417 | //if connected, subscribe to the topic(s) we want to be notified about 418 | if (client.connect((char*) clientName.c_str())) { 419 | Serial.println(" -- Connected"); 420 | client.subscribe(lightTopic); 421 | } 422 | else{Serial.println(" -- Failed");} 423 | 424 | //otherwise print failed for debugging 425 | } 426 | } 427 | } 428 | 429 | 430 | 431 | 432 | //generate unique name from MAC addr 433 | String macToStr(const uint8_t* mac){ 434 | 435 | String result; 436 | 437 | for (int i = 0; i < 6; ++i) { 438 | result += String(mac[i], 16); 439 | 440 | if (i < 5){ 441 | result += ':'; 442 | } 443 | } 444 | 445 | return result; 446 | } 447 | 448 | //this functions simplifies checking whether a task needs to run by checking our timing variables 449 | //and returning true or false depending on whether we need to run or not 450 | boolean checkTimer(unsigned long *previousTime, unsigned long interval){ 451 | if(currentMillis - *previousTime >= interval){ 452 | *previousTime = currentMillis; 453 | return true; 454 | } 455 | return false; 456 | } 457 | 458 | 459 | 460 | 461 | 462 | 463 | -------------------------------------------------------------------------------- /Home Automation/Part 7/Install HAP-NodeJS.txt: -------------------------------------------------------------------------------- 1 | curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - 2 | 3 | sudo apt-get install git nodejs libavahi-compat-libdnssd-dev node-gyp 4 | 5 | git clone https://github.com/KhaosT/HAP-NodeJS.git 6 | 7 | cd HAP-NodeJS 8 | 9 | sudo npm install 10 | 11 | sudo npm install mqtt 12 | 13 | -------------------------------------------------------------------------------- /Home Automation/Part 7/RGBLight_accessory.js: -------------------------------------------------------------------------------- 1 | var Accessory = require('../').Accessory; 2 | var Service = require('../').Service; 3 | var Characteristic = require('../').Characteristic; 4 | var uuid = require('../').uuid; 5 | var lightState = 0; 6 | 7 | 8 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 9 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 10 | var name = "RGB Light"; //Name to Show to IOS 11 | var UUID = "hap-nodejs:accessories:RGBLight"; //Change the RGBLight to something unique for each light - this should be unique for each node on your system 12 | var USERNAME = "AC:AF:AC:2C:5D:FB"; //This must also be unique for each node - make sure you change it! 13 | 14 | var MQTT_IP = 'YOUR.MQTT.IP.HERE' 15 | var lightTopic = '/YOUR/LIGHT/TOPIC/HERE' 16 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 17 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 18 | 19 | 20 | // MQTT Setup 21 | var mqtt = require('mqtt'); 22 | var options = { 23 | port: 1883, 24 | host: MQTT_IP, 25 | clientId: 'FGAK35243' 26 | }; 27 | var client = mqtt.connect(options); 28 | client.on('message', function(topic, message) { 29 | 30 | }); 31 | 32 | //setup HK light object 33 | var lightUUID = uuid.generate(UUID); 34 | var light = exports.accessory = new Accessory(name, lightUUID); 35 | 36 | // Add properties for publishing (in case we're using Core.js and not BridgedCore.js) 37 | light.username = USERNAME; 38 | light.pincode = "031-45-154"; 39 | 40 | //add a light service and setup the On Characteristic 41 | light 42 | .addService(Service.Lightbulb) 43 | .getCharacteristic(Characteristic.On) 44 | .on('get', function(callback) { 45 | callback(null, lightAction.getState()); 46 | }); 47 | 48 | light 49 | .getService(Service.Lightbulb) 50 | .getCharacteristic(Characteristic.On) 51 | .on('set', function(value, callback) { 52 | lightAction.setState(value); 53 | callback(); 54 | }); 55 | 56 | //Add and setup Brightness 57 | light 58 | .getService(Service.Lightbulb) 59 | .addCharacteristic(Characteristic.Brightness) 60 | .on('set', function(value, callback){ 61 | lightAction.setBrightness(value); 62 | callback() 63 | }); 64 | 65 | light 66 | .getService(Service.Lightbulb) 67 | .getCharacteristic(Characteristic.Brightness) 68 | .on('get', function(callback){ 69 | callback(null, lightAction.getBrightness()) 70 | }); 71 | 72 | //Add and setup Saturation 73 | light 74 | .getService(Service.Lightbulb) 75 | .addCharacteristic(Characteristic.Saturation) 76 | .on('set', function(value, callback){ 77 | lightAction.setSaturation(value); 78 | callback() 79 | }); 80 | 81 | light 82 | .getService(Service.Lightbulb) 83 | .getCharacteristic(Characteristic.Saturation) 84 | .on('get', function(callback){ 85 | callback(null, lightAction.getSaturation()) 86 | }); 87 | 88 | //Add and setup Hue 89 | light 90 | .getService(Service.Lightbulb) 91 | .addCharacteristic(Characteristic.Hue) 92 | .on('set', function(value, callback){ 93 | lightAction.setHue(value); 94 | callback() 95 | }); 96 | 97 | light 98 | .getService(Service.Lightbulb) 99 | .getCharacteristic(Characteristic.Hue) 100 | .on('get', function(callback){ 101 | callback(null, lightAction.getHue()) 102 | }); 103 | 104 | 105 | 106 | // here's a fake temperature sensor device that we'll expose to HomeKit 107 | var lightAction = { 108 | 109 | //initialize the various state variables 110 | currentState: 0, 111 | currentBrightness: 0, 112 | currentHue: 0, 113 | currentSaturation: 0, 114 | 115 | lastBrightness: 0, 116 | lastHue: 0, 117 | lastSaturation: 0, 118 | 119 | 120 | //On Characteristic set/get 121 | getState: function() { return this.currentState;}, 122 | setState: function(newState){ 123 | 124 | if((newState == true && this.currentState == 0) || (newState == false && this.currentState == 1) ){ 125 | console.log("Setting new outlet state: " + newState.toString()); 126 | if(newState == true){ 127 | client.publish(lightTopic, 'p1'); 128 | this.currentState = 1; 129 | } 130 | else{ 131 | client.publish(lightTopic, 'p0'); 132 | this.currentState = 0; 133 | } 134 | } 135 | 136 | }, 137 | 138 | //Brightness Characteristic set/get 139 | getBrightness: function(){return this.currentBrightness;}, 140 | setBrightness: function(newBrightness){ 141 | this.currentBrightness = newBrightness; 142 | this.updateLight(); 143 | }, 144 | 145 | 146 | //Saturation Characteristic set/get 147 | getSaturation: function(){return this.currentSaturation;}, 148 | setSaturation: function(newSaturation){ 149 | this.currentSaturation = newSaturation; 150 | this.updateLight(); 151 | }, 152 | 153 | 154 | //Hue Characteristic set/get 155 | getHue: function(){return this.currentHue;}, 156 | setHue: function(newHue){ 157 | this.currentHue = newHue; 158 | this.updateLight(); 159 | }, 160 | 161 | 162 | //other light setting functions 163 | updateState: function() { 164 | this.currentState = lightState; 165 | }, 166 | 167 | updateLight: function(){ 168 | if(this.lastSaturation != this.currentSaturation || this.lastHue != this.currentHue || this.lastBrightness != this.currentBrightness){ 169 | pubBrightness = this.currentBrightness / 100; 170 | pubHue = this.currentHue / 360; 171 | pubSaturation = this.currentSaturation / 100; 172 | toPublish = 'h' + pubHue.toFixed(3).toString() + ',' + pubSaturation.toFixed(3).toString() + ',' + pubBrightness.toFixed(3).toString() 173 | client.publish(lightTopic, toPublish); 174 | 175 | this.lastBrightness = this.currentBrightness; 176 | this.lastHue = this.currentHue; 177 | this.lastSaturation = this.currentSaturation; 178 | } 179 | } 180 | 181 | } 182 | 183 | 184 | 185 | // update the characteristic values so interested iOS devices can get notified 186 | setInterval(function() { 187 | light 188 | .getService(Service.Lightbulb) 189 | .setCharacteristic(Characteristic.On, lightAction.currentState); 190 | light 191 | .getService(Service.Lightbulb) 192 | .setCharacteristic(Characteristic.Brightness, lightAction.getBrightness()); 193 | light 194 | .getService(Service.Lightbulb) 195 | .setCharacteristic(Characteristic.Hue, lightAction.getHue()); 196 | light 197 | .getService(Service.Lightbulb) 198 | .setCharacteristic(Characteristic.Saturation, lightAction.getSaturation()); 199 | 200 | }, 2000); 201 | -------------------------------------------------------------------------------- /Home Automation/Part 8/relayLight_accessory.js: -------------------------------------------------------------------------------- 1 | var Accessory = require('../').Accessory; 2 | var Service = require('../').Service; 3 | var Characteristic = require('../').Characteristic; 4 | var uuid = require('../').uuid; 5 | 6 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 7 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 8 | var name = "Relay Light"; 9 | var UUID = "hap-nodejs:accessories:Relay1"; 10 | var USERNAME = "A2:AF:1A:1C:AD:CB"; 11 | 12 | var MQTT_IP = 'YOUR.MQTT.IP.ADDRESS' 13 | var lightTopic = '/YOUR/LIGHT/TOPIC' 14 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 15 | ////////////////CHANGE THESE SETTINGS TO MATCH YOUR SETUP BEFORE RUNNING!!!!!!!!!!!!!////////////////////////// 16 | 17 | // MQTT Setup 18 | var mqtt = require('mqtt'); 19 | var options = { 20 | port: 1883, 21 | host: MQTT_IP, 22 | clientId: 'cdfadfrAK343' 23 | }; 24 | var client = mqtt.connect(options); 25 | client.on('message', function(topic, message) { 26 | 27 | }); 28 | 29 | //setup HK light object 30 | var lightUUID = uuid.generate(UUID); 31 | var light = exports.accessory = new Accessory(name, lightUUID); 32 | 33 | // Add properties for publishing (in case we're using Core.js and not BridgedCore.js) 34 | light.username = USERNAME; 35 | light.pincode = "031-45-154"; 36 | 37 | //add a light service and setup the On Characteristic 38 | light 39 | .addService(Service.Lightbulb) 40 | .getCharacteristic(Characteristic.On) 41 | .on('get', function(callback) { 42 | callback(null, lightAction.getState()); 43 | }); 44 | 45 | light 46 | .getService(Service.Lightbulb) 47 | .getCharacteristic(Characteristic.On) 48 | .on('set', function(value, callback) { 49 | lightAction.setState(value); 50 | callback(); 51 | }); 52 | 53 | 54 | 55 | var lightAction = { 56 | 57 | //initialize the various state variables 58 | currentState: 0, 59 | 60 | //On Characteristic set/get 61 | getState: function() { return this.currentState;}, 62 | setState: function(newState){ 63 | 64 | if(newState != this.currentState ){ 65 | console.log("Setting new outlet state: " + newState.toString()); 66 | if(newState == true){ 67 | client.publish(lightTopic, '1'); 68 | this.currentState = 1; 69 | } 70 | else{ 71 | client.publish(lightTopic, '0'); 72 | this.currentState = 0; 73 | } 74 | } 75 | 76 | } 77 | } 78 | 79 | // update the characteristic values so interested iOS devices can get notified 80 | setInterval(function() { 81 | light 82 | .getService(Service.Lightbulb) 83 | .setCharacteristic(Characteristic.On, lightAction.currentState); 84 | 85 | }, 2000); 86 | -------------------------------------------------------------------------------- /Home Automation/Sketches/RGBLight/RGBLight.ino: -------------------------------------------------------------------------------- 1 | /* 2 | RGBLight.ino 3 | Copyright (c) 2016 ItKindaWorks All right reserved. 4 | github.com/ItKindaWorks 5 | 6 | This file is part of RGBLight 7 | 8 | RGBLight is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | RGBLight is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with RGBLight. If not, see . 20 | */ 21 | 22 | /* 23 | This is an MQTT RGB light controller program for the ESP8266. 24 | The light can be controlled in one of three ways. You can send 25 | an HSB update, RGB update, or moodlight mode on/off. 26 | All updates must be formatted correctly, see below: 27 | 28 | ex RGB string: "r255,050,000" (r = 255, g = 050, b = 000) 29 | ex HSB string: "h1.00,0.50,0.01" (h = 1.00, s = 0.50, b = 0.01) 30 | ex moodlight string: "m1" (moodlight activate) 31 | 32 | This program also posts a status update to the status topic 33 | which is the lightTopic plus "/status" (ex. if the lightTopic 34 | is "/home/RGBlight" then the statusTopic would be "home/RGBlight/status") 35 | 36 | Change the Topic/Hostname/OTA Password and network settings to match your system. 37 | 38 | */ 39 | 40 | #include "ESPHelper.h" 41 | #include 42 | #include "Metro.h" 43 | 44 | #define TOPIC "/your/mqtt/topic" 45 | #define STATUS TOPIC "/status" 46 | #define NETWORK_HOSTNAME "YOUR OTA HOSTNAME" 47 | #define OTA_PASSWORD "YOUR OTA PASSWORD" 48 | 49 | #define RED_PIN 12 50 | #define GREEN_PIN 13 51 | #define BLUE_PIN 14 52 | 53 | typedef struct lightState{ 54 | double hue; 55 | double saturation; 56 | double brightness; 57 | int red; 58 | int redRate; 59 | int green; 60 | int greenRate; 61 | int blue; 62 | int blueRate; 63 | int fadePeriod; 64 | int updateType; 65 | }; 66 | 67 | typedef struct timer { 68 | unsigned long previousTime; 69 | int interval; 70 | }; 71 | 72 | 73 | 74 | enum superModes {SET, MOOD}; 75 | enum moodColors{RED, GREEN, BLUE}; 76 | enum modes {NORMAL, FADING}; 77 | enum updateTypes{HSB, RGB, POWER}; 78 | 79 | 80 | lightState nextState; 81 | 82 | int superMode = SET; //overall mode of the light (moodlight, network controlled, etc) 83 | boolean newCommand = false; 84 | 85 | 86 | char* lightTopic = TOPIC; 87 | char* statusTopic = STATUS; 88 | char* hostnameStr = NETWORK_HOSTNAME; 89 | 90 | const int redPin = RED_PIN; 91 | const int greenPin = GREEN_PIN; 92 | const int bluePin = BLUE_PIN; 93 | 94 | char statusString[50]; //string containing the current setting for the light 95 | 96 | 97 | //set this info for your own network 98 | netInfo homeNet = {.name = "NETWORK NICKNAME", .mqtt = "YOUR MQTT-IP", .ssid = "YOUR SSID", .pass = "YOUR NETWORK PASS"}; 99 | 100 | ESPHelper myESP(&homeNet); 101 | 102 | 103 | void setup() { 104 | //initialize the light as an output and set to LOW (off) 105 | pinMode(redPin, OUTPUT); 106 | pinMode(bluePin, OUTPUT); 107 | pinMode(greenPin, OUTPUT); 108 | 109 | //all off 110 | digitalWrite(redPin, LOW); //all off 111 | digitalWrite(greenPin, LOW); 112 | digitalWrite(bluePin, LOW); 113 | 114 | delay(1000); 115 | 116 | colorTest(); 117 | 118 | //setup ota on esphelper 119 | myESP.OTA_enable(); 120 | myESP.OTA_setPassword(OTA_PASSWORD); 121 | myESP.OTA_setHostnameWithVersion(hostnameStr); 122 | 123 | //subscribe to the lighttopic 124 | myESP.addSubscription(lightTopic); 125 | myESP.begin(); 126 | myESP.setCallback(callback); 127 | } 128 | 129 | 130 | 131 | void loop(){ 132 | static bool connected = false; //keeps track of connection state to reset from MOOD to SET when network connection is made 133 | 134 | 135 | if(myESP.loop() == FULL_CONNECTION){ 136 | 137 | //if the light was previously not connected to wifi and mqtt, update the status topic with the light being off 138 | if(!connected){ 139 | connected = true; //we have reconnected so now we dont need to flag the setting anymore 140 | myESP.publish(statusTopic, "h0.00,0.00,0.00 ", true); 141 | } 142 | 143 | lightHandler(); 144 | } 145 | 146 | 147 | yield(); 148 | } 149 | 150 | 151 | void lightHandler(){ 152 | //new and current lightStates 153 | static lightState newState; 154 | static lightState currentState; 155 | 156 | static int currentMoodColor = 0; //the current moodlight chosen color 157 | 158 | static int isFading = 0; 159 | 160 | 161 | //if the super mode is mood light and the light isnt currently fading, 162 | //then change to a new color and start a new fade 163 | if(superMode == MOOD && isFading == 0){ 164 | if(currentMoodColor == RED){ 165 | nextState.red = 0; 166 | nextState.green = 1023; 167 | nextState.blue = 0; 168 | nextState.updateType = RGB; 169 | newCommand = true; 170 | currentMoodColor = GREEN; 171 | 172 | } 173 | else if(currentMoodColor == GREEN){ 174 | nextState.red = 0; 175 | nextState.green = 0; 176 | nextState.blue = 1023; 177 | nextState.updateType = RGB; 178 | newCommand = true; 179 | currentMoodColor = BLUE; 180 | } 181 | else if(currentMoodColor == BLUE){ 182 | nextState.red = 1023; 183 | nextState.green = 0; 184 | nextState.blue = 0; 185 | nextState.updateType = RGB; 186 | newCommand = true; 187 | currentMoodColor = RED; 188 | } 189 | } 190 | 191 | lightUpdater(&newState, currentState); 192 | isFading = lightChanger(newState, ¤tState); 193 | 194 | } 195 | 196 | 197 | //this function actually changes the light values and does the fading 198 | //returns 1 if fading 199 | //returns 0 if not fading 200 | //returns -1 if the timer doesnt get triggered 201 | int lightChanger(lightState newState, lightState *currentState){ 202 | static Metro changeTimer = Metro(1); 203 | 204 | static int changeMode = NORMAL; //the current mode (fading or normal) 205 | static int currentPeriod = 0; //time since starting the fade 206 | 207 | 208 | //only allow fade updates every 1ms 209 | if(changeTimer.check()){ 210 | 211 | //check to see if this is there is a new command and set the mode to FADING 212 | if(newCommand){ 213 | newCommand = false; 214 | changeMode = FADING; 215 | } 216 | 217 | 218 | 219 | if(changeMode == FADING){ 220 | 221 | //check whether or not a fade is needed - if so update the channel velues 222 | if((newState.red != currentState->red || newState.blue != currentState->blue || newState.green != currentState->green) || (currentPeriod <= currentState->fadePeriod)){ 223 | 224 | if(currentPeriod % newState.redRate == 0){ 225 | if(newState.red > currentState->red){currentState->red++;} 226 | else if (newState.red < currentState->red){currentState->red--;} 227 | } 228 | 229 | if(currentPeriod % newState.greenRate == 0){ 230 | if(newState.green > currentState->green){currentState->green++;} 231 | else if (newState.green < currentState->green){currentState->green--;} 232 | } 233 | 234 | if(currentPeriod % newState.blueRate == 0){ 235 | if(newState.blue > currentState->blue){currentState->blue++;} 236 | else if (newState.blue < currentState->blue){currentState->blue--;} 237 | } 238 | 239 | //write to the analog pins 240 | analogWrite(redPin, currentState->red); 241 | analogWrite(greenPin, currentState->green); 242 | analogWrite(bluePin, currentState->blue); 243 | 244 | //increment the period 245 | currentPeriod++; 246 | return 1; //return 1 on mode being FADING 247 | } 248 | 249 | //if no fade is needed then reset the period and set the mode to NORMAL 250 | else{ 251 | currentPeriod = 0; 252 | changeMode = NORMAL; 253 | return 0; //return 0 on mode being NORMAL 254 | } 255 | 256 | } 257 | 258 | 259 | else if (changeMode == NORMAL){ 260 | return 0; //return 0 on mode being NORMAL 261 | } 262 | 263 | } 264 | 265 | return -1; //return -1 on timer not set off 266 | 267 | } 268 | 269 | //calculates new information (color values, fade times, etc) for 270 | //new color updates 271 | void lightUpdater (lightState *newState, lightState currentState){ 272 | 273 | //calculate new vars only if there is a new command 274 | if (newCommand){ 275 | 276 | //determine which kind of update this is 277 | if(nextState.updateType == HSB){ 278 | 279 | //convert from HSB to RGB 280 | int newRGB[3]; 281 | H2R_HSBtoRGBfloat(nextState.hue, nextState.saturation, nextState.brightness, newRGB); 282 | newState->red = newRGB[0]; 283 | newState->green = newRGB[1]; 284 | newState->blue = newRGB[2]; 285 | 286 | //determine the RGB difference from the current values to new values (how far each channel needs to fade) 287 | int redDiff = abs(newState->red - currentState.red); 288 | int greenDiff = abs(newState->green - currentState.green); 289 | int blueDiff = abs(newState->blue - currentState.blue); 290 | 291 | //calculate the new fade times for each channel (how long to wait between fading up/down) 292 | if(redDiff > 0){newState->redRate = (nextState.fadePeriod / redDiff);} 293 | else{newState->redRate = nextState.fadePeriod;} 294 | 295 | if(greenDiff > 0){newState->greenRate = (nextState.fadePeriod / greenDiff);} 296 | else{newState->greenRate = nextState.fadePeriod;} 297 | 298 | if(blueDiff > 0){newState->blueRate = (nextState.fadePeriod / blueDiff);} 299 | else{newState->blueRate = nextState.fadePeriod;} 300 | 301 | //set the total time to fade 302 | newState->fadePeriod = nextState.fadePeriod; 303 | 304 | } 305 | else if(nextState.updateType == RGB){ 306 | 307 | //set new RGB values from update 308 | newState->red = nextState.red; 309 | newState->green = nextState.green; 310 | newState->blue = nextState.blue; 311 | 312 | //determine the RGB difference from the current values to new values (how far each channel needs to fade) 313 | int redDiff = abs(newState->red - currentState.red); 314 | int greenDiff = abs(newState->green - currentState.green); 315 | int blueDiff = abs(newState->blue - currentState.blue); 316 | 317 | //calculate the new fade times for each channel (how long to wait between fading up/down) 318 | if(redDiff > 0){newState->redRate = (nextState.fadePeriod / redDiff) + 1;} 319 | else{newState->redRate = nextState.fadePeriod;} 320 | 321 | if(greenDiff > 0){newState->greenRate = (nextState.fadePeriod / greenDiff) + 1;} 322 | else{newState->greenRate = nextState.fadePeriod;} 323 | 324 | if(blueDiff > 0){newState->blueRate = (nextState.fadePeriod / blueDiff) + 1;} 325 | else{newState->blueRate = nextState.fadePeriod;} 326 | 327 | //set the total time to fade 328 | newState->fadePeriod = nextState.fadePeriod; 329 | 330 | } 331 | } 332 | 333 | } 334 | 335 | 336 | 337 | //MQTT callback 338 | void callback(char* topic, byte* payload, unsigned int length) { 339 | 340 | //convert topic to string to make it easier to work with 341 | String topicStr = topic; 342 | 343 | char newPayload[40]; 344 | memcpy(newPayload, payload, length); 345 | newPayload[length] = '\0'; 346 | 347 | //handle HSB updates 348 | if(payload[0] == 'h'){ 349 | nextState.hue = atof(&newPayload[1]); 350 | nextState.saturation = atof(&newPayload[7]); 351 | nextState.brightness = atof(&newPayload[13]); 352 | 353 | nextState.updateType = HSB; 354 | nextState.fadePeriod = 2100; 355 | newCommand = true; 356 | superMode = SET; 357 | 358 | } 359 | 360 | //handle RGB updates 361 | else if (payload[0] == 'r'){ 362 | int newRed = atoi(&newPayload[1]); 363 | int newGreen = atoi(&newPayload[5]); 364 | int newBlue = atoi(&newPayload[9]); 365 | 366 | nextState.red = newRed; 367 | nextState.green = newGreen; 368 | nextState.blue = newBlue; 369 | 370 | nextState.updateType = RGB; 371 | newCommand = true; 372 | nextState.fadePeriod = 2100; 373 | superMode = SET; 374 | } 375 | 376 | //handle moodlight updates 377 | else if(payload[0] == 'm'){ 378 | 379 | if(payload[1] == '1'){ 380 | superMode = MOOD; 381 | nextState.fadePeriod = 10000; 382 | newCommand = true; 383 | } 384 | else if(payload[1] == '0'){ 385 | superMode = SET; 386 | nextState.fadePeriod = 2100; 387 | newCommand = true; 388 | } 389 | } 390 | 391 | 392 | //package up status message reply and send it back out to the status topic 393 | strcpy(statusString, newPayload); 394 | myESP.publish(statusTopic, statusString, true); 395 | } 396 | 397 | 398 | 399 | 400 | void colorTest(){ 401 | digitalWrite(redPin, HIGH); //red on 402 | delay(500); 403 | digitalWrite(redPin, LOW); //green on 404 | digitalWrite(greenPin, HIGH); 405 | delay(500); 406 | digitalWrite(greenPin, LOW); //blue on 407 | digitalWrite(bluePin, HIGH); 408 | delay(500); 409 | 410 | digitalWrite(redPin, HIGH); //all on 411 | digitalWrite(greenPin, HIGH); 412 | digitalWrite(bluePin, HIGH); 413 | delay(500); 414 | digitalWrite(redPin, LOW); //all off 415 | digitalWrite(greenPin, LOW); 416 | digitalWrite(bluePin, LOW); 417 | } 418 | 419 | 420 | char *ftoa(char *a, double f, int precision) 421 | { 422 | long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; 423 | 424 | char *ret = a; 425 | long heiltal = (long)f; 426 | itoa(heiltal, a, 10); 427 | while (*a != '\0') a++; 428 | *a++ = '.'; 429 | long desimal = abs((long)((f - heiltal) * p[precision])); 430 | itoa(desimal, a, 10); 431 | return ret; 432 | } 433 | 434 | 435 | 436 | 437 | float map_double(double x, double in_min, double in_max, double out_min, double out_max) 438 | { 439 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 440 | } 441 | 442 | 443 | -------------------------------------------------------------------------------- /Home Automation/Sketches/RelayControl/RelayControl.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 ItKindaWorks All right reserved. 3 | github.com/ItKindaWorks 4 | 5 | This file is part of RelayControl 6 | 7 | RelayControl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | RelayControl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with RelayControl. If not, see . 19 | */ 20 | 21 | /* 22 | This is a simple MQTT relay/light controller program for the ESP8266. 23 | By sending a '1' or '0' to the relayTopic the relayPin can be toggled 24 | on or off. This program also posts a status update to the status topic 25 | which is the relayTopic plus "/status" (ex. if the relayTopic 26 | is "/home/light" then the statusTopic would be "home/light/status") 27 | */ 28 | 29 | #include "ESPHelper.h" 30 | 31 | #define TOPIC "/your/mqtt/topic" 32 | #define STATUS TOPIC "/status" //dont change this - this is for the status topic which is whatever your mqtt topic is plus /status (ex /home/light/status) 33 | 34 | #define NETWORK_HOSTNAME "YOUR OTA HOST NAME" 35 | #define OTA_PASSWORD "YOUR OTA PASSWORD" 36 | 37 | #define RELAY_PIN 3 //rx pin on esp 38 | #define BLINK_PIN 1 //tx/led on esp-01 39 | 40 | 41 | char* relayTopic = TOPIC; 42 | char* statusTopic = STATUS; 43 | char* hostnameStr = NETWORK_HOSTNAME; 44 | 45 | const int relayPin = RELAY_PIN; 46 | const int blinkPin = BLINK_PIN; //tx pin on esp 47 | 48 | //set this info for your own network 49 | netInfo homeNet = {.name = "NETWORK NICKNAME", .mqtt = "YOUR MQTT-IP", .ssid = "YOUR SSID", .pass = "YOUR NETWORK PASS"}; 50 | 51 | ESPHelper myESP(&homeNet); 52 | 53 | void setup() { 54 | //setup ota 55 | myESP.OTA_enable(); 56 | myESP.OTA_setPassword(OTA_PASSWORD); 57 | myESP.OTA_setHostnameWithVersion(hostnameStr); 58 | 59 | 60 | //setup the rest of ESPHelper 61 | myESP.enableHeartbeat(blinkPin); //comment out to disable the heartbeat 62 | myESP.addSubscription(relayTopic); //add the relay topic to the subscription list 63 | myESP.begin(); 64 | myESP.setCallback(callback); 65 | 66 | 67 | pinMode(relayPin, OUTPUT); 68 | delay(100); 69 | } 70 | 71 | 72 | void loop(){ 73 | //loop ESPHelper and wait for commands from mqtt 74 | myESP.loop(); 75 | yield(); 76 | } 77 | 78 | 79 | //mqtt callback 80 | void callback(char* topic, byte* payload, unsigned int length) { 81 | String topicStr = topic; 82 | 83 | //if the payload from mqtt was 1, turn the relay on and update the status topic with 1 84 | if(payload[0] == '1'){ 85 | digitalWrite(relayPin, HIGH); 86 | myESP.publish(statusTopic, "1",true); 87 | } 88 | 89 | //else turn the relay off and update the status topic with 0 90 | else if (payload[0] == '0'){ 91 | digitalWrite(relayPin, LOW); 92 | myESP.client.publish(statusTopic, "0", true); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266 -------------------------------------------------------------------------------- /Relay Control/Breadboard.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Relay Control/Breadboard.fzz -------------------------------------------------------------------------------- /Relay Control/Breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ItKindaWorks/ESP8266/8dd89db57ea1adc29a498238c77b5d35c65b1b5d/Relay Control/Breadboard.jpg -------------------------------------------------------------------------------- /Relay Control/relayControl/relayControl.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //ESP8266 aRest UI Relay tutorial 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | // Create aREST instance 12 | aREST_UI myRest = aREST_UI(); 13 | 14 | // WiFi parameters 15 | const char* ssid = "YOUR_SSID_HERE"; 16 | const char* password = "YOUR_PASSWORD_HERE"; 17 | 18 | // The port to listen for incoming TCP connections 19 | #define LISTEN_PORT 80 20 | 21 | // Create an instance of the server 22 | WiFiServer server(LISTEN_PORT); 23 | 24 | 25 | void setup(void) 26 | { 27 | // Start Serial for debugging 28 | Serial.begin(115200); 29 | 30 | // Create a title for our webpage 31 | myRest.title("Relay Control"); 32 | 33 | // Create button to control pin 2 34 | myRest.button(2); 35 | 36 | // Give name and ID to device 37 | myRest.set_id("1"); 38 | myRest.set_name("esp8266"); 39 | 40 | // Connect to the network and start the server 41 | connectWifi(); 42 | } 43 | 44 | void loop() { 45 | restLoop(); //automatically handle the aRest functionality 46 | } 47 | 48 | 49 | boolean restLoop(){ 50 | WiFiClient client = server.available(); 51 | 52 | if (!client) { //check to see if the client is connected or not and return if not connected 53 | return false; 54 | } 55 | 56 | while(!client.available()){ //wait for input from the client - note that this is a blocking operation 57 | delay(1); 58 | } 59 | 60 | myRest.handle(client); //handle any requests from the client 61 | 62 | return true; //and return 63 | } 64 | 65 | void connectWifi(){ 66 | Serial.print("Connecting to "); 67 | Serial.println(ssid); 68 | 69 | //Start the wifi subsystem 70 | WiFi.begin(ssid, password); 71 | 72 | //wait for connection 73 | while (WiFi.status() != WL_CONNECTED) { 74 | delay(500); 75 | Serial.print("."); 76 | } 77 | 78 | //print connection IP upon success 79 | Serial.println(""); 80 | Serial.println("WiFi connected"); 81 | Serial.println("IP address: "); 82 | Serial.println(WiFi.localIP()); 83 | 84 | // Start the server 85 | server.begin(); 86 | Serial.println("Server started"); 87 | } 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /Serial Breakout Test/espNode/espNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 Simple Serial breakout test via MQTT - ESP side 7 | // 8 | //This code demonstrates using an ESP8266 serial break board for bi-directional communication. 9 | //It connects to a network and listens subscribes to an MQTT topic. When the ESP recieves a '1' it sends that to the 10 | //teensy and the teensy turns a light on and pings back on the serial line. When the ESP gets the ping back it publishes 11 | //a confirmation to the MQTT broker on a different topic 12 | 13 | 14 | #include 15 | #include 16 | 17 | 18 | //EDIT THESE LINES TO MATCH YOUR SETUP 19 | #define MQTT_SERVER "YOUR.MQTT.SERVER.IP" 20 | const char* ssid = "YOUR_SSID"; 21 | const char* password = "YOUR_PASSWORD"; 22 | 23 | //topic to subscribe to for the light 24 | char* lightTopic = "/test/esp1"; 25 | 26 | //confirmation topic 27 | char* lightConfirm = "/test/esp1Confirm"; 28 | 29 | 30 | WiFiClient wifiClient; 31 | PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient); 32 | 33 | void setup() { 34 | 35 | //start the serial line for debugging 36 | Serial.begin(115200); 37 | delay(100); 38 | 39 | 40 | //start wifi subsystem 41 | WiFi.begin(ssid, password); 42 | 43 | //attempt to connect to the WIFI network and then connect to the MQTT server 44 | reconnect(); 45 | 46 | //wait a bit before starting the main loop 47 | delay(2000); 48 | } 49 | 50 | 51 | 52 | void loop(){ 53 | 54 | //reconnect if connection is lost 55 | if (!client.connected() && WiFi.status() == 3) {reconnect();} 56 | 57 | //maintain MQTT connection 58 | client.loop(); 59 | 60 | //MUST delay to allow ESP8266 WIFI functions to run 61 | delay(10); 62 | } 63 | 64 | 65 | //MQTT callback 66 | void callback(char* topic, byte* payload, unsigned int length) { 67 | 68 | //convert topic to string to make it easier to work with 69 | String topicStr = topic; 70 | 71 | //turn the light on via serial to another micro if the payload is '1' and wait for ping back from other micro and confirm via confirm topic 72 | if(payload[0] == '1'){ 73 | Serial.write('1'); 74 | for(int i = 0; i < 10; i++){ //wait up to 100 ms for ping from other micro - loop 10 times each time waiting 10ms 75 | if(Serial.available() >= 1){ 76 | if(Serial.read() == '1'){ 77 | client.publish(lightConfirm, "Light turned on confirm"); 78 | break; 79 | } 80 | } 81 | delay(10); 82 | } 83 | } 84 | 85 | //turn the light off via serial to another micro if the payload is '0' and wait for ping back from other micro and confirm via confirm topic 86 | else if (payload[0] == '0'){ 87 | Serial.write('0'); 88 | for(int i = 0; i < 10; i++){ //wait up to 100 ms for ping from other micro - loop 10 times each time waiting 10ms 89 | if(Serial.available() >= 1){ 90 | if(Serial.read() == '0'){ 91 | client.publish(lightConfirm, "Light turned off confirm"); 92 | break; 93 | } 94 | } 95 | delay(10); 96 | } 97 | } 98 | 99 | } 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | //networking functions 109 | 110 | void reconnect() { 111 | 112 | //attempt to connect to the wifi if connection is lost 113 | if(WiFi.status() != WL_CONNECTED){ 114 | 115 | 116 | //loop while we wait for connection 117 | while (WiFi.status() != WL_CONNECTED) { 118 | delay(500); 119 | } 120 | 121 | 122 | } 123 | 124 | //make sure we are connected to WIFI before attemping to reconnect to MQTT 125 | if(WiFi.status() == WL_CONNECTED){ 126 | // Loop until we're reconnected to the MQTT server 127 | while (!client.connected()) { 128 | 129 | // Generate client name based on MAC address and last 8 bits of microsecond counter 130 | String clientName; 131 | clientName += "esp8266-"; 132 | uint8_t mac[6]; 133 | WiFi.macAddress(mac); 134 | clientName += macToStr(mac); 135 | 136 | //if connected, subscribe to the topic(s) we want to be notified about 137 | if (client.connect((char*) clientName.c_str())) { 138 | client.subscribe(lightTopic); 139 | } 140 | 141 | //otherwise print failed for debugging 142 | } 143 | } 144 | } 145 | 146 | //generate unique name from MAC addr 147 | String macToStr(const uint8_t* mac){ 148 | 149 | String result; 150 | 151 | for (int i = 0; i < 6; ++i) { 152 | result += String(mac[i], 16); 153 | 154 | if (i < 5){ 155 | result += ':'; 156 | } 157 | } 158 | 159 | return result; 160 | } 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /Serial Breakout Test/teensyNode/teensyNode.ino: -------------------------------------------------------------------------------- 1 | //ItKindaWorks - Creative Commons 2016 2 | //github.com/ItKindaWorks 3 | // 4 | //Requires PubSubClient found here: https://github.com/knolleary/pubsubclient 5 | // 6 | //ESP8266 Simple Serial breakout test via MQTT - teensy/arduino side 7 | // 8 | //This code demonstrates using an ESP8266 serial break board for bi-directional communication. 9 | //It connects to a network and listens subscribes to an MQTT topic. When the ESP recieves a '1' it sends that to the 10 | //teensy and the teensy turns a light on and pings back on the serial line. When the ESP gets the ping back it publishes 11 | //a confirmation to the MQTT broker on a different topic 12 | 13 | 14 | const int lightPin = 11; 15 | 16 | void setup() { 17 | //initialize the light as an output and set to LOW (off) 18 | pinMode(lightPin, OUTPUT); 19 | digitalWrite(lightPin, LOW); 20 | 21 | //start the serial line for debugging 22 | Serial1.begin(115200); 23 | delay(100); 24 | 25 | } 26 | 27 | 28 | 29 | void loop(){ 30 | 31 | if(Serial1.available()){ 32 | char inByte = Serial1.read(); 33 | if(inByte == '1'){ 34 | digitalWrite(lightPin, HIGH); 35 | Serial1.write('1'); 36 | } 37 | else if(inByte == '0'){ 38 | digitalWrite(lightPin, LOW); 39 | Serial1.write('0'); 40 | } 41 | } 42 | } 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | --------------------------------------------------------------------------------