2

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?

Community
  • 1
  • 1
PolskiPhysics
  • 255
  • 2
  • 8
  • sounds like you are still a little confused on how to use arguments. see the docs here: http://docs.python.org/2/tutorial/controlflow.html#more-on-defining-functions – Corley Brigman Mar 13 '14 at 19:48

1 Answers1

1

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.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • Change the `while` to `for` and drop the `n += 1` – pat Mar 13 '14 at 19:52
  • Also, this is an inefficient CRC implementation. You can avoid the inner loop by precalculating a table of 256 entries. – pat Mar 13 '14 at 19:53
  • @pat -- I'm sure it is... You're right about the changes that should be made to OP's code. I'm going to leave it as it is to make it immediately recognizable from above, but hopefully OP will note your comments and make the appropriate changes. I don't know what CRC is, so I'll take both of your word that this implementation works (at very least). – mgilson Mar 13 '14 at 19:55
  • @mgilson -- Thanks, this seems to accomplish what I was looking to do. The link you provided looks like it could be quite useful once I've got some more experience. – PolskiPhysics Mar 13 '14 at 20:04
  • @pat -- Good to know, but I'm not concerned about efficiency for now, just something where I can understand how it works. I didn't even know what modbus was or how to calculate a CRC until a few days ago. Is there any entry-level reading on CRCs that you'd recommend? – PolskiPhysics Mar 13 '14 at 20:12
  • Wikipedia has some accessible articles on CRC, the mathematics behind it, and various implementation strategies. See [here](http://en.wikipedia.org/wiki/Cyclic_redundancy_check), [here](http://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks), and [here](http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks) – pat Mar 13 '14 at 20:16