| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| package org.apache.plc4x.edgent; |
| |
| import com.google.gson.JsonObject; |
| import org.apache.edgent.function.Consumer; |
| import org.apache.edgent.function.Function; |
| import org.apache.edgent.function.Supplier; |
| import org.apache.plc4x.java.api.messages.PlcReadRequest; |
| import org.apache.plc4x.java.api.messages.PlcReadResponse; |
| import org.apache.plc4x.java.api.types.PlcClientDatatype; |
| |
| import java.time.LocalDate; |
| import java.time.LocalDateTime; |
| import java.time.LocalTime; |
| import java.util.List; |
| |
| /** |
| * WIP - A plc4x Apache Edgent {@link Supplier} and {@link Consumer} connector factory. |
| * <p> |
| * TODO: |
| * Are there cases where a single logical poll would want to read from |
| * multiple addrs/data (of different types) from a device and bundle the values |
| * into a single TStream tuple (e.g., a JsonObject)? How would we support that? |
| * Is there a similar need for writing to multiple addrs/values on a device? |
| * Ah... NOTE: plc4c "batch" requests are coming and will help to address this. |
| * |
| * <p> |
| * Sample use to read plc device data into an Edgent TStream: |
| * <pre>{@code |
| * PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://192.168.0.1/0/0"); |
| * plcConnection.connect(); |
| * PlcConnectionAdapter adapter = new PlcConnectionAdapter(plcConnection)); |
| * |
| * DirectProvider dp = new DirectProvider(); |
| * Topology top = dp.newTopology(); |
| * TStream<Byte> stream = top.poll(PlcFunctions.byteSupplier(adapter, "INPUTS/0", 1, TimeUnit.SECONDS); |
| * stream.print(); |
| * dp.submit(top); |
| * }</pre> |
| * <p> |
| * Sample use to write Edgent TStream data to a plc device: |
| * <pre>{@code |
| * PlcConnection plcConnection = new PlcDriverManager().getConnection("s7://192.168.0.1/0/0"); |
| * plcConnection.connect(); |
| * PlcConnectionAdapter adapter = new PlcConnectionAdapter(plcConnection); |
| * |
| * DirectProvider dp = new DirectProvider(); |
| * Topology top = dp.newTopology(); |
| * |
| * TStream<Byte> stream = ... |
| * stream.print(); |
| * TSink<Byte> sink = stream.sink(PlcFunctions.byteConsumer(adapter, "OUTPUTS/0")); |
| * |
| * dp.submit(top); |
| * }</pre> |
| */ |
| public class PlcFunctions { |
| |
| private PlcFunctions() { |
| throw new IllegalStateException("Utility class!"); |
| } |
| |
| /** |
| * Create a new Edgent {@link Supplier} to read data from the |
| * plc device. |
| * <p> |
| * Every call to the returned {@link Supplier#get()} reads a |
| * new data value from the plc device address and connection |
| * associated with the {@code PlcConnectionAdapter}. |
| * <p> |
| * |
| * @param adapter the @{link PlcConnectionAdapter} |
| * @param addressStr the plc device address string |
| * @return the {@code Supplier<T>} |
| * <p> |
| * // TODO: No need to import the Topology module for just this comment ... I think |
| * //see org.apache.edgent.topology.Topology#poll(Supplier, long, java.util.concurrent.TimeUnit) |
| */ |
| /*public static Supplier<byte[]> rawSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(byte[].class, PlcClientDatatype.RAW, addressStr); |
| } |
| |
| public static Supplier<Object> objectSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Object.class, PlcClientDatatype.OBJECT, addressStr); |
| }*/ |
| |
| public static Supplier<Boolean> booleanSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Boolean.class, PlcClientDatatype.BOOLEAN, addressStr); |
| } |
| |
| public static Supplier<List<Boolean>> booleanListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Boolean.class, PlcClientDatatype.BOOLEAN, addressStr); |
| } |
| |
| public static Supplier<Byte> byteSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Byte.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<List<Byte>> byteListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Byte.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<Short> shortSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Short.class, PlcClientDatatype.SHORT, addressStr); |
| } |
| |
| public static Supplier<List<Short>> shortListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Short.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<Integer> integerSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Integer.class, PlcClientDatatype.INTEGER, addressStr); |
| } |
| |
| public static Supplier<List<Integer>> integerListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Integer.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<Long> longSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Long.class, PlcClientDatatype.LONG, addressStr); |
| } |
| |
| public static Supplier<List<Long>> longListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Long.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<Float> floatSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Float.class, PlcClientDatatype.FLOAT, addressStr); |
| } |
| |
| public static Supplier<List<Float>> floatListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Float.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<Double> doubleSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(Double.class, PlcClientDatatype.DOUBLE, addressStr); |
| } |
| |
| public static Supplier<List<Double>> doubleListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(Double.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<String> stringSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(String.class, PlcClientDatatype.STRING, addressStr); |
| } |
| |
| public static Supplier<List<String>> stringListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(String.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<LocalTime> timeSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(LocalTime.class, PlcClientDatatype.TIME, addressStr); |
| } |
| |
| public static Supplier<List<LocalTime>> timeListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(LocalTime.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<LocalDate> dateSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(LocalDate.class, PlcClientDatatype.DATE, addressStr); |
| } |
| |
| public static Supplier<List<LocalDate>> dateListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(LocalDate.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<LocalDateTime> dateTimeSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newSupplier(LocalDateTime.class, PlcClientDatatype.DATE_TIME, addressStr); |
| } |
| |
| public static Supplier<List<LocalDateTime>> dateTimeListSupplier(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newListSupplier(LocalDateTime.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Supplier<PlcReadResponse> batchSupplier(PlcConnectionAdapter adapter, PlcReadRequest readRequest) { |
| return adapter.newSupplier(readRequest); |
| } |
| |
| /** |
| * Create a new Edgent {@link Consumer} to write data to the |
| * plc device. |
| * <p> |
| * Every call to the returned {@link Consumer#accept(Object)} |
| * writes the value to the the device address and connection |
| * associated with the {@code PlcConnectionAdapter}. |
| * |
| * @param adapter the @{link PlcConnectionAdapter} |
| * @param addressStr the plc device address string |
| * @return the {@code Consumer<T>} |
| * <p> |
| * // TODO: No need to import the Topology module for just this comment ... I think |
| * //see org.apache.edgent.topology.TStream#sink(Consumer) |
| */ |
| /*public static Consumer<byte[]> rawConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(byte[].class, PlcClientDatatype.RAW, addressStr); |
| } |
| |
| public static Consumer<Object> objectConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Object.class, PlcClientDatatype.OBJECT, addressStr); |
| }*/ |
| |
| public static Consumer<Boolean> booleanConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Boolean.class, PlcClientDatatype.BOOLEAN, addressStr); |
| } |
| |
| public static Consumer<Byte> byteConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Byte.class, PlcClientDatatype.BYTE, addressStr); |
| } |
| |
| public static Consumer<Short> shortConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Short.class, PlcClientDatatype.SHORT, addressStr); |
| } |
| |
| public static Consumer<Integer> integerConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Integer.class, PlcClientDatatype.INTEGER, addressStr); |
| } |
| |
| public static Consumer<Long> longConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Long.class, PlcClientDatatype.LONG, addressStr); |
| } |
| |
| public static Consumer<Float> floatConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Float.class, PlcClientDatatype.FLOAT, addressStr); |
| } |
| |
| public static Consumer<Double> doubleConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(Double.class, PlcClientDatatype.DOUBLE, addressStr); |
| } |
| |
| public static Consumer<String> stringConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(String.class, PlcClientDatatype.STRING, addressStr); |
| } |
| |
| public static Consumer<LocalTime> timeConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(LocalTime.class, PlcClientDatatype.TIME, addressStr); |
| } |
| |
| public static Consumer<LocalDate> dateConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(LocalDate.class, PlcClientDatatype.DATE, addressStr); |
| } |
| |
| public static Consumer<LocalDateTime> dateTimeConsumer(PlcConnectionAdapter adapter, String addressStr) { |
| return adapter.newJsonConsumer(LocalDateTime.class, PlcClientDatatype.DATE_TIME, addressStr); |
| } |
| |
| /** |
| * Create a new Edgent {@link Consumer} to write data to the |
| * plc device. |
| * <p> |
| * TODO: Is it premature to supply this? |
| * <p> |
| * Every call to the returned {@link Consumer#accept(Object)} |
| * <ul> |
| * <li>calls {@code addressFn} to get the device address string</li> |
| * <li>calls {@code valueFn} to get the {@code T} to write</li> |
| * <li>writes the value to the device address using the connection |
| * associated with the {@code PlcConnectionAdapter}.</li> |
| * </ul> |
| * |
| * @param adapter the @{link PlcConnectionAdapter} |
| * @param addressFn {@code Function} the returns a device {@code PlcField} from a {@code JsonObject} |
| * @param valueFn {@code Function} the returns a {@code Value} from a {@code JsonObject} |
| * @return the {@code Consumer<JsonObject>} |
| * <p> |
| * // TODO: No need to import the Topology module for just this comment ... I think |
| * //see org.apache.edgent.topology.TStream#sink(Consumer) |
| */ |
| public static Consumer<JsonObject> booleanConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Boolean> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.BOOLEAN, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> byteConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Byte> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.BYTE, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> shortConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Short> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.SHORT, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> integerConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Integer> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.INTEGER, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> longConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Long> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.LONG, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> floatConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Float> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.FLOAT, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> doubleConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, Double> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.DOUBLE, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> stringConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, String> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.STRING, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> timeConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, LocalTime> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.TIME, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> dateConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, LocalDate> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.DATE, addressFn, valueFn); |
| } |
| |
| public static Consumer<JsonObject> dateTimeConsumer(PlcConnectionAdapter adapter, Function<JsonObject, String> addressFn, Function<JsonObject, LocalDateTime> valueFn) { |
| return adapter.newJsonConsumer(PlcClientDatatype.DATE_TIME, addressFn, valueFn); |
| } |
| |
| } |