Search in sources :

Example 1 with TelegramValue

use of org.openhab.binding.ebus.internal.configuration.TelegramValue in project openhab1-addons by openhab.

the class EBusConfigurationProvider method transformDataTypes.

/**
     * @param configurationEntry
     */
protected void transformDataTypes(TelegramConfiguration configurationEntry) {
    // Use filter property if set
    if (StringUtils.isNotEmpty(configurationEntry.getFilter())) {
        String filter = configurationEntry.getFilter();
        filter = P_PLACEHOLDER.matcher(filter).replaceAll("[0-9A-Z]{2}");
        logger.trace("Compile RegEx filter: {}", filter);
        configurationEntry.setFilterPattern(Pattern.compile(filter));
    } else {
        // Build filter string
        // Always ignore first two hex bytes
        String filter = "[0-9A-Z]{2} [0-9A-Z]{2}";
        // Add command to filter string
        if (StringUtils.isNotEmpty(configurationEntry.getCommand())) {
            filter += " " + configurationEntry.getCommand();
            filter += " [0-9A-Z]{2}";
        }
        // Add data to filter string
        if (StringUtils.isNotEmpty(configurationEntry.getData())) {
            Matcher matcher = P_BRACKETS_VALS.matcher(configurationEntry.getData());
            filter += " " + matcher.replaceAll("[0-9A-Z]{2}");
        }
        // Finally add .* to end with everything
        filter += " .*";
        logger.trace("Compile RegEx filter: {}", filter);
        configurationEntry.setFilterPattern(Pattern.compile(filter));
    }
    // remove brackets if used
    if (StringUtils.isNotEmpty(configurationEntry.getData())) {
        Matcher matcher = P_BRACKETS_CLEAN.matcher(configurationEntry.getData());
        configurationEntry.setData(matcher.replaceAll(""));
    }
    // compile scipt's if available also once
    if (configurationEntry.getValues() != null && !configurationEntry.getValues().isEmpty()) {
        Map<String, TelegramValue> values = configurationEntry.getValues();
        for (Entry<String, TelegramValue> entry : values.entrySet()) {
            if (StringUtils.isNotEmpty(entry.getValue().getScript())) {
                String script = entry.getValue().getScript();
                // check if engine is available
                if (StringUtils.isNotEmpty(script) && compEngine != null) {
                    try {
                        CompiledScript compile = compEngine.compile(script);
                        entry.getValue().setCsript(compile);
                    } catch (ScriptException e) {
                        logger.error("Error while compiling JavaScript!", e);
                    }
                }
            }
        }
    }
    // compile scipt's if available
    if (configurationEntry.getComputedValues() != null && !configurationEntry.getComputedValues().isEmpty()) {
        Map<String, TelegramValue> cvalues = configurationEntry.getComputedValues();
        for (Entry<String, TelegramValue> entry : cvalues.entrySet()) {
            if (StringUtils.isNotEmpty(entry.getValue().getScript())) {
                String script = entry.getValue().getScript();
                // check if engine is available
                if (StringUtils.isNotEmpty(script) && compEngine != null) {
                    try {
                        CompiledScript compile = compEngine.compile(script);
                        entry.getValue().setCsript(compile);
                    } catch (ScriptException e) {
                        logger.error("Error while compiling JavaScript!", e);
                    }
                }
            }
        }
    }
}
Also used : CompiledScript(javax.script.CompiledScript) ScriptException(javax.script.ScriptException) Matcher(java.util.regex.Matcher) TelegramValue(org.openhab.binding.ebus.internal.configuration.TelegramValue)

Example 2 with TelegramValue

use of org.openhab.binding.ebus.internal.configuration.TelegramValue in project openhab1-addons by openhab.

the class EBusTelegramParser method parse.

/**
     * Parses a valid eBus telegram and returns a map with key/values based on
     * configuration registry.
     * 
     * @param telegram The eBus telegram
     * @return A Map with parsed key/values
     */
public Map<String, Object> parse(EBusTelegram telegram) {
    // Check if a configuration provider is set
    if (configurationProvider == null) {
        logger.error("Configuration not loaded, can't parse telegram!");
        return null;
    }
    // Secure null check
    if (telegram == null) {
        return null;
    }
    // All parsed values
    final Map<String, Object> valueRegistry = new HashMap<String, Object>();
    // All parsed values with short keys, used for script evaluation
    final Map<String, Object> valueRegistryShortKeys = new HashMap<String, Object>();
    // Get as byte buffer
    final ByteBuffer byteBuffer = telegram.getBuffer();
    // Get hex string for debugging
    final String bufferString = EBusUtils.toHexDumpString(byteBuffer).toString();
    // queries the configuration provider for matching registry entries
    final List<TelegramConfiguration> matchedTelegramRegistry = configurationProvider.getCommandsByFilter(bufferString);
    loggerAnalyses.debug(bufferString);
    // No registry entries found, so this is a unknown telegram
    if (matchedTelegramRegistry.isEmpty()) {
        if (debugWriter != null && (debugWriteMode.contains("unknown") || debugWriteMode.contains("all"))) {
            debugWriter.writeTelegram(telegram, "<unknown>");
        }
        loggerAnalyses.debug("  >>> Unknown ----------------------------------------");
        if (loggerBrutforce.isTraceEnabled()) {
            loggerBrutforce.trace(bufferString);
            bruteforceEBusTelegram(telegram);
        }
        return null;
    }
    // loop thru all matching telegrams from registry
    for (TelegramConfiguration registryEntry : matchedTelegramRegistry) {
        int debugLevel = 0;
        // get id and class key if used
        String idKey = StringUtils.defaultString(registryEntry.getId());
        String classKey = StringUtils.defaultString(registryEntry.getClazz());
        // load debug level for this configuration entry if available
        if (registryEntry.getDebug() != null) {
            debugLevel = registryEntry.getDebug();
            if (debugWriter != null && debugWriteMode.contains("debug")) {
                debugWriter.writeTelegram(telegram, "DEBUG:" + registryEntry.getComment());
            }
        }
        if (debugWriter != null && debugWriteMode.equals("all")) {
            debugWriter.writeTelegram(telegram, registryEntry.getComment());
        }
        // get values block of configuration
        Map<String, TelegramValue> values = registryEntry.getValues();
        // debug
        loggerAnalyses.debug("  >>> {}", StringUtils.defaultIfEmpty(registryEntry.getComment(), "<No comment available>"));
        TelegramValue settings = null;
        // loop over all entries
        for (Entry<String, TelegramValue> entry : values.entrySet()) {
            String uniqueKey = (classKey != "" ? classKey + "." : "") + (idKey != "" ? idKey + "." : "") + entry.getKey();
            settings = entry.getValue();
            // Extract the value from byte buffer
            Object value = getValue(byteBuffer, entry.getValue());
            if (value == null) {
                // its okay if the value is null, maybe out of range min/max or replace value found
                logger.trace("Returned value is null, skip ...");
                continue;
            }
            // If compiled script available for this key, execute it now
            if (settings.getCsript() != null) {
                try {
                    // Add global variables thisValue and keyName to JavaScript context
                    HashMap<String, Object> bindings = new HashMap<String, Object>();
                    // short key
                    bindings.put(entry.getKey(), value);
                    // full key
                    bindings.put(uniqueKey, value);
                    // alias thisValue
                    bindings.put("thisValue", value);
                    // Evaluates script
                    value = evaluateScript(entry, bindings);
                } catch (ScriptException e) {
                    logger.error("Error on evaluating JavaScript!", e);
                    break;
                }
            }
            // debug
            String label = StringUtils.defaultString(settings.getLabel());
            String format = String.format("%-35s%-10s%s", uniqueKey, value, label);
            String alias = null;
            if (settings.getMapping() != null) {
                Map<String, String> mapping = settings.getMapping();
                alias = mapping.get(value.toString());
            }
            if (debugLevel >= 2) {
                loggerAnalyses.debug("    >>> " + format);
                if (alias != null) {
                    loggerAnalyses.debug("      >>> " + alias);
                }
            } else {
                loggerAnalyses.trace("    >>> " + format);
                if (alias != null) {
                    loggerAnalyses.trace("      >>> " + alias);
                }
            }
            // Add result to registry
            valueRegistry.put(uniqueKey, value);
            // Add result to temp. short key registry, used for scripts
            valueRegistryShortKeys.put(entry.getKey(), value);
            // also use class.id as key as shortcut if we have only one value
            if (values.size() == 1) {
                if (!StringUtils.isEmpty(classKey) && !StringUtils.isEmpty(idKey)) {
                    uniqueKey = classKey + "." + idKey;
                    valueRegistry.put(uniqueKey, value);
                }
            }
        }
        // computes values available? if not exit here
        if (registryEntry.getComputedValues() == null) {
            continue;
        }
        // post execute the computes_values block
        Map<String, TelegramValue> cvalues = registryEntry.getComputedValues();
        for (Entry<String, TelegramValue> entry : cvalues.entrySet()) {
            String uniqueKey = (classKey != "" ? classKey + "." : "") + (idKey != "" ? idKey + "." : "") + entry.getKey();
            // Add all values to script scope
            HashMap<String, Object> bindings = new HashMap<String, Object>();
            bindings.putAll(valueRegistryShortKeys);
            bindings.putAll(valueRegistry);
            Object value;
            try {
                // Evaluates script
                value = evaluateScript(entry, bindings);
                // Add result to registry
                valueRegistry.put(uniqueKey, value);
                if (debugLevel >= 2) {
                    String label = StringUtils.defaultString(settings.getLabel());
                    String format = String.format("%-35s%-10s%s", uniqueKey, value, label);
                    loggerAnalyses.debug("    >>> " + format);
                }
            } catch (ScriptException e) {
                logger.error("Error on evaluating JavaScript!", e);
            }
        }
    }
    return valueRegistry;
}
Also used : HashMap(java.util.HashMap) ByteBuffer(java.nio.ByteBuffer) TelegramValue(org.openhab.binding.ebus.internal.configuration.TelegramValue) ScriptException(javax.script.ScriptException) TelegramConfiguration(org.openhab.binding.ebus.internal.configuration.TelegramConfiguration)

Example 3 with TelegramValue

use of org.openhab.binding.ebus.internal.configuration.TelegramValue in project openhab1-addons by openhab.

the class EBusCommandProcessor method composeEBusTelegram.

/**
     * @param commandId
     * @param commandClass
     * @param dst
     * @param src
     * @param values
     * @return
     */
private byte[] composeEBusTelegram(String commandId, Byte dst, Byte src, Map<String, Object> values) {
    if (configurationProvider == null || configurationProvider.isEmpty()) {
        logger.debug("eBUS configuration provider not ready, can't get send data yet.");
        return null;
    }
    byte[] buffer = null;
    TelegramConfiguration commandCfg = configurationProvider.getCommandById(commandId);
    if (commandCfg != null) {
        if (dst == null && StringUtils.isNotEmpty(commandCfg.getDst())) {
            dst = EBusUtils.toByte(commandCfg.getDst());
        }
        if (dst == null) {
            logger.error("Unable to send command, destination address is missing. Set \"dst\" in item.cfg ...");
            return null;
        }
        byte[] bytesData = EBusUtils.toByteArray(commandCfg.getData());
        byte[] bytesCmd = EBusUtils.toByteArray(commandCfg.getCommand());
        if (values == null || values.isEmpty()) {
            logger.trace("No setter-values for eBUS telegram, used default data ...");
            buffer = new byte[bytesData.length + 6];
            buffer[0] = src;
            buffer[1] = dst;
            buffer[4] = (byte) bytesData.length;
            System.arraycopy(bytesCmd, 0, buffer, 2, bytesCmd.length);
            System.arraycopy(bytesData, 0, buffer, 5, bytesData.length);
            return buffer;
        }
        Map<String, TelegramValue> valuesConfig = commandCfg.getValues();
        if (valuesConfig == null || valuesConfig.isEmpty()) {
            logger.warn("No values configurated in json cfg ...");
            return null;
        }
        for (Entry<String, Object> entry : values.entrySet()) {
            TelegramValue valueEntry = valuesConfig.get(entry.getKey());
            if (valueEntry == null) {
                logger.warn("Unable to set value key \"{}\" in command \"{}.{}\", can't compose telegram ...", entry.getKey(), commandId);
                return null;
            }
            String type = valueEntry.getType();
            int pos = valueEntry.getPos() - 1;
            BigDecimal value = NumberUtils.toBigDecimal(entry.getValue());
            if (valueEntry.getMax() != null && value.compareTo(valueEntry.getMax()) == 1) {
                throw new RuntimeException("Value larger than allowed!");
            }
            if (valueEntry.getMin() != null && value.compareTo(valueEntry.getMin()) == -1) {
                throw new RuntimeException("Value smaller than allowed!");
            }
            if (value != null && valueEntry.getFactor() != null) {
                value = value.divide(valueEntry.getFactor());
            }
            byte[] encode = EBusCodecUtils.encode(type, value);
            if (encode.length == 0) {
                logger.warn("eBUS codec encoder returns empty buffer ...");
                return null;
            }
            // add computed single value to data buffer
            System.arraycopy(encode, 0, bytesData, pos - 5, encode.length);
        }
        for (Entry<String, TelegramValue> value : valuesConfig.entrySet()) {
            // check if the special value type for kromsch�der/wolf crc is availabel
            if (StringUtils.equals(value.getValue().getType(), "crc-kw")) {
                byte b = 0;
                int pos = value.getValue().getPos() - 6;
                for (int i = 0; i < bytesData.length; i++) {
                    // exclude crc pos
                    if (i != pos) {
                        b = EBusUtils.crc8(bytesData[i], b, (byte) 0x5C);
                    }
                }
                // set crc to specified position
                bytesData[pos] = b;
            }
        }
        bytesData = EBusUtils.encodeEBusData(bytesData);
        buffer = new byte[bytesData.length + 6];
        buffer[0] = src;
        buffer[1] = dst;
        buffer[4] = (byte) bytesData.length;
        System.arraycopy(bytesCmd, 0, buffer, 2, bytesCmd.length);
        System.arraycopy(bytesData, 0, buffer, 5, bytesData.length);
        return buffer;
    }
    return null;
}
Also used : TelegramConfiguration(org.openhab.binding.ebus.internal.configuration.TelegramConfiguration) TelegramValue(org.openhab.binding.ebus.internal.configuration.TelegramValue) BigDecimal(java.math.BigDecimal)

Aggregations

TelegramValue (org.openhab.binding.ebus.internal.configuration.TelegramValue)3 ScriptException (javax.script.ScriptException)2 TelegramConfiguration (org.openhab.binding.ebus.internal.configuration.TelegramConfiguration)2 BigDecimal (java.math.BigDecimal)1 ByteBuffer (java.nio.ByteBuffer)1 HashMap (java.util.HashMap)1 Matcher (java.util.regex.Matcher)1 CompiledScript (javax.script.CompiledScript)1