eclipse-kura / kura

Eclipse Kura™ is a versatile framework to supercharge your edge devices, streamlining the process of configuring your gateway, connecting sensors, and IoT devices to seamlessly collect, process, and send data to the cloud.
https://eclipse.dev/kura/
Eclipse Public License 2.0
500 stars 309 forks source link

[Sense HAT driver] Unable to read to I2C device #2098

Closed iyanmv closed 5 years ago

iyanmv commented 6 years ago

I am trying to use the Sense HAT driver to read data from the environmental sensors and send it to a Kapua instance. I installed the driver mentioned in the form but when I try to add a new driver I get some errors (see kura.log) saying that it is not possible to read or write to the I2C device. I have already enabled the I2C kernel module using the raspi-config tool and I confirm that the Sense HAT works because I am able to measure using the python library.

nicolatimeus commented 6 years ago

The log reports Locked by other application.

Do you have other applications trying to use the i2c bus (for example the SenseHAT driver and SenseHAT example running at the same time)?

Can you please try to start from a fresh Kura 3.2.0 install and then installing and using only the SenseHAT driver? Try also not to use the pyhton library to avoid interference.

iyanmv commented 6 years ago

I will try to uninstall the python library and the packages I installed in the Raspbian and try again. That is the first thing I thought, but I don't see how having theses packages installed in the system can lock the i2c bus.

Also, I am not sure to understand the first thing you mentioned. What do you mean with SenseHAT driver and SenseHAT example running at the same time?

nicolatimeus commented 6 years ago

I was referring to the Sensehat Example Bundle for Eclipse Kura available from Eclipse Marketplace [1]. Yes, please try to start from a clean setup first, If the problem persists we can investigate further.

[1] https://marketplace.eclipse.org/content/sensehat-example-bundle-eclipse-kura

iyanmv commented 6 years ago

Ok, I tried the bundle before the driver but I uninstalled it before trying to install the driver. Anyway, I will try tomorrow from a clean setup frist and I will comment here if it works.

iyanmv commented 6 years ago

Same issue and same execptions in the log from a clean setup.

nicolatimeus commented 6 years ago

Ok, I will try to replicate the issue.

iyanmv commented 6 years ago

More details. I hope they are useful. First time I try to create a new driver after installing the sensehat package I get the following error:

kura.log

``` 2018-05-10 07:32:02,509 [Component Resolve Thread (Bundle 7)] INFO o.e.k.e.d.s.SenseHatDriver - Activating SenseHat Driver... 2018-05-10 07:32:02,510 [Component Resolve Thread (Bundle 7)] INFO o.e.k.e.d.s.SenseHatDriver - Opening Sense Hat... 2018-05-10 07:32:02,578 [Component Resolve Thread (Bundle 7)] ERROR o.e.k.r.s.s.LSM9DS1 - Could not create I2C Device java.io.IOException: java.io.IOException at org.eclipse.kura.raspberrypi.sensehat.sensors.KuraI2CDevice.(KuraI2CDevice.java:31) at org.eclipse.kura.raspberrypi.sensehat.sensors.LSM9DS1.getIMUSensor(LSM9DS1.java:190) at org.eclipse.kura.raspberrypi.sensehat.impl.SenseHatImpl.getIMUSensor(SenseHatImpl.java:68) at org.eclipse.kura.example.driver.sensehat.SenseHatInterface.(SenseHatInterface.java:59) at org.eclipse.kura.example.driver.sensehat.SenseHatDriver.getSensehatInterface(SenseHatDriver.java:68) at org.eclipse.kura.example.driver.sensehat.SenseHatDriver.activate(SenseHatDriver.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.eclipse.equinox.internal.ds.model.ServiceComponent.activate(ServiceComponent.java:235) at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.activate(ServiceComponentProp.java:146) at org.eclipse.equinox.internal.ds.model.ServiceComponentProp.build(ServiceComponentProp.java:345) at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponent(InstanceProcess.java:620) at org.eclipse.equinox.internal.ds.ServiceReg.getService(ServiceReg.java:53) at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse$1.run(ServiceFactoryUse.java:212) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.factoryGetService(ServiceFactoryUse.java:210) at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.getService(ServiceFactoryUse.java:111) at org.eclipse.osgi.internal.serviceregistry.ServiceConsumer$2.getService(ServiceConsumer.java:45) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:496) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getService(ServiceRegistry.java:461) at org.eclipse.osgi.internal.framework.BundleContextImpl.getService(BundleContextImpl.java:619) at org.osgi.util.tracker.ServiceTracker.addingService(ServiceTracker.java:414) at org.eclipse.kura.core.configuration.ConfigurationServiceImpl$3.addingService(ConfigurationServiceImpl.java:276) at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:941) at org.osgi.util.tracker.ServiceTracker$Tracked.customizerAdding(ServiceTracker.java:1) at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256) at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229) at org.osgi.util.tracker.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:901) at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:109) at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:915) at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:862) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:801) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:127) at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:225) at org.eclipse.osgi.internal.framework.BundleContextImpl.registerService(BundleContextImpl.java:464) at org.eclipse.equinox.internal.ds.InstanceProcess.registerService(InstanceProcess.java:536) at org.eclipse.equinox.internal.ds.InstanceProcess.buildComponents(InstanceProcess.java:260) at org.eclipse.equinox.internal.ds.Resolver.buildNewlySatisfied(Resolver.java:473) at org.eclipse.equinox.internal.ds.Resolver.enableComponents(Resolver.java:217) at org.eclipse.equinox.internal.ds.SCRManager.processConfigurationEvent(SCRManager.java:403) at org.eclipse.equinox.internal.ds.SCRManager.processConfigurationEvent(SCRManager.java:303) at org.eclipse.equinox.internal.ds.WorkThread.run(WorkThread.java:91) at org.eclipse.equinox.internal.util.impl.tpt.threadpool.Executor.run(Executor.java:70) Caused by: java.io.IOException at com.oracle.dio.i2cbus.impl.I2CSlaveImpl.open0(Native Method) at com.oracle.dio.i2cbus.impl.I2CSlaveImpl.(I2CSlaveImpl.java:70) at com.oracle.dio.i2cbus.impl.I2CDeviceFactory.create(I2CDeviceFactory.java:43) at com.oracle.dio.i2cbus.impl.I2CDeviceFactory.create(I2CDeviceFactory.java:38) at jdk.dio.DeviceManager.openWithConfig(DeviceManager.java:290) at jdk.dio.DeviceManager.open(DeviceManager.java:273) at jdk.dio.DeviceManager.open(DeviceManager.java:209) at org.eclipse.kura.raspberrypi.sensehat.sensors.KuraI2CDevice.(KuraI2CDevice.java:29) ... 46 more ```

Then I tried some things.

  1. I enable I2C interface using raspi-config tool -> Same exception as shown in the first comment.
  2. I left dtparam=i2c_arm=on while commenting i2c-dev in /etc/modules -> Same exception
  3. I commented i2c-dev from /etc/modules while keeping the line dtparam=i2c_arm=on in /boot/config -> java.io.IOException: java.io.IOException

So it looks like in a clean install, the raspberry pi 3 does not enable the I2C interface (this agrees with rasp documentation) and I get an IOException but if I load the kernel module, Kura sees the interface locked. Let me know if you can replicate the issue.

Thanks!

nicolatimeus commented 6 years ago

Replicated by installing the openjdk-8-jre-headless package which provides the JVM version you reported. In my setup the driver works if the oracle-java8-jdk package is installed, which provides the following java version:

java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) Client VM (build 25.65-b01, mixed mode)

There might some issue regarding using the jdk.dio library either with openjdk itself or with some JVM version more recent than 1.8.0_65.

Moreover, I've found this by digging into the jdk.dio source in Kura repo:

The com.oracle.dio.impl.Handle.tryLock(int) method, which is called in the code path that leads to the reported exception has the following signature [1]:

public native boolean tryLock(int timeout);

And this is its native implementation [2]:

/*
 * Tries locking the device.
 * Class:     com_oracle_dio_impl_Handle
 * Method:    tryLock
 */
JNIEXPORT void JNICALL Java_com_oracle_dio_impl_Handle_tryLock
  (JNIEnv* env, jobject obj, jint timeout) {
    device_reference device = getDeviceReferenceFromHandleObject(env, obj);
    if (device != INVALID_DEVICE_REFERENCE) {
        //  add an implementation
    }
}

The native function returns void instead of a jboolean, and its implementation looks incomplete. This is quite suspicious.

[1] https://github.com/eclipse/kura/blob/develop/target-platform/jdk.dio-parent/src/dev/src/se/classes/com/oracle/dio/impl/Handle.java#L41 [2] https://github.com/eclipse/kura/blob/develop/target-platform/jdk.dio-parent/src/dev/src/se/native/com/oracle/dio/dio_common.cpp#L458

iyanmv commented 6 years ago

Ok, great! It works with Oracle's JVM. Thank you very much.

MMaiero commented 6 years ago

@nicolatimeus Let's document this in the official documentation.

cdealti commented 6 years ago

Add the necessary documentation