Last active
November 22, 2020 14:54
-
-
Save sivar2311/e9272c991d0fd28f8efc7e9868c32e15 to your computer and use it in GitHub Desktop.
Beamerlift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <ESP8266WiFi.h> | |
#include <ArduinoOTA.h> | |
#include "logger.h" | |
Logger logger; | |
#define ENABLE_DEBUG | |
#ifdef ENABLE_DEBUG | |
#define NODEBUG_WEBSOCKETS | |
#define NDEBUG | |
#endif | |
#include "SinricPro.h" | |
#include "SinricProSwitch.h" | |
#define WIFI_SSID "" | |
#define WIFI_PASS "" | |
#define APP_KEY "" | |
#define APP_SECRET "" | |
#define SWITCH_ID "" | |
#define BAUD_RATE 115200 // Change baudrate to your need | |
#define LIFT_TIME 45000 // 45 seconds | |
#define HOSTNAME "beamerlift" | |
const int RELAY_PIN1=D2; | |
const int RELAY_PIN2=D5; | |
bool powerState; | |
unsigned long previousMillis = 0; | |
bool onPowerState(const String &deviceId, bool &state) { | |
if (powerState == state) return true; // same command again? ignore but return "OK" | |
if (previousMillis) { // move in progress?? | |
state = powerState; // report current state | |
return false; // abort request! | |
} | |
logger.printf("Beamerlift moving %s\r\n", state?"up":"down"); | |
powerState = state; // update state (position) | |
digitalWrite(RELAY_PIN1, LOW); // turn off relay1 | |
digitalWrite(RELAY_PIN2, LOW); // turn off relay2 | |
delay(5); // for security...give the relays a bit time to release | |
previousMillis = millis(); // Get the initial time the appliance was turned on | |
if (state) { | |
digitalWrite(RELAY_PIN1, HIGH); // state == true? turn on relay 1 | |
} else { | |
digitalWrite(RELAY_PIN2, HIGH); // state == false? turn on relay 2 | |
} | |
return true; | |
} | |
void checkTimer() { | |
if (previousMillis && millis() - previousMillis >= LIFT_TIME) { // Check if appliance was turned on for 45s | |
logger.printf("Beamerlift stopped moving\r\n"); | |
digitalWrite(RELAY_PIN1, LOW); // Turn off the relay after 45 seconds | |
digitalWrite(RELAY_PIN2, LOW); // Turn off the relay after 45 seconds | |
previousMillis = 0; | |
} | |
} | |
void setupWiFi() { | |
logger.printf("\r\n[Wifi]: Connecting"); | |
WiFi.hostname(HOSTNAME); | |
WiFi.begin(WIFI_SSID, WIFI_PASS); | |
while (WiFi.status() != WL_CONNECTED) { | |
logger.printf("."); | |
delay(250); | |
} | |
logger.printf("connected!\r\n[WiFi]: IP-Address is %s\r\n", WiFi.localIP().toString().c_str()); | |
ArduinoOTA.setHostname(HOSTNAME); | |
ArduinoOTA.begin(); | |
} | |
void setupSinricPro() { | |
SinricProSwitch& mySwitch = SinricPro[SWITCH_ID]; | |
mySwitch.onPowerState(onPowerState); | |
SinricPro.onConnected([](){ logger.printf("Connected to SinricPro\r\n"); }); | |
SinricPro.onDisconnected([](){ logger.printf("Disconnected from SinricPro\r\n"); }); | |
SinricPro.begin(APP_KEY, APP_SECRET); | |
} | |
void setup() { | |
pinMode(RELAY_PIN1, OUTPUT); // define Relay GPIO as output | |
pinMode(RELAY_PIN2, OUTPUT); // define Relay GPIO as output | |
Serial.begin(BAUD_RATE); Serial.printf("\r\n\r\n"); | |
setupWiFi(); | |
setupSinricPro(); | |
} | |
void checkWiFi() { | |
static wl_status_t lastWiFiState; | |
wl_status_t currentWiFiState = WiFi.status(); | |
if (lastWiFiState == currentWiFiState) return; | |
logger.printf("WiFi-status changed: %d -> %d\r\n", lastWiFiState, currentWiFiState); | |
lastWiFiState = currentWiFiState; | |
} | |
void loop() { | |
ArduinoOTA.handle(); | |
SinricPro.handle(); | |
logger.handle(); | |
checkTimer(); | |
checkWiFi(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _LOGGER_H_ | |
#define _LOGGER_H_ | |
#include "Arduino.h" | |
#include "LittleFS.h" | |
#include "ESP8266WebServer.h" | |
#include "NTPClient.h" | |
#include "WiFiUdp.h" | |
#define LOGGER_BUFFSIZE 256 | |
class Logger : public Print { | |
public: | |
Logger(const String filename="/log.txt", size_t maxFileSize = 1024*800); | |
~Logger(); | |
virtual size_t write(uint8_t c) override; | |
virtual void handle(unsigned long interval=1000); | |
private: | |
String filename; | |
int utc_diff; | |
size_t maxFileSize; | |
File logFile; | |
size_t pos; | |
bool dirty; | |
bool newLine; | |
char buf[LOGGER_BUFFSIZE]; | |
ESP8266WebServer server; | |
WiFiUDP ntpUDP; | |
NTPClient timeClient; | |
WiFiServer telnet; | |
WiFiClient telnetClient; | |
virtual void clearFile(); | |
void welcomeTelnet(); | |
const char* makeTimestamp(); | |
}; | |
Logger::Logger(const String filename, size_t maxFileSize) : | |
filename(filename), | |
maxFileSize(maxFileSize), | |
pos(0), | |
dirty(false), | |
newLine(false), | |
timeClient(ntpUDP, "pool.ntp.org", 3600), | |
telnet(23) { | |
LittleFS.begin(); | |
timeClient.begin(); | |
telnet.begin(); | |
logFile = LittleFS.open(filename, "a"); | |
server.on("/clear", HTTP_GET, [&]() { | |
clearFile(); | |
server.sendHeader("Location", String("/"), true); | |
server.send ( 302, "text/plain", ""); | |
}); | |
server.on("/", HTTP_GET, [&]() { | |
File tempFile = LittleFS.open("/log.txt", "r"); | |
server.streamFile(tempFile, "text/plain"); | |
tempFile.close(); | |
}); | |
server.begin(); | |
} | |
Logger::~Logger() { | |
logFile.close(); | |
} | |
size_t Logger::write(uint8_t c) { | |
if (c) { | |
buf[pos++] = (char) c; | |
Serial.write((char) c); | |
dirty = true; | |
} | |
if (c == '\n' || pos==LOGGER_BUFFSIZE-1) { | |
if (newLine) { | |
const char* timestamp = makeTimestamp(); | |
if (logFile) { | |
logFile.print(timestamp); | |
logFile.write(buf, pos); | |
} | |
if (telnetClient) { | |
telnetClient.print(timestamp); | |
telnetClient.write(buf, pos); | |
} | |
newLine = false; | |
} | |
newLine = (c == '\n'); | |
pos = 0; | |
} | |
return 1; | |
} | |
void Logger::clearFile() { | |
logFile.close(); | |
LittleFS.remove(filename); | |
logFile = LittleFS.open(filename, "a"); | |
logFile.printf("(%s) Log file cleared\r\n",timeClient.getFormattedTime().c_str()); | |
logFile.flush(); | |
} | |
void Logger::handle(unsigned long interval) { | |
if (logFile.size() >= maxFileSize) clearFile(); | |
timeClient.update(); | |
server.handleClient(); | |
if (telnet.hasClient()) { | |
telnetClient = telnet.available(); | |
telnetClient.setNoDelay(true); | |
welcomeTelnet(); | |
} | |
static unsigned long lastMillis = 0; | |
unsigned long currentMillis = millis(); | |
if (dirty && currentMillis - lastMillis >= interval) { | |
lastMillis = currentMillis; | |
logFile.flush(); | |
dirty=false; | |
} | |
} | |
void Logger::welcomeTelnet() { | |
const int buffSize = 1024; | |
size_t bytesToRead; | |
File log = LittleFS.open(filename, "r"); | |
size_t remaining = log.available(); | |
char buf[buffSize]; | |
while (remaining) { | |
if (remaining >= buffSize) { | |
bytesToRead = buffSize; | |
} else { | |
bytesToRead = remaining; | |
} | |
log.readBytes(buf, bytesToRead); | |
telnetClient.write(buf, bytesToRead); | |
remaining -= bytesToRead; | |
yield(); | |
} | |
log.close(); | |
} | |
const char* Logger::makeTimestamp() { | |
time_t epochTime = timeClient.getEpochTime(); | |
struct tm *ptm = localtime ((time_t *)&epochTime); | |
static char timestamp[64]; | |
snprintf(timestamp, 64, "[%04d-%02d-%02d %02d:%02d:%02d (%d) %ddBm]: ", | |
ptm->tm_year+1900, | |
ptm->tm_mon+1, | |
ptm->tm_mday, | |
ptm->tm_hour, | |
ptm->tm_min, | |
ptm->tm_sec, | |
WiFi.status(), | |
WiFi.RSSI()); | |
return timestamp; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment