plc4x-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [incubator-plc4x] timbo2k commented on a change in pull request #46: PLC4X-88: Add Triggering to PLC Scraper
Date Wed, 06 Mar 2019 17:49:10 GMT
timbo2k commented on a change in pull request #46: PLC4X-88: Add Triggering to PLC Scraper
URL: https://github.com/apache/incubator-plc4x/pull/46#discussion_r263058508
 
 

 ##########
 File path: plc4j/utils/scraper/src/main/java/org/apache/plc4x/java/scraper/triggeredscraper/triggerhandler/TriggerConfiguration.java
 ##########
 @@ -0,0 +1,342 @@
+/*
+ * 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.java.scraper.triggeredscraper.triggerhandler;
+
+import org.apache.plc4x.java.api.exceptions.PlcInvalidFieldException;
+import org.apache.plc4x.java.s7.model.S7Field;
+import org.apache.plc4x.java.scraper.exception.ScraperException;
+import org.apache.plc4x.java.scraper.triggeredscraper.TriggeredScrapeJobImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * basic configuration for all available triggers and handling of regarding condition
+ */
+public class TriggerConfiguration{
+    private static final Logger logger = LoggerFactory.getLogger(TriggerConfiguration.class);
+
+    private static final String S_7_TRIGGER_VAR = "S7_TRIGGER_VAR";
+    private static final String SCHEDULED = "SCHEDULED";
+
+    private static final Pattern TRIGGER_STRATEGY_PATTERN =
+        Pattern.compile("\\((?<strategy>[A-Z_0-9]+),(?<scheduledInterval>\\d+)(,(\\((?<s7var>\\S+)\\))((?<comp>[!=<>]{1,2}))(\\((?<compVar>[a-z0-9.]+)\\)))?\\)");
+
+    private final TriggerType triggerType;
+    private final long scrapeInterval;
+    private final String s7triggerField;
+    private final String comparator;
+    private Comparators comparatorType;
+    private TriggeredScrapeJobImpl triggeredScrapeJobImpl;
+
+    private final Object compareValue;
+    private final S7Field s7Field;
+
+    /**
+     * default constructor when an S7Field should be used for triggering
+     * @param triggerType type of trigger from enum
+     * @param scrapeInterval scrape interval of triggered variable
+     * @param s7triggerField field that is conditional for trigger comparison
+     * @param comparator selected comparator
+     * @param compareValue selected ref-value that is comapred against
+     * @param triggeredScrapeJobImpl the job which is valid for the configuration
+     * @throws ScraperException when something goes wrong with configuration
+     */
+    public TriggerConfiguration(TriggerType triggerType, String scrapeInterval, String s7triggerField,
String comparator, String compareValue, TriggeredScrapeJobImpl triggeredScrapeJobImpl) throws
ScraperException {
+        this.triggerType = triggerType;
+        this.triggeredScrapeJobImpl = triggeredScrapeJobImpl;
+        this.scrapeInterval = parseScrapeInterval(scrapeInterval);
+
+        //test for valid field-connection string, on exception quit job and return message
to user
+        try {
+            this.s7Field = S7Field.of(s7triggerField);
+        }
+        catch (PlcInvalidFieldException e){
+            logger.debug(e.getMessage(),e);
+            String exceptionMessage = String.format("Invalid trigger Field for Job %s: %s",triggeredScrapeJobImpl.getJobName(),s7triggerField);
+            throw new ScraperException(exceptionMessage);
+        }
+        this.s7triggerField = s7triggerField;
+        this.comparator = comparator;
+
+        this.compareValue = convertCompareValue(compareValue);
+        detectComparatorType();
+        matchTypeAndComparator();
+
+    }
+
+    /**
+     * default constructor when scheduled trigger shall be performed
+     * @param triggerType type of trigger from enum
+     * @param scrapeInterval scrape interval of data from block
+     * @throws ScraperException when something goes wrong with configuration
+     */
+    public TriggerConfiguration(TriggerType triggerType, String scrapeInterval) throws ScraperException
{
+        this.triggerType = triggerType;
+        this.scrapeInterval = parseScrapeInterval(scrapeInterval);
+        this.s7triggerField = null;
+        this.comparator = null;
+        this.compareValue = null;
+        this.s7Field = null;
+        this.comparatorType = null;
+    }
+
+    /**
+     * parses String of scrape interval
+     * @param scrapeInterval string extracted from RegEx
+     * @return converted value
+     * @throws ScraperException if parsing could not be performed
+     */
+    private long parseScrapeInterval(String scrapeInterval) throws ScraperException {
+        try {
+            return Long.parseLong(scrapeInterval);
+        }
+        catch (Exception e){
+            handleException(e);
+            String exceptionMessage = String.format("No valid numeric for scrapeInterval
for Job %s: %s",triggeredScrapeJobImpl.getJobName(),scrapeInterval);
+            throw new ScraperException(exceptionMessage);
+        }
+    }
+
+    /**
+     * evaluates the trigger dependent of base type and converts acquired respectively ref-value
to the needed datatype
+     * @param value acquired value
+     * @return true when condition is matched, false otherwise
+     * @throws ScraperException when something goes wrong
+     */
+    boolean evaluateTrigger(Object value) throws ScraperException {
+        if(detectVariableType().equals(Boolean.class)){
+            boolean currentValue;
+            boolean refValue;
+            try{
+                currentValue = (boolean) value;
+                refValue = (boolean) compareValue;
+            }
+            catch (Exception e){
+                handleException(e);
+                return false;
+            }
+            if(this.comparatorType.equals(Comparators.EQUAL)){
+                return currentValue == refValue;
+            }
+            else {
+                return currentValue != refValue;
+            }
+        }
+        if(detectVariableType().equals(Double.class)) {
+            double currentValue;
+            double refValue;
+            try{
+                currentValue = (double) value;
+                refValue = (double) compareValue;
+            }
+            catch (Exception e){
+                handleException(e);
+                return false;
+            }
+
+            switch (this.comparatorType) {
+                case EQUAL:
+                    return currentValue == refValue;
+                case UNEQUAL:
+                    return currentValue != refValue;
+                case SMALLER:
+                    return currentValue < refValue;
+                case SMALLER_EQUAL:
+                    return currentValue <= refValue;
+                case GREATER:
+                    return currentValue > refValue;
+                case GREATER_EQUAL:
+                    return currentValue >= refValue;
+            }
+
+        }
+        //should not happen, as fallback return false which always implies that no data is
collected
+        return false;
+    }
+
+    /**
+     * convertes parsed comparator from regex to ComparatorType
+     * @throws ScraperException when no valid comparator has been used
+     */
+    private void detectComparatorType() throws ScraperException {
+        switch (this.comparator){
+            case "==":
+                this.comparatorType= Comparators.EQUAL;
+                break;
+            case "!=":
+                this.comparatorType= Comparators.UNEQUAL;
+                break;
+            case "<=":
+                this.comparatorType= Comparators.SMALLER_EQUAL;
+                break;
+            case "<":
+                this.comparatorType= Comparators.SMALLER;
+                break;
+            case ">=":
+                this.comparatorType= Comparators.GREATER_EQUAL;
+                break;
+            case ">":
+                this.comparatorType= Comparators.GREATER;
+                break;
+            default:
+                throw new ScraperException("Invalid comparator detected!");
+        }
+    }
+
+    /**
+     * matches data-type and comparator for a valid combination
+     * @throws ScraperException when invalid combination is detected
+     */
+    private void matchTypeAndComparator() throws ScraperException {
+        if(detectVariableType().equals(Boolean.class)
+            && !(this.comparatorType.equals(Comparators.EQUAL) || this.comparatorType.equals(Comparators.UNEQUAL))){
+            String exceptionMessage = String.format("Trigger-Data-Type (%s) and Comparator
(%s) do not match",this.s7Field.getDataType(),this.comparatorType);
+            throw new ScraperException(exceptionMessage);
+        }
+        //all other combinations are valid
+    }
+
+    /**
+     * defines the used base type for comparison
+     * @return the detected base type
+     * @throws ScraperException when an unsupported S7-Type is choosen,which is not (yet)
implemented for comparison
+     * ToDo check how to handle time-variables if needed
+     */
+    private Class detectVariableType() throws ScraperException {
+        switch (this.s7Field.getDataType()){
+            case BOOL:
+                return Boolean.class;
+            case INT:
+            case UINT:
+            case SINT:
+            case USINT:
+            case DINT:
+            case UDINT:
+            case LINT:
+            case ULINT:
+            case REAL:
+            case LREAL:
+                return Double.class;
+            default:
+                throw new ScraperException("Unsupported trigger data-type used: "+this.s7Field.getDataType());
+        }
+    }
+
+    /**
+     * parses the ref-value to a given value, as well as checking if ref-value matches to
the given data-type
+     * @param compareValue compare-value extracted by regex
+     * @return converted object to needed data-type
+     * @throws ScraperException when something does not match or parsing fails
+     */
+    private Object convertCompareValue(String compareValue) throws ScraperException {
+        if(detectVariableType().equals(Boolean.class)){
+            switch (compareValue){
+                case "1":
+                case "true":
+                    return true;
+                case "0":
+                case "false":
+                    return false;
+                default:
+                    String exceptionMessage = String.format("No valid compare Value at DataType
Boolean for trigger for Job %s: %s",triggeredScrapeJobImpl.getJobName(),compareValue);
+                    throw new ScraperException(exceptionMessage);
+            }
+        }
+        if(detectVariableType().equals(Double.class)){
+            try {
+                return Double.parseDouble(compareValue);
+            }
+            catch (Exception e){
+                String exceptionMessage = String.format("No valid compare Value at DataType
Numeric for trigger for Job %s: %s",triggeredScrapeJobImpl.getJobName(),compareValue);
+                throw new ScraperException(exceptionMessage);
+            }
+        }
+        String exceptionMessage = "Invalid Datatype detected ... should not happen and be
catched earlier - please report";
+        throw new ScraperException(exceptionMessage);
+    }
+
+    /**
+     * creates the TriggerConfiguration for a given ScrapeJob from triggerConfig-String
+     * @param jobStrategy config-string from file
+     * @param triggeredScrapeJob job belonging to the config
+     * @return created TriggerConfiguration
+     * @throws ScraperException when something goes wrong
+     */
+    public static TriggerConfiguration createConfiguration(String jobStrategy,TriggeredScrapeJobImpl
triggeredScrapeJob) throws ScraperException {
+        Matcher matcher = TRIGGER_STRATEGY_PATTERN.matcher(jobStrategy);
+
+        if(matcher.matches()){
+            String strat = matcher.group("strategy");
+            String scheduledMs = matcher.group("scheduledInterval");
+
+            logger.debug("Strategy: {}, scheduled ms: {}",strat,scheduledMs);
+
+            switch (strat){
+                case S_7_TRIGGER_VAR:
+                    String s7FieldString = matcher.group("s7var");
+                    String comparatorString = matcher.group("comp");
+                    String comparatorVariable = matcher.group("compVar");
+
+                    return new TriggerConfiguration(TriggerType.S7_TRIGGER_VAR,scheduledMs,s7FieldString,comparatorString,comparatorVariable,triggeredScrapeJob);
+                case SCHEDULED:
+                    return new TriggerConfiguration(TriggerType.SCHEDULED,scheduledMs);
+                default:
+                    throw new ScraperException("Unknown Trigger Strategy "+strat);
+            }
+
+
+        }
+        throw new ScraperException("Invalid trigger strategy string description: "+jobStrategy);
+    }
+
+    private void handleException(Exception e){
+        //push up if needed
+        logger.debug("Exception: ", e);
+    }
+
+    TriggerType getTriggerType() {
+        return triggerType;
+    }
+
+    public long getScrapeInterval() {
+        return scrapeInterval;
+    }
+
+    String getS7triggerField() {
+        return s7triggerField;
+    }
+
+    public enum  Comparators{
+        EQUAL,
+        UNEQUAL,
+        GREATER,
+        GREATER_EQUAL,
+        SMALLER,
+        SMALLER_EQUAL
+    }
+
+    public enum TriggerType {
 
 Review comment:
   good point ... i created issue https://issues.apache.org/jira/browse/PLC4X-89 for that

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message