Skip to content

Instantly share code, notes, and snippets.

@sivar2311
Last active November 22, 2020 14:54
Show Gist options
  • Save sivar2311/e9272c991d0fd28f8efc7e9868c32e15 to your computer and use it in GitHub Desktop.
Save sivar2311/e9272c991d0fd28f8efc7e9868c32e15 to your computer and use it in GitHub Desktop.
Beamerlift
#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();
}
#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