Search in sources :

Example 1 with FirmataFieldDigital

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;
}
Also used : PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcField(org.apache.plc4x.java.api.model.PlcField) DefaultPlcSubscriptionField(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField) PlcInvalidFieldException(org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException) FirmataFieldDigital(org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital) FirmataFieldAnalog(org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldAnalog)

Example 2 with FirmataFieldDigital

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);
                    }
                }
            }
        }
    }
}
Also used : DefaultPlcConsumerRegistration(org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration) PlcBOOL(org.apache.plc4x.java.spi.values.PlcBOOL) PlcSubscriptionHandle(org.apache.plc4x.java.api.model.PlcSubscriptionHandle) FirmataSubscriptionHandle(org.apache.plc4x.java.firmata.readwrite.model.FirmataSubscriptionHandle) Consumer(java.util.function.Consumer) FirmataFieldDigital(org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 3 with FirmataFieldDigital

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;
}
Also used : PlcList(org.apache.plc4x.java.spi.values.PlcList) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcValue(org.apache.plc4x.java.api.value.PlcValue) FirmataFieldDigital(org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital)

Aggregations

FirmataFieldDigital (org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldDigital)3 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Consumer (java.util.function.Consumer)1 PlcInvalidFieldException (org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException)1 PlcField (org.apache.plc4x.java.api.model.PlcField)1 PlcSubscriptionHandle (org.apache.plc4x.java.api.model.PlcSubscriptionHandle)1 PlcValue (org.apache.plc4x.java.api.value.PlcValue)1 FirmataFieldAnalog (org.apache.plc4x.java.firmata.readwrite.field.FirmataFieldAnalog)1 FirmataSubscriptionHandle (org.apache.plc4x.java.firmata.readwrite.model.FirmataSubscriptionHandle)1 DefaultPlcConsumerRegistration (org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration)1 DefaultPlcSubscriptionField (org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField)1 PlcBOOL (org.apache.plc4x.java.spi.values.PlcBOOL)1 PlcList (org.apache.plc4x.java.spi.values.PlcList)1