Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //TallyWhacker over WIFI using MQTT and Home Assistant with OTA Support
- //Tried to get deep sleep operational but couldn't. Got other shit I want to sniff..
- //Most of the code was copied from:
- //https://community.home-assistant.io/t/report-the-temperature-with-esp8266-to-mqtt/42489
- //Requires PubSubClient library found here: https://github.com/knolleary/pubsubclient
- #include <PubSubClient.h>
- #include <ESP8266WiFi.h>
- #include <ArduinoOTA.h>
- #include <Servo.h>
- void callback(char* topic, byte* payload, unsigned int length);
- #define MQTT_SERVER "<IP_ADDY>" //IP addy of MQTT broker eg. 192.168.1.4
- const char* ssid = "<SSID>"; //name of broadcasted wifi access point
- const char* password = "<SSID_PW>"; //wifi password
- int relayOutput = 15; //GPIO15, labeled as D8 on nodemcu esp8266
- int servoOutput = 12; //GPIO12, labeled as D6 on nodemcu esp8266
- //servoSetLeft indicates if the servo arm is over the ESP or over the batteries
- //0xffff indicates its over the ESP; 0x0000 for batteries
- uint32_t servoSetLeft;
- //tallyOn indicates if the TallyWhacker should be operating
- //0xffff indicates it's operating; 0x0000 for not
- uint32_t tallyOn;
- //random number used for the whacking interval formula
- long randomNumber = 0;
- //last time tallywhacked
- uint32_t previousWhack = 0;
- //This is the MQTT Topic that will be used to manage if the TallyWhacker should be whacking
- //Refer to my YAML component entry
- char const* tallywhacker = "home/tallywhacker";
- Servo servo;
- WiFiClient wifiClient;
- PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);
- void setup()
- {
- //initialize the switch as an output and set to LOW (off)
- pinMode(relayOutput, OUTPUT);
- digitalWrite(relayOutput, HIGH);
- servo.attach(servoOutput);
- servo.write(90);
- delay(500);
- digitalWrite(relayOutput, LOW);
- //A name given to your ESP8266 module when discovering it as a port in ARDUINO IDE
- ArduinoOTA.setHostname("TallyWhacker");
- ArduinoOTA.begin(); // OTA initialization
- // Serial.begin(115200);
- // delay(100);
- // Serial.println("Serial initialized.");
- //start wifi subsystem
- WiFi.begin(ssid, password);
- //attempt to connect to the WIFI network and then connect to the MQTT server
- reconnect();
- //check if random number is inRTC memory; if so, initialize it to 0x0000
- ESP.rtcUserMemoryRead(33, &servoSetLeft, sizeof(servoSetLeft));
- delay(10);
- // Serial.print("Memread servoSetLeft: "); Serial.println(servoSetLeft);
- if(servoSetLeft != 0x0000 || servoSetLeft != 0xffff)
- {
- servoSetLeft = 0x0000;
- ESP.rtcUserMemoryWrite(33, &servoSetLeft, sizeof(servoSetLeft));
- delay(10);
- }
- //check if random number is inRTC memory; if so, initialize it to 0x0000
- ESP.rtcUserMemoryRead(34, &tallyOn, sizeof(tallyOn));
- delay(10);
- // Serial.print("Memread tallyOn: "); Serial.println(tallyOn);
- if(tallyOn != 0x0000 || tallyOn != 0xffff)
- {
- tallyOn = 0x0000;
- ESP.rtcUserMemoryWrite(34, &tallyOn, sizeof(tallyOn));
- delay(15);
- }
- randomSeed(ESP.random());
- //wait a bit before starting the main loop
- delay(500);
- }
- void loop()
- {
- //reconnect if connection is lost
- if (!client.connected() && WiFi.status() == 3) {reconnect();}
- ArduinoOTA.handle();
- //maintain MQTT connection
- client.loop();
- //MUST delay to allow ESP8266 WIFI functions to run
- delay(10);
- ESP.rtcUserMemoryRead(34, &tallyOn, sizeof(tallyOn));
- delay(10);
- // Serial.print("Loop memread tallyOn: "); Serial.println(tallyOn);
- if(tallyOn == 0xffff)
- {
- uint32_t time = millis();
- if(time - previousWhack >= randomNumber)
- {
- previousWhack = millis();
- //set random interval between whackings
- randomNumber= random(4, 34)*1000; //5-35 seconds
- //read from RTC memory, the last position of the servo.
- //servoSetLeft == 0xffff means the servo arm is over the ESP
- ESP.rtcUserMemoryRead(33, &servoSetLeft, sizeof(servoSetLeft));
- delay(10);
- if(servoSetLeft == 0x0000)
- {
- digitalWrite(relayOutput, HIGH);
- servo.write(50);
- delay(1500);
- digitalWrite(relayOutput, LOW);
- servoSetLeft = 0xffff;
- ESP.rtcUserMemoryWrite(33, &servoSetLeft, sizeof(servoSetLeft));
- delay(10);
- }
- else if(servoSetLeft == 0xffff)
- {
- digitalWrite(relayOutput, HIGH);
- servo.write(140);
- delay(1500);
- digitalWrite(relayOutput, LOW);
- servoSetLeft = 0x0000;
- ESP.rtcUserMemoryWrite(33, &servoSetLeft, sizeof(servoSetLeft));
- delay(10);
- }
- }
- }
- }
- void callback(char* topic, byte* payload, unsigned int length)
- {
- //convert topic to string to make it easier to work with
- //Note: the "topic" value gets overwritten everytime it receives confirmation (callback) message from MQTT
- String topicStr = topic;
- Serial.println(topicStr);
- Serial.println(servoSetLeft);
- if (topicStr == "home/tallywhacker")
- {
- //turn the tallywhacker on if the payload is '1' and publish to the MQTT server a confirmation message
- if(payload[0] == '1')
- {
- tallyOn = 0xffff;
- ESP.rtcUserMemoryWrite(34, &tallyOn, sizeof(tallyOn));
- delay(10);
- Serial.print("Callback tallyOn: "); Serial.println(tallyOn);
- client.publish("home/tallyConfirm", "1");
- }
- //turn the tallywhacker off if the payload is '0' and publish to the MQTT server a confirmation message
- else if (payload[0] == '0')
- {
- tallyOn = 0x0000;
- ESP.rtcUserMemoryWrite(34, &tallyOn, sizeof(tallyOn));
- delay(10);
- Serial.print("Callback tallyOn: "); Serial.println(tallyOn);
- client.publish("home/tallyConfirm", "0");
- }
- }
- }
- void reconnect()
- {
- //attempt to connect to the wifi if connection is lost
- if(WiFi.status() != WL_CONNECTED)
- {
- //loop while we wait for connection
- while (WiFi.status() != WL_CONNECTED)
- {
- delay(500);
- }
- }
- //make sure we are connected to WIFI before attemping to reconnect to MQTT
- if(WiFi.status() == WL_CONNECTED)
- {
- // Loop until we're reconnected to the MQTT server
- while (!client.connected())
- {
- // Generate client name based on MAC address and last 8 bits of microsecond counter
- String clientName;
- clientName += "tallywhacker-";
- uint8_t mac[6];
- WiFi.macAddress(mac);
- clientName += macToStr(mac);
- //if connected, subscribe to the topic(s) we want to be notified about
- //Delete "tallywhacker", and "<password>" here if you are not using any password
- //<password> is for your MQTT broker
- if (client.connect((char*) clientName.c_str(), "tallywhacker", "<password>"))
- { //Update accordingly with your MQTT account
- client.subscribe(tallywhacker);
- }
- //otherwise print failed for debugging
- else{abort();}
- }
- }
- }
- //generate unique name from MAC addr
- String macToStr(const uint8_t* mac)
- {
- String result;
- for (int i = 0; i < 6; ++i)
- {
- result += String(mac[i], 16);
- if (i < 5)
- {
- result += ':';
- }
- }
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement