├── README.md ├── s7-read-example.py ├── s7-read-new.py ├── s7-writeoutputs-new.py └── scan7.py /README.md: -------------------------------------------------------------------------------- 1 | scan7 2 | ===== 3 | 4 | Tool to communicate with Siemens S7 PLCs. 5 | This tool is based on Snap7 library, as well as the Python wrapper. 6 | Install docs can be found here : http://python-snap7.readthedocs.org/en/latest/installation.html 7 | 8 | See http://snap7.sourceforge.net/snap7_client.html for supported functions. 9 | Some functions are not supported on S7-1200 and S7-1500. 10 | -------------------------------------------------------------------------------- /s7-read-example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import snap7 5 | 6 | SIEMENS_S71200 = '192.168.0.50' 7 | 8 | class Siemens(object): 9 | 10 | def __init__(self, host): 11 | self.client = snap7.client.Client() 12 | self.client.connect(SIEMENS_S71200, 0, 1) 13 | 14 | def read_input(self, i): 15 | r = self.client.read_area(snap7.types.areas['PE'], 0, i, 1) 16 | return r[0] == 1 17 | 18 | def read_output(self, i): 19 | r = self.client.read_area(snap7.types.areas['PA'], 0, i, 1) 20 | return r[0] == 1 21 | 22 | def write_output(self, area, data): 23 | data = bytearray([0x01]) 24 | r = self.client.write_area(snap7.types.areas['PA'], 0, 0, data) 25 | return r 26 | 27 | def close(self): 28 | self.client.disconnect() 29 | 30 | 31 | s7 = Siemens(SIEMENS_S71200) 32 | 33 | print 'Valeurs des inputs' 34 | for i in range(0, 7): 35 | print 'Valeur input ' + str(i) + ' : ' + str(s7.read_input(i)) 36 | 37 | print '\r\nValeur des outputs' 38 | for i in range(0, 7): 39 | print 'Valeur output ' + str(i) + ' : ' + str(s7.read_output(i)) 40 | 41 | s7.close() 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /s7-read-new.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import snap7 5 | import sys 6 | 7 | SIEMENS_S71200 = sys.argv[1] 8 | 9 | s7 = snap7.client.Client() 10 | s7.connect(SIEMENS_S71200, 0, 1) 11 | r = s7.read_area(snap7.types.areas['PE'], 0, 0, 1) 12 | rr = bin(r[0]) 13 | rrr = rr[2:] 14 | while len(rrr) < 8: 15 | rrr = '0' + rrr 16 | 17 | Input0 = rrr[7] 18 | Input1 = rrr[6] 19 | Input2 = rrr[5] 20 | Input3 = rrr[4] 21 | Input4 = rrr[3] 22 | Input5 = rrr[2] 23 | Input6 = rrr[1] 24 | Input7 = rrr[0] 25 | 26 | s = s7.read_area(snap7.types.areas['PA'], 0, 0, 1) 27 | ss = bin(s[0]) 28 | sss = ss[2:] 29 | while len(sss) < 6: 30 | sss = '0' + sss 31 | 32 | 33 | Output5 = sss[0] 34 | Output4 = sss[1] 35 | Output3 = sss[2] 36 | Output2 = sss[3] 37 | Output1 = sss[4] 38 | Output0 = sss[5] 39 | 40 | print '=== Inputs ===' 41 | print "Input 0 : " + Input0 42 | print "Input 1 : " + Input1 43 | print "Input 2 : " + Input2 44 | print "Input 3 : " + Input3 45 | print "Input 4 : " + Input4 46 | print "Input 5 : " + Input5 47 | print "Input 6 : " + Input6 48 | print "Input 7 : " + Input7 49 | 50 | print '===Outputs===' 51 | print "Output 0 : " + Output0 52 | print "Output 1 : " + Output1 53 | print "Output 2 : " + Output2 54 | print "Output 3 : " + Output3 55 | print "Output 4 : " + Output4 56 | print "Output 5 : " + Output5 57 | 58 | s7.disconnect() -------------------------------------------------------------------------------- /s7-writeoutputs-new.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import snap7 5 | import sys 6 | 7 | SIEMENS_S71200 = sys.argv[1] 8 | LIGHTS = sys.argv[2] 9 | 10 | s7 = snap7.client.Client() 11 | s7.connect(SIEMENS_S71200, 0, 1) 12 | LIGHTS = LIGHTS[::-1] 13 | data1 = bytearray([int(LIGHTS, 2)]) 14 | r = s7.write_area(snap7.types.areas['PA'], 0, 0, data1) 15 | print r 16 | s7.disconnect() -------------------------------------------------------------------------------- /scan7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import snap7 5 | 6 | # OptionParser imports 7 | from optparse import OptionParser 8 | 9 | import logging 10 | logging.basicConfig() 11 | 12 | # Script version 13 | VERSION = '0.1a' 14 | 15 | # Options definition (I stole this options parsing thing from Thomas Debize but he's OK with it 16 | option_0 = { 'name' : ('-t', '--target'), 'help' : 'IP address of the PLC', 'nargs' : 1 } 17 | option_1 = { 'name' : ('-s', '--scan'), 'help' : 'Scan the PLC for information', 'nargs' : 0 } 18 | option_2 = { 'name' : ('-r', '--read'), 'help' : 'Read some data from the PLC {inputs | outputs}', 'nargs' : 1 } 19 | option_3 = { 'name' : ('-w', '--write'), 'help' : 'Write data to the PLC', 'nargs' : 2 } 20 | 21 | options = [option_1, option_2, option_3, option_0] 22 | 23 | class Siemens(object): 24 | 25 | def __init__(self, host): 26 | self.client = snap7.client.Client() 27 | self.client.connect(host, 0, 1) 28 | 29 | def read_all_inputs(self): 30 | i = 1 31 | inputs = list() 32 | while True: 33 | try: 34 | r = self.client.read_area(snap7.types.areas['PE'], 0, i, 1) 35 | i = i + 1 36 | inputs.append(r[0]) 37 | print 'Value at #' + str(i) + str(r[0]) 38 | except ZeroDivisionError: 39 | print 'YOLO' 40 | except: 41 | print 'Unexpected error when reading input #' + str(i) 42 | return inputs 43 | 44 | def read_input(self, i): 45 | r = self.client.read_area(snap7.types.areas['PE'], 0, i, 1) 46 | return r[0] == 1 47 | 48 | def read_output(self, i): 49 | r = self.client.read_area(snap7.types.areas['PA'], 0, i, 1) 50 | return r[0] == 1 51 | 52 | def write_output(self, area, data): 53 | data = bytearray([0x01]) 54 | r = self.client.write_area(snap7.types.areas['PA'], 0, 0, data) 55 | return r 56 | 57 | def close(self): 58 | self.client.disconnect() 59 | 60 | def main(options, arguments): 61 | global VERSION 62 | 63 | print 'scan7.py version %s\n' % VERSION 64 | 65 | # Parse options 66 | if (options.target == None): 67 | parser.error('Please specify a target') 68 | 69 | if (options.read == None and options.write == None and options.scan == None): 70 | parser.error('Please specify an action : read, write or scan') 71 | 72 | if ((options.read and options.write) or (options.read and options.scan) or (options.write and options.scan)): 73 | parser.error('Please choose one action only ! Make up your mind !') 74 | 75 | # Actually do something usefull here 76 | s7 = Siemens(options.target) 77 | datas = snap7.types.areas 78 | for i in datas: 79 | print str(i) + ' :: ' + str(datas[i]) 80 | for i in range(0,100): 81 | print str(i) + '::' + str(s7.client.read_area(snap7.types.areas['PA'], 0, i, 1)) 82 | 83 | 84 | if (options.read): 85 | if (options.read == 'inputs'): 86 | inputs = s7.read_all_inputs() 87 | for i in range(0, len(inputs)): 88 | print 'Input #' + str(i) + ' : ' + str(inputs(i)) 89 | elif (options.read == 'output'): 90 | outputs = s7.read_all_outputs() 91 | for i in range(0, len(outputs)): 92 | print 'Output #' + str(i) + ' : ' + str(outputs(i)) 93 | else: 94 | parser.error('Valid data to be read : "inputs" or "outputs"') 95 | 96 | s7.close() 97 | 98 | return None 99 | 100 | if __name__ == "__main__" : 101 | parser = OptionParser() 102 | for option in options: 103 | param = option['name'] 104 | del option['name'] 105 | parser.add_option(*param, **option) 106 | 107 | options, arguments = parser.parse_args() 108 | main(options, arguments) --------------------------------------------------------------------------------