Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import Failure. Invalid driver class name. Unable to locate QwiicAs6212/QwiicKx13X #25

Open
Aser-Abdelfatah opened this issue Jul 8, 2024 · 2 comments

Comments

@Aser-Abdelfatah
Copy link

Aser-Abdelfatah commented Jul 8, 2024

Hi,
I'm using Nvidia Jetbot with JetPack 4.6. I'm using the standard Spark Fun setup and double checked that the wiring are right according to SparkFun assembly guide here
I installed this package using pip3 as well as Qwiic_I2C and all the drivers.
When I try to run
import qwiic
I get the errors
Invalid driver class name. Unable to locate QwiicAs6212
Invalid driver class name. Unable to locate QwiicKx13X
The packages for both QwiicAs6212 and QwiicKx13X are installed. Also, the jetbot is not wired to either of the two modules as well. I don't get why I'm receiving the error.
Furthermore, qwiic.scan() continues to run forever. So, I'm not able to use the Robot class of jetbot, which depends on qwicc.

Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/qwiic_i2c/linux_i2c.py", line 261, in isDeviceConnected
self._i2cbus.write_quick(devAddress)
File "/home/aser/.local/lib/python3.6/site-packages/smbus2/smbus2.py", line 379, in write_quick
ioctl(self.fd, I2C_SMBUS, msg)
TimeoutError: [Errno 110] Connection timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "", line 1, in
File "/home/aser/.local/lib/python3.6/site-packages/qwiic/init.py", line 239, in scan
return i2c_driver.scan()
File "/usr/local/lib/python3.6/dist-packages/qwiic_i2c/linux_i2c.py", line 284, in scan
if self.ping(currAddress) == True:
File "/usr/local/lib/python3.6/dist-packages/qwiic_i2c/linux_i2c.py", line 272, in ping
return self.isDeviceConnected(devAddress)
File "/usr/local/lib/python3.6/dist-packages/qwiic_i2c/linux_i2c.py", line 261, in isDeviceConnected
self._i2cbus.write_quick(devAddress)

@sfe-SparkFro
Copy link

Hi there, thanks for reporting this! I can replicate the problem on my end, will work on fixing this soon!

@sfe-SparkFro
Copy link

Ok, so the root problem is that those 2 packages don't match the format that Qwiic_Py expects in order to include them. Relevant code is here:

Qwiic_Py/qwiic/__init__.py

Lines 156 to 202 in 50964b6

def _load_driver_classes():
driver_dir = __file__.rsplit(os.sep, 1)[0] + os.sep + "drivers"
try:
driver_packages = os.listdir(driver_dir)
except IOError:
print("The qwiic drivers are not installed - please check your installation")
return
for driver in driver_packages:
# The driver objects are just the driver pacakge names in camelcase
tmp_parts = driver.split('_')
class_name = tmp_parts[0].title() + ''.join(x.title() for x in tmp_parts[1:])
try:
module = __import__(driver)
# by default we look for a class name of QwiicName, where name is camel cased
# Camel case is sometimes missed by the driver implementors, so we try to
# catch this here.. Adds a little to startup, but it's a one time event.
if not hasattr(module, class_name):
moduleItems = dir(module)
i =0
lname = class_name.lower()
for tmp in moduleItems:
if lname == tmp.lower():
break
i = i + 1
if i >= len(moduleItems):
print("Invalid driver class name. Unable to locate %s" % class_name)
continue
class_name = moduleItems[i]
cls_driver = getattr(module, class_name)
setattr(sys.modules[__name__], class_name, cls_driver)
_QwiicInternal.add_qwiic_device(cls_driver)
except Exception as err:
print("Error loading module `%s`: %s" % (driver, err))
continue

In short, it expects the device package names to be in the format of qwiic_device_name, and tries to find a class in the format of QwiicDeviceName. If so, that class is included. If it's not found, that error message gets printed instead.

The reason the qwiic_kx13x fails is because it has classes named QwiicKX13XCore, QwiicKX132, and QwiicKX134, but not QwiicKx13X like excepted. qwiic_as6212 similarly fails because it has a class named QwiicAs6212Sensor, but not QwiicAs6212 .

I'm not actually sure how best to address this. qwiic_as6212 could probably be fixed by adding an empty class called QwiicAs6212 that inherits QwiicAs6212Sensor, which should fix this problem and maintain backwards compatibility. However Qwiic_Py really needs to include QwiicKX132 and QwiicKX134 separately, but they're both part of the same package, and Qwiic_Py is really not setup to include multiple classes from the same package. Could maybe add a special case to detect if the driver is called qwiic_kx13x, then attempt to include both of those classes explicitly, but that's kinda hacky. Will have to mull this over.

So that's why those error messages appear, but it's odd that this wasn't a problem before. For some reason, previous versions of Qwiic_Py seemed to not include those 2 device drivers. If I run pip install sparkfun-qwiic==1.1.6 (working version as of 3 years ago) followed by ls /home/pi/.local/lib/python3.11/site-packages/qwiic/drivers/, I get the following:

pi@raspberrypi:~ $ pip install sparkfun-qwiic==1.1.6
...
Successfully installed sparkfun-qwiic-1.1.10
pi@raspberrypi:~ $ ls /home/pi/.local/lib/python3.11/site-packages/qwiic/drivers/
pi_servo_hat        qwiic_ccs811               qwiic_joystick    qwiic_pir        qwiic_serlcd     qwiic_vl53l1x
qwiic_adxl313       qwiic_dual_encoder_reader  qwiic_keypad      qwiic_proximity  qwiic_sgp40      top_phat_button
qwiic_alphanumeric  qwiic_eeprom               qwiic_max3010x    qwiic_relay      qwiic_tca9548a   ublox_gps
qwiic_bme280        qwiic_gpio                 qwiic_micro_oled  qwiic_rfid       qwiic_titan_gps
qwiic_button        qwiic_icm20948             qwiic_pca9685     qwiic_scmd       qwiic_twist

qwiic_kx13x and qwiic_as6212 are not included there for some reason, despite both of those existing in the repo at that time.

However if I run pip install sparkfun-qwiic==1.1.10 (latest version of this package, skipping broken versions), they are included:

pi@raspberrypi:~ $ pip install sparkfun-qwiic==1.1.10
...
Successfully installed sparkfun-qwiic-1.1.10
pi@raspberrypi:~ $ ls /home/pi/.local/lib/python3.11/site-packages/qwiic/drivers/
pi_servo_hat               qwiic_eeprom      qwiic_max3010x      qwiic_relay                 qwiic_twist
qwiic_adxl313              qwiic_gpio        qwiic_micro_oled    qwiic_rfid                  qwiic_vl53l1x
qwiic_alphanumeric         qwiic_icm20948    qwiic_oled_base     qwiic_scmd                  top_phat_button
qwiic_as6212               qwiic_joystick    qwiic_oled_display  qwiic_serlcd                ublox_gps
qwiic_bme280               qwiic_keypad      qwiic_otos          qwiic_sgp40
qwiic_button               qwiic_kx13x       qwiic_pca9685       qwiic_soil_moisture_sensor
qwiic_ccs811               qwiic_large_oled  qwiic_pir           qwiic_tca9548a
qwiic_dual_encoder_reader  qwiic_led_stick   qwiic_proximity     qwiic_titan_gps

Not sure why that is, but they're at least being included now, so I'm not going to dive into that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants