[tr064] Normalize numbers in phonebook entries (#9733)

* [tr064] Normalize numbers in phone book entries.

Phone book numbers and numbers to be looked up might be formatted
differently (real world example: '+49 (12345) 67890' vs. '01234567890'
(where the former is phonebook formatting and the latter is the format
transmitted by the avmfritz binding). Make sure such formatting
differences do not cause lookup mismatches.

Signed-off-by: Danny Baumann <dannybaumann@web.de>
pull/9748/head
maniac103 2021-01-07 17:38:47 +01:00 committed by GitHub
parent 93824b5091
commit d87c94d603
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 7 deletions

View File

@ -168,6 +168,7 @@ The default is to use all available phonebooks from the specified thing.
In case the format of the number in the phonebook and the format of the number from the channel are different (e.g. regarding country prefixes), the `matchCount` parameter can be used.
The configured `matchCount` is counted from the right end and denotes the number of matching characters needed to consider this number as matching.
A `matchCount` of `0` is considered as "match everything".
Matching is done on normalized versions of the numbers that have all characters except digits, '+' and '*' removed.
## Rule Action
@ -178,7 +179,8 @@ The phonebooks of a `fritzbox` thing can be used to lookup a number from rules v
`phonebook` and `matchCount` are optional parameters.
You can omit one or both of these parameters.
The configured `matchCount` is counted from the right end and denotes the number of matching characters needed to consider this number as matching.
A `matchCount` of `0` is considered as "match everything" and is used as default if no other value is given.
A `matchCount` of `0` is considered as "match everything" and is used as default if no other value is given.
As in the phonebook profile, matching is done on normalized versions of the numbers that have all characters except digits, '+' and '*' removed.
The return value is either the phonebook entry (if found) or the input number.
Example (use all phonebooks, match 5 digits from right):

View File

@ -31,7 +31,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.tr064.internal.dto.additions.NumberType;
import org.openhab.binding.tr064.internal.dto.additions.PhonebooksType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -73,7 +72,7 @@ public class Tr064PhonebookImpl implements Phonebook {
phonebook = phonebooksType.getPhonebook().getContact().stream().map(contact -> {
String contactName = contact.getPerson().getRealName();
return contact.getTelephony().getNumber().stream()
.collect(Collectors.toMap(NumberType::getValue, number -> contactName));
.collect(Collectors.toMap(number -> normalizeNumber(number.getValue()), number -> contactName));
}).collect(HashMap::new, HashMap::putAll, HashMap::putAll);
logger.debug("Downloaded phonebook {}: {}", phonebookName, phonebook);
} catch (JAXBException | InterruptedException | ExecutionException | TimeoutException e) {
@ -88,10 +87,11 @@ public class Tr064PhonebookImpl implements Phonebook {
@Override
public Optional<String> lookupNumber(String number, int matchCount) {
String matchString = matchCount > 0 && matchCount < number.length()
? number.substring(number.length() - matchCount)
: number;
logger.trace("matchString for '{}' is '{}'", number, matchString);
String normalized = normalizeNumber(number);
String matchString = matchCount > 0 && matchCount < normalized.length()
? normalized.substring(normalized.length() - matchCount)
: normalized;
logger.trace("Normalized '{}' to '{}', matchString is '{}'", number, normalized, matchString);
return matchString.isBlank() ? Optional.empty()
: phonebook.keySet().stream().filter(n -> n.endsWith(matchString)).findFirst().map(phonebook::get);
}
@ -100,4 +100,9 @@ public class Tr064PhonebookImpl implements Phonebook {
public String toString() {
return "Phonebook{" + "phonebookName='" + phonebookName + "', phonebook=" + phonebook + '}';
}
private String normalizeNumber(String number) {
// Naive normalization: remove all non-digit characters
return number.replaceAll("[^0-9]\\+\\*", "");
}
}