def _device_is_water_pump(self): try: device_type = None try: with Packer() as packer: # packer.debug = True # first write => the register address we want read/write packer.write(self.I2C_REGISTERS["TYPE"]) packer.end() self._smbus.write_bytes(self._address, bytearray(packer.read())) except Exception as e: print("ERROR: on packer, {}".format(e)) try: sleep(self._short_timeout) raw = self._smbus.read_bytes( self._address, 5) # read 5 bytes from slave due to data format if self._debug: print("Raw data from i2c: ", raw) except Exception as e: print("ERROR: on smbus, {}".format(e)) try: with Unpacker() as unpacker: # unpacker.debug = True unpacker.write(raw) device_type = unpacker.read()[ 0] # type data is the first field of list except Exception as e: print("ERROR: on unpack, {}".format(e)) return device_type == self.I2C_DEVICES_TYPE except Exception as e: print("ERROR: on device type check {}".format(e))
def test_packer(self): packer = Packer() packer.write(127) packer.end() packed = [i for i in packer.read() if i != 0] expected = [2, 5, 127, 185, 4] self.assertIsNotNone(packed) self.assertTrue(type(packed).__name__ == "list") self.assertEqual(expected, packed)
def read(self, register: int, num_of_bytes: int = 5): """ @brief read data from i2c bus @param register > int i2c register to read @param num_of_byte > int number of bytes to read started from the register by default num_of_bytes = 5 because the data format from ESP32 i2c slave is 5 length more information on Packer() and Unpacker() classes @return list """ # if not self._device_is_water_pump(): # raise Exception("Current device type is not a water pump") # else: try: unpacked = None try: with Packer() as packer: packer.write(register) packer.end() packed = packer.read() if self._debug: print("packed: ", packed) self._smbus.write_bytes(self._address, bytearray(packed)) except Exception as e: print("ERROR: on packer, {}".format(e)) try: sleep(self._short_timeout) # let the bus process first write raw = self._smbus.read_bytes(self._address, num_of_bytes) if self._debug: print("Raw data from i2c: ", raw) except Exception as e: print("ERROR: on smbus, {}".format(e)) try: with Unpacker() as unpacker: unpacker.write(list(raw)) unpacked = unpacker.read() except Exception as e: print("ERROR: on unpacker, {}".format(e)) if self._debug: print("Read: %s registers start from: %s" % (num_of_bytes, hex(register))) print("Get values: ", unpacked) return unpacked except Exception as e: print("ERROR: on read, {}".format(e))
def write(self, register: int, value=None): """ @brief write data through i2c bus @param register > int/byte i2c register to read @param value > int/list to be write through i2c """ # if not self._device_is_water_pump(): # raise Exception("Current device type is not a water pump") # else: try: with Packer() as packer: # first write => the register address we want read/write packer.write(register) # if value == None we just write register we want read into the i2c bus and then read the value if None is not value: if int is not type(value) and list is type(value): for elm in value: packer.write(elm) elif int is type(value): packer.write(value) else: raise Exception("cannot format this kind of data: ", value) packer.end() # finish data formatting packed = packer.read() except Exception as e: print("ERROR: {0}, cannot use packer yo prepare data".format(e)) try: self._smbus.write_bytes(self._address, bytearray(packed)) except Exception as e: print( "ERROR: {0}, when write data on i2c: ".format(e), packed, ) if self._debug: print("Write %s on register: %s" % (value, hex(register)))