Краткий ответ:
Установите флаг и проверьте, установлен ли он перед отправкой запроса.
Длинный ответ:
Требуются два файла.Два файла ниже работают следующим образом:
Вы переходите к FrontEnd.html.Он поддерживает состояние и содержит iframe.Iframe загружается с BackEnd.php (его переменные состояния установлены в значения по умолчанию и передаются через метод get).Когда клавиша нажата или отпущена, FrontEnd.html перезагружает iframe с BackEnd.php (передача состояния через метод get).
BackEnd.php отправляет сообщение на последовательный порт и отображает состояние клавиш со стрелками на основе переменных, переданных ему из FrontEnd.html.
<!doctype html>
<html lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
var controllerIsReady = false;
var keyEventBuffer = new Array();
var keyBeingHeld = new Array();
keyBeingHeld[0] = false;//left
keyBeingHeld[1] = false;//right
keyBeingHeld[2] = false;//up
keyBeingHeld[3] = false;//down
function controllerReady(){
controllerIsReady = false;
if(keyEventBuffer.length > 0){
bufferDiv = document.getElementById('eventBuffer');
buffHtmlStr = " ";
for (i=0;i<keyEventBuffer.length;i++){
tempStr = keyEventBuffer[i];
index = tempStr.indexOf("action", 0)+7;
keyEventStr = tempStr.substr(index,(tempStr.length-index));
buffHtmlStr = buffHtmlStr + "<br />" + keyEventStr;
}
bufferDiv.innerHTML = buffHtmlStr;
//shift event off and make request
stateStr = keyEventBuffer.shift();
iframe = document.getElementById('stateFrame');
iframe.src = "http://www.vdstudios.net/robotics/BackEnd.php"+stateStr;
}
else{
controllerIsReady = true;//alert("ready");
bufferDiv = document.getElementById('eventBuffer');
bufferDiv.innerHTML = "empty";
}
}
function setControllerState(action){
leftPressState="up";
rightPressState="up";
upPressState="up";
downPressState="up";
if (keyBeingHeld[0]){
leftPressState="down";
}
if (keyBeingHeld[1]){
rightPressState="down";
}
if (keyBeingHeld[2]){
upPressState="down";
}
if (keyBeingHeld[3]){
downPressState="down";
}
var stateStr = "?upPressState="+upPressState+"&downPressState="+downPressState+"&leftPressState="+leftPressState+"&rightPressState="+rightPressState+"&action="+action;
//add stateStr to fifo and if controllerIsReady call controllerReady
keyEventBuffer.push(stateStr);
if(controllerIsReady){
controllerReady();
}
}
$(document).keydown(function(event) {
if (!event) var event = window.event;
switch (event.keyCode) {
case 37:
if (!keyBeingHeld[0]){
keyBeingHeld[0] = true;
setControllerState ("leftArrowPress");
}
break;
case 38:
if (!keyBeingHeld[2]){
keyBeingHeld[2] = true;
setControllerState ("upArrowPress");
}
break;
case 39:
if (!keyBeingHeld[1]){
keyBeingHeld[1] = true;
setControllerState ("rightArrowPress");
}
break;
case 40:
if (!keyBeingHeld[3]){
keyBeingHeld[3] = true;
setControllerState ("downArrowPress");
}
break;
}
});
$(document).keyup(function(event) {
if (!event) var event = window.event;
switch (event.keyCode) {
case 37:
if (keyBeingHeld[0]){
keyBeingHeld[0] = false;
setControllerState ("leftArrowRelease");
}
break;
case 38:
if (keyBeingHeld[2]){
keyBeingHeld[2] = false;
setControllerState ("upArrowRelease");
}
break;
case 39:
if (keyBeingHeld[1]){
keyBeingHeld[1] = false;
setControllerState ("rightArrowRelease");
}
break;
case 40:
if (keyBeingHeld[3]){
keyBeingHeld[3] = false;
setControllerState ("downArrowRelease");
}
break;
}
});
</script>
</head>
<body>
<p>Press one of the arrow keys.</p>
<iframe id="stateFrame" name="stateFrame" style="width:160px;height:180px;" src="http://www.vdstudios.net/robotics/BackEnd.php?upPressState=up&downPressState=up&leftPressState=up&rightPressState=up&action=none"></iframe>
<div style="width:160px;padding:2px;padding-top:5px;background-color:#cccccc;text-align:center;">Event buffer<hr /><div id="eventBuffer" style="width:100%;">text</div></div>
</body>
</html>
BackEnd.php
<?php
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
// HTTP/1.0
header("Pragma: no-cache");
$upPressState = cleanupSpecialChars($_GET['upPressState']) or $upPressState = 'up';
$downPressState = cleanupSpecialChars($_GET['downPressState']) or $downPressState = 'up';
$leftPressState = cleanupSpecialChars($_GET['leftPressState']) or $leftPressState = 'up';
$rightPressState = cleanupSpecialChars($_GET['rightPressState']) or $rightPressState = 'up';
$action = cleanupSpecialChars($_GET['action']) or $action = 'none';
//send message to serial port
if($action == "upArrowPress"){
sendCMD(25);
}
else if($action == "downArrowPress"){
sendCMD(24);
}
else if($action == "leftArrowPress"){
sendCMD(28);
}
else if($action == "rightArrowPress"){
sendCMD(29);
}
else if($action == "upArrowRelease"){
sendCMD(15);
}
else if($action == "downArrowRelease"){
sendCMD(14);
}
else if($action == "leftArrowRelease"){
sendCMD(18);
}
else if($action == "rightArrowRelease"){
sendCMD(19);
}
//the rest is to display the state
$pressedColor = "bbffbb";
$releasedColor = "bbbbbb";
$upArrowColor = $releasedColor;
$downArrowColor = $releasedColor;
$leftArrowColor = $releasedColor;
$rightArrowColor = $releasedColor;
if($upPressState == "down"){
$upArrowColor = $pressedColor;
}
if($downPressState == "down"){
$downArrowColor = $pressedColor;
}
if($leftPressState == "down"){
$leftArrowColor = $pressedColor;
}
if($rightPressState == "down"){
$rightArrowColor = $pressedColor;
}
echo("<html><head><style>");
echo("body{background-color:#000000;}
div#container{position:absolute;left:10px;top:10px;background-color:#eeeeee;
font-size:20px;padding:20px;width:100px;height:92px;text-align:center;}
div.arrow{position:absolute;width:30px;padding-top:2px;padding-bottom:2px;}
div#upArrow{left:55px;top:20px;background-color:#".$upArrowColor.";}
div#downArrow{left:55px;top:82px;background-color:#".$downArrowColor.";}
div#leftArrow{left:20px;top:50px;background-color:#".$leftArrowColor.";}
div#rightArrow{left:90px;top:50px;background-color:#".$rightArrowColor.";}
div#lastAction{position:absolute;left:0px;bottom:2px;font-size:14px;color:#ffffee;}");
echo("</style></head><body onload='parent.controllerReady();'>");
echo("<div id='container'>
<div class='arrow' id='upArrow'>↑</div><div class='arrow' id='downArrow'>↓</div>
<div class='arrow' id='leftArrow'>←</div><div class='arrow' id='rightArrow'>→</div>
</div><div id='lastAction'>Last Action:<br />".$action."</div>");
echo("</body></html>");
//cleanup input
function cleanupSpecialChars($inStr){
$tempStr = htmlentities(stripslashes($inStr));
$retStr = str_replace(array('\\','/'), '', $tempStr);
return $retStr;
}
function sendCMD($cmd){
if($fp =fopen("com4", "wb")){//windows server
fwrite($fp,$cmd);
usleep(15000);
fclose($fp);
}
else if($fp =fopen("/dev/ttyS3", "wb")){//linux server
fwrite($fp,$cmd);
usleep(15000);
fclose($fp);
}
}
?>
Вы можете увидеть их на моем сервере здесь: http://www.vdstudios.net/robotics/FrontEnd.html
Я могу помочь вам с созданием сообщения дляпоследовательный порт, если вы дадите мне подробную информацию о том, что ожидает устройство.
РЕДАКТИРОВАТЬ:
Добавлен код для построения / отправки сообщения на последовательный порт.Также обновлен запущенный пример с тем же.Вы можете увидеть это по ссылке выше.
Редактировать 2:
Добавлен код для буферизации ключевых событий.Добавлен код для синхронизации состояний бэкэнда и внешнего интерфейса.