diff --git a/smartapps/smartthings/ubi.src/ubi.groovy b/smartapps/smartthings/ubi.src/ubi.groovy index a00f5ab..6e8d357 100644 --- a/smartapps/smartthings/ubi.src/ubi.groovy +++ b/smartapps/smartthings/ubi.src/ubi.groovy @@ -107,8 +107,8 @@ mappings { path("/locks") { action: [ GET: "listLocks", - PUT: "updateLock", - POST: "updateLock" + PUT: "updateLocks", + POST: "updateLocks" ] } path("/locks/:id") { @@ -442,31 +442,87 @@ def executePhrase() { } private void updateAll(devices) { + def type = params.param1 def command = request.JSON?.command - if (command) - { - command = command.toLowerCase() - devices."$command"() + if (!devices) { + httpError(404, "Devices not found") + } + if (command){ + devices.each { device -> + executeCommand(device, type, command) + } } } private void update(devices) { log.debug "update, request: ${request.JSON}, params: ${params}, devices: $devices.id" - //def command = request.JSON?.command - def command = params.command - if (command) - { - command = command.toLowerCase() - def device = devices.find { it.id == params.id } - if (!device) - { + def type = params.param1 + def command = request.JSON?.command + def device = devices?.find { it.id == params.id } + + if (!device) { httpError(404, "Device not found") - } - else - { - device."$command"() - } } + + if (command) { + executeCommand(device, type, command) + } +} + +/** + * Validating the command passed by the user based on capability. + * @return boolean + */ +def validateCommand(device, deviceType, command) { + def capabilityCommands = getDeviceCapabilityCommands(device.capabilities) + def currentDeviceCapability = getCapabilityName(deviceType) + if (capabilityCommands[currentDeviceCapability]) { + return command in capabilityCommands[currentDeviceCapability] ? true : false + } else { + // Handling other device types here, which don't accept commands + httpError(400, "Bad request.") + } +} + +/** + * Need to get the attribute name to do the lookup. Only + * doing it for the device types which accept commands + * @return attribute name of the device type + */ +def getCapabilityName(type) { + switch(type) { + case "switches": + return "Switch" + case "locks": + return "Lock" + default: + return type + } +} + +/** + * Constructing the map over here of + * supported commands by device capability + * @return a map of device capability -> supported commands + */ +def getDeviceCapabilityCommands(deviceCapabilities) { + def map = [:] + deviceCapabilities.collect { + map[it.name] = it.commands.collect{ it.name.toString() } + } + return map +} + +/** + * Validates and executes the command + * on the device or devices + */ +def executeCommand(device, type, command) { + if (validateCommand(device, type, command)) { + device."$command"() + } else { + httpError(403, "Access denied. This command is not supported by current capability.") + } } private show(devices, type) {