Meteo Recipe

Да се разработи Linux/OSGi базирана разпределена сензорна система за събиране на метеорологични данни, състояща се от сензорна, сервизна и приложна части. Съставните части на системата да са гъвкаво конфигурируеми и с възможност да работят върху различни платформи. Функционалността, свързана с всеки отделен сензор да е йерархично разпределена и да може да се преконфигурира по време на работа на системата. Всеки отделен сензор или група, както и поддържаните от тях услуги да се регистрират в системата автоматично след инсталирането и пускането им в действие. Интерфейса към потребителя и персонала по поддръжката да е унифициран и достъпен чрез специализирано приложение или Интернет. Да се дефинират критерии за оценка на системата и съставните и части. Да се извърши анализ на възможни решения съобразно дефинираните критерии.

Meteo Recipe

Postby mladen » Wed Aug 17, 2011 6:01 pm

This recipe demonstrates bulding of Java Application with GPIO and ADC support. Accessing of GPIO and ADC is made through dynamic libraries written in C. In Java this interface is available through JNI bindings.

First let’s make base structure of recipe
Code: Select all
mkdir –p /angstrom/sources/local/recipes/meteo/files/bin
mkdir –p /angstrom/sources/local/recipes/meteo/files/lib
mkdir –p /angstrom/sources/local/recipes/meteo/files/meteo/channels
mkdir –p /angstrom/sources/local/recipes/meteo/files/meteo_test


Bin – directory for compiled JAVA files
Lib – sources of C library
Meteo – JAVA API sources
Meteo_test – JAVA Test API sources

Let’s add necessary files in lib directory

DigitalChannel.c - includes C implementation and JNI exports for export, direction, read and write GPIO channels. In addition there is function for software PWM. It can be used to test the system time quantum.
Code: Select all
#include "meteo_channels_DigitalChannel.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

#define TRUE  0x01
#define FALSE 0x00

int pwm_flag = FALSE;

char *uitos(unsigned int number) {
   unsigned int n = number;
   int size = 1;
   do {
      size++;
      n /= 10;
   } while(n >= 1);
   char *buffer = (char *) malloc(size);
   if(buffer == NULL) {
      printf("Cannot allocate memory.\n");
      exit(1);
   }
   memset(buffer, 0, size);
   sprintf(buffer, "%d", number);
   return buffer;
}

void exportGPIO(unsigned int number) {
   FILE *fp;
   int size, count;
   //Using sysfs we need to write "gpioNumber" to /sys/class/gpio/export
   //This will create the folder /sys/class/gpio/gpio"gpioNumber"
   if((fp = fopen("/sys/class/gpio/export", "wb")) == NULL) {
      printf("Cannot open export file.\n");
      exit(1);
   }
   char *gpioNumber = uitos(number);
   //Write our value of "gpioNumber" to the file
   size = strlen(gpioNumber);
   count = fwrite(gpioNumber, sizeof(char), size, fp);
   fclose(fp);
   if(size != count) {
      printf("Fwrite error.\n");
      exit(1);
   }
   //printf("...export file accessed, new pin %s now accessible\n", gpioNumber);
   free(gpioNumber);
}

void unexportGPIO(unsigned int number) {
   FILE *fp;
   int size, count;
   //Using sysfs we need to write "gpioNumber" to /sys/class/gpio/export
   //This will create the folder /sys/class/gpio/gpio"gpioNumber"
   if((fp = fopen("/sys/class/gpio/unexport", "wb")) == NULL) {
      printf("Cannot open unexport file.\n");
      exit(1);
   }
   char *gpioNumber = uitos(number);
   //Write our value of "gpioNumber" to the file
   size = strlen(gpioNumber);
   count = fwrite(gpioNumber, sizeof(char), size, fp);
   fclose(fp);
   if(size != count) {
      printf("Fwrite error.\n");
      exit(1);
   }
   //printf("...unexport file accessed, new pin %s now unaccessible\n", gpioNumber);
   free(gpioNumber);
}

void directionGPIO(unsigned int number, const char *gpioDirection) {
   FILE *fp;
   int size, count;
   char *gpioNumber = uitos(number);
   size = strlen("/sys/class/gpio/gpio") + strlen(gpioNumber) + strlen("/direction");
   char *path = (char *) malloc(size);
   count = sprintf(path, "%s%s%s", "/sys/class/gpio/gpio", gpioNumber, "/direction");
   if(count != size) {
      printf("Sprintf error.\n");
      exit(1);
   }
   //SET DIRECTION
   //Open the LED's sysfs file in binary for reading and writing, store file pointer in fp
   if((fp = fopen(path, "wb")) == NULL) {
      printf("Cannot open direction file.\n");
      exit(1);
   }
   //Write our value of "out" or "in" to the file
   size = strlen(gpioDirection);
   count = fwrite(gpioDirection, sizeof(char), size, fp);
   fclose(fp);
   if(size != count) {
      printf("Fwrite error.\n");
      exit(1);
   }
   //printf("...direction of pin %s set to %s\n", gpioNumber, gpioDirection);
   free(path);
   free(gpioNumber);
}

unsigned int readGPIO(unsigned int number) {
   FILE *fp;
   int size, count;
   unsigned int value;
   char *gpioNumber = uitos(number);
   size = strlen("/sys/class/gpio/gpio") + strlen(gpioNumber) + strlen("/value");
   char *path = (char *) malloc(size);
   count = sprintf(path, "%s%s%s", "/sys/class/gpio/gpio", gpioNumber, "/value");
   if(count != size) {
      printf("Sprintf error.\n");
      exit(1);
   }
   //GET VALUE
   //Open the LED's sysfs file in binary for reading, store file pointer in fp
   if((fp = fopen(path, "rb")) == NULL) {
      printf("Cannot open value file.\n");
      exit(1);
   }
   size = sizeof(char);
   char *gpioValue = (char *) malloc(size);
   count = fread(gpioValue, sizeof(char), size, fp);
   fclose(fp);
   if(size != count) {
      printf("Fread error.\n");
      exit(1);
   }
   value = atoi(gpioValue);
   //printf("...value of pin %s set to %d...\n", gpioNumber, value);
   free(path);
   free(gpioNumber);
   free(gpioValue);
   return value;
}

void writeGPIO(unsigned int number, unsigned int value) {
   FILE *fp;
   int size, count;
   char *gpioNumber = uitos(number);
   size = strlen("/sys/class/gpio/gpio") + strlen(gpioNumber) + strlen("/value");
   char *path = (char *) malloc(size);
   count = sprintf(path, "%s%s%s", "/sys/class/gpio/gpio", gpioNumber, "/value");
   if(count != size) {
      printf("Sprintf error.\n");
      exit(1);
   }
   //SET VALUE
   //Open the LED's sysfs file in binary for writing, store file pointer in fp
   if((fp = fopen(path, "wb")) == NULL) {
      printf("Cannot open value file.\n");
      exit(1);
   }
   char *gpioValue = uitos(value);
   size = strlen(gpioValue);
   //Write our value of "gpioNumber" to the file
   count = fwrite(gpioValue, sizeof(char), size, fp);
   fclose(fp);
   if(size != count) {
      printf("Fwrite error.\n");
      exit(1);
   }
   //printf("...value of pin %s set to %s...\n", gpioNumber, gpioValue);
   free(path);
   free(gpioNumber);
   free(gpioValue);
}

void nsleep(double seconds) {
   struct timespec req = {0}, rem = {0};
   time_t sec = (int) seconds;
   unsigned long nsec = seconds * 1000000000L - sec * 1000000000L;
   req.tv_sec = sec;
   req.tv_nsec = nsec;
   nanosleep(&req, &rem);
}

JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_export(JNIEnv *env, jobject obj, jint number, jstring direction) {
   /*Extracting information from the parameter */
   const char *gpioDirection = (*env)->GetStringUTFChars(env, direction, 0);

   exportGPIO(number);
   directionGPIO(number, gpioDirection);

   /*Releasing the Java String once you have got the C string is very important!!!*/
   (*env)->ReleaseStringUTFChars(env, direction, gpioDirection);
}

JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_unexport(JNIEnv *env, jobject obj, jint number) {
   unexportGPIO(number);
}

JNIEXPORT jint JNICALL Java_meteo_channels_DigitalChannel_read(JNIEnv *env, jobject obj, jint number) {
   return readGPIO(number);
}

JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_write(JNIEnv *env, jobject obj, jint number, jint value) {
   writeGPIO(number, value);
}

JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_stopPWM(JNIEnv *env, jobject obj, jint number) {
   pwm_flag = TRUE;
}

JNIEXPORT void JNICALL Java_meteo_channels_DigitalChannel_pwm(JNIEnv *env, jobject obj, jint number, jdouble f, jdouble k) {
   //Export GPIO
   exportGPIO(number);
   directionGPIO(number, "out");

   double t, t1, t2;

   t = 1.0 / f;
   t1 = t * k / 100.0;
   t2 = t * (100.0 - k) / 100.0;

   //Run an infinite loop - will require Ctrl-C to exit this program
   while(1) {
      if(pwm_flag == TRUE) {
         unexportGPIO(number);
         break;
      }
      if(t1 > 0) {
         writeGPIO(number, 1); //high level
         nsleep(t1);
      }
      if(t2 > 0) {
         writeGPIO(number, 0); //low level
         nsleep(t2);
      }
   }
}


AnalogChannel.c - includes C API implementation and JNI exports for accessing and reading ADC channels.
Code: Select all
/*
ADC Operation
================
1 To enable clocks for the ADC block, set the TSEN bit in the Syscon section (ADCClkDiv register).
2 Set the DeviceCfg.ADCEN bit.
3 Clear the DeviceCfg.ADCPD bit.
4 Select an input. First unlock the software lock by writing 0xAA to the ADCSWLock register.
Then write an appropriate value (selected from Table 20-2on page520) to the ADCSwitch register.
5 To poll, read the ADCResult register repeatedly. Bit 31 of this register is the SDR,
or Synchronous Data Ready, bit. This bit is set when a new valid conversion value appears in
this register and is cleared when this register is read.
So when two consecutive reads show the bit clear and then set, the second read has the new valid value.
6 Conversion data may also be processed using interrupts from this module. If bit 11 in the ADCIntEn register
(the RINTEN bit) is set, an interrupt occurs whenever the SDR bit in the ADCResult register is set.
Therefore, an interrupt handler can read the ADCResult register whenever a new valid sample appears
in the register, which both returns a new conversion value and clears the interrupt.


Register Memory Map
====================
Address Name SW locked Type Size Description
-------------------------------------------------------------------------
0x8090_0000 Reserved
0x8090_0004 Reserved
0x8090_0008 ADCResult No Read Only 32 bits ADC result register.
0x8090_000C Reserved
0x8090_0010 Reserved
0x8090_0014 Reserved
0x8090_0018 ADCSwitch Write Read/Write 28 bits ADC Switch Matrix control register.
0x8090_001C Reserved
0x8090_0020 ADCSWLock NA Read/Write 1-bit read ADC software lock register.
8-bit write
0x8090_0024 ADCIntEn No Read/Write 9 bits ADC Interrupt Enable Register

0x8093_0090 ADCClkDiv Yes R/W 32 ADC Clock Divider

0x8093_0080 DeviceCfg Yes R/W 32 Device configuration

ADC result register: 0x8090_0008

Bit 31: SDR: Synchronous Data Ready
Bit 0-12: AD: Analog-to-digital converter output at 12-bit resolution

ADCSwitch: 0x8090_0018

Input to Measure ADC Switch Value
ADC4 0x0000_0610
ADC3 0x0000_0620
ADC2 0x0000_0640
ADC1 0x0000_0680
ADC0 0x0000_0608

ADCSWLock: 0x8090_0020

SWLCK Software lock bits
WRITE: The Unlock value for this feature is 0xAA
READ: During a read operation SWLCK[0] has the following meaning:
1 = Unlocked for current bus access.
0 = Locked

ADCIntEn: 0x8090_0024

RINTEN: Bit 11: Synchronous Data Ready Interrupt Enable. Setting this bit results in an
interrupt whenever the Synchronous Data Ready (SDR) bit in the ADCResult register is set.

ADCClkDiv: 0x8093_0090

ADCEN: Bit 31: ADC clock enable.
ADIV: Bit 16: ADC clock divider value.
0 - ADC Clock is divide-by-16 from the external oscillator.
1 - ADC Clock is divide-by-4 from the external oscillator.

DeviceCfg: 0x8093_0080

ADCPD: Bit 2: ADC Power Down.
1 - ADC and clocks are powered down.
0 - ADC and clocks are active. ADCPD must be zero for normal ADC operation.
ADCEN: Bit 17: ADC Enable.
The ADCEN bit does not affect the ADC power state.
ADC power down is directly controlled by the ADCPD bit.
1 = ADC Interface enabled.
0 = ADC Interface disabled.
*/

#include "meteo_channels_AnalogChannel.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <assert.h>

#include "peekpoke.h"
#include "ep93xx_adc.h"

/* Prototypes */
int get_channel_value(int channel);

/* globals */
static unsigned long adc_page, syscon_page;
static int devmem;

int get_channel_value(int channel) {
   int cur_ch, avg, i;
   
   switch(channel) {
      case 0:
         cur_ch = ADC_CH0;
      break;
      case 1:
         cur_ch = ADC_CH1;
      break;
      case 2:
         cur_ch = ADC_CH2;
      break;
      case 3:
         cur_ch = ADC_CH3;
      break;
      case 4:
         cur_ch = ADC_CH4;
      break;
   }
   
   //discard first two samples
   read_channel(adc_page, cur_ch);
   read_channel(adc_page, cur_ch);
   
   avg = 0;
   //read 10 more samples
   for(i = 0; i < 10; i++) {
      usleep(10000);
      avg += read_channel(adc_page, cur_ch);
   }
   
   avg /= 10;
   
   if(avg < 0x7000) avg += 0x10000;
   
   avg -= 40905;
   
   return avg;
}

JNIEXPORT void JNICALL Java_meteo_channels_AnalogChannel_init(JNIEnv *env, jobject obj) {
   devmem = open("/dev/mem", O_RDWR|O_SYNC);
   assert(devmem != -1);
   
   adc_page = (unsigned long) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, devmem, ADC_PAGE);
   assert(&adc_page != MAP_FAILED);
   
   syscon_page = (unsigned long) mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, devmem, SYSCON_PAGE);
   assert(&syscon_page != MAP_FAILED);
   
   init_ADC(adc_page, syscon_page);
}

JNIEXPORT void JNICALL Java_meteo_channels_AnalogChannel_destroy(JNIEnv *env, jobject obj) {
   assert(munmap(&adc_page, getpagesize()) == -1);
   assert(munmap(&syscon_page, getpagesize()) == -1);
   close(devmem);
}

JNIEXPORT jint JNICALL Java_meteo_channels_AnalogChannel_read(JNIEnv *env, jobject obj, jint channel) {
   return get_channel_value(channel);
}

JNIEXPORT jdouble JNICALL Java_meteo_channels_AnalogChannel_readAsVoltage(JNIEnv *env, jobject obj, jint channel) {
   int value = get_channel_value(channel);
   return ((double)value * 3.3) / 49732;
}


ep93xx_adc.h - includes registry address defines and base ADC functions
Code: Select all
#define ADC_PAGE          0x80900000
#define ADCRESULT_OFFSET  0x0008
#define SDR_MASK          0x80000000
#define DATA_OFFSET       0x0008
#define DATA_MASK         0xFFFF
#define ADCSWITCH_OFFSET  0x0018
#define ADC_CH0           0x0608
#define ADC_CH1           0x0680
#define ADC_CH2           0x0640
#define ADC_CH3           0x0620
#define ADC_CH4           0x0610
#define ADCSWLOCK_OFFSET  0x0020
#define UNLOCK_VAL        0xAA

#define SYSCON_PAGE       0x80930000
#define ADCCLKDIV_OFFSET  0x0090
#define SYSCON_UNLOCK     0x00C0
#define TSEN_MASK         0x80000000
#define DEVICECFG_OFFSET  0x0080
#define ADCPD_MASK        0x02
#define ADCEN_MASK        0x20000

/*  prototypes  */
void init_ADC(unsigned long adc_page, unsigned long syscon_page);
int read_channel(unsigned long adc_page, unsigned short channel);
static char is_ADC_busy(unsigned long adc_page);

void init_ADC(unsigned long adc_page, unsigned long syscon_page)
{
   unsigned long val;

   /*    set TSEN bit     */
   val = PEEK32(syscon_page + ADCCLKDIV_OFFSET);
   //unlock the software lock
   POKE32(syscon_page + SYSCON_UNLOCK, UNLOCK_VAL);
   POKE32(syscon_page + ADCCLKDIV_OFFSET, TSEN_MASK | val);

   /*    set ADCEN bit    */
   val = PEEK32(syscon_page + DEVICECFG_OFFSET);
   POKE32(adc_page + SYSCON_UNLOCK, UNLOCK_VAL); //unlock the soft lock
   POKE32(syscon_page + DEVICECFG_OFFSET, val | ADCEN_MASK);

   /*    clear ADCPD bit  */
   val = PEEK32(syscon_page + DEVICECFG_OFFSET);
   POKE32(adc_page + SYSCON_UNLOCK, UNLOCK_VAL); //unlock the soft lock
   POKE32(syscon_page + DEVICECFG_OFFSET, val & ~ADCPD_MASK);
}

int read_channel(unsigned long adc_page, unsigned short channel)
{
   unsigned long val;

   POKE32(adc_page + ADCSWLOCK_OFFSET, UNLOCK_VAL); //unlock the soft lock

   //write ADCSwitch reg to select channel
   POKE32(adc_page + ADCSWITCH_OFFSET, channel);

   while(is_ADC_busy(adc_page)); //poll ADCResult

   //read result from data regisyyter
   val = PEEK32(adc_page + DATA_OFFSET) ;

   val = val & DATA_MASK;

   return val;   
}

static char is_ADC_busy(unsigned long adc_page)
{
   unsigned long val;
   
   val = PEEK32(adc_page + ADCRESULT_OFFSET);

   if((val & SDR_MASK) == SDR_MASK) return TRUE;

   return FALSE;
}

peekpoke.h
Code: Select all
// We can't expect that a dereference of an unsigned short * always
// produces a ldrh or strh since the compiler may choose to use
// a byte write instead.  Hence, we emit the peeks and pokes using
// inline assembler.  --JO
static inline unsigned short PEEK16(unsigned long addr) {
        unsigned short ret;

        asm volatile (
                "ldrh %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        );
        return ret;
}

static inline void POKE16(unsigned long addr, unsigned short dat) {
        asm volatile (
                "strh %1, [ %0 ]\n"
                :
                : "r" (addr), "r" (dat)
                : "memory"
        );
}

static inline unsigned long PEEK32(unsigned long addr) {
        unsigned long ret;

        asm volatile (
                "ldr %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        );
        return ret;
}
static inline void POKE32(unsigned long addr, unsigned long dat) {
        asm volatile (
                "str %1, [ %0 ]\n"
                :
                : "r" (addr), "r" (dat)
                : "memory"
        );
}
static inline unsigned char PEEK8(unsigned long addr) {
        unsigned char ret;

        asm volatile (
                "ldrb %0, [ %1 ]\n"
                : "=r" (ret)
                : "r" (addr)
                : "memory"
        );
        return ret;
}
static inline void POKE8(unsigned long addr, unsigned char dat) {
        asm volatile (
                "strb %1, [ %0 ]\n"
                :
                : "r" (addr), "r" (dat)
                : "memory"
        );
}

#define TRUE  0x01
#define FALSE 0x00


Next we have to add necessary JAVA API files in meteo directory

DigitalChannel.java
Code: Select all
package meteo.channels;

public class DigitalChannel {
   public native void export(int number, String direction);
   public native void unexport(int number);
   public native int read(int number);
   public native void write(int number, int value);
   public native void pwm(int number, double f, double k);
   public native void stopPWM(int number);
   static {
       System.loadLibrary("DigitalChannel");
   }
}


AnalogChannel.java
Code: Select all
package meteo.channels;

public class AnalogChannel {
   private native void init();
   public native void destroy();
   public native int read(int channel);
   public native double readAsVoltage(int channel);
   public AnalogChannel() {
      this.init();
   }
   static {
       System.loadLibrary("AnalogChannel");
   }
}


JAVA API has no main class, so it can’t be tested directly after deployment. That’s why there is another class MeteoTest which can be used for basic test of API functionallity. This class is located in meteo_test directory

MeteoTest.java
Code: Select all
package meteo_test;

import java.text.DecimalFormat;
import meteo.channels.*;

public class MeteoTest {
   private static AnalogChannel analog;
   private static DigitalChannel digital;
   
   private static double f = 70.0; //Hz
   private static double k = 50.0; //%
   private static int pwmGPIO = 8;
   
   private static class PwmTest extends Thread {
        public void run() {
            digital.pwm(pwmGPIO, f, k);
         System.out.println("PWM Stopped");
        }
        public void stopPWM() {
         digital.stopPWM(pwmGPIO);
        }
    }
   
   public static void main(String[] args) {
      // Analog Channel Test
      DecimalFormat dFormat = new DecimalFormat("0.000");
      
      System.out.println("Read all 5 ADC channels:");
      analog = new AnalogChannel();
      for(int i = 0; i < 5; i++) {
         System.out.println("Analog channel " + i + " value: " + analog.read(i) + ", as voltage: " + dFormat.format(analog.readAsVoltage(i)) + "V");
      }
      analog.destroy();
      
      // Digital Channel Test
      //Integer to keep track of whether we want on or off
        boolean toggle = false;
      int value = 0;
      int gpio = 0;
      
      System.out.println("Digital channel test: export GPIO 6, 8 as output and GPIO 4 as input.");
      digital = new DigitalChannel();
      digital.export(6, "out");
      digital.export(8, "out");
      digital.export(4, "in");
      for(int i = 0; i < 10; i++) {
         toggle = !toggle;
         value = digital.read(4);
         gpio = value == 0 ? 6 : 8;
         if(toggle) {
            digital.write(gpio, 1);
         }
         else {
            digital.write(gpio, 0);
         }
         try {
            Thread.sleep(1000);
         }
         catch (InterruptedException e) {
            System.out.println("thread interrupted");
         }
      }
      digital.unexport(6);
      digital.unexport(8);
      digital.unexport(4);
      
      System.out.println("Start PWM Test for 5 seconds.");
      PwmTest test = new PwmTest();
      test.start();
      try {
         Thread.sleep(5000);
      }
      catch (InterruptedException e) {
         System.out.println("thread interrupted");
      }
      test.stopPWM();
   }
}


Finally we have to add meteo recipe
meteo_1.0.bb
Code: Select all
DESCRIPTION = "JAVA Meteo Application"
PR = "r0"

DEPENDS = "classpath classpath-tools-native"

inherit autotools java-library

SRC_URI = "file://meteo/* \
   file://meteo_test/* \
   file://lib/* \
   file://bin"

S = ${WORKDIR}

do_compile() {
   #JAVAH="gjavah -classpath \$(CLASSPATH) -d \$(DEST) -jni" \
   JAVAH="gjavah -jni"
   JAR=gjar \
   #JAVAC="javac -classpath \$(CLASSPATH) -d \$(TOP)/ -O -source 1.3 -target 1.3" \
   JAVAC="javac"
   JAVAINCLUDEDIR=${STAGING_INCDIR}/classpath \
   GLIBTOOL="${TARGET_SYS}-libtool --tag=CC"
   
   ${JAVAC} meteo/channels/AnalogChannel.java
   ${JAVAC} meteo/channels/DigitalChannel.java
   ${JAVAH} -classpath ${S} -d lib/ meteo.channels.AnalogChannel
   ${JAVAH} -classpath ${S} -d lib/ meteo.channels.DigitalChannel
   ${CC} ${CFLAGS} ${LDFLAGS} -shared -I${JAVAINCLUDEDIR} lib/AnalogChannel.c -o lib/libAnalogChannel.so
   ${CC} ${CFLAGS} ${LDFLAGS} -shared -I${JAVAINCLUDEDIR} lib/DigitalChannel.c -o lib/libDigitalChannel.so
   ${JAR} cvf bin/meteo.jar meteo
   ${JAVAC} -classpath bin/meteo.jar meteo_test/MeteoTest.java
   ${JAR} cmf meteo_test/headers.txt bin/meteo_test.jar meteo_test/*.class
}

do_install() {
   install -d ${D}/${libdir_jni}
   install -d ${D}/${datadir_java}
   
   METEO_PATH="${D}/${libdir_jni}" \
   JHOME="${D}/${datadir_java}" \
   GLIBTOOL="${TARGET_SYS}-libtool"
   
   install -m 0755 ${S}/lib/lib*.so ${METEO_PATH}
   install -m 0755 ${S}/bin/*.jar ${JHOME}
}

do_stage() {
   oe_jarinstall -s bin/meteo.jar
   oe_jarinstall -s bin/meteo_test.jar
}

PACKAGES = "lib${PN}-jni lib${PN}-dev lib${PN}-jni-dbg lib${PN}-test ${JPN}"

FILES_lib${PN}-jni = "${libdir_jni}/lib*.so"
FILES_lib${PN}-dev = "${libdir_jni}/lib*.la ${libdir_jni}/lib*.a"
FILES_lib${PN}-jni-dbg = "${libdir_jni}/.debug/lib*.so"
FILES_lib${PN}-test = "${datadir_java}/*_test.jar"


Build meteo recipe with the following command
Code: Select all
bitbake meteo && bitbake package-index


After successful build, on target platform you can deploy the following packages:
libmeteo-jni – dynamic libraries. They will be installed as libAnalogChannel.so and libDigitalChannel.so in /usr/lib/jni directory
libmeteo-java – JAVA API archive. It will be installed as meteo.jar in /usr/share/java directory
libmeteo-test – JAVA API Test application. It will be installed as meteo_test.jar in /usr/share/java directory.

Let’s deploy our application on target platform. Execute the following command on target platform.
Code: Select all
opkg update && opkg install libmeteo-jni && opkg install libmeteo-java && opkg install libmeteo-test


Start test application
Code: Select all
cd /usr/share/java
java –jar meteo_test.jar
mladen
 
Posts: 10
Joined: Tue Feb 22, 2011 5:16 pm

Return to OSGi based sensor network

Who is online

Users browsing this forum: No registered users and 1 guest