Я потратил часы, пытаясь понять этот интерфейс: https://developer.amazon.com/docs/device-apis/alexa-contactsensor.html
Но всякий раз, когда я пытаюсь задать область тестирования консоли разработчика alexa, на этой странице интерфейса появляется пример: «Алекса, моя дверь открыта»? », она отвечает:« Датчик двери не поддерживает это ».
Я выложу ВСЕ код ниже.Кто-то может помочь?
### Обратите внимание, что этот пример не имеет дело с аутентификацией пользователя, только использует виртуальные устройства, пропускает много реализации и обработки ошибок, чтобы сохранить код простым и сфокусированным."" "
import logging
import time
import json
import uuid
# Imports for v3 validation
#from validation import validate_message
# Setup logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# To simplify this sample Lambda, we omit validation of access tokens and retrieval of a specific
# user's appliances. Instead, this array includes a variety of virtual appliances in v2 API syntax,
# and will be used to demonstrate transformation between v2 appliances and v3 endpoints.
SAMPLE_APPLIANCES = [
{
"endpointId": "endpoint-001",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Switch",
"version": "3",
"friendlyName": "Switch",
"friendlyDescription": "001 Switch that can only be turned on/off",
"isReachable": True,
"actions": [
"turnOn",
"turnOff"
],
"additionalApplianceDetails": {
"detail1": "For simplicity, this is the only appliance",
"detail2": "that has some values in the additionalApplianceDetails"
}
},
{
"endpointId": "endpoint-002",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Light",
"version": "1",
"friendlyName": "Light",
"friendlyDescription": "002 Light that is dimmable and can change color and color temperature",
"isReachable": True,
"actions": [
"turnOn",
"turnOff",
"setPercentage",
"incrementPercentage",
"decrementPercentage",
"setColor",
"setColorTemperature",
"incrementColorTemperature",
"decrementColorTemperature"
],
"additionalApplianceDetails": {}
},
{
"endpointId": "endpoint-003",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart White Light",
"version": "1",
"friendlyName": "White Light",
"friendlyDescription": "003 Light that is dimmable and can change color temperature only",
"isReachable": True,
"actions": [
"turnOn",
"turnOff",
"setPercentage",
"incrementPercentage",
"decrementPercentage",
"setColorTemperature",
"incrementColorTemperature",
"decrementColorTemperature"
],
"additionalApplianceDetails": {}
},
{
"endpointId": "endpoint-007",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Activity",
"version": "1",
"friendlyName": "Watch TV",
"friendlyDescription": "007 Activity that runs sequentially that can be turned on and off",
"isReachable": True,
"actions": [
"turnOn",
"turnOff"
],
"additionalApplianceDetails": {}
},
{
"endpointId": "endpoint-008",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Camera",
"version": "1",
"friendlyName": "Baby Camera",
"friendlyDescription": "008 Camera that streams from an RSTP source",
"isReachable": True,
"actions": [
"retrieveCameraStreamUri"
],
"additionalApplianceDetails": {}
},
{
"endpointId": "endpoint-009",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Door Sensor",
"version": "3",
"friendlyName": "Door Sensor",
"friendlyDescription": "009 Sensor allows for state updates BOYYYYYY",
"isReachable": True,
"actions": [
"detectionState"
],
"additionalApplianceDetails": {}
},
{
"endpointId": "endpoint-010",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Door Sensor",
"version": "3",
"friendlyName": "Brian's Sensor",
"friendlyDescription": "009 Sensor allows for state updates BOYYYYYY",
"isReachable": True,
"actions": [
"turnOn",
"detectionState"
],
"additionalApplianceDetails": {}
},
{
"endpointId": "endpoint-011",
"manufacturerName": "Sample Manufacturer",
"modelName": "Smart Switch",
"version": "3",
"friendlyName": "tester",
"friendlyDescription": "009 Sensor allows for state updates BOYYYYYY",
"isReachable": True,
"actions": [
"turnOn",
"detectionState"
],
"additionalApplianceDetails": {}
}
]
def lambda_handler(request, context):
"""Main Lambda handler.
Since you can expect both v2 and v3 directives for a period of time during the migration
and transition of your existing users, this main Lambda handler must be modified to support
both v2 and v3 requests.
"""
try:
logger.info("Directive:")
logger.info(json.dumps(request, indent=4, sort_keys=True))
version = get_directive_version(request)
if version == "3":
logger.info("Received v3 directive!")
if request["directive"]["header"]["name"] == "Discover":
response = handle_discovery_v3(request)
else:
response = handle_non_discovery_v3(request)
else:
logger.info("Received v2 directive!")
if request["header"]["namespace"] == "Alexa.ConnectedHome.Discovery":
response = handle_discovery()
else:
response = handle_non_discovery(request)
logger.info("Response:")
#logger.info(JSON.stringify(response))
logger.info(json.dumps(response))
#if version == "3":
# logger.info("Validate v3 response")
# validate_message(request, response)
return response
except ValueError as error:
logger.error(error)
raise
# v2 handlers
def handle_discovery():
header = {
"namespace": "Alexa.ConnectedHome.Discovery",
"name": "DiscoverAppliancesResponse",
"payloadVersion": "2",
"messageId": get_uuid()
}
payload = {
"discoveredAppliances": SAMPLE_APPLIANCES
}
response = {
"header": header,
"payload": payload
}
return response
def handle_non_discovery(request):
request_name = request["header"]["name"]
if request_name == "TurnOnRequest":
header = {
"namespace": "Alexa.ConnectedHome.Control",
"name": "TurnOnConfirmation",
"payloadVersion": "2",
"messageId": get_uuid()
}
payload = {}
elif request_name == "TurnOffRequest":
header = {
"namespace": "Alexa.ConnectedHome.Control",
"name": "TurnOffConfirmation",
"payloadVersion": "2",
"messageId": get_uuid()
}
# other handlers omitted in this example
payload = {}
response = {
"header": header,
"payload": payload
}
return response
# v2 utility functions
def get_appliance_by_appliance_id(appliance_id):
for appliance in SAMPLE_APPLIANCES:
if appliance["endpointId"] == appliance_id:
return appliance
return None
def get_utc_timestamp(seconds=None):
return time.strftime("%Y-%m-%dT%H:%M:%S.00Z", time.gmtime(seconds))
def get_uuid():
return str(uuid.uuid4())
# v3 handlers
def handle_discovery_v3(request):
endpoints = []
for appliance in SAMPLE_APPLIANCES:
endpoints.append(get_endpoint_from_v2_appliance(appliance))
response = {
"event": {
"header": {
"namespace": "Alexa.Discovery",
"name": "Discover.Response",
"payloadVersion": "3",
"messageId": get_uuid()
},
"payload": {
"endpoints": endpoints
}
}
}
return response
def handle_non_discovery_v3(request):
request_namespace = request["directive"]["header"]["namespace"]
request_name = request["directive"]["header"]["name"]
if request_namespace == "Alexa.PowerController":
if request_name == "TurnOn":
value = "ON"
else:
value = "OFF"
response = {
"context": {
"properties": [
{
"namespace": "Alexa.PowerController",
"name": "powerState",
"value": value,
"timeOfSample": get_utc_timestamp(),
"uncertaintyInMilliseconds": 500
}
]
},
"event": {
"header": {
"namespace": "Alexa",
"name": "Response",
"payloadVersion": "3",
"messageId": get_uuid(),
"correlationToken": request["directive"]["header"]["correlationToken"]
},
"endpoint": {
"scope": {
"type": "BearerToken",
"token": request["directive"]["endpoint"]["scope"]["token"]
},
"endpointId": request["directive"]["endpoint"]["endpointId"]
},
"payload": {}
}
}
return response
elif request_namespace == "Alexa.Authorization":
if request_name == "AcceptGrant":
response = {
"event": {
"header": {
"namespace": "Alexa.Authorization",
"name": "AcceptGrant.Response",
"payloadVersion": "3",
"messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4"
},
"payload": {}
}
}
return response
elif request_namespace == "Alexa.ContactSensor":
if request_name == "detectionState":
response = {
"context": {
"properties": [
{
"namespace": "Alexa.ContactSensor",
"name": "detectionState",
"value": "DETECTED",
"timeOfSample": get_utc_timestamp(),
"uncertaintyInMilliseconds": 0
},
{
"namespace": "Alexa.EndpointHealth",
"name": "connectivity",
"value":
{
"value": "OK"
},
"timeOfSample": get_utc_timestamp(),
"uncertaintyInMilliseconds": 0
}
]
},
"event": {
"header": {
"messageId": get_uuid(),
"correlationToken": request["directive"]["header"]["correlationToken"],
"namespace": "Alexa",
"name": "StateReport",
"payloadVersion": "3"
},
"endpoint": {
"endpointId": "endpoint-009",
"cookie": {}
},
"payload": {}
}
}
elif request_name == "ReportState":
response = {
"event": {
"header": {
"namespace": "Alexa",
"name": "ReportState",
"payloadVersion": "3",
"messageId": get_uuid(),
"correlationToken": request["directive"]["header"]["correlationToken"]
},
"endpoint": {
"endpointId": "endpoint-009",
"scope": {
"type":"BearerToken",
"token":endpoint.scope.token
}
},
"payload": {}
}
}
return response
# other handlers omitted in this example
# v3 utility functions
def get_endpoint_from_v2_appliance(appliance):
endpoint = {
"endpointId": appliance["endpointId"],
"manufacturerName": appliance["manufacturerName"],
"friendlyName": appliance["friendlyName"],
"description": appliance["friendlyDescription"],
"displayCategories": [],
"cookie": appliance["additionalApplianceDetails"],
"capabilities": []
}
endpoint["displayCategories"] = get_display_categories_from_v2_appliance(appliance)
endpoint["capabilities"] = get_capabilities_from_v2_appliance(appliance)
return endpoint
def get_directive_version(request):
try:
return request["directive"]["header"]["payloadVersion"]
except:
try:
return request["header"]["payloadVersion"]
except:
return "-1"
def get_endpoint_by_endpoint_id(endpoint_id):
appliance = get_appliance_by_appliance_id(endpoint_id)
if appliance:
return get_endpoint_from_v2_appliance(appliance)
return None
def get_display_categories_from_v2_appliance(appliance):
model_name = appliance["modelName"]
if model_name == "Smart Switch": displayCategories = ["SWITCH"]
elif model_name == "Smart Light": displayCategories = ["LIGHT"]
elif model_name == "Smart White Light": displayCategories = ["LIGHT"]
elif model_name == "Smart Thermostat": displayCategories = ["THERMOSTAT"]
elif model_name == "Smart Lock": displayCategories = ["SMARTLOCK"]
elif model_name == "Smart Scene": displayCategories = ["SCENE_TRIGGER"]
elif model_name == "Smart Activity": displayCategories = ["ACTIVITY_TRIGGER"]
elif model_name == "Smart Camera": displayCategories = ["CAMERA"]
elif model_name == "Smart Door Sensor": displayCategories = ["MOTION_SENSOR"]
else: displayCategories = ["OTHER"]
return displayCategories
def get_capabilities_from_v2_appliance(appliance):
model_name = appliance["modelName"]
if model_name == 'Smart Switch':
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"supported": [
{ "name": "powerState" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
elif model_name == "Smart Door Sensor":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.MotionSensor", #Door Sensor ----------------
"version": "3",
"properties.supported":"detectionState",
#{"name": "ReportState"}
"proactivelyReported": True,
"retrievable": True
}
]
elif model_name == "Smart Light":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"supported": [
{ "name": "powerState" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.ColorController",
"version": "3",
"properties": {
"supported": [
{ "name": "color" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.ColorTemperatureController",
"version": "3",
"properties": {
"supported": [
{ "name": "colorTemperatureInKelvin" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.BrightnessController",
"version": "3",
"properties": {
"supported": [
{ "name": "brightness" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.PowerLevelController",
"version": "3",
"properties": {
"supported": [
{ "name": "powerLevel" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.PercentageController",
"version": "3",
"properties": {
"supported": [
{ "name": "percentage" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
elif model_name == "Smart White Light":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"supported": [
{ "name": "powerState" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.ColorTemperatureController",
"version": "3",
"properties": {
"supported": [
{ "name": "colorTemperatureInKelvin" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.BrightnessController",
"version": "3",
"properties": {
"supported": [
{ "name": "brightness" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.PowerLevelController",
"version": "3",
"properties": {
"supported": [
{ "name": "powerLevel" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.PercentageController",
"version": "3",
"properties": {
"supported": [
{ "name": "percentage" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
elif model_name == "Smart Thermostat":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.ThermostatController",
"version": "3",
"properties": {
"supported": [
{ "name": "targetSetpoint" },
{ "name": "thermostatMode" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.TemperatureSensor",
"version": "3",
"properties": {
"supported": [
{ "name": "temperature" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
elif model_name == "Smart Thermostat Dual":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.ThermostatController",
"version": "3",
"properties": {
"supported": [
{ "name": "upperSetpoint" },
{ "name": "lowerSetpoint" },
{ "name": "thermostatMode" }
],
"proactivelyReported": True,
"retrievable": True
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.TemperatureSensor",
"version": "3",
"properties": {
"supported": [
{ "name": "temperature" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
elif model_name == "Smart Lock":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.LockController",
"version": "3",
"properties": {
"supported": [
{ "name": "lockState" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
elif model_name == "Smart Scene":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.SceneController",
"version": "3",
"supportsDeactivation": False,
"proactivelyReported": True
}
]
elif model_name == "Smart Activity":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.SceneController",
"version": "3",
"supportsDeactivation": True,
"proactivelyReported": True
}
]
elif model_name == "Smart Camera":
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.CameraStreamController",
"version": "3",
"cameraStreamConfigurations" : [ {
"protocols": ["RTSP"],
"resolutions": [{"width":1280, "height":720}],
"authorizationTypes": ["NONE"],
"videoCodecs": ["H264"],
"audioCodecs": ["AAC"]
} ]
}
]
else:
# in this example, just return simple on/off capability
capabilities = [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"supported": [
{ "name": "powerState" }
],
"proactivelyReported": True,
"retrievable": True
}
}
]
# additional capabilities that are required for each endpoint
endpoint_health_capability = {
"type": "AlexaInterface",
"interface": "Alexa.EndpointHealth",
"version": "3",
"properties": {
"supported":[
{ "name":"connectivity" }
],
"proactivelyReported": True,
"retrievable": True
}
}
alexa_interface_capability = {
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
}
capabilities.append(endpoint_health_capability)
capabilities.append(alexa_interface_capability)
return capabilities