Question

My lab is receiving some new equipment soon, and I'm writing my own modbus script to automate test processes. Thus far, this is the most complex task I've had to pit my limited programming proficiency against.

Instead of writing a new class from scratch to manage commands, I'd like to make a class EZTcomm that inherits its functionality from bytearray and add a EZTcomm.crc property to store the Cyclical Redundancy Checksum.

After reading this question and docs.python.org, I'm still really confused about how to do this. It seems that if I want to modify the __init__() method at all in my new class then I need to explicitly call bytearray.__init__() first, but I can't figure out how to pass the arguments in the EZTcomm call to bytearray.__init__(), nor do I know how to use the arguments in the bytearray.__init__() call as variables to calculate the CRC.

This is what I have written thus far:

class EZTcomm(bytearray):

    def __init__(self, *args, **kwargs):
        bytearray.__init__(self, *args, **kwargs)
        self.check = crc(args)

    def CRC(bytearray_in):
        '''Calculates a Cyclical Redundancy Checksum (CRC16).'''
        crc = 0xFFFF
        for work_byte in bytearray_in:
            crc ^= work_byte
            n = 0
            while n in range(8):
                if (crc & 0x0001):
                    crc >>= 1
                    crc ^= 0xA001
                else:
                    crc >>= 1
                n += 1
        return crc

############

test = EZTcomm([0x01,0x03,0x00,0x23,0x00,0x02])
print(test)
print(test.check)

Is this anywhere close to working the way I want it to? What should I be doing differently?

Was it helpful?

Solution

You're close. You want CRC to be a regular function1:

def CRC(bytearray_in):
    '''Calculates a Cyclical Redundancy Checksum (CRC16).'''
    crc = 0xFFFF
    for work_byte in bytearray_in:
        crc ^= work_byte
        n = 0
        while n in range(8):
            if (crc & 0x0001):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
            n += 1
    return crc

which you call from your subclass's init:

class EZTcomm(bytearray):

    def __init__(self, *args, **kwargs):
        bytearray.__init__(self, *args, **kwargs)
        self.check = CRC(self)

inside __init__, self is the instance of your subclass that you're creating. It's a bytearray, so it should work with CRC assuming CRC works at all. Of course, you can get more complicated here and use super to do the calling of the base class's __init__ method:

class EZTcomm(bytearray):

    def __init__(self, *args, **kwargs):
        super(EZTcomm, self).__init__(*args, **kwargs)
        # super().__init__(*args, **kwargs)  # python3.x only.
        self.check = CRC(self)

super has the advantage that it makes things work nicely with multiple inheritance, but in general, I advise people to really know what they're doing before they start messing with it. There are a number of best practices that you should follow to get the most out of it. See: http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ for some details.

1Your while loop would be better as a for loop: for n in range(8):....
If you do that, you drop the n = 0 and n += 1 lines.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top