Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion kura-apps-target-definition/kura-apps.target
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
Contributors:
Eurotech

--><target name="kura-apps Target Definition" sequenceNumber="75">
-->
<target name="kura-apps Target Definition" sequenceNumber="75">
<locations>
<location includeDependencyDepth="direct" includeDependencyScopes="compile,test"
missingManifest="ignore" type="Maven">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=17))"
Service-Component: OSGI-INF/*.xml
Import-Package: org.eclipse.kura;version="[1.0,2.0)",
org.eclipse.kura.configuration;version="[1.0,2.0)",
org.eclipse.kura.gpio;version="1.0.0",
org.eclipse.kura.gpio;version="[1.2,2.0)",
org.osgi.framework;version="1.8.0",
org.osgi.service.component;version="1.2.0",
org.osgi.util.tracker;version="1.5.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2025 Eurotech and/or its affiliates and others
* Copyright (c) 2011, 2026 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -17,9 +17,9 @@

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
Expand All @@ -29,6 +29,8 @@
import org.eclipse.kura.configuration.ConfigurableComponent;
import org.eclipse.kura.gpio.GPIOService;
import org.eclipse.kura.gpio.KuraClosedDeviceException;
import org.eclipse.kura.gpio.KuraGPIODescription;
import org.eclipse.kura.gpio.KuraGPIODeviceException;
import org.eclipse.kura.gpio.KuraGPIODirection;
import org.eclipse.kura.gpio.KuraGPIOMode;
import org.eclipse.kura.gpio.KuraGPIOPin;
Expand Down Expand Up @@ -62,8 +64,10 @@
public class GpioComponent implements ConfigurableComponent {

/**
* Inner class defined to track the CloudServices as they get added, modified or removed.
* Specific methods can refresh the cloudService definition and setup again the Cloud Client.
* Inner class defined to track the CloudServices as they get added, modified or
* removed.
* Specific methods can refresh the cloudService definition and setup again the
* Cloud Client.
*
*/
private final class GPIOServiceTrackerCustomizer implements ServiceTrackerCustomizer<GPIOService, GPIOService> {
Expand Down Expand Up @@ -193,9 +197,10 @@ private void acquirePins() {
if (this.gpioService != null) {
logger.info("______________________________");
logger.info("Available GPIOs on the system:");
Map<Integer, String> gpios = this.gpioService.getAvailablePins();
for (Entry<Integer, String> e : gpios.entrySet()) {
logger.info("#{} - [{}]", e.getKey(), e.getValue());
List<KuraGPIODescription> gpioDescriptions = this.gpioService.getAvailablePinDescriptions();
for (KuraGPIODescription desc : gpioDescriptions) {
logger.info("GPIO Pin Description: {}", desc.getDisplayName());
logger.debug("GPIO Extended Pin Description: {}", desc.getProperties());
}
logger.info("______________________________");
getPins();
Expand All @@ -209,41 +214,81 @@ private void getPins() {
int[] triggers = this.gpioComponentOptions.getTriggers();
for (int i = 0; i < pins.length; i++) {
try {
logger.info("Acquiring GPIO pin {} with params:", pins[i]);
String pin = pins[i];
logger.info("Acquiring GPIO pin {} with params:", pin);
logger.info(" Direction....: {}", directions[i]);
logger.info(" Mode.........: {}", modes[i]);
logger.info(" Trigger......: {}", triggers[i]);
KuraGPIOPin p = getPin(pins[i], getPinDirection(directions[i]), getPinMode(modes[i]),
List<KuraGPIOPin> acquiredPins = getPins(pin, getPinDirection(directions[i]), getPinMode(modes[i]),
getPinTrigger(triggers[i]));
if (p != null) {
p.open();
logger.info("GPIO pin {} acquired", pins[i]);
if (p.getDirection() == KuraGPIODirection.OUTPUT) {
acquiredOutputPins.add(p);
} else {
acquiredInputPins.add(p);
acquiredPins.forEach(p -> {
try {
p.open();
logger.info("GPIO pin {} acquired", pin);
if (p.getDirection() == KuraGPIODirection.OUTPUT) {
acquiredOutputPins.add(p);
} else {
acquiredInputPins.add(p);
}
} catch (IOException | KuraGPIODeviceException | KuraUnavailableDeviceException e) {
logger.error("I/O Error occurred!", e);
}
} else {
logger.info("GPIO pin {} not found", pins[i]);
}
} catch (IOException e) {
logger.error("I/O Error occurred!", e);
});
} catch (Exception e) {
logger.error("got errror", e);
logger.error("got error", e);
}
}
}

private KuraGPIOPin getPin(String resource, KuraGPIODirection pinDirection, KuraGPIOMode pinMode,
private List<KuraGPIOPin> getPins(String resource, KuraGPIODirection pinDirection, KuraGPIOMode pinMode,
KuraGPIOTrigger pinTrigger) {
KuraGPIOPin pin = null;
List<KuraGPIOPin> pins = new ArrayList<>();
// Resource can be terminal number, pin name or in the format
// pinName:controller:line.
// i.e. "1024" or "GPIO1_24" or "PIN:1:24"
// In the latter case, omitting a field or setting to * means all, i.e. ":1:24"
// or "PIN:*:24" or "PIN:1:"
String[] parts = resource.split(":");
try {
int terminal = Integer.parseInt(resource);
if (terminal > 0 && terminal < 1255) {
pin = this.gpioService.getPinByTerminal(Integer.parseInt(resource), pinDirection, pinMode, pinTrigger);
switch (parts.length) {
case 1:
KuraGPIOPin pin = getPinByNameOrTerminal(parts, pinDirection, pinMode, pinTrigger);
if (pin != null) {
pins.add(pin);
}
break;
case 3:
Map<String, String> pinDescription = new HashMap<>();
if (!parts[0].trim().isEmpty() && !parts[0].trim().equals("*")) {
pinDescription.put("name", parts[0].trim());
}
if (!parts[1].trim().isEmpty() && !parts[1].trim().equals("*")) {
pinDescription.put("controller", parts[1].trim());
}
if (!parts[2].trim().isEmpty() && !parts[2].trim().equals("*")) {
pinDescription.put("line", parts[2].trim());
}
pins = this.gpioService.getPins(pinDescription, pinDirection, pinMode,
pinTrigger);
break;
default:
logger.error("Invalid GPIO pin resource format: {}", resource);
break;
}
} catch (IllegalArgumentException e) {
logger.error("Invalid GPIO pin parameters!", e);
}
return pins;
}

private KuraGPIOPin getPinByNameOrTerminal(String[] parts, KuraGPIODirection pinDirection, KuraGPIOMode pinMode,
KuraGPIOTrigger pinTrigger) {
KuraGPIOPin pin = null;
try {
int terminal = Integer.parseInt(parts[0].trim());
pin = this.gpioService.getPinByTerminal(terminal, pinDirection, pinMode, pinTrigger);
} catch (NumberFormatException e) {
pin = this.gpioService.getPinByName(resource, pinDirection, pinMode, pinTrigger);
pin = this.gpioService.getPinByName(parts[0].trim(), pinDirection, pinMode, pinTrigger);
}
return pin;
}
Expand Down Expand Up @@ -320,42 +365,42 @@ private void releasePins() {

private KuraGPIODirection getPinDirection(int direction) {
switch (direction) {
case 0, 2:
return KuraGPIODirection.INPUT;
case 1, 3:
return KuraGPIODirection.OUTPUT;
default:
return KuraGPIODirection.OUTPUT;
case 0, 2:
return KuraGPIODirection.INPUT;
case 1, 3:
return KuraGPIODirection.OUTPUT;
default:
return KuraGPIODirection.OUTPUT;
}
}

private KuraGPIOMode getPinMode(int mode) {
switch (mode) {
case 2:
return KuraGPIOMode.INPUT_PULL_DOWN;
case 1:
return KuraGPIOMode.INPUT_PULL_UP;
case 8:
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
case 4:
return KuraGPIOMode.OUTPUT_PUSH_PULL;
default:
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
case 2:
return KuraGPIOMode.INPUT_PULL_DOWN;
case 1:
return KuraGPIOMode.INPUT_PULL_UP;
case 8:
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
case 4:
return KuraGPIOMode.OUTPUT_PUSH_PULL;
default:
return KuraGPIOMode.OUTPUT_OPEN_DRAIN;
}
}

private KuraGPIOTrigger getPinTrigger(int trigger) {
switch (trigger) {
case 0:
return KuraGPIOTrigger.NONE;
case 2:
return KuraGPIOTrigger.RAISING_EDGE;
case 3:
return KuraGPIOTrigger.BOTH_EDGES;
case 1:
return KuraGPIOTrigger.FALLING_EDGE;
default:
return KuraGPIOTrigger.NONE;
case 0:
return KuraGPIOTrigger.NONE;
case 2:
return KuraGPIOTrigger.RAISING_EDGE;
case 3:
return KuraGPIOTrigger.BOTH_EDGES;
case 1:
return KuraGPIOTrigger.FALLING_EDGE;
default:
return KuraGPIOTrigger.NONE;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2025 Eurotech and/or its affiliates and others
* Copyright (c) 2025, 2026 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
Expand All @@ -20,75 +20,72 @@

@SuppressWarnings("checkstyle:MethodName")
@ObjectClassDefinition( //
id = "org.eclipse.kura.example.gpio.GpioComponent", //
name = "GPIO Configuration", //
description = "Example of a GPIO Configuring Application." //
id = "org.eclipse.kura.example.gpio.GpioComponent", //
name = "GPIO Configuration", //
description = "Example of a GPIO Configuring Application." //

)
@ComponentPropertyType
public @interface GpioComponentOCD {

@AttributeDefinition(name = "Gpio Service Pid", //
description = "The Kura GPIO service to be used to interact with gpios.", //
required = true //
// <Icon resource="http://s3.amazonaws.com/kura-resources/application/icon/applications-other.png" size="32"/>
)
String gpio_service_pid() default "org.eclipse.kura.gpio.GPIOService";
@AttributeDefinition(name = "Gpio Service Pid", //
description = "The Kura GPIO service to be used to interact with gpios.", //
required = true //
)
String gpio_service_pid() default "org.eclipse.kura.gpio.GPIOService";

@AttributeDefinition(name = "Gpio Input Read Mode", //
description = "Specifies how input pin value is obtained. If set to PIN_STATUS_LISTENER, the pin value will be printed on the log on change, if set to POLLING, the pin value will be readed and printed on the log periodically.", //
required = true, //
options = { //
@Option(label = "PIN_STATUS_LISTENER", value = "PIN_STATUS_LISTENER"), //
@Option(label = "POLLING", value = "POLLING") //
})
String gpio_input_read_mode() default "PIN_STATUS_LISTENER";
@AttributeDefinition(name = "Gpio Input Read Mode", //
description = "Specifies how input pin value is obtained. If set to PIN_STATUS_LISTENER, the pin value will be printed on the log on change, if set to POLLING, the pin value will be readed and printed on the log periodically.", //
required = true, //
options = { //
@Option(label = "PIN_STATUS_LISTENER", value = "PIN_STATUS_LISTENER"), //
@Option(label = "POLLING", value = "POLLING") //
})
String gpio_input_read_mode() default "PIN_STATUS_LISTENER";

@AttributeDefinition(name = "Gpio Pins", //
description = "List of GPIO pins expressed as pin number or pin name (i.e. DOUT1, DIN1, ...).", //
required = false, //
cardinality = 5 //
)
String[] gpio_pins() default {};
@AttributeDefinition(name = "Gpio Pins", //
description = "List of GPIO pins expressed as pin number (i.e. 1022), pin name (i.e. DOUT1, DIN1, ...) or name:controller:line (i.e. GPIO1:0:24). " //
+ "In the latter case, omitting a field or setting to * means all, i.e. \":1:24\" or \"PIN:*:24\" or \"PIN:1:\"", //
required = false, //
cardinality = 5 //
)
String[] gpio_pins() default {};

@AttributeDefinition(name = "Gpio Directions", //
description = "Pin directions", //
required = false, //
cardinality = 5, //
options = { //
@Option(label = "Only input", value = "0"), //
@Option(label = "Only output", value = "1"), //
@Option(label = "Both, init input", value = "2"), //
@Option(label = "Both, init output", value = "3") //
})
int[] gpio_directions() default { 3, 3, 3, 3, 3 };
@AttributeDefinition(name = "Gpio Directions", //
description = "Pin directions", //
required = false, //
cardinality = 5, //
options = { //
@Option(label = "Only input", value = "0"), //
@Option(label = "Only output", value = "1"), //
@Option(label = "Both, init input", value = "2"), //
@Option(label = "Both, init output", value = "3") //
})
int[] gpio_directions() default { 3, 3, 3, 3, 3 };

@AttributeDefinition(name = "Gpio Modes", //
description = "Pin working mode", //
required = false, //
cardinality = 5, //
options = { //
@Option(label = "Default", value = "-1"), //
@Option(label = "Input with Pull Down", value = "2"), //
@Option(label = "Input with Pull Up", value = "1"), //
@Option(label = "Open Drain Output", value = "8"), //
@Option(label = "Push-Pull Output", value = "4") //
})
int[] gpio_modes() default { -1, -1, -1, -1, -1 };
@AttributeDefinition(name = "Gpio Modes", //
description = "Pin working mode", //
required = false, //
cardinality = 5, //
options = { //
@Option(label = "Default", value = "-1"), //
@Option(label = "Input with Pull Down", value = "2"), //
@Option(label = "Input with Pull Up", value = "1"), //
@Option(label = "Open Drain Output", value = "8"), //
@Option(label = "Push-Pull Output", value = "4") //
})
int[] gpio_modes() default { -1, -1, -1, -1, -1 };

@AttributeDefinition(name = "Gpio Triggers", //
description = "Input triggering mode", //
required = false, //
cardinality = 5, //
options = { //
@Option(label = "Default", value = "-1"), //
@Option(label = "No trigger", value = "0"), //
@Option(label = "Rising edge", value = "2"), //
@Option(label = "Both edges", value = "3"), //
@Option(label = "Falling edge", value = "1") //
// <Option label="High level" value="4"/>
// <Option label="Low level" value="5"/>
// <Option label="Both levels" value="6"/>
})
int[] gpio_triggers() default { -1, -1, -1, -1, -1 };
@AttributeDefinition(name = "Gpio Triggers", //
description = "Input triggering mode", //
required = false, //
cardinality = 5, //
options = { //
@Option(label = "Default", value = "-1"), //
@Option(label = "No trigger", value = "0"), //
@Option(label = "Rising edge", value = "2"), //
@Option(label = "Both edges", value = "3"), //
@Option(label = "Falling edge", value = "1") //
})
int[] gpio_triggers() default { -1, -1, -1, -1, -1 };
}