Shop OBEX P1 Docs P2 Docs Learn Events
Spinneret *Timeout* — Parallax Forums

Spinneret *Timeout*

PodionPodion Posts: 90
edited 2012-08-20 10:26 in Propeller 1
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
{{
───────────────────────────────────────────────── 
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"                 


{{
&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
&#9474;                                                   TERMS OF USE: MIT License                                                  &#9474;                                                            
&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
&#9474;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    &#9474; 
&#9474;files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    &#9474;
&#9474;modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software&#9474;
&#9474;is furnished to do so, subject to the following conditions:                                                                   &#9474;
&#9474;                                                                                                                              &#9474;
&#9474;The above copyright notice and this permission notice shall be included in all copies or substantial ions of the Software.&#9474;
&#9474;                                                                                                                              &#9474;
&#9474;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          &#9474;
&#9474;WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         &#9474;
&#9474;COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   &#9474;
&#9474;ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         &#9474;
&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
}}

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

  • Mike GMike G Posts: 2,702
    edited 2012-07-23 20:30
    Try lengthening the retry delay.

    See the following post (18) for more information.
    http://forums.parallax.com/showthread.php?138781-Spinneret-Errors-%28Can-t-load-page!%29
  • twctwc Posts: 107
    edited 2012-07-24 06:18
    Using Explorer I can access your server, but the LED: state isn't shown (it's always blank) so I don't know if the LED_ON, LED_OFF control is working.
  • PodionPodion Posts: 90
    edited 2012-07-24 10:55
    Ok thank you TWC ! I will check for the led status.
  • PodionPodion Posts: 90
    edited 2012-07-25 18:43
    I fix The LED State. And for my IPhone I just change those
    DELAY           = $10
      MAX_TRIES       = $25
    

    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..
  • Mike GMike G Posts: 2,702
    edited 2012-07-25 18:56
    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 ?
    See the Service and Ajax section of the tutorial.
    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
  • PodionPodion Posts: 90
    edited 2012-08-15 10:00
    Hello Mike,
    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>
    
    
    
    {{&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; 
    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        
    &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; 
    }}
    
    
    {
    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"                 
    
    
    
    
    
  • Mike GMike G Posts: 2,702
    edited 2012-08-16 12:50
    Podion,

    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 true
    

    2) 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?
  • PodionPodion Posts: 90
    edited 2012-08-19 21:48
    Almost .. When I use the following code, the LED stay "on" when I refreshed the page but the "LED : State" always return to "State".
    {{
    &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; 
    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        
    &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; 
    }}
    
    
    {
    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:
            &#8226; Parallax Serial Terminal.spin
            &#8226; W5100_Indirect_Driver.spin
            &#8226; S35390A_SD-MMC_FATEngineWrapper.spin
            &#8226; Request.spin
            &#8226; Response.spin
            &#8226; StringMethods.spin
            &#8226; 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.
    {{
    &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; 
    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        
    &#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472; 
    }}
    
    
    {
    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:
            &#8226; Parallax Serial Terminal.spin
            &#8226; W5100_Indirect_Driver.spin
            &#8226; S35390A_SD-MMC_FATEngineWrapper.spin
            &#8226; Request.spin
            &#8226; Response.spin
            &#8226; StringMethods.spin
            &#8226; 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 !!
  • Mike GMike G Posts: 2,702
    edited 2012-08-20 08:30
    The SendLedResponse method in your last post is not the updated method. Please take a closer look at the the the first IF blocks. As written in your last post, if the query string is NOT led=on then the LED is turned off. You must update the if block to filter for both "on" and "off".

    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
    
  • PodionPodion Posts: 90
    edited 2012-08-20 10:26
    You are right it is my mistake. With this code everything works! Thank you very much Mike! You're awesome! :smile:
Sign In or Register to comment.