Shop OBEX P1 Docs P2 Docs Learn Events
Chunking Data transfer — Parallax Forums

Chunking Data transfer

oodesoodes Posts: 131
edited 2013-12-19 11:29 in Accessories
Hello Guys ,

I dont have the exact source code on me its in the office at work but I was having some issues today when trying to chunk data across from Spinneret to another Spinneret. I 'm using one as the Http server. In the ClentGet on the Serve Beer website I'm using the 'GetMyIp' function to contact another spinneret and transfer data. The transfer works fine when the packet is smaller than the rxdata buffer. When the data is larger Im trying to send it in 1k byte chunks cant seem to get it working
  bytefill(@tempBuff, 0, TEMP_BUFFER)        ' Wait for the response   
  repeat until size := Socket.rxTCP(id, @rxdata) { Here the slave spinneret is sending the data after the connection is established. Obviously the first 1k chunk is getting across and I'm logging it the logfile.}   
   bytemove(@tempBuff, @rxdata, strsize(@rxdata))     
  pst.str(@tempBuff)   
 AppendLog(@logfile)
I need to read in 1k of data into the @rxdata , log it in the AppendLog bytefill the buffer with 0's and keep repeating this until all the data is transferred. I know this is a trivial matter but I cant seem to get it working
«1

Comments

  • Mike GMike G Posts: 2,702
    edited 2013-11-14 13:29
    Sounds like you need to implement Flow Control

    I have to ask, why transfer data from one Spinneret to another? Does the second Spinneret process the data?
  • oodesoodes Posts: 131
    edited 2013-11-14 13:55
    So if i implement a type of software handshake-acknowledge would that work?. Send 1000 bytes , second spinneret says ok got it , send me another 1000 and keep repeating until the transfer is complete.?

    Using one spinneret as a expander board to my existed prop devices as all the I/O's are in use , this also enables me to use an Ethernet connection to the device. The httpserver is running a website and requests and view the logs from all the networked prop devices.
  • Mike GMike G Posts: 2,702
    edited 2013-11-15 04:24
    So if i implement a type of software handshake-acknowledge would that work?. Send 1000 bytes , second spinneret says ok got it , send me another 1000 and keep repeating until the transfer is complete.?
    That's it! On the first handshake, send the total bytes and file name. This lets the client know when the file ends and it serves as a validation check.
    Using one spinneret as a expander board to my existed prop devices as all the I/O's are in use , this also enables me to use an Ethernet connection to the device. The httpserver is running a website and requests and view the logs from all the networked prop devices.
    I don't know the project requirements and I don't want to tell you how to design a solution but why send logs from one Spinneret to another? I see the multiple Spinneret as an ideal situation because the logs are unique to the Spinneret. Sending files to a centralized Spinneret means extra code to deal with the batch job and logic to identify the file source. The logs are always available via HTTP GET and a browser.

    I would stay away from a batch job and send log records via HTTP GET or POST in real-time to whatever server. The out-of-the-box HttpServer can easily handle one record at a time and up to 1k as you have identified in post 1.
  • oodesoodes Posts: 131
    edited 2013-11-15 04:38
    I'm making some good progress with this already this morning
    On the first handshake send the total bytes and file name. This lets the client know when the file ends and it serves as a validation check.

    Thats a great idea. Thanks

    I don't know the project requirements and I don't want to tell you how to design a solution but why send logs from one Spinneret to another? I see the multiple Spinneret as an ideal situation because the logs are unique to the Spinneret. Sending files to a centralized Spinneret means extra code to deal with the batch job and logic to identify the file source. The logs are always available via HTTP GET and a browser.



    I all for advice Mike and design ideas, you may have guessed but I a bit of novice :P . Do you mean that by having the Http Server running on one spinneret that I can view the logs stored on the sdcards of the networked spinnerets using the HTTP GET and not having to transfer it ?

    Ah you mean send the log entries to the server as they happen instead of saving them on the sdcard of the 'slaves' and trying to chunk the data like im doing? And then I can view the Logs on the server?
  • Mike GMike G Posts: 2,702
    edited 2013-11-15 04:50
    I all for advice Mike and design ideas, you may have guessed but I a bit of novice . Do you mean that by having the Http Server running on one spinneret that I can view the logs stored on the sdcards of the networked spinnerets using the HTTP GET and not having to transfer it ?
    I'm not sure if I understand the question.

    Any Spinneret running HttpServer and storing logs on an SD Card is accessible by a browser. Moving the files to another Spinneret is extra work unless the target Spinneret is processing the files in some way. Again, I don't know the project specifics but it seems like a lot of extra work for no reason. Is there a reason to batch the log files?
  • Mike GMike G Posts: 2,702
    edited 2013-11-15 05:00
    Ah you mean send the log entries to the server as they happen instead of saving them on the sdcard of the 'slaves' and trying to chunk the data like im doing? And then I can view the Logs on the server?
    Yes, that's what I would do.
  • oodesoodes Posts: 131
    edited 2013-11-15 05:02
    The penny has finally dropped! Mike your a legend.
  • oodesoodes Posts: 131
    edited 2013-12-06 02:05
    Mike,

    Quick question. Can you tell me why that when I access a file on the Spinneret from my browser sometimes it downloads the file and other times it just is viewed on the window. Is this to do with the html code I'm using or the spinneret. Seems to do one or the other at different times if I change bits of code in my source spin file.
    dowload.png
    browserview.jpg
    295 x 145 - 21K
    1024 x 576 - 63K
  • Mike GMike G Posts: 2,702
    edited 2013-12-06 03:47
    It's tough to say without seeing the file and the related source code.

    Is the behavior the same in all browsers?
    What file content causes the file to download?
    What file content causes the file to display in the browser window?

    HttpServer looks at the file extension to send the appropriate content-type header. Is the file extension always txt?
    What behavior do you want; download or view?
  • oodesoodes Posts: 131
    edited 2013-12-06 04:08
    Well at the minute at home I have your out of the box Weserver running , not doing anything. I just wanted to try to contact it from work. I haven't changed any of the code
    On the sd card are some text file
    logs.png
    name as in the Picture.
    http://93.107.65.84:5000 and enter the password 'desmond' . If you click on the Logfiles tab at the top . If you click on PROGEN1 (LOGFILE1.TXT) or PROGEN2(LOGFILE2.TXT) on the Left hand side in the logfiles page you will view the .txt files in the browser. If you click on 'VIEW THE LOGFILES' (LOGTEMPS.TXT) you will download the .txt file.
    Don't mind my crappy webpages :D .
    I want to download the file , not view it

    I normally run Chrome but I just checked it with Explorer and its the same outcome and files are always .TXT . Content is always lines of text unless some unprintable characters make there way in there which can happen. I originally thought it was to do with the size of the file but this is not the case

    DEs
    594 x 66 - 4K
  • Mike GMike G Posts: 2,702
    edited 2013-12-06 05:03
    Include the header Content-Disposition: attachment; to ask the browser to download a file.
    Content-Disposition: attachment; filename="log.txt"
    

    Or right click and save.
  • oodesoodes Posts: 131
    edited 2013-12-06 05:13
    Cheers Mike!
  • oodesoodes Posts: 131
    edited 2013-12-10 08:33
    Mike ,

    Back again. I've migrated my code from the Http Server to the new WebServer and I have a quick question.
    On the old server the Staticfilehandler was called at the end of the Dispatcher(if not returned first). On the new Server RenderFile now does the job of the StaticFilehandler and RenderDynamic handles anything that isnt static. So on the old server from your examples on the ServerBeer it is possible to intercept the RequestLine for the example of turning on and off a LED.
    My question is that I want to parse the querysting from a static file? Like if I have in the html code
    [COLOR=#370707]<a href="led.htm[/COLOR][B]?led=on[/B][COLOR=#370707]">LED On</a>
    [/COLOR]
    
    The render file will always return the led.htm and I want to get to the querystring
    Does my Question make any sense?

    It is located in the HttpHeader in the TokenizeHeader function? How might I extract this and use it?
    repeat until IsEndOfLine(byte[ptr]) 
        if(IsStatusLineToken(byte[ptr]))
          'Set a pointer to the querystring if one exists
          if(byte[ptr] == "?")
            headerSections[QUERYSTRING] := ptr
            sectionTokenCnt[QUERYSTRING] := tokens-1
          byte[ptr++] := 0
          isToken := true
        else
          if(isToken)
            tokenPtr[tokens++] := ptr++
            isToken := false
          else        
            ptr++
    

    Des
  • Mike GMike G Posts: 2,702
    edited 2013-12-10 16:16
    req.Get(String("led"))
    
  • oodesoodes Posts: 131
    edited 2013-12-11 01:51
    Thanks Mike,

    I was making the call from the wrong place.
    if(FileExists(fn, pathElements))
          if(strcomp(Req.GetFileName, string("delete.htm")))               
            pst.str(string(13, "Did we Enter the delete? "))               
            DeleteFile(sockid)
          if(strcomp(Req.GetFileName, string("Update.htm")))               
             pst.str(string(13, "Did we Enter? "))                         
             UpDateLog(sockId)
             'Update:=1
          
          RenderFile(sockId, fn)
    
    

    Think this is right, working anyway

    Thanks
  • Mike GMike G Posts: 2,702
    edited 2013-12-11 03:46
    Take a closer look at the demo WebServer_5100 demo, specifically RenderDynamic. Notice RenderDynamic contains request filters. The filter let you find any request and return a custom response. This behavior is very similar to HttpServer.

    Do you see the four example filters in RenderDynamic?
  • oodesoodes Posts: 131
    edited 2013-12-11 06:48
    Yep I was looking at them and I know I am doing something really simple wrong. My issue was that when I was trying to parse the request I keep returning the static file. I'm thinking my error is in my html
    maybe.
    SO I have a webpage called delete.htm
    <html>
    <head>
    <title>Deleting the LogFile</title>
    </head>
    <body>
    <div style="width:600px;margin:auto;">
      <h1 style="text-align:center;color:blue;">DELETE LOGS</h1>
      <div style="text-align:center;"><a href="host.htm">Main Menu</a> | <a href="logfile.htm">LOGFILES</a></div>
      <p style="text-align:center;color:red;font-size:50px;">ARE YOU SURE YOU WANT TO DELETE THE LOGFILES??</p>
      <p style="text-align:center;color:blue;font-size:20px;"><a href="delete.htm?delete=Yes">YES DELETE</a>           ::           <a href="delete.htm?delete=no">NO DON'T DELETE</a></p>
    </div>
    </body>
    </html>
    
    The static file delete.htm is returned by the Renderfile which is fine for the initial display . But when I am attempting to get to the querystring on the last line of the html
    <a href="delete.htm?delete=Yes">YES DELETE</a>
    
    , the Renderfile returns delete.htm due to the If else statement.
    if(FileExists(fn, pathElements))     
       RenderFile(sockId, fn)   
     else     
       ifnot(RenderDynamic(sockId))       
         sock[sockId].Send(@_404, strsize(@_404))
    
    You will to excuse my ignorance on this Mike.
  • Mike GMike G Posts: 2,702
    edited 2013-12-11 07:31
    The logic says if the file exists on the SD card then render the file. Otherwise, check the HTTP request filter for a dynamic call. Since delete.htm exists the file is returned to the caller. You can always move the logic around and check the RenderDynamic first or change the name of delete.htm to mgmtlog.htm. Secondly, a physical file is not required to perform a task, just a filter.

    i.e. You could create a filter that looks for that returns an XML response to the caller.
    http://123.123.123.123:80/log/delete
    
  • oodesoodes Posts: 131
    edited 2013-12-11 07:52
    I knew what was happening but not sure how to get around it. I had changed the name of the file and my command was getting executed which is the most important thing but I was displaying a blank page in the browser and I just wanted to sort it for the aesthetics more than anything. The webpages will be secondary as I'm working on automating the entire project and able to expand the network by plug and play of additional Spinners.
    I need to look more into the XML end of things and the web side based programming. ROLL on the christmas holidays.
    Thanks again
  • Mike GMike G Posts: 2,702
    edited 2013-12-11 16:56
    If you have the need to render a static file, you can always pass the socket ID and a the file name to the RenderFile(id, fn) method.
  • oodesoodes Posts: 131
    edited 2013-12-12 00:46
    Yes, that could be useful. Cheers.
    Another unrelated Question I came across recently maybe you could shed some light on. If I have a buffer located in the DAT section, say a 1000 bytes and at some point in the Program I do a bytefill of a 1000 0's to clear the buffer , i notice that sometimes this will clear what is located in the DAT section directly below it. Took me a long time to figure out what was happening. e.g below: If I bytefill Logdata with zero's it was also clearing what was in the ENQ location. I noticed this happening also with some elements I had in my VAR section also.
    LogData       byte   $0[LogDatabuff]
    ENQ           byte   $05,$0
    

    One of my spinners also sometimes draws an extra 100mA of current after powerOn , program in the eeprom runs but ethernet connections are unresponsive . You ever come across this?
  • Mike GMike G Posts: 2,702
    edited 2013-12-12 03:37
    Another unrelated Question I came across recently maybe you could shed some light on. If I have a buffer located in the DAT section, say a 1000 bytes and at some point in the Program I do a bytefill of a 1000 0's to clear the buffer , i notice that sometimes this will clear what is located in the DAT section directly below it. Took me a long time to figure out what was happening. e.g below: If I bytefill Logdata with zero's it was also clearing what was in the ENQ location. I noticed this happening also with some elements I had in my VAR section also.
    Sounds like a bug. It's tough to provide any help without the source code. Maybe the log processing is overflowing the buffer? Is LogDatabuff a CON?
    One of my spinners also sometimes draws an extra 100mA of current after powerOn , program in the eeprom runs but ethernet connections are unresponsive . You ever come across this?
    What's the spinneret doing on start up? DHCP, SNTP, initializing hardware???
  • oodesoodes Posts: 131
    edited 2013-12-12 04:14
    LogDatabuff yes is a CON . I moved it to the bottom of the DAT section so it couldn't over right anything.
    CON
      _clkmode = xtal1 + pll16x     
      _xinfreq = 5_000_000
    
    
      TCP_MTU       = 1460
      BUFFER_2K     = $800
      BUFFER_LOG    = $80
      BUFFER_WS     = $20
      BUFFER_SNTP   = 48+8 
    
    
      LogDatabuff   = $3E8 '1000 
    

    This is a modified version of GetMyIp (Modifed probably not in a good way but it works ), don't waste much time sifting to my rubbish code
    PUB GetLogfiles(id) | size, idx, tempMask,size1,x,a,Unit, Timeout,TimeoutCount,y 
        Unit:=1
        LogtransferNo++                                         'keep a record of the number of Logtransfers
        x:=0
        'tempMask := tcpMask
        'tcpMask := SetTcpSocketMaskById(id, 0)
    
    
        repeat until Unit > NoOfUnits 'or Timeout ==1 
    
    
            if byte[remoteIP][0] <> $C0     '192- First byte of IP will always be 192
                pst.str(string(13, "We have No assigned Ip addresses, byte[0]=  "))
                pst.dec(byte[remoteIP][0])
                return
            
            Sock[id].Close                                          'Close the socket number 'id'
            pause(delay)
            sock[id].Init(id, WIZ#TCP, CLIENT_PORT)                'Initialize a socket for connecting to Slave Spinnerets 
            sock[id].RemoteIp(byte[remoteIP][0], byte[remoteIP][1], byte[remoteIP][2], byte[remoteIP][3])
            'sock[id].RemoteIp(192,168,1,15) 
            sock[id].RemotePort(CLIENT_PORT) 
            pause(delay)
            sock[id].Open 
            ' Connect to the remote server
            
            Sock[id].Connect
            pause(delay)
            repeat while !Sock[id].Connected
              TimeoutCount++                    'Increment a counter if we are not getting a connection
              if TimeoutCount==25000            'About 3 seconds
                'pst.str(string(13, "We have a Timeout, Progen No. "))
                'pst.dec(unit)
                'pst.str(string(" is not online",13))
                TimeoutCount:=0
                Timeout:=1
                if(FileExists(@logfilename,1))
                  Sd.openFile(@logfilename, "A")
                else
                  Sd.newFile(@logfilename)
                  Sd.openFile(@logfilename, "W")
                Sd.writeString(@time)
                Sd.writebyte(HT) 
                Sd.writeString(@Progen)
                LOGDEC(Unit)
                Sd.writeString(@ProgenSpin)
                Sd.writebyte(CR)
                Sd.writebyte(LF)
                Sd.closeFile
                Quit                             'Quit the repeat loop 
                'repeat
            
               
            if timeout==1                       'If we do get a Timeout set x=1 so we can skip the next section
              'pst.str(string(13," We here??"))
              x:=1
              Timeout:=0
    
    
            
            if x==0   
               pst.str(string(13, "Connected... Begin Transfer",13))
              
            TimeoutCount:=0
            repeat until x==1             'This is where the data transfer occurs, waits for an ENQ, if recieved sends an ACK 
                'a:=StringSend(id, @Nack)
                bytefill(@logdata,0,strsize(@logdata))
                repeat until size := sock[id].Available
                 if(size =< 0)
                    y:=1
                    Quit
                'pst.str(string(13, "Number of bytes recieved  is ")) 
               ' pst.dec(size)
                sock[id].Receive(@LogData, size)
                'pst.str(string(13, "Data in the recieve buffer is hex  ")) 
                'pst.hex(LogData,2)
                'pst.str(string(13, "Data  string in Ascii is   "))
                'pst.str(@LogData)
                pst.char(CR)
                Pause(100)  
                Timeoutcount:=0
                if y==1
                    pst.str(string(13,"Attempting another Quit",13))
                    Quit
                    
                if strcomp(@ENQ,@Logdata)                                   'Enquiry is the beginning of the handshake 
                   pst.str(string(13,"Recieved a Enq from the slave",13))
                elseif strcomp(@Esc,@Logdata)                               'Esc is the end of the transmission or there is no Logfile to transmitt. 
                   pst.str(string("Recieved an ESC from the Slave ...EJECT",13))  
                   x:=1
                   Quit
                else                                                        'Anything else recieved should be dealt with as an Error and system should -working so far.
                   pst.str(string(13,"Did not receive a ENQ from the slave"))
                   
                   if(FileExists(@logfilename,1))
                      Sd.openFile(@logfilename, "A")
                   else
                      Sd.newFile(@logfilename)
                      Sd.openFile(@logfilename, "W")
                   Sd.writeString(@time)
                   Sd.writebyte(HT) 
                   Sd.writeString(@Progen)
                   LOGDEC(Unit)
                   Sd.writebyte(HT)
                   Sd.writeString(@ErrorShake)
                   Sd.writebyte(CR)
                   Sd.writebyte(LF)
                   Sd.closeFile
                   x:=1
                   Quit
                   
                bytefill(@Logdata, 0, strsize(@logdata))
                Sock[id].Send(@Ack,strsize(@Ack))    'Send the Ack back so the Slave knows to send the Data
                Timeoutcount:=0
                repeat until size := sock[id].Available
                'repeat until size := Sock[id].receive(id, @Logdata)
                    TimeoutCount++                    'Increment a counter if we are not recieving any data. -working so far
                    if TimeoutCount==25000            'About 3 seconds
                       'pst.str(string(13, "We have a Timeout, Progen No. "))
                       'pst.dec(unit)
                       'pst.str(string(" Did not send the data",13))
                       TimeoutCount:=0
                       if(FileExists(@logfilename,1))
                         Sd.openFile(@logfilename, "A")
                       else
                           Sd.newFile(@logfilename)
                           Sd.openFile(@logfilename, "W")
                       Sd.writeString(@time)
                       Sd.writebyte(HT) 
                       Sd.writeString(@Progen)
                       LOGDEC(Unit)
                       Sd.writebyte(HT)
                       Sd.writeString(@ErrorShake)
                       Sd.writebyte(CR)
                       Sd.writebyte(LF)
                       Sd.closeFile
                       x:=1
                       Quit
                       
                sock[id].Receive(@LogData, size)
               
                Sock[id].Send(@Eot,strsize(@Eot)) 
                'AppendLog(@Logdata)
                if(FileExists(@logfilename,1))
                  Sd.openFile(@logfilename, "A")
                else
                  Sd.newFile(@logfilename)
                  Sd.openFile(@logfilename, "W")
                 
                Sd.writeData(@logdata, strsize(@logdata))
                Sd.closeFile  
                'pst.str(string("Are we even in here??????????????"))
                'bytemove(@tempBuff, @rxdata, strsize(@rxdata))
                'pst.str(string("Data recieved from the Slave is .."))
                pst.str(@Logdata)
                pst.char(13)
                'Sd.openFile(string("LOG_FILE.TXT"),"W") 
                'AppendLog(@Logdata)
               ' bytefill(@tempBuff, 0, TEMP_BUFFER)
                bytefill(@Logdata, 0, strsize(@logdata))
                size~
                
               ' pst.str(string("Sending back the EOT.."))
                'pst.hex(Eot,2)
                'pst.char(13)
                
            x:=0   
            pst.str(string(13, "Disconnect and reset socket: "))
            pst.dec(id)
            pst.char(13)
            pst.str(string(13, "Transfer No: "))
            pst.dec(LogTransferNo)
            pst.str(string(" Date & Time: ")) 
            pst.str(@time)
            ' Reset the socket
            Sock[id].Disconnect
            pause(delay)
            Unit++                     'Used for debug-display only
            remoteIp.byte[3]+=1        'Increase the Ip address octet by one . IP address must be sequential at the minute . Starts at 192.168.1.31 this will make next IP 192.168.1.32 and so on for NoOfUnits.
            
        ' Reset the tcpMask 
        'tcpMask := tempMask
        Sock[id].Disconnect
        remoteIp.byte[3]:=15          'Reset the original Ip addresss so the first Unit is contacted again.
        pause(delay)     
        sock[id].Init(id, WIZ#TCP, HTTP_PORT)
        sock[id].open
        sock[id].listen 
        pause(delay)     
        return
    
    What's the spinneret doing on start up? DHCP, SNTP, initializing hardware???

    Pretty much all of the above. Uses your INIT function from the webserver, Starts 2 more cogs , one using FULLDuplexSerial for Comms with another device and another for handling logEntries.
  • Mike GMike G Posts: 2,702
    edited 2013-12-12 04:29
    bytefill(@logdata,0,strsize(@logdata)) 
    
    This code assumes @logdata has a terminating zero. This would be safer; bytefill(@logdata,0,LogDatabuff) but not ideal. Even better logdata[0] := 0.
    sock[id].Receive(@LogData, size) 
    
    This just takes whatever is in the Rx buffer and plops it into LogData. There no "Size" limit checks.
  • Mike GMike G Posts: 2,702
    edited 2013-12-12 04:36
    Starts 2 more cogs , one using FULLDuplexSerial for Comms with another device and another for handling logEntries.
    Place debug statements in the Init method before and after suspect processes. When you find a start without an end, you'll know where execution hangs.
  • oodesoodes Posts: 131
    edited 2013-12-12 04:50
    I'd be lost without ya Mike, thanks for the help.
    Do ya mind me asking , do you work for Parallax or are ya just really into Parallax devices?
  • Mike GMike G Posts: 2,702
    edited 2013-12-13 04:24
    I'm a long time Parallax fan and since I wrote the web server I feel obliged to help.
  • oodesoodes Posts: 131
    edited 2013-12-18 03:48
    Place debug statements in the Init method before and after suspect processes. When you find a start without an end, you'll know where execution hangs.


    Still running into this problem with the extra current draw. I'm thinking its the Spinneret , all cogs are starting fine i have debugged them 7 in total(4 original from webserver , extra SDcard(5) , comms with another Prop using FullduplexSerial(6) and a LogfileHandler(7) but it will hang at
    [/COLOR]
    [COLOR=#333333]Retrieving Network Parameters .. Please wait 
    
    Error Code : 1    ''sometimes Error Code 2
    Discover Error  
    
    when the extra current draw is occurring. This only seems to happen after long stages in Power Down (Overnight) . Could it be related to the charging of the super Capacitor? I also had other code running on this same spinneret a few months ago and it was starting ok but this sporadic probem would occur and could not connect to it when all it was doing was waiting for a connection. Problem only occurs at Startup and seems to be Ethernet related so if it is hardware must be either the Capacitor or the Ethernet PHY

    I have loaded exact same software (bar the MAC address) onto a different Spinneret and its was working fine and then when I loaded back up the original one that was causing problems starting working again. Its a really sporadic problem.

    I remember in one of your posts you mentioned blowing a Spinneret , what was the symptoms do you recall ? I'm just interested to know if you ever had any similar problems and whether I need to bin this spinneret

    Des
  • Mike GMike G Posts: 2,702
    edited 2013-12-18 04:16
    That's a DHCP discovery error. The DHCP library was unable to retrieve an IP address from the DHCP server. It could be a timeout, configuration, an unexpected DHCP packet value, or a process overwriting a buffer. It's hard to say without the source code... feel like a broken record.

    Anyway, you have the error trapped. Retry the the DHCP process when you get a discovery error. Since the issue is intermittent, it's probably a timeout. Timeouts are configurable in the socket object: TRANS_TIMEOUT.
  • oodesoodes Posts: 131
    edited 2013-12-18 04:31
    feel like a broken record.

    :D , I feel bad putting up code and expect someone else to sieve through it.(I wont hesitate next time) I was just interested to see if anything similiar had happened.

    Retry the the DHCP process when you get a discovery error.


    When the extra current draw is happening I can retry it a 100 times and it makes no difference. I have to start disconnecting Ethernet cable , remove the power cables , restart and eventually it works , might be 1 min might be 3 hrs.

    Source to fix the record
    [/COLOR]''121217 -- Added a lock to opening the logfile.txt in case there is a collision. 
    ''131213 -- Think this end is working. Main Server still not accepting every call , docklight will so I think problem is on the other end.
    ''131112 -- Sending 12 bytes to the Main server including the IP. Working sporadically . Investogate-Always sending the data so problem must be on Server side
    ''131211 -- Removing alot of unused code to make space for new code. Commented out sections.  Need to implement a client call to the Main Server for sending Ip address. SendIp not finished. 
    ''131210 -- Contact made with new Main Server.Using Port 5010. Datatransfer is working. Needs collisions testing- Change batch when transferring data.
    ''131209 -- Working to an extent, just tested with Docklight, opening the log when a connection is recieved , needs some fine tuning with The Main Server.
    ''131206 -- Attempting to run this server software on the Progen SPinnerets. Logging the entries from the PROGEN, SPace gona be an issue. Need to get rid of some server code.
    ''       -- Removed SMTP will have to set the clock manual or re-enter the SNTP. Space a Priority  . Needs a lot of work see MULTISOCKET section. Can write or read to sdcard from this function.
    CON
      _clkmode = xtal1 + pll16x     
      _xinfreq = 5_000_000
    
    
      TCP_MTU       = 1460
      BUFFER_2K     = $800
      BUFFER_LOG    = $80
      BUFFER_WS     = $20
      BUFFER_SNTP   = 48+8 
      
      CR            = $0D
      LF            = $0A
      'NULL          = $00
      HT            = $09
      { Web Server Configuration }
      SOCKETS       = 3
      DHCP_SOCK     = 3
      SNTP_SOCK     = 2
      ATTEMPTS      = 5
      { Port Configuration }
      HTTP_PORT     =  5010 '80        'This a Slave Spinneret and we dont want this to contact the Outside world or vice versa.
      SNTP_PORT     =  123
      CLIENT_PORT   =  5005                'This is used to contact the MAIN server to delivier its IP Address
    
    
      { SD IO }
      DISK_PARTION  = 0 
      SUCCESS       = -1
      IO_OK         = 0
      IO_READ       = "r"
      IO_WRITE      = "w"
       '---------------------------------------------------------------------------------------------------------
       '---------------------------------------------------------------------------------------------------------
       '********************************************************************************************************
      '                                                                                                                                     _____
        ' SEE SENDIP(2) FUNCTION THIS MUST BE CONFIGURED. S/N & REMOTE IP OF MAIN SERVER                                      |\    |      |     |
      '                                                                                                                       | \   |      |     |
       '**********************************************************************************************************            |  \  |      |_____|_
       '_________________________________________________________________________________________________________             |   \ |  _   |      |
       '__________________________________________________________________________________________________________            |    \| |_|  |______|
    
    
      { Serial IO PINs } 
      USB_Rx        = 31
      USB_Tx        = 30
    
    
      DELAY           = $05
      {{ Content Types }}
      #0, CSS, GIF, HTML, ICO, JPG, JS, PDF, PNG, TXT, XML, ZIP
      
      {{ USA Standard Time Zone Abbreviations }}
      #-10, HST,AtST,_PST,MST,CST,EST,AlST
    
    
      GMT           = 0
      AZ_TIME       = 1
                  
      {{ USA Daylight Time Zone Abbreviations  }}
      #-9, HDT,AtDT,PDT,MDT,CDT,EDT,AlDT
    
    
      Zone = GMT '<- Insert your timezone
    
    
      RTC_CHECK_DELAY = 4_000_000  '1_000_000 = ~4 minutes
        
    VAR
      long  ProGenStack[50], Cardstack[70]
      long  longHIGH, longLOW, MM_DD_YYYY, DW_HH_MM_SS 'Expected 4-contigous variables for SNTP  
      byte  Progenflag, HandshakeError , Cardentry, Cardready,DeleteLog, Datatransfer, SocketInit ,sdcardlock , IPsent
      byte  ProgenLog[100] ,bufftemp[300]', IpAddress[4]
    DAT
    '64, 147, 116, 229 '<- This SNTP server is on the west coast
    
    
      sntpIp        byte  129, 6, 15, 30  '<- NIST, Gaithersburg, Maryland
      version       byte  "1.2", $0
      hasSd         byte  $00
      approot       byte  "\", $0  
    '  _404          byte  "HTTP/1.1 404 OK", CR, LF,                                {
    '}                     "Content-Type: text/html", CR, LF, CR, LF,                {
    '}                     "<html>",                                                 {
    '}                     "<head>",                                                 {
    '}                     "<title>Not Found</title><head>",                         {
    '}                     "<body>",                                                 {
    '}                     "Page not found!",                                        {                                                                                                       
    '}                     "</body>",                                                {
    '}                     "</html>", CR, LF, $0
    
    
    '  xmlPinState   byte  "<root>", CR, LF, "  <pin>" 
    '  pinNum        byte  $30, $30, "</pin>", CR, LF, "  <value>"
    '  pinState      byte  $30, $30, "</value>", CR, LF, "  <dir>" 
    '  pinDir        byte  $30, $30, "</dir>", CR, LF,                               {
    '}                     "</root>", 0
    
    
    '  xmlTime       byte  "<root>", CR, LF, "  <time>" 
    '  xtime         byte  "00/00/0000 00:00:00</time>", CR, LF, "  <day>"
    '  xday          byte  "---","</day>", CR, LF, "</root>", $0
    
    
    '  _h200         byte  "HTTP/1.1 200 OK", CR, LF, $0
     ' _h404         byte  "HTTP/1.1 404 Not Found", CR, LF, $0
     ' _css          byte  "Content-Type: text/css",CR, LF, $0
     ' _gif          byte  "Content-Type: image/gif",CR, LF, $0
     ' _html         byte  "Content-Type: text/html", CR, LF, $0
     ' _ico          byte  "Content-Type: image/x-icon",CR, LF, $0
     ' _jpg          byte  "Content-Type: image/jpeg",CR, LF, $0
     ' _js           byte  "Content-Type: application/javascript",CR, LF, $0
     ' _pdf          byte  "Content-Type: application/pdf",CR, LF, $0
     ' _png          byte  "Content-Type: image/png",CR, LF, $0 
     ' _txt          byte  "Content-Type: text/plain; charset=utf-8",CR, LF, $0  
     ' _xml          byte  "Content-Type: text/xml",CR, LF, $0
     ' _zip          byte  "Content-Type: application/zip",CR, LF, $0
     ' _contLen      byte  "Content-Length: ", $0   
      _newline      byte  CR, LF, $0
      time          byte  "00/00/0000 00:00:00", 0
      sntpBuff      byte  $0[BUFFER_SNTP] 
      workSpace     byte  $0[BUFFER_WS]
      logBuf        byte  $0[BUFFER_LOG]
      wizver        byte  $00
      buff          byte  $0[BUFFER_2K]
      null          long  $00
      dhcpRenew     byte  $00
      'contentType   long  @_css, @_gif, @_html, @_ico, @_jpg, @_js, @_pdf, @_png, @_txt, @_xml, @_zip, $0
      mtuBuff       long  TCP_MTU
      SOH              byte  $01,$0
      Etx              byte  $03,$0
      Eot              byte  $04,$0
      Enq              byte  $05,$0
      ESC              byte  $1B,$0
      Ack              byte  $06,$0
      LogCreated       byte  "LOG_FILE.TXT was Created for ", 0
      ProgenNo         byte  "ProgenNo. 1 ", 0
      Test1            byte  "This is a test", 0
      ServerShakeErr   byte  "Handshaking Error when Transferring Logfile, Logfile may not be up to date", 0
      HandshakeErr     byte  " Handshaking Error with Progen, Last Data Entry may have been lost", 0
      IP               byte  "IP", 0 
      IpAddress        byte  $00,$00,$00,$00,$00,$00
      'IPstring         word  @IP, @IpAddress , $0
        
       
    
    
    OBJ
      pst             : "Parallax Serial Terminal"
      wiz             : "W5100"
      dhcp            : "Dhcp" 
      sock[SOCKETS]   : "Socket"
      req             : "HttpHeader"
      SDcard          : "S35390A_SD-MMC_FATEngineWrapper"
      SDCard1         : "S35390A_SD-MMC_FATEngineWrapper" '1 Cog 
      sntp            : "SNTP Simple Network Time Protocol v2.11"
      rtc             : "S35390A_RTCEngine"
      Progen          : "PropCom"                         '1 Cog
     
    PUB Init | i, t1 ,t2
    
    
      'A hardware reset can take 1.5 seconds
      'before the Sockets are ready to Send/Receive
      wiz.HardReset(WIZ#WIZ_RESET)
                               
      pst.Start(115_200)      
      pause(500)
    
    
      '---------------------------------------------------
      'Main COG
      '--------------------------------------------------- 
      pst.str(string("COG[0]: Spinneret Web Server v"))
      pst.str(@version)
    
    
      sdcardlock:=locknew
      '---------------------------------------------------
      'Start the ProGen Communication
      '---------------------------------------------------
      ' pst.str(string(CR, "CP1 in"))  
       cognew(ProgGenCog,@ProGenstack)
       repeat until ProGenFlag==1
       pst.str(string(13,"COG[2]: ProgGenCog Started "))
       
        
      '---------------------------------------------------
      'Start the Parallax Serial Terminal
      '---------------------------------------------------
      {
      pst.str(string(CR, "COG["))
      i := pst.GetCogId
      pst.dec(i)
      pst.str(string("]: Parallax Serial Terminal"))
      }
      pst.str(string(CR, "COG[3]: Parallax Serial Terminal"))
      '---------------------------------------------------
      'Start the SD Driver and Mount the SD card 
      '---------------------------------------------------  
      ifnot(SDcard.Start)
        pst.str(string(CR, "        Failed to start SD driver!"))
      else
        pst.str(string(CR, "COG["))
        i := SDcard.GetCogId
        pst.dec(i)
        pst.str(string("]: Started SD Driver"))  
      pause(500)
    
    
      pst.str(string(CR,"        Mount SD Card - "))
      t1 := SDcard.mount(DISK_PARTION)
      t2 := SDCard1.mount(DISK_PARTION) 
      pst.str(t1)
      pst.str(t2) 
      if(strcomp(t1, string("OK"))) and (strcomp(t2, string("OK")))
        hasSd := true
      else
        hasSd := false
        repeat
          pst.str(string(CR,"SD card Error, check and reboot"))
          Pause(2000) 
    
    
      'pst.str(string(CR, "CP2 in"))  
      cognew(Cardhandler,@Cardstack)   
      repeat until Cardready==1 
      '---------------------------------------------------
      'Initialize the Realtime clock library
      '--------------------------------------------------- 
      pst.str(string(CR,"        Init RTC: "))
      rtc.RTCEngineStart(29, 28, -1)
      pst.str(FillTime(@time))
    
    
      '--------------------------------------------------- 
      'Start the WizNet SPI driver
      '--------------------------------------------------- 
      wiz.Start(WIZ#SPI_CS, WIZ#SPI_SCK, WIZ#SPI_MOSI, WIZ#SPI_MISO)
      pst.str(string(CR, "COG["))
      i := wiz.GetCogId
      pst.dec(i)
      pst.str(string("]: Started W5100 SPI Driver"))
    
    
      'Verify SPI connectivity by reading the WizNet 5100 version register 
      wizver := GetVersion
      if(wizver == 0)
        pst.str(string(CR, CR, "SPI communication failed!", CR, "Check connections", CR))
        return
      else
        pst.str(string(CR, "        WizNet 5100 Connected; Reg(0x19) = ") )
        pst.dec(wizver)
    
    
      pst.str(string(CR, "COG[n]: "))
      pst.dec(i~ +1)
      pst.str(string(" COGs in Use"))
        
      pst.str(@divider)
    
    
      'MAC (Source Hardware Address) must be unique
      'on the local network
      'wiz.SetMac($00, $08, $DC, $16, $F1, $32)  '<- My second Spinneret
      wiz.SetMac($00, $08, $DC, $16, $F6, $71)   '<- PROGEN2 Spinneret   -this will change for each Unit
    
    
      'Invoke DHCP to retrived network parameters
      'This assumes the WizNet 5100 is connected 
      'to a router with DHCP support
      pst.str(string(CR,"Retrieving Network Parameters...Please Wait"))
      pst.str(@divider)
      if(InitNetworkParameters)
        PrintNetworkParams
      else
        PrintDhcpError
        return     
      
      '--------------------------------------------------- 
      'Snyc the RTC using SNTP
      '---------------------------------------------------
      pst.str(string(CR, "Sync RTC with Time Server")) 
      pst.str(@divider)
      if(SyncSntpTime(SNTP_SOCK))
        PrintRemoteIp(SNTP_SOCK)
        pst.str(string("Web time.........."))
        DisplayHumanTime
      else
        pst.str(string(CR, "Sync failed"))
    
    
      '--------------------------------------------------- 
      ' Set DHCP renew -> (Current hour + 12) // 24
      '--------------------------------------------------- 
      dhcpRenew := (rtc.clockHour + 12) // 24
      pst.str(string("DHCP Renew........"))
      if(dhcpRenew < 10)
        pst.char("0")
      pst.dec(dhcpRenew)
      pst.str(string(":00:00",CR))
        
    
    
      '--------------------------------------------------- 
      'Start up the web server
      '---------------------------------------------------
      pst.str(string(CR, "Initialize Sockets"))
      pst.str(@divider)
      repeat i from 0 to SOCKETS-1
        sock[i].Init(i, WIZ#TCP, HTTP_PORT)
    
    
      OpenListeners
      StartListners
    
    
      'ResetSntpSock(SNTP_SOCK)
         
      pst.str(string(CR, "Start Socket Services", CR))
      MultiSocketService
    
    
      pst.str(string("Fatal Error!!!"))  
      CloseAll
      pst.str(string(CR, "Rebooting..."))
      pause(1000) 
      reboot
      
    PRI MultiSocketService | bytesToRead, sockId, fn, i, pathElements ,Datawrites, Filelength, Overflow, Remainder, BytesSent,Error1, ServerShakeError,x
      bytesToRead := sockId := i := 0
      repeat
          
          
          repeat
            if IpSent ==0
              Pause(1000)
              if SendIp(2)==0                                                   'Send the Ip address of the unit to the main Server  . 0= Logical False
                repeat until x ==-1
                    Pause(5000)                                                ' -1 == Logical True , functioned returns true when everything is ok
                    x:=SendIP(2)                                              ' -1 == Logical True , functioned returns true when everything is ok
                
                
              sock[sockId].SetSocketIR($FF)
              sockId := ++sockId // SOCKETS   
              pst.str(string(CR,"Exited the Send Ip process"))
              Quit                                                             'If we send an IP we need to quit after it so that we don't semd the logfile, need to close the connection and start the repeat loop again.
              
            Overflow:=FileLength:=Remainder:=Error1:=0 
            bytesToRead~ 
            CloseWait
            
            'Cycle through the sockets one at a time
            'looking for a connections
            'pst.str(string(CR, "Waiting for a connection", CR))
            'PrintAllStatuses
            pst.str(string(CR,"Cp0"))
            repeat until sock[sockId].Connected
              sockId := ++sockId // SOCKETS
              if(++i//RTC_CHECK_DELAY == 0)
                rtc.readTime
                'pst.str(string("DHCP Time check: "))
                'pst.dec(rtc.clockHour)
                'pst.char(":")
                'pst.dec(rtc.clockMinute)
                'pst.char(CR)
                if(rtc.clockHour == dhcpRenew)
                  RenewDhcpLease
                i~
            pst.str(string(CR,"We have a Connection"))      
            'Repeat until we have data in the buffer
            'repeat until bytesToRead := sock[sockId].Available
            'pst.str(string(CR,"Cp2"))
            Datatransfer:=1
            Datawrites:=1
            'Sdcard.closeFile
            repeat until not lockset(sdcardlock)
            if OpenFile(string("LOG_FILE.TXT")) ==-1          'This is logical TRUE 
              pst.str(string(CR,"File is found"))
              lockclr(sdcardlock)
            else
              pst.str(string(CR,"Error with Opening Logfile"))
              lockclr(sdcardlock)
              Quit                                             'not sure what exactly to do here , need to revisit. 
                    'repeat for time being
            Filelength:=SDcard.getFileSize
            'Sdcard.closeFile
            pst.str(string(CR,"Filesize="))
            pst.dec(Filelength)
            pst.char(13)
            if Filelength==0                                           'If no new entries in the logfile then dont do a transfer and send the ESC
              Sock[sockId].send(@ESC,1)
              pst.str(string(13,"LogFile is Empty .QUIT"))
              Datatransfer:=0
              sock[sockid].Disconnect
              Quit
            if Filelength>1000                                        'If the Filength is greater than 1500 then we need to do multiple log transfers
                Datawrites:=(FileLength/1000)                         'Find number of times to write full 1500 bytes
                Overflow:=FileLength//1000                            'Find the overflow
                FileLength:=1000
                Remainder:=1
            'pst.str(string("Datawrites="))
            'pst.dec(Datawrites)
            'pst.char(13)
            'pst.str(string("Overflow="))
            'pst.dec(Overflow)
           ' pst.char(13)
            'PrintAllStatuses
            repeat Datawrites
                'pst.str(string("Sending..Byte in Enq buffer is .."))
                'pst.hex(Enq,2)
                'pst.char(13)                                                
                bytesSent:=Sock[sockId].Send(@Enq,1)                                 'Send an Enq to the Host to begin the Handshake
                pst.str(string("Numbers of bytes sent is.."))
                pst.dec(bytesSent)
                pst.char(13)                                                      
                ByteReturn(@buff)                                                    'Wait for a Response- should be an ACK
                'pst.str(string("Byte returned from Bytereturn is")) 
                'pst.hex(buff.byte[0],2)
                'pst.char(13) 
                if strcomp(@buff,@Ack)                                               'If the response is an ACK , clear the buffer and proceed otherwise stuck in repeat loop.
                   bytefill(@buff, 0, 1)
                   pst.str(string(13,"Found the Ack",13))
                else
                  pst.str(string("Didnt find the Ack..Problem ",13))
                  bytefill(@buff, 0, 1)
                  'bytefill (@buff,$0,1000) 
                  Error1:=ServerShakeError:=1
                  Remainder:=0                                                       'If there is an error we dont want to enter the reaminder loop.         
                  Quit
                  
                bytefill (@buff,$0,1000)                                             'Clear the sending data buffer
                SDCard.readFromFile(@buff, Filelength)                               'Read the Filelength from sd card or Max 1000 bytes
                bytesSent :=Sock[sockId].Send(@buff, Filelength)                     'Send the data to the host
                'Sock.send(@Etx,1) 
                ByteReturn(@buff)
                pst.str(string("No of bytes sent...."))
                pst.dec(bytesSent)
                pst.char(13)
                pst.str(@buff)
                Pause(10)
                pst.char(13)
                                                                                      'Wait for a response-host should a return a EOT when it has finished receiving data
                if strcomp(@buff,@Eot)                                                'If the response is good proceed otherwise stuck in repeat loop 
                   pst.str(string(13,"Received an EOT from server",13))
                else
                   pst.str(string("Didnt find the Eot ",13))
                   pst.str(string("Data in the buff buffer is. "))
                   pst.hex(buff.byte[0],2)
                   pst.char(13)
                   bytefill(@buff, 0, 1)
                   bytefill (@buff,$0,1000) 
                   Error1:=ServerShakeError:=1
                   Remainder:=0                                                       'If there is an error we dont want to enter the reaminder loop.
                   Quit
                'pst.str(string(13,"Did we exit this loop",13))
            if Remainder==1
                'bytefill(@buff, 0, 1)
                pst.str(string(13,"In the remainder sector",13)) 
                'bytefill (@buff,$0,1000)
                bytesSent:=Sock[sockId].Send(@Enq,1)  
                ByteReturn(@buff)                                       'Wait for a Response- should be an ACK
               ' pst.str(string("Byte returned from Bytereturn is")) 
               ' pst.hex(buff.byte[0],2)
               ' pst.char(13) 
                if strcomp(@buff,@Ack)                                  'If the response is an ACK , clear the buffer and proceed otherwise stuck in repeat loop.
                   bytefill(@buff, 0, 1)
                   pst.str(string(13,"Found the Ack 2",13))
                else
                  pst.str(string("Didnt find the Ack 2..Problem ",13))
                  bytefill(@buff, 0, 1)
                  Error1:=1
                  ServerShakeError:=1 
                  Quit 
                FileLength:=SDcard.getFileSize    
                Sdcard.fileseek(FileLength-Overflow)
                SDCard.readFromFile(@buff,Overflow)
                SDCARD.closefile 
                Sock.Send(@buff,Overflow)
                Remainder:=0
                'pst.str(string(13,"In the remainder sector Data="))
                'pst.str(@buff)
                'pst.char(13)
            SDCARD.closefile
            if ServerShakeError ==1
               FillTime(@time)
               SDcard.openFile(string("LOG_FILE.TXT"),"A")
               SDCard.writeString(@time)
               SDCARD.writebyte(HT)
               SDCard.writeString(@ProgenNo)
               SDCARD.writebyte(HT) 
               SDCard.writeString(@ServerShakeErr)
               SDCARD.writebyte(CR)
               SDCARD.writebyte(LF)
               SDCARD.closefile
               ServerShakeError:=0
                                                         'Send an ESC to signify the End of data transfer, host will see this and end close the connection                        
            'pst.str(string("Byte in ESC buffer is .."))
            'pst.hex(ESC,2)
            'pst.char(13)
            if Error1==0                                                   'If there is an error we dont want to delete the Logfile.
               DeleteLog:=1
               Sock[sockid].send(@ESC,1)
               'pst.str(string("Did we send the ESC .Yes if in here."))
            Datatransfer:=0
            sock[sockid].Disconnect
            'Check for a timeout error
            'Move the Rx buffer into HUB memory
            'sock[sockId].Receive(@buff, bytesToRead)
         
            'Display the request header
            pst.str(@buff)
         
            'Tokenize and index the header
        {    req.TokenizeHeader(@buff, bytesToRead)
            fn := req.GetFileName
            pathElements := req.PathElements
            
            if(FileExists(fn, pathElements))
              RenderFile(sockId, fn)
            else
              ifnot(RenderDynamic(sockId))
                sock[sockId].Send(@_404, strsize(@_404))
        }
            'Close the socket and reset the
            'interupt register
            'sock[sockId].Disconnect
            sock[sockId].SetSocketIR($FF)
         
            sockId := ++sockId // SOCKETS
            'pst.str(string(CR,"Cp3"))
    PUB SendIp(id)  |i  , strpointer , TimeoutCount
    'When a device is connected we want it to communicate with the Main server by sending it its IP address so the Main server can contact it to retrive its Logfiles
        IPaddress[0] := 0 
        TimeoutCount:=0
        ipaddress.byte[0]:="I"
        ipaddress.byte[1]:="P"
        ipaddress.byte[2]:="1"                         'This is the serial number of the Unit, This will be Unique for each unit  . Sends the string "SNXXXXIP follwed by the IP  . 12 bytes in total
        ipaddress.byte[3]:="8"
        ipaddress.byte[4]:="3"
        ipaddress.byte[5]:="2" 
       ' ipaddress.byte[6]:="I"
       ' ipaddress.byte[7]:="P"
        'ipaddress.byte[1]:="" 
        strpointer:=@ipAddress+6
        'pst.str(string(CR,"Ip address of this Unit is " ))
        'pst.str(dhcp.GetIp)
        repeat i from 0 to 3
          'pst.dec(byte[dhcp.GetIp][i])
          byte[strpointer++]:= byte[dhcp.GetIp][i]
          'if(i < 3)
          '  pst.char($2E)
          'else
          '  pst.char($0D)
        byte[strPointer++]:=0 
        'pst.dec(dhcp.GetIp)
        pst.str(string(CR,"Ip String address of this Unit is :" ))
        repeat i from 0 to 5
           pst.dec(ipAddress.byte[i])
           if(i >1 and i < 5)
            pst.char($2E)
          ' else
          '   if i>4
          '      pst.char($0D) 
        'repeat
        'if SocketInit==0                                             'If the socket is already Initialized then we dont need to keep repeating this if there is an error
        Sock[id].Close                                           'Close the socket number 'id'
        pause(delay)
        sock[id].Init(id, WIZ#TCP, CLIENT_PORT)                  'Initialize a socket for connecting to Slave Spinnerets 
        'sock[id].RemoteIp(byte[remoteIP][0], byte[remoteIP][1], byte[remoteIP][2], byte[remoteIP][3])
        sock[id].RemoteIp(192,168,1,11)                         'This address will need to be fixed , Progen server will always need to initiate contact to this address. 
        sock[id].RemotePort(5000) 
        pause(delay)
        sock[id].Open 
        ' Connect to the remote server
         
        Sock[id].Connect
        pause(delay)
        'SocketInit:=1
        pst.str(string(CR,"Contacting the server"))    
        repeat while !Sock[id].Connected
         TimeoutCount++                    'Increment a counter if we are not getting a connection
         if TimeoutCount==25000            'About 3 seconds
            'bytefill(@IPaddress,0,6)
            pst.str(string(CR,"Error contacting the Server",CR))
            Sock[id].Disconnect
            pause(delay)     
            sock[id].Init(id, WIZ#TCP, HTTP_PORT)
            sock[id].open
            sock[id].listen 
            Return False                             'Quit the function
          
        pst.str(string(CR,"We have a Connection" ))
        'Sock[id].Send(@@IPString,strsize(@IPString))
        'pause(delay)
        Sock[id].Send(@Ipaddress,strsize(@Ipaddress))
        pst.str(string(CR,"Data sent was " ))
        repeat i from 0 to 5
           pst.dec(ipAddress.byte[i])
           if(i >1 and i < 5)
            pst.char($2E)
        Sock[id].Disconnect
        pause(delay)     
        sock[id].Init(id, WIZ#TCP, HTTP_PORT)
        sock[id].open
        sock[id].listen 
        pause(delay)
        Ipsent:=1                                                       'Stops us ending the Ip after a Logtransfer     
        return true 
        
        
    PUB ByteReturn(strpointer):Timeout |totalbytes,receiving,bytestoread,buffer
        bytefill(@buff,0,1000)
        totalBytes := 0
        receiving:=true
        repeat while receiving
          'Data in the buffer?
           'pst.str(string("CP1")) 
           bytesToRead := sock.Available
           totalBytes += bytesToRead
         
          'Check for a timeout
          if(bytesToRead < 0)
            receiving := false
            pst.str(string("Timeout", CR))
            Timeout:=-1
            return
    
    
          if(bytesToRead == 0)
             receiving := false
             'pst.str(string(CR, "Done Receiving Response", CR))
              next 
    
    
          if(bytesToRead > 0) 
            'Get the Rx buffer  
            buffer := sock.Receive(strpointer, bytesToRead)
           ' pst.str(string(CR, "Are we here?")) 
            'pst.hex(strpointer.byte[0],2) 
            'pst.char(CR)
          bytesToRead~
       'pst.str(string("CP2"))
       'pst.str(string("Data received from the server is.."))
       'pst.hex(server,2)
       'pst.char(13)
       return Timeout 
    PRI RenewDhcpLease | requestIp
      pst.str(string(CR,"Retrieving Network Parameters...Please Wait"))
      pst.str(@divider)
      requestIp := dhcp.GetIp
      dhcp.SetRequestIp(byte[requestIp][0],byte[requestIp][1],byte[requestIp][2],byte[requestIp][3]) 
      if(InitNetworkParameters)
        PrintNetworkParams
      else
        PrintDhcpError
        
      rtc.readTime 
      dhcpRenew := (rtc.clockHour + 12) // 24
      pst.str(string("DHCP Renew........"))
      if(dhcpRenew < 10)
        pst.char("0")
      pst.dec(dhcpRenew)
      pst.str(string(":00:00",CR))
      
    {{   Old root directory structure
    PRI BuildAndSendHeader(id, contentLength) | dest, src
      dest := @buff
      bytemove(dest, @_h200, strsize(@_h200))
      dest += strsize(@_h200)
    
    
      src := GetContentType(req.GetFileNameExtension)
      bytemove(dest, src, strsize(src))
      dest += strsize(src)
    
    
      'Add content-length : value CR, LF
      if(contentLength > 0)
        bytemove(dest, @_contLen, strsize(@_contLen))
        dest += strsize(@_contLen)
        src := Dec(contentLength)
        bytemove(dest, src, strsize(src))
        dest += strsize(src)
        bytemove(dest, @_newline, strsize(@_newline))
        dest += strsize(@_newline)
    
    
      'End the header with a new line
      bytemove(dest, @_newline, strsize(@_newline))
      dest += strsize(@_newline)
      byte[dest] := 0
    
    
      sock[id].send(@buff, strsize(@buff))  
    }}
    {PRI BuildAndSendHeader(id, contentLength, ext) | dest, src
      dest := @buff
      bytemove(dest, @_h200, strsize(@_h200))
      dest += strsize(@_h200)
    
    
      src := GetContentType(GetExtension(ext))
      bytemove(dest, src, strsize(src))
      dest += strsize(src)
    
    
      'Add content-length : value CR, LF
      if(contentLength > 0)
        bytemove(dest, @_contLen, strsize(@_contLen))
        dest += strsize(@_contLen)
        src := Dec(contentLength)
        bytemove(dest, src, strsize(src))
        dest += strsize(src)
        bytemove(dest, @_newline, strsize(@_newline))
        dest += strsize(@_newline)
    
    
      'End the header with a new line
      bytemove(dest, @_newline, strsize(@_newline))
      dest += strsize(@_newline)
      byte[dest] := 0
    
    
      sock[id].send(@buff, strsize(@buff))
    }
    PUB ProgGenCog | Error,locPointer,LocRx,Timeout
    
    
        Progen.start(26,27, 0, 115200)
        pst.str(string(13,"COG[1]: PropCom Object Started ")) 
        ProGenFlag:=1
    
    
        repeat
          
          repeat until Error ==1
            Progen.rxflush                                          'All this loop does is wait on data from the Progen. If there is a Handshake fail , quits the repeat loop and starts again.
            locPointer:=0
            locPointer:=@ProgenLog
            'pst.str(string("Waiting for Data.....",13))
            locRx:=0
            'pst.str(string(CR, "CP1 out"))  
            repeat until locRx ==$05              'wait for ENQ from Progen
               locRx:=Progen.rxcheck
            'pst.str(string("Found the ENQ",13)) 
            Progen.tx($06)                        'If we get a ENQ from the Progen send an ACK
            repeat until locRx ==$02              'wait for STX from Progen  
              locRx:=Progen.rxtime(100)
              if locRx == -1                                'If no byte is recieved
                 TimeOut := -1                             'Timeout has occured
                 pst.str(string("We have a Timeout 0",CR))
                 'outa[user]:=0
                 Error:=1
                 HandshakeError:=1
                 Quit
               'pst.str(string("CP 1",13)) 
            'pst.str(string("Did we make it here",13))
            if Timeout==0
                repeat until locRx==$03 or Timeout==-1               'if we recieve an STX read into the buffer the command
                   locRx:=Progen.rxtime(100)
                   if locRx == -1                                'If no byte is recieved
                      TimeOut := -1                             'Timeout has occured
                       pst.str(string("We have a Timeout 1",CR))
                       'outa[user]:=0
                       Error:=1
                       HandshakeError:=1 
                       Quit
                   else
                     byte[locPointer++] := locRx               'Otherwise keep displayed the next byte recieved
                byte[locPointer-1]:=0
            
            cardentry:=1                                    'See cardhandler  
            pst.str(@ProgenLog)
            pst.char(CR)
            'pst.str(string("Are we here after an Error??",CR))  
            
            'if Error==1
            '   bytefill(@ProgenLog,0,100)
          'pst.str(string("Are we here after an Error Part 2??",CR)) 
          Error:=Timeout:=0 
          
        'repeat
          'Pause(3000)
          'pst.str(string("Just hang here for now",CR))
    PUB Cardhandler | Templogsize ,TempLog   
      
    {  SDCard.Start
      pause(100)
      
       'Mount the SD card
      pst.str(string("Mount SD Card - ")) 
      SDCard.mount(fileErrorHandle) 
      SDCard1.mount(fileErrorHandle)
      pst.str(string("OK",13)) 
    }
      CardReady:=1
      
      ifnot\SDCARD.newfile(string("LOG_FILE.TXT"))
         pst.str(string("LogFile Creation Error ",13))
      else
         pst.str(string("LogFile 1 Created ",13)) 
      SDcard.openFile(string("LOG_FILE.TXT"),"W")
      SDcard.writeString(@time)
      SDCARD.writebyte(HT)
      SDcard.writeString(@LogCreated)
      SDcard.writeString(@ProGenNo)
      SDCARD.writebyte(CR)
      SDCARD.writebyte(LF)
      SDCARD.closefile
    
    
      repeat
        'pst.str(string(CR, "CP2 out"))      
        repeat until CardEntry==1                                   'Repeat until there is a LOGFILE ENTRY on the PROGEN  
         if DeleteLog==1
            SDCARD.deleteEntry(string("LOG_FILE.TXT"))                  'Delete the file so the same contents are not resent
            'pst.str(string(13,"CP1")) 
            SDcard.newFile(string("LOG_FILE.TXT"))                  'Open a new logfile for the next entries
            'pst.str(string(13,"CP2"))
            Sdcard.closeFile
            'pst.str(string(13,"CP3"))
            DeleteLog:=0
         if Datatransfer ==0 and TempLog ==1                        'If there has been a write to the temporary log it must be transferrred to the main log but only when a data transfer is not in progress
            SDcard.openFile(string("LOGFILEA.TXT"),"R")
            Templogsize:=SDcard.getFileSize
            SDCARD.readFromFile(@bufftemp,Templogsize)
            Sdcard.closeFile
            SDcard.openFile(string("LOG_FILE.TXT"),"A")
            SDCard.writeString(@bufftemp)
            SDCARD.writebyte(CR)
            SDCARD.writebyte(LF)
            SDCARD.closefile
            SDCARD.deleteEntry(string("LOGFILEA.TXT"))                  'Delete the file so the same contents are not resent
            bytefill(@bufftemp,0,Templogsize)
            Templogsize:=Templog:=0
        FillTime(@time)
        
        case Datatransfer                'If there is a log transfer in progress we must write to a temporary logfile
         0:
            repeat until not lockset(sdcardlock)
            SDcard.openFile(string("LOG_FILE.TXT"),"A")
            SDCard.writeString(@time)
            SDCARD.writebyte(HT)
            if HandshakeError==1
               SDCard.writeString(@HandshakeErr)
               SDCARD.writebyte(CR)
               SDCARD.writebyte(LF)
               SDCARD.closefile
               CardEntry:=HandshakeError:=0 
            Else
                SDCard.writeString(@ProgenLog)
                SDCARD.writebyte(CR)
                SDCARD.writebyte(LF)
                SDCARD.closefile
                bytefill(@ProgenLog,0,100)
                CardEntry:=0
            lockclr(sdcardlock)    
          'SDCARD.writebyte(CR)
          'SDCARD.writebyte(LF)
         1:
             'pst.str(string(13,"WE in here!!!!!!!!"))
             ifnot\sdcard1.newfile(string("LOGFILEA.TXT"))
                pst.str(string(13,"Sdcard ABorted Error"))
                
             else
               'pst.str(string(13,"Logging in the Temp log",13))
               SDcard1.openFile(string("LOGFILEA.TXT"),"A") 
               SDCard1.writeString(@time)
               SDCARD1.writebyte(HT)
               if HandshakeError==1
                  SDCard1.writeString(@HandshakeErr)
                  SDCARD1.writebyte(CR)
                  SDCARD1.writebyte(LF)
                  SDCARD1.closefile
                  CardEntry:=HandshakeError:=0 
               else
                    SDCard1.writeString(@ProgenLog)
                    SDCARD1.writebyte(CR)
                    SDCARD1.writebyte(LF)
                    SDCARD1.closefile
                    bytefill(@ProgenLog,0,100)
                    CardEntry:=0
                    TempLog:=1  
               
        
    
    
    PRI GetExtension(fn)  
      return fn + (strsize(fn) - 3)
    
    
    
    
    {PRI RenderDynamic(id)
    
    
      'Process pinstate
      if(strcomp(req.GetFileName, string("pinstate.xml")))
        BuildPinStateXml( req.Get(string("led")), req.Get(string("value")) )
        BuildAndSendHeader(id, -1, string("xml"))
        sock[id].Send(@xmlPinState, strsize(@xmlPinState))
        return true
    
    
      if(strcomp(req.GetFileName, string("p_encode.xml")))
        BuildPinEndcodeStateXml( req.Get(string("value")) )
        BuildAndSendHeader(id, -1, string("xml"))
        sock[id].Send(@xmlPinState, strsize(@xmlPinState))
        return true
    
    
      if(strcomp(req.GetFileName, string("time.xml")))
        FillTime(@xTime)
        FillDay(@xday)
        BuildAndSendHeader(id, -1, string("xml"))
        sock[id].Send(@xmlTime, strsize(@xmlTime))
        return true
    
    
      if(strcomp(req.GetFileName, string("sntptime.xml")))
        SyncSntpTime(SNTP_SOCK)
        FillTime(@xTime)
        FillDay(@xday) 
        BuildAndSendHeader(id, -1, string("xml"))
        sock[id].Send(@xmlTime, strsize(@xmlTime))
        ResetSntpSock(SNTP_SOCK) 
        return true  
    
    
      return false
       
    }
      
    {PRI BuildPinStateXml(strpin, strvalue) | pin, value, state, dir
      pin := StrToBase(strpin, 10)
      value := StrToBase(strvalue, 10)  
    
    
      SetPinState(pin, value)
      state := ReadPinState(pin)
    
    
      'Write the pin number to the XML doc
      if(strsize(strpin) > 1)
        bytemove(@pinNum,strpin, 2)
      else
        byte[@pinNum] := $30
        byte[@pinNum][1] := byte[strpin]
    
    
      'Write the pin value
      value := Dec(ReadPinState(pin))
      if(strsize(value) > 1)
        bytemove(@pinState, value, 2)
      else
        byte[@pinState] := $30
        byte[@pinState][1] := byte[value]
    
    
      'Write Pin direction
      dir := Dec(ReadDirState(pin))
      if(strsize(dir) > 1)
        bytemove(@pinDir, value, 2)
      else
        byte[@pinDir] := $30
        byte[@pinDir][1] := byte[dir]
    
    
    
    
    PRI ReadDirState(pin)
      return dira[pin]
       
    PRI ReadPinState(pin)
      return outa[pin] | ina[pin]
     
    PRI SetPinState(pin, value)
      if(value == -1)
        return
      if(pin < 23 or pin > 27)
        return
          
      dira[pin]~~
      outa[pin] := value  
    }
    
    
    {PRI BuildPinEndcodeStateXml(strvalue) | value, state, dir
      value := StrToBase(strvalue, 10)  
    
    
      'pst.dec(value)
      
      if(value > -1)
        SetEncodedPinstate(value)
        state := ReadEncodedPinState
    
    
      'Write the pin number to the XML doc
      bytemove(@pinNum,string("$F"), 2)
    
    
      'Write the pin value
      value := Dec(ReadEncodedPinState)
      if(strsize(value) > 1)
        bytemove(@pinState, value, 2)
      else
        byte[@pinState] := $30
        byte[@pinState][1] := byte[value]
    
    
      'Write Pin direction
      dir := Dec(ReadEncodedDirState)
      if(strsize(dir) > 1)
        bytemove(@pinDir, value, 2)
      else
        byte[@pinDir] := $30
        byte[@pinDir][1] := byte[dir]
    }
        
    {PRI ReadEncodedDirState
      return dira[27..24]
       
    PRI ReadEncodedPinState
      return outa[27..24] | ina[27..24]
    
    
    PRI SetEncodedPinState(value)
      dira[27..24]~~
      outa[27..24] := value   
    }  
    {PRI ValidateParameters(pin, value)
      if(pin < 23 or pin > 27)
        return false
      if(value > 1 or value < -1)
        return false
    
    
      return true
    }
     {{ Old root directory structure
    PRI RenderFile(id, fn) | fs, bytes
    
    
     'Render a static file from the SD Card
    
    
      mtuBuff := sock[id].GetMtu
    
    
      OpenFile(fn)
      fs := SDcard.getFileSize 
      BuildAndSendHeader(id, fs)
    
    
      'pst.str(string(cr,"Render File",cr))
      repeat until fs =< 0
        'Writeline(string("Bytes Left"), fs)
    
    
        if(fs < mtuBuff)
          bytes := fs
        else
          bytes := mtuBuff
    
    
        SDcard.readFromFile(@buff, bytes)
        fs -= sock[id].Send(@buff, bytes)
      
      SDcard.closeFile
      return
     }} 
    {PRI RenderFile(id, fn) | fs, bytes
    {{
      Render a static file from the SD Card
    }}
      mtuBuff := sock[id].GetMtu
    
    
      OpenFile(fn)
      fs := SDcard.getFileSize 
      BuildAndSendHeader(id, fs, fn)
    
    
      'pst.str(string(cr,"Render File",cr))
      repeat until fs =< 0
        'Writeline(string("Bytes Left"), fs)
    
    
        if(fs < mtuBuff)
          bytes := fs
        else
          bytes := mtuBuff
    
    
        SDcard.readFromFile(@buff, bytes)
        fs -= sock[id].Send(@buff, bytes)
      
      SDcard.closeFile
      return
    }
    PRI SyncSntpTime(sockId) | ptr
    
    
      'Initialize the socket
      sock[sockId].Init(SNTP_SOCK, WIZ#UDP, SNTP_PORT)
      'Initialize the destination paramaters
      'sock[sockId].RemoteIp(64, 147, 116, 229)
      sock[sockId].RemoteIp(sntpIp[0], sntpIp[1], sntpIp[2], sntpIp[3])
      sock[sockId].RemotePort(SNTP_PORT)
    
    
      'Setup the buffer
      sntp.CreateUDPtimeheader(@sntpBuff)  
      ptr := SntpSendReceive(SNTP_SOCK, @sntpBuff, 48)
      if(ptr == @null)
        return false
      else
        'Set the time
        SNTP.GetTransmitTimestamp(Zone,@sntpBuff,@LongHIGH,@LongLOW)
        'PUB writeTime(second, minute, hour, day, date, month, year)                      
        rtc.writeTime(byte[@DW_HH_MM_SS][0],      { Seconds
                    } byte[@DW_HH_MM_SS][1],      { Minutes
                    } byte[@DW_HH_MM_SS][2],      { Hour
                    } byte[@DW_HH_MM_SS][3],      { Day of week
                    } byte[@MM_DD_YYYY][2],       { Day
                    } byte[@MM_DD_YYYY][3],       { Month
                    } word[@MM_DD_YYYY][0])       { Year}
    
    
      return true
    
    
    PRI ResetSntpSock(sockId)
      sock[sockId].Init(sockId, WIZ#TCP, HTTP_PORT)
      sock[sockId].Open
      sock[sockId].Listen 
        
    PUB SntpSendReceive(sockId, buffer, len) | bytesToRead, ptr 
      bytesToRead := 0
    
    
      'Open socket and Send Message
      sock[sockId].Open
      sock[sockId].Send(buffer, len)
      pause(500)
      bytesToRead := sock[sockId].Available
       
      'Check for a timeout
      if(bytesToRead =< 0 )
        bytesToRead~
        return @null
    
    
      if(bytesToRead > 0) 
        'Get the Rx buffer  
        ptr := sock[sockId].Receive(buffer, bytesToRead)
    
    
      sock[sockId].Disconnect
      return ptr
    
    
        
    {PRI Writeline(label, value)
      pst.str(label)
      repeat 25 - strsize(label)
        pst.char(".")
      pst.dec(value)
      pst.char(CR)
    }
    PRI OpenFile(filename) | rc
    {{
      Verify if the file exists
    }}
      rc := SDcard.listEntry(filename)
      if(rc == IO_OK)
        rc := SDcard.openFile(filename, IO_READ)
          if(rc == SUCCESS)
            return true
      return false
      
     {{     Single directory
    PRI FileExists(filename) | rc
    
    
      'Verify if the file exists
    
    
      ifnot(hasSd)
        return false
        
      rc := SDcard.listEntry(filename)
      if(rc == IO_OK)
        rc := SDcard.openFile(filename, IO_READ)
          if(rc == SUCCESS)
            SDcard.closeFile
            return true
      return false  
     }}
     
    PRI FileExists(filename, pathElements) | rc
    {{
      Verify if the file exists
    }}
      ifnot(hasSd)
        return false
    
    
      ChangeDirectory(pathElements)
        
      rc := SDcard.listEntry(filename)
      if(rc == IO_OK)
        rc := SDcard.openFile(filename, IO_READ)
          if(rc == SUCCESS)
            SDcard.closeFile
            return true
      return false
    
    
    PRI ChangeDirectory(pathElements) | i
      SDcard.changeDirectory(@approot)
      if(req.IsFileRequest)
        pathElements--  
      'Path elements include a file name
      ' req.IsFileRequest = true if a file is explictly requested
      if(pathElements =< 0)
        'pst.str(string("Root request", CR, CR))
        return
      else
        'pst.str(string("Sub dir request", CR, CR))
        repeat i from 0 to pathElements-1
          'pst.str( req.GetUrlPart(i) )
          'pst.char(CR)
          SDcard.changeDirectory(req.GetUrlPart(i))
            
    {PRI GetContentType(ext)
    {{
      Determine the content-type 
    }}
      if(strcomp(ext, string("css")) OR strcomp(ext, string("CSS")))
        return @@contentType[CSS]
        
      if(strcomp(ext, string("gif")) OR strcomp(ext, string("GIF")))
        return @@contentType[GIF]
        
      if(strcomp(ext, string("htm")) OR strcomp(ext, string("HTM")))
        return @@contentType[HTML]
        
      if(strcomp(ext, string("ico")) OR strcomp(ext, string("ICO")))
        return @@contentType[ICO]
        
      if(strcomp(ext, string("jpg")) OR strcomp(ext, string("JPG")))
        return @@contentType[JPG]
        
      if(strcomp(ext, string("js")) OR strcomp(ext, string("JS")))
        return @@contentType[JS]
        
      if(strcomp(ext, string("pdf")) OR strcomp(ext, string("PDF")))
        return @@contentType[PDF]
        
      if(strcomp(ext, string("png")) OR strcomp(ext, string("PNG")))
        return @@contentType[PNG]
        
      if(strcomp(ext, string("txt")) OR strcomp(ext, string("TXT")))
        return @@contentType[TXT]
        
      if(strcomp(ext, string("xml")) OR strcomp(ext, string("XML")))
        return @@contentType[XML]
        
      if(strcomp(ext, string("zip")) OR strcomp(ext, string("ZIP")))
        return @@contentType[ZIP]
        
      return @@contentType[HTML]
    }
    
    
      
    
    
    PRI GetVersion | i
      i := 0
      result := 0
      repeat until result > 0
        result := wiz.GetVersion
        if(i++ > ATTEMPTS*5)
          return 0
        pause(250)
    
    
    PRI InitNetworkParameters | i
    
    
      i := 0 
      'Initialize the DHCP object
      dhcp.Init(@buff, DHCP_SOCK)
    
    
      'Request an IP. The requested IP
      'might not be assigned by DHCP
      dhcp.SetRequestIp(192, 168, 1, 120)
    
    
      'Invoke the SHCP process
      repeat until dhcp.DoDhcp(true)
        if(++i > ATTEMPTS)
          return false
      return true
    
    
    
    
    PRI PrintDhcpError
      if(dhcp.GetErrorCode > 0)
        pst.char(CR) 
        pst.str(string(CR, "Error Code: "))
        pst.dec(dhcp.GetErrorCode)
        pst.char(CR)
        pst.str(dhcp.GetErrorMessage)
        pst.char(CR)
    
    
    PRI PrintNetworkParams
    
    
      pst.str(string("Assigned IP......."))
      PrintIp(dhcp.GetIp)
      
      pst.str(string("Lease Time........"))
      pst.dec(dhcp.GetLeaseTime)
      pst.str(string(" (seconds)"))
      pst.char(CR)
     
      pst.str(string("DNS Server........"))
      PrintIp(wiz.GetDns)
    
    
      pst.str(string("DHCP Server......."))
      printIp(dhcp.GetDhcpServer)
    
    
      pst.str(string("Router............"))
      printIp(dhcp.GetRouter)
    
    
      pst.str(string("Gateway..........."))                                        
      printIp(wiz.GetGatewayIp)
    
    
    PRI PrintRemoteIp(id)
      pst.str(string("Remote IP........."))
      printIp(wiz.GetRemoteIp(id))
         
    PRI OpenListeners | i
      'pst.str(string("Open",CR))
      repeat i from 0 to SOCKETS-1  
        sock[i].Open
          
    PRI StartListners | i
      repeat i from 0 to SOCKETS-1
        if(sock[i].Listen)
          pst.str(string("Socket "))
          pst.dec(i)
          pst.str(string(" Port....."))
          pst.dec(sock[i].GetPort)
          pst.str(string("; MTU="))
          pst.dec(sock[i].GetMtu)
          pst.str(string("; TTL="))
          pst.dec(sock[i].GetTtl)
          pst.char(CR)
        else
          pst.str(string("Listener failed ",CR))
    
    
    
    
    
    
    PRI SetTranactionTimeout(timeout) | i
      repeat i from 0 to SOCKETS-1
        sock[i].SetTransactionTimeout(timeout)
    
    
    PRI CloseWait | i
      repeat i from 0 to SOCKETS-1
        if(sock[i].IsCloseWait) 
          sock[i].Disconnect
          sock[i].Close
          
        if(sock[i].IsClosed)  
          sock[i].Open
          sock[i].Listen
    
    
    PRI CloseAll | i
      repeat i from 0 to SOCKETS-1
        sock[i].Disconnect
        sock[i].Close
            
    PRI PrintStatus(id)
      pst.str(string("Status ("))
      pst.dec(id)
      pst.str(string(")......."))
      pst.hex(wiz.GetSocketStatus(id), 2)
      pst.char(13)
    
    
    PRI PrintAllStatuses | i
      pst.str(string(CR, "Socket Status", CR))
      repeat i from 0 to SOCKETS-1
        pst.dec(i)
        pst.str(string("  "))
      pst.char(CR)
      repeat i from 0 to SOCKETS-1
        pst.hex(wiz.GetSocketStatus(i), 2)
        pst.char($20)
      pst.char(CR)
          
    PRI PrintIp(addr) | i
      repeat i from 0 to 3
        pst.dec(byte[addr][i])
        if(i < 3)
          pst.char($2E)
        else
          pst.char($0D)
          
    {PRI PrintExtension
      pst.str(req.GetFileNameExtension)
      pst.char(CR)
    
    
    PRI PrintRequestedFileName
      pst.str(req.GetFileName)
      pst.char(CR)  
    }    
    {PRI PrintTokens | i, tcnt   
      't1 := req.GetTokens
      tcnt := req.GetStatusLineTokenCount
      repeat i from 0 to tcnt-1
        pst.str(req.EnumerateHeader(i))
        pst.char(CR)
    }
    {PUB DisplayUdpHeader(buffer)
      pst.char(CR)
      pst.str(string(CR, "Message from......."))
      PrintIp(buffer)
      pst.char(":")
      pst.dec(DeserializeWord(buffer + 4))
      pst.str(string(" ("))
      pst.dec(DeserializeWord(buffer + 6))
      pst.str(string(")", CR))
    }    
    PUB DisplayHumanTime
        if byte[@MM_DD_YYYY][3]<10
           pst.Char("0")
        pst.dec(byte[@MM_DD_YYYY][3])
        pst.Char("/")
        if byte[@MM_DD_YYYY][2]<10
           pst.Char("0")
        pst.dec(byte[@MM_DD_YYYY][2])
        pst.Char("/")
        pst.dec(word[@MM_DD_YYYY][0])                    
        pst.Char($20)
        if byte[@DW_HH_MM_SS][2]<10
           pst.Char("0")
        pst.dec(byte[@DW_HH_MM_SS][2])
        pst.Char(":")
        if byte[@DW_HH_MM_SS][1]<10
           pst.Char("0")
        pst.dec(byte[@DW_HH_MM_SS][1])
        pst.Char(":")
        if byte[@DW_HH_MM_SS][0]<10
           pst.Char("0")
        pst.dec(byte[@DW_HH_MM_SS][0])
        pst.str(string("(GMT "))
        if Zone<0
           pst.Char("-")
        else
           pst.Char("+")
        pst.str(string(" ",||Zone+48,":00) "))
        pst.Char(13)
        
    PRI FillTime(ptr)
     '00/00/0000 00:00:00
    
    
      rtc.readTime
    
    
      FillTimeHelper(rtc.clockDate, ptr)
      ptr += 3
      
      FillTimeHelper(rtc.clockMonth, 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 ptr-17
    
    
    PRI FillDay(ptr)
      rtc.readTime
      bytemove(ptr, rtc.getDayString, 3)
      return ptr
      
    PRI FillTimeHelper(value, ptr) | t1
      if(value < 10)
        byte[ptr++] := "0"
      
      t1 := Dec(value)
      bytemove(ptr, t1, strsize(t1))
    
    
    
    
    PUB Dec(value) | i, x, j
    {{Send value as decimal characters.
      Parameter:
        value - byte, word, or long value to send as decimal characters.
    
    
    Note: This source came from the Parallax Serial Termianl library
    }}
    
    
      j := 0
      x := value == NEGX                                                            'Check for max negative
      if value < 0
        value := ||(value+x)                                                        'If negative, make positive; adjust for max negative                                                                  'and output sign
    
    
      i := 1_000_000_000                                                            'Initialize divisor
    
    
      repeat 10                                                                     'Loop for 10 digits
        if value => i
          workspace[j++] := value / i + "0" + x*(i == 1)                                      'If non-zero digit, output digit; adjust for max negative
          value //= i                                                               'and digit from value
          result~~                                                                  'flag non-zero found
        elseif result or i == 1
          workspace[j++] := "0"                                                                'If zero digit (or only digit) output it
        i /= 10
        
      workspace[j] := 0
      return @workspace
    
    
    PRI DeserializeWord(buffer) | value
      value := byte[buffer++] << 8
      value += byte[buffer]
      return value
      
    PRI StrToBase(stringptr, base) : value | chr, index
    {Converts a zero terminated string representation of a number to a value in the designated base.
    Ignores all non-digit characters (except negative (-) when base is decimal (10)).}
    
    
      value := index := 0
      repeat until ((chr := byte[stringptr][index++]) == 0)
        chr := -15 + --chr & 011111 + 39*(chr > 56)                              'Make "0"-"9","A"-"F","a"-"f" be 0 - 15, others out of range     
        if (chr > -1) and (chr < base)                                              'Accumulate valid values into result; ignore others
          value := value * base + chr                                                  
      if (base == 10) and (byte[stringptr] == "-")                                  'If decimal, address negative sign; ignore otherwise
        value := - value
                 
    PRI pause(Duration)  
      waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
      return
    
    
    DAT
      divider   byte  CR, "-----------------------------------------------", CR, $0
    
    

    I can email it to you if you like

Sign In or Register to comment.