Simple communication with a TCP/IP device using Python

I had an interesting correspondence recently with Wim Bruyn from Holland who was using my SerialSend program to implement a remote-controlled relay system for switching appliances on and off automatically. The relays Wim is using (ETH002) are actually controlled via TCP/IP, so he ended up abandoning SerialSend in favour of a custom Python script. It struck me as a great example of using Python to do automation really easily and I think others will find it useful. Wim has kindly given me permission to reproduce it here. I made some tiny modifications, but Wim did all the work.

Python is available for Windows, Linux, Mac OS and various other platforms. It can be downloaded for free from python.org and only takes a couple of minutes to install. All modules used in the examples below (socket, smtplib, argparse, time) are part of the standard library, so they shouldn’t require separate installation.

I’ll present this example in two stages. The first is very pared back version which demonstrates the basic process of sending a short byte sequence via TCP/IP and then sending a short report via email.

#
# simple_rc.py - Written by Wim Bruyn (slightly modified by Ted Burke)
#
# This short Python program sends a three byte command to a remote
# controlled relay device via TCP/IP. It receives a response indicating
# whether the command was carried out. A report is then sent via email.
#

import socket    # used for TCP/IP communication 
import smtplib   # used to send email report
import time      # used to insert current date in email report

# Prepare 3-byte control message for transmission
TCP_IP = '192.168.2.115'
TCP_PORT = 17494
BUFFER_SIZE = 80
MESSAGE = '\x21\x01\x00' # Relays 1 permanent off

# Open socket, send message, close socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE)
data = s.recv(BUFFER_SIZE)
s.close()

# Create report and send as email
sender = 'joe.bloggs@email.com'
receivers = ['joe.bloggs@email.com']

if data == '\x00':
    msg = 'Device powered off on date: ' + time.strftime(“%c”)
else:
    msg = 'Error: Device not powered off on date: ' + time.strftime(“%c”)

smtpObj = smtplib.SMTP('mailhost.email.com', 25)
smtpObj.sendmail(sender, receivers, msg)
smtpObj.quit()

The second example, shown below, is Wim’s final program. It parses command line arguments, allowing eight relay modules to be switched on or off individually. Wim uses this program in conjunction with the Windows Task Scheduler to automate on/off switching of appliances.

#
# SwitchETH002.py - Written by Wim Bruyn
#
# Platform: python33, Windows 7
#
# Purpose:
#   Switching ETH002 or ETH008 TCP/IP relays on and off and send an
#   e-mail when done. Windows task scheduler can be used to activate
#   the relays (optional).
#
# Command line arguments required for:
#   Relays number (1-8),
#   Mode (on/off),
#   e-mail report ID (free format text).
#
# Example usage:
#
#   c:\python33\python.exe SwitchETH002.py 2 off "External WD USB disk"
#

import socket
import time
import argparse
import smtplib

def SendCommandToRelays (MESSAGE): #Value of MESSAGE is command to be send to relays
    TCP_IP = '192.168.2.115' #IP address of the relays
    TCP_PORT = 17494 #Port number of the relays
    BUFFER_SIZE = 80

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((TCP_IP, TCP_PORT))
    s.send(MESSAGE)
    data = s.recv(BUFFER_SIZE) #Response from Relays
    s.close()

    if data == b'\x00':
        SendMailMessage ( (args.Device + ' is powered ' + args.Function + ', on date: ' + time.strftime("%c") ) )
    else:
        SendMailMessage ( ('Error:' + args.Device + ' is not powered ' + args.Function + ', on date: ' + time.strftime("%c")) )

def SendMailMessage (Mtext): #Value of Mtext is action report send to mail recipient
    sender = 'joe.bloggs@email.com' #mail address of the sender
    receivers = ['joe.bloggs@email.com'] #mail address of the receiver

    smtpObj = smtplib.SMTP(‘mailhost.email.com’, 25)
    smtpObj.sendmail(sender, receivers, Mtext)
    smtpObj.quit()

parser = argparse.ArgumentParser()
parser.add_argument ("Number", help = "Relays number 1 – 8", type=int, choices = [1, 2, 3, 4, 5, 6, 7, 8])
parser.add_argument ("Function", help = "on is relays on, off is relays off", choices = ["on", "off"])
parser.add_argument ("Device", help = "Device id for e-mail message")

args = parser.parse_args()

if args.Number == 1 :
    if args.Function == 'on' :
        print ('Relays 1 on'),
        SendCommandToRelays ( b'\x21\x01\x00' ) #Relays 1 permanent on
    elif args.Function == 'off' :
        print ('Relays 1 off'),
        SendCommandToRelays ( b'\x20\x01\x00' ) #Relays 1 permanent off

if args.Number == 2 :
    if args.Function == 'on' :
        print ('Relays 2 on'),
        SendCommandToRelays ( b'\x21\x02\x00' ) #Relays 2 permanent on
    elif args.Function == 'off' :
        print ('Relays 2 off'),
        SendCommandToRelays ( b'\x20\x02\x00' ) #Relays 2 permanent off

if args.Number == 3 :
    if args.Function == 'on' :
        print ('Relays 3 on'),
        SendCommandToRelays ( b'\x21\x03\x00' ) #Relays 3 permanent on
    elif args.Function == 'off' :
        print ('Relays 3 off'),
        SendCommandToRelays ( b'\x20\x03\x00' ) #Relays 3 permanent off

if args.Number == 4 :
    if args.Function == 'on' :
        print ('Relays 4 on'),
        SendCommandToRelays ( b'\x21\x04\x00' ) #Relays 4 permanent on
    elif args.Function == 'off' :
        print ('Relays 4 off'),
        SendCommandToRelays ( b'\x20\x04\x00' ) #Relays 4 permanent off

if args.Number == 5 :
    if args.Function == 'on' :
        print ('Relays 5 on'),
        SendCommandToRelays ( b'\x21\x05\x00' ) #Relays 5 permanent on
    elif args.Function == 'off' :
        print ('Relays 5 off'),
        SendCommandToRelays ( b'\x20\x05\x00' ) #Relays 5 permanent off

if args.Number == 6 :
    if args.Function == 'on' :
        print ('Relays 6 on'),
        SendCommandToRelays ( b'\x21\x06\x00' ) #Relays 6 permanent on
    elif args.Function == 'off' :
        print ('Relays 6 off'),
        SendCommandToRelays ( b'\x20\x06\x00' ) #Relays 6 permanent off

if args.Number == 7 :
    if args.Function == 'on' :
        print ('Relays 7 on'),
        SendCommandToRelays ( b'\x21\x07\x00' ) #Relays 7 permanent on
    elif args.Function == 'off' :
        print ('Relays 7 off'),
        SendCommandToRelays ( b'\x20\x07\x00' ) #Relays 7 permanent off

if args.Number == 8 :
    if args.Function == 'on' :
        print ('Relays 8 on'),
        SendCommandToRelays ( b'\x21\x08\x00' ) #Relays 8 permanent on
    elif args.Function == 'off' :
        print ('Relays 8 off'),
        SendCommandToRelays ( b'\x20\x08\x00' ) #Relays 8 permanent off
About these ads
This entry was posted in Uncategorized and tagged , , , , , , , , , , , , , . Bookmark the permalink.

One Response to Simple communication with a TCP/IP device using Python

  1. Brad says:

    Thank You…I will try it.

    Brad

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s