socket.sendto / UDP problem

Todd Walter twalter at rogers.com
Fri Oct 22 13:41:38 EDT 2010


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Thank you all for your help, I now have a functioning interface.  As it
turns out, trying to do things the "correct" way was wrong.  The timing
was so tight that doing anything (such as traversing the while-loop
once) instead of a read immediately after transmission meant we missed
the PLC's response. And, for whatever reason, I had to wrap the
outgoing text in bytes() (this is still a mystery, but obviously it
thinks strings going to the socket module are unicode.)  The shorter, numeric,
messages were able to complete sufficiently quickly that catching the response
worked within a while loop but not the larger, 66-byte, message.

Again, thanks all for your assistance.  

Cheers,

Todd

- ---- The functional code ---

def PLC_Functions(command, argument):
    """ 
        Command is one of:  GetTray, Status, SetText
        Argument is one of: tray number (as string), None, message (as string)
        
    The PC (arbitrarily) transmits / receives on socket 2260 (pcSocket)
    The PLC receives on socket 2002 and responds to whatever port it sees in the header
    The protocol used is UDP
    """
    pcSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    # bind it
    pcSocket.bind((config.get('megamat','pcip'),int(config.get('megamat','sourceport'))))
    # make them blocking (i/o is 'fire-and-forget' to a PLC that may or may not respond in a given time.)
    # non-blocking fails and raises windows exceptions for some reason (20-Oct-2010)
    pcSocket.settimeout(1.0) # 1ms?  PLC will respond in ~0.10ms
    
    if command == 'CallTray':
        # frame 1 (see docs for frame sequence)
        print 'Received call tray command for tray %s' %(argument)
        getReadyMsg = '0145\r'
        totalsent = 0
        while totalsent < len(getReadyMsg):
            sent = pcSocket.sendto(bytes(getReadyMsg[totalsent:]),MegaMatPLC)
            response, address = pcSocket.recvfrom(17)
            if sent == 0:
                raise RunTimeError('Transmission failure.  Please confirm MegaMat settings in megapy.ini')
            totalsent = totalsent + sent
        # Frame 2
        '''
        response = ''
        while '\r' not in response:
            response, address = pcSocket.recvfrom(17)
            if response == '':
                raise RunTimeError('PLC did not respond') 
            #this should be changed.  The MIF software will wait until it receives a response or timeout, not ABEND
        '''
        print response, address
            
        if response[0:4] == '0135':
            print 'Drive ready received.'
            # Frame 5
            # Transmit tray request 
            if int(argument) < 10:
                shelfPrefix = '0000'
            else:
                shelfPrefix = '000'
                
            shelf = shelfPrefix + argument
            unit = '001'
            stack = '01'
            """
            There is a 10 digit number plus 40 blanks spaces after the shelf description built above.
            It is possible this is for storing shelf descriptions and barcodes on the PLC.  We will
            follow the example of the MIF software and put a phony b/c and blank description.
            X is a field terminator and \r is the end of transmission (EoT.) 
            """
            fakeBarcode = '1234567890'
            fortySpacesField = '    ' + 'Todd Was Here' + '                       ' + 'X\r'
            #fortySpacesField = ' '*40 + 'X\r'
            getShelfMsg = '0105' + shelf + unit + stack + fakeBarcode + fortySpacesField
            print 'Transmitting shelf request as follows: \n' + getShelfMsg

            sent = pcSocket.sendto(bytes(getShelfMsg),MegaMatPLC)
            response, address = pcSocket.recvfrom(132)
            print sent
            print response, address
            
            #Frame 6
            '''
            response = ''
            while '\r' not in response:
                response, address = pcSocket.recvfrom(16)
                if response == '':
                    raise RunTimeError('PLC did not respond') 
                    #this should be changed.  The MIF software will wait until it receives a response or timeout, not ABEND
            '''
            print response, address
                        
            pcSocket.close()
            
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.16 (GNU/Linux)

iEYEARECAAYFAkzBzN0ACgkQwnknPuQqPINgfQCeN4hm8jDCnwU2niC0dOHkJO8F
+MAAn1/kECizBDEY4doQj1+3+Si9Zyjg
=SvAW
-----END PGP SIGNATURE-----


More information about the Python-list mailing list