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.
Brak komentarzy:
Prześlij komentarz