FTP _Client_ for the Fez Panda II

Hi
For a project I am working on I need to upload files containing sensor data from the FEZ to a NAS (FTP server).
I have tried to find code examples showing the FEZ acting as an FTP client uploding files by have not been able to find any examples.

I do have the option of porting/develop my own ftp-client FEZ compliant code based on eg. Jaimon Mathew’s c# FTP client.

But if any one all ready has an working FTP client for the FEZ Panda II I would very much like to have the source code :slight_smile:

Thanks!

Hey there Clylloff, welcome to the forum

I have never seen a FTP client talked about for netmf on the forum here; some talk about the FTP server but nothing about client… Whether you can achieve this will mainly be related to the interactions with the Wiz5100 chip that provides the Panda with netorking capability; that’s where you should start your research. I suspect FTP isn’t an overly complex protocol, but it does use two ports to communicate (commands and data separated) so there may be some peculiarities that you might grapple with - but that’s the fun part right :wink:

Hi,
I’d be interested in a ftp-client for FEZ / Gadgeteer too. If you adopt the code of the Jaimon Mathew ftp-client, i’d be glad if you would post it here in the forum. I used a modification of the open-source ftp-client from Jaimon Mathew (on PC) to communicate with the ftp-server of skewworks (in this forum) on a spider mainboard. It should not be too difficult to adopt the client software.

I cannot find my code, but I did make an FTP client on the Panda II that downloaded a text file and an image file. I had started with .NET 1.1 socket based FTP client program and just fixed the reference errors and I don’t believe I had to do much else. I don’t think it took me too much time either.

An FTP client on the panda is completely achievable. Active mode is the easiest to port in my opinion. I’ve got several projects going already otherwise I’d offer to write up a quick one, but the protocol is very easy and well documented. It shouldn’t take more than a days work. Good luck and don’t forget to show off when you’re done. :slight_smile:

Hi

Sorry for returning so late… This is my first attempt on an FTP client for the FEZ Panda capable of uploading/appending a file to a FTP server. Testet against a Netgear NAS with no problems encountered.

(PS I can’t take credit for all the code…the implemetation is a mix of forum-code and selfmade code )

Usage:


FtpClient.initializeNetwork();
FtpClient.connectToRemoteFtpServer("--IPADRESS--", 21, "ftp_user", "Password");
FtpClient.changeWorkingdirectory("Ftp_root");
FtpClient.appendToFile("Test.txt", Encoding.UTF8.GetBytes("filecontent as string"));
FtpClient.disconnectFromRemoteFtpServer();

Class impelmentation


using System;
using Microsoft.SPOT;
using GHIElectronics.NETMF.Net.Sockets;
using GHIElectronics.NETMF.Net;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Net.NetworkInformation;
using System.Text;
using GHIElectronics.NETMF.FEZ;

namespace FEZ_Panda_II_FTP_Client
{
    static class FtpClient
    {
        static Socket clientSocket;

        public static void initializeNetwork()
        {
            // Enable the Ethernet
            WIZnet_W5100.Enable(SPI.SPI_module.SPI1, (Cpu.Pin)FEZ_Pin.Digital.Di10, (Cpu.Pin)FEZ_Pin.Digital.Di7, true);
            Dhcp.EnableDhcp(new byte[] { 0x00, 0x26, 0x1C, 0x7B, 0x29, 0xE8 }, "FEZ  Temp/Light");
            Debug.Print("Network settings:");
            Debug.Print("IP Address: " + new IPAddress(NetworkInterface.IPAddress).ToString());
            Debug.Print("Subnet Mask: " + new IPAddress(NetworkInterface.SubnetMask).ToString());
            Debug.Print("Default Getway: " + new IPAddress(NetworkInterface.GatewayAddress).ToString());
            Debug.Print("DNS Server: " + new IPAddress(NetworkInterface.DnsServer).ToString());
        }

        public static void connectToRemoteFtpServer(string remoteHost, int remotePort, string remoteUser, string remotePass)
        {
            IPAddress serverFTP_IP = IPAddress.Parse(remoteHost);
            IPEndPoint serverEndPoint = new IPEndPoint(serverFTP_IP, remotePort);
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientSocket.Connect(serverEndPoint);
            Debug.Print("Connected to remote server");
            getRemoteServerReply(220);

            sendCommand("USER " + remoteUser);
            getRemoteServerReply(331);
            sendCommand("PASS " + remotePass);
            getRemoteServerReply(230);
        }

        public static void changeWorkingdirectory(string directory)
        {
            sendCommand("CWD " + directory);
            getRemoteServerReply(250);
        }

        public static void uploadFile(string fileName, byte[] fileData)
        {
            sendCommand("TYPE I");
            getRemoteServerReply(200);

            sendCommand("PASV");
            IPEndPoint uploadEndpoint = getUploadEndpoint(getRemoteServerReply(227));

            clientSocket.SendTimeout = 30000;
            clientSocket.ReceiveTimeout = 30000;

            sendCommand("STOR " + fileName);
            Socket uploadSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            uploadSocket.Connect(uploadEndpoint);
            getRemoteServerReply(150);

            int count = 0;
            while (count < fileData.Length)
            {
                count += uploadSocket.Send(fileData, count, fileData.Length - count, SocketFlags.None);
                Debug.Print("Uploaded bytes: " + count.ToString());
            }
            uploadSocket.Close();
            getRemoteServerReply(226);
        }

        public static void appendToFile(string fileName, byte[] fileData)
        {
            sendCommand("TYPE I");
            getRemoteServerReply(200);

            sendCommand("PASV");
            IPEndPoint uploadEndpoint = getUploadEndpoint(getRemoteServerReply(227));

            clientSocket.SendTimeout = 30000;
            clientSocket.ReceiveTimeout = 30000;

            sendCommand("APPE " + fileName);
            Socket uploadSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            uploadSocket.Connect(uploadEndpoint);
            getRemoteServerReply(150);

            int count = 0;
            while (count < fileData.Length)
            {
                count += uploadSocket.Send(fileData, count, fileData.Length - count, SocketFlags.None);
                Debug.Print("Uploaded bytes: " + count.ToString());
            }
            uploadSocket.Close();
            getRemoteServerReply(226);
        }

        public static void disconnectFromRemoteFtpServer()
        {
            sendCommand("QUIT");
            getRemoteServerReply();
            clientSocket.Close();
        }

        public static void sendCommand(string command)
        {
            Debug.Print("Client request: " + command);
            Byte[] cmdBytes = Encoding.UTF8.GetBytes((command + "\r\n"));
            clientSocket.Send(cmdBytes, cmdBytes.Length, 0);
        }

        public static IPEndPoint getUploadEndpoint(ServerReply serverReply)
        {
            string ipAndPort = "";
            int firstPar = 0;
            int lastPar = 0;

            firstPar = serverReply.servereply.IndexOf("(");
            lastPar = serverReply.servereply.IndexOf(")");
            ipAndPort = serverReply.servereply.Substring(firstPar + 1, lastPar - firstPar - 1);
            string[] ipAndPortParts = ipAndPort.Split(',');
            IPAddress uploadIP = IPAddress.Parse(ipAndPortParts[0] + "." + ipAndPortParts[1] + "." + ipAndPortParts[2] + "." + ipAndPortParts[3]);
            int uploadPort = (Int32.Parse(ipAndPortParts[4]) * 256) + Int32.Parse(ipAndPortParts[5]);
            Debug.Print("File upload port: " + uploadIP.ToString() + ":" + uploadPort);
            return new IPEndPoint(uploadIP, uploadPort);
        }

        public static ServerReply getRemoteServerReply()
        {

            byte[] inBuffer = new byte[100];
            if (clientSocket.Poll(10 * 1000 * 1000, SelectMode.SelectRead))
            {
                int count = clientSocket.Receive(inBuffer);
                string str = new string(Encoding.UTF8.GetChars(inBuffer), 0, count);
                Debug.Print("Remote server reply: " + str);
                return new ServerReply(str, Int32.Parse(str.Substring(0, 3)));
            }
            else
            {
                throw new Exception("Timeout from FTP server");
            }
        }

        public static ServerReply getRemoteServerReply(int expectedReplyCode)
        {
            ServerReply serverReply = getRemoteServerReply();
            if (expectedReplyCode != serverReply.replyCode)
            {
                throw new Exception("Server returned: " + serverReply.replyCode + " " + serverReply.servereply + " Expected: " + expectedReplyCode);
            }
            return serverReply;
        }
    }

    class ServerReply
    {
        string _serverReply;
        int _replyCode;
        public ServerReply(string serverReply, int replyCode)
        {
            _serverReply = serverReply;
            _replyCode = replyCode;
        }

        public string servereply
        {
            get
            {
                return _serverReply;
            }
        }

        public int replyCode
        {
            get
            {
                return _replyCode;
            }
        }
    }
}


2 Likes

Very cool!

I suggest to put it on Codeshare!

1 Like

Done, http://www.tinyclr.com/codeshare/entry/662