mirror of https://github.com/jeelabs/esp-link.git
parent
79c8dc8c4d
commit
f368545aa7
@ -0,0 +1,8 @@ |
|||||||
|
all: user_img |
||||||
|
|
||||||
|
clean: |
||||||
|
rm -rf web-page.espfs.img
|
||||||
|
|
||||||
|
user_img: |
||||||
|
../../../../../createEspFs.pl web-page web-page.espfs.img
|
||||||
|
|
Binary file not shown.
@ -1,519 +0,0 @@ |
|||||||
#!/usr/bin/perl |
|
||||||
use strict; |
|
||||||
|
|
||||||
use threads; |
|
||||||
use threads::shared; |
|
||||||
|
|
||||||
use IO::Socket::INET; |
|
||||||
use Data::Dumper; |
|
||||||
use File::Basename; |
|
||||||
|
|
||||||
my $ledLabel : shared = "LED is turned off"; |
|
||||||
my $ledFreq : shared = 10; |
|
||||||
my @ledHistory : shared; |
|
||||||
my $startTime : shared = time; |
|
||||||
my $pattern : shared = "50_50"; |
|
||||||
my $userFname : shared; |
|
||||||
my $userLname : shared; |
|
||||||
my $userAge : shared; |
|
||||||
my $userGender : shared; |
|
||||||
my $userNotifs : shared; |
|
||||||
|
|
||||||
|
|
||||||
# auto-flush on socket |
|
||||||
$| = 1; |
|
||||||
|
|
||||||
# creating a listening socket |
|
||||||
my $server = new IO::Socket::INET ( |
|
||||||
LocalHost => '0.0.0.0', |
|
||||||
LocalPort => '7777', |
|
||||||
Proto => 'tcp', |
|
||||||
Listen => 25, |
|
||||||
Reuse => 1 |
|
||||||
); |
|
||||||
die "cannot create socket $!\n" unless $server; |
|
||||||
print "server waiting for client connection on port 7777\n"; |
|
||||||
|
|
||||||
|
|
||||||
my @webmethods = ( |
|
||||||
[ "menu", \&getMenu ], |
|
||||||
[ "pins", \&getPins ], |
|
||||||
[ "system/info", \&getSystemInfo ], |
|
||||||
[ "wifi/info", \&getWifiInfo ], |
|
||||||
); |
|
||||||
|
|
||||||
my $client; |
|
||||||
|
|
||||||
while ($client = $server->accept()) |
|
||||||
{ |
|
||||||
threads->create( sub { |
|
||||||
$client->autoflush(1); # Always a good idea |
|
||||||
close $server; |
|
||||||
|
|
||||||
my $httpReq = parse_http( $client ); |
|
||||||
#print Dumper($httpReq); |
|
||||||
my $httpResp = process_http( $httpReq ); |
|
||||||
#print Dumper($httpResp); |
|
||||||
|
|
||||||
my $data = "HTTP/1.1 " . $httpResp->{code} . " " . $httpResp->{text} . "\r\n"; |
|
||||||
|
|
||||||
if( exists $httpResp->{fields} ) |
|
||||||
{ |
|
||||||
for my $key( keys %{$httpResp->{fields}} ) |
|
||||||
{ |
|
||||||
$data .= "$key: " . $httpResp->{fields}{$key} . "\r\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
$data .= "\r\n"; |
|
||||||
if( exists $httpResp->{body} ) |
|
||||||
{ |
|
||||||
$data .= $httpResp->{body}; |
|
||||||
} |
|
||||||
|
|
||||||
$client->send($data); |
|
||||||
|
|
||||||
if( $httpResp->{done} ) |
|
||||||
{ |
|
||||||
# notify client that response has been sent |
|
||||||
shutdown($client, 1); |
|
||||||
} |
|
||||||
} ); |
|
||||||
close $client; # Only meaningful in the client |
|
||||||
} |
|
||||||
|
|
||||||
exit(0); |
|
||||||
|
|
||||||
sub parse_http |
|
||||||
{ |
|
||||||
my ($client) = @_; |
|
||||||
# read up to 1024 characters from the connected client |
|
||||||
my $data = ""; |
|
||||||
|
|
||||||
do{ |
|
||||||
my $buf = ""; |
|
||||||
$client->recv($buf, 1024); |
|
||||||
$data .= $buf; |
|
||||||
}while( $data !~ /\r\n\r\n/s ); |
|
||||||
|
|
||||||
my %resp; |
|
||||||
|
|
||||||
my @lines = split /\r\n/, $data; |
|
||||||
my $head = shift @lines; |
|
||||||
|
|
||||||
if( $head =~ /(GET|POST) / ) |
|
||||||
{ |
|
||||||
$resp{method} = $1; |
|
||||||
$head =~ s/(GET|POST) //; |
|
||||||
if( $head =~ /^([^ ]+) HTTP\/\d\.\d/ ) |
|
||||||
{ |
|
||||||
my $args = $1; |
|
||||||
my $u = $args; |
|
||||||
$u =~ s/\?.*$//g; |
|
||||||
$args =~ s/^.*\?//g; |
|
||||||
my %arg = split /[=\&]/, $args; |
|
||||||
$resp{urlArgs} = \%arg; |
|
||||||
$resp{url} = $u; |
|
||||||
|
|
||||||
my %fields; |
|
||||||
while( my $arg = shift @lines ) |
|
||||||
{ |
|
||||||
if( $arg =~ /^([\w-]+): (.*)$/ ) |
|
||||||
{ |
|
||||||
$fields{$1} = $2; |
|
||||||
} |
|
||||||
} |
|
||||||
$resp{fields} = \%fields; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
$resp{method} = 'ERROR'; |
|
||||||
$resp{error} = 'Invalid HTTP request'; |
|
||||||
} |
|
||||||
|
|
||||||
if( $resp{method} eq 'POST' ) |
|
||||||
{ |
|
||||||
my $remaining = join("\r\n", @lines); |
|
||||||
my $cnt_len = $resp{fields}{'Content-Length'}; |
|
||||||
|
|
||||||
while( length($remaining) < $cnt_len ) |
|
||||||
{ |
|
||||||
my $buf = ""; |
|
||||||
$client->recv($buf, 1024); |
|
||||||
$remaining .= $buf; |
|
||||||
} |
|
||||||
|
|
||||||
$resp{postData} = $remaining; |
|
||||||
my %pargs = split /[=\&]/, $remaining; |
|
||||||
$resp{postArgs} = \%pargs; |
|
||||||
} |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
$resp{method} = 'ERROR'; |
|
||||||
$resp{error} = 'Invalid HTTP request'; |
|
||||||
} |
|
||||||
|
|
||||||
return \%resp; |
|
||||||
} |
|
||||||
|
|
||||||
sub simple_response |
|
||||||
{ |
|
||||||
my ($code, $msg) = @_; |
|
||||||
|
|
||||||
my %resp; |
|
||||||
$resp{code} = $code; |
|
||||||
$resp{text} = $msg; |
|
||||||
$resp{fields} = {}; |
|
||||||
$resp{done} = 1; |
|
||||||
|
|
||||||
return \%resp; |
|
||||||
} |
|
||||||
|
|
||||||
sub slurp |
|
||||||
{ |
|
||||||
my ($file) = @_; |
|
||||||
|
|
||||||
open IF, "<", $file or die "Can't read file: $!"; |
|
||||||
my @fc = <IF>; |
|
||||||
close(IF); |
|
||||||
my $cnt = join("", @fc); |
|
||||||
return $cnt; |
|
||||||
} |
|
||||||
|
|
||||||
sub content_response |
|
||||||
{ |
|
||||||
my ($content, $url) = @_; |
|
||||||
|
|
||||||
my %resp; |
|
||||||
$resp{code} = 200; |
|
||||||
$resp{text} = "OK"; |
|
||||||
$resp{done} = 1; |
|
||||||
$resp{body} = $content; |
|
||||||
|
|
||||||
$resp{fields} = {}; |
|
||||||
$resp{fields}{'Content-Length'} = length($content); |
|
||||||
|
|
||||||
$resp{fields}{'Content-Type'} = "text/json"; |
|
||||||
$resp{fields}{'Content-Type'} = "text/html; charset=UTF-8" if( $url =~ /\.html$/ ); |
|
||||||
$resp{fields}{'Content-Type'} = "text/css" if( $url =~ /\.css$/ ); |
|
||||||
$resp{fields}{'Content-Type'} = "text/javascript" if( $url =~ /\.js$/ ); |
|
||||||
$resp{fields}{'Content-Type'} = "image/gif" if( $url =~ /\.ico$/ ); |
|
||||||
$resp{fields}{'Connection'} = 'close'; |
|
||||||
|
|
||||||
return \%resp; |
|
||||||
} |
|
||||||
|
|
||||||
sub process_http |
|
||||||
{ |
|
||||||
my ($httpReq) = @_; |
|
||||||
if( $httpReq->{method} eq 'ERROR' ) |
|
||||||
{ |
|
||||||
return simple_response(400, $httpReq->{error}); |
|
||||||
} |
|
||||||
|
|
||||||
if( $httpReq->{url} =~ /\.json$/ ) |
|
||||||
{ |
|
||||||
my $url = $httpReq->{url}; |
|
||||||
$url =~ s/\.json$//; |
|
||||||
my $pth = dirname $0; |
|
||||||
|
|
||||||
if( -f "$pth/web-server/$url" ) |
|
||||||
{ |
|
||||||
return process_user_comm($httpReq); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if( $httpReq->{method} eq 'GET' ) |
|
||||||
{ |
|
||||||
my $url = $httpReq->{url}; |
|
||||||
$url =~ s/^\///; |
|
||||||
|
|
||||||
$url = "home.html" if ! $url; |
|
||||||
|
|
||||||
my $pth = dirname $0; |
|
||||||
|
|
||||||
if( -f "$pth/../html/$url" ) |
|
||||||
{ |
|
||||||
my $cnt = slurp( "$pth/../html/$url" ); |
|
||||||
|
|
||||||
if( $url =~ /\.html$/ ) |
|
||||||
{ |
|
||||||
my $prep = slurp( "$pth/../html/head-" ); |
|
||||||
$cnt = "$prep$cnt"; |
|
||||||
} |
|
||||||
return content_response($cnt, $url); |
|
||||||
} |
|
||||||
if( -f "$pth/web-server/$url" ) |
|
||||||
{ |
|
||||||
my $cnt = slurp( "$pth/web-server/$url" ); |
|
||||||
|
|
||||||
if( $url =~ /\.html$/ ) |
|
||||||
{ |
|
||||||
my $prep = slurp( "$pth/head-user-" ); |
|
||||||
$cnt = "$prep$cnt"; |
|
||||||
} |
|
||||||
return content_response($cnt, $url); |
|
||||||
} |
|
||||||
elsif( grep { $_->[0] eq $url } @webmethods ) |
|
||||||
{ |
|
||||||
my @mth = grep { $_->[0] eq $url } @webmethods; |
|
||||||
my $webm = $mth[0]; |
|
||||||
|
|
||||||
return content_response( $webm->[1]->(), $url ); |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
return simple_response(404, "File not found"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return simple_response(400, "Invalid HTTP request"); |
|
||||||
} |
|
||||||
|
|
||||||
sub getMenu |
|
||||||
{ |
|
||||||
my $out = sprintf( |
|
||||||
"{ " . |
|
||||||
"\"menu\": [ " . |
|
||||||
"\"Home\", \"/home.html\", " . |
|
||||||
"\"WiFi Station\", \"/wifi/wifiSta.html\", " . |
|
||||||
"\"WiFi Soft-AP\", \"/wifi/wifiAp.html\", " . |
|
||||||
"\"µC Console\", \"/console.html\", " . |
|
||||||
"\"Services\", \"/services.html\", " . |
|
||||||
#ifdef MQTT |
|
||||||
"\"REST/MQTT\", \"/mqtt.html\", " . |
|
||||||
#endif |
|
||||||
"\"Debug log\", \"/log.html\", " . |
|
||||||
"\"Web Server\", \"/web-server.html\"" . |
|
||||||
"%s" . |
|
||||||
" ], " . |
|
||||||
"\"version\": \"%s\", " . |
|
||||||
"\"name\": \"%s\"" . |
|
||||||
" }", readUserPages(), "dummy", "dummy-esp-link"); |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
|
|
||||||
sub getPins |
|
||||||
{ |
|
||||||
return '{ "reset":12, "isp":-1, "conn":-1, "ser":2, "swap":0, "rxpup":1 }'; |
|
||||||
} |
|
||||||
|
|
||||||
sub getSystemInfo |
|
||||||
{ |
|
||||||
return '{ "name": "esp-link-dummy", "reset cause": "6=external", "size": "4MB:512/512", "upload-size": "3145728", "id": "0xE0 0x4016", "partition": "user2.bin", "slip": "disabled", "mqtt": "disabled/disconnected", "baud": "57600", "description": "" }'; |
|
||||||
} |
|
||||||
|
|
||||||
sub getWifiInfo |
|
||||||
{ |
|
||||||
return '{"mode": "STA", "modechange": "yes", "ssid": "DummySSID", "status": "got IP address", "phy": "11n", "rssi": "-45dB", "warn": "Switch to <a href=\"#\" onclick=\"changeWifiMode(3)\">STA+AP mode</a>", "apwarn": "Switch to <a href=\"#\" onclick=\"changeWifiMode(3)\">STA+AP mode</a>", "mac":"12:34:56:78:9a:bc", "chan":"11", "apssid": "ESP_012345", "appass": "", "apchan": "11", "apmaxc": "4", "aphidd": "disabled", "apbeac": "100", "apauth": "OPEN","apmac":"12:34:56:78:9a:bc", "ip": "192.168.1.2", "netmask": "255.255.255.0", "gateway": "192.168.1.1", "hostname": "esp-link", "staticip": "0.0.0.0", "dhcp": "on"}'; |
|
||||||
} |
|
||||||
|
|
||||||
sub read_dir_structure |
|
||||||
{ |
|
||||||
my ($dir, $base) = @_; |
|
||||||
|
|
||||||
my @files; |
|
||||||
|
|
||||||
opendir my $dh, $dir or die "Could not open '$dir' for reading: $!\n"; |
|
||||||
|
|
||||||
while (my $file = readdir $dh) { |
|
||||||
if ($file eq '.' or $file eq '..') { |
|
||||||
next; |
|
||||||
} |
|
||||||
|
|
||||||
my $path = "$dir/$file"; |
|
||||||
if( -d "$path" ) |
|
||||||
{ |
|
||||||
my @sd = read_dir_structure($path, "$base/$file"); |
|
||||||
push @files, @sd ; |
|
||||||
} |
|
||||||
else |
|
||||||
{ |
|
||||||
push @files, "$base/$file"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
close( $dh ); |
|
||||||
|
|
||||||
$_ =~ s/^\/// for(@files); |
|
||||||
return @files; |
|
||||||
} |
|
||||||
|
|
||||||
sub readUserPages |
|
||||||
{ |
|
||||||
my $pth = dirname $0; |
|
||||||
my @files = read_dir_structure( "$pth/web-server", "/" ); |
|
||||||
|
|
||||||
@files = grep { $_ =~ /\.html$/ } @files; |
|
||||||
|
|
||||||
my $add = ''; |
|
||||||
for my $f ( @files ) |
|
||||||
{ |
|
||||||
my $nam = $f; |
|
||||||
$nam =~ s/\.html$//; |
|
||||||
$nam =~ s/[^\/]*\///g; |
|
||||||
$add .= ", \"$nam\", \"$f\""; |
|
||||||
} |
|
||||||
|
|
||||||
return $add; |
|
||||||
} |
|
||||||
|
|
||||||
sub jsonString |
|
||||||
{ |
|
||||||
my ($text) = @_; |
|
||||||
return 'null' if ! defined $text; |
|
||||||
return "\"$text\""; |
|
||||||
} |
|
||||||
|
|
||||||
sub jsonNumber |
|
||||||
{ |
|
||||||
my ($num) = @_; |
|
||||||
return 'null' if ! defined $num; |
|
||||||
return $num + 0; |
|
||||||
} |
|
||||||
|
|
||||||
sub led_add_history |
|
||||||
{ |
|
||||||
my ($msg) = @_; |
|
||||||
pop @ledHistory if @ledHistory >= 10; |
|
||||||
|
|
||||||
my $elapsed = time - $startTime; |
|
||||||
my $secs = $elapsed % 60; |
|
||||||
my $mins = int($elapsed / 60) % 60; |
|
||||||
my $hours = int($elapsed / 3600) % 24; |
|
||||||
|
|
||||||
$secs = "0$secs" if length($secs) == 1; |
|
||||||
$mins = "0$mins" if length($mins) == 1; |
|
||||||
$hours = "0$hours" if length($hours) == 1; |
|
||||||
|
|
||||||
$msg = "$hours:$mins:$secs $msg"; |
|
||||||
unshift @ledHistory, $msg; |
|
||||||
} |
|
||||||
|
|
||||||
sub process_user_comm_led |
|
||||||
{ |
|
||||||
my ($http) = @_; |
|
||||||
my $loadData = ''; |
|
||||||
|
|
||||||
if( $http->{urlArgs}{reason} eq "button" ) |
|
||||||
{ |
|
||||||
my $btn = $http->{urlArgs}{id}; |
|
||||||
|
|
||||||
if($btn eq "btn_on" ) |
|
||||||
{ |
|
||||||
$ledLabel = "LED is turned on"; |
|
||||||
led_add_history("Set LED on"); |
|
||||||
} |
|
||||||
elsif($btn eq "btn_blink" ) |
|
||||||
{ |
|
||||||
$ledLabel = "LED is blinking"; |
|
||||||
led_add_history("Set LED blinking"); |
|
||||||
} |
|
||||||
elsif($btn eq "btn_off" ) |
|
||||||
{ |
|
||||||
$ledLabel = "LED is turned off"; |
|
||||||
led_add_history("Set LED off"); |
|
||||||
} |
|
||||||
} |
|
||||||
elsif( $http->{urlArgs}{reason} eq "submit" ) |
|
||||||
{ |
|
||||||
if( exists $http->{postArgs}{frequency} ) |
|
||||||
{ |
|
||||||
$ledFreq = $http->{postArgs}{frequency}; |
|
||||||
led_add_history("Set frequency to $ledFreq Hz"); |
|
||||||
} |
|
||||||
if( exists $http->{postArgs}{pattern} ) |
|
||||||
{ |
|
||||||
$pattern = $http->{postArgs}{pattern}; |
|
||||||
my $out = $pattern; |
|
||||||
$out =~ s/_/\% - /; |
|
||||||
$out .= "%"; |
|
||||||
led_add_history("Set pattern to $out"); |
|
||||||
} |
|
||||||
return simple_response(204, "OK"); |
|
||||||
} |
|
||||||
elsif( $http->{urlArgs}{reason} eq "load" ) |
|
||||||
{ |
|
||||||
$loadData = ', "frequency": ' . $ledFreq . ', "pattern": "' . $pattern . '"'; |
|
||||||
} |
|
||||||
|
|
||||||
my $list = ", \"led_history\": [" . join(", ", map { "\"$_\"" } @ledHistory ) . "]"; |
|
||||||
my $r = '{"text": "' . $ledLabel . '"' . $list . $loadData . '}'; |
|
||||||
return content_response($r, $http->{url}); |
|
||||||
} |
|
||||||
|
|
||||||
sub process_user_comm_voltage |
|
||||||
{ |
|
||||||
my ($http) = @_; |
|
||||||
|
|
||||||
my $voltage = (((time - $startTime) % 60) - 30) / 30.0 + 4.0; |
|
||||||
$voltage = sprintf("%.2f V", $voltage); |
|
||||||
|
|
||||||
my $table = ', "table": [["Time", "Min", "AVG", "Max"], ["0s-10s", "1 V", "3 V", "5 V"], ["10s-20s", "1 V", "2 V", "3 V"]]'; |
|
||||||
my $r = '{"voltage": "' . $voltage . '"' . $table . '}'; |
|
||||||
return content_response($r, $http->{url}); |
|
||||||
} |
|
||||||
|
|
||||||
sub process_user_comm_user |
|
||||||
{ |
|
||||||
my ($http) = @_; |
|
||||||
|
|
||||||
|
|
||||||
if( $http->{urlArgs}{reason} eq "submit" ) |
|
||||||
{ |
|
||||||
if( exists $http->{postArgs}{last_name} ) |
|
||||||
{ |
|
||||||
$userLname = $http->{postArgs}{last_name}; |
|
||||||
} |
|
||||||
if( exists $http->{postArgs}{first_name} ) |
|
||||||
{ |
|
||||||
$userFname = $http->{postArgs}{first_name}; |
|
||||||
} |
|
||||||
if( exists $http->{postArgs}{age} ) |
|
||||||
{ |
|
||||||
$userAge = $http->{postArgs}{age}; |
|
||||||
} |
|
||||||
if( exists $http->{postArgs}{gender} ) |
|
||||||
{ |
|
||||||
$userGender = $http->{postArgs}{gender}; |
|
||||||
} |
|
||||||
if( exists $http->{postArgs}{notifications} ) |
|
||||||
{ |
|
||||||
$userNotifs = $http->{postArgs}{notifications}; |
|
||||||
} |
|
||||||
return simple_response(204, "OK"); |
|
||||||
} |
|
||||||
elsif( $http->{urlArgs}{reason} eq "load" ) |
|
||||||
{ |
|
||||||
my $r = '{"last_name": ' . jsonString($userLname) . |
|
||||||
', "first_name": ' . jsonString($userFname) . |
|
||||||
', "age": ' . jsonNumber($userAge) . |
|
||||||
', "gender": ' . jsonString($userGender) . |
|
||||||
', "notifications":' . jsonString($userNotifs) . '}'; |
|
||||||
|
|
||||||
return content_response($r, $http->{url}); |
|
||||||
} |
|
||||||
|
|
||||||
return content_response("{}", $http->{url}); |
|
||||||
} |
|
||||||
|
|
||||||
sub process_user_comm() |
|
||||||
{ |
|
||||||
my ($http) = @_; |
|
||||||
|
|
||||||
if( $http->{url} eq '/LED.html.json' ) |
|
||||||
{ |
|
||||||
return process_user_comm_led($http); |
|
||||||
} |
|
||||||
|
|
||||||
if( $http->{url} eq '/Voltage.html.json' ) |
|
||||||
{ |
|
||||||
return process_user_comm_voltage($http); |
|
||||||
} |
|
||||||
|
|
||||||
if( $http->{url} eq '/User.html.json' ) |
|
||||||
{ |
|
||||||
return process_user_comm_user($http); |
|
||||||
} |
|
||||||
} |
|
@ -1,11 +0,0 @@ |
|||||||
<!doctype html> |
|
||||||
<html><head> |
|
||||||
<title>esp-link</title> |
|
||||||
<link rel="stylesheet" href="/pure.css"> |
|
||||||
<link rel="stylesheet" href="/style.css"> |
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
||||||
<script src="/ui.js"></script> |
|
||||||
<script src="/userpage.js"></script> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<div id="layout"> |
|
@ -1,36 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<div class="header"> |
|
||||||
<h1>LED configuration</h1> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="content"> |
|
||||||
<div class="pure-g"><div class="pure-u-1 pure-u-md-1-2"> |
|
||||||
<div class="card"> |
|
||||||
<h1>Control</h1> |
|
||||||
<button id="btn_on" type="button">Turn on</button> |
|
||||||
<button id="btn_blink" type="button">Start blinking</button> |
|
||||||
<button id="btn_off" type="button">Turn off</button> |
|
||||||
<p id="text"/> |
|
||||||
</div> |
|
||||||
<div class="card"> |
|
||||||
<h1>Frequency and pattern</h1> |
|
||||||
<form> |
|
||||||
<b>Pattern:</b><br/> |
|
||||||
<input type="radio" name="pattern" value="25_75">25% on 75% off</input><br/> |
|
||||||
<input type="radio" name="pattern" value="50_50">50% on 50% off</input><br/> |
|
||||||
<input type="radio" name="pattern" value="75_25">75% on 25% off</input><br/> |
|
||||||
|
|
||||||
<b>Frequency:</b><br/> |
|
||||||
<input type="range" name="frequency" min="1" max="25"><br/> |
|
||||||
<input type="submit"> |
|
||||||
</form> |
|
||||||
</div></div> |
|
||||||
<div class="pure-u-1 pure-u-md-1-2"> |
|
||||||
<div class="card" style="min-height: 400px"> |
|
||||||
<h1>Logs</h1> |
|
||||||
<ul id="led_history"/> |
|
||||||
</div> |
|
||||||
</div></div> |
|
||||||
</div> |
|
||||||
</body></html> |
|
@ -1,24 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<div class="header"> |
|
||||||
<h1>User setup</h1> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="content"> |
|
||||||
<form> |
|
||||||
First name:<br/><input name="first_name" type="text"/> |
|
||||||
Last name:<br/><input name="last_name" type="text"/> |
|
||||||
Age: |
|
||||||
<input name="age" type="number"/> |
|
||||||
Gender: |
|
||||||
<select name="gender"> |
|
||||||
<option value="female">Female</option> |
|
||||||
<option value="male">Male</option> |
|
||||||
</select> |
|
||||||
<br> |
|
||||||
Notifications<input name="notifications" type="checkbox"/> |
|
||||||
<br> |
|
||||||
<input type="submit"> |
|
||||||
</form> |
|
||||||
</div> |
|
||||||
</body></html> |
|
@ -1,15 +0,0 @@ |
|||||||
<!-- EspLink will add header here --> |
|
||||||
|
|
||||||
<meta name="refresh-rate" content="500" /> |
|
||||||
|
|
||||||
<div class="header"> |
|
||||||
<h1>Voltage measurement</h1> |
|
||||||
</div> |
|
||||||
|
|
||||||
<div class="content"> |
|
||||||
<p id="voltage" align="center" style="font-size: 800%"/> |
|
||||||
|
|
||||||
<table class="pure-table pure-table-bordered" align="center" id="table"/> |
|
||||||
</div> |
|
||||||
|
|
||||||
</body></html> |
|
Loading…
Reference in new issue