summaryrefslogtreecommitdiff
path: root/SmartDeviceLink/private/SDLVoiceCommandManager.m
diff options
context:
space:
mode:
Diffstat (limited to 'SmartDeviceLink/private/SDLVoiceCommandManager.m')
-rw-r--r--SmartDeviceLink/private/SDLVoiceCommandManager.m61
1 files changed, 55 insertions, 6 deletions
diff --git a/SmartDeviceLink/private/SDLVoiceCommandManager.m b/SmartDeviceLink/private/SDLVoiceCommandManager.m
index fc0048736..3d7f51dd5 100644
--- a/SmartDeviceLink/private/SDLVoiceCommandManager.m
+++ b/SmartDeviceLink/private/SDLVoiceCommandManager.m
@@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface SDLVoiceCommand()
@property (assign, nonatomic) UInt32 commandId;
+@property (copy, nonatomic, readwrite) NSArray<NSString *> *voiceCommands;
@end
@@ -40,6 +41,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (assign, nonatomic) UInt32 lastVoiceCommandId;
@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *currentVoiceCommands;
+@property (copy, nonatomic) NSArray<SDLVoiceCommand *> *originalVoiceCommands;
@end
@@ -104,20 +106,33 @@ UInt32 const VoiceCommandIdMin = 1900000000;
#pragma mark - Setters
- (void)setVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
- if (voiceCommands == self.voiceCommands) {
+ if (voiceCommands == self.originalVoiceCommands) {
SDLLogD(@"New voice commands are equal to the existing voice commands, skipping...");
return;
}
- // Set the ids
- [self sdl_updateIdsOnVoiceCommands:voiceCommands];
+ // Validate the voiceCommand's strings. In the rare case that the user has set only empty whitespace strings, abort the update operation.
+ NSArray<SDLVoiceCommand *> *validatedVoiceCommands = [self sdl_removeEmptyVoiceCommands:voiceCommands];
+ if (validatedVoiceCommands.count == 0 && voiceCommands.count > 0) {
+ SDLLogE(@"New voice commands are invalid, skipping...");
+ return;
+ }
+
+ // Check if all new voice commands have unique strings
+ if (![self.class sdl_arePendingVoiceCommandsUnique:voiceCommands]) {
+ SDLLogE(@"Not all voice command strings are unique across all voice commands. Voice commands will not be set.");
+ return;
+ }
// Set the new voice commands internally
- _voiceCommands = voiceCommands;
+ _originalVoiceCommands = voiceCommands;
+ _voiceCommands = validatedVoiceCommands;
+ // Set the ids
+ [self sdl_updateIdsOnVoiceCommands:self.voiceCommands];
// Create the operation, cancel previous ones and set this one
__weak typeof(self) weakSelf = self;
- SDLVoiceCommandUpdateOperation *updateOperation = [[SDLVoiceCommandUpdateOperation alloc] initWithConnectionManager:self.connectionManager pendingVoiceCommands:voiceCommands oldVoiceCommands:_currentVoiceCommands updateCompletionHandler:^(NSArray<SDLVoiceCommand *> *newCurrentVoiceCommands, NSError * _Nullable error) {
+ SDLVoiceCommandUpdateOperation *updateOperation = [[SDLVoiceCommandUpdateOperation alloc] initWithConnectionManager:self.connectionManager pendingVoiceCommands:self.voiceCommands oldVoiceCommands:_currentVoiceCommands updateCompletionHandler:^(NSArray<SDLVoiceCommand *> *newCurrentVoiceCommands, NSError * _Nullable error) {
weakSelf.currentVoiceCommands = newCurrentVoiceCommands;
[weakSelf sdl_updatePendingOperationsWithNewCurrentVoiceCommands:newCurrentVoiceCommands];
}];
@@ -146,12 +161,46 @@ UInt32 const VoiceCommandIdMin = 1900000000;
}
}
+/// Remove all voice command strings consisting of just whitespace characters as the module will reject any "empty" strings.
+/// @param voiceCommands - array of SDLVoiceCommands that are to be uploaded
+/// @return A list of voice commands with the empty voice commands removed
+- (NSArray<SDLVoiceCommand *> *)sdl_removeEmptyVoiceCommands:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ NSMutableArray<SDLVoiceCommand *> *validatedVoiceCommands = [[NSMutableArray alloc] init];
+ for (SDLVoiceCommand *voiceCommand in voiceCommands) {
+ NSMutableArray<NSString *> *voiceCommandStrings = [[NSMutableArray alloc] init];
+ for (NSString *voiceCommandString in voiceCommand.voiceCommands) {
+ NSString *trimmedString = [voiceCommandString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
+ // Updates voice command strings array by only adding ones that are not empty(e.g. "", " ", ...)
+ if (trimmedString.length > 0) {
+ [voiceCommandStrings addObject:voiceCommandString];
+ }
+ }
+ if (voiceCommandStrings.count > 0) {
+ voiceCommand.voiceCommands = voiceCommandStrings;
+ [validatedVoiceCommands addObject:voiceCommand];
+ }
+ }
+ return [validatedVoiceCommands copy];
+}
+
+/// Evaluate the pendingVoiceCommands to check if there is two or more voiceCommands with the same string
++ (BOOL)sdl_arePendingVoiceCommandsUnique:(NSArray<SDLVoiceCommand *> *)voiceCommands {
+ NSUInteger voiceCommandCount = 0;
+ NSMutableSet<NSString *> *voiceCommandsSet = [[NSMutableSet alloc] init];
+ for (SDLVoiceCommand *voiceCommand in voiceCommands) {
+ [voiceCommandsSet addObjectsFromArray:voiceCommand.voiceCommands];
+ voiceCommandCount += voiceCommand.voiceCommands.count;
+ }
+
+ return (voiceCommandsSet.count == voiceCommandCount);
+}
+
#pragma mark - Observers
- (void)sdl_commandNotification:(SDLRPCNotificationNotification *)notification {
SDLOnCommand *onCommand = (SDLOnCommand *)notification.notification;
- for (SDLVoiceCommand *voiceCommand in self.voiceCommands) {
+ for (SDLVoiceCommand *voiceCommand in self.currentVoiceCommands) {
if (onCommand.cmdID.unsignedIntegerValue != voiceCommand.commandId) { continue; }
voiceCommand.handler();