następnie wykorzystałem kod w języku python z: http://www.uugear.com/portfolio/dht11-humidity-temperature-sensor-module/
Wszystko działało ok jednak postanowiłem napisać kod w Javie. Zwykła konwersja kodu z Pythona na Jave nie przyniosła żadnego pożądanego skutku. Thread.sleep czy inne znalezione w internecie metody nie dają wymaganej precyzji.
Poniżej opisuję jak wywołać kod z języka C w Javie. W tym celu wykorzystam JNI tj Java Native Interface. Biblioteka obecnie ma wyświetlać hello world, ale docelowo zostanie rozbudowana i posłuży do pobrania temperatury z czujnika DHT11.
W pierwszej kolejności musimy przygotować klasę w javie. Muszą być w niej zawarte metody, które później napiszemy w C. Klasę nazwałem tak, jak będzie się nazywać moja biblioteka. Poniżej przykład:
Wgrywamy na Raspberry, przechodzimy do folderu gdzie wgralismy plik java i kompilujemy:
Następnie za pomocą Javy generujemy plik nagłówkowy języka C.
W wyniku powyższej operacji utworzy się plik DHT11.h. W moim przypadku wygląda on tak:
Utworzony plik *.h zalecam skopiować do: /usr/local/include/. Nie jest to konieczne, ale dzięki temu nie trzeba będzie zmieniać ścieżek podczas kompilowania.
Kolejna rzecz którą musimy ustawić to zmienna środowiskowa JAVA_HOME. Najpierw należy sprawdzić czy jest ustawiona aby to zrobić należy wywołać:
Następnie programujemy klasę w C. Musi się ona nazywać jak nasza biblioteka i kalsa Javy. Otwieramy wygenerowany plik nagłówkowy DHT11.h i kopiujemy metody:
Poniżej opisuję jak wywołać kod z języka C w Javie. W tym celu wykorzystam JNI tj Java Native Interface. Biblioteka obecnie ma wyświetlać hello world, ale docelowo zostanie rozbudowana i posłuży do pobrania temperatury z czujnika DHT11.
W pierwszej kolejności musimy przygotować klasę w javie. Muszą być w niej zawarte metody, które później napiszemy w C. Klasę nazwałem tak, jak będzie się nazywać moja biblioteka. Poniżej przykład:
public class DHT11 { static { System.loadLibrary("DHT11"); // Load native library at runtime DHT11.dll (Windows) or libDHT11.so (Unixes) } public native void runTest(); }
Wgrywamy na Raspberry, przechodzimy do folderu gdzie wgralismy plik java i kompilujemy:
javac DHT11.java
Następnie za pomocą Javy generujemy plik nagłówkowy języka C.
javah DHT11
W wyniku powyższej operacji utworzy się plik DHT11.h. W moim przypadku wygląda on tak:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class DHT11 */ #ifndef _Included_DHT11 #define _Included_DHT11 #ifdef __cplusplus extern "C" { #endif /* * Class: DHT11 * Method: runTest * Signature: ()V */ JNIEXPORT void JNICALL Java_DHT11_runTest (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
Utworzony plik *.h zalecam skopiować do: /usr/local/include/. Nie jest to konieczne, ale dzięki temu nie trzeba będzie zmieniać ścieżek podczas kompilowania.
Kolejna rzecz którą musimy ustawić to zmienna środowiskowa JAVA_HOME. Najpierw należy sprawdzić czy jest ustawiona aby to zrobić należy wywołać:
echo $JAVA_HOMEJeśli zostanie zwrócony pusty wynik to trzeba ustawić tą zmienną przez polecenie:
export JAVA_HOME="scieżkaDoJavy"
Następnie programujemy klasę w C. Musi się ona nazywać jak nasza biblioteka i kalsa Javy. Otwieramy wygenerowany plik nagłówkowy DHT11.h i kopiujemy metody:
JNIEXPORT void JNICALL Java_DHT11_runTest (JNIEnv *, jobject)Następnie do skopiowanych metod dodajemy nazwy obiektów, nawiasy klamrowe i uzupełniamy co ma robić metoda, w tym wypadku wyświetlić na ekranie napis "hello world". Includujemy również potrzebne biblioteki:
#include <jni.h> #include <stdio.h> #include "DHT11.h" JNIEXPORT void JNICALL Java_DHT11_runTest(JNIEnv *env, jobject thisObj) { printf("Hello World\n"); return; }
Gdy kod w C jest już gotowy to musimy go skompilować
gcc -fPIC -c DHT11.c -I $JAVA_HOME/include
Jeśli będzie błąd fatal error: jni_md.h: No such file or directory to należy dodać powiązania symboliczne. Szczegóły tutaj: http://stackoverflow.com/questions/24996017/jdk-1-8-on-linux-missing-include-file a w moim przypadku wyglądało to tak:
sudo ln -s /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/include/linux/jni_md.h /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt//include/jni_md.h sudo ln -s /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt/include/linux/jawt_md.h /usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt//include/jawt_md.h
gcc DHT11.o -shared -o libDHT11.so -Wl,-soname,DHT11
Jeśli wszystko zostało wykonane prawidłowo to utworzy się plik libDHT11.so. Zostało napisanie klasy w javie która odwoła się do utworzonej biblioteki. Przykładowy kod javy:
public class DHT11 { static { System.loadLibrary("DHT11"); // Load native library at runtime // DHT11.dll (Windows) or libDHT11.so (Unixes) } public native void runTest(); public static void main(String[] args) throws InterruptedException { new DHT11().runTest(); Thread.sleep(4000); System.out.println("Wychodze"); } }
Zapisujemy i wgrywamy na Raspberry Pi. Do folderu z powyższą klasą wgrywamy bibliotekę libDHT11.so. Kompilujemy i uruchamiamy:
javac DHT11.java java DHT11
niestety wyskoczy błąd:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no DHT11in java.library.path
Błąd wynika z tego, że domyślnie java nie wie gdzie jest plik libDHT11.so. Ponieważ skopiowaliśmy go do folderu gdzie jest skompilowana klasa to możemy dodać parametr do maszyny wirtualnej javy -Djava.library.path i wskazać bieżący folder:
java -Djava.library.path=. DHT11
Tym razem już powinno być ok i program wyświetli na ekranie hello world.