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);
}
}
}
}
}
}
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;
}
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;
}
Aggregations