diff --git a/pi4j-core/pom.xml b/pi4j-core/pom.xml
index e695f29c..810a53f5 100644
--- a/pi4j-core/pom.xml
+++ b/pi4j-core/pom.xml
@@ -7,6 +7,7 @@
Pi4J :: LIBRARY :: Java Library (CORE)
Pi4J Java API & Runtime Library
jar
+
com.pi4j
pi4j-parent
@@ -14,9 +15,6 @@
../pom.xml
-
-
-
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/BoardModel.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/BoardModel.java
new file mode 100644
index 00000000..f18d49f0
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/BoardModel.java
@@ -0,0 +1,359 @@
+package com.pi4j.boardinfo.definition;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.pi4j.boardinfo.definition.BoardType.*;
+
+/**
+ * Partially based on
+ * en.wikipedia.org/wiki/Raspberry_Pi
+ * oastic.com/posts/how-to-know-which-raspberry-do-you-have
+ * raspberrypi.com/documentation/computers/raspberry-pi.html#new-style-revision-codes-in-use
+ * raspberrypi-spy.co.uk/2012/09/checking-your-raspberry-pi-board-version/
+ */
+public enum BoardModel {
+ MODEL_1_A("Raspberry Pi 1 Model A", SINGLE_BOARD_COMPUTER,
+ new ArrayList<>(),
+ PiModel.MODEL_A,
+ HeaderVersion.TYPE_1,
+ LocalDate.of(2013, 2, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(700),
+ Collections.singletonList(256 * 1024)),
+ MODEL_1_A_PLUS("Raspberry Pi 1 Model A+", SINGLE_BOARD_COMPUTER,
+ Collections.singletonList("900021"),
+ PiModel.MODEL_A,
+ HeaderVersion.TYPE_1,
+ LocalDate.of(2014, 11, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(700),
+ Arrays.asList(256 * 1024, 512 * 1024),
+ Collections.singletonList("Amount of memory changed to 512Mb on 20160810")),
+ MODEL_3_A_PLUS("Raspberry Pi 3 Model A+", SINGLE_BOARD_COMPUTER,
+ Collections.singletonList("9020e0"),
+ PiModel.MODEL_A,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2018, 11, 1),
+ Soc.BCM2837B0,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(1400),
+ Collections.singletonList(512 * 1024)),
+ MODEL_1_B("Raspberry Pi 1 Model B", SINGLE_BOARD_COMPUTER,
+ new ArrayList<>(),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_1,
+ LocalDate.of(2012, 4, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(700),
+ Arrays.asList(256 * 1024, 512 * 1024),
+ Collections.singletonList("Amount of memory changed to 512Mb on 20121015")),
+ MODEL_1_B_PLUS("Raspberry Pi 1 Model B+", SINGLE_BOARD_COMPUTER,
+ Collections.singletonList("900032"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_1,
+ LocalDate.of(2014, 7, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(700),
+ Collections.singletonList(512 * 1024)),
+ MODEL_2_B("Raspberry Pi 2 Model B", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("a01040", "a01041", "a21041"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_2,
+ LocalDate.of(2015, 2, 1),
+ Soc.BCM2836,
+ Cpu.CORTEX_A7, 4,
+ Collections.singletonList(900),
+ Collections.singletonList(1024 * 1024)),
+ MODEL_2_B_V1_2("Raspberry Pi 2 Model B V1.2", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("a02042", "a22042"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_2,
+ LocalDate.of(2016, 10, 1),
+ Soc.BCM2837,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(900),
+ Collections.singletonList(1024 * 1024)),
+ MODEL_3_B("Raspberry Pi 3 Model B", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("a02082", "a22082", "a32082", "a52082", "a22083"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2016, 2, 1),
+ Soc.BCM2837,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(1200),
+ Collections.singletonList(1024 * 1024)),
+ MODEL_3_B_PLUS("Raspberry Pi 3 Model B+", SINGLE_BOARD_COMPUTER,
+ Collections.singletonList("a020d3"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2018, 3, 14),
+ Soc.BCM2837B0,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(1400),
+ Collections.singletonList(1024 * 1024)),
+ MODEL_4_B("Raspberry Pi 4 Model B", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("a03111", "b03111", "b03112", "b03114", "b03115", "c03111", "c03112", "c03114", "c03115", "d03114", "d03115"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2019, 6, 24),
+ Soc.BCM2711,
+ Cpu.CORTEX_A72, 4,
+ Arrays.asList(1500, 1800),
+ Arrays.asList(1024 * 1024, 2048 * 1024, 4096 * 1024, 8192 * 1024)),
+ MODEL_400("Raspberry Pi 400", ALL_IN_ONE_COMPUTER,
+ Collections.singletonList("c03130"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2020, 11, 2),
+ Soc.BCM2711C0,
+ Cpu.CORTEX_A72, 4,
+ Collections.singletonList(1800),
+ Collections.singletonList(4096 * 1024)),
+ MODEL_5_B("Raspberry Pi 5 Model B", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("c04170", "d04170"),
+ PiModel.MODEL_B,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2023, 9, 28),
+ Soc.BCM2712,
+ Cpu.CORTEX_A76, 4,
+ Collections.singletonList(2400),
+ Arrays.asList(4096 * 1024, 8192 * 1024)),
+ COMPUTE_1("Compute Module 1", STACK_ON_COMPUTER,
+ Collections.singletonList("900061"),
+ PiModel.COMPUTE,
+ HeaderVersion.COMPUTE,
+ LocalDate.of(2014, 4, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(700),
+ Collections.singletonList(512 * 1024)),
+ COMPUTE_3("Compute Module 3", STACK_ON_COMPUTER,
+ Arrays.asList("a020a0", "a220a0"),
+ PiModel.COMPUTE,
+ HeaderVersion.COMPUTE,
+ LocalDate.of(2017, 1, 1),
+ Soc.BCM2837,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(1200),
+ Collections.singletonList(1024 * 1024)),
+ COMPUTE_3_PLUS("Compute Module 3+", STACK_ON_COMPUTER,
+ Collections.singletonList("a02100"),
+ PiModel.COMPUTE,
+ HeaderVersion.COMPUTE,
+ LocalDate.of(2019, 1, 1),
+ Soc.BCM2837B0,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(1200),
+ Collections.singletonList(1024 * 1024)),
+ COMPUTE_4("Compute Module 4", STACK_ON_COMPUTER,
+ Arrays.asList("a03140", "b03140", "c03140", "d03140"),
+ PiModel.COMPUTE,
+ HeaderVersion.COMPUTE,
+ LocalDate.of(2020, 10, 1),
+ Soc.BCM2711,
+ Cpu.CORTEX_A72, 4,
+ Collections.singletonList(1500),
+ Arrays.asList(1024 * 1024, 2048 * 1024, 4096 * 1024, 8192 * 1024)),
+ ZERO_PCB_1_2("Raspberry Pi Zero PCB V1.2", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("900092", "920092"),
+ PiModel.ZERO,
+ HeaderVersion.TYPE_2,
+ LocalDate.of(2015, 11, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(1000),
+ Collections.singletonList(512 * 1024)),
+ ZERO_PCB_1_3("Raspberry Pi Zero PCB V1.3", SINGLE_BOARD_COMPUTER,
+ Arrays.asList("900093", "920093"),
+ PiModel.ZERO,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2016, 5, 1),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(1000),
+ Collections.singletonList(512 * 1024)),
+ ZERO_W("Raspberry Pi Zero W", SINGLE_BOARD_COMPUTER,
+ Collections.singletonList("9000c1"),
+ PiModel.ZERO,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2017, 2, 28),
+ Soc.BCM2835,
+ Cpu.ARM1176JZF_S, 1,
+ Collections.singletonList(1000),
+ Collections.singletonList(512 * 1024)),
+ ZERO_V2("Raspberry Pi Zero V2", SINGLE_BOARD_COMPUTER,
+ Collections.singletonList("902120"),
+ PiModel.ZERO,
+ HeaderVersion.TYPE_3,
+ LocalDate.of(2021, 10, 28),
+ Soc.BCM2710A1,
+ Cpu.CORTEX_A53, 4,
+ Collections.singletonList(1000),
+ Collections.singletonList(512 * 1024)),
+ PICO("Raspberry Pi Pico", MICROCONTROLLER,
+ new ArrayList<>(),
+ PiModel.PICO,
+ HeaderVersion.PICO,
+ LocalDate.of(2021, 1, 1),
+ Soc.RP2040,
+ Cpu.CORTEX_MO_PLUS, 1,
+ Collections.singletonList(1000),
+ Collections.singletonList(264 + 2048)),
+ PICO_W("Raspberry Pi Pico W", MICROCONTROLLER,
+ new ArrayList<>(),
+ PiModel.PICO,
+ HeaderVersion.PICO,
+ LocalDate.of(2022, 6, 1),
+ Soc.RP2040,
+ Cpu.CORTEX_MO_PLUS, 1,
+ Collections.singletonList(1000),
+ Collections.singletonList(264 + 2048),
+ Collections.singletonList("Same form factor as PICO but with Wi-Fi")),
+ UNKNOWN("Unknown", BoardType.UNKNOWN,
+ new ArrayList<>(),
+ PiModel.UNKNOWN,
+ HeaderVersion.UNKNOWN,
+ null,
+ Soc.UNKNOWN,
+ Cpu.UNKNOWN, 0,
+ new ArrayList<>(),
+ new ArrayList<>());
+
+ private static final Logger logger = LoggerFactory.getLogger(BoardModel.class);
+
+ private final String label;
+ private final BoardType boardType;
+ private final List boardCodes;
+ private final PiModel model;
+ private final HeaderVersion headerVersion;
+ private final LocalDate releaseDate;
+ private final Soc soc;
+ private final Cpu cpu;
+ private final Integer numberOfCpu;
+ private final List versionsProcessorSpeedInMhz;
+ private final List versionsMemoryInKb;
+ private final List remarks;
+
+ BoardModel(String label, BoardType boardType, List boardCodes,
+ PiModel model, HeaderVersion headerVersion, LocalDate releaseDate,
+ Soc soc, Cpu cpu, Integer numberOfCpu,
+ List versionsProcessorSpeedInMhz, List versionsMemoryInKb) {
+ this(label, boardType, boardCodes, model, headerVersion, releaseDate, soc, cpu, numberOfCpu, versionsProcessorSpeedInMhz,
+ versionsMemoryInKb, new ArrayList<>());
+ }
+
+ BoardModel(String label, BoardType boardType, List boardCodes,
+ PiModel model, HeaderVersion headerVersion, LocalDate releaseDate,
+ Soc soc, Cpu cpu, Integer numberOfCpu,
+ List versionsProcessorSpeedInMhz, List versionsMemoryInKb,
+ List remarks) {
+ this.label = label;
+ this.boardType = boardType;
+ this.boardCodes = boardCodes;
+ this.model = model;
+ this.headerVersion = headerVersion;
+ this.releaseDate = releaseDate;
+ this.soc = soc;
+ this.cpu = cpu;
+ this.numberOfCpu = numberOfCpu;
+ this.versionsProcessorSpeedInMhz = versionsProcessorSpeedInMhz;
+ this.versionsMemoryInKb = versionsMemoryInKb;
+ this.remarks = remarks;
+ }
+
+ public static BoardModel getByBoardCode(String boardCode) {
+ var matches = Arrays.stream(BoardModel.values())
+ .filter(bm -> bm.boardCodes.contains(boardCode))
+ .collect(Collectors.toList());
+ if (matches.isEmpty()) {
+ return BoardModel.UNKNOWN;
+ } else if (matches.size() > 1) {
+ logger.error("Too many matching models found for code {}, probably an error in the definitions", boardCode);
+ }
+ return matches.get(0);
+ }
+
+ public static BoardModel getByBoardName(String boardName) {
+ var matches = Arrays.stream(BoardModel.values())
+ .filter(bm -> boardName.toLowerCase().startsWith(bm.label.toLowerCase()))
+ .collect(Collectors.toList());
+ if (matches.isEmpty()) {
+ return BoardModel.UNKNOWN;
+ } else if (matches.size() > 1) {
+ logger.error("Too many matching models found for name {}, the given name is not exclusive enough", boardName);
+ }
+ return matches.get(0);
+ }
+
+ public String getName() {
+ return name();
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public BoardType getBoardType() {
+ return boardType;
+ }
+
+ public List getBoardCodes() {
+ return boardCodes;
+ }
+
+ public PiModel getModel() {
+ return model;
+ }
+
+ public HeaderVersion getHeaderVersion() {
+ return headerVersion;
+ }
+
+ public LocalDate getReleaseDate() {
+ return releaseDate;
+ }
+
+ public Soc getSoc() {
+ return soc;
+ }
+
+ public Cpu getCpu() {
+ return cpu;
+ }
+
+ public Integer getNumberOfCpu() {
+ return numberOfCpu;
+ }
+
+ public List getVersionsProcessorSpeedInMhz() {
+ return versionsProcessorSpeedInMhz;
+ }
+
+ public List getVersionsMemoryInKb() {
+ return versionsMemoryInKb;
+ }
+
+ public List getVersionsMemoryInMb() {
+ return versionsMemoryInKb.stream().map(m -> m / 1024F).collect(Collectors.toList());
+ }
+
+ public List getVersionsMemoryInGb() {
+ return versionsMemoryInKb.stream().map(m -> m / 1024F / 1024F).collect(Collectors.toList());
+ }
+
+ public List getRemarks() {
+ return remarks;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/BoardType.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/BoardType.java
new file mode 100644
index 00000000..542fe1a7
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/BoardType.java
@@ -0,0 +1,9 @@
+package com.pi4j.boardinfo.definition;
+
+public enum BoardType {
+ ALL_IN_ONE_COMPUTER,
+ MICROCONTROLLER,
+ SINGLE_BOARD_COMPUTER,
+ STACK_ON_COMPUTER,
+ UNKNOWN
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/Cpu.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/Cpu.java
new file mode 100644
index 00000000..7c1da3a9
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/Cpu.java
@@ -0,0 +1,22 @@
+package com.pi4j.boardinfo.definition;
+
+public enum Cpu {
+ ARM1176JZF_S("ARM1176JZF-S"),
+ CORTEX_A53("Cortex-A53"),
+ CORTEX_A7("Cortex-A7"),
+ CORTEX_A72("Cortex-A72"),
+ CORTEX_A76("Cortex-A76"),
+ CORTEX_MO_PLUS("Cortex-M0+"),
+ UNKNOWN("Unknown"),
+ ;
+
+ private final String label;
+
+ Cpu(String label) {
+ this.label = label;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/HeaderPins.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/HeaderPins.java
new file mode 100644
index 00000000..571dbc7a
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/HeaderPins.java
@@ -0,0 +1,123 @@
+package com.pi4j.boardinfo.definition;
+
+import com.pi4j.boardinfo.model.HeaderPin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * List of pins in a Raspberry Pi header.
+ */
+public enum HeaderPins {
+ HEADER_8("8pin header", get8PinsHeader()),
+ HEADER_26_TYPE_1("26pin header - type 1", get26PinsHeader(1)),
+ HEADER_26_TYPE_2("26pin header - type 2", get26PinsHeader(2)),
+ HEADER_40("40pin header", get40PinsHeader()),
+ COMPUTE_J5("Compute J5", getComputeJ5()),
+ COMPUTE_J6("Compute J6", getComputeJ6());
+
+ private final String label;
+ private List pins;
+
+ HeaderPins(String label, List pins) {
+ this.label = label;
+ this.pins = pins;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public List getPins() {
+ return pins;
+ }
+
+ static List get8PinsHeader() {
+ List header = new ArrayList<>();
+
+ header.add(new HeaderPin(1, PinType.POWER, "5.0 VDC"));
+ header.add(new HeaderPin(2, PinType.POWER, "3.3 VDC"));
+ header.add(new HeaderPin(3, PinType.DIGITAL, null, 28, 17, ""));
+ header.add(new HeaderPin(4, PinType.DIGITAL, null, 29, 18, ""));
+ header.add(new HeaderPin(5, PinType.DIGITAL, null, 30, 19, ""));
+ header.add(new HeaderPin(6, PinType.DIGITAL, null, 31, 20, ""));
+ header.add(new HeaderPin(7, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(8, PinType.GROUND, "Ground"));
+
+ return header;
+ }
+
+ static List get26PinsHeader(int type) {
+ List header = new ArrayList<>();
+
+ header.add(new HeaderPin(1, PinType.POWER, "3.3 VDC"));
+ header.add(new HeaderPin(2, PinType.POWER, "5.0 VDC"));
+ header.add(new HeaderPin(3, PinType.DIGITAL_NO_PULL_DOWN, PinFunction.I2C, (type == 1 ? 0 : 2), 8, "SDA1 (I2C)", "SDA.1 pin has a physical pull-up resistor"));
+ header.add(new HeaderPin(4, PinType.POWER, "5.0 VDC"));
+ header.add(new HeaderPin(5, PinType.DIGITAL_NO_PULL_DOWN, PinFunction.I2C, (type == 1 ? 1 : 3), 9, "SCL1 (I2C)", "SCL.1 pin has a physical pull-up resistor"));
+ header.add(new HeaderPin(6, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(7, PinType.DIGITAL, PinFunction.GPCLK, 4, 7, "GPCLK0"));
+ header.add(new HeaderPin(8, PinType.DIGITAL, PinFunction.UART, 14, 15, "UART TxD"));
+ header.add(new HeaderPin(9, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(10, PinType.DIGITAL, PinFunction.UART, 15, 16, "UART RxD"));
+ header.add(new HeaderPin(11, PinType.DIGITAL, PinFunction.SPI, 17, 0, ""));
+ header.add(new HeaderPin(12, PinType.DIGITAL_AND_PWM, PinFunction.SPI, 18, 1, "PCM_CLK/PWM0", "Supports PWM0 [ALT5]"));
+ header.add(new HeaderPin(13, PinType.DIGITAL, null, (type == 1 ? 21 : 27), 2, ""));
+ header.add(new HeaderPin(14, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(15, PinType.DIGITAL, null, 22, 3, ""));
+ header.add(new HeaderPin(16, PinType.DIGITAL, null, 23, 4, ""));
+ header.add(new HeaderPin(17, PinType.POWER, "3.3 VDC"));
+ header.add(new HeaderPin(18, PinType.DIGITAL, null, 24, 5, ""));
+ header.add(new HeaderPin(19, PinType.DIGITAL, PinFunction.SPI, 10, 12, "MOSI (SPI)"));
+ header.add(new HeaderPin(20, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(21, PinType.DIGITAL, PinFunction.SPI, 9, 13, "MISO (SPI)"));
+ header.add(new HeaderPin(22, PinType.DIGITAL, null, 25, 6, ""));
+ header.add(new HeaderPin(23, PinType.DIGITAL, PinFunction.SPI, 11, 14, "SCLK (SPI)"));
+ header.add(new HeaderPin(24, PinType.DIGITAL, PinFunction.SPI, 8, 10, "CE0 (SPI)"));
+ header.add(new HeaderPin(25, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(26, PinType.DIGITAL, PinFunction.SPI, 7, 11, "CE1 (SPI)"));
+
+ return header;
+ }
+
+ static List get40PinsHeader() {
+ List header = new ArrayList<>();
+
+ header.addAll(get26PinsHeader(2));
+
+ header.add(new HeaderPin(27, PinType.DIGITAL_NO_PULL_DOWN, PinFunction.I2C, 0, 30, "SDA0 I2C ID EEPROM", "SDA.0 pin has a physical pull-up resistor"));
+ header.add(new HeaderPin(28, PinType.DIGITAL_NO_PULL_DOWN, PinFunction.I2C, 1, 31, "SCL0 I2C ID EEPROM", "SDC.0 pin has a physical pull-up resistor"));
+ header.add(new HeaderPin(29, PinType.DIGITAL, PinFunction.GPCLK, 5, 21, "GPCLK1"));
+ header.add(new HeaderPin(30, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(31, PinType.DIGITAL, PinFunction.GPCLK, 6, 22, "GPCL2"));
+ header.add(new HeaderPin(32, PinType.DIGITAL_AND_PWM, null, 12, 26, "PWM0", "Supports PWM0 [ALT0]"));
+ header.add(new HeaderPin(33, PinType.DIGITAL_AND_PWM, null, 13, 23, "PWM1", "Supports PWM1 [ALT0]"));
+ header.add(new HeaderPin(34, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(35, PinType.DIGITAL_AND_PWM, PinFunction.SPI, 19,24, "PCM_FS/PWM1", "Supports PWM1 [ALT5]"));
+ header.add(new HeaderPin(36, PinType.DIGITAL, PinFunction.SPI, 16, 27, ""));
+ header.add(new HeaderPin(37, PinType.DIGITAL, null, 26, 25, ""));
+ header.add(new HeaderPin(38, PinType.DIGITAL, PinFunction.SPI, 20, 28, "PCM_DIN"));
+ header.add(new HeaderPin(39, PinType.GROUND, "Ground"));
+ header.add(new HeaderPin(40, PinType.DIGITAL, PinFunction.SPI, 21, 29, "PCM_DOUT"));
+
+ return header;
+ }
+
+ static List getComputeJ5() {
+ List header = new ArrayList<>();
+
+ // TODO
+ // https://pi4j.com/1.2/pins/model-cm-rev1.html#J5_Pinout_60-pin_Header
+
+ return header;
+ }
+
+ static List getComputeJ6() {
+ List header = new ArrayList<>();
+
+ // TODO
+ // https://pi4j.com/1.2/pins/model-cm-rev1.html#J6_Pinout_60-pin_Header
+
+ return header;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/HeaderVersion.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/HeaderVersion.java
new file mode 100644
index 00000000..5d384ea7
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/HeaderVersion.java
@@ -0,0 +1,37 @@
+package com.pi4j.boardinfo.definition;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public enum HeaderVersion {
+ PICO("Pico", "Used on the Pico microcontroller", new ArrayList<>()),
+ TYPE_1("Type 1", "Used on original Model B", Collections.singletonList(HeaderPins.HEADER_26_TYPE_1)),
+ TYPE_2("Type 2", "Used on Model A and Model B (revision 2)", Arrays.asList(HeaderPins.HEADER_26_TYPE_2, HeaderPins.HEADER_8)),
+ TYPE_3("Type 3", "Used on Model A+, B+, Pi Zero, Pi Zero W, Pi2B, Pi3B, Pi4B", Collections.singletonList(HeaderPins.HEADER_40)),
+ COMPUTE("Compute Module", "54 GPIO", Arrays.asList(HeaderPins.COMPUTE_J5, HeaderPins.COMPUTE_J6)),
+ UNKNOWN("Unknown", "", new ArrayList<>());
+
+ private final String label;
+ private final String description;
+ private final List headerPins;
+
+ HeaderVersion(String label, String description, List headerPins) {
+ this.label = label;
+ this.description = description;
+ this.headerPins = headerPins;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List getHeaderPins() {
+ return headerPins;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/InstructionSet.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/InstructionSet.java
new file mode 100644
index 00000000..f4028338
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/InstructionSet.java
@@ -0,0 +1,19 @@
+package com.pi4j.boardinfo.definition;
+
+public enum InstructionSet {
+ ARM_V6_M("ARMv6-M"),
+ ARM_V6("ARMv6"),
+ ARM_V7("ARMv7"),
+ ARM_V8("ARMv8"),
+ UNKNOWN("Unknown");
+
+ private final String label;
+
+ InstructionSet(String label) {
+ this.label = label;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PiModel.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PiModel.java
new file mode 100644
index 00000000..62775beb
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PiModel.java
@@ -0,0 +1,28 @@
+package com.pi4j.boardinfo.definition;
+
+public enum PiModel {
+ COMPUTE("Compute Module", "Pi on a 200-pin DDR2-memory-like module for integration in embedded devices"),
+ MODEL_A("Model A", "Without ethernet connector"),
+ MODEL_B("Model B", "With ethernet connector"),
+ PICO("Pico", "Microcontroller"),
+ ZERO("Zero", "Smaller size and reduced GPIO capabilities"),
+ UNKNOWN("Unknown", "");
+
+ private final String label;
+ private final String description;
+
+ PiModel(String label, String description) {
+ this.label = label;
+ this.description = description;
+
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
+
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PinFunction.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PinFunction.java
new file mode 100644
index 00000000..0b9f64f6
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PinFunction.java
@@ -0,0 +1,27 @@
+package com.pi4j.boardinfo.definition;
+
+/**
+ * List of pin functions in a header.
+ */
+public enum PinFunction {
+ UART("Universal Asynchronous Receiver and Transmitter", "Asynchronous serial communication protocol"),
+ GPCLK("General Purpose Clock", "Output a fixed frequency"),
+ I2C("Inter Integrated Circuit", "Synchronous serial computer bus"),
+ SPI("Serial Peripheral Interface", "Four-wire serial bus");
+
+ private final String label;
+ private final String description;
+
+ PinFunction(String label, String description) {
+ this.label = label;
+ this.description = description;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PinType.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PinType.java
new file mode 100644
index 00000000..1f7a8386
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/PinType.java
@@ -0,0 +1,28 @@
+package com.pi4j.boardinfo.definition;
+
+/**
+ * List of pin types in a header.
+ */
+public enum PinType {
+ POWER("Power", 0x990000),
+ GROUND("Ground", 0x000000),
+ DIGITAL("Digital", 0x009900),
+ DIGITAL_AND_PWM("Digital and PWM", 0xff7ff00),
+ DIGITAL_NO_PULL_DOWN("Digital without pulldown", 0x800080);
+
+ private final String label;
+ private final int color;
+
+ PinType(String label, int color) {
+ this.label = label;
+ this.color = color;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public int getColor() {
+ return color;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/Soc.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/Soc.java
new file mode 100644
index 00000000..e0710bed
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/definition/Soc.java
@@ -0,0 +1,24 @@
+package com.pi4j.boardinfo.definition;
+
+public enum Soc {
+ BCM2710A1(InstructionSet.ARM_V8),
+ BCM2711(InstructionSet.ARM_V8),
+ BCM2711C0(InstructionSet.ARM_V8),
+ BCM2712(InstructionSet.ARM_V8),
+ BCM2835(InstructionSet.ARM_V6),
+ BCM2836(InstructionSet.ARM_V7),
+ BCM2837(InstructionSet.ARM_V8),
+ BCM2837B0(InstructionSet.ARM_V8),
+ RP2040(InstructionSet.ARM_V6_M),
+ UNKNOWN(InstructionSet.UNKNOWN);
+
+ private final InstructionSet instructionSet;
+
+ Soc(InstructionSet instructionSet) {
+ this.instructionSet = instructionSet;
+ }
+
+ public InstructionSet getInstructionSet() {
+ return instructionSet;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/model/BoardInfo.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/BoardInfo.java
new file mode 100644
index 00000000..2ec8e2dc
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/BoardInfo.java
@@ -0,0 +1,28 @@
+package com.pi4j.boardinfo.model;
+
+import com.pi4j.boardinfo.definition.BoardModel;
+
+public class BoardInfo {
+
+ private final BoardModel boardModel;
+ private final OperatingSystem operatingSystem;
+ private final JavaInfo javaInfo;
+
+ public BoardInfo(BoardModel boardModel, OperatingSystem operatingSystem, JavaInfo javaInfo) {
+ this.boardModel = boardModel;
+ this.operatingSystem = operatingSystem;
+ this.javaInfo = javaInfo;
+ }
+
+ public BoardModel getBoardModel() {
+ return boardModel;
+ }
+
+ public OperatingSystem getOperatingSystem() {
+ return operatingSystem;
+ }
+
+ public JavaInfo getJavaInfo() {
+ return javaInfo;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/model/HeaderPin.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/HeaderPin.java
new file mode 100644
index 00000000..34645a71
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/HeaderPin.java
@@ -0,0 +1,59 @@
+package com.pi4j.boardinfo.model;
+
+import com.pi4j.boardinfo.definition.PinFunction;
+import com.pi4j.boardinfo.definition.PinType;
+
+/**
+ * Describes a pin in the header.
+ */
+public class HeaderPin {
+ private final int pinNumber;
+ private final PinType pinType;
+ private final PinFunction pinFunction;
+ private final Integer bcmNumber;
+ private final Integer wiringPiNumber;
+ private final String name;
+ private final String remark;
+
+ public HeaderPin(int pinNumber, PinType pinType, String name) {
+ this(pinNumber, pinType, null, null, null, name, "");
+ }
+
+ public HeaderPin(int pinNumber, PinType pinType, PinFunction pinFunction, Integer bcmNumber, Integer wiringPiNumber, String name) {
+ this(pinNumber, pinType, pinFunction, bcmNumber, wiringPiNumber, name, "");
+ }
+
+ public HeaderPin(int pinNumber, PinType pinType, PinFunction pinFunction, Integer bcmNumber, Integer wiringPiNumber, String name, String remark) {
+ this.pinNumber = pinNumber;
+ this.pinType = pinType;
+ this.pinFunction = pinFunction;
+ this.bcmNumber = bcmNumber;
+ this.wiringPiNumber = wiringPiNumber;
+ this.name = name;
+ this.remark = remark;
+ }
+
+ public int getPinNumber() {
+ return pinNumber;
+ }
+
+ public PinType getPinType() {
+ return pinType;
+ }
+
+ public PinFunction getPinFunction() { return pinFunction; }
+
+ public Integer getBcmNumber() { return bcmNumber; }
+
+ public Integer getWiringPiNumber() {
+ return wiringPiNumber;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/model/JavaInfo.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/JavaInfo.java
new file mode 100644
index 00000000..b04a7e91
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/JavaInfo.java
@@ -0,0 +1,40 @@
+package com.pi4j.boardinfo.model;
+
+public class JavaInfo {
+
+ private final String version;
+ private final String runtime;
+ private final String vendor;
+ private final String vendorVersion;
+
+ public JavaInfo(String version, String runtime, String vendor, String vendorVersion) {
+ this.version = version;
+ this.runtime = runtime;
+ this.vendor = vendor;
+ this.vendorVersion = vendorVersion;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getRuntime() {
+ return runtime;
+ }
+
+ public String getVendor() {
+ return vendor;
+ }
+
+ public String getVendorVersion() {
+ return vendorVersion;
+ }
+
+ @Override
+ public String toString() {
+ return "Version: " + version
+ + ", runtime: " + runtime
+ + ", vendor: " + vendor
+ + ", vendor version: " + vendorVersion;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/model/OperatingSystem.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/OperatingSystem.java
new file mode 100644
index 00000000..1489168e
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/model/OperatingSystem.java
@@ -0,0 +1,33 @@
+package com.pi4j.boardinfo.model;
+
+public class OperatingSystem {
+
+ private final String name;
+ private final String version;
+ private final String architecture;
+
+ public OperatingSystem(String name, String version, String architecture) {
+ this.name = name;
+ this.version = version;
+ this.architecture = architecture;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getArchitecture() {
+ return architecture;
+ }
+
+ @Override
+ public String toString() {
+ return "Name: " + name
+ + ", version: " + version
+ + ", architecture: " + architecture;
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/boardinfo/util/BoardModelDetection.java b/pi4j-core/src/main/java/com/pi4j/boardinfo/util/BoardModelDetection.java
new file mode 100644
index 00000000..f249d7c5
--- /dev/null
+++ b/pi4j-core/src/main/java/com/pi4j/boardinfo/util/BoardModelDetection.java
@@ -0,0 +1,148 @@
+package com.pi4j.boardinfo.util;
+
+import com.pi4j.boardinfo.definition.BoardModel;
+import com.pi4j.boardinfo.model.BoardInfo;
+import com.pi4j.boardinfo.model.JavaInfo;
+import com.pi4j.boardinfo.model.OperatingSystem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.util.concurrent.TimeUnit;
+
+public class BoardModelDetection {
+
+ private static final Logger logger = LoggerFactory.getLogger(BoardModelDetection.class);
+
+ private BoardModelDetection() {
+ // Hide constructor
+ }
+
+ public static BoardInfo current() {
+ var os = new OperatingSystem(System.getProperty("os.name"),
+ System.getProperty("os.version"),
+ System.getProperty("os.arch"));
+ logger.info("Detected OS: {}", os);
+
+ var java = new JavaInfo(System.getProperty("java.version"),
+ System.getProperty("java.runtime.version"),
+ System.getProperty("java.vendor"),
+ System.getProperty("java.vendor.version"));
+ logger.info("Detected Java: {}", java);
+
+ // Example output: c03111
+ var boardVersionCode = getBoardVersionCode();
+ var boardModelByBoardCode = BoardModel.getByBoardCode(boardVersionCode);
+ if (boardModelByBoardCode != BoardModel.UNKNOWN) {
+ logger.info("Detected board type {} by code: {}", boardModelByBoardCode.name(), boardVersionCode);
+ return new BoardInfo(boardModelByBoardCode, os, java);
+ }
+
+ // Example output: Raspberry Pi 4 Model B Rev 1.1
+ var boardName = getBoardName();
+ boardModelByBoardCode = BoardModel.getByBoardName(boardName);
+ if (boardModelByBoardCode != BoardModel.UNKNOWN) {
+ logger.info("Detected board type {} by name: {}", boardModelByBoardCode.name(), boardName);
+ return new BoardInfo(boardModelByBoardCode, os, java);
+ }
+
+ // Maybe there are other ways how a board can be detected?
+ // If so, this method can be further extended...
+ logger.warn("Sorry, could not detect the board type");
+ return new BoardInfo(BoardModel.UNKNOWN, os, java);
+ }
+
+ public static String getBoardVersionCode() {
+ var output = getCommandOutput("cat /proc/cpuinfo | grep 'Revision' | awk '{print $3}'");
+ if (output.isSuccess()) {
+ return output.getOutputMessage();
+ }
+ logger.error("Could not get the board version code: {}", output.getErrorMessage());
+ return "";
+ }
+
+ public static String getBoardName() {
+ var output = getCommandOutput("cat /proc/device-tree/model");
+ if (output.isSuccess()) {
+ return output.getOutputMessage();
+ }
+ logger.error("Could not get the board name: {}", output.getErrorMessage());
+ return "";
+ }
+
+ private static class CommandResult {
+ private final boolean success;
+ private final String outputMessage;
+ private final String errorMessage;
+
+ public CommandResult(boolean success, String outputMessage, String errorMessage) {
+ this.success = success;
+ this.outputMessage = outputMessage;
+ this.errorMessage = errorMessage;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public String getOutputMessage() {
+ return outputMessage;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+ }
+
+ private static CommandResult getCommandOutput(String command) {
+ boolean finished = false;
+ String outputMessage = "";
+ String errorMessage = "";
+
+ ProcessBuilder builder = new ProcessBuilder();
+ builder.command("sh", "-c", command);
+
+ try {
+ Process process = builder.start();
+
+ OutputStream outputStream = process.getOutputStream();
+ InputStream inputStream = process.getInputStream();
+ InputStream errorStream = process.getErrorStream();
+
+ outputMessage = readStream(inputStream);
+ errorMessage = readStream(errorStream);
+
+ finished = process.waitFor(30, TimeUnit.SECONDS);
+ outputStream.flush();
+ outputStream.close();
+
+ if (!finished) {
+ process.destroyForcibly();
+ }
+ } catch (IOException ex) {
+ errorMessage = "IOException: " + ex.getMessage();
+ } catch (InterruptedException ex) {
+ errorMessage = "InterruptedException: " + ex.getMessage();
+ }
+
+ if (!finished || !errorMessage.isEmpty()) {
+ logger.error("Could not execute '{}' to detect the board model: {}", command, errorMessage);
+ return new CommandResult(false, outputMessage, errorMessage);
+ }
+
+ return new CommandResult(true, outputMessage, errorMessage);
+ }
+
+ private static String readStream(InputStream inputStream) {
+ StringBuilder rt = new StringBuilder();
+ try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ rt.append(line);
+ }
+ } catch (Exception ex) {
+ rt.append("ERROR: ").append(ex.getMessage());
+ }
+ return rt.toString();
+ }
+}
diff --git a/pi4j-core/src/main/java/com/pi4j/context/Context.java b/pi4j-core/src/main/java/com/pi4j/context/Context.java
index c5078779..7ee9b77a 100644
--- a/pi4j-core/src/main/java/com/pi4j/context/Context.java
+++ b/pi4j-core/src/main/java/com/pi4j/context/Context.java
@@ -25,6 +25,10 @@
* #L%
*/
+import com.pi4j.boardinfo.definition.BoardModel;
+import com.pi4j.boardinfo.model.BoardInfo;
+import com.pi4j.boardinfo.model.JavaInfo;
+import com.pi4j.boardinfo.model.OperatingSystem;
import com.pi4j.common.Describable;
import com.pi4j.common.Descriptor;
import com.pi4j.config.Config;
@@ -305,6 +309,18 @@ default T provider(IOType ioType) throws ProviderNotFoundEx
throw new ProviderNotFoundException(ioType);
}
+ // ------------------------------------------------------------------------
+ // BOARD INFO ACCESSOR METHODS
+ // ------------------------------------------------------------------------
+
+ /**
+ * Return the BoardInfo containing more info about the
+ * {@link BoardModel}, {@link OperatingSystem}, and {@link JavaInfo}.
+ *
+ * @return {@link BoardInfo}
+ */
+ BoardInfo boardInfo();
+
// ------------------------------------------------------------------------
// I/O INSTANCE ACCESSOR/CREATOR METHODS
// ------------------------------------------------------------------------
diff --git a/pi4j-core/src/main/java/com/pi4j/context/impl/DefaultContext.java b/pi4j-core/src/main/java/com/pi4j/context/impl/DefaultContext.java
index af74d71f..7f283338 100644
--- a/pi4j-core/src/main/java/com/pi4j/context/impl/DefaultContext.java
+++ b/pi4j-core/src/main/java/com/pi4j/context/impl/DefaultContext.java
@@ -25,6 +25,8 @@
* #L%
*/
+import com.pi4j.boardinfo.model.BoardInfo;
+import com.pi4j.boardinfo.util.BoardModelDetection;
import com.pi4j.context.Context;
import com.pi4j.context.ContextConfig;
import com.pi4j.context.ContextProperties;
@@ -62,6 +64,7 @@ public class DefaultContext implements Context {
private Providers providers = null;
private Platforms platforms = null;
private Registry registry = null;
+ private BoardInfo boardInfo = null;
/**
* newInstance.
@@ -78,7 +81,7 @@ private DefaultContext(ContextConfig config) {
logger.trace("new Pi4J runtime context initialized [config={}]", config);
// validate config object exists
- if(config == null){
+ if(config == null) {
throw new LifecycleException("Unable to create new Pi4J runtime context; missing (ContextConfig) config object.");
}
@@ -100,6 +103,12 @@ private DefaultContext(ContextConfig config) {
// create API accessible platforms instance (READ-ONLY ACCESS OBJECT)
this.platforms = DefaultPlatforms.newInstance(this.runtime.platforms());
+ // detect the board model
+ this.boardInfo = BoardModelDetection.current();
+ logger.info("Detected board model: {}", boardInfo.getBoardModel().getLabel());
+ logger.info("Running on: {}", boardInfo.getOperatingSystem());
+ logger.info("With Java version: {}", boardInfo.getJavaInfo());
+
// initialize runtime now
this.runtime.initialize();
@@ -128,6 +137,10 @@ public ContextProperties properties() {
@Override
public Platforms platforms() { return this.platforms; }
+ /** {@inheritDoc} */
+ @Override
+ public BoardInfo boardInfo() { return this.boardInfo; }
+
/** {@inheritDoc} */
@Override
public Future> submitTask(Runnable task) {
diff --git a/pi4j-core/src/main/java/module-info.java b/pi4j-core/src/main/java/module-info.java
index 738e308c..00706ec1 100644
--- a/pi4j-core/src/main/java/module-info.java
+++ b/pi4j-core/src/main/java/module-info.java
@@ -27,9 +27,11 @@
// depends on SLF4J
requires org.slf4j;
-
// exposed interfaces/classes
exports com.pi4j;
+ exports com.pi4j.boardinfo.definition;
+ exports com.pi4j.boardinfo.model;
+ exports com.pi4j.boardinfo.util;
exports com.pi4j.common;
exports com.pi4j.config;
exports com.pi4j.config.exception;
diff --git a/pi4j-core/test/java/com/pi4j/boardinfo/definition/BoardModelTest.java b/pi4j-core/test/java/com/pi4j/boardinfo/definition/BoardModelTest.java
new file mode 100644
index 00000000..9c99dcbf
--- /dev/null
+++ b/pi4j-core/test/java/com/pi4j/boardinfo/definition/BoardModelTest.java
@@ -0,0 +1,29 @@
+package com.pi4j.boardinfo.definition;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class BoardModelTest {
+
+ @Test
+ void testGetBoardModelByBoardCode() {
+ assertAll(
+ () -> assertEquals(BoardModel.MODEL_5_B, BoardModel.getByBoardCode("d04170")),
+ () -> assertEquals(BoardModel.MODEL_400, BoardModel.getByBoardCode("c03130")),
+ () -> assertEquals(BoardModel.MODEL_4_B, BoardModel.getByBoardCode("a03111")),
+ () -> assertEquals(BoardModel.MODEL_4_B, BoardModel.getByBoardCode("c03112")),
+ () -> assertEquals(BoardModel.ZERO_V2, BoardModel.getByBoardCode("902120")),
+ () -> assertEquals(BoardModel.MODEL_2_B_V1_2, BoardModel.getByBoardCode("a02042")),
+ () -> assertEquals(BoardModel.MODEL_2_B, BoardModel.getByBoardCode("a21041"))
+ );
+ }
+
+ @Test
+ void testGetBoardModelByBoardName() {
+ assertAll(
+ () -> assertEquals(BoardModel.MODEL_4_B, BoardModel.getByBoardName("Raspberry Pi 4 Model B Rev 1.1"))
+ );
+ }
+}
diff --git a/pi4j-core/test/java/com/pi4j/boardinfo/model/ModelTest.java b/pi4j-core/test/java/com/pi4j/boardinfo/model/ModelTest.java
new file mode 100644
index 00000000..1e6e53f9
--- /dev/null
+++ b/pi4j-core/test/java/com/pi4j/boardinfo/model/ModelTest.java
@@ -0,0 +1,20 @@
+package com.pi4j.boardinfo.model;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ModelTest {
+
+ @Test
+ void testStringOutputFromOperatingSystem() {
+ var os = new OperatingSystem("aaa", "bbb", "ccc");
+ assertEquals("Name: aaa, version: bbb, architecture: ccc", os.toString());
+ }
+
+ @Test
+ void testStringOutputFromJavaInfo() {
+ var java = new JavaInfo("aaa", "bbb", "ccc", "ddd");
+ assertEquals("Version: aaa, runtime: bbb, vendor: ccc, vendor version: ddd", java.toString());
+ }
+}
diff --git a/pi4j-core/test/java/com/pi4j/boardinfo/util/BoardModelDetectionTest.java b/pi4j-core/test/java/com/pi4j/boardinfo/util/BoardModelDetectionTest.java
new file mode 100644
index 00000000..b6108f67
--- /dev/null
+++ b/pi4j-core/test/java/com/pi4j/boardinfo/util/BoardModelDetectionTest.java
@@ -0,0 +1,28 @@
+package com.pi4j.boardinfo.util;
+
+import com.pi4j.boardinfo.definition.PiModel;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class BoardModelDetectionTest {
+
+ @Test
+ void testGetDetectedBoard() {
+ var detectedBoard = BoardModelDetection.current();
+
+ assertAll(
+ () -> assertEquals(detectedBoard.getOperatingSystem().getName(), System.getProperty("os.name")),
+ () -> assertEquals(detectedBoard.getOperatingSystem().getVersion(), System.getProperty("os.version")),
+ () -> assertEquals(detectedBoard.getOperatingSystem().getArchitecture(), System.getProperty("os.arch")),
+
+ () -> assertEquals(detectedBoard.getJavaInfo().getVersion(), System.getProperty("java.version")),
+ () -> assertEquals(detectedBoard.getJavaInfo().getRuntime(), System.getProperty("java.runtime.version")),
+ () -> assertEquals(detectedBoard.getJavaInfo().getVendor(), System.getProperty("java.vendor")),
+ () -> assertEquals(detectedBoard.getJavaInfo().getVendorVersion(), System.getProperty("java.vendor.version")),
+
+ () -> assertEquals(detectedBoard.getBoardModel().getModel(), PiModel.UNKNOWN) // Only valid on PC, macOS or build server
+ );
+ }
+}