本节利用三星Smartthings Classic物联网平台的web service smartapp,实现了一个Alexa智能家居skill的例子,由此来了解Alexa是如何控制其他云的智能家居设备的。

三星Smartthings平台是如何运行第三方云来控制其设备的

三星Smartthings Classic支持开发者自己编写SmartApp来控制智能家居设备。参考官网中Web Service SmartApps的教程就可以写一个允许使用Web API来远程控制该平台设备的SmartApp。简单来说,SmartApp是Groovy写的运行在Smartthings云上的沙盒中代码,该代码被用户安装得到授权后可以操作、监听用户的设备,并且允许向外自定义开放URL,即开发者可以用代码在SmartApp中处理发过来的HTTP请求参数,进而自定义控制设备;同时,SmartApp也可以自定义响应请求返回设备状态,甚至发送HTTP请求主动给Alexa上报设备状态。

那么,三星如何验证发来的消息呢?答案是使用Oauth。Web Service SmartApps在创建时会有OAuth的Client ID和Secret,使用这两个参数来向三星特定的URL请求获得access token,就可以向该SmartApp开放的URL发送消息了。在OAuth的时候,会让用户选择允许该token访问哪些设备资源。Smartthings还允许创建虚拟设备,所以测试起来非常方便,过多不赘述,详见官网。

Alexa中Skill是如何向其注册设备、控制设备的

亚马逊给出了一个Python的Smart home skill例子,并且有详细的说明,其中用到的AWS服务也都有免费额度的,不用担心扣钱。

  1. Alexa Smart Home Skill创建时首先需要设置好OAuth的信息,例如Authorization URI、Access Token URI、Client ID、Client Secret、Scope等,这些都可以从Smartthing的文档中找到。Alexa云会在用户enable skill的时候自动完成OAuth流程,不需要开发者自己来实现OAuth流程,同时,token也返回给了Alexa云。Skill只有在接到用户intent的时候,才会收到由Alexa云发来的对应的access token。

  2. 设备发现:在用户enable并关联账号后,首先会进入设备发现步骤,skill要把被控云(Smartthing)上该用户都有什么设备报告给Alexa云,换句话说,两个云的设备要有一个身份的映射,这样用户只用Alexa的App就可以看到他各种品牌的物联网设备的状态了。Alexa在设备发现时会发送Discover命令给Skill,并携带token。Skill这时候拿着token去SmartApp开放的URL去查询都有哪些设备,然后根据得到的内容回复如下内容给Alexa,关键的有这么几个:
    • endpointId:设备的唯一标识号。应该在该用户的skill中唯一,类似于设备ID。
    • friendlyName:用户在Alexa App中看到的设备的名字。测试发现Alexa App中有一个BUG,friendlyName若重名,在Alexa App中显示面板中后发现的设备会覆盖掉之前同名的设备,用户没有方法分辨。因此,恶意的skill就有机会伪造用户之前的已发现的设备的状态,但是也称不上一个安全漏洞。
    • manufacturerName、description:Alexa App中看到的设备详细信息,可以随意填写,随意伪造。导致恶意Skill可以在Alexa中随便号称该设备就是Smartthing生产的,结合伪造的friendlyName,使用户完全无法分辨真实skill上报的设备是否被恶意顶替了。
    • displayCategories:说明设备的类型,必须是Alexa预定义的类型之一。
    • capabilities:设备支持的能力,如开关,亮度,以及该能力是否可被主动询问获得,等等。这也是Alexa预定义好的。
  3. 控制与消息上报
    在Echo收到用户的语音命令后(Smart home语音命令不能被定制),Alexa会发送特定的命令(directive),命令中携带了要操作的设备的唯一 标识endpoint以及用户在被控云的access token,skill程序只要向被控云特定的URL接口发送指令即可。
    SmartApp也可以在获得了用户的亚马逊token后,向特定的event结点主动报告更新设备的状态。
{"directive": {"header": {"namespace": "Alexa.Discovery","name": "Discover","payloadVersion": "3","messageId": "1bd5d003-31b9-476f-ad03-71d471922820"},"payload": {"scope": {"type": "BearerToken","token": "access-token-from-skill"}}}
}
{"event": {"header": {"correlationToken": "12345692749237492","messageId": "1bd5d003-31b9-476f-ad03-71d471922820","name": "Discover.Response","namespace": "Alexa.Discovery","payloadVersion": "3"},"payload": {"endpoints": [{"endpointId": "demo_id","manufacturerName": "Smart Device Company","friendlyName": "Bedroom Outlet","description": "Smart Device Switch","displayCategories": ["SWITCH"],"cookie": {"key1": "arbitrary key/value pairs for skill to reference this endpoint.","key2": "There can be multiple entries","key3": "but they should only be used for reference purposes.","key4": "This is not a suitable place to maintain current endpoint state."},"capabilities": [{"type": "AlexaInterface","interface": "Alexa","version": "3"},{"interface": "Alexa.PowerController","version": "3","type": "AlexaInterface","properties": {"supported": [{"name": "powerState"}],"retrievable": true}}]}]}}
}

关于设备身份映射的解释

虽然恶意skill有可能在Alexa App中顶替到其他skill创建的设备,但是用户在Web控制页面和设置routine时能够看到是两个不同的设备。通过查看web页面的网络流量,发现Alexa在真正标识设备时加入了skill的id作为前缀(base64编码)来防止恶意skill之间冲突上报设备信息,Alexa中表示设备信息的数据结构见附录(从浏览器调试中获得)。

另外还有一个小问题是用户语音UI如何准确的翻译到要控制哪个设备,如有相似或同名,似乎Alexa会额外询问到底要选择控制哪一个,这点没有深入测试。

附录代码

Smartapp

/***   My web smartapp**  Copyright 2019 Ascii0x03**  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except*  in compliance with the License. You may obtain a copy of the License at:**      http://www.apache.org/licenses/LICENSE-2.0**  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed*  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License*  for the specific language governing permissions and limitations under the License.**/
definition(name: " My web smartapp",namespace: "J_unique_Namespace",author: "Ascii0x03",description: "web smartapp for alexa",category: "My Apps",iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")preferences {section ("Allow external service to control these things1...") {input "switches", "capability.switch", multiple: true, required: true}
}
mappings {path("/switches") {action: [GET: "listSwitches"]}path("/switches/:command") {action: [PUT: "updateSwitches"]}path("/switches/:deviceid/:command") {action: [PUT: "updateASwitch"]}path("/amazontoken/:accesstoken/:refreshtoken") {action: [GET: "getAmzToken"]}
}def installed() {log.debug "Installed with settings: ${settings}"initialize()
}def updated() {log.debug "Updated with settings: ${settings}"//unsubscribe()initialize()
}def initialize() {// TODO: subscribe to attributes, devices, locations, etc.subscribe(switches, "switch", eventDetectedHandler)//subscribe(switch2, "switch.on", eventDetectedHandler)//subscribe(switch1, "switch.off", eventDetectedHandler)//subscribe(switch2, "switch.off", eventDetectedHandler)
}// returns a list like
// [[name: "kitchen lamp", value: "off"], [name: "bathroom", value: "on"]]
def listSwitches() {def resp = []//def resp = [value:switch1.currentValue("switch")]switches.each {resp << [name: it.displayName, value: it.currentValue("switch")]}return resp
}void updateSwitches() {// use the built-in request object to get the command parameterdef command = params.command// all switches have the command// execute the command on all switches// (note we can do this on the array - the command will be invoked on every elementswitch(command) {case "ON":switches.on()report_state_to_amazon("ON", "switch1")breakcase "OFF":switches.off()report_state_to_amazon("OFF", "switch1")breakdefault:httpError(400, "$command is not a valid command for all switches specified")}
}
void updateASwitch() {def command = params.commanddef deviceid = params.deviceidswitches.each {if(it.displayName == deviceid) {switch(command) {case "ON":it.on()report_state_to_amazon("ON", deviceid)breakcase "OFF":it.off()report_state_to_amazon("OFF", deviceid)breakdefault:httpError(400, "$command is not a valid command for $deviceid specified")}}}
}
def getAmzToken() {def accesstoken = params.accesstokendef refreshtoken = params.refreshtokenlog.debug "accesstoken: $accesstoken"state.amzaccesstoken = accesstokenstate.amzrefreshtoken = refreshtoken
}def report_state_to_amazon(state_value, endpoint_id) {pause(3000)def amz_url = "https://api.amazonalexa.com/v3/events"def sensor_value = "DETECTED"if( state_value == "OFF"){sensor_value = "NOT_DETECTED"    }def body = """
{"context": {"properties": [{"namespace": "Alexa.BrightnessController","name": "brightness","value": 85,"timeOfSample": "2017-02-03T16:20:50.52Z","uncertaintyInMilliseconds": 60000}]},"event": {"header": {"messageId": "c50bbb73-1ee8-44f8-af9b-19a0a2195474","namespace": "Alexa","name": "ChangeReport","payloadVersion": "3"},"endpoint": {"scope": {"type":"BearerToken","token":"$state.amzaccesstoken"},"endpointId" :  "$endpoint_id"},"payload": {"change": {"cause": {"type": "PHYSICAL_INTERACTION"},"properties": [{"namespace": "Alexa.PowerController","name": "powerState","value": "$state_value","timeOfSample": "2019-04-16T16:20:50.52Z","uncertaintyInMilliseconds": 0},{"namespace": "Alexa.ContactSensor","name": "detectionState","value": "$sensor_value","timeOfSample": "2019-04-16T16:20:50.52Z","uncertaintyInMilliseconds": 0}]}}}
}
"""def params = [uri: amz_url,headers: ["Authorization":"Bearer " + state.amzaccesstoken],contentType:"application/json",body:body]log.debug state.amzaccesstoken
//    try {httpPost(params) { resp ->//log.debug "response data: ${resp.statusCode}"//log.debug "response contentType: ${resp.contentType}"}
//    } catch (e) {
//        log.debug "something went wrong sending http to Amazon: $e"//   }
}
// TODO: implement event handlers
def eventDetectedHandler(evt) {log.debug "DetectedHandler called: $evt"//log.debug evt.getDevice()// get the value of this event, e.g., "on" or "off"//log.debug "The value of this event is ${evt.value}"if (evt.value == "on") {report_state_to_amazon("ON", evt.getDevice());} else {report_state_to_amazon("OFF", evt.getDevice());}// get the Date this event happened at//log.debug "This event happened at ${evt.date}"// did the value of this event change from its previous state?//log.debug "The value of this event is different from its previous value: ${evt.isStateChange()}"
}        

Alexa Skill Lambda代码(只贴了lambda_function,其他与git中一致)

# -*- coding: utf-8 -*-# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Amazon Software License (the "License"). You may not use this file except in
# compliance with the License. A copy of the License is located at
#
#    http://aws.amazon.com/asl/
#
# or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific
# language governing permissions and limitations under the License.
from botocore.vendored import requests
import boto3
import json
from alexa.skills.smarthome import AlexaResponsedynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('table_smart_home_skill1')
def lambda_handler(request, context):# Dump the request for logging - check the CloudWatch logsprint('lambda_handler request  -----')print(json.dumps(request))if context is not None:print('lambda_handler context  -----')print(context)# Validate we have an Alexa directiveif 'directive' not in request:aer = AlexaResponse(name='ErrorResponse',payload={'type': 'INVALID_DIRECTIVE','message': 'Missing key: directive, Is the request a valid Alexa Directive?'})return send_response(aer.get())# Check the payload versionpayload_version = request['directive']['header']['payloadVersion']if payload_version != '3':aer = AlexaResponse(name='ErrorResponse',payload={'type': 'INTERNAL_ERROR','message': 'This skill only supports Smart Home API version 3'})return send_response(aer.get())# Crack open the request and see what is being requestedname = request['directive']['header']['name']namespace = request['directive']['header']['namespace']# Handle the incoming request from Alexa based on the namespaceif namespace == 'Alexa.Authorization':if name == 'AcceptGrant':# Note: This sample accepts any grant request# In your implementation you would use the code and token to get and store access tokensgrant_code = request['directive']['payload']['grant']['code']grantee_token = request['directive']['payload']['grantee']['token']###Send the amazon grant_codedata = {"grant_type":"authorization_code", "code":grant_code, "client_id":"amzn1.application-oa2-client.XXX", "client_secret":"XXX"}post_data = ""for key in data:post_data = post_data + key + '=' + data[key] + '&'headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'}r = requests.post('https://api.amazon.com/auth/o2/token', data = post_data, headers = headers)#print(r.status_code)if(r.status_code == 200):print(r.json())resp = r.json()access_token = resp['access_token']refresh_token = resp['refresh_token']###TODO:Send amazon access_token to SmartThingssmartthings_uri = smartthings_discover_endpoint(grantee_token)headers = {'Authorization': 'Bearer ' + grantee_token}r = requests.get(smartthings_uri + '/amazontoken' + '/' + access_token + '/' + refresh_token, headers = headers)#print("JJJ:SmartThings sent amazon token")#print(r.status_code)table.put_item(Item={'ItemId': grantee_token,'amazon_access_token': access_token,'refresh_token': refresh_token,})else:print("JJ:Get access_token Bug!")returnaar = AlexaResponse(namespace='Alexa.Authorization', name='AcceptGrant.Response')return send_response(aar.get())if namespace == 'Alexa.Discovery':if name == 'Discover':adr = AlexaResponse(namespace='Alexa.Discovery', name='Discover.Response')capability_alexa = adr.create_payload_endpoint_capability()#capability_sensor = adr.create_payload_endpoint_capability()capability_alexa_powercontroller = adr.create_payload_endpoint_capability(interface='Alexa.PowerController',supported=[{'name': 'powerState'}],proactively_reported = True,retrievable = True)capability_ContactSensor = adr.create_payload_endpoint_capability(type='AlexaInterface',interface = 'Alexa.ContactSensor',supported=[{'name':'detectionState'}],proactively_reported = True,retrievable = True)adr.add_payload_endpoint(friendly_name='J_smart_sensor_switch',endpoint_id='switch1',description='SmartThings Switch1',display_categories=['SWITCH'],manufacturer_name='SmartThings_J',capabilities=[capability_alexa, capability_alexa_powercontroller, capability_ContactSensor])adr.add_payload_endpoint(friendly_name='J_smart_sensor_switch2',endpoint_id='switch2',description='SmartThings Switch2',display_categories=['SWITCH'],manufacturer_name='SmartThings_J',capabilities=[capability_alexa, capability_alexa_powercontroller, capability_ContactSensor])            return send_response(adr.get())if namespace == 'Alexa.PowerController':# Note: This sample always returns a success response for either a request to TurnOff or TurnOnendpoint_id = request['directive']['endpoint']['endpointId']##TODO: lookup smartthings according to id and find statuspower_state_value = 'OFF' if name == 'TurnOff' else 'ON'correlation_token = request['directive']['header']['correlationToken']token = request['directive']['endpoint']['scope']['token']# Check for an error when setting the statesmartthing_endpoint = smartthings_discover_endpoint(token)state_set = smartthings_control_device(smartthing_endpoint, token, endpoint_id, power_state_value)if not state_set:return AlexaResponse(name='ErrorResponse',payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()apcr = AlexaResponse(correlation_token=correlation_token, token=token, endpoint_id=endpoint_id)apcr.add_context_property(namespace='Alexa.PowerController', name='powerState', value=power_state_value)if power_state_value == "ON":apcr.add_context_property(namespace='Alexa.ContactSensor', name='detectionState', value='DETECTED')else:apcr.add_context_property(namespace='Alexa.ContactSensor', name='detectionState', value='NOT_DETECTED')return send_response(apcr.get())#    if namespace == 'Alexa.LockController':# Note: This sample always returns a success response for either a request to TurnOff or TurnOnendpoint_id = request['directive']['endpoint']['endpointId']state_value = 'LOCKED' if name == 'Lock' else 'UNLOCKED'correlation_token = request['directive']['header']['correlationToken']# Check for an error when setting the statestate_set = set_device_state(endpoint_id=endpoint_id, state='lockState', value=state_value)if not state_set:return AlexaResponse(name='ErrorResponse',payload={'type': 'ENDPOINT_UNREACHABLE', 'message': 'Unable to reach endpoint database.'}).get()apcr = AlexaResponse(correlation_token=correlation_token)apcr.add_context_property(namespace='Alexa.LockController', name='lockState', value=state_value)return send_response(apcr.get())if namespace == 'Alexa':if name == 'ReportState':endpoint_id = request['directive']['endpoint']['endpointId']token = request['directive']['endpoint']['scope']['token']smartthing_endpoint = smartthings_discover_endpoint(token)power_state_value = smartthings_get_device_state(smartthing_endpoint, token, endpoint_id)if power_state_value == 'ON':sensor_state_value = 'DETECTED'else:sensor_state_value = 'NOT_DETECTED'##TODO: retrive status of devicescorrelation_token = request['directive']['header']['correlationToken']apcr = AlexaResponse(correlation_token=correlation_token,token=token, endpoint_id=endpoint_id,name='StateReport')apcr.add_context_property(namespace='Alexa.ContactSensor', name='detectionState', value=sensor_state_value)apcr.add_context_property(namespace='Alexa.PowerController', name='powerState', value=power_state_value)return send_response(apcr.get())def send_response(response):# TODO Validate the responseprint('lambda_handler response -----')print(json.dumps(response))return responsedef set_device_state(endpoint_id, state, value):smartthings_discover_endpoint()return Truedef smartthings_get_device_state(smartthing_endpoint, token, endpoint_id):headers = {'Authorization': 'Bearer '+ token}#print(smartthing_endpoint + '/' + endpoint_id)r = requests.get(smartthing_endpoint + '/' + 'switches', headers=headers)#print(r.json())if (r.status_code == 200):for i in r.json():if i['name'] == endpoint_id:if i['value'] == 'on':return 'ON'else:return 'OFF'else:print("JJJ: get device state BUG!")print(r.status_code)def smartthings_control_device(smartthing_endpoint, token, endpoint_id, cmd):headers = {'Authorization': 'Bearer '+ token}response = requests.put(smartthing_endpoint + '/switches/' + endpoint_id + '/' + cmd, headers=headers)print("JJJ: Control device response: " + str(response.status_code))return Truedef smartthings_discover_endpoint(token):headers = {'Authorization': 'Bearer ' + token}r = requests.get("https://graph.api.smartthings.com/api/smartapps/endpoints", headers=headers)resp = r.json()#print(resp)for i in resp:url = i['uri']return url

Alexa中设备、场景的数据结构

{  "networkDetail":"{"   locationDetails":{  "locationDetails":{  "Default_Location":{  "locationId":"Default_Location","amazonBridgeDetails":{  "amazonBridgeDetails":{  "LambdaBridge_SKILL/eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjE3NTdjNjlmLTFhYzktNGZlYi05NWI3LWFkNTI4OTk1ZTNiNSIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==":{  "amazonBridgeIdentifier":{  "amazonBridgeDSN":"SKILL/eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjE3NTdjNjlmLTFhYzktNGZlYi05NWI3LWFkNTI4OTk1ZTNiNSIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==","amazonBridgeType":"LambdaBridge","lambdaBridge":true,"amazonBridgeSource":"SKILL"},"applianceDetails":{  "applianceDetails":{  "SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjE3NTdjNjlmLTFhYzktNGZlYi05NWI3LWFkNTI4OTk1ZTNiNSIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==_fake_end1":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjE3NTdjNjlmLTFhYzktNGZlYi05NWI3LWFkNTI4OTk1ZTNiNSIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==_fake_end1","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjE3NTdjNjlmLTFhYzktNGZlYi05NWI3LWFkNTI4OTk1ZTNiNSIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ=="},"manufacturerName":"SmartThings","friendlyDescription":"Fake SmartThings Switch","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"smartthings1","friendlyNameModifiedAt":1554150257260,"capabilitiesModifiedAt":1554150257260,"ipAddress":"","port":"","entityId":"6aa7c6ce-723f-4f0b-aca3-a467fa8f89cf","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1554150257260,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  }},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"powerState"}],"proactivelyReported":true,"retrievable":false,"readOnly":false},"interfaceName":"Alexa.PowerController"}],"applianceTypes":[  "SWITCH"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjE3NTdjNjlmLTFhYzktNGZlYi05NWI3LWFkNTI4OTk1ZTNiNSIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ=="}}}}},"LambdaBridge_SKILL/eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjI3MDZhOGNmLWUzYWItNGRjNi04ZTNkLWEwYjlkZWYxOWQ1NyIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==":{  "amazonBridgeIdentifier":{  "amazonBridgeDSN":"SKILL/eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjI3MDZhOGNmLWUzYWItNGRjNi04ZTNkLWEwYjlkZWYxOWQ1NyIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==","amazonBridgeType":"LambdaBridge","lambdaBridge":true,"amazonBridgeSource":"SKILL"},"applianceDetails":{  "applianceDetails":{  "SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjI3MDZhOGNmLWUzYWItNGRjNi04ZTNkLWEwYjlkZWYxOWQ1NyIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==_fake_end1":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjI3MDZhOGNmLWUzYWItNGRjNi04ZTNkLWEwYjlkZWYxOWQ1NyIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ==_fake_end1","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjI3MDZhOGNmLWUzYWItNGRjNi04ZTNkLWEwYjlkZWYxOWQ1NyIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ=="},"manufacturerName":"SmartThings","friendlyDescription":"Fake SmartThings Switch2","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"smartthings1","friendlyNameModifiedAt":1554150257281,"capabilitiesModifiedAt":1554150257281,"ipAddress":"","port":"","entityId":"c792b2e7-e71b-41ec-b2e3-9e9476ab7e35","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1554150257281,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  }},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"powerState"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.PowerController"}],"applianceTypes":[  "SWITCH"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjI3MDZhOGNmLWUzYWItNGRjNi04ZTNkLWEwYjlkZWYxOWQ1NyIsInN0YWdlIjoiZGV2ZWxvcG1lbnQifQ=="}}}}},"LambdaBridge_SKILL/eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9":{  "amazonBridgeIdentifier":{  "amazonBridgeDSN":"SKILL/eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9","amazonBridgeType":"LambdaBridge","lambdaBridge":true,"amazonBridgeSource":"SKILL"},"applianceDetails":{  "applianceDetails":{  "SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_e0401c4e-ff5e-43f6-af5f-4986afb8266e":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_e0401c4e-ff5e-43f6-af5f-4986afb8266e","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Routine","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"Goodbye!","friendlyNameModifiedAt":1552940633050,"capabilitiesModifiedAt":1552940633050,"ipAddress":"","port":"","entityId":"147bd392-8ffd-4dc3-b954-0a91231ecea6","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1552940633050,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSSceneControllerCapability","type":"AlexaInterface","version":"3","proactivelyReported":false,"supportsDeactivation":false,"interfaceName":"Alexa.SceneController"}],"applianceTypes":[  "SCENE_TRIGGER"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_5178a3ef-b365-4338-b1b2-aab4fbbc5e1e":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_5178a3ef-b365-4338-b1b2-aab4fbbc5e1e","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Routine","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"IAmBack","friendlyNameModifiedAt":1552940633063,"capabilitiesModifiedAt":1552940633063,"ipAddress":"","port":"","entityId":"a5c397bd-847b-45fa-89fb-f34eb556f207","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1552940633050,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSSceneControllerCapability","type":"AlexaInterface","version":"3","proactivelyReported":false,"supportsDeactivation":false,"interfaceName":"Alexa.SceneController"}],"applianceTypes":[  "SCENE_TRIGGER"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_f59f6427-db90-4402-8a6b-c2be09ae2ff0":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_f59f6427-db90-4402-8a6b-c2be09ae2ff0","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Switch","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"smartthings2","friendlyNameModifiedAt":1554149203953,"capabilitiesModifiedAt":1554149203953,"ipAddress":"","port":"","entityId":"3b84b62c-4c56-4e6a-814a-5bd92df3511c","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1554149203953,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"connectivity"}],"proactivelyReported":false,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.EndpointHealth"},{  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"powerState"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.PowerController"}],"applianceTypes":[  "SWITCH"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_6848728a-6951-4457-8d1b-037fea3fea67":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_6848728a-6951-4457-8d1b-037fea3fea67","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Routine","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"Good Morning!","friendlyNameModifiedAt":1552940633068,"capabilitiesModifiedAt":1552940633068,"ipAddress":"","port":"","entityId":"5c5d0a42-66a7-47f0-a2a1-3dd88da1e31d","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1552940633050,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSSceneControllerCapability","type":"AlexaInterface","version":"3","proactivelyReported":false,"supportsDeactivation":false,"interfaceName":"Alexa.SceneController"}],"applianceTypes":[  "SCENE_TRIGGER"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_c4940aaa-4e5c-46fe-9419-2d9f77c7cee8":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_c4940aaa-4e5c-46fe-9419-2d9f77c7cee8","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Routine","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"åå","friendlyNameModifiedAt":1552940633074,"capabilitiesModifiedAt":1552940633074,"ipAddress":"","port":"","entityId":"476ee698-1638-41eb-a8a0-e963b60d85c6","applianceNetworkState":{  "reachability":"NOT_REACHABLE","lastSeenAt":1554150273030,"createdAt":1552940633050,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.A3S5BH2HU6VAYF.G090L91072720DQ7.CUSTOMER.2019-03-18T20:23:52.425Z.78cc347a-2f85-4c12-8c82-30555a1c75c0"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/aa14d7cf-2510-42fc-b49a-61a3201d7688"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSSceneControllerCapability","type":"AlexaInterface","version":"3","proactivelyReported":false,"supportsDeactivation":false,"interfaceName":"Alexa.SceneController"}],"applianceTypes":[  "SCENE_TRIGGER"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_403dd373-7940-4edb-ad96-88bf3f28e4cc":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_403dd373-7940-4edb-ad96-88bf3f28e4cc","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Device","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"11111","friendlyNameModifiedAt":1554149203958,"capabilitiesModifiedAt":1554149203958,"ipAddress":"","port":"","entityId":"7cec84af-4f7a-49f0-92d6-e3403ea910fd","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1554149203953,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"powerState"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.PowerController"},{  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"connectivity"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.EndpointHealth"}],"applianceTypes":[  "SMARTPLUG"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_d956f54a-b71a-4c49-b92e-234e880e2bef":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_d956f54a-b71a-4c49-b92e-234e880e2bef","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Switch","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"smartthings1","friendlyNameModifiedAt":1554149203970,"capabilitiesModifiedAt":1554149203970,"ipAddress":"","port":"","entityId":"a7431ebe-3631-4ad4-ac58-112a092df4be","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1554149203953,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"connectivity"}],"proactivelyReported":false,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.EndpointHealth"},{  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"powerState"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.PowerController"}],"applianceTypes":[  "SWITCH"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_63c09df9-6d13-40f8-bec0-c1217c5dd9ed":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_63c09df9-6d13-40f8-bec0-c1217c5dd9ed","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Light (dimmable)","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"smartthings3","friendlyNameModifiedAt":1554149203964,"capabilitiesModifiedAt":1554149203964,"ipAddress":"","port":"","entityId":"1cf0ab83-b1fe-405b-bd00-f1f07a7927a0","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1554149203953,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"brightness"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.BrightnessController"},{  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"connectivity"}],"proactivelyReported":false,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.EndpointHealth"},{  "capabilityType":"AVSInterfaceCapability","type":"AlexaInterface","version":"3","properties":{  "supported":[  {  "name":"powerState"}],"proactivelyReported":true,"retrievable":true,"readOnly":false},"interfaceName":"Alexa.PowerController"}],"applianceTypes":[  "SWITCH","LIGHT"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}},"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_93a23d5f-c61c-44b1-b41e-5bdf6ebd66e8":{  "applianceId":"SKILL_eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9_93a23d5f-c61c-44b1-b41e-5bdf6ebd66e8","endpointTypeId":"","driverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"},"manufacturerName":"SmartThings","friendlyDescription":"SmartThings Routine","modelName":"","deviceType":"CLOUD_DISCOVERED_DEVICE","version":"0","friendlyName":"Good Night!","friendlyNameModifiedAt":1552940633087,"capabilitiesModifiedAt":1552940633087,"ipAddress":"","port":"","entityId":"302b9711-6998-4865-9204-7a4ea5c2d2af","applianceNetworkState":{  "reachability":"REACHABLE","lastSeenAt":1554150273030,"createdAt":1552940633050,"lastSeenDiscoverySessionId":{  "value":"amzn1.HomeAutomation.ApplianceDiscovery.A1OZ7FH12OZY2A.LambdaBridge.fakeDSN.CUSTOMER.2019-04-01T20:24:17.180Z.22e16552-2ad2-4562-bb8d-20e5862326b6"}},"tags":{  "tagNameToValueSetMap":{  }},"additionalApplianceDetails":{  "additionalApplianceDetails":{  "uri":"https://graph.api.smartthings.com:443/api/smartapps/installations/3f4b5154-1538-429d-9311-b095a17c18a8"}},"firmwareVersion":"0","actions":[  ],"capabilities":[  {  "capabilityType":"AVSSceneControllerCapability","type":"AlexaInterface","version":"3","proactivelyReported":false,"supportsDeactivation":false,"interfaceName":"Alexa.SceneController"}],"applianceTypes":[  "SCENE_TRIGGER"],"isEnabled":true,"aliases":[  ],"connectedVia":"","alexaDeviceIdentifierList":[  ],"ipaddress":"","applianceLambdaControlled":true,"applianceDriverIdentity":{  "namespace":"SKILL","identifier":"eyJza2lsbElkIjoiYW16bjEuYXNrLnNraWxsLjJiZGJjNzRmLWNlNGQtNGUyZC1iNzQxLTMyNmM3YmEzNThmMCIsInN0YWdlIjoibGl2ZSJ9"}}}}}}},"applianceGroups":{  "applianceGroups":{  }}}}},"version":"1.0","relations":[  ]
}"
}

转载于:https://www.cnblogs.com/ascii0x03/p/10760219.html

深入理解Amazon Alexa Skill(四)相关推荐

  1. 亚马逊echo中国使用_我如何编程我的第一个Amazon Alexa技能并赢得了免费的Echo Dot...

    亚马逊echo中国使用 by Lorrie Pearson 洛里·皮尔森(Lorrie Pearson) 我如何编程我的第一个Amazon Alexa技能并赢得了免费的Echo Dot (How I ...

  2. amazon alexa_在Amazon Alexa上推出freeCodeCamp编码琐事测验

    amazon alexa Now you can learn coding concepts hands-free using an Amazon Echo. 现在,您可以使用Amazon Echo免 ...

  3. au回声_回声按钮如何将Amazon Alexa技能提升到新水平

    au回声 by Terren Peterson 由Terren Peterson 回声按钮如何将Amazon Alexa技能提升到新水平 (How Echo Buttons take Amazon A ...

  4. alexa skill+自定义oauth2服务完整版教程(保姆级图文教程附demo源码)

    文章目录 前言 一.alexa skill是什么? 二.开发步骤 1.注册账号 2.创建技能 3.创建函数 技能绑定函数 部署oauth2 为技能配置账号,开启oauth2认证 alexa app 开 ...

  5. 【智能语音】ROC-RK3308-CC Amazon Alexa固件发布

    ROC-RK3308-CC已支持Amazon Alexa语音服务,在Firefly 维基教程可下载ROC-RK3308-CC Alexa固件. 维基教程详细介绍了授权.配网.使用流程.编译方法等内容: ...

  6. 理解Unity3D中的四种坐标体系

    coffeecato写在前面:本文比较了unity3d中的四种坐标系,在使用unity3d开发的过程中,已经多次被坐标转换之类的问题卡住,这篇文章可以说是系统的对四种坐标系进行了总结,结合实际的使用经 ...

  7. 创建alexa skill

    注册亚马逊Alexa账号 官网地址:https://developer.amazon.com/alexa 创建技能 登录账号后点击创建技能按钮,选择custom模式与使用自己的服务资源创建技能 点击下 ...

  8. 深入理解编译注解(四)常用接口介绍

    前言 今天猛然想起一个注解在使用上的问题,就一直在网上搜索资料,问题倒是没解决,但是看到了一篇非常好的博客,正好是我这里缺少的,写的很不错,所以直接转载. 在之前的demo中,为了完成编译注解的功能, ...

  9. r语言t检验输出检验统计量_数据统计的理解和运用(四)列联表之卡方检验

    前面几期我们介绍了参数检验,t检验和方差分析: 临度科研:数据统计的理解和运用(三)方差分析​zhuanlan.zhihu.com 临度科研:数据统计的理解和运用(二)t检验的应用​zhuanlan. ...

  10. 通俗理解 三次握手四次挥手(老友依恋式)

    首先我们来看一张图 该图描述的意思: A:你好老哥,我要从你和你建立连接,向B服务端发送请求连接的请求,然后等待对面老哥的回答(其中包含自己要与他确认连接的同步序列字段:可以理解为,咱们两人的手机号码 ...

最新文章

  1. 游标对于分页存储过程
  2. 7.3 GROUP BY的“新”功能
  3. DICOM医学图像处理:Dcmtk与fo-dicom保存文件的不同设计模式之“同步VS异步”+“单线程VS多线程”...
  4. SVN Error:请求的名称有效并且在数据库中找到,但是它没有相关的正确的数据来被解析...
  5. graphics 位深度_热门上海乐家人才公寓深度解析又是一个神
  6. 得物:两款问题商品系标识标注方式不符合最新规定 已先行下架商品
  7. 教师计算机专业知识考试试题及答案,信息技术学科教师基本功测试题及答案
  8. POJ 1915 经典马步 双向bfs
  9. android投影到创维电视,创维Miracast,手机怎么投屏到创维电视,
  10. 概率分布F(x)和概率密度f(x)
  11. 2021江苏高考成绩查询:声讯台,2021年江苏高考成绩几点钟可以查询,附具体查询时间安排...
  12. 【机器学习之随机森林】
  13. 菏泽一中2021级高考成绩查询入口,2021年菏泽中考各学校录取分数线,历年菏泽中考分数线汇总...
  14. 无延时直播/超低延时直播画面同步性测试(实测组图)
  15. Java中高级程序员全程学习路线图
  16. mysql 每个分类前十名_一文解决所有MySQL分类排名问题
  17. android手环通信协议,BLE通信协议
  18. 不要以你的现状来判断你的未来
  19. 雅腾php怎么样_2018年09月26日
  20. linux 显卡驱动程序 接口,Linux显卡驱动程序Nvidia 384.59发布,增加对GeForce GT 1030 GPU支持...

热门文章

  1. 任凭弱水三千,我只取一瓢饮
  2. 弱水三千的由来(转)
  3. 美丽汤的请求 - 小甜饼豆瓣爬虫
  4. Blast2GO-Pro心得
  5. python的debug为什么点第一行直接运行结束了_Python 代码调试工具 pdb 快速入门
  6. Win10隐藏文件资源管理器中的我的电脑上方的7个文件夹
  7. 计算机组成原理笔记——DMA方式
  8. VSCode沙绿色主题设置
  9. iOS 音乐播放器demo讲解
  10. 学生用计算机怎么恢复出厂设置,电脑怎么恢复出厂设置