Spinneret *Timeout*
Hello all
I plug my spinneret on the internet and there is some mistake.
When I access the server 24.230.203.105:5555 with WiFi I have no problem. But when I use another internet connection that does not work at all or it works half the time. Have you any idea?
I try to access the server with my iPhone 4 and it works well with WiFi connection but nothing to do with the cellular network. It still gives the same error. * Timeout * Do you know why?
There is the PST message
Start of Request
ID: 0
Request Count : 16
3-14 2-14 1-14 0-18
clsd open lstn estb clwt clng udps
0000-0000-1110-0001-0000-0000-0000
FIFO[0] 00000000
* Timeout *
There is the code i use
And here is the link to my Spinnerete if you want to try a connection and tell me what result you http://24.230.203.105:5555/index.htm
I plug my spinneret on the internet and there is some mistake.
When I access the server 24.230.203.105:5555 with WiFi I have no problem. But when I use another internet connection that does not work at all or it works half the time. Have you any idea?
I try to access the server with my iPhone 4 and it works well with WiFi connection but nothing to do with the cellular network. It still gives the same error. * Timeout * Do you know why?
There is the PST message
Start of Request
ID: 0
Request Count : 16
3-14 2-14 1-14 0-18
clsd open lstn estb clwt clng udps
0000-0000-1110-0001-0000-0000-0000
FIFO[0] 00000000
* Timeout *
There is the code i use
{{
─────────────────────────────────────────────────
Copyright (c) 2011 AgaveRobotics LLC.
See end of file for terms of use.
File....... HTTPServer.spin
Author..... Mike Gebhard
Company.... Agave Robotics LLC
Email...... mailto:mike.gebhard@agaverobotics.com
Started.... 11/01/2010
Updated.... 07/16/2011
─────────────────────────────────────────────────
}}
{
About:
HTTPServer is the designed for use with the Spinneret Web server manufactured by Parallax Inc.
Usage:
HTTPServer is the top level object.
Required objects:
Parallax Serial Terminal.spin
W5100_Indirect_Driver.spin
S35390A_SD-MMC_FATEngineWrapper.spin
Request.spin
Response.spin
StringMethods.spin
S35390A_RTCEngine.spin
Change Log:
}
CON
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
MAX_PACKET_SIZE = $5C0 '1472 '$800 = 2048
RxTx_BUFFER = $800 '$600 = 1536
TEMP_BUFFER = $600 '$5B4 = 1460
TCP_PROTOCOL = 01 '$300 = 768
UDP_PROTOCOL = 10 '$200 = 512
TCP_CONNECT = $04 '$100 = 256
DELAY = $05
MAX_TRIES = $05
#0, DONE, PUT, CD
DAT
mac byte $00, $08, $DC, $16, $F2, $73
subnet byte 255, 255 ,255, 0
gateway byte 24,230,203,1
ip byte 192,168,0,105
port word 5555
remoteIp byte 24,230,203,105
remotePort word 80
uport word 5050
emailIp byte 0, 0, 0, 0
emailPort word 25
status byte $00, $00, $00, $00
rxdata byte $0[RxTx_BUFFER]
txdata byte $0[RxTx_BUFFER]
udpdata byte $0[TEMP_BUFFER]
fileErrorHandle long $0
debug byte $0
lastFile byte $0[12], 0
closedState byte 00
openState byte 00
listenState byte 00
establishedState byte 00
closingState byte 00
closeWaitState byte 00
lastEstblState byte 00
lastEstblStateDebug byte 00
udpListen byte 00
tcpMask byte 11
udpMask byte 00
fifoSocketDepth byte $0
fifoSocket long $00_00_00_00
debugSemId byte $00
debugCounter long $00
stringMethods long $00
closingTimeout long $00, $00, $00, $00
udpLen long $00
time byte "00/00/0000 00:00:00", 0
httpDate byte "Wed, 01 Feb 2000 01:00:00 GMT", 0
globalCache byte $0
VAR
long StackSpace[20]
OBJ
pst : "Parallax Serial Terminal"
Socket : "W5100_Indirect_Driver"
SDCard : "S35390A_SD-MMC_FATEngineWrapper"
Request : "Request"
Response : "Response"
str : "StringMethods"
rtc : "S35390A_RTCEngine"
PUB Initialize | id, size, st
debug := 1
SDCard.Start
stringMethods := str.Start
Request.Constructor(stringMethods)
Response.Constructor(stringMethods, @txdata)
pst.Start(115_200)
pause(200)
'Mount the SD card
pst.str(string("Mount SD Card - "))
SDCard.mount(fileErrorHandle)
pst.str(string("OK",13))
pst.str(string("Start RTC: "))
rtc.RTCEngineStart(29, 28, -1)
pause(200)
pst.str(FillTime)
'Start the W5100 driver
if(Socket.Start)
pst.str(string(13, "W5100 Driver Started", 13))
pst.str(string(13, "Status Memory Lock ID : "))
pst.dec(Socket.GetLockId)
pst.char(13)
if(debugSemId := locknew) == -1
pst.str(string("Error, no HTTP server locks available", 13))
else
pst.str(string("HTTP Server Lock ID : "))
pst.dec(debugSemId)
pst.char(13)
'Set the Socket addresses
SetMac(@mac)
SetGateway(@gateway)
SetSubnet(@subnet)
SetIP(@ip)
' Initailize TCP sockets (defalut setting; TCP, Port, remote ip and remote port)
repeat id from 0 to 3
InitializeSocket(id)
Request.Release(id)
pause(50)
' Set all TCP sockets to listen
pst.char(13)
repeat id from 0 to 3
Socket.Listen(id)
pst.str(string("TCP Socket Listener ID : "))
pst.dec(id)
pst.char(13)
pause(50)
pst.Str(string(13,"Started Socket Monitoring Service", 13))
cognew(StatusMonitor, @StackSpace)
pause(250)
pst.Str(string(13, "Initial Socket States",13))
StackDump
pst.Str(string(13, "Initial Socket Queue",13))
QueueDump
pst.str(string(13,"//////////////////////////////////////////////////////////////",13))
Main
PUB Main | packetSize, id, i, reset, j, temp
''HTTP Service
repeat
repeat until fifoSocket == 0
bytefill(@rxdata, 0, RxTx_BUFFER)
if(debug)
pst.str(string(13, "----- Start of Request----------------------------",13))
pause(DELAY)
else
pause(DELAY)
' Pop the next socket handle
id := DequeueSocket
if(id < 0)
next
if(debug)
pst.str(string(13,"ID: "))
pst.dec(id)
pst.str(string(13, "Request Count : "))
pst.dec(debugCounter)
pst.char(13)
packetSize := Socket.rxTCP(id, @rxdata)
reset := false
if ((packetSize < 12) AND (strsize(@rxdata) < 12))
repeat i from 0 to MAX_TRIES
'pst.str(string(13,"* Retry *"))
'Wait for a few moments and try again
waitcnt((clkfreq/500) + cnt)
packetSize := Socket.rxTCP(id, @rxdata)
if(packetSize > 12)
quit
if(i == MAX_TRIES)
'Clean up resource request
Request.Release(id)
Socket.Disconnect(id)
reset := true
if(debug)
StackDump
pst.char(13)
QueueDump
pst.str(string(13,"* Timeout *",13))
if(reset)
next
Request.InitializeRequest(id, @rxdata)
if(debug)
pst.char(13)
HeaderLine1(id)
else
pause(DELAY)
' Process router
Dispatcher(id)
'Clean up request resource
Request.Release(id)
' This starts the close process -> 0x00
' use close to force a close
Socket.Disconnect(id)
bytefill(@txdata, 0, RxTx_BUFFER)
debugCounter++
GotoMain
PRI GotoMain
Main
PRI Dispatcher(id)
''Do some processing before sending the response
if(strcomp(Request.GetName(id), string("led")))
Led(id)
StaticFileHandler(id)
return
PRI Led(id) | qstr
'' Get the query string value
qstr := Request.Get(id, string("led"))
if (strcomp( string("on"), qstr ))
LedStatus(1)
else
LedStatus(0)
return
PRI LedStatus(state)
dira[23]~~
outa[23] := state
return
PRI StaticFileHandler(id) | fileSize, i, headerLen, temp, j
''Serve up static files from the SDCard
'pst.str(string(13,"Static File Handler",13))
SDCard.changeDirectory(@approot)
pst.char(13)
'Make sure the directory exists
ifnot(ChangeDirectory(id))
'send 404 error
WriteError(id)
SDCard.changeDirectory(@approot)
return
' Make sure the file exists
ifnot(FileExists(Request.GetFileName(id)))
'send 404 error
WriteError(id)
SDCard.changeDirectory(@approot)
return
' Open the file for reading
SDCard.openFile(Request.GetFileName(id), "r")
fileSize := SDCard.getFileSize
'WriteResponseHeader(id)
'BuildHeader(extension, statusCode, expirer)
headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache)
Socket.txTCP(id, @txdata, headerLen)
if fileSize < MAX_PACKET_SIZE
' send the file in one packet
SDCard.readFromFile(@txdata, fileSize)
Socket.txTCP(id, @txdata, fileSize)
else
' send the file in a bunch of packets
repeat
SDCard.readFromFile(@txdata, MAX_PACKET_SIZE)
Socket.txTCP(id, @txdata, MAX_PACKET_SIZE)
fileSize -= MAX_PACKET_SIZE
' once the remaining fileSize is less then the max packet size, just send that remaining bit and quit the loop
if fileSize < MAX_PACKET_SIZE and fileSize > 0
SDCard.readFromFile(@txdata, fileSize)
Socket.txTCP(id, @txdata, fileSize)
quit
' Bailout
if(i++ > 1_000_000)
WriteError(id)
quit
SDCard.closeFile
SDCard.changeDirectory(@approot)
return
PRI WriteError(id) | headerOffset
'' Simple 404 error
pst.str(string(13, "Write 404 Error",13 ))
headerOffset := Response.BuildHeader(Request.GetExtension(id), 404, false)
Socket.txTCP(id, @txdata, headerOffset)
return
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' directory and file handlers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI ChangeDirectory(id) | i, found
'Handle directory structure for this Request
if(Request.GetDepth(id) > 1)
repeat i from 0 to Request.GetDepth(id)-2
'Return if the directory is not found
ifnot(FileExists(Request.GetPathNode(id, i)))
return false
found := SDCard.changeDirectory(Request.GetPathNode(id, i))
return true
PRI FileExists(fileToCompare) | filenamePtr
'Start file find at the top of the list
SDCard.startFindFile
'Verify that the file exists
repeat while filenamePtr <> 0
filenamePtr := SDCard.nextFile
if(str.MatchPattern(filenamePtr, fileToCompare, 0, false ) == 0 )
return true
return false
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Time Methods and Formats
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetTime(id) | ptr, headerOffset
ptr := @udpdata
FillHttpDate
bytemove(ptr, string("<p>"),3)
ptr += 3
bytemove(ptr, @httpDate, strsize(@httpDate))
ptr += strsize(@httpDate)
bytemove(ptr, string("</p>"),4)
ptr += 3
headerOffset := Response.BuildHeader(Request.GetExtension(id), 200, false)
Socket.txTCP(id, @txdata, headerOffset)
StringSend(id, @udpdata)
bytefill(@udpdata, 0, TEMP_BUFFER)
return
PRI FillTime | ptr, num
'ToString(integerToConvert, destinationPointer)
'00/00/0000 00:00:00
ptr := @time
rtc.readTime
FillTimeHelper(rtc.clockMonth, ptr)
ptr += 3
FillTimeHelper(rtc.clockDate, ptr)
ptr += 3
FillTimeHelper(rtc.clockYear, ptr)
ptr += 5
FillTimeHelper(rtc.clockHour , ptr)
ptr += 3
FillTimeHelper(rtc.clockMinute , ptr)
ptr += 3
FillTimeHelper(rtc.clockSecond, ptr)
return @time
PRI FillHttpDate | ptr, num, temp
'ToString(integerToConvert, destinationPointer)
'Wed, 01 Feb 2000 01:00:00 GMT
ptr := @httpDate
rtc.readTime
temp := rtc.getDayString
bytemove(ptr, temp, strsize(temp))
ptr += strsize(temp) + 2
FillTimeHelper(rtc.clockDate, ptr)
ptr += 3
temp := rtc.getMonthString
bytemove(ptr, temp, strsize(temp))
ptr += strsize(temp) + 1
FillTimeHelper(rtc.clockYear, ptr)
ptr += 5
FillTimeHelper(rtc.clockHour , ptr)
ptr += 3
FillTimeHelper(rtc.clockMinute , ptr)
ptr += 3
FillTimeHelper(rtc.clockSecond, ptr)
return @httpDate
PRI FillTimeHelper(number, ptr) | offset
offset := 0
if(number < 10)
offset := 1
str.ToString(@number, @tempNum)
bytemove(ptr+offset, @tempNum, strsize(@tempNum))
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' SDCard Logger
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI AppendLog(logToAppend)
'' logToAppend: Pointer to a string of test we'd like to log
SDCard.changeDirectory(@approot)
if(FileExists(@logfile))
SDCard.openFile(@logfile, "A")
else
SDCard.newFile(@logfile)
SDCard.writeData(string(13,10,"----- Start "),14)
SDCard.writeData(FillTime, 19)
SDCard.writeData(string(" -----"),6)
SDCard.writeData(@crlf_crlf, 2)
SDCard.writeData(logToAppend, strsize(logToAppend))
SDCard.writeData(@crlf_crlf, 2)
SDCard.writeData(string("----- End "),10)
SDCard.writeData(FillTime, 19)
SDCard.writeData(string(" -----"),6)
SDCard.writeData(@crlf_crlf, 2)
SDCard.closeFile
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Memory Management
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI Set(DestAddress, SrcAddress, Count)
bytemove(DestAddress, SrcAddress, Count)
bytefill(DestAddress+Count, $0, 1)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Socekt helpers
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetTcpSocketMask(id)
return id & tcpMask
PRI DecodeId(value) | tmp
if(01 & value)
return 0
if(10 & value)
return 1
if(00 & value)
return 2
if(00 & value)
return 3
return -1
PRI QueueSocket(id) | tmp
if(fifoSocketDepth > 4)
return false
tmp := |< id
'Unique check
ifnot(IsUnique(tmp))
return false
tmp <<= (fifoSocketDepth++) * 8
fifoSocket |= tmp
return true
PRI IsUnique(encodedId) | tmp
tmp := encodedId & $0F
repeat 4
if(encodedId & fifoSocket)
return false
encodedId <<= 8
return true
PRI DequeueSocket | tmp
if(fifoSocketDepth == 0)
return -2
repeat until not lockset(debugSemId)
tmp := fifoSocket & $0F
fifoSocket >>= 8
fifoSocketDepth--
lockclr(debugSemId)
return DecodeId(tmp)
PRI ResetSocket(id)
Socket.Disconnect(id)
Socket.Close(id)
PRI IsolateTcpSocketById(id) | tmp
tmp := |< id
tcpMask &= tmp
PRI SetTcpSocketMaskById(id, state) | tmp
'' The tcpMask contains the socket the the StatusMonitor monitors
tmp := |< id
if(state == 1)
tcpMask |= tmp
else
tmp := !tmp
tcpMask &= tmp
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' W5100 Helper methods
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI GetCommandRegisterAddress(id)
return Socket#_S0_CR + (id * $0100)
PRI GetStatusRegisterAddress(id)
return Socket#_S0_SR + (id * $0100)
PRI SetMac(_firstOctet)
Socket.WriteMACaddress(true, _firstOctet)
return
PRI SetGateway(_firstOctet)
Socket.WriteGatewayAddress(true, _firstOctet)
return
PRI SetSubnet(_firstOctet)
Socket.WriteSubnetMask(true, _firstOctet)
return
PRI SetIP(_firstOctet)
Socket.WriteIPAddress(true, _firstOctet)
return
PRI StringSend(id, _dataPtr)
Socket.txTCP(id, _dataPtr, strsize(_dataPtr))
return
PRI SendChar(id, _dataPtr)
Socket.txTCP(id, _dataPtr, 1)
return
PRI SendChars(id, _dataPtr, _length)
Socket.txTCP(id, _dataPtr, _length)
return
PRI InitializeSocket(id)
Socket.Initialize(id, TCP_PROTOCOL, port, remotePort, @remoteIp)
return
PRI InitializeSocketForEmail(id)
Socket.Initialize(id, TCP_PROTOCOL, port, emailPort, @emailIp)
return
PRI InitializeUPDSocket(id)
Socket.Initialize(id, UDP_PROTOCOL, uport, remotePort, @remoteIp)
return
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'' Debug/Display Methods
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
PRI QueueDump
'' Display socket IDs in the queue
'' ie 00000401 -> socket Zero is next to pop off
pst.str(string("FIFO["))
pst.dec(fifoSocketDepth)
pst.str(string("] "))
pst.hex(fifoSocket, 8)
PRI StackDump | clsd, open, lstn, estb, clwt, clng, id, ulst
'' This method is purely for debugging
'' It displays the status of all socket registers
repeat until not lockset(debugSemId)
clsd := closedState
open := openState
lstn := listenState
estb := establishedState
clwt := closeWaitState
clng := closingState
ulst := udpListen
lockclr(debugSemId)
pst.char(13)
repeat id from 3 to 0
pst.dec(id)
pst.str(string("-"))
pst.hex(status[id], 2)
pst.str(string(" "))
pause(1)
pst.str(string(13,"clsd open lstn estb clwt clng udps", 13))
pst.bin(clsd, 4)
pst.str(string("-"))
pst.bin(open, 4)
pst.str(string("-"))
pst.bin(lstn, 4)
pst.str(string("-"))
pst.bin(estb, 4)
pst.str(string("-"))
pst.bin(clwt, 4)
pst.str(string("-"))
pst.bin(clng, 4)
pst.str(string("-"))
pst.bin(ulst, 4)
pst.char(13)
PRI HeaderLine1(id) | i
pst.str(Request.GetMethod(id))
pst.char($20)
i := 0
repeat Request.GetDepth(id)
pst.char($2F)
pst.str(Request.GetPathNode(id, i++))
PRI Pause(Duration)
waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
return
PRI StatusMonitor | id, tmp, value
'' StatusMonitor is the heartbeat of the project
'' Here we monitor the state of the Wiznet 5100's 4 sockets
repeat
Socket.GetStatus32(@status[0])
' Encode status register states
repeat until not lockset(debugSemId)
closedState := openState := listenState := establishedState := {
} closeWaitState := closingState := 0
repeat id from 0 to 3
case(status[id])
$00: closedState |= |< id
closedState &= tcpMask
$13: openState |= |< id
openState &= tcpMask
$14: listenState |= |< id
listenState &= tcpMask
$17: establishedState |= |< id
establishedState &= tcpMask
$18,$1A,$1B: closingState |= |< id
closingState &= tcpMask
$1C: closeWaitState |= |< id
closeWaitState &= tcpMask
$1D: closingState |= |< id
closingState &= tcpMask
$22: udpListen |= |< id
udpListen &= udpMask
if(lastEstblState <> establishedState)
value := establishedState
repeat while value > 0
tmp := DecodeId(value)
if(tmp > -1)
QueueSocket(tmp)
tmp := |< tmp
tmp := !tmp
value &= tmp
lastEstblState := establishedState
lockclr(debugSemId)
' Initialize a closed socket
if(closedState > 0)
id := DecodeId(closedState)
if(id > -1)
InitializeSocket(id & tcpMask)
'Start a listener on an initialized/open socket
if(openState > 0)
id := DecodeId(openState)
if(id > -1)
Socket.Listen(id & tcpMask)
' Close the socket if the status is close/wait
' response processor should close the socket with disconnect
' there could be a timeout so we have a forced close.
' TODO: CCheck for a port that gets stuck in a closing state
'if(closeWaitState > 0)
'id := DecodeId(closeWaitState)
'if(id > -1)
'Socket.Close(id & tcpMask)
'pause(100)
return
DAT
approot byte "\", 0
defaultpage byte "index.htm", 0
logfile byte "log.txt", 0
'binFile byte "filename.bin", 0
FS byte "/", 0
fn byte "filename=", 0
doublequote byte $22, 0
crlf byte 13, 10, 0
crlf_crlf byte 13, 10, 13, 10, 0
uploadfile byte $0[12], 0
uploadfolder byte "uploads", 0
tempNum byte "0000",0
multipart byte "Content-Type: multipart/form-data; boundary=",0
boundary byte $2D, $2D
boundary1 byte $0[64]
'loadme file "TogglePin0.binary"
{{
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ TERMS OF USE: MIT License │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
│files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
│modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
│is furnished to do so, subject to the following conditions: │
│ │
│The above copyright notice and this permission notice shall be included in all copies or substantial ions of the Software.│
│ │
│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
│WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
│COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
│ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
}}
And here is the link to my Spinnerete if you want to try a connection and tell me what result you http://24.230.203.105:5555/index.htm

Comments
See the following post (18) for more information.
http://forums.parallax.com/showthread.php?138781-Spinneret-Errors-%28Can-t-load-page!%29
Now all work. But I want to know if it's possible to the LED to not turning off wen i click on the LED.htm link ? And if it is possible to show the current LED status even wen it's the firs time I load the LED.htm ?
My problem is that i don't want necessarily to change the LED or light status wen I'm out of my house .. i just want to know the status. If someone turn on the light i don't want to make I'm freak because the light is turning off all time i check the LED status..
http://spinneret.servebeer.com:5000/services/ajaxled.htm
A simple AJAX HTTP GET request can return the state of any pin and update the DOM.
This is an example from the tutorial where the current time is requested when the page loads. Successive requests (Clicking the link) invoke an AJAX request where only the <span id="placeholder"></span> is updated in the DOM.
<html> <head> <title>Get Time</title> <script language="javascript" type="application/javascript"> //Gets the browser specific XmlHttpRequest Object function getXmlHttpRequestObject() { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } else { alert("Your Browser does not support AJAX!\nIt's about time to upgrade don't you think?"); } } //XmlHttpRequest object var req = getXmlHttpRequestObject(); var htmlTarget; function getRequest(resource, elementId) { // handle the case where a querystring is not detected var char = "&"; if(resource.indexOf("?", 0) == -1) { char = "?"; } if (req.readyState == 4 || req.readyState == 0) { req.open("GET", resource + char + 'ms=' + new Date().getTime(), true); req.onreadystatechange = handleResponse; htmlTarget = elementId; req.send(null); return false; } } function handleResponse() { if (req.readyState == 4) { parseState(req.responseXML); } } function parseState(xDoc) { var target = document.getElementById(htmlTarget); target.innerHTML = xDoc.getElementsByTagName("time")[0].childNodes[0].nodeValue; } </script> </head> <body style="background-color:beige;"> <div style="width:600px;margin:auto;background-color:white;padding:10px;"> <h1 style="text-align:center;color:blue;">Get Time</h1> <p> <a href="time.htm" onClick="return getRequest('xmltime', 'placeholder');">Get Time</a> </p> <p><span id="placeholder"></span></p> </div> <script language='javascript' type='text/javascript'> getRequest('xmltime', 'placeholder'); </script> </body> </html>Tutorial source files can be found on the Google Code repository
http://code.google.com/p/spinneret-web-server/source/browse/#svn%2Ftrunk%2FMultiSocketServer_MikeG%2FTutorialSourceArchives%2Fhtml
I tried to find a solution to my problem but I found nothing.
The first time the page load status of the LED is alway "State." All I want is that when the page load status of the LED is "on" or "off".
What can I modify in the code to avoid every time I refreshed the page the status LED always returns a "State"?
<html><head> <title>J&A LUX Control</title> <script language="javascript" type="application/javascript"> //Gets the browser specific XmlHttpRequest Object function getXmlHttpRequestObject() { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } else { alert("Your Browser does not support AJAX!\nIt's about time to upgrade don't you think?"); } } //XmlHttpRequest object var req = getXmlHttpRequestObject(); var htmlTarget; function getRequest(resource, elementId) { // handle the case where a querystring is not detected var char = "&"; if(resource.indexOf("?", 0) == -1) { char = "?"; } if (req.readyState == 4 || req.readyState == 0) { req.open("GET", resource + char + 'ms=' + new Date().getTime(), true); req.onreadystatechange = handleResponse; htmlTarget = elementId; req.send(null); return false; } } function handleResponse() { if (req.readyState == 4) { var str = req.responseText; //alert(str); var placeholder = document.getElementById(htmlTarget); placeholder.innerHTML = str; } } </script> </head> <body style="background-color:beige;"> <div style="width:600px;margin:auto;background-color:white;padding:10px;"> <h1 style="text-align:center;color:blue;">LED</h1> <div style="text-align:center;"><a href="index.htm">Home</a> | <a href="led.htm">LUX Control</a></div> <h2>Section</h2> <p> <a href="led.htm" onClick="return getRequest('aled.htm?led=on', 'placeholder');">LED On </a> :: <a href="led.htm" onClick="return getRequest('aled.htm?led=off', 'placeholder');">LED Off</a> </p> <p>LED: <span id="placeholder">State</span></p> </div> </body> </html>{{───────────────────────────────────────────────── Copyright (c) 2011 AgaveRobotics LLC. See end of file for terms of use. File....... HTTPServer.spin Author..... Mike Gebhard Company.... Agave Robotics LLC Email...... mailto:mike.gebhard@agaverobotics.com Started.... 11/01/2010 Updated.... 07/16/2011 ───────────────────────────────────────────────── }} { About: HTTPServer is the designed for use with the Spinneret Web server manufactured by Parallax Inc. Usage: HTTPServer is the top level object. Required objects: Parallax Serial Terminal.spin W5100_Indirect_Driver.spin S35390A_SD-MMC_FATEngineWrapper.spin Request.spin Response.spin StringMethods.spin S35390A_RTCEngine.spin Change Log: } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 MAX_PACKET_SIZE = $5C0 '1472 '$800 = 2048 RxTx_BUFFER = $800 '$600 = 1536 TEMP_BUFFER = $600 '$5B4 = 1460 TCP_PROTOCOL = 01 '$300 = 768 UDP_PROTOCOL = 10 '$200 = 512 TCP_CONNECT = $04 '$100 = 256 DELAY = $10 MAX_TRIES = $25 #0, DONE, PUT, CD DAT mac byte $00, $08, $DC, $16, $F2, $73 subnet byte 255, 255 ,255, 0 gateway byte 24,230,203,1 ip byte 192,168,0,105 port word 5555 remoteIp byte 24,230,203,105 remotePort word 80 uport word 5050 emailIp byte 0, 0, 0, 0 emailPort word 25 status byte $00, $00, $00, $00 rxdata byte $0[RxTx_BUFFER] txdata byte $0[RxTx_BUFFER] udpdata byte $0[TEMP_BUFFER] fileErrorHandle long $0 debug byte $0 lastFile byte $0[12], 0 closedState byte 00 openState byte 00 listenState byte 00 establishedState byte 00 closingState byte 00 closeWaitState byte 00 lastEstblState byte 00 lastEstblStateDebug byte 00 udpListen byte 00 tcpMask byte 11 udpMask byte 00 fifoSocketDepth byte $0 fifoSocket long $00_00_00_00 debugSemId byte $00 debugCounter long $00 stringMethods long $00 closingTimeout long $00, $00, $00, $00 udpLen long $00 time byte "00/00/0000 00:00:00", 0 httpDate byte "Wed, 01 Feb 2000 01:00:00 GMT", 0 globalCache byte $1 VAR long StackSpace[20] OBJ pst : "Parallax Serial Terminal" Socket : "W5100_Indirect_Driver" SDCard : "S35390A_SD-MMC_FATEngineWrapper" Request : "Request" Response : "Response" str : "StringMethods" rtc : "S35390A_RTCEngine" PUB Initialize | id, size, st debug := 1 SDCard.Start stringMethods := str.Start Request.Constructor(stringMethods) Response.Constructor(stringMethods, @txdata) pst.Start(115_200) pause(200) 'Mount the SD card pst.str(string("Mount SD Card - ")) SDCard.mount(fileErrorHandle) pst.str(string("OK",13)) pst.str(string("Start RTC: ")) rtc.RTCEngineStart(29, 28, -1) pause(200) pst.str(FillTime) 'Start the W5100 driver if(Socket.Start) pst.str(string(13, "W5100 Driver Started", 13)) pst.str(string(13, "Status Memory Lock ID : ")) pst.dec(Socket.GetLockId) pst.char(13) if(debugSemId := locknew) == -1 pst.str(string("Error, no HTTP server locks available", 13)) else pst.str(string("HTTP Server Lock ID : ")) pst.dec(debugSemId) pst.char(13) 'Set the Socket addresses SetMac(@mac) SetGateway(@gateway) SetSubnet(@subnet) SetIP(@ip) ' Initailize TCP sockets (defalut setting; TCP, Port, remote ip and remote port) repeat id from 0 to 3 InitializeSocket(id) Request.Release(id) pause(50) ' Set all TCP sockets to listen pst.char(13) repeat id from 0 to 3 Socket.Listen(id) pst.str(string("TCP Socket Listener ID : ")) pst.dec(id) pst.char(13) pause(50) pst.Str(string(13,"Started Socket Monitoring Service", 13)) cognew(StatusMonitor, @StackSpace) pause(250) pst.Str(string(13, "Initial Socket States",13)) StackDump pst.Str(string(13, "Initial Socket Queue",13)) QueueDump pst.str(string(13,"//////////////////////////////////////////////////////////////",13)) Main PUB Main | packetSize, id, i, reset, j, temp ''HTTP Service repeat repeat until fifoSocket == 0 bytefill(@rxdata, 0, RxTx_BUFFER) if(debug) pst.str(string(13, "----- Start of Request----------------------------",13)) pause(DELAY) else pause(DELAY) ' Pop the next socket handle id := DequeueSocket if(id < 0) next if(debug) pst.str(string(13,"ID: ")) pst.dec(id) pst.str(string(13, "Request Count : ")) pst.dec(debugCounter) pst.char(13) packetSize := Socket.rxTCP(id, @rxdata) reset := false if ((packetSize < 12) AND (strsize(@rxdata) < 12)) repeat i from 0 to MAX_TRIES pst.str(string(13,"* Retry *")) 'Wait for a few moments and try again waitcnt((clkfreq/300 ) + cnt) packetSize := Socket.rxTCP(id, @rxdata) if(packetSize > 12) quit if(i == MAX_TRIES) 'Clean up resource request Request.Release(id) Socket.Disconnect(id) reset := true if(debug) StackDump pst.char(13) QueueDump pst.str(string(13,"* Timeout *",13)) if(reset) next Request.InitializeRequest(id, @rxdata) if(debug) pst.char(13) HeaderLine1(id) else pause(DELAY) ' Process router Dispatcher(id) 'Clean up request resource Request.Release(id) ' This starts the close process -> 0x00 ' use close to force a close Socket.Disconnect(id) bytefill(@txdata, 0, RxTx_BUFFER) debugCounter++ GotoMain PRI SendLedResposne(id) | headerLen, qstr '' Get the query string value qstr := Request.Get(id, string("led")) '' Exit if there is no querystring if(qstr == 0) return '' Turn the LED on if the led= value is "on" if (strcomp(string("on"), qstr )) LedStatus(1) else LedStatus(0) '' Build and send the header '' Send the value of led= on or off headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) Socket.txTCP(id, qstr, strsize(qstr)) return PRI GotoMain Main PRI Dispatcher(id) ''Do some processing before sending the response Request.Get(id, string("led")) if(strcomp(Request.GetFileName(id), string("aled.htm")) AND Request.GetDepth(id) == 1) SendLedResposne(id) return StaticFileHandler(id) return return PRI LedStatus(state) dira[24]~~ outa[24] := state return PRI StaticFileHandler(id) | fileSize, i, headerLen, temp, j ''Serve up static files from the SDCard 'pst.str(string(13,"Static File Handler",13)) SDCard.changeDirectory(@approot) pst.char(13) 'Make sure the directory exists ifnot(ChangeDirectory(id)) 'send 404 error WriteError(id) SDCard.changeDirectory(@approot) return ' Make sure the file exists ifnot(FileExists(Request.GetFileName(id))) 'send 404 error WriteError(id) SDCard.changeDirectory(@approot) return ' Open the file for reading SDCard.openFile(Request.GetFileName(id), "r") fileSize := SDCard.getFileSize 'WriteResponseHeader(id) 'BuildHeader(extension, statusCode, expirer) headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) if fileSize < MAX_PACKET_SIZE ' send the file in one packet SDCard.readFromFile(@txdata, fileSize) Socket.txTCP(id, @txdata, fileSize) else ' send the file in a bunch of packets repeat SDCard.readFromFile(@txdata, MAX_PACKET_SIZE) Socket.txTCP(id, @txdata, MAX_PACKET_SIZE) fileSize -= MAX_PACKET_SIZE ' once the remaining fileSize is less then the max packet size, just send that remaining bit and quit the loop if fileSize < MAX_PACKET_SIZE and fileSize > 0 SDCard.readFromFile(@txdata, fileSize) Socket.txTCP(id, @txdata, fileSize) quit ' Bailout if(i++ > 1_000_000) WriteError(id) quit SDCard.closeFile SDCard.changeDirectory(@approot) return PRI WriteError(id) | headerOffset '' Simple 404 error pst.str(string(13, "Write 404 Error",13 )) headerOffset := Response.BuildHeader(Request.GetExtension(id), 404, false) Socket.txTCP(id, @txdata, headerOffset) return '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' directory and file handlers '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI ChangeDirectory(id) | i, found 'Handle directory structure for this Request if(Request.GetDepth(id) > 1) repeat i from 0 to Request.GetDepth(id)-2 'Return if the directory is not found ifnot(FileExists(Request.GetPathNode(id, i))) return false found := SDCard.changeDirectory(Request.GetPathNode(id, i)) return true PRI FileExists(fileToCompare) | filenamePtr 'Start file find at the top of the list SDCard.startFindFile 'Verify that the file exists repeat while filenamePtr <> 0 filenamePtr := SDCard.nextFile if(str.MatchPattern(filenamePtr, fileToCompare, 0, false ) == 0 ) return true return false '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Time Methods and Formats '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetTime(id) | ptr, headerOffset ptr := @udpdata FillHttpDate bytemove(ptr, string("<p>"),3) ptr += 3 bytemove(ptr, @httpDate, strsize(@httpDate)) ptr += strsize(@httpDate) bytemove(ptr, string("</p>"),4) ptr += 3 headerOffset := Response.BuildHeader(Request.GetExtension(id), 200, false) Socket.txTCP(id, @txdata, headerOffset) StringSend(id, @udpdata) bytefill(@udpdata, 0, TEMP_BUFFER) return PRI FillTime | ptr, num 'ToString(integerToConvert, destinationPointer) '00/00/0000 00:00:00 ptr := @time rtc.readTime FillTimeHelper(rtc.clockMonth, ptr) ptr += 3 FillTimeHelper(rtc.clockDate, ptr) ptr += 3 FillTimeHelper(rtc.clockYear, ptr) ptr += 5 FillTimeHelper(rtc.clockHour , ptr) ptr += 3 FillTimeHelper(rtc.clockMinute , ptr) ptr += 3 FillTimeHelper(rtc.clockSecond, ptr) return @time PRI FillHttpDate | ptr, num, temp 'ToString(integerToConvert, destinationPointer) 'Wed, 01 Feb 2000 01:00:00 GMT ptr := @httpDate rtc.readTime temp := rtc.getDayString bytemove(ptr, temp, strsize(temp)) ptr += strsize(temp) + 2 FillTimeHelper(rtc.clockDate, ptr) ptr += 3 temp := rtc.getMonthString bytemove(ptr, temp, strsize(temp)) ptr += strsize(temp) + 1 FillTimeHelper(rtc.clockYear, ptr) ptr += 5 FillTimeHelper(rtc.clockHour , ptr) ptr += 3 FillTimeHelper(rtc.clockMinute , ptr) ptr += 3 FillTimeHelper(rtc.clockSecond, ptr) return @httpDate PRI FillTimeHelper(number, ptr) | offset offset := 0 if(number < 10) offset := 1 str.ToString(@number, @tempNum) bytemove(ptr+offset, @tempNum, strsize(@tempNum)) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' SDCard Logger '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI AppendLog(logToAppend) '' logToAppend: Pointer to a string of test we'd like to log SDCard.changeDirectory(@approot) if(FileExists(@logfile)) SDCard.openFile(@logfile, "A") else SDCard.newFile(@logfile) SDCard.writeData(string(13,10,"----- Start "),14) SDCard.writeData(FillTime, 19) SDCard.writeData(string(" -----"),6) SDCard.writeData(@crlf_crlf, 2) SDCard.writeData(logToAppend, strsize(logToAppend)) SDCard.writeData(@crlf_crlf, 2) SDCard.writeData(string("----- End "),10) SDCard.writeData(FillTime, 19) SDCard.writeData(string(" -----"),6) SDCard.writeData(@crlf_crlf, 2) SDCard.closeFile '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Memory Management '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI Set(DestAddress, SrcAddress, Count) bytemove(DestAddress, SrcAddress, Count) bytefill(DestAddress+Count, $0, 1) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Socekt helpers '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetTcpSocketMask(id) return id & tcpMask PRI DecodeId(value) | tmp if(01 & value) return 0 if(10 & value) return 1 if(00 & value) return 2 if(00 & value) return 3 return -1 PRI QueueSocket(id) | tmp if(fifoSocketDepth > 4) return false tmp := |< id 'Unique check ifnot(IsUnique(tmp)) return false tmp <<= (fifoSocketDepth++) * 8 fifoSocket |= tmp return true PRI IsUnique(encodedId) | tmp tmp := encodedId & $0F repeat 4 if(encodedId & fifoSocket) return false encodedId <<= 8 return true PRI DequeueSocket | tmp if(fifoSocketDepth == 0) return -2 repeat until not lockset(debugSemId) tmp := fifoSocket & $0F fifoSocket >>= 8 fifoSocketDepth-- lockclr(debugSemId) return DecodeId(tmp) PRI ResetSocket(id) Socket.Disconnect(id) Socket.Close(id) PRI IsolateTcpSocketById(id) | tmp tmp := |< id tcpMask &= tmp PRI SetTcpSocketMaskById(id, state) | tmp '' The tcpMask contains the socket the the StatusMonitor monitors tmp := |< id if(state == 1) tcpMask |= tmp else tmp := !tmp tcpMask &= tmp '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' W5100 Helper methods '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetCommandRegisterAddress(id) return Socket#_S0_CR + (id * $0100) PRI GetStatusRegisterAddress(id) return Socket#_S0_SR + (id * $0100) PRI SetMac(_firstOctet) Socket.WriteMACaddress(true, _firstOctet) return PRI SetGateway(_firstOctet) Socket.WriteGatewayAddress(true, _firstOctet) return PRI SetSubnet(_firstOctet) Socket.WriteSubnetMask(true, _firstOctet) return PRI SetIP(_firstOctet) Socket.WriteIPAddress(true, _firstOctet) return PRI StringSend(id, _dataPtr) Socket.txTCP(id, _dataPtr, strsize(_dataPtr)) return PRI SendChar(id, _dataPtr) Socket.txTCP(id, _dataPtr, 1) return PRI SendChars(id, _dataPtr, _length) Socket.txTCP(id, _dataPtr, _length) return PRI InitializeSocket(id) Socket.Initialize(id, TCP_PROTOCOL, port, remotePort, @remoteIp) return PRI InitializeSocketForEmail(id) Socket.Initialize(id, TCP_PROTOCOL, port, emailPort, @emailIp) return PRI InitializeUPDSocket(id) Socket.Initialize(id, UDP_PROTOCOL, uport, remotePort, @remoteIp) return '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Debug/Display Methods '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI QueueDump '' Display socket IDs in the queue '' ie 00000401 -> socket Zero is next to pop off pst.str(string("FIFO[")) pst.dec(fifoSocketDepth) pst.str(string("] ")) pst.hex(fifoSocket, 8) PRI StackDump | clsd, open, lstn, estb, clwt, clng, id, ulst '' This method is purely for debugging '' It displays the status of all socket registers repeat until not lockset(debugSemId) clsd := closedState open := openState lstn := listenState estb := establishedState clwt := closeWaitState clng := closingState ulst := udpListen lockclr(debugSemId) pst.char(13) repeat id from 3 to 0 pst.dec(id) pst.str(string("-")) pst.hex(status[id], 2) pst.str(string(" ")) pause(1) pst.str(string(13,"clsd open lstn estb clwt clng udps", 13)) pst.bin(clsd, 4) pst.str(string("-")) pst.bin(open, 4) pst.str(string("-")) pst.bin(lstn, 4) pst.str(string("-")) pst.bin(estb, 4) pst.str(string("-")) pst.bin(clwt, 4) pst.str(string("-")) pst.bin(clng, 4) pst.str(string("-")) pst.bin(ulst, 4) pst.char(13) PRI HeaderLine1(id) | i pst.str(Request.GetMethod(id)) pst.char($20) i := 0 repeat Request.GetDepth(id) pst.char($2F) pst.str(Request.GetPathNode(id, i++)) PRI Pause(Duration) waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt) return PRI StatusMonitor | id, tmp, value '' StatusMonitor is the heartbeat of the project '' Here we monitor the state of the Wiznet 5100's 4 sockets repeat Socket.GetStatus32(@status[0]) ' Encode status register states repeat until not lockset(debugSemId) closedState := openState := listenState := establishedState := { } closeWaitState := closingState := 0 repeat id from 0 to 3 case(status[id]) $00: closedState |= |< id closedState &= tcpMask $13: openState |= |< id openState &= tcpMask $14: listenState |= |< id listenState &= tcpMask $17: establishedState |= |< id establishedState &= tcpMask $18,$1A,$1B: closingState |= |< id closingState &= tcpMask $1C: closeWaitState |= |< id closeWaitState &= tcpMask $1D: closingState |= |< id closingState &= tcpMask $22: udpListen |= |< id udpListen &= udpMask if(lastEstblState <> establishedState) value := establishedState repeat while value > 0 tmp := DecodeId(value) if(tmp > -1) QueueSocket(tmp) tmp := |< tmp tmp := !tmp value &= tmp lastEstblState := establishedState lockclr(debugSemId) ' Initialize a closed socket if(closedState > 0) id := DecodeId(closedState) if(id > -1) InitializeSocket(id & tcpMask) 'Start a listener on an initialized/open socket if(openState > 0) id := DecodeId(openState) if(id > -1) Socket.Listen(id & tcpMask) ' Close the socket if the status is close/wait ' response processor should close the socket with disconnect ' there could be a timeout so we have a forced close. ' TODO: CCheck for a port that gets stuck in a closing state 'if(closeWaitState > 0) 'id := DecodeId(closeWaitState) 'if(id > -1) 'Socket.Close(id & tcpMask) 'pause(100) return DAT approot byte "\", 0 defaultpage byte "index.htm", 0 logfile byte "log.txt", 0 'binFile byte "filename.bin", 0 FS byte "/", 0 fn byte "filename=", 0 doublequote byte $22, 0 crlf byte 13, 10, 0 crlf_crlf byte 13, 10, 13, 10, 0 uploadfile byte $0[12], 0 uploadfolder byte "uploads", 0 tempNum byte "0000",0 multipart byte "Content-Type: multipart/form-data; boundary=",0 boundary byte $2D, $2D boundary1 byte $0[64] 'loadme file "TogglePin0.binary"Use an AJAX GET to retrieve the pin state after the page has loaded. You will update two files, HttpServer and aled.htm.
1) Update the SendLedResposne method to make an additional querystring check. We're looking for ?led=what. If we see a "what" then get the pin state INA[23]. If the pin state is 1, send the string "on" otherwise send "off".
PRI SendLedResposne(id) | headerLen, qstr '' Get the query string value qstr := Request.Get(id, string("led")) '' Exit if there is no querystring if(qstr == 0) return false '' Turn the LED on if the led= value is "on" if (strcomp(string("on"), qstr )) LedStatus(1) if (strcomp(string("off"), qstr )) LedStatus(0) if (strcomp(string("what"), qstr )) if(ina[23]) qstr := string("on") else qstr := string("off") '' Build and send the header '' Send the value of led= on or off headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) Socket.txTCP(id, qstr, strsize(qstr)) return true2) Update aled.htm by adding an AJAX call below the "State" text.
<html><head> <title>J&A LUX Control</title> <script language="javascript" type="application/javascript"> //Gets the browser specific XmlHttpRequest Object function getXmlHttpRequestObject() { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } else { alert("Your Browser does not support AJAX!\nIt's about time to upgrade don't you think?"); } } //XmlHttpRequest object var req = getXmlHttpRequestObject(); var htmlTarget; function getRequest(resource, elementId) { // handle the case where a querystring is not detected var char = "&"; if(resource.indexOf("?", 0) == -1) { char = "?"; } if (req.readyState == 4 || req.readyState == 0) { req.open("GET", resource + char + 'ms=' + new Date().getTime(), true); req.onreadystatechange = handleResponse; htmlTarget = elementId; req.send(null); return false; } } function handleResponse() { if (req.readyState == 4) { var str = req.responseText; //alert(str); var placeholder = document.getElementById(htmlTarget); placeholder.innerHTML = str; } } </script> </head> <body style="background-color:beige;"> <div style="width:600px;margin:auto;background-color:white;padding:10px;"> <h1 style="text-align:center;color:blue;">LED</h1> <div style="text-align:center;"><a href="index.htm">Home</a> | <a href="aled.htm">LUX Control</a></div> <h2>Section</h2> <p> <a href="#" onClick="return getRequest('aled.htm?led=on', 'placeholder');">LED On </a> :: <a href="#" onClick="return getRequest('aled.htm?led=off', 'placeholder');">LED Off</a> </p> <p>LED: <span id="placeholder">State</span></p> <script language="javascript" type="text/javascript"> getRequest('aled.htm?led=what', 'placeholder') </script> </div> </body> </html>When the page loads, You'll see "State" while the AJAX GET retrieves the pin state from the server. But it will change.
Can we make this thread as solved?
{{ ───────────────────────────────────────────────── Copyright (c) 2011 AgaveRobotics LLC. See end of file for terms of use. File....... HTTPServer.spin Author..... Mike Gebhard Company.... Agave Robotics LLC Email...... mailto:mike.gebhard@agaverobotics.com Started.... 11/01/2010 Updated.... 07/16/2011 ───────────────────────────────────────────────── }} { About: HTTPServer is the designed for use with the Spinneret Web server manufactured by Parallax Inc. Usage: HTTPServer is the top level object. Required objects: • Parallax Serial Terminal.spin • W5100_Indirect_Driver.spin • S35390A_SD-MMC_FATEngineWrapper.spin • Request.spin • Response.spin • StringMethods.spin • S35390A_RTCEngine.spin Change Log: } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 MAX_PACKET_SIZE = $5C0 '1472 '$800 = 2048 RxTx_BUFFER = $800 '$600 = 1536 TEMP_BUFFER = $600 '$5B4 = 1460 TCP_PROTOCOL = 01 '$300 = 768 UDP_PROTOCOL = 10 '$200 = 512 TCP_CONNECT = $04 '$100 = 256 DELAY = $10 MAX_TRIES = $25 #0, DONE, PUT, CD DAT mac byte $00, $08, $DC, $16, $F2, $73 subnet byte 255, 255 ,255, 0 gateway byte 24,230,203,1 ip byte 192,168,0,105 port word 5555 remoteIp byte 24,230,203,105 remotePort word 80 uport word 5050 emailIp byte 0, 0, 0, 0 emailPort word 25 status byte $00, $00, $00, $00 rxdata byte $0[RxTx_BUFFER] txdata byte $0[RxTx_BUFFER] udpdata byte $0[TEMP_BUFFER] fileErrorHandle long $0 debug byte $0 lastFile byte $0[12], 0 closedState byte 00 openState byte 00 listenState byte 00 establishedState byte 00 closingState byte 00 closeWaitState byte 00 lastEstblState byte 00 lastEstblStateDebug byte 00 udpListen byte 00 tcpMask byte 11 udpMask byte 00 fifoSocketDepth byte $0 fifoSocket long $00_00_00_00 debugSemId byte $00 debugCounter long $00 stringMethods long $00 closingTimeout long $00, $00, $00, $00 udpLen long $00 time byte "00/00/0000 00:00:00", 0 httpDate byte "Wed, 01 Feb 2000 01:00:00 GMT", 0 globalCache byte $1 VAR long StackSpace[20] OBJ pst : "Parallax Serial Terminal" Socket : "W5100_Indirect_Driver" SDCard : "S35390A_SD-MMC_FATEngineWrapper" Request : "Request" Response : "Response" str : "StringMethods" rtc : "S35390A_RTCEngine" PUB Initialize | id, size, st debug := 1 SDCard.Start stringMethods := str.Start Request.Constructor(stringMethods) Response.Constructor(stringMethods, @txdata) pst.Start(115_200) pause(200) 'Mount the SD card pst.str(string("Mount SD Card - ")) SDCard.mount(fileErrorHandle) pst.str(string("OK",13)) pst.str(string("Start RTC: ")) rtc.RTCEngineStart(29, 28, -1) pause(200) pst.str(FillTime) 'Start the W5100 driver if(Socket.Start) pst.str(string(13, "W5100 Driver Started", 13)) pst.str(string(13, "Status Memory Lock ID : ")) pst.dec(Socket.GetLockId) pst.char(13) if(debugSemId := locknew) == -1 pst.str(string("Error, no HTTP server locks available", 13)) else pst.str(string("HTTP Server Lock ID : ")) pst.dec(debugSemId) pst.char(13) 'Set the Socket addresses SetMac(@mac) SetGateway(@gateway) SetSubnet(@subnet) SetIP(@ip) ' Initailize TCP sockets (defalut setting; TCP, Port, remote ip and remote port) repeat id from 0 to 3 InitializeSocket(id) Request.Release(id) pause(50) ' Set all TCP sockets to listen pst.char(13) repeat id from 0 to 3 Socket.Listen(id) pst.str(string("TCP Socket Listener ID : ")) pst.dec(id) pst.char(13) pause(50) pst.Str(string(13,"Started Socket Monitoring Service", 13)) cognew(StatusMonitor, @StackSpace) pause(250) pst.Str(string(13, "Initial Socket States",13)) StackDump pst.Str(string(13, "Initial Socket Queue",13)) QueueDump pst.str(string(13,"//////////////////////////////////////////////////////////////",13)) Main PUB Main | packetSize, id, i, reset, j, temp ''HTTP Service repeat repeat until fifoSocket == 0 bytefill(@rxdata, 0, RxTx_BUFFER) if(debug) pst.str(string(13, "----- Start of Request----------------------------",13)) pause(DELAY) else pause(DELAY) ' Pop the next socket handle id := DequeueSocket if(id < 0) next if(debug) pst.str(string(13,"ID: ")) pst.dec(id) pst.str(string(13, "Request Count : ")) pst.dec(debugCounter) pst.char(13) packetSize := Socket.rxTCP(id, @rxdata) reset := false if ((packetSize < 12) AND (strsize(@rxdata) < 12)) repeat i from 0 to MAX_TRIES pst.str(string(13,"* Retry *")) 'Wait for a few moments and try again waitcnt((clkfreq/300 ) + cnt) packetSize := Socket.rxTCP(id, @rxdata) if(packetSize > 12) quit if(i == MAX_TRIES) 'Clean up resource request Request.Release(id) Socket.Disconnect(id) reset := true if(debug) StackDump pst.char(13) QueueDump pst.str(string(13,"* Timeout *",13)) if(reset) next Request.InitializeRequest(id, @rxdata) if(debug) pst.char(13) HeaderLine1(id) else pause(DELAY) ' Process router Dispatcher(id) 'Clean up request resource Request.Release(id) ' This starts the close process -> 0x00 ' use close to force a close Socket.Disconnect(id) bytefill(@txdata, 0, RxTx_BUFFER) debugCounter++ GotoMain PRI SendLedResposne(id) | headerLen, qstr '' Get the query string value qstr := Request.Get(id, string("led")) '' Exit if there is no querystring if(qstr == 0) return false '' Turn the LED on if the led= value is "on" if (strcomp(string("on"), qstr )) LedStatus(1) else LedStatus(0) '' Build and send the header '' Send the value of led= on or off headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) Socket.txTCP(id, qstr, strsize(qstr)) return true PRI GotoMain Main PRI Dispatcher(id) ''Do some processing before sending the response if(strcomp(Request.GetFileName(id), string("aled.htm")) AND Request.GetDepth(id) == 1) SendLedResposne(id) return StaticFileHandler(id) return PRI Led(id) | qstr '' Get the query string value qstr := Request.Get(id, string("led")) if (strcomp( string("on"), qstr )) LedStatus(1) return PRI LedStatus(state) dira[24]~~ outa[24] := state return PRI StaticFileHandler(id) | fileSize, i, headerLen, temp, j ''Serve up static files from the SDCard 'pst.str(string(13,"Static File Handler",13)) SDCard.changeDirectory(@approot) pst.char(13) 'Make sure the directory exists ifnot(ChangeDirectory(id)) 'send 404 error WriteError(id) SDCard.changeDirectory(@approot) return ' Make sure the file exists ifnot(FileExists(Request.GetFileName(id))) 'send 404 error WriteError(id) SDCard.changeDirectory(@approot) return ' Open the file for reading SDCard.openFile(Request.GetFileName(id), "r") fileSize := SDCard.getFileSize 'WriteResponseHeader(id) 'BuildHeader(extension, statusCode, expirer) headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) if fileSize < MAX_PACKET_SIZE ' send the file in one packet SDCard.readFromFile(@txdata, fileSize) Socket.txTCP(id, @txdata, fileSize) else ' send the file in a bunch of packets repeat SDCard.readFromFile(@txdata, MAX_PACKET_SIZE) Socket.txTCP(id, @txdata, MAX_PACKET_SIZE) fileSize -= MAX_PACKET_SIZE ' once the remaining fileSize is less then the max packet size, just send that remaining bit and quit the loop if fileSize < MAX_PACKET_SIZE and fileSize > 0 SDCard.readFromFile(@txdata, fileSize) Socket.txTCP(id, @txdata, fileSize) quit ' Bailout if(i++ > 1_000_000) WriteError(id) quit SDCard.closeFile SDCard.changeDirectory(@approot) return PRI WriteError(id) | headerOffset '' Simple 404 error pst.str(string(13, "Write 404 Error",13 )) headerOffset := Response.BuildHeader(Request.GetExtension(id), 404, false) Socket.txTCP(id, @txdata, headerOffset) return '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' directory and file handlers '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI ChangeDirectory(id) | i, found 'Handle directory structure for this Request if(Request.GetDepth(id) > 1) repeat i from 0 to Request.GetDepth(id)-2 'Return if the directory is not found ifnot(FileExists(Request.GetPathNode(id, i))) return false found := SDCard.changeDirectory(Request.GetPathNode(id, i)) return true PRI FileExists(fileToCompare) | filenamePtr 'Start file find at the top of the list SDCard.startFindFile 'Verify that the file exists repeat while filenamePtr <> 0 filenamePtr := SDCard.nextFile if(str.MatchPattern(filenamePtr, fileToCompare, 0, false ) == 0 ) return true return false '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Time Methods and Formats '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetTime(id) | ptr, headerOffset ptr := @udpdata FillHttpDate bytemove(ptr, string("<p>"),3) ptr += 3 bytemove(ptr, @httpDate, strsize(@httpDate)) ptr += strsize(@httpDate) bytemove(ptr, string("</p>"),4) ptr += 3 headerOffset := Response.BuildHeader(Request.GetExtension(id), 200, false) Socket.txTCP(id, @txdata, headerOffset) StringSend(id, @udpdata) bytefill(@udpdata, 0, TEMP_BUFFER) return PRI FillTime | ptr, num 'ToString(integerToConvert, destinationPointer) '00/00/0000 00:00:00 ptr := @time rtc.readTime FillTimeHelper(rtc.clockMonth, ptr) ptr += 3 FillTimeHelper(rtc.clockDate, ptr) ptr += 3 FillTimeHelper(rtc.clockYear, ptr) ptr += 5 FillTimeHelper(rtc.clockHour , ptr) ptr += 3 FillTimeHelper(rtc.clockMinute , ptr) ptr += 3 FillTimeHelper(rtc.clockSecond, ptr) return @time PRI FillHttpDate | ptr, num, temp 'ToString(integerToConvert, destinationPointer) 'Wed, 01 Feb 2000 01:00:00 GMT ptr := @httpDate rtc.readTime temp := rtc.getDayString bytemove(ptr, temp, strsize(temp)) ptr += strsize(temp) + 2 FillTimeHelper(rtc.clockDate, ptr) ptr += 3 temp := rtc.getMonthString bytemove(ptr, temp, strsize(temp)) ptr += strsize(temp) + 1 FillTimeHelper(rtc.clockYear, ptr) ptr += 5 FillTimeHelper(rtc.clockHour , ptr) ptr += 3 FillTimeHelper(rtc.clockMinute , ptr) ptr += 3 FillTimeHelper(rtc.clockSecond, ptr) return @httpDate PRI FillTimeHelper(number, ptr) | offset offset := 0 if(number < 10) offset := 1 str.ToString(@number, @tempNum) bytemove(ptr+offset, @tempNum, strsize(@tempNum)) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' SDCard Logger '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI AppendLog(logToAppend) '' logToAppend: Pointer to a string of test we'd like to log SDCard.changeDirectory(@approot) if(FileExists(@logfile)) SDCard.openFile(@logfile, "A") else SDCard.newFile(@logfile) SDCard.writeData(string(13,10,"----- Start "),14) SDCard.writeData(FillTime, 19) SDCard.writeData(string(" -----"),6) SDCard.writeData(@crlf_crlf, 2) SDCard.writeData(logToAppend, strsize(logToAppend)) SDCard.writeData(@crlf_crlf, 2) SDCard.writeData(string("----- End "),10) SDCard.writeData(FillTime, 19) SDCard.writeData(string(" -----"),6) SDCard.writeData(@crlf_crlf, 2) SDCard.closeFile '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Memory Management '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI Set(DestAddress, SrcAddress, Count) bytemove(DestAddress, SrcAddress, Count) bytefill(DestAddress+Count, $0, 1) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Socekt helpers '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetTcpSocketMask(id) return id & tcpMask PRI DecodeId(value) | tmp if(01 & value) return 0 if(10 & value) return 1 if(00 & value) return 2 if(00 & value) return 3 return -1 PRI QueueSocket(id) | tmp if(fifoSocketDepth > 4) return false tmp := |< id 'Unique check ifnot(IsUnique(tmp)) return false tmp <<= (fifoSocketDepth++) * 8 fifoSocket |= tmp return true PRI IsUnique(encodedId) | tmp tmp := encodedId & $0F repeat 4 if(encodedId & fifoSocket) return false encodedId <<= 8 return true PRI DequeueSocket | tmp if(fifoSocketDepth == 0) return -2 repeat until not lockset(debugSemId) tmp := fifoSocket & $0F fifoSocket >>= 8 fifoSocketDepth-- lockclr(debugSemId) return DecodeId(tmp) PRI ResetSocket(id) Socket.Disconnect(id) Socket.Close(id) PRI IsolateTcpSocketById(id) | tmp tmp := |< id tcpMask &= tmp PRI SetTcpSocketMaskById(id, state) | tmp '' The tcpMask contains the socket the the StatusMonitor monitors tmp := |< id if(state == 1) tcpMask |= tmp else tmp := !tmp tcpMask &= tmp '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' W5100 Helper methods '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetCommandRegisterAddress(id) return Socket#_S0_CR + (id * $0100) PRI GetStatusRegisterAddress(id) return Socket#_S0_SR + (id * $0100) PRI SetMac(_firstOctet) Socket.WriteMACaddress(true, _firstOctet) return PRI SetGateway(_firstOctet) Socket.WriteGatewayAddress(true, _firstOctet) return PRI SetSubnet(_firstOctet) Socket.WriteSubnetMask(true, _firstOctet) return PRI SetIP(_firstOctet) Socket.WriteIPAddress(true, _firstOctet) return PRI StringSend(id, _dataPtr) Socket.txTCP(id, _dataPtr, strsize(_dataPtr)) return PRI SendChar(id, _dataPtr) Socket.txTCP(id, _dataPtr, 1) return PRI SendChars(id, _dataPtr, _length) Socket.txTCP(id, _dataPtr, _length) return PRI InitializeSocket(id) Socket.Initialize(id, TCP_PROTOCOL, port, remotePort, @remoteIp) return PRI InitializeSocketForEmail(id) Socket.Initialize(id, TCP_PROTOCOL, port, emailPort, @emailIp) return PRI InitializeUPDSocket(id) Socket.Initialize(id, UDP_PROTOCOL, uport, remotePort, @remoteIp) return '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Debug/Display Methods '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI QueueDump '' Display socket IDs in the queue '' ie 00000401 -> socket Zero is next to pop off pst.str(string("FIFO[")) pst.dec(fifoSocketDepth) pst.str(string("] ")) pst.hex(fifoSocket, 8) PRI StackDump | clsd, open, lstn, estb, clwt, clng, id, ulst '' This method is purely for debugging '' It displays the status of all socket registers repeat until not lockset(debugSemId) clsd := closedState open := openState lstn := listenState estb := establishedState clwt := closeWaitState clng := closingState ulst := udpListen lockclr(debugSemId) pst.char(13) repeat id from 3 to 0 pst.dec(id) pst.str(string("-")) pst.hex(status[id], 2) pst.str(string(" ")) pause(1) pst.str(string(13,"clsd open lstn estb clwt clng udps", 13)) pst.bin(clsd, 4) pst.str(string("-")) pst.bin(open, 4) pst.str(string("-")) pst.bin(lstn, 4) pst.str(string("-")) pst.bin(estb, 4) pst.str(string("-")) pst.bin(clwt, 4) pst.str(string("-")) pst.bin(clng, 4) pst.str(string("-")) pst.bin(ulst, 4) pst.char(13) PRI HeaderLine1(id) | i pst.str(Request.GetMethod(id)) pst.char($20) i := 0 repeat Request.GetDepth(id) pst.char($2F) pst.str(Request.GetPathNode(id, i++)) PRI Pause(Duration) waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt) return PRI StatusMonitor | id, tmp, value '' StatusMonitor is the heartbeat of the project '' Here we monitor the state of the Wiznet 5100's 4 sockets repeat Socket.GetStatus32(@status[0]) ' Encode status register states repeat until not lockset(debugSemId) closedState := openState := listenState := establishedState := { } closeWaitState := closingState := 0 repeat id from 0 to 3 case(status[id]) $00: closedState |= |< id closedState &= tcpMask $13: openState |= |< id openState &= tcpMask $14: listenState |= |< id listenState &= tcpMask $17: establishedState |= |< id establishedState &= tcpMask $18,$1A,$1B: closingState |= |< id closingState &= tcpMask $1C: closeWaitState |= |< id closeWaitState &= tcpMask $1D: closingState |= |< id closingState &= tcpMask $22: udpListen |= |< id udpListen &= udpMask if(lastEstblState <> establishedState) value := establishedState repeat while value > 0 tmp := DecodeId(value) if(tmp > -1) QueueSocket(tmp) tmp := |< tmp tmp := !tmp value &= tmp lastEstblState := establishedState lockclr(debugSemId) ' Initialize a closed socket if(closedState > 0) id := DecodeId(closedState) if(id > -1) InitializeSocket(id & tcpMask) 'Start a listener on an initialized/open socket if(openState > 0) id := DecodeId(openState) if(id > -1) Socket.Listen(id & tcpMask) ' Close the socket if the status is close/wait ' response processor should close the socket with disconnect ' there could be a timeout so we have a forced close. ' TODO: CCheck for a port that gets stuck in a closing state 'if(closeWaitState > 0) 'id := DecodeId(closeWaitState) 'if(id > -1) 'Socket.Close(id & tcpMask) 'pause(100) return DAT approot byte "\", 0 defaultpage byte "index.htm", 0 logfile byte "log.txt", 0 'binFile byte "filename.bin", 0 FS byte "/", 0 fn byte "filename=", 0 doublequote byte $22, 0 crlf byte 13, 10, 0 crlf_crlf byte 13, 10, 13, 10, 0 uploadfile byte $0[12], 0 uploadfolder byte "uploads", 0 tempNum byte "0000",0 multipart byte "Content-Type: multipart/form-data; boundary=",0 boundary byte $2D, $2D boundary1 byte $0[64] 'loadme file "TogglePin0.binary"<html> <head> <title>J&A LUX Control</title> <script language="javascript" type="application/javascript"> //Gets the browser specific XmlHttpRequest Object function getXmlHttpRequestObject() { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } else { alert("Your Browser does not support AJAX!\nIt's about time to upgrade don't you think?"); } } //XmlHttpRequest object var req = getXmlHttpRequestObject(); var htmlTarget; function getRequest(resource, elementId) { // handle the case where a querystring is not detected var char = "&"; if(resource.indexOf("?", 0) == -1) { char = "?"; } if (req.readyState == 4 || req.readyState == 0) { req.open("GET", resource + char + 'ms=' + new Date().getTime(), true); req.onreadystatechange = handleResponse; htmlTarget = elementId; req.send(null); return false; } } function handleResponse() { if (req.readyState == 4) { var str = req.responseText; //alert(str); var placeholder = document.getElementById(htmlTarget); placeholder.innerHTML = str; } } </script> </head> <body style="background-color:beige;"> <div style="width:600px;margin:auto;background-color:white;padding:10px;"> <h1 style="text-align:center;color:blue;">LED</h1> <div style="text-align:center;"><a href="index.htm">Home</a> | <a href="led.htm">LUX Control</a></div> <h2>Section</h2> <p> <a href="led.htm" onClick="return getRequest('aled.htm?led=on', 'placeholder');">LED On </a> :: <a href="led.htm" onClick="return getRequest('aled.htm?led=off', 'placeholder');">LED Off</a> </p> <p>LED: <span id="placeholder">State</span></p> </script> </div> </body> </html>Wen i use the new code you just send me the "State" of the Led is always update on the webpage. But all time I reload the page the state of the Led return to "off" and the Led is close.
{{ ───────────────────────────────────────────────── Copyright (c) 2011 AgaveRobotics LLC. See end of file for terms of use. File....... HTTPServer.spin Author..... Mike Gebhard Company.... Agave Robotics LLC Email...... mailto:mike.gebhard@agaverobotics.com Started.... 11/01/2010 Updated.... 07/16/2011 ───────────────────────────────────────────────── }} { About: HTTPServer is the designed for use with the Spinneret Web server manufactured by Parallax Inc. Usage: HTTPServer is the top level object. Required objects: • Parallax Serial Terminal.spin • W5100_Indirect_Driver.spin • S35390A_SD-MMC_FATEngineWrapper.spin • Request.spin • Response.spin • StringMethods.spin • S35390A_RTCEngine.spin Change Log: } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 MAX_PACKET_SIZE = $5C0 '1472 '$800 = 2048 RxTx_BUFFER = $800 '$600 = 1536 TEMP_BUFFER = $600 '$5B4 = 1460 TCP_PROTOCOL = 01 '$300 = 768 UDP_PROTOCOL = 10 '$200 = 512 TCP_CONNECT = $04 '$100 = 256 DELAY = $10 MAX_TRIES = $25 #0, DONE, PUT, CD DAT mac byte $00, $08, $DC, $16, $F2, $73 subnet byte 255, 255 ,255, 0 gateway byte 24,230,203,1 ip byte 192,168,0,105 port word 5555 remoteIp byte 24,230,203,105 remotePort word 80 uport word 5050 emailIp byte 0, 0, 0, 0 emailPort word 25 status byte $00, $00, $00, $00 rxdata byte $0[RxTx_BUFFER] txdata byte $0[RxTx_BUFFER] udpdata byte $0[TEMP_BUFFER] fileErrorHandle long $0 debug byte $0 lastFile byte $0[12], 0 closedState byte 00 openState byte 00 listenState byte 00 establishedState byte 00 closingState byte 00 closeWaitState byte 00 lastEstblState byte 00 lastEstblStateDebug byte 00 udpListen byte 00 tcpMask byte 11 udpMask byte 00 fifoSocketDepth byte $0 fifoSocket long $00_00_00_00 debugSemId byte $00 debugCounter long $00 stringMethods long $00 closingTimeout long $00, $00, $00, $00 udpLen long $00 time byte "00/00/0000 00:00:00", 0 httpDate byte "Wed, 01 Feb 2000 01:00:00 GMT", 0 globalCache byte $1 VAR long StackSpace[20] OBJ pst : "Parallax Serial Terminal" Socket : "W5100_Indirect_Driver" SDCard : "S35390A_SD-MMC_FATEngineWrapper" Request : "Request" Response : "Response" str : "StringMethods" rtc : "S35390A_RTCEngine" PUB Initialize | id, size, st debug := 1 SDCard.Start stringMethods := str.Start Request.Constructor(stringMethods) Response.Constructor(stringMethods, @txdata) pst.Start(115_200) pause(200) 'Mount the SD card pst.str(string("Mount SD Card - ")) SDCard.mount(fileErrorHandle) pst.str(string("OK",13)) pst.str(string("Start RTC: ")) rtc.RTCEngineStart(29, 28, -1) pause(200) pst.str(FillTime) 'Start the W5100 driver if(Socket.Start) pst.str(string(13, "W5100 Driver Started", 13)) pst.str(string(13, "Status Memory Lock ID : ")) pst.dec(Socket.GetLockId) pst.char(13) if(debugSemId := locknew) == -1 pst.str(string("Error, no HTTP server locks available", 13)) else pst.str(string("HTTP Server Lock ID : ")) pst.dec(debugSemId) pst.char(13) 'Set the Socket addresses SetMac(@mac) SetGateway(@gateway) SetSubnet(@subnet) SetIP(@ip) ' Initailize TCP sockets (defalut setting; TCP, Port, remote ip and remote port) repeat id from 0 to 3 InitializeSocket(id) Request.Release(id) pause(50) ' Set all TCP sockets to listen pst.char(13) repeat id from 0 to 3 Socket.Listen(id) pst.str(string("TCP Socket Listener ID : ")) pst.dec(id) pst.char(13) pause(50) pst.Str(string(13,"Started Socket Monitoring Service", 13)) cognew(StatusMonitor, @StackSpace) pause(250) pst.Str(string(13, "Initial Socket States",13)) StackDump pst.Str(string(13, "Initial Socket Queue",13)) QueueDump pst.str(string(13,"//////////////////////////////////////////////////////////////",13)) Main PUB Main | packetSize, id, i, reset, j, temp ''HTTP Service repeat repeat until fifoSocket == 0 bytefill(@rxdata, 0, RxTx_BUFFER) if(debug) pst.str(string(13, "----- Start of Request----------------------------",13)) pause(DELAY) else pause(DELAY) ' Pop the next socket handle id := DequeueSocket if(id < 0) next if(debug) pst.str(string(13,"ID: ")) pst.dec(id) pst.str(string(13, "Request Count : ")) pst.dec(debugCounter) pst.char(13) packetSize := Socket.rxTCP(id, @rxdata) reset := false if ((packetSize < 12) AND (strsize(@rxdata) < 12)) repeat i from 0 to MAX_TRIES pst.str(string(13,"* Retry *")) 'Wait for a few moments and try again waitcnt((clkfreq/300 ) + cnt) packetSize := Socket.rxTCP(id, @rxdata) if(packetSize > 12) quit if(i == MAX_TRIES) 'Clean up resource request Request.Release(id) Socket.Disconnect(id) reset := true if(debug) StackDump pst.char(13) QueueDump pst.str(string(13,"* Timeout *",13)) if(reset) next Request.InitializeRequest(id, @rxdata) if(debug) pst.char(13) HeaderLine1(id) else pause(DELAY) ' Process router Dispatcher(id) 'Clean up request resource Request.Release(id) ' This starts the close process -> 0x00 ' use close to force a close Socket.Disconnect(id) bytefill(@txdata, 0, RxTx_BUFFER) debugCounter++ GotoMain PRI SendLedResposne(id) | headerLen, qstr '' Get the query string value qstr := Request.Get(id, string("led")) '' Exit if there is no querystring if(qstr == 0) return false '' Turn the LED on if the led= value is "on" if (strcomp(string("on"), qstr )) LedStatus(1) else LedStatus(0) if (strcomp(string("what"), qstr )) if (ina[24]) qstr := string("on") else qstr := string("off") '' Build and send the header '' Send the value of led= on or off headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) Socket.txTCP(id, qstr, strsize(qstr)) return true PRI GotoMain Main PRI Dispatcher(id) ''Do some processing before sending the response if(strcomp(Request.GetFileName(id), string("aled.htm")) AND Request.GetDepth(id) == 1) SendLedResposne(id) return StaticFileHandler(id) return PRI LedStatus(state) dira[24] ~~ outa[24] := state return PRI StaticFileHandler(id) | fileSize, i, headerLen, temp, j ''Serve up static files from the SDCard 'pst.str(string(13,"Static File Handler",13)) SDCard.changeDirectory(@approot) pst.char(13) 'Make sure the directory exists ifnot(ChangeDirectory(id)) 'send 404 error WriteError(id) SDCard.changeDirectory(@approot) return ' Make sure the file exists ifnot(FileExists(Request.GetFileName(id))) 'send 404 error WriteError(id) SDCard.changeDirectory(@approot) return ' Open the file for reading SDCard.openFile(Request.GetFileName(id), "r") fileSize := SDCard.getFileSize 'WriteResponseHeader(id) 'BuildHeader(extension, statusCode, expirer) headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) if fileSize < MAX_PACKET_SIZE ' send the file in one packet SDCard.readFromFile(@txdata, fileSize) Socket.txTCP(id, @txdata, fileSize) else ' send the file in a bunch of packets repeat SDCard.readFromFile(@txdata, MAX_PACKET_SIZE) Socket.txTCP(id, @txdata, MAX_PACKET_SIZE) fileSize -= MAX_PACKET_SIZE ' once the remaining fileSize is less then the max packet size, just send that remaining bit and quit the loop if fileSize < MAX_PACKET_SIZE and fileSize > 0 SDCard.readFromFile(@txdata, fileSize) Socket.txTCP(id, @txdata, fileSize) quit ' Bailout if(i++ > 1_000_000) WriteError(id) quit SDCard.closeFile SDCard.changeDirectory(@approot) return PRI WriteError(id) | headerOffset '' Simple 404 error pst.str(string(13, "Write 404 Error",13 )) headerOffset := Response.BuildHeader(Request.GetExtension(id), 404, false) Socket.txTCP(id, @txdata, headerOffset) return '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' directory and file handlers '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI ChangeDirectory(id) | i, found 'Handle directory structure for this Request if(Request.GetDepth(id) > 1) repeat i from 0 to Request.GetDepth(id)-2 'Return if the directory is not found ifnot(FileExists(Request.GetPathNode(id, i))) return false found := SDCard.changeDirectory(Request.GetPathNode(id, i)) return true PRI FileExists(fileToCompare) | filenamePtr 'Start file find at the top of the list SDCard.startFindFile 'Verify that the file exists repeat while filenamePtr <> 0 filenamePtr := SDCard.nextFile if(str.MatchPattern(filenamePtr, fileToCompare, 0, false ) == 0 ) return true return false '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Time Methods and Formats '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetTime(id) | ptr, headerOffset ptr := @udpdata FillHttpDate bytemove(ptr, string("<p>"),3) ptr += 3 bytemove(ptr, @httpDate, strsize(@httpDate)) ptr += strsize(@httpDate) bytemove(ptr, string("</p>"),4) ptr += 3 headerOffset := Response.BuildHeader(Request.GetExtension(id), 200, false) Socket.txTCP(id, @txdata, headerOffset) StringSend(id, @udpdata) bytefill(@udpdata, 0, TEMP_BUFFER) return PRI FillTime | ptr, num 'ToString(integerToConvert, destinationPointer) '00/00/0000 00:00:00 ptr := @time rtc.readTime FillTimeHelper(rtc.clockMonth, ptr) ptr += 3 FillTimeHelper(rtc.clockDate, ptr) ptr += 3 FillTimeHelper(rtc.clockYear, ptr) ptr += 5 FillTimeHelper(rtc.clockHour , ptr) ptr += 3 FillTimeHelper(rtc.clockMinute , ptr) ptr += 3 FillTimeHelper(rtc.clockSecond, ptr) return @time PRI FillHttpDate | ptr, num, temp 'ToString(integerToConvert, destinationPointer) 'Wed, 01 Feb 2000 01:00:00 GMT ptr := @httpDate rtc.readTime temp := rtc.getDayString bytemove(ptr, temp, strsize(temp)) ptr += strsize(temp) + 2 FillTimeHelper(rtc.clockDate, ptr) ptr += 3 temp := rtc.getMonthString bytemove(ptr, temp, strsize(temp)) ptr += strsize(temp) + 1 FillTimeHelper(rtc.clockYear, ptr) ptr += 5 FillTimeHelper(rtc.clockHour , ptr) ptr += 3 FillTimeHelper(rtc.clockMinute , ptr) ptr += 3 FillTimeHelper(rtc.clockSecond, ptr) return @httpDate PRI FillTimeHelper(number, ptr) | offset offset := 0 if(number < 10) offset := 1 str.ToString(@number, @tempNum) bytemove(ptr+offset, @tempNum, strsize(@tempNum)) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' SDCard Logger '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI AppendLog(logToAppend) '' logToAppend: Pointer to a string of test we'd like to log SDCard.changeDirectory(@approot) if(FileExists(@logfile)) SDCard.openFile(@logfile, "A") else SDCard.newFile(@logfile) SDCard.writeData(string(13,10,"----- Start "),14) SDCard.writeData(FillTime, 19) SDCard.writeData(string(" -----"),6) SDCard.writeData(@crlf_crlf, 2) SDCard.writeData(logToAppend, strsize(logToAppend)) SDCard.writeData(@crlf_crlf, 2) SDCard.writeData(string("----- End "),10) SDCard.writeData(FillTime, 19) SDCard.writeData(string(" -----"),6) SDCard.writeData(@crlf_crlf, 2) SDCard.closeFile '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Memory Management '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI Set(DestAddress, SrcAddress, Count) bytemove(DestAddress, SrcAddress, Count) bytefill(DestAddress+Count, $0, 1) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Socekt helpers '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetTcpSocketMask(id) return id & tcpMask PRI DecodeId(value) | tmp if(01 & value) return 0 if(10 & value) return 1 if(00 & value) return 2 if(00 & value) return 3 return -1 PRI QueueSocket(id) | tmp if(fifoSocketDepth > 4) return false tmp := |< id 'Unique check ifnot(IsUnique(tmp)) return false tmp <<= (fifoSocketDepth++) * 8 fifoSocket |= tmp return true PRI IsUnique(encodedId) | tmp tmp := encodedId & $0F repeat 4 if(encodedId & fifoSocket) return false encodedId <<= 8 return true PRI DequeueSocket | tmp if(fifoSocketDepth == 0) return -2 repeat until not lockset(debugSemId) tmp := fifoSocket & $0F fifoSocket >>= 8 fifoSocketDepth-- lockclr(debugSemId) return DecodeId(tmp) PRI ResetSocket(id) Socket.Disconnect(id) Socket.Close(id) PRI IsolateTcpSocketById(id) | tmp tmp := |< id tcpMask &= tmp PRI SetTcpSocketMaskById(id, state) | tmp '' The tcpMask contains the socket the the StatusMonitor monitors tmp := |< id if(state == 1) tcpMask |= tmp else tmp := !tmp tcpMask &= tmp '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' W5100 Helper methods '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI GetCommandRegisterAddress(id) return Socket#_S0_CR + (id * $0100) PRI GetStatusRegisterAddress(id) return Socket#_S0_SR + (id * $0100) PRI SetMac(_firstOctet) Socket.WriteMACaddress(true, _firstOctet) return PRI SetGateway(_firstOctet) Socket.WriteGatewayAddress(true, _firstOctet) return PRI SetSubnet(_firstOctet) Socket.WriteSubnetMask(true, _firstOctet) return PRI SetIP(_firstOctet) Socket.WriteIPAddress(true, _firstOctet) return PRI StringSend(id, _dataPtr) Socket.txTCP(id, _dataPtr, strsize(_dataPtr)) return PRI SendChar(id, _dataPtr) Socket.txTCP(id, _dataPtr, 1) return PRI SendChars(id, _dataPtr, _length) Socket.txTCP(id, _dataPtr, _length) return PRI InitializeSocket(id) Socket.Initialize(id, TCP_PROTOCOL, port, remotePort, @remoteIp) return PRI InitializeSocketForEmail(id) Socket.Initialize(id, TCP_PROTOCOL, port, emailPort, @emailIp) return PRI InitializeUPDSocket(id) Socket.Initialize(id, UDP_PROTOCOL, uport, remotePort, @remoteIp) return '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Debug/Display Methods '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' PRI QueueDump '' Display socket IDs in the queue '' ie 00000401 -> socket Zero is next to pop off pst.str(string("FIFO[")) pst.dec(fifoSocketDepth) pst.str(string("] ")) pst.hex(fifoSocket, 8) PRI StackDump | clsd, open, lstn, estb, clwt, clng, id, ulst '' This method is purely for debugging '' It displays the status of all socket registers repeat until not lockset(debugSemId) clsd := closedState open := openState lstn := listenState estb := establishedState clwt := closeWaitState clng := closingState ulst := udpListen lockclr(debugSemId) pst.char(13) repeat id from 3 to 0 pst.dec(id) pst.str(string("-")) pst.hex(status[id], 2) pst.str(string(" ")) pause(1) pst.str(string(13,"clsd open lstn estb clwt clng udps", 13)) pst.bin(clsd, 4) pst.str(string("-")) pst.bin(open, 4) pst.str(string("-")) pst.bin(lstn, 4) pst.str(string("-")) pst.bin(estb, 4) pst.str(string("-")) pst.bin(clwt, 4) pst.str(string("-")) pst.bin(clng, 4) pst.str(string("-")) pst.bin(ulst, 4) pst.char(13) PRI HeaderLine1(id) | i pst.str(Request.GetMethod(id)) pst.char($20) i := 0 repeat Request.GetDepth(id) pst.char($2F) pst.str(Request.GetPathNode(id, i++)) PRI Pause(Duration) waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt) return PRI StatusMonitor | id, tmp, value '' StatusMonitor is the heartbeat of the project '' Here we monitor the state of the Wiznet 5100's 4 sockets repeat Socket.GetStatus32(@status[0]) ' Encode status register states repeat until not lockset(debugSemId) closedState := openState := listenState := establishedState := { } closeWaitState := closingState := 0 repeat id from 0 to 3 case(status[id]) $00: closedState |= |< id closedState &= tcpMask $13: openState |= |< id openState &= tcpMask $14: listenState |= |< id listenState &= tcpMask $17: establishedState |= |< id establishedState &= tcpMask $18,$1A,$1B: closingState |= |< id closingState &= tcpMask $1C: closeWaitState |= |< id closeWaitState &= tcpMask $1D: closingState |= |< id closingState &= tcpMask $22: udpListen |= |< id udpListen &= udpMask if(lastEstblState <> establishedState) value := establishedState repeat while value > 0 tmp := DecodeId(value) if(tmp > -1) QueueSocket(tmp) tmp := |< tmp tmp := !tmp value &= tmp lastEstblState := establishedState lockclr(debugSemId) ' Initialize a closed socket if(closedState > 0) id := DecodeId(closedState) if(id > -1) InitializeSocket(id & tcpMask) 'Start a listener on an initialized/open socket if(openState > 0) id := DecodeId(openState) if(id > -1) Socket.Listen(id & tcpMask) ' Close the socket if the status is close/wait ' response processor should close the socket with disconnect ' there could be a timeout so we have a forced close. ' TODO: CCheck for a port that gets stuck in a closing state 'if(closeWaitState > 0) 'id := DecodeId(closeWaitState) 'if(id > -1) 'Socket.Close(id & tcpMask) 'pause(100) return DAT approot byte "\", 0 defaultpage byte "index.htm", 0 logfile byte "log.txt", 0 'binFile byte "filename.bin", 0 FS byte "/", 0 fn byte "filename=", 0 doublequote byte $22, 0 crlf byte 13, 10, 0 crlf_crlf byte 13, 10, 13, 10, 0 uploadfile byte $0[12], 0 uploadfolder byte "uploads", 0 tempNum byte "0000",0 multipart byte "Content-Type: multipart/form-data; boundary=",0 boundary byte $2D, $2D boundary1 byte $0[64] 'loadme file "TogglePin0.binary"<html><head> <title>J&A LUX Control</title> <script language="javascript" type="application/javascript"> //Gets the browser specific XmlHttpRequest Object function getXmlHttpRequestObject() { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } else { alert("Your Browser does not support AJAX!\nIt's about time to upgrade don't you think?"); } } //XmlHttpRequest object var req = getXmlHttpRequestObject(); var htmlTarget; function getRequest(resource, elementId) { // handle the case where a querystring is not detected var char = "&"; if(resource.indexOf("?", 0) == -1) { char = "?"; } if (req.readyState == 4 || req.readyState == 0) { req.open("GET", resource + char + 'ms=' + new Date().getTime(), true); req.onreadystatechange = handleResponse; htmlTarget = elementId; req.send(null); return false; } } function handleResponse() { if (req.readyState == 4) { var str = req.responseText; //alert(str); var placeholder = document.getElementById(htmlTarget); placeholder.innerHTML = str; } } </script> </head> <body style="background-color:beige;"> <div style="width:600px;margin:auto;background-color:white;padding:10px;"> <h1 style="text-align:center;color:blue;">LED</h1> <div style="text-align:center;"><a href="index.htm">Home</a> | <a href="led.htm">LUX Control</a></div> <h2>Section</h2> <p> <a href="led.htm" onClick="return getRequest('aled.htm?led=on', 'placeholder');">LED On </a> :: <a href="led.htm" onClick="return getRequest('aled.htm?led=off', 'placeholder');">LED Off</a> </p> <p>LED: <span id="placeholder">State</span></p> [LEFT][FONT=Parallax]<script language="javascript" type="text/javascript"> getRequest('aled.htm?led=what', 'placeholder') [/FONT][/LEFT] </div> </body> </html>Is it possible to have the "LED: State" always update on the page and the Led status remain the same even if I reload the page ?
If you want to see the page http://24.230.203.105:5555/index.htm it is your last code that I use now.
Thank you !!
Also please see the updated Dispatcher method.
Updated methods
PRI SendLedResposne(id) | headerLen, qstr '' Get the query string value qstr := Request.Get(id, string("led")) '' Exit if there is no querystring if(qstr == 0) return false '' Turn the LED on if the led= value is "on" if (strcomp(string("on"), qstr )) LedStatus(1) if (strcomp(string("off"), qstr )) LedStatus(0) if (strcomp(string("what"), qstr )) if(ina[23]) qstr := string("on") else qstr := string("off") '' Build and send the header '' Send the value of led= on or off headerLen := Response.BuildHeader(Request.GetExtension(id), 200, globalCache) Socket.txTCP(id, @txdata, headerLen) Socket.txTCP(id, qstr, strsize(qstr)) return true PRI Dispatcher(id) ''Do some processing before sending the response Request.Get(id, string("led")) if(strcomp(Request.GetFileName(id), string("aled.htm")) AND Request.GetDepth(id) == 1) if(SendLedResposne(id)) return StaticFileHandler(id) return