Anton Linus 4 years ago
parent
commit
181fe557bc
  1. BIN
      .DS_Store
  2. BIN
      code/esp8266/.DS_Store
  3. 10
      code/esp8266/README.md
  4. 166
      code/esp8266/otastaImg-close-button/DNSServer.cpp
  5. 71
      code/esp8266/otastaImg-close-button/DNSServer.h
  6. 18
      code/esp8266/otastaImg-close-button/data/index.html
  7. BIN
      code/esp8266/otastaImg-close-button/data/pic.jpg
  8. 115
      code/esp8266/otastaImg-close-button/otastaImg-close-button.ino
  9. 166
      code/esp8266/otastaImg/DNSServer.cpp
  10. 72
      code/esp8266/otastaImg/DNSServer.h
  11. 12
      code/esp8266/otastaImg/data/index.html
  12. BIN
      code/esp8266/otastaImg/data/pic.jpg
  13. 98
      code/esp8266/otastaImg/otastaImg.ino
  14. 9
      works/Dennis de Bel & Anton Jehle/paracity_gallery_v041/README.md
  15. BIN
      works/Jonas Lund/hello capitalism/otastaImg/data/.DS_Store

BIN
.DS_Store

Binary file not shown.

BIN
code/esp8266/.DS_Store

Binary file not shown.

10
code/esp8266/README.md

@ -1,5 +1,11 @@
# opencoil-paracity: code
### Description of Files
* otastaImg - Offline ESP8266 webserver + captive portal + filesystem (iOS only atm)
* otastaImg-close-button - The above, but with 'close' button, just like your Hotel/Train/Airport wifi ;) (iOS only atm)
* paracity_gallery_v041 - Offline ESP8266 webserver + captive portal + filesystem hosting relevant files to reproduce all of this hardware and software (BROKEN)
### Prerequisites
This guide assumes you have a 4MB ESP12F microcontroller and use Arduino IDE.
@ -8,6 +14,10 @@ This guide assumes you have a 4MB ESP12F microcontroller and use Arduino IDE.
* SPIFFS: You will need to add SPIFFS file upload support to Arduino if you want to upload files to the ESP12F, see: https://github.com/esp8266/arduino-esp8266fs-plugin
### Uploading Data to SPIFFS
The website served on the ESP8266 lives in the 'data' folder inside the sketchyour sketch. To upload this data you need the 'Arduino ESP8266 filesystem uploader' plugin. Find it [here](https://github.com/esp8266/arduino-esp8266fs-plugin).
You will find the tool/function in Arduino > Tools > ESP8266 Sketch Data Upload (make sure the directory path is correct). Close the Serial Monitor prior to uploading data.
### Uploading Code
For ESP12F use the following settings in Arduino IDE

166
code/esp8266/otastaImg-close-button/DNSServer.cpp

@ -0,0 +1,166 @@
#include "./DNSServer.h"
#include <lwip/def.h>
#include <Arduino.h>
#define DEBUG
#define DEBUG_OUTPUT Serial
DNSServer::DNSServer()
{
_ttl = htonl(60);
_errorReplyCode = DNSReplyCode::NonExistentDomain;
}
bool DNSServer::start(const uint16_t &port, const String &domainName,
const IPAddress &resolvedIP)
{
_port = port;
_domainName = domainName;
_resolvedIP[0] = resolvedIP[0];
_resolvedIP[1] = resolvedIP[1];
_resolvedIP[2] = resolvedIP[2];
_resolvedIP[3] = resolvedIP[3];
downcaseAndRemoveWwwPrefix(_domainName);
return _udp.begin(_port) == 1;
}
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
{
_errorReplyCode = replyCode;
}
void DNSServer::setTTL(const uint32_t &ttl)
{
_ttl = htonl(ttl);
}
void DNSServer::stop()
{
_udp.stop();
}
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
{
domainName.toLowerCase();
domainName.replace("www.", "");
domainName.replace("https://", "");
}
void DNSServer::processNextRequest()
{
_currentPacketSize = _udp.parsePacket();
if (_currentPacketSize)
{
_buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
_udp.read(_buffer, _currentPacketSize);
_dnsHeader = (DNSHeader*) _buffer;
if (_dnsHeader->QR == DNS_QR_QUERY &&
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
requestIncludesOnlyOneQuestion() &&
(_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
)
{
replyWithIP();
}
else if (_dnsHeader->QR == DNS_QR_QUERY)
{
replyWithCustomCode();
}
free(_buffer);
}
}
bool DNSServer::requestIncludesOnlyOneQuestion()
{
return ntohs(_dnsHeader->QDCount) == 1 &&
_dnsHeader->ANCount == 0 &&
_dnsHeader->NSCount == 0 &&
_dnsHeader->ARCount == 0;
}
String DNSServer::getDomainNameWithoutWwwPrefix()
{
String parsedDomainName = "";
unsigned char *start = _buffer + 12;
if (*start == 0)
{
return parsedDomainName;
}
int pos = 0;
while(true)
{
unsigned char labelLength = *(start + pos);
for(int i = 0; i < labelLength; i++)
{
pos++;
parsedDomainName += (char)*(start + pos);
}
pos++;
if (*(start + pos) == 0)
{
downcaseAndRemoveWwwPrefix(parsedDomainName);
return parsedDomainName;
}
else
{
parsedDomainName += ".";
}
}
}
void DNSServer::replyWithIP()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
_dnsHeader->QDCount = _dnsHeader->QDCount;
//_dnsHeader->RA = 1;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, _currentPacketSize);
_udp.write((uint8_t)192); // answer name is a pointer
_udp.write((uint8_t)12); // pointer to offset at 0x00c
_udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
_udp.write((uint8_t)1);
_udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
_udp.write((uint8_t)1);
_udp.write((unsigned char*)&_ttl, 4);
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
_udp.write((uint8_t)0);
_udp.write((uint8_t)4);
_udp.write(_resolvedIP, sizeof(_resolvedIP));
_udp.endPacket();
#ifdef DEBUG
DEBUG_OUTPUT.print("DNS responds: ");
DEBUG_OUTPUT.print(_resolvedIP[0]);
DEBUG_OUTPUT.print(".");
DEBUG_OUTPUT.print(_resolvedIP[1]);
DEBUG_OUTPUT.print(".");
DEBUG_OUTPUT.print(_resolvedIP[2]);
DEBUG_OUTPUT.print(".");
DEBUG_OUTPUT.print(_resolvedIP[3]);
DEBUG_OUTPUT.print(" for ");
DEBUG_OUTPUT.println(getDomainNameWithoutWwwPrefix());
#endif
}
void DNSServer::replyWithCustomCode()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->RCode = (unsigned char)_errorReplyCode;
_dnsHeader->QDCount = 0;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, sizeof(DNSHeader));
_udp.endPacket();
}

71
code/esp8266/otastaImg-close-button/DNSServer.h

@ -0,0 +1,71 @@
#ifndef DNSServer_h
#define DNSServer_h
#include <WiFiUdp.h>
#define DNS_QR_QUERY 0
#define DNS_QR_RESPONSE 1
#define DNS_OPCODE_QUERY 0
enum class DNSReplyCode
{
NoError = 0,
FormError = 1,
ServerFailure = 2,
NonExistentDomain = 3,
NotImplemented = 4,
Refused = 5,
YXDomain = 6,
YXRRSet = 7,
NXRRSet = 8
};
struct DNSHeader
{
uint16_t ID; // identification number
unsigned char RD : 1; // recursion desired
unsigned char TC : 1; // truncated message
unsigned char AA : 1; // authoritive answer
unsigned char OPCode : 4; // message_type
unsigned char QR : 1; // query/response flag
unsigned char RCode : 4; // response code
unsigned char Z : 3; // its z! reserved
unsigned char RA : 1; // recursion available
uint16_t QDCount; // number of question entries
uint16_t ANCount; // number of answer entries
uint16_t NSCount; // number of authority entries
uint16_t ARCount; // number of resource entries
};
class DNSServer
{
public:
DNSServer();
void processNextRequest();
void setErrorReplyCode(const DNSReplyCode &replyCode);
void setTTL(const uint32_t &ttl);
// Returns true if successful, false if there are no sockets available
bool start(const uint16_t &port,
const String &domainName,
const IPAddress &resolvedIP);
// stops the DNS server
void stop();
private:
WiFiUDP _udp;
uint16_t _port;
String _domainName;
unsigned char _resolvedIP[4];
int _currentPacketSize;
unsigned char* _buffer;
DNSHeader* _dnsHeader;
uint32_t _ttl;
DNSReplyCode _errorReplyCode;
void downcaseAndRemoveWwwPrefix(String &domainName);
String getDomainNameWithoutWwwPrefix();
bool requestIncludesOnlyOneQuestion();
void replyWithIP();
void replyWithCustomCode();
};
#endif

18
code/esp8266/otastaImg-close-button/data/index.html

@ -0,0 +1,18 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!--do some user agent checks...-->
<head>
<title></title>
</head>
<body>
hi
<img src="pic.jpg">
<br><br>
<a href="/CONNECT">CONNECT (Close Captive Portal)</a>
</body>
</html>

BIN
code/esp8266/otastaImg-close-button/data/pic.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

115
code/esp8266/otastaImg-close-button/otastaImg-close-button.ino

@ -0,0 +1,115 @@
// Captive portal with (arduino) OTA + SPIFFS
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h> // Over-the-Air updates
#include <ESP8266WebServer.h>
#include "./DNSServer.h" // Dns server
#include <FS.h> // SPIFFS
DNSServer dnsServer;
const byte DNS_PORT = 53;
ESP8266WebServer server(80);
#ifndef STASSID
#define STASSID "\xF0\x9F\x9B\xB4 beta"
//#define STASPSK "mypassword"
#endif
IPAddress apIP(192, 168, 4, 1);
const char* ssid = STASSID;
//const char* password = STAPSK;
void setup() {
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(ssid);
dnsServer.start(DNS_PORT, "*", apIP); // redirect dns request to AP ip
MDNS.begin("esp8266", WiFi.softAPIP());
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
//Over-the-Air updates
ArduinoOTA.setHostname("ESP8266");
//ArduinoOTA.setPassword("change-me"); //enabling password disables SPIFFS upload
ArduinoOTA.begin();
SPIFFS.begin();
//close the captive portal screen on ios!
server.on("/CONNECT", closeCNAdelay);
//if page is not found, redirect traffic to index.html (cheap way to redirect all traffic to our lading page)
server.onNotFound([]() {
if(!handleFileRead(server.uri())){
const char *metaRefreshStr = "<head><meta http-equiv=\"refresh\" content=\"0; url=http://192.168.4.1/index.html\" /></head><body><p>redirecting...</p></body>";
server.send(200, "text/html", metaRefreshStr);
}
});
server.begin();
}
void loop() {
dnsServer.processNextRequest();
ArduinoOTA.handle();
server.handleClient();
delay(50);
}
String getContentType(String filename){
if(server.hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".mp4")) return "video/mp4";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
//Given a file path, look for it in the SPIFFS file storage. Returns true if found, returns false if not found.
bool handleFileRead(String path){
if(path.endsWith("/")) path += "index.html";
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
if(SPIFFS.exists(pathWithGz))
path += ".gz";
File file = SPIFFS.open(path, "r");
size_t sent = server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}
void handleAppleCaptivePortal() {
String Page = F("<HTML><HEAD><TITLE>Success</TITLE></HEAD><BODY>Success</BODY></HTML>");
server.sendHeader("Cache-Control","no-cache, no-store, must-revalidate");
server.sendHeader("Pragma", "no-cache");
server.sendHeader("Expires", "-1");
server.send(200, "text/html", Page);
return;
}
void closeCNAdelay(){
server.on("/hotspot-detect.html", handleAppleCaptivePortal);
return;
}

166
code/esp8266/otastaImg/DNSServer.cpp

@ -0,0 +1,166 @@
#include "./DNSServer.h"
#include <lwip/def.h>
#include <Arduino.h>
#define DEBUG
#define DEBUG_OUTPUT Serial
DNSServer::DNSServer()
{
_ttl = htonl(60);
_errorReplyCode = DNSReplyCode::NonExistentDomain;
}
bool DNSServer::start(const uint16_t &port, const String &domainName,
const IPAddress &resolvedIP)
{
_port = port;
_domainName = domainName;
_resolvedIP[0] = resolvedIP[0];
_resolvedIP[1] = resolvedIP[1];
_resolvedIP[2] = resolvedIP[2];
_resolvedIP[3] = resolvedIP[3];
downcaseAndRemoveWwwPrefix(_domainName);
return _udp.begin(_port) == 1;
}
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
{
_errorReplyCode = replyCode;
}
void DNSServer::setTTL(const uint32_t &ttl)
{
_ttl = htonl(ttl);
}
void DNSServer::stop()
{
_udp.stop();
}
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
{
domainName.toLowerCase();
domainName.replace("www.", "");
domainName.replace("https://", "");
}
void DNSServer::processNextRequest()
{
_currentPacketSize = _udp.parsePacket();
if (_currentPacketSize)
{
_buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
_udp.read(_buffer, _currentPacketSize);
_dnsHeader = (DNSHeader*) _buffer;
if (_dnsHeader->QR == DNS_QR_QUERY &&
_dnsHeader->OPCode == DNS_OPCODE_QUERY &&
requestIncludesOnlyOneQuestion() &&
(_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
)
{
replyWithIP();
}
else if (_dnsHeader->QR == DNS_QR_QUERY)
{
replyWithCustomCode();
}
free(_buffer);
}
}
bool DNSServer::requestIncludesOnlyOneQuestion()
{
return ntohs(_dnsHeader->QDCount) == 1 &&
_dnsHeader->ANCount == 0 &&
_dnsHeader->NSCount == 0 &&
_dnsHeader->ARCount == 0;
}
String DNSServer::getDomainNameWithoutWwwPrefix()
{
String parsedDomainName = "";
unsigned char *start = _buffer + 12;
if (*start == 0)
{
return parsedDomainName;
}
int pos = 0;
while(true)
{
unsigned char labelLength = *(start + pos);
for(int i = 0; i < labelLength; i++)
{
pos++;
parsedDomainName += (char)*(start + pos);
}
pos++;
if (*(start + pos) == 0)
{
downcaseAndRemoveWwwPrefix(parsedDomainName);
return parsedDomainName;
}
else
{
parsedDomainName += ".";
}
}
}
void DNSServer::replyWithIP()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
_dnsHeader->QDCount = _dnsHeader->QDCount;
//_dnsHeader->RA = 1;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, _currentPacketSize);
_udp.write((uint8_t)192); // answer name is a pointer
_udp.write((uint8_t)12); // pointer to offset at 0x00c
_udp.write((uint8_t)0); // 0x0001 answer is type A query (host address)
_udp.write((uint8_t)1);
_udp.write((uint8_t)0); //0x0001 answer is class IN (internet address)
_udp.write((uint8_t)1);
_udp.write((unsigned char*)&_ttl, 4);
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
_udp.write((uint8_t)0);
_udp.write((uint8_t)4);
_udp.write(_resolvedIP, sizeof(_resolvedIP));
_udp.endPacket();
#ifdef DEBUG
DEBUG_OUTPUT.print("DNS responds: ");
DEBUG_OUTPUT.print(_resolvedIP[0]);
DEBUG_OUTPUT.print(".");
DEBUG_OUTPUT.print(_resolvedIP[1]);
DEBUG_OUTPUT.print(".");
DEBUG_OUTPUT.print(_resolvedIP[2]);
DEBUG_OUTPUT.print(".");
DEBUG_OUTPUT.print(_resolvedIP[3]);
DEBUG_OUTPUT.print(" for ");
DEBUG_OUTPUT.println(getDomainNameWithoutWwwPrefix());
#endif
}
void DNSServer::replyWithCustomCode()
{
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->RCode = (unsigned char)_errorReplyCode;
_dnsHeader->QDCount = 0;
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
_udp.write(_buffer, sizeof(DNSHeader));
_udp.endPacket();
}

72
code/esp8266/otastaImg/DNSServer.h

@ -0,0 +1,72 @@
#ifndef DNSServer_h
#define DNSServer_h
#include <WiFiUdp.h>
#define DNS_QR_QUERY 0
#define DNS_QR_RESPONSE 1
#define DNS_OPCODE_QUERY 0
enum class DNSReplyCode
{
NoError = 0,
FormError = 1,
ServerFailure = 2,
NonExistentDomain = 3,
NotImplemented = 4,
Refused = 5,
YXDomain = 6,
YXRRSet = 7,
NXRRSet = 8
};
struct DNSHeader
{
uint16_t ID; // identification number
unsigned char RD : 1; // recursion desired
unsigned char TC : 1; // truncated message
unsigned char AA : 1; // authoritive answer
unsigned char OPCode : 4; // message_type
unsigned char QR : 1; // query/response flag
unsigned char RCode : 4; // response code
unsigned char Z : 3; // its z! reserved
unsigned char RA : 1; // recursion available
uint16_t QDCount; // number of question entries
uint16_t ANCount; // number of answer entries
uint16_t NSCount; // number of authority entries
uint16_t ARCount; // number of resource entries
};
class DNSServer
{
public:
DNSServer();
void processNextRequest();
void setErrorReplyCode(const DNSReplyCode &replyCode);
void setTTL(const uint32_t &ttl);
// Returns true if successful, false if there are no sockets available
bool start(const uint16_t &port,
const String &domainName,
const IPAddress &resolvedIP);
// stops the DNS server
void stop();
private:
WiFiUDP _udp;
uint16_t _port;
String _domainName;
unsigned char _resolvedIP[4];
int _currentPacketSize;
unsigned char* _buffer;
DNSHeader* _dnsHeader;
uint32_t _ttl;
DNSReplyCode _errorReplyCode;
void downcaseAndRemoveWwwPrefix(String &domainName);
String getDomainNameWithoutWwwPrefix();
bool requestIncludesOnlyOneQuestion();
void replyWithIP();
void replyWithCustomCode();
};
#endif

12
code/esp8266/otastaImg/data/index.html

@ -0,0 +1,12 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title></title>
</head>
<body>
hi
<img src="pic.jpg">
</body>
</html>

BIN
code/esp8266/otastaImg/data/pic.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

98
code/esp8266/otastaImg/otastaImg.ino

@ -0,0 +1,98 @@
// Captive portal with (arduino) OTA + SPIFFS
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h> // Over-the-Air updates
#include <ESP8266WebServer.h>
#include "./DNSServer.h" // Dns server
#include <FS.h> // SPIFFS
DNSServer dnsServer;
const byte DNS_PORT = 53;
ESP8266WebServer server(80);
#ifndef STASSID
#define STASSID "\xF0\x9F\x9B\xB4 beta"
//#define STASPSK "mypassword"
#endif
IPAddress apIP(192, 168, 4, 1);
const char* ssid = STASSID;
//const char* password = STAPSK;
void setup() {
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(ssid);
dnsServer.start(DNS_PORT, "*", apIP); // redirect dns request to AP ip
MDNS.begin("esp8266", WiFi.softAPIP());
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
//Over-the-Air updates
ArduinoOTA.setHostname("ESP8266");
//ArduinoOTA.setPassword("change-me"); //enabling password disables SPIFFS upload
ArduinoOTA.begin();
SPIFFS.begin();
//redirect all traffic to index.html
server.onNotFound([]() {
if(!handleFileRead(server.uri())){
const char *metaRefreshStr = "<head><meta http-equiv=\"refresh\" content=\"0; url=http://192.168.4.1/index.html\" /></head><body><p>redirecting...</p></body>";
server.send(200, "text/html", metaRefreshStr);
}
});
server.begin();
}
void loop() {
dnsServer.processNextRequest();
ArduinoOTA.handle();
server.handleClient();
delay(50);
}
String getContentType(String filename){
if(server.hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".mp4")) return "video/mp4";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
//Given a file path, look for it in the SPIFFS file storage. Returns true if found, returns false if not found.
bool handleFileRead(String path){
if(path.endsWith("/")) path += "index.html";
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){
if(SPIFFS.exists(pathWithGz))
path += ".gz";
File file = SPIFFS.open(path, "r");
size_t sent = server.streamFile(file, contentType);
file.close();
return true;
}
return false;
}

9
works/Dennis de Bel & Anton Jehle/paracity_gallery_v041/README.md

@ -15,11 +15,11 @@ The exhibition will start on October 26th in the public space in front of Zentru
Now do it yourself!
## hardware
In this repo you will find a 3d printable .stl file that will allow you to print a mould for vacuumforming the charging pad cover.
In this Archive you will find a 3d printable .stl file that will allow you to print a mould for vacuumforming the charging pad cover.
## software
In this repo you will find an arduino sketch for the ESP8266 wireless chip.
In this Archive you will find an arduino sketch for the ESP8266 wireless chip.
### prerequisites
@ -56,6 +56,11 @@ For ESP12F use the following settings in Arduino IDE
These settings give you about 2.471 KB of SPIFFS storage space for files and ~512KB sketch size
### Uploading Data to SPIFFS
The website served on the ESP8266 lives in the 'data' folder inside the sketchyour sketch. To upload this data you need the 'Arduino ESP8266 filesystem uploader' plugin. Find it [here](https://github.com/esp8266/arduino-esp8266fs-plugin).
You will find the tool/function in Arduino > Tools > ESP8266 Sketch Data Upload (make sure the directory path is correct). Close the Serial Monitor prior to uploading data.
### over the air (OTA) uploading

BIN
works/Jonas Lund/hello capitalism/otastaImg/data/.DS_Store

Binary file not shown.
Loading…
Cancel
Save