use of org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital in project plc4x by apache.
the class FirmataDriverContext method processSubscriptionRequest.
public List<FirmataMessage> processSubscriptionRequest(PlcSubscriptionRequest subscriptionRequest) {
// Convert the request into maps of bit sets.
Map<Integer, PinMode> requestDigitalFieldPinModes = new HashMap<>();
Map<Integer, PinMode> requestAnalogFieldPinModes = new HashMap<>();
for (String fieldName : subscriptionRequest.getFieldNames()) {
final PlcField field = subscriptionRequest.getField(fieldName);
DefaultPlcSubscriptionField subscriptionField = (DefaultPlcSubscriptionField) field;
if (subscriptionField.getPlcField() instanceof FirmataFieldDigital) {
FirmataFieldDigital fieldDigital = (FirmataFieldDigital) subscriptionField.getPlcField();
PinMode fieldPinMode = (fieldDigital.getPinMode() != null) ? fieldDigital.getPinMode() : PinMode.PinModeInput;
if (!(fieldPinMode.equals(PinMode.PinModeInput) || fieldPinMode.equals(PinMode.PinModePullup))) {
throw new PlcInvalidFieldException("Subscription field must be of type 'INPUT' (default) or 'PULLUP'");
}
for (int pin = fieldDigital.getAddress(); pin < fieldDigital.getAddress() + fieldDigital.getNumberOfElements(); pin++) {
requestDigitalFieldPinModes.put(pin, fieldPinMode);
}
} else if (subscriptionField.getPlcField() instanceof FirmataFieldAnalog) {
FirmataFieldAnalog fieldAnalog = (FirmataFieldAnalog) subscriptionField.getPlcField();
for (int pin = fieldAnalog.getAddress(); pin < fieldAnalog.getAddress() + fieldAnalog.getNumberOfElements(); pin++) {
requestAnalogFieldPinModes.put(pin, PinMode.PinModeInput);
}
} else {
throw new PlcRuntimeException("Unsupported field type " + field.getClass().getSimpleName());
}
}
// If a requested digital pin is already subscribed, blank this out
for (Map.Entry<Integer, PinMode> entry : requestDigitalFieldPinModes.entrySet()) {
int pin = entry.getKey();
PinMode pinMode = entry.getValue();
if (digitalPins.containsKey(pin)) {
if (!digitalPins.get(pin).equals(pinMode)) {
throw new PlcInvalidFieldException(String.format("Error setting digital pin to mode %s, pin is already set to mode %s", pinMode.toString(), digitalPins.get(pin).toString()));
} else {
requestDigitalFieldPinModes.remove(pin);
}
}
}
// If a requested analog pin is already subscribed, blank this out
for (Map.Entry<Integer, PinMode> entry : requestAnalogFieldPinModes.entrySet()) {
int pin = entry.getKey();
if (analogPins.containsKey(pin)) {
requestAnalogFieldPinModes.remove(pin);
}
}
// Remember the subscription itself.
subscriptions.add(subscriptionRequest);
// Create a list of messages that need to be sent to achieve the desired subscriptions.
List<FirmataMessage> messages = new LinkedList<>();
for (Map.Entry<Integer, PinMode> entry : requestDigitalFieldPinModes.entrySet()) {
int pin = entry.getKey();
PinMode pinMode = entry.getValue();
// Digital pins can be input and output, so first we have to set it to "input"
messages.add(new FirmataMessageCommand(new FirmataCommandSetPinMode((byte) pin, pinMode, false), false));
// And then tell the remote to send change of state information.
messages.add(new FirmataMessageSubscribeDigitalPinValue((byte) pin, true, false));
}
for (Map.Entry<Integer, PinMode> entry : requestAnalogFieldPinModes.entrySet()) {
int pin = entry.getKey();
// Tell the remote to send change of state information for this analog pin.
messages.add(new FirmataMessageSubscribeAnalogPinValue((byte) pin, true, false));
}
return messages;
}
use of org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital in project plc4x by apache.
the class FirmataProtocolLogic method publishDigitalEvents.
protected void publishDigitalEvents(BitSet changedBits, BitSet bitValues) {
// If nothing changed, no need to do anything.
if (changedBits.cardinality() == 0) {
return;
}
// Try sending the subscription event to all listeners.
for (Map.Entry<DefaultPlcConsumerRegistration, Consumer<PlcSubscriptionEvent>> entry : consumers.entrySet()) {
final DefaultPlcConsumerRegistration registration = entry.getKey();
final Consumer<PlcSubscriptionEvent> consumer = entry.getValue();
// Only if the current data point matches the subscription, publish the event to it.
for (PlcSubscriptionHandle handle : registration.getSubscriptionHandles()) {
if (handle instanceof FirmataSubscriptionHandle) {
FirmataSubscriptionHandle subscriptionHandle = (FirmataSubscriptionHandle) handle;
// (The bit subscribed to in this field actually changed).
if (subscriptionHandle.getField() instanceof FirmataFieldDigital) {
FirmataFieldDigital digitalField = (FirmataFieldDigital) subscriptionHandle.getField();
// send out an update event with all of its current values.
if (digitalField.getBitSet().intersects(changedBits)) {
List<PlcValue> values = new ArrayList<>(digitalField.getBitSet().cardinality());
for (int i = 0; i < digitalField.getBitSet().length(); i++) {
values.add(new PlcBOOL(bitValues.get(i)));
}
sendUpdateEvents(consumer, subscriptionHandle.getName(), values);
}
}
}
}
}
}
use of org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital in project plc4x by apache.
the class FirmataDriverContext method processWriteRequest.
public List<FirmataMessage> processWriteRequest(PlcWriteRequest writeRequest) {
List<FirmataMessage> messages = new LinkedList<>();
for (String fieldName : writeRequest.getFieldNames()) {
if (!(writeRequest.getField(fieldName) instanceof FirmataFieldDigital)) {
throw new PlcRuntimeException("Writing only supported for digital pins");
}
FirmataFieldDigital digitalField = (FirmataFieldDigital) writeRequest.getField(fieldName);
final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
if ((digitalField.getNumberOfElements() > 1) && plcValue.isList()) {
final PlcList plcList = (PlcList) plcValue;
if (plcList.getList().size() != digitalField.getNumberOfElements()) {
throw new PlcRuntimeException("Required " + digitalField.getNumberOfElements() + " but got " + plcList.getList().size());
}
}
for (int i = 0; i < digitalField.getNumberOfElements(); i++) {
int pin = digitalField.getAddress() + i;
if (!digitalPins.containsKey(pin)) {
digitalPins.put(pin, PinMode.PinModeOutput);
messages.add(new FirmataMessageCommand(new FirmataCommandSetPinMode((byte) pin, PinMode.PinModeOutput, false), false));
} else // Check that a requested output pin is currently not configured as 'input'.
if (!digitalPins.get(pin).equals(PinMode.PinModeOutput)) {
throw new PlcRuntimeException("Pin " + pin + " already configured as " + digitalPins.get(pin).name());
}
messages.add(new FirmataMessageCommand(new FirmataCommandSetDigitalPinValue((short) pin, plcValue.getIndex(i).getBoolean(), false), false));
}
}
return messages;
}
Aggregations