1
0
mirror of https://github.com/s00500/ESPUI.git synced 2025-07-03 09:40:19 +00:00

25 Commits
1.0 ... 1.2

Author SHA1 Message Date
4be249e82b Bump version for release 2017-11-15 19:33:29 +01:00
114705e925 Experimenting with block programming 2017-11-14 15:47:55 +01:00
7e948c34fc codeformating 2017-11-14 12:14:59 +01:00
86132fe38d update example 2017-11-14 12:13:05 +01:00
6da6c3841b Color none, update example 2017-11-14 12:12:12 +01:00
fa45d9033b Color feature, and API changes 2017-11-14 12:09:52 +01:00
cca76c1389 Button text in example 2017-11-13 17:23:28 +01:00
b65b974ad0 Adding funny colors 2017-11-13 17:22:56 +01:00
6d206d21f9 send button value for button text 2017-11-13 17:22:02 +01:00
3c26def22a Updating example 2017-11-13 16:11:42 +01:00
0dc231bc9c Added possibility to update without ID 2017-11-13 16:10:56 +01:00
404bf89f60 removed src/HTML_PAGE.h 2017-11-13 15:06:48 +01:00
b895cc7fcc starting integrated data upload feature 2017-11-13 11:42:40 +01:00
47aaedfa9a more documentation refinements 2017-11-13 11:17:58 +01:00
d13d471bc6 Updating documentation 2017-11-13 11:02:15 +01:00
ef50e44a99 removing issue reference 2017-11-13 10:51:22 +01:00
ff11534b9d Merge branch 'master' of https://github.com/s00500/ESPUI 2017-10-23 12:21:03 +02:00
6f9f35c28e Fixing center Pad Button on touch devices 2017-10-23 12:20:54 +02:00
0f0162ad8b Versionbump 2017-10-20 12:40:48 +02:00
356f3d6edd More example mistakes
when stressed out...
2017-10-20 12:04:03 +02:00
436c700139 Version bump 2017-10-20 11:52:43 +02:00
929aa109e4 Update gui.ino
typo
2017-10-20 11:49:54 +02:00
4ee8b7e6b4 Update keywords.txt 2017-10-20 11:28:10 +02:00
912738198d Merge pull request #1 from per1234/keyword-separator
Use correct separator in keywords.txt
2017-10-20 11:25:51 +02:00
4b331eb096 Use correct separator in keywords.txt
The Arduino IDE requires the use of a tab separator between the name and identifier. Without this tab the keyword is not highlighted.

Reference: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords
2017-10-19 23:52:29 -07:00
18 changed files with 1322 additions and 848 deletions

View File

@ -1,6 +1,5 @@
# ESPUI
![ESPUI Controlpad](https://github.com/s00500/ESPUI/blob/master/docs/controlpad.png)
![ESPUI Switch](https://github.com/s00500/ESPUI/blob/master/docs/switch.png)
![ESPUI](https://github.com/s00500/ESPUI/blob/master/docs/ui_complete.png)
ESPUI is a simple library to make a web user interface for your projects using the **ESP32**
@ -14,6 +13,34 @@ I completely rewrote the EasyUI Library created by ayushsharma82 [Here](https://
Now it uses ESPAsyncWebserver and is mainly to be used with the ESP32 Processor.
ESP8266 support will be interesting maybe in the future.
## Dependencies
This library is dependent on the following libraries to function properly.
- [ESP32 Core Library](https://github.com/espressif/arduino-esp32)
- [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer)
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
## How to Install
Make sure all the dependencies are installed, then install like so:
#### Directly Through Arduino IDE
You can find this Library in the Arduino IDE library manager
Go to Sketch > Include Library > Library Manager > Search for "EasyUI" > Install
#### Manual Install
For Windows: Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip) and extract the .zip in Documents>Arduino>Libraries>{Place "ESPUI" folder Here}
For Linux: Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip) and extract the .zip in Sketchbook/Libraries/{Place "ESPUI" folder Here}
For macOs: Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip) and extract the .zip in ~/Documents/Arduino/libraries/{Place "ESPUI" folder Here}
#### Manually through IDE
Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip), Go to Sketch>Include Library>Add .zip Library> Select the Downloaded .zip File.
## Getting started (Filesystem upload)
ESPUI **NEEDS** its files burnt on the SPIFFS filesystem on the ESP. **Without this ESPUI will NOT work at all**
@ -23,35 +50,6 @@ To do this download and install me-no-devs wonderful [ESP32 sketch data uploader
Then open the example sketch and select "ESP32 Upload Sketch Data" from the Tools menu.
Now you are set to go and use any code you want to with this library
## How to Install
###### Directly Through Arduino IDE
THIS IS NOT DONE YET
~~Go to Sketch > Include Library > Library Manager > Search for "EasyUI" > Install~~
###### Manual Install
For Windows: Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip) and extract the .zip in Documents>Arduino>Libraries>{Place "ESPUI" folder Here}
For Linux: Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip) and extract the .zip in Sketchbook/Libraries/{Place "ESPUI" folder Here}
For macOs: Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip) and extract the .zip in ~/Documents/Arduino/libraries/{Place "ESPUI" folder Here}
###### Manually through IDE
Download the [Repository](https://github.com/s00500/ESPUI/archive/master.zip), Go to Sketch>Include Library>Add .zip Library> Select the Downloaded .zip File.
## Dependencies
This library is dependent on the following libraries to function properly.
- [ESP32 Core Library](https://github.com/espressif/arduino-esp32)
- [ESPAsyncWebserver](https://github.com/me-no-dev/ESPAsyncWebServer)
(There is still an open issue because there is a mistake in the current version that creates an error, please wait until that is done or checkout the [issue](https://github.com/me-no-dev/ESPAsyncWebServer/issues/234))
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
## User interface Elements
- Label (updateable)
- Button
@ -78,5 +76,42 @@ ESPUI's frontend is based on [Skeleton CSS](http://getskeleton.com/) and jQuery-
ESPUI does not need network access and can be used in standalone access point mode.
All assets are loaded from the internal SPIFFS filesystem of the ESP32.
This section will explain in detail how the Library is to be used from the Arduino code side. As of now the Facilino blocks are not implemented.
In the arduino setup() routine the interface can be customised by adding UI Elements. This is done by calling the corresponding library methods on the Library object ESPUI. Eg: ESPUI.button(“button”, &myCallback); creates a button in the interface that calls the “my-Callback” function when changed. All buttons and items call their callback whenever there is a state change from them. This means the button will call the callback when it is pressed and also again when it is released. To seperate different events an integer number with the event name is passed to the callback function that can be handled in a switch(){}case{} statement. Here is an overview of the currently implemented different elements of the UI library:
#### Button
![Buttons](https://github.com/s00500/ESPUI/blob/master/docs/ui_button.png)
Buttons have a name and a callback value. They have one event for press and one for release.
#### Switch
![Switches](https://github.com/s00500/ESPUI/blob/master/docs/ui_switches.png)
Switches sync their state on all connected devices. This means when you change their value they change visibly on all tablets or computers that currently display the interface. They also have two types of events: one for turning on and one for turning off.
#### Buttonpad
![control pads](https://github.com/s00500/ESPUI/blob/master/docs/ui_controlpad.png)
Button pads come in two flavours: with or without a center button. They are very useful for con-trolling all kinds of movements of vehicles or also of course our walking robots. They use a single callback per pad and have 8 or 10 different event types to differentiate the button actions.
#### Labels
![labels](https://github.com/s00500/ESPUI/blob/master/docs/ui_labels.png)
Labels are a nice tool to get information from the robot to the user interface. This can be done to show states, values of sensors and configuration parameters. To send data from the code use ESP.print(labelId, “Text”); . Labels get a name on creation and a initial value. The name is not changeable once the UI initialized.
#### Initialization of the UI
After all the elements are configured you can use ESPUI.begin(“Some Title”); to start the UI interface. The web interface can then be used from multiple devices at once and also shows an connection status in the top bar.
The library is designed to be easy to use and can still be extended with a lot of more functionality.
# Contribute
Liked this Library? You can Support me by sending me a :coffee: [Coffee](https://paypal.me/lukasbachschwell/3).
Liked this Library? You can **support** me by sending me a :coffee: [Coffee](https://paypal.me/lukasbachschwell/3).

176
blocks.js Normal file
View File

@ -0,0 +1,176 @@
// This is a block definition for projects like roboblocks
//
// Main Block
Blockly.Blocks['espui'] = {
category: Facilino.locales.getKey('LANG_CATEGORY_BLOCKS'),
helpUrl: Facilino.getHelpUrl('espui'),
tags: ['webinterface'],
examples: ['lol.bly'],
init: function() {
this.appendDummyInput()
.appendField('ESPUI Title:')
.appendField(new Blockly.FieldTextInput('string'), 'ui_name');
this.appendStatementInput('ui_elements')
.setCheck('ui_element');
this.setColour("#37d1f9");
this.setTooltip("Creates a webinterface on the ESP32");
}
};
Blockly.Arduino['espui'] = function(block) {
var ui_name = block.getFieldValue('ui_name');
var ui_elements = Blockly.Arduino.statementToCode(block, 'ui_elements');
Blockly.Arduino.definitions_['define_wifi_h'] = '#include <WiFi.h>';
Blockly.Arduino.definitions_['define_espui_h'] = '#include <ESPUI.h>';
Blockly.Arduino.setups_['setup_espui'] = ui_elements;
Blockly.Arduino.setups_['setup_espui'] += '\nESPUI.begin("' + ui_name + '");\n';
return null;
};
//Elements
Blockly.Blocks['espui_button'] = {
category: Facilino.locales.getKey('LANG_CATEGORY_BLOCKS'),
helpUrl: Facilino.getHelpUrl('espui'),
tags: ['webinterface'],
examples: ['lol.bly'],
init: function() {
var colorOptions = [
['none', 'COLOR_NONE'],
['turquoise', 'COLOR_TURQUOISE'],
['emerald', 'COLOR_EMERALD'],
['peterriver', 'COLOR_PETERRIVER'],
['wet asphalt', 'COLOR_WETASPHALT'],
['sunflower', 'COLOR_SUNFLOWER'],
['carrot', 'COLOR_CARROT'],
['alizarin', 'COLOR_ALIZARIN'],
];
this.appendDummyInput()
.appendField('ESPUI Button')
.appendField(new Blockly.FieldTextInput('name'), 'ui_name');
this.appendDummyInput()
.appendField('UI Color')
.appendField(new Blockly.FieldDropdown(colorOptions), 'ui_color');
this.setColour("#3357c7");
this.setPreviousStatement(true, 'ui_element');
this.setNextStatement(true, 'ui_element');
this.setTooltip('A web interface button');
this.appendStatementInput('on_down')
.appendField('Pressed:')
.setCheck(null);
this.appendStatementInput('on_up')
.appendField('Released:')
.setCheck(null);
}
};
Blockly.Arduino['espui_button'] = function(block) {
var ui_name = block.getFieldValue('ui_name');
var ui_color = block.getFieldValue('ui_color');
var ui_name_clean = ui_name.replace(' ', '_');
var on_down = Blockly.Arduino.statementToCode(block, 'on_down');
var on_up = Blockly.Arduino.statementToCode(block, 'on_up');
Blockly.Arduino.definitions_['define_ui_button_' + ui_name_clean] =
'void button_' + ui_name_clean + '(Control c, int type) {\nswitch(type){\ncase B_DOWN:\n' +
on_down + '\nbreak;\n' +
'case B_UP:\n' +
on_up + '\nbreak;\n' +
'}\n';
var code = 'ESPUI.button("' + ui_name + '",&button_' + ui_name_clean + ', ' + ui_color + ');\n';
return code;
};
Blockly.Blocks['espui_label'] = {
category: Facilino.locales.getKey('LANG_CATEGORY_BLOCKS'),
helpUrl: Facilino.getHelpUrl('espui'),
tags: ['webinterface'],
examples: ['lol.bly'],
init: function() {
var colorOptions = [
['none', 'COLOR_NONE'],
['turquoise', 'COLOR_TURQUOISE'],
['emerald', 'COLOR_EMERALD'],
['peterriver', 'COLOR_PETERRIVER'],
['wet asphalt', 'COLOR_WETASPHALT'],
['sunflower', 'COLOR_SUNFLOWER'],
['carrot', 'COLOR_CARROT'],
['alizarin', 'COLOR_ALIZARIN'],
];
this.appendDummyInput()
.appendField('ESPUI Label')
.appendField(new Blockly.FieldTextInput('label'), 'ui_name');
this.appendDummyInput()
.appendField('UI Color')
.appendField(new Blockly.FieldDropdown(colorOptions), 'ui_color');
this.appendDummyInput()
.appendField('Initial Value:')
.appendField(new Blockly.FieldTextInput('value'), 'start_value');
this.setColour("#3357c7");
this.setPreviousStatement(true, 'ui_element');
this.setNextStatement(true, 'ui_element');
this.setTooltip('A web interface label you can update from your code');
}
};
Blockly.Arduino['espui_label'] = function(block) {
var ui_name = block.getFieldValue('ui_name');
var ui_color = block.getFieldValue('ui_color');
var ui_name_clean = ui_name.replace(' ', '_');
var start_value = block.getFieldValue('start_value');
var code = 'ESPUI.label("' + ui_name + '", ' + ui_color + ', "' + start_value + '");\n';
return code;
};
Blockly.Blocks['espui_switcher'] = {
category: Facilino.locales.getKey('LANG_CATEGORY_BLOCKS'),
helpUrl: Facilino.getHelpUrl('espui'),
tags: ['webinterface'],
examples: ['lol.bly'],
init: function() {
var colorOptions = [
['none', 'COLOR_NONE'],
['turquoise', 'COLOR_TURQUOISE'],
['emerald', 'COLOR_EMERALD'],
['peterriver', 'COLOR_PETERRIVER'],
['wet asphalt', 'COLOR_WETASPHALT'],
['sunflower', 'COLOR_SUNFLOWER'],
['carrot', 'COLOR_CARROT'],
['alizarin', 'COLOR_ALIZARIN'],
];
this.appendDummyInput()
.appendField('ESPUI Switcher')
.appendField(new Blockly.FieldTextInput('name'), 'ui_name');
this.appendDummyInput()
.appendField('UI Color')
.appendField(new Blockly.FieldDropdown(colorOptions), 'ui_color');
this.setColour("#3357c7");
this.setPreviousStatement(true, 'ui_element');
this.setNextStatement(true, 'ui_element');
this.setTooltip('A web interface button');
this.appendStatementInput('on_on')
.appendField('When swithed on:')
.setCheck(null);
this.appendStatementInput('on_off')
.appendField('When swithed off:')
.setCheck(null);
}
};
Blockly.Arduino['espui_switcher'] = function(block) {
var ui_name = block.getFieldValue('ui_name');
var ui_color = block.getFieldValue('ui_color');
var ui_name_clean = ui_name.replace(' ', '_');
var on_on = Blockly.Arduino.statementToCode(block, 'on_down');
var on_off = Blockly.Arduino.statementToCode(block, 'on_up');
Blockly.Arduino.definitions_['define_ui_switcher_' + ui_name_clean] =
'void switcher_' + ui_name_clean + '(Control c, int type) {\nswitch(type){\ncase S_ACTIVE:\n' +
on_on + '\nbreak;\n' +
'case S_INACTIVE:\n' +
on_off + '\nbreak;\n' +
'}\n';
var code = 'ESPUI.switcher("' + ui_name + '",&switcher_' + ui_name_clean + ', ' + ui_color + ', false);\n';
return code;
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/ui_complete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

BIN
docs/ui_labels.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/ui_status.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/ui_switches.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Control</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAPFBMVEUAAACA1VWR21qQ2liR3FqR3FqS3VuR3VqR3VuR3VqO21mS21uS3FqS3FqS21uJ2GKQ21qR3FuR3FoAAAB/3Gu7AAAAEnRSTlMABoA3kPBwz8i5Kzioxg4NVcU3uEJHAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB+EFEhcEM+HpYwQAAABYSURBVBjThY/JDsAgCESt4lpX/v9jLQZJ6qF9t3khAyj1xXUKbQ4BVowDwqOYgExkkW4iY6lPaF06RqM8YItOuRbMaz6xjbsusDAW/drplBg47jP696cXE8bPA1eUDeK2AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTA1LTE4VDIzOjA0OjUxKzAyOjAwxE59ewAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wNS0xOFQyMzowNDo1MSswMjowMLUTxccAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC"/>
<link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body onload="javascript:start();">
<div><h4><div id="mainHeader">Control</div> <span id="conStatus" class="label">Offline</span></h4></div>
<hr />
<div class="container">
<div id="row" class="row u-full-width">
</div>
</div>
<script src="/js/zepto.js"></script>
<script src="/js/controls.js"></script>
</body>
<head>
<meta charset="utf-8">
<title>Control</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAPFBMVEUAAACA1VWR21qQ2liR3FqR3FqS3VuR3VqR3VuR3VqO21mS21uS3FqS3FqS21uJ2GKQ21qR3FuR3FoAAAB/3Gu7AAAAEnRSTlMABoA3kPBwz8i5Kzioxg4NVcU3uEJHAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB+EFEhcEM+HpYwQAAABYSURBVBjThY/JDsAgCESt4lpX/v9jLQZJ6qF9t3khAyj1xXUKbQ4BVowDwqOYgExkkW4iY6lPaF06RqM8YItOuRbMaz6xjbsusDAW/drplBg47jP696cXE8bPA1eUDeK2AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTA1LTE4VDIzOjA0OjUxKzAyOjAwxE59ewAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wNS0xOFQyMzowNDo1MSswMjowMLUTxccAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC"
/>
<link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body onload="javascript:start();">
<div>
<h4><div id="mainHeader">Control</div> <span id="conStatus" class="label">Offline</span></h4></div>
<hr />
<div class="container">
<div id="row" class="row u-full-width">
</div>
</div>
<script src="/js/zepto.js"></script>
<script src="/js/controls.js"></script>
</body>
</html>

View File

@ -13,150 +13,260 @@ const LEFT = 2;
const RIGHT = 3;
const CENTER = 4;
// Colors
const C_TURQUOISE = 0;
const C_EMERALD = 1;
const C_PETERRIVER = 2;
const C_WETASPHALT = 3;
const C_SUNFLOWER = 4;
const C_CARROT = 5;
const C_ALIZARIN = 6;
const C_NONE = 7;
function colorClass(colorId) {
colorId = Number(colorId);
switch (colorId) {
case C_TURQUOISE:
return "turquoise";
break;
case C_EMERALD:
return "emerald";
break;
case C_PETERRIVER:
return "peterriver";
break;
case C_WETASPHALT:
return "wetasphalt";
break;
case C_SUNFLOWER:
return "sunflower";
break;
case C_CARROT:
return "carrot"
break;
case C_ALIZARIN:
return "alizarin"
break;
case C_NONE:
return ""
break;
default:
return "";
}
}
var websock;
function start() {
websock = new WebSocket('ws://' + window.location.hostname + '/ws');
websock.onopen = function(evt) {
console.log('websock open');
$("#conStatus").addClass("color-green");
$("#conStatus").text("Connected");
};
websock.onclose = function(evt) {
console.log('websock close');
$("#conStatus").removeClass("color-green");
$("#conStatus").addClass("color-red");
$("#conStatus").text("Error / No Connection");
};
websock.onerror = function(evt) {
console.log(evt);
$("#conStatus").removeClass("color-green");
$("#conStatus").addClass("color-red");
$("#conStatus").text("Error / No Connection");
};
websock.onmessage = function(evt) {
console.log(evt);
var data = JSON.parse(evt.data);
var e = document.body;
var center = "";
switch(data.type){
case UI_TITEL:
document.title = data.label;
$('#mainHeader').html(data.label);
break;
case UI_LABEL:
$('#row').append("<div class='two columns card'><h5 id='"+data.id+"'>"+data.label+"</h5><hr /><span id='l"+data.id+"' class='label'>"+data.value+"</span></div>");
break;
case UI_BUTTON:
$('#row').append("<div class='two columns card'><h5>"+data.label+"</h5><hr/><button onmousedown='buttonclick("+data.id+", true)' onmouseup='buttonclick("+data.id+", false)' id='"+data.id+"'></button></div>");
$('#'+data.id).on({ 'touchstart' : function(e){e.preventDefault(); buttonclick(data.id, true) } });
$('#'+data.id).on({ 'touchend' : function(e){e.preventDefault(); buttonclick(data.id, false) } });
break;
case UI_SWITCHER:
var label = "<label id='sl"+data.id+"' class='switch checked'>";
var input = "<input type='checkbox' id='s"+data.id+"' onClick='switcher("+data.id+",null)' checked>";
if(data.value == "0"){
label = "<label id='sl"+data.id+"' class='switch'>";
input = "<input type='checkbox' id='s"+data.id+"' onClick='switcher("+data.id+",null)' >";
}
$('#row').append(
"<div id='"+data.id+"' class='two columns card'><h5>"+data.label+"</h5><hr/>" +
label + "<i class='icon-ok'></i>" +
"<i class='icon-remove'></i>" + input +
"</label>" +
"</div>");
break;
case UI_CPAD:
center = "<a class='confirm' onmousedown='padclick(CENTER, "+data.id+", true)' onmouseup='padclick(CENTER, "+data.id+", false)' href='#' id='c"+data.id+"'>OK</a>";
//NO BREAK
case UI_PAD:
$('#row').append(
"<div class='two columns card'><h5>"+data.label+"</h5><hr/>"+
"<nav class='control'>"+
"<ul>"+
"<li><a onmousedown='padclick(FOR, "+data.id+", true)' onmouseup='padclick(FOR, "+data.id+", false)' href='#' id='pf"+data.id+"'>▲</a></li>" +
"<li><a onmousedown='padclick(RIGHT, "+data.id+", true)' onmouseup='padclick(RIGHT, "+data.id+", false)' href='#' id='pr"+data.id+"'>▲</a></li>" +
"<li><a onmousedown='padclick(LEFT, "+data.id+", true)' onmouseup='padclick(LEFT, "+data.id+", false)' href='#' id='pl"+data.id+"'>▲</a></li>" +
"<li><a onmousedown='padclick(BACK, "+data.id+", true)' onmouseup='padclick(BACK, "+data.id+", false)' href='#' id='pb"+data.id+"'></a></li>" +
"</ul>"+
center +
"</nav>"+
"</div>");
websock = new WebSocket('ws://' + window.location.hostname + '/ws');
websock.onopen = function(evt) {
console.log('websock open');
$("#conStatus").addClass("color-green");
$("#conStatus").text("Connected");
};
websock.onclose = function(evt) {
console.log('websock close');
$("#conStatus").removeClass("color-green");
$("#conStatus").addClass("color-red");
$("#conStatus").text("Error / No Connection");
};
websock.onerror = function(evt) {
console.log(evt);
$("#conStatus").removeClass("color-green");
$("#conStatus").addClass("color-red");
$("#conStatus").text("Error / No Connection");
};
websock.onmessage = function(evt) {
console.log(evt);
var data = JSON.parse(evt.data);
var e = document.body;
var center = "";
switch (data.type) {
case UI_TITEL:
document.title = data.label;
$('#mainHeader').html(data.label);
break;
case UI_LABEL:
$('#row').append("<div class='two columns card tcenter " + colorClass(data.color) + "'><h5 id='" + data.id + "'>" + data.label + "</h5><hr /><span id='l" + data.id + "' class='label'>" + data.value + "</span></div>");
break;
case UI_BUTTON:
$('#row').append("<div class='one columns card tcenter " + colorClass(data.color) + "'><h5>" + data.label + "</h5><hr/><button onmousedown='buttonclick(" + data.id + ", true)' onmouseup='buttonclick(" + data.id + ", false)' id='" + data.id + "'>" + data.value + "</button></div>");
$('#' + data.id).on({
'touchstart': function(e) {
e.preventDefault();
buttonclick(data.id, true)
}
});
$('#' + data.id).on({
'touchend': function(e) {
e.preventDefault();
buttonclick(data.id, false)
}
});
break;
case UI_SWITCHER:
var label = "<label id='sl" + data.id + "' class='switch checked'>";
var input = "<input type='checkbox' id='s" + data.id + "' onClick='switcher(" + data.id + ",null)' checked>";
if (data.value == "0") {
label = "<label id='sl" + data.id + "' class='switch'>";
input = "<input type='checkbox' id='s" + data.id + "' onClick='switcher(" + data.id + ",null)' >";
}
$('#row').append(
"<div id='" + data.id + "' class='one columns card tcenter " + colorClass(data.color) + "'><h5>" + data.label + "</h5><hr/>" +
label + "<i class='icon-ok'></i>" +
"<i class='icon-remove'></i>" + input +
"</label>" +
"</div>");
break;
case UI_CPAD:
center = "<a class='confirm' onmousedown='padclick(CENTER, " + data.id + ", true)' onmouseup='padclick(CENTER, " + data.id + ", false)' href='#' id='pc" + data.id + "'>OK</a>";
//NO BREAK
case UI_PAD:
$('#row').append(
"<div class='two columns card tcenter " + colorClass(data.color) + "'><h5>" + data.label + "</h5><hr/>" +
"<nav class='control'>" +
"<ul>" +
"<li><a onmousedown='padclick(FOR, " + data.id + ", true)' onmouseup='padclick(FOR, " + data.id + ", false)' href='#' id='pf" + data.id + "'>▲</a></li>" +
"<li><a onmousedown='padclick(RIGHT, " + data.id + ", true)' onmouseup='padclick(RIGHT, " + data.id + ", false)' href='#' id='pr" + data.id + "'>▲</a></li>" +
"<li><a onmousedown='padclick(LEFT, " + data.id + ", true)' onmouseup='padclick(LEFT, " + data.id + ", false)' href='#' id='pl" + data.id + "'>▲</a></li>" +
"<li><a onmousedown='padclick(BACK, " + data.id + ", true)' onmouseup='padclick(BACK, " + data.id + ", false)' href='#' id='pb" + data.id + "'>▲</a></li>" +
"</ul>" +
center +
"</nav>" +
"</div>");
$('#pf'+data.id).on({ 'touchstart' : function(e){e.preventDefault(); padclick(FOR, data.id, true) } });
$('#pf'+data.id).on({ 'touchend' : function(e){e.preventDefault(); padclick(FOR, data.id, false) } });
$('#pl'+data.id).on({ 'touchstart' : function(e){e.preventDefault(); padclick(LEFT, data.id, true) } });
$('#pl'+data.id).on({ 'touchend' : function(e){e.preventDefault(); padclick(LEFT, data.id, false) } });
$('#pr'+data.id).on({ 'touchstart' : function(e){e.preventDefault(); padclick(RIGHT, data.id, true) } });
$('#pr'+data.id).on({ 'touchend' : function(e){e.preventDefault(); padclick(RIGHT, data.id, false) } });
$('#pb'+data.id).on({ 'touchstart' : function(e){e.preventDefault(); padclick(BACK, data.id, true) } });
$('#pb'+data.id).on({ 'touchend' : function(e){e.preventDefault(); padclick(BACK,data.id, false) } });
$('#pc'+data.id).on({ 'touchstart' : function(e){e.preventDefault(); padclick(CENTER, data.id, true) } });
$('#pc'+data.id).on({ 'touchend' : function(e){e.preventDefault(); padclick(CENTER,data.id, false) } });
$('#pf' + data.id).on({
'touchstart': function(e) {
e.preventDefault();
padclick(FOR, data.id, true)
}
});
$('#pf' + data.id).on({
'touchend': function(e) {
e.preventDefault();
padclick(FOR, data.id, false)
}
});
$('#pl' + data.id).on({
'touchstart': function(e) {
e.preventDefault();
padclick(LEFT, data.id, true)
}
});
$('#pl' + data.id).on({
'touchend': function(e) {
e.preventDefault();
padclick(LEFT, data.id, false)
}
});
$('#pr' + data.id).on({
'touchstart': function(e) {
e.preventDefault();
padclick(RIGHT, data.id, true)
}
});
$('#pr' + data.id).on({
'touchend': function(e) {
e.preventDefault();
padclick(RIGHT, data.id, false)
}
});
$('#pb' + data.id).on({
'touchstart': function(e) {
e.preventDefault();
padclick(BACK, data.id, true)
}
});
$('#pb' + data.id).on({
'touchend': function(e) {
e.preventDefault();
padclick(BACK, data.id, false)
}
});
$('#pc' + data.id).on({
'touchstart': function(e) {
e.preventDefault();
padclick(CENTER, data.id, true)
}
});
$('#pc' + data.id).on({
'touchend': function(e) {
e.preventDefault();
padclick(CENTER, data.id, false)
}
});
break;
case UPDATE_LABEL:
$('#l'+data.id).html(data.value);
break;
case UPDATE_SWITCHER:
if(data.value == "0")
switcher(data.id, 0);
else
switcher(data.id, 1);
break;
default:
console.error('Unknown type or event');
break;
}
};
break;
case UPDATE_LABEL:
$('#l' + data.id).html(data.value);
break;
case UPDATE_SWITCHER:
if (data.value == "0")
switcher(data.id, 0);
else
switcher(data.id, 1);
break;
default:
console.error('Unknown type or event');
break;
}
};
}
function buttonclick(number, isdown) {
if(isdown)websock.send("bdown:"+number);
else websock.send("bup:"+number);
if (isdown) websock.send("bdown:" + number);
else websock.send("bup:" + number);
}
function padclick(type, number, isdown) {
switch(type){
case CENTER:
if(isdown)websock.send("pcdown:"+number);
else websock.send("pcup:"+number);
break;
case FOR:
if(isdown)websock.send("pfdown:"+number);
else websock.send("pfup:"+number);
break;
case BACK:
if(isdown)websock.send("pbdown:"+number);
else websock.send("pbup:"+number);
break;
case LEFT:
if(isdown)websock.send("pldown:"+number);
else websock.send("plup:"+number);
break;
case RIGHT:
if(isdown)websock.send("prdown:"+number);
else websock.send("prup:"+number);
break;
switch (type) {
case CENTER:
if (isdown) websock.send("pcdown:" + number);
else websock.send("pcup:" + number);
break;
case FOR:
if (isdown) websock.send("pfdown:" + number);
else websock.send("pfup:" + number);
break;
case BACK:
if (isdown) websock.send("pbdown:" + number);
else websock.send("pbup:" + number);
break;
case LEFT:
if (isdown) websock.send("pldown:" + number);
else websock.send("plup:" + number);
break;
case RIGHT:
if (isdown) websock.send("prdown:" + number);
else websock.send("prup:" + number);
break;
}
}
function switcher(number, state){
if(state == null){
if($('#s'+number).is(':checked')){
websock.send("sactive:"+number);
$('#sl'+number).addClass('checked');
}else {
websock.send("sinactive:"+number);
$('#sl'+number).removeClass('checked');
}
}else if(state == 1){
$('#sl'+number).addClass('checked');
$('#sl'+number).prop( "checked", true );
}else if(state == 0){
$('#sl'+number).removeClass('checked');
$('#sl'+number).prop( "checked", false );
}
}
function switcher(number, state) {
if (state == null) {
if ($('#s' + number).is(':checked')) {
websock.send("sactive:" + number);
$('#sl' + number).addClass('checked');
} else {
websock.send("sinactive:" + number);
$('#sl' + number).removeClass('checked');
}
} else if (state == 1) {
$('#sl' + number).addClass('checked');
$('#sl' + number).prop("checked", true);
} else if (state == 0) {
$('#sl' + number).removeClass('checked');
$('#sl' + number).prop("checked", false);
}
}

View File

@ -1,17 +1,18 @@
#include <ESPUI.h>
#include <WiFi.h>
#include <EasyUI.h>
const char* ssid = "ESP32";
const char* password = "";
const char *ssid = "ESP32";
const char *password = "";
long oldTime = 0;
bool switchi = false;
void setup(void) {
Serial.begin(115200);
WiFi.mode(WIFI_AP);
WiFi.setHostname(ssid);
WiFi.softAP(ssid);
//WiFi.softAP(ssid, password);
// WiFi.softAP(ssid, password);
Serial.println("");
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
@ -31,109 +32,109 @@ void setup(void) {
Serial.println(WiFi.localIP());
*/
EasyUI.label("Status: Stop");
EasyUI.label("0");
EasyUI.button("Push Button", &buttonCallback);
EasyUI.button("Push Button", &buttonExample);
EasyUI.pad("center", true, &padExample);
EasyUI.pad("NoCenter", false, &padExample);
EasyUI.switcher("Switch one", false, &switchExample);
EasyUI.switcher("Switch two", true, &otherSwitchExample);
EasyUI.begin("ESP32 Control");
ESPUI.label("Status:", COLOR_TURQUOISE, "Stop");
ESPUI.label("Millis:", COLOR_EMERALD, "0");
ESPUI.button("Push Button", &buttonCallback, COLOR_PETERRIVER);
ESPUI.button("Other Button", &buttonExample, COLOR_WETASPHALT, "Press");
ESPUI.pad("Pad with center", true, &padExample, COLOR_SUNFLOWER);
ESPUI.pad("Pad without center", false, &padExample, COLOR_CARROT);
ESPUI.switcher("Switch one", false, &switchExample, COLOR_ALIZARIN);
ESPUI.switcher("Switch two", true, &otherSwitchExample, COLOR_NONE);
ESPUI.begin("ESP32 Control");
}
void loop(void) {
if (millis() - oldTime > 5000) {
EasyUI.print(1, String(millis()));
ESPUI.print("Millis:", String(millis()));
switchi = !switchi;
ESPUI.updateSwitcher("Switch one", switchi);
oldTime = millis();
}
}
void buttonCallback(int id, int type) {
void buttonCallback(Control sender, int type) {
switch (type) {
case B_DOWN:
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println("Button UP");
break;
case B_DOWN:
Serial.println("Button DOWN");
break;
case B_UP:
Serial.println("Button UP");
break;
}
}
void buttonExample(int id, int type) {
void buttonExample(Control sender, int type) {
switch (type) {
case B_DOWN:
Serial.println("Status: Start");
EasyUI.print(0, "Status: Start");
break;
case B_UP:
Serial.println("Status: Stop");
EasyUI.print(0, "Status: Stop");
break;
case B_DOWN:
Serial.println("Status: Start");
ESPUI.print(0, "Status: Start");
break;
case B_UP:
Serial.println("Status: Stop");
ESPUI.print(0, "Status: Stop");
break;
}
}
void padExample(int id, int value) {
void padExample(Control sender, int value) {
switch (value) {
case P_LEFT_DOWN:
Serial.print("left down");
break;
case P_LEFT_UP:
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print("center up");
break;
case P_LEFT_DOWN:
Serial.print("left down");
break;
case P_LEFT_UP:
Serial.print("left up");
break;
case P_RIGHT_DOWN:
Serial.print("right down");
break;
case P_RIGHT_UP:
Serial.print("right up");
break;
case P_FOR_DOWN:
Serial.print("for down");
break;
case P_FOR_UP:
Serial.print("for up");
break;
case P_BACK_DOWN:
Serial.print("back down");
break;
case P_BACK_UP:
Serial.print("back up");
break;
case P_CENTER_DOWN:
Serial.print("center down");
break;
case P_CENTER_UP:
Serial.print("center up");
break;
}
Serial.print(" ");
Serial.println(id);
Serial.println(sender.id);
}
void switchExample(int id, int value) {
void switchExample(Control sender, int value) {
switch (value) {
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(id);
Serial.println(sender.id);
}
void otherSwitchExample(int id, int value) {
void otherSwitchExample(Control sender, int value) {
switch (value) {
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
case S_ACTIVE:
Serial.print("Active:");
break;
case S_INACTIVE:
Serial.print("Inactive");
break;
}
Serial.print(" ");
Serial.println(id);
Serial.println(sender.id);
}

View File

@ -1,8 +1,10 @@
EasyUI KEYWORD1
ESPUI KEYWORD1
detectCDN KEYWORD2
title KEYWORD2
begin KEYWORD2
label KEYWORD2
toggleButton KEYWORD2
loop KEYWORD2
label KEYWORD2
button KEYWORD2
switcher KEYWORD2
pad KEYWORD2
begin KEYWORD2
print KEYWORD2
updateSwitcher KEYWORD2

View File

@ -1,5 +1,5 @@
name=ESPUI
version=1.0
version=1.2.0
author=Lukas Bachschwell
maintainer=Lukas Bachschwell <lukas@lbsfilm.at>
sentence=ESP32 Web Interface Library

View File

@ -3,144 +3,248 @@
#include <functional>
// Handle Websockets Communication
void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
switch(type) {
case WS_EVT_DISCONNECT:
Serial.printf("Disconnected!\n");
break;
case WS_EVT_CONNECT:
{
Serial.println("Connected");
ESPUI.jsonDom(client);
Serial.println("JSON Data Sent to Client!");
}
break;
case WS_EVT_DATA:
String msg = "";
for (size_t i = 0; i < len; i++) {
msg += (char) data[i];
}
if(msg.startsWith("bdown:")){
ESPUI.controls[msg.substring(6).toInt()]->callback(msg.substring(6).toInt(), B_DOWN);
}else if(msg.startsWith("bup:")){
ESPUI.controls[msg.substring(4).toInt()]->callback(msg.substring(4).toInt(), B_UP);
}else if(msg.startsWith("pfdown:")){
ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_FOR_DOWN);
}else if(msg.startsWith("pfup:")){
ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_FOR_UP);
}else if(msg.startsWith("pldown:")){
ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_LEFT_DOWN);
}else if(msg.startsWith("plup:")){
ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_LEFT_UP);
}else if(msg.startsWith("prdown:")){
ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_RIGHT_DOWN);
}else if(msg.startsWith("prup:")){
ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_RIGHT_UP);
}else if(msg.startsWith("pbdown:")){
ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_BACK_DOWN);
}else if(msg.startsWith("pbup:")){
ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_BACK_UP);
}else if(msg.startsWith("pcdown:")){
ESPUI.controls[msg.substring(7).toInt()]->callback(msg.substring(7).toInt(), P_CENTER_DOWN);
}else if(msg.startsWith("pcup:")){
ESPUI.controls[msg.substring(5).toInt()]->callback(msg.substring(5).toInt(), P_CENTER_UP);
}else if(msg.startsWith("sactive:")){
ESPUI.updateSwitcher(msg.substring(8).toInt(), true);
ESPUI.controls[msg.substring(8).toInt()]->callback(msg.substring(8).toInt(), S_ACTIVE);
}else if(msg.startsWith("sinactive:")){
ESPUI.updateSwitcher(msg.substring(10).toInt(), false);
ESPUI.controls[msg.substring(10).toInt()]->callback(msg.substring(10).toInt(), S_INACTIVE);
}
break;
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_DISCONNECT:
if (debug)
Serial.printf("Disconnected!\n");
break;
case WS_EVT_CONNECT: {
if (debug)
Serial.println("Connected");
ESPUI.jsonDom(client);
if (debug)
Serial.println("JSON Data Sent to Client!");
} break;
case WS_EVT_DATA:
String msg = "";
for (size_t i = 0; i < len; i++) {
msg += (char)data[i];
}
if (msg.startsWith("bdown:")) {
Control *c = ESPUI.controls[msg.substring(6).toInt()];
c->callback(*c, B_DOWN);
} else if (msg.startsWith("bup:")) {
Control *c = ESPUI.controls[msg.substring(4).toInt()];
c->callback(*c, B_UP);
} else if (msg.startsWith("pfdown:")) {
Control *c = ESPUI.controls[msg.substring(7).toInt()];
c->callback(*c, P_FOR_DOWN);
} else if (msg.startsWith("pfup:")) {
Control *c = ESPUI.controls[msg.substring(5).toInt()];
c->callback(*c, P_FOR_UP);
} else if (msg.startsWith("pldown:")) {
Control *c = ESPUI.controls[msg.substring(7).toInt()];
c->callback(*c, P_LEFT_DOWN);
} else if (msg.startsWith("plup:")) {
Control *c = ESPUI.controls[msg.substring(5).toInt()];
c->callback(*c, P_LEFT_UP);
} else if (msg.startsWith("prdown:")) {
Control *c = ESPUI.controls[msg.substring(7).toInt()];
c->callback(*c, P_RIGHT_DOWN);
} else if (msg.startsWith("prup:")) {
Control *c = ESPUI.controls[msg.substring(5).toInt()];
c->callback(*c, P_RIGHT_UP);
} else if (msg.startsWith("pbdown:")) {
Control *c = ESPUI.controls[msg.substring(7).toInt()];
c->callback(*c, P_BACK_DOWN);
} else if (msg.startsWith("pbup:")) {
Control *c = ESPUI.controls[msg.substring(5).toInt()];
c->callback(*c, P_BACK_UP);
} else if (msg.startsWith("pcdown:")) {
Control *c = ESPUI.controls[msg.substring(7).toInt()];
c->callback(*c, P_CENTER_DOWN);
} else if (msg.startsWith("pcup:")) {
Control *c = ESPUI.controls[msg.substring(5).toInt()];
c->callback(*c, P_CENTER_UP);
} else if (msg.startsWith("sactive:")) {
Control *c = ESPUI.controls[msg.substring(8).toInt()];
ESPUI.updateSwitcher(c->id, true);
c->callback(*c, S_ACTIVE);
} else if (msg.startsWith("sinactive:")) {
Control *c = ESPUI.controls[msg.substring(10).toInt()];
ESPUI.updateSwitcher(c->id, false);
c->callback(*c, S_INACTIVE);
}
break;
}
}
void ESPUIClass::label(const char* label, String value){
Control* newL = new Control();
void ESPUIClass::label(const char *label, int color, String value) {
if (labelExists(label)) {
if (debug)
Serial.println("UI ERROR: Element " + String(label) +
" exists, skipping creating element!");
return;
}
Control *newL = new Control();
newL->type = UI_LABEL;
newL->label = label;
if(value != "") newL->value = value; // Init with labeltext
else newL->value = String(label);
newL->color = color;
if (value != "")
newL->value = value; // Init with labeltext
else
newL->value = String(label);
newL->callback = NULL;
newL->id = cIndex;
controls[cIndex] = newL;
cIndex++;
}
void ESPUIClass::button(const char* label, void(* callBack)(int, int)){
Control* newB = new Control();
void ESPUIClass::button(const char *label, void (*callBack)(Control, int),
int color, String value) {
if (labelExists(label)) {
if (debug)
Serial.println("UI ERROR: Element " + String(label) +
" exists, skipping creating element!");
return;
}
Control *newB = new Control();
newB->type = UI_BUTTON;
newB->label = label;
newB->color = color;
if (value != "")
newB->value = value; // Init with labeltext
else
newB->value = String(label);
newB->callback = callBack;
newB->id = cIndex;
controls[cIndex] = newB;
cIndex++;
}
void ESPUIClass::switcher(const char* label, bool startState, void(* callBack)(int, int)){
Control* newS = new Control();
void ESPUIClass::switcher(const char *label, bool startState,
void (*callBack)(Control, int), int color) {
if (labelExists(label)) {
if (debug)
Serial.println("UI ERROR: Element " + String(label) +
" exists, skipping creating element!");
return;
}
Control *newS = new Control();
newS->type = UI_SWITCHER;
newS->label = label;
newS->color = color;
newS->value = String(startState);
newS->callback = callBack;
newS->id = cIndex;
controls[cIndex] = newS;
cIndex++;
}
void ESPUIClass::pad(const char* label, bool center, void(* callBack)(int, int)){
Control* newP = new Control();
if(center)newP->type = UI_CPAD;
else newP->type = UI_PAD;
void ESPUIClass::pad(const char *label, bool center,
void (*callBack)(Control, int), int color) {
if (labelExists(label)) {
if (debug)
Serial.println("UI ERROR: Element " + String(label) +
" exists, skipping creating element!");
return;
}
Control *newP = new Control();
if (center)
newP->type = UI_CPAD;
else
newP->type = UI_PAD;
newP->label = label;
newP->color = color;
newP->callback = callBack;
newP->id = cIndex;
controls[cIndex] = newP;
cIndex++;
}
void ESPUIClass::print(int id, String value){
if(id<cIndex && controls[id]->type == UI_LABEL){
void ESPUIClass::print(int id, String value) {
if (id < cIndex && controls[id]->type == UI_LABEL) {
controls[id]->value = value;
String json;
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
JsonObject &root = jsonBuffer.createObject();
root["type"] = UPDATE_LABEL;
root["value"] = value;
root["id"] = String(id);
root.printTo(json);
this->ws->textAll(json);
}else{
Serial.println(String("Error: ")+ String(id) +String(" is no label"));
} else {
if (debug)
Serial.println(String("Error: ") + String(id) + String(" is no label"));
}
}
void ESPUIClass::updateSwitcher(int id, bool nValue){
if(id<cIndex && controls[id]->type == UI_SWITCHER){
controls[id]->value = nValue?1:0;
void ESPUIClass::print(String label, String value) {
if (!labelExists(label)) {
if (debug)
Serial.println("UI ERROR: Element does not " + String(label) +
" exist, cannot update!");
return;
}
print(getIdByLabel(label), value);
}
void ESPUIClass::updateSwitcher(int id, bool nValue) {
if (id < cIndex && controls[id]->type == UI_SWITCHER) {
controls[id]->value = nValue ? 1 : 0;
String json;
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
JsonObject &root = jsonBuffer.createObject();
root["type"] = UPDATE_SWITCH;
root["value"] = nValue?1:0;
root["value"] = nValue ? 1 : 0;
root["id"] = String(id);
root.printTo(json);
this->ws->textAll(json);
}else{
Serial.println(String("Error: ")+ String(id) +String(" is no switcher"));
} else {
if (debug)
Serial.println(String("Error: ") + String(id) +
String(" is no switcher"));
}
}
void ESPUIClass::updateSwitcher(String label, bool nValue) {
if (!labelExists(label)) {
if (debug)
Serial.println("UI ERROR: Element does not " + String(label) +
" exist, cannot update!");
return;
}
updateSwitcher(getIdByLabel(label), nValue);
}
int ESPUIClass::getIdByLabel(String label) {
for (int i = 0; i < cIndex; i++) {
if (String(controls[i]->label) == label)
return i;
}
return -1; // failed, nonexistant
}
bool ESPUIClass::labelExists(String label) {
for (int i = 0; i < cIndex; i++) {
if (String(controls[i]->label) == label)
return true;
}
return false;
}
// Convert & Transfer Arduino elements to JSON elements
void ESPUIClass::jsonDom(AsyncWebSocketClient * client){
for(int i=-1; i<cIndex; i++){
void ESPUIClass::jsonDom(AsyncWebSocketClient *client) {
for (int i = -1; i < cIndex; i++) {
String json;
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
if(i == -1){
JsonObject &root = jsonBuffer.createObject();
if (i == -1) {
root["type"] = UI_TITEL;
root["label"] = String(ui_title);
}else{
} else {
root["type"] = controls[i]->type;
root["label"] = String(controls[i]->label);
root["value"] = String(controls[i]->value);
root["color"] = String(controls[i]->color);
root["id"] = String(i);
}
root.printTo(json);
@ -148,8 +252,7 @@ void ESPUIClass::jsonDom(AsyncWebSocketClient * client){
}
}
void ESPUIClass::begin(const char * _title){
void ESPUIClass::begin(const char *_title) {
ui_title = _title;
server = new AsyncWebServer(80);
ws = new AsyncWebSocket("/ws");
@ -158,17 +261,17 @@ void ESPUIClass::begin(const char * _title){
server->addHandler(ws);
server->serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm");
//Heap for general Servertest
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
// Heap for general Servertest
server->on("/heap", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", String(ESP.getFreeHeap()));
});
server->onNotFound([](AsyncWebServerRequest *request){
request->send(404);
});
server->onNotFound(
[](AsyncWebServerRequest *request) { request->send(404); });
server->begin();
Serial.println("UI Initialized");
if (debug)
Serial.println("UI Initialized");
}
ESPUIClass ESPUI;

View File

@ -3,25 +3,28 @@
#define HARDWARE "esp32"
//ifdef 8266
#define debug true
// ifdef 8266
//#include "Hash.h"
#include "Arduino.h"
#include "stdlib_noniso.h"
#include "ArduinoJson.h"
#include "FS.h"
#include "SPIFFS.h"
#include "WiFi.h"
#include "stdlib_noniso.h"
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
typedef struct Control
{
unsigned int type;
const char *label;
void (*callback)(int, int);
String value;
typedef struct Control {
unsigned int type;
unsigned int id; // just mirroring the id here for practical reasons
const char *label;
void (*callback)(Control, int);
String value;
unsigned int color;
} Control;
// Types
@ -36,7 +39,7 @@ typedef struct Control
// Values
#define B_DOWN -1
#define B_UP 1
#define B_UP 1
#define P_LEFT_DOWN -2
#define P_LEFT_UP 2
@ -52,31 +55,50 @@ typedef struct Control
#define S_INACTIVE 7
// Colors
#define COLOR_TURQUOISE 0
#define COLOR_EMERALD 1
#define COLOR_PETERRIVER 2
#define COLOR_WETASPHALT 3
#define COLOR_SUNFLOWER 4
#define COLOR_CARROT 5
#define COLOR_ALIZARIN 6
#define COLOR_NONE 6
class ESPUIClass{
class ESPUIClass {
public:
void begin(const char* _title); // Setup servers and page
void begin(const char *_title); // Setup servers and page
// Creating Elements
void label(const char* label, String value = ""); // Create Label
void button(const char* label, void(* callBack)(int, int)); // Create Event Button
void switcher(const char* label, bool startState, void(* callBack)(int, int)); // Create Toggle Button
void pad(const char* label, bool centerButton, void(* callBack)(int, int)); // Create Pad Control
void label(const char *label, int color, String value = ""); // Create Label
void button(const char *label, void (*callBack)(Control, int), int color,
String value = ""); // Create Event Button
void switcher(const char *label, bool startState,
void (*callBack)(Control, int),
int color); // Create Toggle Button
void pad(const char *label, bool centerButton, void (*callBack)(Control, int),
int color); // Create Pad Control
// Update Elements
void print(int id, String value);
void print(String label, String value);
void updateSwitcher(int id, bool nValue);
void updateSwitcher(String label, bool nValue);
// Variables ---
const char* ui_title = "ESPUI"; // Store UI Title and Header Name
int cIndex; // Control index
Control* controls[25];
void jsonDom(AsyncWebSocketClient * client);
const char *ui_title = "ESPUI"; // Store UI Title and Header Name
int cIndex = 0; // Control index
Control *controls[25];
void jsonDom(AsyncWebSocketClient *client);
int getIdByLabel(String label);
bool labelExists(String label);
private:
AsyncWebServer* server;
AsyncWebSocket* ws;
AsyncWebServer *server;
AsyncWebSocket *ws;
};
extern ESPUIClass ESPUI;

View File

@ -1,30 +0,0 @@
const char HTML_HEAD1[] PROGMEM = R"=====(
<!DOCTYPE html>
<html lang="en">
<head>
)=====";
const char HTML_HEAD2[] PROGMEM = R"=====(
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAPFBMVEUAAACA1VWR21qQ2liR3FqR3FqS3VuR3VqR3VuR3VqO21mS21uS3FqS3FqS21uJ2GKQ21qR3FuR3FoAAAB/3Gu7AAAAEnRSTlMABoA3kPBwz8i5Kzioxg4NVcU3uEJHAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB+EFEhcEM+HpYwQAAABYSURBVBjThY/JDsAgCESt4lpX/v9jLQZJ6qF9t3khAyj1xXUKbQ4BVowDwqOYgExkkW4iY6lPaF06RqM8YItOuRbMaz6xjbsusDAW/drplBg47jP696cXE8bPA1eUDeK2AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTA1LTE4VDIzOjA0OjUxKzAyOjAwxE59ewAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wNS0xOFQyMzowNDo1MSswMjowMLUTxccAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAAAElFTkSuQmCC"/>
<link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div class="container">
)=====";
const char HTML_BODY[] PROGMEM = R"=====(
<div class="container">
<div id="row" class="row u-full-width">
</div>
</div>
)=====";
const char HTML_END[] PROGMEM = R"=====(
<script src="/js/sockets.js"></script>
</body>
</html>
)=====";

21
src/uploadData.h Normal file
View File

@ -0,0 +1,21 @@
const char INDEX[] PROGMEM = R"=====(
<!DOCTYPE html>
<html lang="en">
</html>
)=====";
const char CSS_NORMALIZE[] PROGMEM = R"=====(
<style></style>
)=====";
const char CSS_STYLE[] PROGMEM = R"=====(
<style></style>
)=====";
const char JS_ZEPTO[] PROGMEM = R"=====(
<script></script>
)=====";
const char JS_CONTROLS[] PROGMEM = R"=====(
<script></script>
)=====";