One of the projects that have been on my to-do list since years involves controlling a number of Inter-Integrated Circuit (\$I^2C\$) peripherals. Lately I've been turning everything into it's own library and I'm wondering if I'm doing it right.
While the libraries are usually called by a server-like script, they all have a demo function as well.
My goal is to write a production-quality library for multiple controllers. To make sure I didn't make any silly mistakes, I put one up for review.
The following library will control a LED-shield connected by I2C to a Raspberry Pi (B+). Registers 2 till 8 are responsible for the lighting and take values from 0 to 255. Overflows (values above 255) are not a problem, since only the last 8 bits will be saved in the hardware. However, this is potentially wasteful on the bus.
There's one method of setting the white LED and two methods of setting the red, green and blue LED. The latter can be set by using RGB or hue, saturation, brightness (HSB) values.
The library makes use of the System Management Bus (SMBus), which is a simplified version of \$I^2C\$. Since nothing time-critical is going on, this does suffice.
A library should have docstrings just about everywhere for introspection and plenty of other reasons (see PEP 257). Those get tedious quickly, and can probably be improved. The docstrings are explicitly up for review.
import smbus class LED: """ I2C LED controller. Set registers 2 till 8. Registers 2 till 5 are directly responsible for the power of one LED each: White, red, green and blue. Those registers will be named by their number. Registers 6 till 8 (HSB) are an alternative method of setting red, green and blue. RGB and HSB will override each other. """ def __init__(self, bus=1, address=0x71): """ Set bus and address. """ self.bus = smbus.SMBus(bus) self.address = address def writeWhiteRegister(self, value=0): """ Set white register. """ self.bus.write_byte_data(self.address, 2, value) def writeRedRegister(self, value=0): """ Set red register. """ self.bus.write_byte_data(self.address, 3, value) def writeGreenRegister(self, value=0): """ Set green register. """ self.bus.write_byte_data(self.address, 4, value) def writeBlueRegister(self, value=0): """ Set blue register. """ self.bus.write_byte_data(self.address, 5, value) def writeRgbwRegisters(self, red=0, green=0, blue=0, white=0): """ Set red, green, blue and white registers. Default for all is 0. """ self.writeRedRegister(red) self.writeGreenRegister(green) self.writeBlueRegister(blue) self.writeWhiteRegister(white) def writeHueRegister(self, value=0): """ Set hue. """ self.bus.write_byte_data(self.address, 6, value) def writeSaturationRegister(self, value=0): """ Set saturation. """ self.bus.write_byte_data(self.address, 7, value) def writeBrightnessRegister(self, value=0): """ Set brightness. """ self.bus.write_byte_data(self.address, 8, value) def writeHsbRegisters(self, hue=0, saturation=0, brightness=0): """ Set hue, saturation and brightness. Warning: Setting any of saturation or brightness on 0 will result in LEDs off. """ self.writeHueRegister(hue) self.writeSaturationRegister(saturation) self.writeBrightnessRegister(brightness)
import Led from argparse import ArgumentParser def main(): parser = ArgumentParser(description='LED Demo') group = parser.add_mutually_exclusive_group(required=True) group.add_argument( '--rgbw', type=int, nargs=4 ) group.add_argument( '--hsb', type=int, nargs=3 ) args = parser.parse_args() led = Led.LED() if args.rgbw: led.writeRgbwRegisters(*args.rgbw) else: led.writeHsbRegisters(*args.hsb) if __name__ == '__main__': main()
python ledDemo.py --rgbw 90 100 110 120 python ledDemo.py --hsb 120 130 140
I'm not certain whether adding shebangs is a standardized practice in libraries and their example usage. I suspect it's not for the former but is for the latter. Any input on this during a review would be great.