Pi4j 使用 java 与 raspberry Pi 不工作

Pi4j to use java with raspberry Pi not working

老实说,我快要放弃了,我已经尝试了很多不同的可能性,现在已经好几个星期,差不多一个月了,遇到了多个问题。

我是一名新手程序员,尤其是 java,但我对 java

有很好的理解

我可以创建一个 maven 项目没问题,我对 java 本身的结构没有问题,但我不完全理解 pom.xml.

文件编译得很好,但是当我用 java -jar (filename) 启动它时,我得到以下输出;

Exception in thread "main" java.lang.NoClassDefFoundError: com/pi4j/Pi4J at com.pi.rasberri.Main.main(Main.java:16) Caused by: java.lang.ClassNotFoundException: com.pi4j.Pi4J at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ... 1 more

这是我几乎被肢解的 pom;

   (The long links)
<modelVersion>4.0.0</modelVersion>
<groupId>com.pi</groupId>
<artifactId>Rasberri</artifactId>
<version>3.6.1</version>
<packaging>jar</packaging>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>  <dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.32</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
    </dependency>
    <dependency>
        <groupId>com.pi4j</groupId>
        <artifactId>pi4j-core</artifactId>
        <version>2.0</version>
    </dependency>
    <dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-raspberrypi</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-pigpio</artifactId>
    <version>2.0</version>
</dependency>
</dependencies> <build>
  <plugins>
      <plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version> </plugin>    <plugin>    <groupId>org.apache.maven.plugins</groupId>   

maven-jar-plugin 3.1.0 true com.pi.rasberri.Main lib/ true true com.pi.rasberri.Main false true

还有我的代码,就是com.pi.rasberri.Main

    package com.pi.rasberri;

import com.pi4j.Pi4J;
import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.gpio.digital.DigitalState;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {
   
    private static final int PIN_LED = 6;
    
    public static void main(String[] args) throws Exception{
        
       var pi4j = Pi4J.newAutoContext();
        int x = 0;
        
        var ledConfig = DigitalOutput.newConfigBuilder(pi4j)
           .id("led")
           .name("LED Flasher")
           .address(PIN_LED)
           .shutdown(DigitalState.LOW)
           .initial(DigitalState.LOW)
           .provider("pigpio-digital-output");
      
        var led = pi4j.create(ledConfig);
        
        
        while(x != 5){
        
            led.high();
            sleep(1000);
            led.low();
            sleep(500);
            x++;
        }
    }
    
    static void sleep(int z){
    
        try {
           Thread.sleep(z);
        }   catch (InterruptedException ex) {
           System.out.println("Thread.sleep went fucky wucky");
        }
    }
    }

我会很感激任何能指引我去某个地方的东西,因为我现在很迷茫,当然,如果我找到答案,我会告诉大家! 提前致谢

                       **UPDATE**

Thank you, tgdavies, the article you linked was the answer to that specific problem!**

Just in case anyone else has the same chain of issues as me;

But with that being said, i ran directly into another error;

[main] INFO com.pi4j.Pi4J - New auto context [main] INFO com.pi4j.Pi4J - New context builder [main] INFO com.pi4j.platform.impl.DefaultRuntimePlatforms - adding platform to managed platform map [id=raspberrypi; name=RaspberryPi Platform; priority=5; class=com.pi4j.plugin.raspberrypi.platform.RaspberryPiPlatform] Exception in thread "main" com.pi4j.provider.exception.ProviderNotFoundException: Pi4J provider [pigpio-digital-output] could not be found. Please include this 'provider' JAR in the classpath. at com.pi4j.provider.impl.DefaultRuntimeProviders.get(DefaultRuntimeProviders.java:238) at com.pi4j.provider.impl.DefaultProviders.get(DefaultProviders.java:147) at com.pi4j.provider.Providers.get(Providers.java:253) at com.pi4j.context.Context.create(Context.java:316) at com.pi4j.internal.IOCreator.create(IOCreator.java:58) at com.pi4j.internal.IOCreator.create(IOCreator.java:96) at com.pi4j.internal.IOCreator.create(IOCreator.java:176) at com.pi.rasberri.Main.main(Main.java:27)

我稍微清理了一下pom.xml;

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.32</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
    <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.pi4j</groupId>
        <artifactId>pi4j-core</artifactId>
        <version>2.0</version>
    </dependency>
    <dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-raspberrypi</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-pigpio</artifactId>
    <version>2.0</version>
</dependency>
</dependencies>
  

<build>
      <plugins>  <!--Package all libraries classes into one runnable jar -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
                <archive>
                    <manifest>
                <mainClass>com.pi.rasberri.Main</mainClass>
                    </manifest>
                </archive>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
            </configuration>
        </plugin>    
</plugins>
</build>
</project>

至此,我知道至少有两种可能性,

  1. 代码只需 运行 在 raspberry pi
  2. 我输入的类路径不正确

但老实说,我真的不知道从哪里开始进行故障排除 我尝试了一些方法,其中之一是尝试另一种编译文件的方法, 但另一种方法只会导致更长的错误串。

接下来我应该尝试什么? 提前致谢! 并感谢迄今为止提出故障排除步骤建议的任何人!

哦,目标是希望创建一个单独的 jar 文件以在 raspberry pi

上执行

update

I tried to run it on the Raspberri pi, and it resulted in the same error so it's not that

感谢 tgdavies、MadProgrammer 和 khmarbaise 的回答,解决方法是创建一个 fat jar它基本上是一个包含所有一个文件中的依赖项,示例可以在原文中找到question/comments

更新!!

Pi4j 已在其网站上发布了 V2 fat jar 的说明! 我试过了,现在效果很好

https://pi4j.com/getting-started/minimal-example-application-fatjar/

我没有 Raspberry Pi 来进行最终测试,但我想我找到了解决方法。

使用 this answer 我设法在 Docker 中获得 2021-10-30-raspios-bullseye-armhf-lite.img 运行ning。我使用您的代码构建了一个项目并复制了所有需要的文件并尝试启动它(mypiapp 是我的 jar 包含您的 main-class):

java -cp mypiapp-0.0.1-SNAPSHOT.jar:lib/pi4j-core-2.1.1.jar:lib/pi4j-library-pigpio-2.1.1.jar:lib/pi4j-plugin-pigpio-2.1.1.jar:lib/pi4j-plugin-raspberrypi-2.1.1.jar:lib/slf4j-api-1.7.32.jar:lib/slf4j-simple-1.7.32.jar com.github.fwi.mypiapp.MyPiApp

然后给了我错误:

[main] ERROR com.pi4j.library.pigpio.util.NativeLibraryLoader - Unable to load [libpi4j-pigpio.so] using path: [/lib/armhf/libpi4j-pigpio.so]
java.lang.UnsatisfiedLinkError: /tmp/libpi4j-pigpio1770932771276400506.so: libpigpio.so.1: cannot open shared object file: No such file or directory

真可惜。但至少没有 ProviderNotFoundException (我也可以使用“具有依赖性的胖罐子”来重现)。长 java-命令似乎可以防止该异常发生。

我可以通过 运行ning(在 Raspbian 中)

稍微改善这种情况
apt install pigpio

现在长 java-命令显示:

[main] WARN com.pi4j.library.pigpio.impl.PiGpioNativeImpl - PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed

在 Docker 容器中 运行 时,这是可以预期的。但至少找到并加载了本机库。

现在介绍可能解决“fat jar”问题的解决方法。我们将从 Spring 借用一些 Maven 设置和代码。 Spring 也可以构建 fat-jars 并且做得更复杂但也更好。 pom 现在看起来像(在需要的地方更新您的项目名称):

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.1</version>
    </parent>
    
    <groupId>com.github.fwi</groupId>
    <artifactId>mypiapp</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
        <start.class>com.github.fwi.mypiapp.MyPiApp</start.class>
        <pi4j.version>2.1.1</pi4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.pi4j</groupId>
            <artifactId>pi4j-plugin-raspberrypi</artifactId>
            <version>${pi4j.version}</version>
        </dependency>
        <dependency>
            <groupId>com.pi4j</groupId>
            <artifactId>pi4j-plugin-pigpio</artifactId>
            <version>${pi4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>${start.class}</mainClass>
                    <layout>ZIP</layout>
                    <executable>false</executable>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

只需 运行 mvn clean package 即可构建 fat-jar。 运行 它使用 java -jar mypiapp-fat.jar 在我的例子中,它给出了与 运行 长 java-命令时完全相同的错误(即没有 ProviderNotFoundException)。所以我认为这可以在真正的 Raspberry-Pi 上运行(不过可能仍然需要 apt install pigpio)。

一些注意事项:

  • Spring 父级设置了一些良好的 Maven 默认值,还为 spring-boot-maven-plugin
  • 设置了良好的默认值
  • Java 版本必须使用 java.version 属性.
  • 设置
  • 使用包含您的 main 方法的 class 的名称更新 start.class
  • pom.xml 中的 3 个依赖项将拉入所有其他依赖项(依赖项的依赖项)
  • Spring 文档参考:packaging and nested-jars launcher options.

我在使用 Raspberry P4、java 11 和 pi4j v2 时遇到了同样的问题。我直接从树莓派

下载 pigpio 库解决了这个问题
sudo apt-get install pigpio

库安装完成后,jar 运行良好。 如果您不是 root 用户

,还请记住 运行 您的程序 sudo