-
-
Notifications
You must be signed in to change notification settings - Fork 195
WebMenu
(not tested with arduino-ide yet, anyone?)
The library provides esp8266 drivers to serve the menu as a web-page, automating menu navigation and values input/output. The web-page uses Web-Sockets to update field values without refreshing the page, with a fall back of common web-link that will refresh the page when needed.
There is also a JSON IO available for web-sockets and http.
All HTTP output (not web-sockets) are streamed to the client minimizing memory usage.
The example uses JQuery + bootstrap to provide a smooth experience across client platforms and device types with a responsive UI.
note: you need to upload a file system image to esp8266 in adddition to normal sketch upload.
- Client-side xslt translation, modern browsers, including mobile, support it.
- JavaScript, without it links works but fields are not updated
assuming webmenu
is a device name.
http://webmenu/
serves a static web cover page, you can customize this page.
http://webmenu/menu?at=/
access the auto-generated menu pages, on this case the root.
http://webmenu/json?at=/
access the JSON output with root page state
all above modes accept a menu path parameter to activate options, update fields or set navigation state. The same path control is available for web-sockets, with JSON output
the http at
parameter or the websocket string sent should contain a menu path using character /
as a separator.
/
menu main page (root)
/0
use first option
- if its a sub-menu, navigate into it, path can continue into submenus by separating indexes with
/
ex:/0/1/3
- execute some action if its a regular prompt
- change value if it its a toggle option
- ignored on other controls
lets say /0 is a toggle field, we can toggle it by calling its path, but we can also set it to enumerated values, lets say it has values "No"/"Yes", then:
/0/0
will set it to "No"
/0/1
will set it to "Yes"
The same technique can be used to update text or numeric fields.
web-sockets should send a null terminated string.
while issuing menu requests a response is provided that can, depending on the output device, be translated to and html page or a JSON response.
This is an JSON output example for a menu root.
while on a menu page you can use the browser console and the function menu(...)
to send web-socket requests.
{
"output":"",
"menu":{"title":{"prompt":"Main menu"},
"path":"","sel":"0",
"items":[
{"idx":"0","enabled":"1","selStart":">","prompt":"Led: ","value":"Off","options":["On","Off"]},
{"idx":"1","enabled":"1","selStart":" ","prompt":"Action A"},
{"idx":"2","enabled":"1","selStart":" ","prompt":"Action B"},
{"idx":"3","enabled":"1","selStart":" ","prompt":"On" ,"field":"50","range":
{"low":"0","high":"100","step":"10","tune":"1"},"unit":"ms"},
{"idx":"4","enabled":"1","selStart":" ","prompt":"Select" ,"select":"Zero","options":["Zero","One","Two"]},
{"idx":"5","enabled":"1","selStart":" ","prompt":"Choose" ,"choose":"Last","options":
["First","Second","Third","Last"]}
]
}
}
.menu.title.prompt
current menu prompt
.menu.path
path of current menu page
.menu.sel
current selection (not important on async interfaces as web)
.menu.items
list of menu items (prompts/fields/pads)
sub-menus display as single prompts and form a new menu page/state when activated
note: Choose fields not yet implemented on web-page side.
all items have some common info with prompts
ex:
{"idx":"1","enabled":"1","selStart":" ","prompt":"Action A"}
.idx option/field path index number
.enable 0/1 disabled/enabled
.prompt
option title, can be empty
[.cursor
] cursor character optional and not relevant for web
[.selStart
] cursor start, optional and not relevant for web
[.selEnd
] cursor end, optional and not relevant for web
ex:
{
"idx":"1",
"enabled":"1",
"cursor":" ",
"prompt":"",
"field":"0.00",
"range":{
"low":"0.00",
"high":"100.00",
"step":"10.00",
"tune":"1.00"
},
"unit":"%"
}
complements prompt info with:
.field
current value of the field
.range
and object containing field boundaries and update info
.unit
field unit text to draw after the field value
.low
minimum value allowed, DO NOT SET OUTSIDE RANGE
.high
maximum value
.step
normal value adjust step
.tune
tuning value adjust step
ex:
{"idx":"1","enabled":"1","selStart":" ","prompt":"Key","editCursor":" ","text":"XXXXXX"}
complements prompt info with:
.text
current text value
.editCursor
not important for web
ex:
{
"idx":"6",
"enabled":"1",
"selStart":" ",
"prompt":"Demo:",
"value":"Off",
"options":["Off","On"]
}
complements prompt info with:
.value
the current field value text, the actual value is an index of options list
.option
a list of possible value strings ordered by index, start at 0
Pads are groups of options (sub-menus) that are drawn together as a single option
ex:
{
"idx":"0",
"enabled":"1",
"selStart":">",
"prompt":"",
"pad":[
{"idx":"0","enabled":"1","cursor":" ","prompt":"" ,"field":"1","range":
{"low":"1","high":"31","step":"1","tune":"0"},"unit":"/"},
{"idx":"1","enabled":"1","cursor":" ","prompt":"" ,"field":"1","range":
{"low":"1","high":"12","step":"1","tune":"0"},"unit":"/"},
{"idx":"2","enabled":"1","cursor":" ","prompt":"" ,"field":"2000","range":
{"low":"2000","high":"2100","step":"10","tune":"1"},"unit":""}
]
}
they complement the prompt with:
.pad
a list of prompts/fields
On the example the esp8266 is serving static files from the file system image (flash partition), with a couple of special handlers. You can customize all files here.
http requests
- an http request to the root will serve the static
index.html
page -
/menu
outputs xml with a xslt translation page (dynamic content) -
/json
raw json output (dynamic content)
Static files like .css, images, .xslt and .js can be customized as needed. On the example we use jquery + bootstrap to produce a nice page. You can include as many as needed, with no extra code to handle them.
XML responses are translated to HTML on the client side by a static xslt translation sheet. This, just as the .css, can be customized. By default it translates the raw XML emitted by the menu into a complete HTML page with some nicer bootstrap controls.
Enumerated fields are on this example translated very freely to drop-down boxes or button groups on the client side.
Numeric fields can present them selves as regular html input fields or as a slider control, depending on some analysis of range done by the xslt style-sheet, so the menu structure type is not mandatory.
JSON output is adequate to feed mobile apps, specially if requested by web-sockets instead of http, however can use both.
The JSON output provides a map to the served menu structure with all info needed to draw each page, so a generic mobile app can be build around this (hint: help needed)
beware that web-socket JSON output still uses buffers (no streaming).
There is a prototype javascript system to update page values based on a web-socket json refresh... it is still a protype.