forked from marva/sumorobot-web
remove multiple robots and remote control from control panel
This commit is contained in:
parent
6fc62fad71
commit
aaed346a9a
39
index.html
39
index.html
@ -6,6 +6,7 @@
|
|||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
<link rel="stylesheet" href="bootstrap.min.css">
|
<link rel="stylesheet" href="bootstrap.min.css">
|
||||||
<link rel="shortcut icon" type="image/png" href="logo.png"/>
|
<link rel="shortcut icon" type="image/png" href="logo.png"/>
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Orbitron" rel="stylesheet">
|
||||||
<script src="jquery.min.js" type="text/javascript" charset="utf-8"></script>
|
<script src="jquery.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="bootstrap.min.js" type="text/javascript" charset="utf-8"></script>
|
<script src="bootstrap.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
<script src="blockly_compressed.js" type="text/javascript" charset="utf-8"></script>
|
<script src="blockly_compressed.js" type="text/javascript" charset="utf-8"></script>
|
||||||
@ -24,35 +25,11 @@
|
|||||||
RoboKoding logo
|
RoboKoding logo
|
||||||
</object>
|
</object>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-addon robot-nr">1</span>
|
<span class="input-group-addon" id="robot-label">robot name</span>
|
||||||
<input type="text" class="form-control robot-id" placeholder="ID" />
|
<input type="text" class="form-control" id="robot-id" placeholder="sumo-ID" />
|
||||||
<span class="input-group-addon addon-no-border robot-nr">2</span>
|
|
||||||
<input type="text" class="form-control robot-id" placeholder="ID" />
|
|
||||||
<span class="input-group-addon addon-no-border robot-nr">3</span>
|
|
||||||
<input type="text" class="form-control robot-id" placeholder="ID" />
|
|
||||||
<span class="input-group-addon addon-no-border robot-nr">4</span>
|
|
||||||
<input type="text" class="form-control robot-id" placeholder="ID" />
|
|
||||||
<span class="input-group-addon addon-no-border robot-nr">5</span>
|
|
||||||
<input type="text" class="form-control robot-id" placeholder="ID" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group btn-group-justified btn-group-robot" role="group" aria-label="robots">
|
<div class="btn-group btn-group-robot" role="group" aria-label="robots">
|
||||||
<a href="#" class="btn btn-lg btn-robot-nr">1</a>
|
<a href="#" class="btn btn-lg btn-robot-go">GO!</a>
|
||||||
<a href="#" class="btn btn-lg btn-robot-nr">2</a>
|
|
||||||
<a href="#" class="btn btn-lg btn-robot-nr">3</a>
|
|
||||||
<a href="#" class="btn btn-lg btn-robot-nr">4</a>
|
|
||||||
<a href="#" class="btn btn-lg btn-robot-nr">5</a>
|
|
||||||
<a href="#" class="btn btn-lg btn-robot-add">+</a>
|
|
||||||
</div>
|
|
||||||
<div class="remote-label">
|
|
||||||
<div class="btn-group form-check-label" data-toggle="buttons">
|
|
||||||
<label class="btn btn-primary active" id="remote-disabled">
|
|
||||||
<input type="radio" name="remote" autocomplete="off" checked> Disabled
|
|
||||||
</label>
|
|
||||||
<label class="btn btn-primary" id="remote-enabled">
|
|
||||||
<input type="radio" name="remote" autocomplete="off"> Enabled
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
Remote control
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -84,9 +61,9 @@
|
|||||||
<block type="sumorobot_line"></block>
|
<block type="sumorobot_line"></block>
|
||||||
</xml>
|
</xml>
|
||||||
|
|
||||||
<div class="btn-group btn-group-justified btn-group-control">
|
<div class="btn-group d-flex btn-group-control" role="group">
|
||||||
<a href="#" class="btn btn-lg btn-success btn-start">Start</a>
|
<a href="#" class="btn btn-lg btn-success btn-start w-100">Start</a>
|
||||||
<a href="#" class="btn btn-lg btn-danger btn-stop">Stop</a>
|
<a href="#" class="btn btn-lg btn-danger btn-stop w-100">Stop</a>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
112
styles.css
112
styles.css
@ -1,15 +1,12 @@
|
|||||||
html, body {
|
html, body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
font-family: "Orbitron" !important;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
/* logo object */
|
|
||||||
object.logo {
|
|
||||||
width: 45%;
|
|
||||||
}
|
|
||||||
/* the whole interface is in the table */
|
/* the whole interface is in the table */
|
||||||
table.blockly-table {
|
table.blockly-table {
|
||||||
height: 95%;
|
height: 95%;
|
||||||
@ -21,47 +18,25 @@ span.has-error {
|
|||||||
border-color: #a94442 !important;
|
border-color: #a94442 !important;
|
||||||
background-color: #f2dede !important;
|
background-color: #f2dede !important;
|
||||||
}
|
}
|
||||||
span.addon-no-border {
|
|
||||||
border-left: 0px !important;
|
|
||||||
border-right: 0px !important;
|
|
||||||
}
|
|
||||||
span.input-group-addon {
|
|
||||||
padding: 0.5vw 1vw !important;
|
|
||||||
}
|
|
||||||
/* form items */
|
|
||||||
label.btn-primary {
|
|
||||||
border-width: 3px !important;
|
|
||||||
}
|
|
||||||
input.form-control {
|
|
||||||
padding: 0.5vw 1vw !important;
|
|
||||||
}
|
|
||||||
input.has-error {
|
input.has-error {
|
||||||
border-color: #a94442 !important;
|
border-color: #a94442 !important;
|
||||||
}
|
}
|
||||||
/* buttons */
|
/* robot connect button */
|
||||||
a.btn-robot-nr, a.btn-robot-add {
|
a.btn-robot-go, a.btn-robot-go:hover {
|
||||||
font-size: 10vw !important;
|
color: #3768d8;
|
||||||
border: 3px solid rgba(0, 0, 0, 0.1) !important;
|
|
||||||
}
|
}
|
||||||
a.btn-robot-add {
|
/* start code button */
|
||||||
opacity: 0.5;
|
a.btn-start {
|
||||||
}
|
|
||||||
a.btn-selected {
|
|
||||||
border-color: #fc3 !important;
|
|
||||||
}
|
|
||||||
a.btn-success {
|
|
||||||
border-width: 3px !important;
|
border-width: 3px !important;
|
||||||
border-color: #4cae4c !important;
|
border-color: #4cae4c !important;
|
||||||
background-color: #44CC00 !important;
|
background-color: #44CC00 !important;
|
||||||
}
|
}
|
||||||
a.btn-danger {
|
/* stop code button */
|
||||||
|
a.btn-stop {
|
||||||
border-width: 3px !important;
|
border-width: 3px !important;
|
||||||
border-color: #d43f3a !important;
|
border-color: #d43f3a !important;
|
||||||
background-color: #b80000 !important;
|
background-color: #b80000 !important;
|
||||||
}
|
}
|
||||||
a.btn-danger.disabled {
|
|
||||||
background-color: #ee4d4d !important;
|
|
||||||
}
|
|
||||||
.btn:hover, .btn.hover {
|
.btn:hover, .btn.hover {
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
border-color: #fc3 !important;
|
border-color: #fc3 !important;
|
||||||
@ -70,18 +45,9 @@ a.btn-danger.disabled {
|
|||||||
.goog-menuitem-content {
|
.goog-menuitem-content {
|
||||||
font-size: 2em !important;
|
font-size: 2em !important;
|
||||||
}
|
}
|
||||||
/* remote control enabler container */
|
|
||||||
div.form-check-label {
|
|
||||||
font-size: 5vw;
|
|
||||||
}
|
|
||||||
/* remote control enabler label container */
|
|
||||||
div.remote-label {
|
|
||||||
font-size: 4vw;
|
|
||||||
margin-top: 1vw;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
/* start and stop button group */
|
/* start and stop button group */
|
||||||
div.btn-group-control {
|
div.btn-group-control {
|
||||||
|
width: 100%;
|
||||||
z-index: 35;
|
z-index: 35;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
@ -115,27 +81,87 @@ div#stream {
|
|||||||
}
|
}
|
||||||
/* for mobile and tablet screen */
|
/* for mobile and tablet screen */
|
||||||
@media screen and (max-width: 1000px) {
|
@media screen and (max-width: 1000px) {
|
||||||
|
/* logo object */
|
||||||
|
object.logo {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
/* control panel robot name input */
|
||||||
|
div.input-group {
|
||||||
|
width: 100%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
span.input-group-addon {
|
||||||
|
font-size: 7vw;
|
||||||
|
padding: 0.5vw 0.5vw !important;
|
||||||
|
}
|
||||||
|
input.form-control {
|
||||||
|
font-size: 7vw;
|
||||||
|
padding: 0.5vw 0.5vw !important;
|
||||||
|
}
|
||||||
|
/* robot connect button */
|
||||||
|
div.btn-group-robot {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
a.btn-robot-go {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 30vw !important;
|
||||||
|
border: 3px solid rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
/* Blockly workspace */
|
||||||
td#blocklyArea {
|
td#blocklyArea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
/* Blockly code area */
|
||||||
td#blocklyCodeArea {
|
td#blocklyCodeArea {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
/* ace editor */
|
||||||
div#blocklyCode {
|
div#blocklyCode {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* for desktop screen */
|
/* for desktop screen */
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
|
/* logo object */
|
||||||
|
object.logo {
|
||||||
|
width: 45%;
|
||||||
|
}
|
||||||
|
/* control panel robot name input */
|
||||||
|
div.input-group {
|
||||||
|
width: 35%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
span.input-group-addon {
|
||||||
|
font-size: 2vw;
|
||||||
|
padding: 0.5vw 0.5vw !important;
|
||||||
|
}
|
||||||
|
input.form-control {
|
||||||
|
font-size: 2vw;
|
||||||
|
padding: 0.5vw 0.5vw !important;
|
||||||
|
}
|
||||||
|
/* robot connect button */
|
||||||
|
div.btn-group-robot {
|
||||||
|
width: 35%;
|
||||||
|
}
|
||||||
|
a.btn-robot-go {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 10vw !important;
|
||||||
|
border: 3px solid rgba(0, 0, 0, 0.1) !important;
|
||||||
|
}
|
||||||
|
/* Blockly workspace */
|
||||||
td#blocklyArea {
|
td#blocklyArea {
|
||||||
width: 60%;
|
width: 60%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
/* Blockly code area */
|
||||||
td#blocklyCodeArea {
|
td#blocklyCodeArea {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
/* ace editor */
|
||||||
div#blocklyCode {
|
div#blocklyCode {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
135
sumorobot.js
135
sumorobot.js
@ -86,52 +86,24 @@ Sumorobot.prototype.close = function() {
|
|||||||
this.websocket.close();
|
this.websocket.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* function to set local storage */
|
||||||
|
function getLocalStorageItem(item) {
|
||||||
|
/* when the local storage doesn't exist, return empty string */
|
||||||
|
if (typeof(Storage) === "undefined") return "";
|
||||||
|
/* otherwise return item from the local storage*/
|
||||||
|
return localStorage.getItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* function to set local storage */
|
||||||
|
function setLocalStorageItem(item, value) {
|
||||||
|
/* when local storage doesn't exist, return */
|
||||||
|
if (typeof(Storage) === "undefined") return;
|
||||||
|
/* otherwise set the item to the local storage */
|
||||||
|
localStorage.setItem(item, value)
|
||||||
|
}
|
||||||
|
|
||||||
window.onload = function() {
|
window.onload = function() {
|
||||||
/* function to update the control panel */
|
$("#robot-id").val(getLocalStorageItem("sumorobot.robotId"));
|
||||||
function updateControlPanel() {
|
|
||||||
/* hide all buttons and text fields */
|
|
||||||
$(".robot-id, .robot-nr, .btn-robot-nr").hide();
|
|
||||||
/* show the first button and text field */
|
|
||||||
$(".robot-id:eq(0), .robot-nr:eq(0), .btn-robot-nr:eq(0)").show();
|
|
||||||
|
|
||||||
/* adjust the buttons and text fields to be in the middle */
|
|
||||||
$(".input-group, .btn-group-robot").css("width", "20%");
|
|
||||||
$(".input-group, .btn-group-robot").css("margin-left", "40%");
|
|
||||||
|
|
||||||
/* hide the robot add button */
|
|
||||||
$(".btn-robot-add").hide();
|
|
||||||
|
|
||||||
/* populate robots IDs and buttons */
|
|
||||||
for (var i = 0; i < 5; i++) {
|
|
||||||
var id = getLocalStorageItem("sumorobot.robotID" + i);
|
|
||||||
if (id) {
|
|
||||||
$(".robot-id:eq(" + i + ")").val(id);
|
|
||||||
$(".robot-id:eq(" + i + "), .robot-nr:eq(" + i + "), .btn-robot-nr:eq(" + i + ")").show();
|
|
||||||
$(".input-group, .btn-group-robot").css("width", 20 + (i * 20) + "%");
|
|
||||||
$(".input-group, .btn-group-robot").css("margin-left", 40 - (i * 10) + "%");
|
|
||||||
} else {
|
|
||||||
/* when no robots yet added */
|
|
||||||
if (i != 0) {
|
|
||||||
/* show the robot add button */
|
|
||||||
$(".btn-robot-add").show();
|
|
||||||
$(".btn-group-robot").css("width", 20 + (i * 20) + "%");
|
|
||||||
$(".input-group, .btn-group-robot").css("margin-left", 40 - (i * 10) + "%");
|
|
||||||
/* add click listener to the robot add button */
|
|
||||||
$(".btn-robot-add").click(function() {
|
|
||||||
$(".robot-id:eq(" + i + "), .robot-nr:eq(" + i + "), .btn-robot-nr:eq(" + i + ")").show();
|
|
||||||
$(".input-group, .btn-group-robot").css("width", 20 + (i * 20) + "%");
|
|
||||||
$(".input-group, .btn-group-robot").css("margin-left", 40 - (i * 10) + "%");
|
|
||||||
$(this).hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load the control panel */
|
|
||||||
updateControlPanel();
|
|
||||||
|
|
||||||
/* load ace editor */
|
/* load ace editor */
|
||||||
pythonEditor = ace.edit("blocklyCode");
|
pythonEditor = ace.edit("blocklyCode");
|
||||||
/* set the style */
|
/* set the style */
|
||||||
@ -356,22 +328,6 @@ window.onload = function() {
|
|||||||
onresize();
|
onresize();
|
||||||
Blockly.svgResize(workspace);
|
Blockly.svgResize(workspace);
|
||||||
|
|
||||||
/* function to set local storage */
|
|
||||||
function getLocalStorageItem(item) {
|
|
||||||
/* when the local storage doesn't exist, return empty string */
|
|
||||||
if (typeof(Storage) === "undefined") return "";
|
|
||||||
/* otherwise return item from the local storage*/
|
|
||||||
return localStorage.getItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* function to set local storage */
|
|
||||||
function setLocalStorageItem(item, value) {
|
|
||||||
/* when local storage doesn't exist, return */
|
|
||||||
if (typeof(Storage) === "undefined") return;
|
|
||||||
/* otherwise set the item to the local storage */
|
|
||||||
localStorage.setItem(item, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* retrieve the blocks */
|
/* retrieve the blocks */
|
||||||
var xml = Blockly.Xml.textToDom(getLocalStorageItem("sumorobot.blockly"));
|
var xml = Blockly.Xml.textToDom(getLocalStorageItem("sumorobot.blockly"));
|
||||||
/* resume the blocks */
|
/* resume the blocks */
|
||||||
@ -454,23 +410,7 @@ window.onload = function() {
|
|||||||
case 40: // down
|
case 40: // down
|
||||||
if (remoteControl) sumorobot.send("backward");
|
if (remoteControl) sumorobot.send("backward");
|
||||||
break;
|
break;
|
||||||
case 49: // 1
|
|
||||||
$(".btn-robot-nr:eq(0)").click();
|
|
||||||
break;
|
|
||||||
case 50: // 2
|
|
||||||
$(".btn-robot-nr:eq(1)").click();
|
|
||||||
break;
|
|
||||||
case 51: // 3
|
|
||||||
$(".btn-robot-nr:eq(2)").click();
|
|
||||||
break;
|
|
||||||
case 52: // 4
|
|
||||||
$(".btn-robot-nr:eq(3)").click();
|
|
||||||
break;
|
|
||||||
case 53: // 5
|
|
||||||
$(".btn-robot-nr:eq(4)").click();
|
|
||||||
break;
|
|
||||||
case 67: // c
|
case 67: // c
|
||||||
updateControlPanel();
|
|
||||||
$("#panel").toggle();
|
$("#panel").toggle();
|
||||||
break;
|
break;
|
||||||
case 76: // l
|
case 76: // l
|
||||||
@ -505,10 +445,8 @@ window.onload = function() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 82: // r
|
case 82: // r
|
||||||
if (remoteControl)
|
/* toggle remote control */
|
||||||
$("#remote-disabled").click();
|
remoteControl = !remoteControl;
|
||||||
else
|
|
||||||
$("#remote-enabled").click();
|
|
||||||
break;
|
break;
|
||||||
case 83: // s
|
case 83: // s
|
||||||
$(".btn-stop").addClass("hover");
|
$(".btn-stop").addClass("hover");
|
||||||
@ -536,11 +474,6 @@ window.onload = function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* start button listener */
|
|
||||||
$(".btn-close").click(function() {
|
|
||||||
$("#stream").hide();
|
|
||||||
});
|
|
||||||
|
|
||||||
/* start button listener */
|
/* start button listener */
|
||||||
$(".btn-start").click(function() {
|
$(".btn-start").click(function() {
|
||||||
sumostart = true;
|
sumostart = true;
|
||||||
@ -562,32 +495,18 @@ window.onload = function() {
|
|||||||
workspace.highlightBlock(lastHighlighted, false);
|
workspace.highlightBlock(lastHighlighted, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* remote control enable listener */
|
|
||||||
$("#remote-enabled").click(function() {
|
|
||||||
remoteControl = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
/* remote control disable listener */
|
|
||||||
$("#remote-disabled").click(function() {
|
|
||||||
remoteControl = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
/* robot number button listener */
|
/* robot number button listener */
|
||||||
$(".btn-robot-nr").click(function() {
|
$(".btn-robot-go").click(function() {
|
||||||
/* extract and validate the selected robot ID */
|
/* extract and validate the selected robot ID */
|
||||||
var index = $(".btn-robot-nr").index($(this));
|
var robotId = $("#robot-id").val().trim();
|
||||||
var robotID = $(".robot-id:eq(" + index + ")").val();
|
if (robotId === "" || /^(sumo-[a-f0-9]{6})$/.test(robotId) == false) {
|
||||||
if (robotID.trim() === "") {
|
$("#robot-id, #robot-label").addClass("has-error");
|
||||||
$(".robot-nr:eq(" + index + "), .robot-id:eq(" + index + ")").addClass("has-error");
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
$(".robot-nr:eq(" + index + "), .robot-id:eq(" + index + ")").removeClass("has-error");
|
$("#robot-id, #robot-label").removeClass("has-error");
|
||||||
}
|
}
|
||||||
/* highlight the selected robot button */
|
|
||||||
$(".btn-robot-nr").removeClass("btn-selected");
|
|
||||||
$(this).addClass("btn-selected");
|
|
||||||
/* update robot IDs in local storage */
|
/* update robot IDs in local storage */
|
||||||
setLocalStorageItem("sumorobot.robotID" + index, robotID);
|
setLocalStorageItem("sumorobot.robotId", robotId);
|
||||||
/* in case there is a open connection */
|
/* in case there is a open connection */
|
||||||
if (sumorobot && blockHighlight) {
|
if (sumorobot && blockHighlight) {
|
||||||
/* close the connections */
|
/* close the connections */
|
||||||
@ -595,9 +514,9 @@ window.onload = function() {
|
|||||||
blockHighlight.close();
|
blockHighlight.close();
|
||||||
}
|
}
|
||||||
/* connect to the selected robots WebSocket */
|
/* connect to the selected robots WebSocket */
|
||||||
sumorobot = new Sumorobot("ws://" + robotServer + ":80/p2p/browser/" + robotID + "/");
|
sumorobot = new Sumorobot("ws://" + robotServer + ":80/p2p/browser/" + robotId + "/");
|
||||||
/* connect to the other block highlight WebSocket */
|
/* connect to the other block highlight WebSocket */
|
||||||
blockHighlight = new WebSocket("ws://" + robotServer + ":80/p2p/browser/" + robotID + "-highlight/");
|
blockHighlight = new WebSocket("ws://" + robotServer + ":80/p2p/browser/" + robotId + "-highlight/");
|
||||||
/* when there is a message from the WebSocket */
|
/* when there is a message from the WebSocket */
|
||||||
blockHighlight.onmessage = function(evt) {
|
blockHighlight.onmessage = function(evt) {
|
||||||
/* when scope is received */
|
/* when scope is received */
|
||||||
|
Loading…
Reference in New Issue
Block a user