Shop OBEX P1 Docs P2 Docs Learn Events
Dump Files on Spinneret w/o removing the card — Parallax Forums

Dump Files on Spinneret w/o removing the card

Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
edited 2011-07-05 17:51 in Accessories
Folks will likely come up with more sophisticated methods of moving files to the SD card on the Spinneret without removing it, but this one is working for me. (mostly)

Simply change the name of the file both in the SD write line and the end of the program.
Use F10 to upload the file to your SD card. Once it's done, the Spinneret will reboot starting the Webserver from EEPROM.

I don't have a perfect method of determining the end of the file, so I get a few characters of trash at the end. (If anyone sees a solution to this, feel free to post it)

Adjust the line if r == 0 or r > 127 to if r == 2 or r > 127
Seems to solve the problem.

File2Spinneret.zip

OBC

Comments

  • Mike GMike G Posts: 2,702
    edited 2011-07-04 15:06
    Hope it's okay that I post my file upload here. I built a console app in C# that uploads first level directory files and root files to a remote Spinneret. It's not the most elegant piece of code but it works and there is a lot of debug code. The C# app expects that you have a directory structure on the SC card... it does NOT create new directories only uploads files to established directories on the SD card. I got tired of pulling the card out every time a made a small change to an HTML file.

    The app has a configuration file, App.config, if you're viewing the project with VS 2010. Otherwise, the exe (MultiSocketUpload.exe) and config (MultiSocketUpload.exe.config) file are in \MultiSocketUpload\MultiSocketUpload\bin\Debug. You have to update the config file for your setup. Again the source can be downloaded from http://www.agaverobotics.com/spinneret/source/
    <configuration>
      <appSettings>
        <add key="remoteSite" value="spinneret.servebeer.com"/>
        <!--<add key="remoteSite" value="spinneret"/>-->
        <add key="port" value="5000"/>
        <add key="localSiteRoot" value="C:\Inetpub\wwwroot\multisocket"/>
        <add key="username" value="username"/>
      </appSettings>
    </configuration>
    

    remoteSite = your Spinneret address
    port = port
    localSiteRoot = the root directory of your HTML web site.
    username = a string to authenticate the upload.

    There's an Authenticate SPIN method that is looking for "username". You should change the Authenticate SPIN method and the default config file node. The console app will ask for a username, if you press enter, the default value in the config file is used. Lazy, I did not feel like typing a username each time I ran a test...

    You also need the SPIN logic see the code snippet below or down load the whole thing from http://www.agaverobotics.com/spinneret/source/
    PRI UploadSite(id) | rxBytes, bytesRead, packetSize, i, j, command
    
      packetSize := 0
      i := 0
      command := PUT
    
      'We're expecting a HTTP PUT
      ifnot(strcomp(Request.GetMethod(id), String("PUT")))
        return
    
      'pst.char(13) 
      'pst.str(@rxdata)
      'pst.char(13)
    
      'Initail handshake
      bytefill(@rxdata, 0, RxTx_BUFFER)
      pst.str(string(13, "Send Greeting"))
      StringSend(id, string("Hello from Spinneret!",13,10))
    
      'Authenticate 
      ifnot(Authenticate(id))
        return
    
      'Get first level target directory 
      GetDirectory(id)
    
      'Repeat until we get the QUIT command from the client
      repeat until command == DONE
    
        'Initailize
        pst.str(string(13, "------------[ Debug ]------------", 13))
        bytefill(@binFile, 0, 12)
        pause(100)
    
        ' Get a filename and size
        GetUploadFileName(id)
        rxBytes := GetFileSize(id)
    
        'if the file exists then delete the file and create a new file
        pst.str(string(13, "File Exists?"))
        if(FileExists(@binFile))
          pst.str(string(13, "YES File Exists - DELETE"))
          SDCard.deleteEntry(@binFile)
         
        pst.str(string(13, "Create file"))
        SDCard.newFile(@binFile)
         
        pst.str(string(13, "Open file"))
        SDCard.openFile(@binFile, "w")
        pst.str(string(13, "File Upload in process"))
    
     
        j := 0
        'Reads the file stream and write to the SD Card   
        repeat while rxBytes > 0
          j++
          ' Get byte stream
          packetSize := Socket.rxTCP(id, @rxdata)
          if(packetSize > 0)
            'Write byte stream to the SD card
            SDCard.writeData(@rxdata, packetSize)
            StringSend(id, string("OK - Write"))
         
            rxBytes := rxBytes - packetSize
            pst.str(string(13, "Bytes Left: "))
            pst.dec(rxBytes)
      
            pause(100)
            i := 0
          else
            i++
            pause(100) 
          if(i > 100)
            StringSend(id, string("TIMEOUT"))
            SDCard.closeFile
            quit
    
        ' Diagnotics - Loop counter
        pst.str(string(13, "loops     : "))
        pst.dec(j)
          
        SDCard.closeFile
        command := GetHttpFileTxCommnad(id)           
    
        'change directory
        if(command == CD)
          SDCard.changeDirectory(@approot)
          GetDirectory(id)
    
      'CD to root and get out of here
      SDCard.changeDirectory(@approot)
      pst.str(string(13, "Done!!!", 13))
      return
    
    
    PRI Authenticate(id) : ok | packetSize
      ''Username
      ok := false
      pst.str(string(13, "Wait for username"))
      repeat
        packetSize := Socket.rxTCP(id, @rxdata)
        pause(200)
        if(packetSize > 0)
          quit
      pst.str(string(13, "Received Username"))
      pst.char(13)
      pst.str(@rxdata)
      if(strcomp(@rxdata, string("username")))
        StringSend(id, string("OK - Authenticated"))
        ok := true 
      else
        StringSend(id, string("QUIT - No Dice"))
        
      bytefill(@rxdata, 0, 50)
      return 
    
      
    PRI GetUploadFileName(id)  | packetSize
      ''Get file name
      pst.str(string(13, "Wait for filename"))
      repeat
        packetSize := Socket.rxTCP(id, @rxdata)
        pause(200)
        if(packetSize > 0)
          quit
          
      pst.str(string(13, "Received Filename: "))
      pst.str(@rxdata)
      
      bytemove(@binFile, @rxdata, strsize(@rxdata) #> 12)
      StringSend(id, string("OK - Received Filename"))
      bytefill(@rxdata, 0, 50)
      return
    
      
    PRI GetFileSize(id) : rxBytes | packetSize
      pst.str(string(13, "Get file size"))
      repeat
        packetSize := Socket.rxTCP(id, @rxdata)
        pause(200)
        if(packetSize > 0)
          quit
          
      pst.str(string(13, "Received File Size: "))
      rxBytes := str.ToInteger(@rxdata)  
      pst.dec(rxBytes)
      
      StringSend(id, string("OK - Received File Size"))
      bytefill(@rxdata, 0, 50)
      return
    
      
    PRI GetDirectory(id) : rxBytes | packetSize
      bytefill(@binDir, 0, 8)
      pst.str(string(13, "Get directory"))
      repeat
        packetSize := Socket.rxTCP(id, @rxdata)
        pause(200)
        if(packetSize > 0)
          quit
          
      pst.str(string(13, "Received Directory: "))
      StringSend(id, string("OK - Received Directory"))
      bytemove(@binDir, @rxdata, strsize(@rxdata))
      pst.str(@binDir)
    
      bytefill(@rxdata, 0, 50)
    
      pst.str(string(13, "Change Directory "))
      SDCard.changeDirectory(@binDir)
      pst.str(string(13, "Change Directory Success"))
      return
    
    PRI GetHttpFileTxCommnad(id) : again | packetSize
      bytefill(@rxdata, 0, RxTx_BUFFER)
      pst.str(string(13, "Upload another file?"))
      repeat
        packetSize := Socket.rxTCP(id, @rxdata)
        pause(200)
        if(packetSize > 0)
          quit
          
      pst.str(string(13, "Received Command: "))
      pst.str(@rxdata)
      
      if(strcomp(@rxdata, string("QUIT")))
        StringSend(id, string("OK - Bye"))
        again := DONE
      if(strcomp(@rxdata, string("PUT")))
        StringSend(id, string("OK - Put File"))
        again := PUT
      if(strcomp(@rxdata, string("CD")))
        StringSend(id, string("OK - Change Directory"))
        again := CD
    
      pst.str(string(13, "File Command: "))
      pst.dec(again)
     
      bytefill(@rxdata, 0, 50)
      return
    

    Finally you'll need an entry in the Dispatcher method to execute the logic.
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2011-07-05 12:48
    I take it that this

    http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-csharp-express

    is the requirement to run this tool?

    Thanks!
    OBC
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2011-07-05 13:14
    Hitting a glitch here.. Your configuration file doesn't seem to like local ip addresses. 192.168.2.123 instead of the domain name spinneret.propellerpowered.com (which isn't accessible from inside my network) causes the upload program to crash.

    OBC
  • Mike GMike G Posts: 2,702
    edited 2011-07-05 16:32
    I use a HOST file on my internal network.
    http://en.wikipedia.org/wiki/Hosts_%28file%29

    I can change the code to accept an IP end point too. I'll have an update in a few hours.
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2011-07-05 16:42
    Thanks Mike!
  • Mike GMike G Posts: 2,702
    edited 2011-07-05 17:51
    Updated the .NET project to accept and IP address as well as a hostname.

    C# express is not required. .NET framework 4 is required to fire up the exe.

    Changed
        // Fancy pants socket routine
        private static Socket ConnectSocket(string server, int port)
        {
            Socket s = null;
            IPHostEntry hostEntry = null;
    
            // Get host related information.
            hostEntry = Dns.GetHostEntry(server);
    ...
    

    to
        // Fancy pants socket routine
        private static Socket ConnectSocket(string server, int port)
        {
            Socket s = null;
            IPHostEntry hostEntry = null;
    
            IPAddress ip;
            if (IPAddress.TryParse(server, out ip))
                hostEntry = Dns.GetHostEntry(ip);
            else
                // Get host related information.
                hostEntry = Dns.GetHostEntry(server);
    ...
    
Sign In or Register to comment.