Tutorial 30: Transfer a File using Socket File Transfer

In the context of the Cookie Thief project we need to back up any pictures we take with our Raspberry Pi. I show you how to do that in this tutorial. In this tutorial I show you how to transfer or backup a file using Python 3, sockets and two Raspberry Pis.

This tutorial is a little older (published in 2015!). The main principles are still relevant, so I haven't needed to update this lesson.


DIFFICULTY
DIFFICULT
COMPUTER FAMILIARITY
SOME
PYTHON PROGRAMMING
LOTS
ABOUT
0
MINUTES
  • How to transmit a file between two computers using Python 3

You can copy / paste the code below if you’re having issues with typos or want a shortcut. However I recommend that you follow along in the tutorial to understand what is going on!

cookieServer3.py


import socket
from cookieLED import callLED

host = ''
port = 5560

def setupServer():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print("Socket created.")
    try:
        s.bind((host, port))
    except socket.error as msg:
        print(msg)
    print("Socket bind comlete.")
    return s

def setupConnection():
    s.listen(1) # Allows one connection at a time.
    conn, address = s.accept()
    print("Connected to: " + address[0] + ":" + str(address[1]))
    return conn

def storeFile(filePath):
    picFile = open(filePath, 'wb')
    print("Opened the file.")
    pic = conn.recv(1024)
    while pic:
        print("Receiving picture still.")
        picFile.write(pic)
        pic = conn.recv(1024)
    picFile.close()

def dataTransfer(conn):
    # A big loop that sends/receives data until told not to.
    while True:
        # Receive the data
        data = conn.recv(1024) # receive the data
        data = data.decode('utf-8')
        # Split the data such that you separate the command
        # from the rest of the data.
        dataMessage = data.split(' ', 1)
        command = dataMessage[0]
        if command == 'GET':
            reply = GET()
        elif command == 'REPEAT':
            reply = REPEAT(dataMessage)
        elif command == 'STORE':
            print("Store command received. Time to save a picture")
            storeFile(dataMessage[1])
            reply = "File stored."
        elif command == 'LED_ON':
            callLED()
            reply = 'LED was on'
        elif command == 'EXIT':
            print("Our client has left us :(")
            break
        elif command == 'KILL':
            print("Our server is shutting down.")
            s.close()
            break
        else:
            reply = 'Unknown Command'
        # Send the reply back to the client
        conn.sendall(str.encode(reply))
        print("Data has been sent!")
    conn.close()
        

s = setupServer()

while True:
    try:
        conn = setupConnection()
        dataTransfer(conn)
    except:
        break

cookieClient3.py


import socket
from time import sleep
from time import time

host = '192.168.2.2'
port = 5560

def setupSocket():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    return s

def sendPic(s, filePath):
    print(filePath)
    pic = open(filePath, 'rb')
    chunk = pic.read(1024)
    s.send(str.encode("STORE " + filePath))
    t = time()
    while chunk:
        print("Sending Picture")
        s.send(chunk)
        chunk = pic.read(1024)
    pic.close()
    print("Done sending")
    print("Elapsed time = " + str(time() - t) + 's')
    s.close()
    return "Done sending"

def sendReceive(s, message):
    s.send(str.encode(message))
    reply = s.recv(1024)
    print("We have received a reply")
    print("Send closing message.")
    s.send(str.encode("EXIT"))
    s.close()
    reply = reply.decode('utf-8')
    return reply

def transmit(message):
    s = setupSocket()
    response = sendReceive(s, message)
    return response

def backup(filePath):
    s = setupSocket()
    response = sendPic(s, filePath)
    return response

cookieMain3.py


import P3picam
import picamera
from datetime import datetime
from subprocess import call
from time import sleep
from cookieClient3 import backup
from cookieAnalog2 import getTemp

motionState = False
picPath = "/home/pi/Desktop/cookie/images/"
sleepTime = 3
triggerTemp = 20

def captureImage(currentTime, picPath):
    # Generate the picture's name
    picName = currentTime.strftime("%Y.%m.%d-%H%M%S") + '.jpg'
    with picamera.PiCamera() as camera:
        camera.resolution = (1280, 720)
        camera.capture(picPath + picName)
    print("We have taken a picture.")
    return picName

def getTime():
    # Fetch the current time
    currentTime = datetime.now()
    return currentTime

def timeStamp(currentTime, picPath, picName):
    # Variable for file path
    filepath = picPath + picName
    # Create message to stamp on picture
    message = currentTime.strftime("%Y.%m.%d - %H:%M:%S")
    # Create command to execute
    timestampCommand = "/usr/bin/convert " + filepath + " -pointsize 36 \
    -fill red -annotate +700+650 '" + message + "' " + filepath
    # Execute the command
    call([timestampCommand], shell=True)
    print("We have timestamped our picture.")

def tempMonitor():
    print("About to take a reading.")
    temp = float(getTemp())
    print("Out temp is: " + str(temp))
    if temp > float(triggerTemp):
        message = "LED_ON"
        print("Transmitting data.")
        response = transmit(message)
        print(response)

while True:
    currentTime = getTime()
    picName = captureImage(currentTime, picPath)
    print("Took a picture")
    completePath = picPath + picName
    print(completePath)
    backup(completePath)
    print("Everything should be backed up now.")
    break
    #motionState = P3picam.motion()
    #tempMonitor()
    #sleep(sleepTime)
    #print(motionState)
    #if motionState:
    #    currentTime = getTime()
    #    picName = captureImage(currentTime, picPath)
    #    timeStamp(currentTime, picPath, picName)
        

You shouldn’t need any additional material to complete this tutorial.