Add JS client
This commit is contained in:
@@ -10,13 +10,21 @@ binDir = "bin"
|
||||
bin = @["randopix", "pixctrl"]
|
||||
|
||||
# Dependencies
|
||||
requires "nim >= 1.0.0", "gintro", "argparse", "jester"
|
||||
requires "nim >= 1.0.0", "gintro", "argparse", "jester", "ajax"
|
||||
|
||||
proc genJS =
|
||||
echo "Generating JS Client"
|
||||
exec("nim js -o:src/resources/pixctrl.js src/pixctrl.nim")
|
||||
|
||||
task genJS, "Generate the Javascript client":
|
||||
exec "nim js -o:src/resources/script.js src/pixscript.nim"
|
||||
genJS()
|
||||
|
||||
task buildAll, "Generate JS and run build":
|
||||
genJS()
|
||||
exec "nimble build"
|
||||
|
||||
task debug, "Compile debug version":
|
||||
exec "nim c -d:debug --debugger:native -o:bin/randopix src/randopix.nim"
|
||||
|
||||
task release, "Compile release version":
|
||||
exec fmt"nim c -d:release -o:bin/randopix-{version} src/randopix.nim"
|
||||
before install:
|
||||
genJS()
|
||||
@@ -21,6 +21,9 @@ type
|
||||
command*: Command ## Command that the application should execute
|
||||
parameter*: string ## Optional parameter for the command
|
||||
|
||||
proc `$`(cMsg: CommandMessage): string =
|
||||
$(%cMsg)
|
||||
|
||||
proc newOpResult*(): OpResult =
|
||||
OpResult(success: true)
|
||||
|
||||
@@ -30,9 +33,6 @@ proc newOpResult*(msg: string): OpResult =
|
||||
proc newCommandMessage*(c: Command, p: string = ""): CommandMessage =
|
||||
CommandMessage(command: c, parameter: p)
|
||||
|
||||
proc wrap*(msg: CommandMessage): string =
|
||||
$(%msg) & "\r\L"
|
||||
|
||||
proc enumToStrings*(en: typedesc): seq[string] =
|
||||
for x in en:
|
||||
result.add $x
|
||||
101
src/pixctrl.nim
101
src/pixctrl.nim
@@ -1,17 +1,32 @@
|
||||
import strutils, httpClient
|
||||
import argparse
|
||||
import strutils
|
||||
import common
|
||||
|
||||
const modeHelp = "Change the display mode. Possible values: [$1]" % Mode.enumToStrings().join(", ")
|
||||
|
||||
var
|
||||
randopixServer*: string ## URL for the randopix server
|
||||
client = newHttpClient()
|
||||
when defined(js):
|
||||
import ajax, jsconsole, dom, json
|
||||
else:
|
||||
import httpClient
|
||||
import argparse
|
||||
var randopixServer* {.exportc.}: string ## URL for the randopix server
|
||||
|
||||
proc sendCommand(msg: CommandMessage) =
|
||||
let resp = client.post(randopixServer, msg.wrap)
|
||||
if not resp.status.contains("200"):
|
||||
echo "Error while sending command: ", resp.status
|
||||
when defined(js):
|
||||
console.log("Sending:", $msg, "to URL:", document.URL)
|
||||
var req = newXMLHttpRequest()
|
||||
|
||||
proc processSend(e:Event) =
|
||||
if req.readyState == rsDONE:
|
||||
if req.status != 200:
|
||||
console.log("There was a problem with the request.")
|
||||
console.log($req.status, req.statusText)
|
||||
|
||||
req.onreadystatechange = processSend
|
||||
req.open("POST", document.URL)
|
||||
req.send(cstring($(%*msg)))
|
||||
else:
|
||||
let client = newHttpClient()
|
||||
let resp = client.post(randopixServer, $msg)
|
||||
if not resp.status.contains("200"):
|
||||
echo "Error while sending command: ", resp.status
|
||||
|
||||
proc sendCommand(cmd: Command) =
|
||||
sendCommand(newCommandMessage(cmd))
|
||||
@@ -26,7 +41,7 @@ proc switchMode*(mode: string) =
|
||||
return
|
||||
sendCommand(newCommandMessage(cMode, mode))
|
||||
|
||||
proc refresh*() =
|
||||
proc refresh*() {.exportc.} =
|
||||
## Force refresh of the current image
|
||||
sendCommand(cRefresh)
|
||||
|
||||
@@ -34,33 +49,43 @@ proc setTimeout*(seconds: string) =
|
||||
## Set the image timeout to this value
|
||||
sendCommand(newCommandMessage(cTimeout, seconds))
|
||||
|
||||
when isMainModule:
|
||||
var p = newParser("pixctrl"):
|
||||
help("Control utilitiy for randopix")
|
||||
option("-s", "--server", help="Host running the randopix server", default="http://localhost:8080/")
|
||||
run:
|
||||
randopixServer = opts.server
|
||||
|
||||
command($cRefresh):
|
||||
## Force refresh command
|
||||
help("Force image refresh now")
|
||||
when defined(js):
|
||||
proc getModes(): seq[cstring] {.exportc.} =
|
||||
for mode in enumToStrings(Mode):
|
||||
result.add cstring(mode)
|
||||
proc switchMode*(mode: cstring) {.exportc.} =
|
||||
switchMode($mode)
|
||||
proc setTimeout*(seconds: cstring) {.exportc.} =
|
||||
setTimeout($seconds)
|
||||
else:
|
||||
when isMainModule:
|
||||
const modeHelp = "Change the display mode. Possible values: [$1]" % Mode.enumToStrings().join(", ")
|
||||
var p = newParser("pixctrl"):
|
||||
help("Control utilitiy for randopix")
|
||||
option("-s", "--server", help="Host running the randopix server", default="http://localhost:8080/")
|
||||
run:
|
||||
refresh()
|
||||
randopixServer = opts.server
|
||||
|
||||
command($cTimeout):
|
||||
## Timeout Command
|
||||
help("Set timeout in seconds before a new image is displayed")
|
||||
arg("seconds", default = "300")
|
||||
run:
|
||||
setTimeout(opts.seconds)
|
||||
command($cRefresh):
|
||||
## Force refresh command
|
||||
help("Force image refresh now")
|
||||
run:
|
||||
refresh()
|
||||
|
||||
command($cMode):
|
||||
## Mode switch command
|
||||
help(modeHelp)
|
||||
arg("mode")
|
||||
run:
|
||||
switchMode(opts.mode)
|
||||
try:
|
||||
p.run(commandLineParams())
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
command($cTimeout):
|
||||
## Timeout Command
|
||||
help("Set timeout in seconds before a new image is displayed")
|
||||
arg("seconds", default = "300")
|
||||
run:
|
||||
setTimeout(opts.seconds)
|
||||
|
||||
command($cMode):
|
||||
## Mode switch command
|
||||
help(modeHelp)
|
||||
arg("mode")
|
||||
run:
|
||||
switchMode(opts.mode)
|
||||
try:
|
||||
p.run(commandLineParams())
|
||||
except:
|
||||
echo getCurrentExceptionMsg()
|
||||
@@ -9,10 +9,27 @@
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/style">
|
||||
|
||||
<script src="/pixctrl" type="text/javascript"></script>
|
||||
<script src="/script" type="text/javascript"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>randopix web control</h1>
|
||||
|
||||
<p>
|
||||
<button type="button" class="btn" onclick="refresh()">Refresh Image Now!</button>
|
||||
</p>
|
||||
|
||||
<div>Switch the image mode</div>
|
||||
<p>
|
||||
<select id="modeselect"></select>
|
||||
<button type="button" class="btn" onclick="js_setMode()">Set Mode</button>
|
||||
</p>
|
||||
|
||||
<div>Adjust timespan between images</div>
|
||||
<p>
|
||||
<input id="timeout" type="number">
|
||||
<button type="button" class="btn" onclick="js_setTimeout()">Set Timeout</button>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,29 @@
|
||||
function capitalize(string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
const modes = getModes();
|
||||
const modeselect = document.getElementById("modeselect");
|
||||
modes.forEach(mode => {
|
||||
let opt = document.createElement('option');
|
||||
opt.value = mode;
|
||||
opt.innerHTML = capitalize(mode)
|
||||
modeselect.appendChild(opt);
|
||||
});
|
||||
}
|
||||
|
||||
function js_setTimeout() {
|
||||
const elem = document.getElementById("timeout");
|
||||
const timeout = parseInt(elem.value);
|
||||
if (timeout < 1) {
|
||||
console.error("timeout must be positive");
|
||||
return;
|
||||
}
|
||||
setTimeout(timeout.toString());
|
||||
}
|
||||
|
||||
function js_setMode() {
|
||||
const modeselect = document.getElementById("modeselect");
|
||||
switchMode(modeselect.value)
|
||||
}
|
||||
@@ -1,3 +1,57 @@
|
||||
body {
|
||||
background-color: blue;
|
||||
}
|
||||
color: yellow;
|
||||
}
|
||||
/* Chrome, Safari, Opera */
|
||||
@-webkit-keyframes rainbow {
|
||||
0%{color: orange;}
|
||||
10%{color: purple;}
|
||||
20%{color: red;}
|
||||
30%{color: CadetBlue;}
|
||||
40%{color: yellow;}
|
||||
50%{color: coral;}
|
||||
60%{color: green;}
|
||||
70%{color: cyan;}
|
||||
80%{color: DeepPink;}
|
||||
90%{color: DodgerBlue;}
|
||||
100%{color: orange;}
|
||||
}
|
||||
|
||||
/* Internet Explorer */
|
||||
@-ms-keyframes rainbow {
|
||||
0%{color: orange;}
|
||||
10%{color: purple;}
|
||||
20%{color: red;}
|
||||
30%{color: CadetBlue;}
|
||||
40%{color: yellow;}
|
||||
50%{color: coral;}
|
||||
60%{color: green;}
|
||||
70%{color: cyan;}
|
||||
80%{color: DeepPink;}
|
||||
90%{color: DodgerBlue;}
|
||||
100%{color: orange;}
|
||||
}
|
||||
|
||||
/* Standard Syntax */
|
||||
@keyframes rainbow {
|
||||
0%{color: orange;}
|
||||
10%{color: purple;}
|
||||
20%{color: red;}
|
||||
30%{color: CadetBlue;}
|
||||
40%{color: yellow;}
|
||||
50%{color: coral;}
|
||||
60%{color: green;}
|
||||
70%{color: cyan;}
|
||||
80%{color: DeepPink;}
|
||||
90%{color: DodgerBlue;}
|
||||
100%{color: orange;}
|
||||
}
|
||||
|
||||
h1 {
|
||||
/* Chrome, Safari, Opera */
|
||||
-webkit-animation: rainbow 5s infinite;
|
||||
/* Internet Explorer */
|
||||
-ms-animation: rainbow 5s infinite;
|
||||
/* Standar Syntax */
|
||||
animation: rainbow 5s infinite;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import asyncdispatch, strutils, json
|
||||
import asyncdispatch, strutils, json, logging
|
||||
import jester
|
||||
import common
|
||||
|
||||
const
|
||||
index = slurp("resources/index.html")
|
||||
style = slurp("resources/site.css")
|
||||
pixctrlJs = slurp("resources/pixctrl.js")
|
||||
script = slurp("resources/script.js")
|
||||
|
||||
type
|
||||
@@ -22,24 +23,35 @@ proc log(things: varargs[string, `$`]) =
|
||||
|
||||
router randopixRouter:
|
||||
get "/":
|
||||
log "Access from ", request.ip
|
||||
resp index
|
||||
|
||||
get "/style":
|
||||
resp(style, contentType="text/css")
|
||||
|
||||
get "/pixctrl":
|
||||
resp(pixctrlJs, contentType="text/javascript")
|
||||
|
||||
get "/script":
|
||||
resp(script, contentType="text/javascript")
|
||||
|
||||
post "/":
|
||||
let json = request.body.parseJson
|
||||
let msg = json.to(CommandMessage)
|
||||
# Pass command from client to main applicaiton
|
||||
chan.send(msg)
|
||||
resp Http200
|
||||
try:
|
||||
log "Command from ", request.ip
|
||||
let json = request.body.parseJson
|
||||
let msg = json.to(CommandMessage)
|
||||
log "Got message: ", $msg
|
||||
# Pass command from client to main applicaiton
|
||||
chan.send(msg)
|
||||
resp Http200
|
||||
except:
|
||||
log "Error: ", getCurrentExceptionMsg()
|
||||
|
||||
proc runServer*[ServerArgs](arg: ServerArgs) {.thread, nimcall.} =
|
||||
verbose = arg.verbose
|
||||
if verbose:
|
||||
logging.setLogFilter(lvlInfo)
|
||||
else:
|
||||
logging.setLogFilter(lvlNotice)
|
||||
let port = Port(arg.port)
|
||||
let settings = newSettings(port=port)
|
||||
var server = initJester(randopixRouter, settings=settings)
|
||||
|
||||
Reference in New Issue
Block a user