126 lines
3.8 KiB
Java
126 lines
3.8 KiB
Java
package li.strolch.plc.core.hw.gpio;
|
|
|
|
import static java.util.stream.Collectors.joining;
|
|
import static li.strolch.plc.model.PlcConstants.PARAM_SIMULATED;
|
|
import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import com.pi4j.io.gpio.*;
|
|
import li.strolch.plc.core.hw.Plc;
|
|
import li.strolch.plc.core.hw.connections.SimplePlcConnection;
|
|
|
|
public class RaspiBcmGpioOutputConnection extends SimplePlcConnection {
|
|
|
|
private boolean verbose;
|
|
private List<Integer> outputBcmAddresses;
|
|
private Map<String, Pin> pinsByAddress;
|
|
private Map<String, GpioPinDigitalOutput> gpioPinsByAddress;
|
|
private boolean inverted;
|
|
|
|
public RaspiBcmGpioOutputConnection(Plc plc, String id) {
|
|
super(plc, id);
|
|
}
|
|
|
|
@Override
|
|
public void initialize(Map<String, Object> parameters) {
|
|
this.simulated = parameters.containsKey(PARAM_SIMULATED) && (boolean) parameters.get(PARAM_SIMULATED);
|
|
|
|
@SuppressWarnings("unchecked")
|
|
List<Integer> bcmOutputPins = (List<Integer>) parameters.get("bcmOutputPins");
|
|
this.outputBcmAddresses = bcmOutputPins;
|
|
|
|
this.pinsByAddress = new HashMap<>();
|
|
for (Integer address : this.outputBcmAddresses) {
|
|
Pin pin = RaspiBcmPin.getPinByAddress(address);
|
|
if (pin == null)
|
|
throw new IllegalArgumentException("RaspiBcmPin " + address + " does not exist!");
|
|
String key = this.id + "." + address;
|
|
this.pinsByAddress.put(key, pin);
|
|
logger.info("Registered address " + key + " for RaspiBcmPin " + pin);
|
|
}
|
|
|
|
this.verbose = parameters.containsKey("verbose") && (Boolean) parameters.get("verbose");
|
|
this.inverted = parameters.containsKey("inverted") && (boolean) parameters.get("inverted");
|
|
logger.info(
|
|
"Configured Raspi BCM GPIO Output for Pins " + this.outputBcmAddresses.stream().map(Object::toString)
|
|
.collect(joining(", ")));
|
|
}
|
|
|
|
@Override
|
|
public boolean connect() {
|
|
if (this.simulated) {
|
|
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
|
|
return super.connect();
|
|
}
|
|
|
|
try {
|
|
GpioController gpioController = PlcGpioController.getInstance();
|
|
|
|
this.gpioPinsByAddress = new HashMap<>();
|
|
for (String address : this.pinsByAddress.keySet()) {
|
|
Pin pin = this.pinsByAddress.get(address);
|
|
GpioPinDigitalOutput outputPin = gpioController.provisionDigitalOutputPin(pin);
|
|
this.gpioPinsByAddress.put(address, outputPin);
|
|
logger.info("Provisioned output pin " + outputPin + " for address " + address);
|
|
}
|
|
|
|
return super.connect();
|
|
|
|
} catch (Throwable e) {
|
|
handleBrokenConnection("Failed to connect to GpioController: " + getExceptionMessageWithCauses(e), e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void disconnect() {
|
|
if (this.simulated) {
|
|
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
|
|
super.disconnect();
|
|
return;
|
|
}
|
|
|
|
try {
|
|
GpioController gpioController = PlcGpioController.getInstance();
|
|
for (GpioPinDigitalOutput outputPin : this.gpioPinsByAddress.values()) {
|
|
gpioController.unprovisionPin(outputPin);
|
|
}
|
|
this.gpioPinsByAddress.clear();
|
|
} catch (Error e) {
|
|
logger.error("Failed to disconnect " + this.id, e);
|
|
}
|
|
|
|
super.disconnect();
|
|
}
|
|
|
|
@Override
|
|
public void send(String address, Object value) {
|
|
if (this.simulated) {
|
|
logger.warn(this.id + ": Running SIMULATED, NOT CONNECTING!");
|
|
return;
|
|
}
|
|
|
|
boolean high = (boolean) value;
|
|
if (this.inverted)
|
|
high = !high;
|
|
|
|
GpioPinDigitalOutput outputPin = this.gpioPinsByAddress.get(address);
|
|
if (outputPin == null)
|
|
throw new IllegalArgumentException("Output pin with address " + address + " does not exist!");
|
|
|
|
PinState newState = high ? PinState.HIGH : PinState.LOW;
|
|
if (this.verbose)
|
|
logger.info("Setting pin " + outputPin + " to new state " + newState);
|
|
outputPin.setState(newState);
|
|
}
|
|
|
|
@Override
|
|
public Set<String> getAddresses() {
|
|
return this.pinsByAddress.keySet();
|
|
}
|
|
}
|