270 lines
7.8 KiB
C++
270 lines
7.8 KiB
C++
// global config
|
|
|
|
#include "config.h"
|
|
|
|
//################# LIBRARIES ##########################
|
|
#include <ESP8266WiFi.h>
|
|
#include <ESP8266WebServer.h>
|
|
#include <ESP8266mDNS.h>
|
|
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
|
|
#include <DNSServer.h>
|
|
#include <SPI.h>
|
|
#include <Adafruit_GFX.h>
|
|
#include <Max72xxPanel.h>
|
|
#include <time.h>
|
|
#include <ArduinoOTA.h>
|
|
#include "OTAsetup.h"
|
|
#include "d_helper.h"
|
|
#include "FS.h"
|
|
|
|
#define HOSTNAME "LibreMetric-"
|
|
|
|
//################# DISPLAY CONNECTIONS ################
|
|
// LED Matrix Pin -> ESP8266 Pin
|
|
// Vcc -> 3v (3V on NodeMCU 3V3 on WEMOS)
|
|
// Gnd -> Gnd (G on NodeMCU)
|
|
// DIN -> D7 (Same Pin for WEMOS)
|
|
// CS -> D4 (Same Pin for WEMOS)
|
|
// CLK -> D5 (Same Pin for WEMOS)
|
|
|
|
//################ PROGRAM SETTINGS ####################
|
|
String version = "0.1b";
|
|
int PORT = 80;
|
|
int wait = 50;
|
|
int spacer = 1;
|
|
int width = 5 + spacer;
|
|
String SITE_WIDTH = "1000";
|
|
int timezone = 1;
|
|
int dstOffset = 1;
|
|
const char* ntpServer = "fr.pool.ntp.org";
|
|
int brightness = 16;
|
|
int pinCS = D4;
|
|
int numberOfHorizontalDisplays = 4;
|
|
int numberOfVerticalDisplays = 1;
|
|
|
|
//################## INITIALIZING ######################
|
|
char time_value[20];
|
|
String message, webpage;
|
|
ESP8266WebServer server(PORT);
|
|
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
|
|
|
|
// in a terminal: telnet esp IP
|
|
#ifdef DEBUG_TELNET
|
|
WiFiServer telnetServer(23);
|
|
WiFiClient telnetClient;
|
|
|
|
void handleTelnet(void) {
|
|
if (telnetServer.hasClient()) {
|
|
if (!telnetClient || !telnetClient.connected()) {
|
|
if (telnetClient) {
|
|
telnetClient.stop();
|
|
}
|
|
telnetClient = telnetServer.available();
|
|
} else {
|
|
telnetServer.available().stop();
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void configModeCallback (WiFiManager *myWiFiManager) { // AP config mode
|
|
display_message("Setup");
|
|
}
|
|
|
|
void setup() {
|
|
// Initialisation
|
|
Serial.begin(115200);
|
|
DEBUG_PRINT(F("\n\r"));
|
|
matrix.fillScreen(LOW); // clear screen
|
|
initOTA();
|
|
SPIFFS.begin();
|
|
for (int i=0; i<numberOfHorizontalDisplays; i++){
|
|
DEBUG_PRINT(F("Changing orientation of display #"));
|
|
DEBUG_PRINTLN(i);
|
|
matrix.setRotation(i, 1);
|
|
}
|
|
DEBUG_PRINT(numberOfHorizontalDisplays);
|
|
DEBUG_PRINTLN(F(" displays configurated..."));
|
|
|
|
// Initialise Wi-Fi
|
|
display_message("Wi-Fi");
|
|
WiFiManager wifiManager;
|
|
String hostname(HOSTNAME);
|
|
hostname += String(ESP.getChipId(), HEX);
|
|
WiFi.hostname(hostname);
|
|
#ifndef DEBUG_WifiM
|
|
wifiManager.setDebugOutput(false); // no debug
|
|
#endif
|
|
wifiManager.setTimeout(180);
|
|
wifiManager.setAPCallback(configModeCallback);
|
|
if(!wifiManager.autoConnect("LibreMetric")) {
|
|
DEBUG_PRINTLN(F("failed to connect and timeout occurred"));
|
|
display_message("Failed to connect");
|
|
delay(6000);
|
|
ESP.reset(); //reset and try again
|
|
delay(180000);
|
|
}
|
|
matrix.fillScreen(LOW);
|
|
DEBUG_PRINTLN(F("WiFi connected..."));
|
|
display_message("OK");
|
|
delay(10*wait);
|
|
DEBUG_PRINTLN(WiFi.localIP());
|
|
|
|
// First sync with NTP
|
|
configTime(timezone * 3600, dstOffset * 3600, ntpServer); // First sync of time with (S)NTP
|
|
|
|
// Initialise Telnet Server for debugging purposes
|
|
#ifdef DEBUG_TELNET
|
|
telnetServer.begin();
|
|
telnetServer.setNoDelay(true);
|
|
#endif
|
|
|
|
// Initialise web server
|
|
server.begin();
|
|
DEBUG_PRINTLN(F("Webserver started..."));
|
|
server.on("/", GetMessage);
|
|
if (!MDNS.begin("ESP8266")) {
|
|
DEBUG_PRINTLN("Error setting up MDNS responder!");
|
|
while(1) {
|
|
delay(10*wait);
|
|
}
|
|
}
|
|
|
|
// Initialise mDNS
|
|
DEBUG_PRINTLN("mDNS responder started");
|
|
MDNS.addService("http", "tcp", 80);
|
|
|
|
// Startup OK
|
|
display_message(WiFi.localIP().toString());
|
|
message = "Bienvenue !";
|
|
|
|
}
|
|
|
|
void loop() {
|
|
// Webserver's first
|
|
server.handleClient();
|
|
matrix.fillScreen(LOW);
|
|
|
|
// Getting and parsing the time
|
|
time_t now = time(nullptr);
|
|
String time = String(ctime(&now));
|
|
time.trim();
|
|
time.substring(11,19).toCharArray(time_value, 10);
|
|
int seconds = time.substring(17,19).toInt();
|
|
|
|
// Displaying the time on the LED matrix
|
|
for (int i = 0; i <= 4; i++) {
|
|
if (i != 2 || seconds % 2 == 0) matrix.drawChar(i*6+2,0, time_value[i], HIGH,LOW,1); // H
|
|
}
|
|
matrix.write(); // Send bitmap to display
|
|
|
|
// Parsing and displaying args from webserver
|
|
if (message != "") {
|
|
display_message(message); // Display the message
|
|
DEBUG_PRINT(F("Message envoyé à LibreMetric : "));
|
|
DEBUG_PRINTLN(message);
|
|
message = "";
|
|
}
|
|
if (brightness <= 15) {
|
|
DEBUG_PRINT(F("Nouvelle luminosité : "));
|
|
DEBUG_PRINTLN(brightness);
|
|
matrix.setIntensity(brightness);
|
|
brightness = 16;
|
|
}
|
|
ArduinoOTA.handle();
|
|
|
|
#ifdef DEBUG_TELNET
|
|
// Handle Telnet connection for debugging
|
|
handleTelnet();
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
// Function for displaying all messages
|
|
void display_message(String message){
|
|
if (width * message.length() - spacer > matrix.width()) {
|
|
display_message_long(message);
|
|
}
|
|
else {
|
|
matrix.fillScreen(LOW);
|
|
int x = (matrix.width()-(width * message.length() - spacer))/2;
|
|
int y = (matrix.height() - 8) / 2; // center the text vertically
|
|
for ( int i =0; i < message.length(); i++ ){
|
|
matrix.drawChar(x + (i * width), y, message[i], HIGH, LOW, 1); // HIGH LOW means foreground ON, background OFF, reverse these to invert the display!
|
|
}
|
|
matrix.write(); // Send bitmap to display
|
|
delay(20*wait);
|
|
}
|
|
}
|
|
|
|
// Function for displaying only long messages (longer than LED matrix length)
|
|
// This function is called only by the display_message function
|
|
void display_message_long(String message){
|
|
for ( int i = 0 ; i < width * message.length() + matrix.width() - spacer; i++ ) {
|
|
matrix.fillScreen(LOW);
|
|
int letter = i / width;
|
|
int x = (matrix.width() - 1) - i % width;
|
|
int y = (matrix.height() - 8) / 2; // center the text vertically
|
|
while ( x + width - spacer >= 0 && letter >= 0 ) {
|
|
if ( letter < message.length() ) {
|
|
matrix.drawChar(x, y, message[letter], HIGH, LOW, 1); // HIGH LOW means foreground ON, background OFF, reverse these to invert the display!
|
|
}
|
|
letter--;
|
|
x -= width;
|
|
}
|
|
matrix.write(); // Send bitmap to display
|
|
delay(wait);
|
|
}
|
|
}
|
|
|
|
void GetMessage() {
|
|
if (server.args() > 0 ) { // Arguments were received
|
|
for ( uint8_t i = 0; i <= server.args(); i++ ) {
|
|
String Argument_Name = server.argName(i);
|
|
String client_response = server.arg(i);
|
|
if (Argument_Name == "message" && client_response != "") message = client_response;
|
|
if (Argument_Name == "brightness" && client_response != "") brightness = client_response.toInt();
|
|
}
|
|
}
|
|
String webpage = fileRead("/index.html");
|
|
String ipaddress = WiFi.localIP().toString();
|
|
webpage.replace("ipaddress", ipaddress);
|
|
server.send(200, "text/html", webpage); // Send a response to the client to enter their inputs, if needed, Enter=defaults
|
|
}
|
|
|
|
String fileRead(String name){
|
|
//read file from SPIFFS and store it as a String variable
|
|
String contents;
|
|
File file = SPIFFS.open(name.c_str(), "r");
|
|
if (!file) {
|
|
String errorMessage = "Can't open '" + name + "' !\r\n";
|
|
DEBUG_PRINTLN(errorMessage);
|
|
return "FILE ERROR";
|
|
}
|
|
else {
|
|
|
|
// this is going to get the number of bytes in the file and give us the value in an integer
|
|
int fileSize = file.size();
|
|
int chunkSize=1024;
|
|
//This is a character array to store a chunk of the file.
|
|
//We'll store 1024 characters at a time
|
|
char buf[chunkSize];
|
|
int numberOfChunks=(fileSize/chunkSize)+1;
|
|
|
|
int count=0;
|
|
int remainingChunks=fileSize;
|
|
for (int i=1; i <= numberOfChunks; i++){
|
|
if (remainingChunks-chunkSize < 0){
|
|
chunkSize=remainingChunks;
|
|
}
|
|
file.read((uint8_t *)buf, chunkSize-1);
|
|
remainingChunks=remainingChunks-chunkSize;
|
|
contents+=String(buf);
|
|
}
|
|
file.close();
|
|
return contents;
|
|
}
|
|
}
|
|
|