After building the iPad-serial-to-Cisco-console-management-cable I decided that using minicom was a bit unhandy.

So i hacked together a bit of python with pySerial and added some lines of HTML and Javascript:


#!/usr/bin/python

ip = "127.0.0.1"
port = 8080
maxidle = 30

import socket, thread
import serial
import sys
import signal
from time import sleep
from urllib import unquote_plus

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

bound=False
while not bound:
try:
sock.bind((ip,port))
bound=True
except:
sleep(1)

try:
# on iPad
ser = serial.Serial( port='/dev/tty.iap',
parity=serial.PARITY_NONE, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE,
timeout=1, xonxoff=0, rtscts=0, baudrate=9600)
except:
# on PC
ser = serial.Serial( port=0,
parity=serial.PARITY_NONE, bytesize=serial.EIGHTBITS, stopbits=serial.STOPBITS_ONE,
timeout=1, xonxoff=0, rtscts=0, baudrate=9600)

print "Port is:" + ser.portstr
ser.flushInput()
ser.write("\n")

print "Listening on Port: ", port

sock.listen(1)
messages = []

def client(psock,addr):
global messages
data = psock.recv(1024*100)
if data[:3] == "GET":
data = data.split("\n")[0].split(" ")[1][1:]
if data <> "favicon.ico":
if data == "get":
psock.send("HTTP/1.0 200 OK\nContent-Type: text/plain\n\n")
lock.acquire()
for a in messages:
psock.send(a)
messages = []
lock.release()
elif data[0:4] == "post":
psock.send("HTTP/1.0 200 OK\nContent-Type: text/plain\n\n")
cmd = data[5:]
cmd = unquote_plus(cmd)
for l in cmd.splitlines(1):
ser.write(l)
sleep(.1)
else:
psock.send("HTTP/1.0 200 OK\nContent-Type: text/html\n\n")
psock.send(file("webserialclient.html",'r').read(8192))
psock.close()

def serThread():
global messages
while True:
line = ser.read(10)
if len(line)>0:
lock.acquire()
messages.append(line)
lock.release()

lock = thread.allocate_lock()
tg = thread.start_new_thread(serThread,())

def handler(sig,f):
sock.close()
print "exiting"
exit()

signal.signal(signal.SIGTERM, signal.SIG_IGN)
signal.signal(signal.SIGALRM, handler)

while True:
signal.alarm(maxidle)
csock,addr = sock.accept()
client(csock,addr)

webserial.py



<html>
<head>
<title>
web2ser
</title>
<meta name="viewport" content="width=768px, minimum-scale=1.0, maximum-scale=1.0" />
</head>
<body>
<style type="text/css">
* {
margin:0;
padding:0;
}
body {
font-size:100%;
text-align:center;
background:#eee;
}
textarea {
width:708px;
height:500px;
margin:0; padding:0;
background:#fff;
font-family:monospace;
}

.cmd { font-size:100%; margin:8px; width:320px; }

.button {
font-size:100%;
font-weight: bold;
width: 170px;
margin:8px;
}

/* Landscape mode (default) */
#wrap {
margin:0 auto;
width:1024px;
position:relative;
overflow:hidden;
text-align:left;
}
#header {
float:left;
width:1024px;
padding:10px 10px 0px 35px;
}
#content {
float:left;
width:1024px;
position:relative;
left:768px;
}
#main {
float:left;
width:708px;
position:relative;
right:738px;
padding:10px;
}
#side {
float:right;
width:216px;
position:relative;
right:788px;
padding-top:20px;
padding-bottom:20px;
text-align:center;
}
#sidea,
#sideb,
#sidec {
clear:left;
float:left;
width:216px;
}
#footer {
clear:both;
float:left;
width:1024px;
border-top:1px solid #000;
padding: 5px 20px 5px 20px;
}

@media only screen and (orientation:portrait){
/* portrait mode */
#header,
#wrap,
#footer {
width:768px;
}
#content {
left:0;
}
#main {
float:left;
width:708px;
position:relative;
right:0;
left:30px;
padding:20px 0;
}
#side {
clear:left;
float:left;
width:768px;
right:0;
padding-bottom:20px;
}
#sidea {
clear:none;
width:216px;
float:left;
position:relative;
left:30px;
padding-top:20px;
}
#sideb {
clear:none;
width:216px;
float:left;
position:relative;
left:60px;
padding-top:20px;
}
#sidec {
clear:none;
width:216px;
float:right;
position:relative;
right:30px;
padding-top:20px;
}
}
</style>
<script type="text/javascript">
function $(id) {
return document.getElementById(id);
}

var pollinterval=pollintervalmin=100;
var pollintervallimit=5000;
var myTimeout = null;
function mySetTimeout(interval) {
if(myTimeout != null)
clearTimeout(myTimeout);
myTimeout=window.setTimeout("getData()", interval);
}

function getData() {

var xmlhttp = null;
// Mozilla
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.open("GET", 'get', true);
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
if(xmlhttp.responseText.length>0) {
$('output').value += xmlhttp.responseText;
$('output').scrollTop = $('output').scrollHeight;
pollinterval=pollintervalmin;
}
else
if(pollinterval<pollintervallimit)
pollinterval *=2;
mySetTimeout(pollinterval);
}
else if(xmlhttp.readyState == 4 && xmlhttp.status == 0) {
alert("Can't connect to WebSerial-server. Please start it");
}
}
xmlhttp.send(null);
mySetTimeout(pollintervallimit);
}

function sendCMD(val) {

var xmlhttp = null;
// Mozilla
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
}
// IE
else if (window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.open("GET", 'post?'+val, true);
xmlhttp.onreadystatechange = function() { ; };
xmlhttp.send(null);
mySetTimeout(pollintervalmin);
pollinterval=pollintervalmin;
$('cmd').blur();
return false;
}

function init() {
mySetTimeout(pollinterval);
}
window.onload=init;
</script>
<form name='chat' action='#' onsubmit="return false;">
<div id="wrap">
<div id="header">
<input type='text' name='cmd' id='cmd' class="cmd" size='40' value='' autocapitalize="off" />
<input type="button" class="button" value="Send" onclick="return sendCMD($('cmd').value);" />
<input type='submit' class="button" value="Send w/ Return" onclick="return sendCMD($('cmd').value+'%0D');" />
</div>
<div id="content">
<div id="main"><textarea id=output readonly></textarea></div>
<div id="side">
<div id="sidea">
<input type="button" class="button" value="Return" onclick="return sendCMD('%0D');" /><br/>
<input type="button" class="button" value="Login" onclick="return sendCMD('loginpass%0Dterm len 0%0D');" /><br/>
<input type="button" class="button" value="Enable" onclick="return sendCMD('en%0Denablepass%0D');" /><br/>
<input type="button" class="button" value="Exit" onclick="return sendCMD('exit%0D');" /><br/>
</div>
<div id="sideb">
<input type="button" class="button" value="show int" onclick="return sendCMD('sh int %0D');" /><br/>
<input type="button" class="button" value="show int status" onclick="return sendCMD('sh int statu%0D');" /><br/>
<input type="button" class="button" value="show config" onclick="return sendCMD('sh conf%0D');" /><br/>
<input type="button" class="button" value="show version" onclick="return sendCMD('sh ver%0D');" /><br/>
</div>
<!--div id="sidec">
<input type="button" class="button" value="show int" onclick="return sendCMD('sh int %0D');" /><br/>
<input type="button" class="button" value="show int status" onclick="return sendCMD('sh int statu%0D');" /><br/>
<input type="button" class="button" value="show config" onclick="return sendCMD('sh conf%0D');" /><br/>
<input type="button" class="button" value="show version" onclick="return sendCMD('sh ver%0D');" /><br/>
</div-->
</div>
</div>
<div id="footer"></div>
</div>
</form>
</body>
</html>


webserialclient.html

Comments

Add Comment

Fill out the form below to add your own comments.









Insert Special:






Moderation is turned on for this blog. Your comment will require the administrators approval before it will be visible.