/*
created Feb 2018
by John Milner and Phil Charlesworth for StrongSoft®
This code is in the public domain.
*/
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <MIDI.h>
#include <SPI.h>
#include <EEPROM.h>
//Wemos D1 R2 & mini
// Web page @ 192.168.4.1/main
//MIDI Enable Jumper goes on D13...
# define MIDI_EN 14
//pins 5, 6, 7, 8, 9, 10, 11 cause wdt reset
//pins 13, 14 don't work
int ledReceive = 12; //This one is working...
int ledSend = 4;//This one is working...
unsigned int UDPPort = 9000; // local port to listen on
const char WiFiAPPSK[] = "";
const int Version_UMMU = 2;
const int Version_MSB = 4;
const int Version_LSB = 3;
String response;
String AP_NameString;
String PW_String;
int storedValue;
long previousMillis = 0;
long interval = 20;
char packetBuffer[25400]; //buffer to hold incoming packet
char ReplyBuffer[] = "Hell Yes!!"; // a string to send back - not used...
WiFiUDP Udp;
WiFiServer server(80);
void HandleNoteOn(byte channel, byte note, byte velocity)
{
digitalWrite(ledReceive, HIGH);
byte data[2];
data[0] = 143 + channel;
data[1] = note;
data[2] = velocity;
Udp.beginPacket(Udp.remoteIP(), 9001);
Udp.write(data[0]);
Udp.write(data[1]);
Udp.write(data[2]);
Udp.endPacket();
digitalWrite(ledReceive, LOW);
}
void HandleControlChange (byte channel, byte number, byte value) {
digitalWrite(ledReceive, HIGH);
byte data[2];
data[0] = 175 + channel;
data[1] = number;
data[2] = value;
Udp.beginPacket(Udp.remoteIP(), 9001);
Udp.write(data[0]);
Udp.write(data[1]);
Udp.write(data[2]);
Udp.endPacket();
}
void HandleProgramChange (byte channel, byte value) {
digitalWrite(ledReceive, HIGH);
byte data[1];
data[0] = 191 + channel;
data[1] = value;
Udp.beginPacket(Udp.remoteIP(), 9001);
Udp.write(data[0]);
Udp.write(data[1]);
Udp.endPacket();
}
void HandleSysEx(byte *array, byte size)
{
if (size == 14 || size == 10 || size == 9 || size == 18) { //Supported SysEx
digitalWrite(ledReceive, HIGH);
Udp.beginPacket(Udp.remoteIP(), 9001);
Udp.write(array, size);
Udp.endPacket();
}
}
//**************** START OF WEB PAGES / RESPONSES ****************
String web_page_main() {
Serial.println("got to web_page_main");
response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<font size=\"4\">";
response += "<!DOCTYPE HTML>\r\n";
response += "<HTML>\r\n";
response += "<HEAD>\r\n";
response += "<meta name='viewport' content='width=device-width; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;'/>";
response += "<meta name='apple-mobile-web-app-capable' content='yes'/>";
response += "<style type= 'text/css' >\r\n";
response += "body,td,th { font-family: Gotham, Helvetica, Arial, sans-serif; font-size: 14pt; color: #F9B600; -webkit-text-size-adjust: 100%;}";
response += "body { background-color: #000000; }";
response += "hr { height:0; border:0; border-top:1px solid #F9B600; }";
response += "</style>\r\n";
response +="<TITLE>UMMU Box Rev 2 WiFi Settings - Home</TITLE>\r\n";
response += "UMMU Box Rev 2 - software version ";
response += Version_UMMU;
response += ".";
response += Version_MSB;
response += ".";
response += Version_LSB;
response += "<hr>";
if (WiFi.channel() == EEPROM.read(0) && EEPROM.read(2) == EEPROM.read(1)) {
response += "<br>Your SSID is: <font color='#FFFF00'>";
response += AP_NameString;
response += "<br><br><font color='#F9B600'>Your Password is: <font color='#FFFF00'>";
response += PW_String;
response += "<br><br><font color='#F9B600'>You are now on Channel: <font color='#FFFF00'>";
response += WiFi.channel();
}
if (WiFi.channel() != EEPROM.read(0) | EEPROM.read(2) != EEPROM.read(1)) {
response += "<font color='#FF0000'>ALERT: ";
response += "You have the following unsaved changes to 'Settings' ";
response += "that will come into effect the next time your UMMU Box is restarted...";
if (WiFi.channel() != EEPROM.read(0)) {
response += "<br><font color='#FFFFFF'>- The WiFi Channel will be changed from Channel: ";
response += WiFi.channel();
response += " to Channel: ";
response += EEPROM.read(0);
response += " -";
}
if (EEPROM.read(2) != EEPROM.read(1)) {
response += "<br>The display settings of the SSID will be changed";
}
response += "<br><font color='#FF0000'>It is recommended that you restart the UMMU Box now and reconnect WiFi...";
}
response += "<br><br><font color='#F9B600'>Click <a href=\"/channel\"><font color='#FFFF00'>here</a><font color='#F9B600'> to change the WiFi settings";
if (WiFi.channel() != EEPROM.read(0) | EEPROM.read(2) != EEPROM.read(1)) {
response += " again...";
}
else {
response += "...";
}
response += "<br><br><br><br><br><font color='#555555'>UMMU Box Rev 2 Software ©2016: John Milner and Phil Charlesworth for StrongSoft®: All Rights Reserved...";
response += "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
response += "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
response += "</font></html>\n";
return response;
}
String web_page_channel() {
Serial.println("got to web_page_channel");
response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<font size=\"4\">";
response += "<HTML>\r\n";
response += "<HEAD>\r\n";
response += "<meta name='viewport' content='width=device-width; initial-scale=0.9; maximum-scale=1.0; user-scalable=0;'/>";
response += "<meta name='apple-mobile-web-app-capable' content='yes'/>";
response += "<style type= 'text/css' >\r\n";
response += "input[type=radio]{outline: 1px solid orange }";
response += "body,td,th { font-family: Gotham, Helvetica, Arial, sans-serif; font-size: 14pt; color: #F9B600; -webkit-text-size-adjust: 100%;}";
response += "body { background-color: #000000; }";
response += "hr { height:0; border:0; border-top:1px solid #F9B600; }";
response += "</style>\r\n";
response +="<TITLE>UMMU Box Rev 2 WiFi Settings - Channel</TITLE>\r\n";
response += "UMMU Box Rev 2 - software version ";
response += Version_UMMU;
response += ".";
response += Version_MSB;
response += ".";
response += Version_LSB;
response += "<hr>";
response += "You are currently using Channel: ";
response += WiFi.channel();
response += "<br>";
response += "<form action=\"/main\">";
response += "<br><input type=\"radio\" name=\"channel\" value=\"1\"";
if(WiFi.channel() == 1){
response += " checked";
}
response += "> Channel: 1 ";
response += "<br><input type=\"radio\" name=\"channel\" value=\"2\"";
if(WiFi.channel() == 6){
response += " checked";
}
response += "> Channel: 6 ";
response += "<br><input type=\"radio\" name=\"channel\" value=\"3\"";
if(WiFi.channel() == 11){
response += " checked";
}
response += "> Channel: 11 ";
// response += "<br><input type=\"radio\" name=\"channel\" value=\"4\"";
// if(WiFi.channel() == 14){
// response += " checked";
//}
// response += "> Channel: 14 ";
response += "<br><br><input type=\"submit\" value=\"Change Channel\">";
response += "</form><br>";
/*
response += "The SSID is currently: ";
if (EEPROM.read(2) == 0) { // stored boot value
response += "displayed";
}
else response += "not displayed";
response += "<br>";
response += "<br><form action=\"/main\">";
response += "<input type=\"radio\" name=\"SSID\" value=\"1\"";
if (EEPROM.read(2) == 0){
response += " checked";
}
response += "> SSID: displayed ";
response += "<br><input type=\"radio\" name=\"SSID\" value=\"2\"";
if (EEPROM.read(2) == 1){
response += " checked";
}
response += "> SSID: not displayed";
response += "<br><br><input type=\"submit\" value=\"Change SSID Setting\">";
response += "</form><br>";
*/
response += "Click <a href=\"/scan\"><font color='#FFFF00'>here</a><font color='#F9B600'> to see the Channels that are being used by others...";
response += "<br><br>Click <a href=\"/main\"><font color='#FFFF00'>here</a><font color='#F9B600'> to return to the main menu...";
response += "<br><font color='#555555'>UMMU Box Rev 2 Software ©2016: John Milner and Phil Charlesworth for StrongSoft®: All Rights Reserved...";
response += "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
response += "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
response += "</font></html>\n";
return response;
}
String web_page_scan() {
Serial.println("got to web_page_scan");
response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n<font size=\"4\">";
response += "<!DOCTYPE HTML>\r\n";
response += "<HTML>\r\n";
response += "<HEAD>\r\n";
response += "<meta name='viewport' content='width=device-width; initial-scale=0.8; maximum-scale=1.0; user-scalable=0;'/>";
response += "<meta name='apple-mobile-web-app-capable' content='yes'/>";
response += "<style type= 'text/css' >\r\n";
response += "body,td,th { font-family: Gotham, Helvetica, Arial, sans-serif; font-size: 14pt; color: #F9B600; -webkit-text-size-adjust: none;}";
response += "body { background-color: #000000; }";
response += "hr { height:0; border:0; border-top:1px solid #F9B600; }";
response += "</style>\r\n";
response +="<TITLE>UMMU Box Rev 2 WiFi Settings - Home</TITLE>\r\n";
response += "UMMU Box Rev 2 - software version ";
response += Version_UMMU;
response += ".";
response += Version_MSB;
response += ".";
response += Version_LSB;
response += "<hr>";
response += "Results of the Network Scan:";
response += "<br>";
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0)
response += "no networks found";
else
response += n;
response += " networks found (iOS - Rotate to Landscape for better formatting...)<br><br>";
for (int i = 0; i < n; ++i)
{
// Print SSID and RSSI for each network found
response += i + 1;
response += ": ";
response += WiFi.SSID(i);
response += ": Ch ";
response += WiFi.channel(i);
response += ": Strength: ";
response += WiFi.RSSI(i);
response += "<br>";
}
response += "<br>For best results pick a Channel that is unused or has a high negative signal strength value...";
response += "<br><br>Click <a href=\"/main\"><font color='#FFFF00'>here</a><font color='#F9B600'> to return to the main menu.";
response += "<br><br><br><font color='#555555'>UMMU Box Rev 2 Software ©2016: John Milner and Phil Charlesworth for StrongSoft®: All Rights Reserved...";
response += "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
response += "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>";
response += "</font></html>\n";
return response;
}
String web_page_error() {
response = "HTTP/1.1 404 \r\n";
}
void eeprom_channel_1() {
EEPROM.write(0, 1);
EEPROM.commit();
web_page_main();
}
void eeprom_channel_2() {
EEPROM.write(0, 6);
EEPROM.commit();
web_page_main();
}
void eeprom_channel_3() {
EEPROM.write(0, 0xb);
EEPROM.commit();
web_page_main();
}
void eeprom_channel_4() {
EEPROM.write(0, 0xe);
EEPROM.commit();
web_page_main();
}
void eeprom_SSID_1() {
EEPROM.write(1, 0);
EEPROM.commit();
web_page_main();
}
void eeprom_SSID_2() {
EEPROM.write(1, 1);
EEPROM.commit();
web_page_main();
}
//**************** END OF WEB PAGES / RESPONSES ****************
void setup() {
pinMode(ledReceive, OUTPUT);
pinMode(ledSend, OUTPUT);
pinMode(MIDI_EN, OUTPUT);
digitalWrite(MIDI_EN, HIGH);
WiFi.mode(WIFI_AP);
server.begin();
MIDI.begin(MIDI_CHANNEL_OMNI);
MIDI.setThruFilterMode(Off);
MIDI.setHandleSystemExclusive(HandleSysEx);
//MIDI.setHandleNoteOn(HandleNoteOn);
//MIDI.setHandleControlChange(HandleControlChange);
//MIDI.setHandleProgramChange(HandleProgramChange);
EEPROM.begin(1);
if (EEPROM.read(2) != EEPROM.read(1)) { // EEPROM(2) stores boot value ->
EEPROM.write(2, EEPROM.read(1)); // so we can check for changes
EEPROM.commit();
}
delay(100);
Serial.println("");
Serial.print("EEPROM 0 : ");
Serial.print(EEPROM.read(0));
Serial.print(", EEPROM 1 : ");
Serial.print(EEPROM.read(1));
Serial.print(", EEPROM 2 : ");
Serial.println(EEPROM.read(2));
// WiFi.mode(WIFI_AP);
//WiFi.softAP("ESPTEST", "11111111", 1, 0);
//WiFi.softAP("ESPTEST", "11111111", EEPROM.read(0),EEPROM.read(1));
String macID = WiFi.softAPmacAddress();
macID.remove(2, 1);
macID.remove(4, 1);
macID.remove(6, 1);
macID.remove(8, 1);
macID.remove(10, 1);
macID.remove(12, 1);
macID.toUpperCase();
AP_NameString = "UB-" + macID;
char charBuf[50];
AP_NameString.toCharArray(charBuf, 50);
macID.remove(0, 6);
macID.toLowerCase();
PW_String = "pw" + macID;
char passBuf[50];
PW_String.toCharArray(passBuf, 50);
server.begin();
WiFi.softAP(charBuf, passBuf, EEPROM.read(0),0);
Udp.begin(UDPPort);
Serial.begin(31250);
Serial.flush();
//Serial.println();
//Serial.println("Started Access Point - Local ip: 192.168.4.1");
delay(50);
digitalWrite(ledSend, HIGH);
delay(700);
digitalWrite(ledSend, LOW);
digitalWrite(ledReceive, HIGH);
delay(700);
digitalWrite(ledReceive, LOW);
digitalWrite(ledSend, HIGH);
delay(50);
digitalWrite(ledSend, LOW);
delay(50);
digitalWrite(ledSend, HIGH);
delay(50);
digitalWrite(ledSend, LOW);
delay(50);
digitalWrite(ledSend, HIGH);
delay(50);
digitalWrite(ledSend, LOW);
delay(50);
digitalWrite(ledSend, HIGH);
delay(50);
digitalWrite(ledSend, LOW);
delay(50);
digitalWrite(ledSend, HIGH);
delay(50);
digitalWrite(ledSend, LOW);
delay(50);
digitalWrite(ledSend, HIGH);
delay(50);
digitalWrite(ledSend, LOW);
delay(100);
digitalWrite(ledReceive, HIGH);
delay(50);
digitalWrite(ledReceive, LOW);
delay(50);
digitalWrite(ledReceive, HIGH);
delay(50);
digitalWrite(ledReceive, LOW);
delay(50);
digitalWrite(ledReceive, HIGH);
delay(50);
digitalWrite(ledReceive, LOW);
delay(50);
digitalWrite(ledReceive, HIGH);
delay(50);
digitalWrite(ledReceive, LOW);
delay(50);
digitalWrite(ledReceive, HIGH);
delay(50);
digitalWrite(ledReceive, LOW);
delay(50);
digitalWrite(ledReceive, HIGH);
delay(50);
digitalWrite(ledReceive, LOW);
delay(700);
for (int Flash = 0; Flash < 2; Flash++) { //Rev 2 UMMU Box...
digitalWrite(ledSend, HIGH);
digitalWrite(ledReceive, HIGH);
delay(200);
digitalWrite(ledSend, LOW);
digitalWrite(ledReceive, LOW);
delay(200);
}
delay(1400);
//number of flashes below = Rev Number...
for (int V = 0; V < Version_MSB; V++) {
digitalWrite(ledSend, HIGH);
delay(500);
digitalWrite(ledSend, LOW);
delay(500);
}
//End of Rev Number flashes...
//number of flashes below = Rev Number after decimal
for (int v = 0; v < Version_LSB; v++) {
digitalWrite(ledReceive, HIGH);
delay(500);
digitalWrite(ledReceive, LOW);
delay(500);
}
}
void loop() {
// Check for remote request.
WiFiClient client = server.available();
if (client) { // if client send the web page
Serial.println("we have a client");
String req = client.readStringUntil('\r');
// Serial.println(req);
client.flush();
if (req.indexOf("channel=1") != -1)
eeprom_channel_1();
else if (req.indexOf("channel=2") != -1)
eeprom_channel_2();
else if (req.indexOf("channel=3") != -1)
eeprom_channel_3();
else if (req.indexOf("channel=4") != -1)
eeprom_channel_4();
else if (req.indexOf("SSID=1") != -1)
eeprom_SSID_1();
else if (req.indexOf("SSID=2") != -1)
eeprom_SSID_2();
else if (req.indexOf("/main") != -1)
web_page_main();
else if (req.indexOf("/channel") != -1)
web_page_channel();
else if (req.indexOf("/scan") != -1)
web_page_scan();
else
web_page_error();
// Send the response to the client
// Serial.print(response);
client.print(response);
delay(100);
client.flush();
client.stop();
// Serial.println("Client disconnected");
}
MIDI.read();
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
digitalWrite(ledReceive, LOW);
digitalWrite(ledSend, LOW);
}
//Serial.flush();
String received_command = "";
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (packetSize) {
/*
Serial.print("Received packet of size ");
Serial.println(packetSize);
Serial.print("From ");
IPAddress remoteIp = Udp.remoteIP();
Serial.print(remoteIp);
Serial.print(", port ");
Serial.println(Udp.remotePort());
Serial.println("Local ip: 192.168.4.1");
*/
digitalWrite(ledSend, HIGH);
if (packetSize > 3) {
char packetBuffer[255]; //buffer to hold incoming packet
// read the packet into packetBufffer
Udp.read(packetBuffer, 255);
//if (len > 0) {
// packetBuffer[len] = 0;
// }
// Serial.println("Contents:");
MIDI.sendSysEx(packetSize, (byte*)packetBuffer, true);
/*
// send a reply, to the IP address and port that sent us the packet we received
Udp.beginPacket(Udp.remoteIP(), 9001);
Udp.write(ReplyBuffer);
Udp.endPacket();
*/
}
if (packetSize == 3) { //Note On/Off and Control Change
char packetBuffer[3]; //buffer to hold incoming packet,
// read the packet into packetBufffer
Udp.read(packetBuffer, 3);
MIDI.sendControlChange( packetBuffer[1], packetBuffer[2], packetBuffer[0] - 47 - 128);
MIDI.sendNoteOn( packetBuffer[1], packetBuffer[2], packetBuffer[0] - 143);
MIDI.sendNoteOff( packetBuffer[1], packetBuffer[2], packetBuffer[0] - 127);
}
if (packetSize == 2) { //Program Change
char packetBuffer[2]; //buffer to hold incoming packet,
// read the packet into packetBufffer
Udp.read(packetBuffer, 2);
MIDI.sendProgramChange(packetBuffer[1], packetBuffer[0] - 191);
}
}
}