├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── capability_evaluations └── test_plans │ ├── BrightnessController │ ├── ColorController │ ├── ColorTemperatureController │ ├── PowerController │ ├── ThermostatAuto │ ├── ThermostatCool_CELSIUS │ ├── ThermostatCool_FAHRENHEIT │ ├── ThermostatHeat_CELSIUS │ └── ThermostatHeat_FAHRENHEIT ├── sample_async ├── README.md └── python │ └── sample_async.py ├── sample_lambda ├── README.md └── python │ ├── __init__.py │ ├── jsonschema │ ├── __init__.py │ ├── __main__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ ├── _format.cpython-36.pyc │ │ ├── _utils.cpython-36.pyc │ │ ├── _validators.cpython-36.pyc │ │ ├── compat.cpython-36.pyc │ │ ├── exceptions.cpython-36.pyc │ │ └── validators.cpython-36.pyc │ ├── _format.py │ ├── _reflect.py │ ├── _utils.py │ ├── _validators.py │ ├── cli.py │ ├── compat.py │ ├── exceptions.py │ ├── schemas │ │ ├── draft3.json │ │ └── draft4.json │ ├── tests │ │ ├── __init__.py │ │ ├── compat.py │ │ ├── test_cli.py │ │ ├── test_exceptions.py │ │ ├── test_format.py │ │ ├── test_jsonschema_test_suite.py │ │ └── test_validators.py │ └── validators.py │ ├── lambda.py │ └── validation.py ├── sample_messages ├── Authorization │ ├── Authorization.AcceptGrant.request.json │ ├── Authorization.AcceptGrant.response.json │ └── ErrorResponse.Authorization.ACCEPT_GRANT_FAILED.json ├── BrightnessController │ ├── BrightnessController.AdjustBrightness.request.json │ ├── BrightnessController.AdjustBrightness.response.json │ ├── BrightnessController.SetBrightness.request.json │ └── BrightnessController.SetBrightness.response.json ├── CameraStreamController │ ├── CameraStreamController.request.json │ └── CameraStreamController.response.json ├── ChangeReport │ └── ChangeReport.json ├── ChannelController │ ├── ChannelController.ChangeChannel.request.json │ ├── ChannelController.SkipChannels.request.json │ └── ChannelController.response.json ├── ColorController │ ├── ColorController.SetColor.request.json │ └── ColorController.SetColor.response.json ├── ColorTemperatureController │ ├── ColorTemperatureController.DecreaseColorTemperature.request.json │ ├── ColorTemperatureController.IncreaseColorTemperature.request.json │ ├── ColorTemperatureController.SetColorTemperature.request.json │ └── ColorTemperatureController.response.json ├── DeferredResponse │ └── DeferredResponse.json ├── Discovery │ ├── Discovery.request.json │ └── Discovery.response.json ├── ErrorResponse │ ├── ErrorResponse.General.ENDPOINT_LOW_POWER.json │ ├── ErrorResponse.General.TEMPERATURE_VALUE_OUT_OF_RANGE.json │ ├── ErrorResponse.General.VALUE_OUT_OF_RANGE.json │ ├── ErrorResponse.General.json │ └── README.md ├── InputController │ ├── InputController.SelectInput.request.json │ └── InputController.SelectInput.response.json ├── LockController │ ├── LockController.Lock.request.json │ ├── LockController.Lock.response.json │ ├── LockController.Unlock.request.json │ ├── LockController.Unlock.response.json │ └── README.md ├── PercentageController │ ├── PercentageController.AdjustPercentage.request.json │ ├── PercentageController.SetPercentage.request.json │ └── PercentageController.response.json ├── PlaybackController │ ├── PlaybackController.FastForward.request.json │ ├── PlaybackController.Next.request.json │ ├── PlaybackController.Pause.request.json │ ├── PlaybackController.Play.request.json │ ├── PlaybackController.Previous.request.json │ ├── PlaybackController.Rewind.request.json │ ├── PlaybackController.StartOver.request.json │ ├── PlaybackController.Stop.request.json │ └── PlaybackController.response.json ├── PowerController │ ├── PowerController.TurnOff.request.json │ ├── PowerController.TurnOff.response.json │ ├── PowerController.TurnOn.request.json │ └── PowerController.TurnOn.response.json ├── PowerLevelController │ ├── PowerLevelController.AdjustPowerLevel.request.json │ ├── PowerLevelController.SetPowerLevel.request.json │ └── PowerLevelController.response.json ├── README.md ├── SceneController │ ├── SceneController.Activate.request.json │ ├── SceneController.ActivationStarted.message.json │ ├── SceneController.Deactivate.request.json │ └── SceneController.DeactivationStarted.message.json ├── Speaker │ ├── Speaker.AdjustVolume.request.json │ ├── Speaker.SetMute.request.json │ ├── Speaker.SetVolume.request.json │ └── Speaker.response.json ├── StateReport │ ├── ReportState.json │ └── StateReport.json ├── StepSpeaker │ ├── StepSpeaker.AdjustVolume.request.json │ ├── StepSpeaker.SetMute.request.json │ └── StepSpeaker.response.json ├── TemperatureSensor │ └── TemperatureSensor.response.json └── ThermostatController │ ├── ErrorResponse.ThermostatController.General.json │ ├── ErrorResponse.ThermostatController.REQUESTED_SETPOINTS_TOO_CLOSE.json │ ├── ThermostatController.AdjustTargetTemperature.request.json │ ├── ThermostatController.SetTargetTemperature.DualMode.request.json │ ├── ThermostatController.SetTargetTemperature.DualMode.response.json │ ├── ThermostatController.SetTargetTemperature.SingleMode.request.json │ ├── ThermostatController.SetTargetTemperature.SingleMode.response.json │ ├── ThermostatController.SetTargetTemperature.TripleMode.request.json │ ├── ThermostatController.SetTargetTemperature.TripleMode.response.json │ └── ThermostatController.SetThermostatMode.request.json ├── validation_schemas ├── README.md └── alexa_smart_home_message_schema.json └── works_with_alexa └── WWA_Submission Form.xlsx /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | endpoint-package.zip 3 | skill-package.zip 4 | sample_lambda/python/python.zip 5 | __pycache__ 6 | *.txt 7 | sample_lambda/python/alexa_smart_home_message_schema.json 8 | sample_lambda/python/lambda1.py 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/alexa/alexa-smarthome/issues), or [recently closed](https://github.com/alexa/alexa-smarthome/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/alexa/alexa-smarthome/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/alexa/alexa-smarthome/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Amazon Software License 1.0 2 | 3 | This Amazon Software License ("License") governs your use, reproduction, and 4 | distribution of the accompanying software as specified below. 5 | 6 | 1. Definitions 7 | 8 | "Licensor" means any person or entity that distributes its Work. 9 | 10 | "Software" means the original work of authorship made available under this 11 | License. 12 | 13 | "Work" means the Software and any additions to or derivative works of the 14 | Software that are made available under this License. 15 | 16 | The terms "reproduce," "reproduction," "derivative works," and 17 | "distribution" have the meaning as provided under U.S. copyright law; 18 | provided, however, that for the purposes of this License, derivative works 19 | shall not include works that remain separable from, or merely link (or bind 20 | by name) to the interfaces of, the Work. 21 | 22 | Works, including the Software, are "made available" under this License by 23 | including in or with the Work either (a) a copyright notice referencing the 24 | applicability of this License to the Work, or (b) a copy of this License. 25 | 26 | 2. License Grants 27 | 28 | 2.1 Copyright Grant. Subject to the terms and conditions of this License, 29 | each Licensor grants to you a perpetual, worldwide, non-exclusive, 30 | royalty-free, copyright license to reproduce, prepare derivative works of, 31 | publicly display, publicly perform, sublicense and distribute its Work and 32 | any resulting derivative works in any form. 33 | 34 | 2.2 Patent Grant. Subject to the terms and conditions of this License, each 35 | Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free 36 | patent license to make, have made, use, sell, offer for sale, import, and 37 | otherwise transfer its Work, in whole or in part. The foregoing license 38 | applies only to the patent claims licensable by Licensor that would be 39 | infringed by Licensor's Work (or portion thereof) individually and 40 | excluding any combinations with any other materials or technology. 41 | 42 | 3. Limitations 43 | 44 | 3.1 Redistribution. You may reproduce or distribute the Work only if 45 | (a) you do so under this License, (b) you include a complete copy of this 46 | License with your distribution, and (c) you retain without modification 47 | any copyright, patent, trademark, or attribution notices that are present 48 | in the Work. 49 | 50 | 3.2 Derivative Works. You may specify that additional or different terms 51 | apply to the use, reproduction, and distribution of your derivative works 52 | of the Work ("Your Terms") only if (a) Your Terms provide that the use 53 | limitation in Section 3.3 applies to your derivative works, and (b) you 54 | identify the specific derivative works that are subject to Your Terms. 55 | Notwithstanding Your Terms, this License (including the redistribution 56 | requirements in Section 3.1) will continue to apply to the Work itself. 57 | 58 | 3.3 Use Limitation. The Work and any derivative works thereof only may be 59 | used or intended for use with the web services, computing platforms or 60 | applications provided by Amazon.com, Inc. or its affiliates, including 61 | Amazon Web Services, Inc. 62 | 63 | 3.4 Patent Claims. If you bring or threaten to bring a patent claim against 64 | any Licensor (including any claim, cross-claim or counterclaim in a 65 | lawsuit) to enforce any patents that you allege are infringed by any Work, 66 | then your rights under this License from such Licensor (including the 67 | grants in Sections 2.1 and 2.2) will terminate immediately. 68 | 69 | 3.5 Trademarks. This License does not grant any rights to use any 70 | Licensor's or its affiliates' names, logos, or trademarks, except as 71 | necessary to reproduce the notices described in this License. 72 | 73 | 3.6 Termination. If you violate any term of this License, then your rights 74 | under this License (including the grants in Sections 2.1 and 2.2) will 75 | terminate immediately. 76 | 77 | 4. Disclaimer of Warranty. 78 | 79 | THE WORK IS PROVIDED "AS IS" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 80 | EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF 81 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR 82 | NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER 83 | THIS LICENSE. SOME STATES' CONSUMER LAWS DO NOT ALLOW EXCLUSION OF AN 84 | IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO YOU. 85 | 86 | 5. Limitation of Liability. 87 | 88 | EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL 89 | THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE 90 | SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, 91 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR 92 | RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING 93 | BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS 94 | OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES 95 | OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF 96 | SUCH DAMAGES. 97 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | Alexa Smart Home Skill API PRIVATE Repository 2 | 3 | Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alexa Smart Home Resources 2 | 3 | This repository contains resources for Alexa Smart Home developers. 4 | 5 | For information on how to get started, developer documentation, and API references, please visit the [Alexa Smart Home developer pages](https://developer.amazon.com/alexa/smart-home). 6 | 7 | ## Alexa Smart Home Samples 8 | 9 | ### Skill Sample : Switch 10 | A basic skill sample implementing a switch exercising the discovery and directive handling process for a virtual device implementing Alexa Smart Home switch capabilities. Available in [Python](https://github.com/alexa/skill-sample-python-smarthome-switch), [Node.js](https://github.com/alexa-samples/skill-sample-nodejs-smarthome-switch), [Java](https://github.com/alexa-samples/skill-sample-java-smarthome-switch). 11 | 12 | ## Additional Content 13 | 14 | - [Smart Home Skill Concepts](https://developer.amazon.com/en-US/docs/alexa/smarthome/smart-home-skill-concepts.html) 15 | - [Implement Smart Home Skill Code](https://developer.amazon.com/en-US/docs/alexa/smarthome/implement-your-skill.html) 16 | - [Send Events to the Alexa Event Gateway](https://developer.amazon.com/en-US/docs/alexa/smarthome/send-events-to-the-alexa-event-gateway.html) 17 | - [Smart Home Skill APIs](https://developer.amazon.com/en-US/docs/alexa/device-apis/smart-home-general-apis.html) 18 | 19 | ## Support and Feedback 20 | 21 | If you find an issue with the sample code, please open an issue against the relevant repository issue tracker. 22 | -------------------------------------------------------------------------------- /capability_evaluations/test_plans/PowerController: -------------------------------------------------------------------------------- 1 | { 2 | "name": "PowerController", 3 | "testCases": [ 4 | { 5 | "name": "DevRe_1.0", 6 | "initialSetups": [ 7 | { 8 | "capabilityState": { 9 | "namespace": "Alexa.PowerController", 10 | "name": "powerState", 11 | "value": "OFF" 12 | }, 13 | "directive": { 14 | "header": { 15 | "namespace": "Alexa.PowerController", 16 | "name": "TurnOff" 17 | }, 18 | "payload": null 19 | } 20 | } 21 | ], 22 | "directive": { 23 | "header": { 24 | "namespace": "Alexa.PowerController", 25 | "name": "TurnOn" 26 | }, 27 | "payload": null 28 | }, 29 | "expectedCapabilityStates": [ 30 | { 31 | "namespace": "Alexa.PowerController", 32 | "name": "powerState", 33 | "value": "ON" 34 | } 35 | ], 36 | "capabilityTolerances": [ 37 | { 38 | "namespace": "Alexa.PowerController", 39 | "name": "powerState", 40 | "percentThreshold": 0 41 | } 42 | ] 43 | }, 44 | { 45 | "name": "DevRe_1.1", 46 | "initialSetups": [ 47 | { 48 | "capabilityState": { 49 | "namespace": "Alexa.PowerController", 50 | "name": "powerState", 51 | "value": "ON" 52 | }, 53 | "directive": { 54 | "header": { 55 | "namespace": "Alexa.PowerController", 56 | "name": "TurnOn" 57 | }, 58 | "payload": null 59 | } 60 | } 61 | ], 62 | "directive": { 63 | "header": { 64 | "namespace": "Alexa.PowerController", 65 | "name": "TurnOff" 66 | }, 67 | "payload": null 68 | }, 69 | "expectedCapabilityStates": [ 70 | { 71 | "namespace": "Alexa.PowerController", 72 | "name": "powerState", 73 | "value": "OFF" 74 | } 75 | ], 76 | "capabilityTolerances": [ 77 | { 78 | "namespace": "Alexa.PowerController", 79 | "name": "powerState", 80 | "percentThreshold": 0 81 | } 82 | ] 83 | } 84 | ] 85 | } -------------------------------------------------------------------------------- /capability_evaluations/test_plans/ThermostatAuto: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ThermostatAuto", 3 | "testCases": [ 4 | { 5 | "name": "Auto_1.0", 6 | "initialSetups": [], 7 | "directive": { 8 | "header": { 9 | "namespace": "Alexa.ThermostatController", 10 | "name": "SetThermostatMode" 11 | }, 12 | "payload": { 13 | "thermostatMode": { 14 | "value": "AUTO" 15 | } 16 | } 17 | }, 18 | "expectedCapabilityStates": [ 19 | { 20 | "namespace": "Alexa.ThermostatController", 21 | "name": "thermostatMode", 22 | "value": "AUTO" 23 | } 24 | ], 25 | "capabilityTolerances": [ 26 | { 27 | "namespace": "Alexa.ThermostatController", 28 | "name": "thermostatMode", 29 | "percentThreshold": 2 30 | } 31 | ] 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /capability_evaluations/test_plans/ThermostatCool_CELSIUS: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ThermostatCool_CELSIUS", 3 | "testCases": [ 4 | { 5 | "name": "CelCool_1.2", 6 | "initialSetups": [ 7 | { 8 | "capabilityState": { 9 | "namespace": "Alexa.ThermostatController", 10 | "name": "thermostatMode", 11 | "value": "COOL" 12 | }, 13 | "directive": { 14 | "header": { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "SetThermostatMode" 17 | }, 18 | "payload": { 19 | "thermostatMode": { 20 | "value": "COOL" 21 | } 22 | } 23 | } 24 | }, 25 | { 26 | "capabilityState": { 27 | "namespace": "Alexa.ThermostatController", 28 | "name": "targetSetpoint", 29 | "value": { 30 | "value": 32.0, 31 | "scale": "CELSIUS" 32 | } 33 | }, 34 | "directive": { 35 | "header": { 36 | "namespace": "Alexa.ThermostatController", 37 | "name": "SetTargetTemperature" 38 | }, 39 | "payload": { 40 | "targetSetpoint": { 41 | "value": 32.0, 42 | "scale": "CELSIUS" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "directive": { 49 | "header": { 50 | "namespace": "Alexa.ThermostatController", 51 | "name": "SetTargetTemperature" 52 | }, 53 | "payload": { 54 | "targetSetpoint": { 55 | "value": 17, 56 | "scale": "CELSIUS" 57 | } 58 | } 59 | }, 60 | "expectedCapabilityStates": [ 61 | { 62 | "namespace": "Alexa.ThermostatController", 63 | "name": "targetSetpoint", 64 | "value": { 65 | "value": 17, 66 | "scale": "CELSIUS" 67 | } 68 | } 69 | ], 70 | "capabilityTolerances": [ 71 | { 72 | "namespace": "Alexa.ThermostatController", 73 | "name": "targetSetpoint", 74 | "percentThreshold": 2 75 | }, 76 | { 77 | "namespace": "Alexa.ThermostatController", 78 | "name": "thermostatMode", 79 | "percentThreshold": 0 80 | } 81 | ] 82 | }, 83 | { 84 | "name": "CelCool_1.3", 85 | "initialSetups": [ 86 | { 87 | "capabilityState": { 88 | "namespace": "Alexa.ThermostatController", 89 | "name": "thermostatMode", 90 | "value": "COOL" 91 | }, 92 | "directive": { 93 | "header": { 94 | "namespace": "Alexa.ThermostatController", 95 | "name": "SetThermostatMode" 96 | }, 97 | "payload": { 98 | "thermostatMode": { 99 | "value": "COOL" 100 | } 101 | } 102 | } 103 | }, 104 | { 105 | "capabilityState": { 106 | "namespace": "Alexa.ThermostatController", 107 | "name": "targetSetpoint", 108 | "value": { 109 | "value": 36, 110 | "scale": "CELSIUS" 111 | } 112 | }, 113 | "directive": { 114 | "header": { 115 | "namespace": "Alexa.ThermostatController", 116 | "name": "SetTargetTemperature" 117 | }, 118 | "payload": { 119 | "targetSetpoint": { 120 | "value": 36, 121 | "scale": "CELSIUS" 122 | } 123 | } 124 | } 125 | } 126 | ], 127 | "directive": { 128 | "header": { 129 | "namespace": "Alexa.ThermostatController", 130 | "name": "AdjustTargetTemperature" 131 | }, 132 | "payload": { 133 | "targetSetpointDelta": { 134 | "value": -6.0, 135 | "scale": "CELSIUS" 136 | } 137 | } 138 | }, 139 | "expectedCapabilityStates": [ 140 | { 141 | "namespace": "Alexa.ThermostatController", 142 | "name": "targetSetpoint", 143 | "value": { 144 | "value": 30, 145 | "scale": "CELSIUS" 146 | } 147 | } 148 | ], 149 | "capabilityTolerances": [ 150 | { 151 | "namespace": "Alexa.ThermostatController", 152 | "name": "targetSetpoint", 153 | "percentThreshold": 2 154 | }, 155 | { 156 | "namespace": "Alexa.ThermostatController", 157 | "name": "thermostatMode", 158 | "percentThreshold": 0 159 | } 160 | ] 161 | }, 162 | { 163 | "name": "CelCool_1.4", 164 | "initialSetups": [ 165 | { 166 | "capabilityState": { 167 | "namespace": "Alexa.ThermostatController", 168 | "name": "thermostatMode", 169 | "value": "COOL" 170 | }, 171 | "directive": { 172 | "header": { 173 | "namespace": "Alexa.ThermostatController", 174 | "name": "SetThermostatMode" 175 | }, 176 | "payload": { 177 | "thermostatMode": { 178 | "value": "COOL" 179 | } 180 | } 181 | } 182 | }, 183 | { 184 | "capabilityState": { 185 | "namespace": "Alexa.ThermostatController", 186 | "name": "targetSetpoint", 187 | "value": { 188 | "value": 24, 189 | "scale": "CELSIUS" 190 | } 191 | }, 192 | "directive": { 193 | "header": { 194 | "namespace": "Alexa.ThermostatController", 195 | "name": "SetTargetTemperature" 196 | }, 197 | "payload": { 198 | "targetSetpoint": { 199 | "value": 24, 200 | "scale": "CELSIUS" 201 | } 202 | } 203 | } 204 | } 205 | ], 206 | "directive": { 207 | "header": { 208 | "namespace": "Alexa.ThermostatController", 209 | "name": "AdjustTargetTemperature" 210 | }, 211 | "payload": { 212 | "targetSetpointDelta": { 213 | "value": 6.0, 214 | "scale": "CELSIUS" 215 | } 216 | } 217 | }, 218 | "expectedCapabilityStates": [ 219 | { 220 | "namespace": "Alexa.ThermostatController", 221 | "name": "targetSetpoint", 222 | "value": { 223 | "value": 30, 224 | "scale": "CELSIUS" 225 | } 226 | } 227 | ], 228 | "capabilityTolerances": [ 229 | { 230 | "namespace": "Alexa.ThermostatController", 231 | "name": "targetSetpoint", 232 | "percentThreshold": 2 233 | }, 234 | { 235 | "namespace": "Alexa.ThermostatController", 236 | "name": "thermostatMode", 237 | "percentThreshold": 0 238 | } 239 | ] 240 | } 241 | ] 242 | } -------------------------------------------------------------------------------- /capability_evaluations/test_plans/ThermostatCool_FAHRENHEIT: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ThermostatCool_FAHRENHEIT", 3 | "testCases": [ 4 | { 5 | "name": "FahCool_1.2", 6 | "initialSetups": [ 7 | { 8 | "capabilityState": { 9 | "namespace": "Alexa.ThermostatController", 10 | "name": "thermostatMode", 11 | "value": "COOL" 12 | }, 13 | "directive": { 14 | "header": { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "SetThermostatMode" 17 | }, 18 | "payload": { 19 | "thermostatMode": { 20 | "value": "COOL" 21 | } 22 | } 23 | } 24 | }, 25 | { 26 | "capabilityState": { 27 | "namespace": "Alexa.ThermostatController", 28 | "name": "targetSetpoint", 29 | "value": { 30 | "value": 90, 31 | "scale": "FAHRENHEIT" 32 | } 33 | }, 34 | "directive": { 35 | "header": { 36 | "namespace": "Alexa.ThermostatController", 37 | "name": "SetTargetTemperature" 38 | }, 39 | "payload": { 40 | "targetSetpoint": { 41 | "value": 90, 42 | "scale": "FAHRENHEIT" 43 | } 44 | } 45 | } 46 | } 47 | ], 48 | "directive": { 49 | "header": { 50 | "namespace": "Alexa.ThermostatController", 51 | "name": "SetTargetTemperature" 52 | }, 53 | "payload": { 54 | "targetSetpoint": { 55 | "value": 64, 56 | "scale": "FAHRENHEIT" 57 | } 58 | } 59 | }, 60 | "expectedCapabilityStates": [ 61 | { 62 | "namespace": "Alexa.ThermostatController", 63 | "name": "targetSetpoint", 64 | "value": { 65 | "value": 64, 66 | "scale": "FAHRENHEIT" 67 | } 68 | } 69 | ], 70 | "capabilityTolerances": [ 71 | { 72 | "namespace": "Alexa.ThermostatController", 73 | "name": "targetSetpoint", 74 | "percentThreshold": 2 75 | }, 76 | { 77 | "namespace": "Alexa.ThermostatController", 78 | "name": "thermostatMode", 79 | "percentThreshold": 0 80 | } 81 | ] 82 | }, 83 | { 84 | "name": "FahCool_1.3", 85 | "initialSetups": [ 86 | { 87 | "capabilityState": { 88 | "namespace": "Alexa.ThermostatController", 89 | "name": "thermostatMode", 90 | "value": "COOL" 91 | }, 92 | "directive": { 93 | "header": { 94 | "namespace": "Alexa.ThermostatController", 95 | "name": "SetThermostatMode" 96 | }, 97 | "payload": { 98 | "thermostatMode": { 99 | "value": "COOL" 100 | } 101 | } 102 | } 103 | }, 104 | { 105 | "capabilityState": { 106 | "namespace": "Alexa.ThermostatController", 107 | "name": "targetSetpoint", 108 | "value": { 109 | "value": 90, 110 | "scale": "FAHRENHEIT" 111 | } 112 | }, 113 | "directive": { 114 | "header": { 115 | "namespace": "Alexa.ThermostatController", 116 | "name": "SetTargetTemperature" 117 | }, 118 | "payload": { 119 | "targetSetpoint": { 120 | "value": 90, 121 | "scale": "FAHRENHEIT" 122 | } 123 | } 124 | } 125 | } 126 | ], 127 | "directive": { 128 | "header": { 129 | "namespace": "Alexa.ThermostatController", 130 | "name": "AdjustTargetTemperature" 131 | }, 132 | "payload": { 133 | "targetSetpointDelta": { 134 | "value": -6.0, 135 | "scale": "FAHRENHEIT" 136 | } 137 | } 138 | }, 139 | "expectedCapabilityStates": [ 140 | { 141 | "namespace": "Alexa.ThermostatController", 142 | "name": "targetSetpoint", 143 | "value": { 144 | "value": 84, 145 | "scale": "FAHRENHEIT" 146 | } 147 | } 148 | ], 149 | "capabilityTolerances": [ 150 | { 151 | "namespace": "Alexa.ThermostatController", 152 | "name": "targetSetpoint", 153 | "percentThreshold": 2 154 | }, 155 | { 156 | "namespace": "Alexa.ThermostatController", 157 | "name": "thermostatMode", 158 | "percentThreshold": 0 159 | } 160 | ] 161 | }, 162 | { 163 | "name": "FahCool_1.4", 164 | "initialSetups": [ 165 | { 166 | "capabilityState": { 167 | "namespace": "Alexa.ThermostatController", 168 | "name": "thermostatMode", 169 | "value": "COOL" 170 | }, 171 | "directive": { 172 | "header": { 173 | "namespace": "Alexa.ThermostatController", 174 | "name": "SetThermostatMode" 175 | }, 176 | "payload": { 177 | "thermostatMode": { 178 | "value": "COOL" 179 | } 180 | } 181 | } 182 | }, 183 | { 184 | "capabilityState": { 185 | "namespace": "Alexa.ThermostatController", 186 | "name": "targetSetpoint", 187 | "value": { 188 | "value": 74, 189 | "scale": "FAHRENHEIT" 190 | } 191 | }, 192 | "directive": { 193 | "header": { 194 | "namespace": "Alexa.ThermostatController", 195 | "name": "SetTargetTemperature" 196 | }, 197 | "payload": { 198 | "targetSetpoint": { 199 | "value": 74, 200 | "scale": "FAHRENHEIT" 201 | } 202 | } 203 | } 204 | } 205 | ], 206 | "directive": { 207 | "header": { 208 | "namespace": "Alexa.ThermostatController", 209 | "name": "AdjustTargetTemperature" 210 | }, 211 | "payload": { 212 | "targetSetpointDelta": { 213 | "value": 6.0, 214 | "scale": "FAHRENHEIT" 215 | } 216 | } 217 | }, 218 | "expectedCapabilityStates": [ 219 | { 220 | "namespace": "Alexa.ThermostatController", 221 | "name": "targetSetpoint", 222 | "value": { 223 | "value": 80, 224 | "scale": "FAHRENHEIT" 225 | } 226 | } 227 | ], 228 | "capabilityTolerances": [ 229 | { 230 | "namespace": "Alexa.ThermostatController", 231 | "name": "targetSetpoint", 232 | "percentThreshold": 2 233 | }, 234 | { 235 | "namespace": "Alexa.ThermostatController", 236 | "name": "thermostatMode", 237 | "percentThreshold": 0 238 | } 239 | ] 240 | } 241 | ] 242 | } -------------------------------------------------------------------------------- /capability_evaluations/test_plans/ThermostatHeat_CELSIUS: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ThermostatHeat_CELSIUS", 3 | "testCases": [ 4 | { 5 | "name": "CelHeat_1.2", 6 | "initialSetups": [ 7 | { 8 | "capabilityState": { 9 | "namespace": "Alexa.ThermostatController", 10 | "name": "thermostatMode", 11 | "value": "HEAT" 12 | }, 13 | "directive": { 14 | "header": { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "SetThermostatMode" 17 | }, 18 | "payload": { 19 | "thermostatMode": { 20 | "value": "HEAT" 21 | } 22 | } 23 | } 24 | } 25 | ], 26 | "directive": { 27 | "header": { 28 | "namespace": "Alexa.ThermostatController", 29 | "name": "SetTargetTemperature" 30 | }, 31 | "payload": { 32 | "targetSetpoint": { 33 | "value": 17, 34 | "scale": "CELSIUS" 35 | } 36 | } 37 | }, 38 | "expectedCapabilityStates": [ 39 | { 40 | "namespace": "Alexa.ThermostatController", 41 | "name": "targetSetpoint", 42 | "value": { 43 | "value": 17.0, 44 | "scale": "CELSIUS" 45 | } 46 | } 47 | ], 48 | "capabilityTolerances": [ 49 | { 50 | "namespace": "Alexa.ThermostatController", 51 | "name": "targetSetpoint", 52 | "percentThreshold": 2 53 | }, 54 | { 55 | "namespace": "Alexa.ThermostatController", 56 | "name": "thermostatMode", 57 | "percentThreshold": 0 58 | } 59 | ] 60 | }, 61 | { 62 | "name": "CelHeat_1.3", 63 | "initialSetups": [ 64 | { 65 | "capabilityState": { 66 | "namespace": "Alexa.ThermostatController", 67 | "name": "thermostatMode", 68 | "value": "HEAT" 69 | }, 70 | "directive": { 71 | "header": { 72 | "namespace": "Alexa.ThermostatController", 73 | "name": "SetThermostatMode" 74 | }, 75 | "payload": { 76 | "thermostatMode": { 77 | "value": "HEAT" 78 | } 79 | } 80 | } 81 | }, 82 | { 83 | "capabilityState": { 84 | "namespace": "Alexa.ThermostatController", 85 | "name": "targetSetpoint", 86 | "value": { 87 | "value": 10.0, 88 | "scale": "CELSIUS" 89 | } 90 | }, 91 | "directive": { 92 | "header": { 93 | "namespace": "Alexa.ThermostatController", 94 | "name": "SetTargetTemperature" 95 | }, 96 | "payload": { 97 | "targetSetpoint": { 98 | "value": 10.0, 99 | "scale": "CELSIUS" 100 | } 101 | } 102 | } 103 | } 104 | ], 105 | "directive": { 106 | "header": { 107 | "namespace": "Alexa.ThermostatController", 108 | "name": "AdjustTargetTemperature" 109 | }, 110 | "payload": { 111 | "targetSetpointDelta": { 112 | "value": 6.0, 113 | "scale": "CELSIUS" 114 | } 115 | } 116 | }, 117 | "expectedCapabilityStates": [ 118 | { 119 | "namespace": "Alexa.ThermostatController", 120 | "name": "targetSetpoint", 121 | "value": { 122 | "value": 16.0, 123 | "scale": "CELSIUS" 124 | } 125 | } 126 | ], 127 | "capabilityTolerances": [ 128 | { 129 | "namespace": "Alexa.ThermostatController", 130 | "name": "targetSetpoint", 131 | "percentThreshold": 2 132 | }, 133 | { 134 | "namespace": "Alexa.ThermostatController", 135 | "name": "thermostatMode", 136 | "percentThreshold": 0 137 | } 138 | ] 139 | }, 140 | { 141 | "name": "CelHeat_1.4", 142 | "initialSetups": [ 143 | { 144 | "capabilityState": { 145 | "namespace": "Alexa.ThermostatController", 146 | "name": "thermostatMode", 147 | "value": "HEAT" 148 | }, 149 | "directive": { 150 | "header": { 151 | "namespace": "Alexa.ThermostatController", 152 | "name": "SetThermostatMode" 153 | }, 154 | "payload": { 155 | "thermostatMode": { 156 | "value": "HEAT" 157 | } 158 | } 159 | } 160 | }, 161 | { 162 | "capabilityState": { 163 | "namespace": "Alexa.ThermostatController", 164 | "name": "targetSetpoint", 165 | "value": { 166 | "value": 26.0, 167 | "scale": "CELSIUS" 168 | } 169 | }, 170 | "directive": { 171 | "header": { 172 | "namespace": "Alexa.ThermostatController", 173 | "name": "SetTargetTemperature" 174 | }, 175 | "payload": { 176 | "targetSetpoint": { 177 | "value": 26.0, 178 | "scale": "CELSIUS" 179 | } 180 | } 181 | } 182 | } 183 | ], 184 | "directive": { 185 | "header": { 186 | "namespace": "Alexa.ThermostatController", 187 | "name": "AdjustTargetTemperature" 188 | }, 189 | "payload": { 190 | "targetSetpointDelta": { 191 | "value": -6.0, 192 | "scale": "CELSIUS" 193 | } 194 | } 195 | }, 196 | "expectedCapabilityStates": [ 197 | { 198 | "namespace": "Alexa.ThermostatController", 199 | "name": "targetSetpoint", 200 | "value": { 201 | "value": 20.0, 202 | "scale": "CELSIUS" 203 | } 204 | } 205 | ], 206 | "capabilityTolerances": [ 207 | { 208 | "namespace": "Alexa.ThermostatController", 209 | "name": "targetSetpoint", 210 | "percentThreshold": 2 211 | }, 212 | { 213 | "namespace": "Alexa.ThermostatController", 214 | "name": "thermostatMode", 215 | "percentThreshold": 0 216 | } 217 | ] 218 | } 219 | ] 220 | } -------------------------------------------------------------------------------- /capability_evaluations/test_plans/ThermostatHeat_FAHRENHEIT: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ThermostatHeat_FAHRENHEIT", 3 | "testCases": [ 4 | { 5 | "name": "FahHeat_1.2", 6 | "initialSetups": [ 7 | { 8 | "capabilityState": { 9 | "namespace": "Alexa.ThermostatController", 10 | "name": "thermostatMode", 11 | "value": "HEAT" 12 | }, 13 | "directive": { 14 | "header": { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "SetThermostatMode" 17 | }, 18 | "payload": { 19 | "thermostatMode": { 20 | "value": "HEAT" 21 | } 22 | } 23 | } 24 | } 25 | ], 26 | "directive": { 27 | "header": { 28 | "namespace": "Alexa.ThermostatController", 29 | "name": "SetTargetTemperature" 30 | }, 31 | "payload": { 32 | "targetSetpoint": { 33 | "value": 64, 34 | "scale": "FAHRENHEIT" 35 | } 36 | } 37 | }, 38 | "expectedCapabilityStates": [ 39 | { 40 | "namespace": "Alexa.ThermostatController", 41 | "name": "targetSetpoint", 42 | "value": { 43 | "value": 64, 44 | "scale": "FAHRENHEIT" 45 | } 46 | } 47 | ], 48 | "capabilityTolerances": [ 49 | { 50 | "namespace": "Alexa.ThermostatController", 51 | "name": "targetSetpoint", 52 | "percentThreshold": 2 53 | }, 54 | { 55 | "namespace": "Alexa.ThermostatController", 56 | "name": "thermostatMode", 57 | "percentThreshold": 0 58 | } 59 | ] 60 | }, 61 | { 62 | "name": "FahHeat_1.3", 63 | "initialSetups": [ 64 | { 65 | "capabilityState": { 66 | "namespace": "Alexa.ThermostatController", 67 | "name": "thermostatMode", 68 | "value": "HEAT" 69 | }, 70 | "directive": { 71 | "header": { 72 | "namespace": "Alexa.ThermostatController", 73 | "name": "SetThermostatMode" 74 | }, 75 | "payload": { 76 | "thermostatMode": { 77 | "value": "HEAT" 78 | } 79 | } 80 | } 81 | }, 82 | { 83 | "capabilityState": { 84 | "namespace": "Alexa.ThermostatController", 85 | "name": "targetSetpoint", 86 | "value": { 87 | "value": 54, 88 | "scale": "FAHRENHEIT" 89 | } 90 | }, 91 | "directive": { 92 | "header": { 93 | "namespace": "Alexa.ThermostatController", 94 | "name": "SetTargetTemperature" 95 | }, 96 | "payload": { 97 | "targetSetpoint": { 98 | "value": 54, 99 | "scale": "FAHRENHEIT" 100 | } 101 | } 102 | } 103 | } 104 | ], 105 | "directive": { 106 | "header": { 107 | "namespace": "Alexa.ThermostatController", 108 | "name": "AdjustTargetTemperature" 109 | }, 110 | "payload": { 111 | "targetSetpointDelta": { 112 | "value": 6.0, 113 | "scale": "FAHRENHEIT" 114 | } 115 | } 116 | }, 117 | "expectedCapabilityStates": [ 118 | { 119 | "namespace": "Alexa.ThermostatController", 120 | "name": "targetSetpoint", 121 | "value": { 122 | "value": 60, 123 | "scale": "FAHRENHEIT" 124 | } 125 | } 126 | ], 127 | "capabilityTolerances": [ 128 | { 129 | "namespace": "Alexa.ThermostatController", 130 | "name": "targetSetpoint", 131 | "percentThreshold": 2 132 | }, 133 | { 134 | "namespace": "Alexa.ThermostatController", 135 | "name": "thermostatMode", 136 | "percentThreshold": 0 137 | } 138 | ] 139 | }, 140 | { 141 | "name": "FahHeat_1.4", 142 | "initialSetups": [ 143 | { 144 | "capabilityState": { 145 | "namespace": "Alexa.ThermostatController", 146 | "name": "thermostatMode", 147 | "value": "HEAT" 148 | }, 149 | "directive": { 150 | "header": { 151 | "namespace": "Alexa.ThermostatController", 152 | "name": "SetThermostatMode" 153 | }, 154 | "payload": { 155 | "thermostatMode": { 156 | "value": "HEAT" 157 | } 158 | } 159 | } 160 | }, 161 | { 162 | "capabilityState": { 163 | "namespace": "Alexa.ThermostatController", 164 | "name": "targetSetpoint", 165 | "value": { 166 | "value": 60, 167 | "scale": "FAHRENHEIT" 168 | } 169 | }, 170 | "directive": { 171 | "header": { 172 | "namespace": "Alexa.ThermostatController", 173 | "name": "SetTargetTemperature" 174 | }, 175 | "payload": { 176 | "targetSetpoint": { 177 | "value": 60, 178 | "scale": "FAHRENHEIT" 179 | } 180 | } 181 | } 182 | } 183 | ], 184 | "directive": { 185 | "header": { 186 | "namespace": "Alexa.ThermostatController", 187 | "name": "AdjustTargetTemperature" 188 | }, 189 | "payload": { 190 | "targetSetpointDelta": { 191 | "value": -6.0, 192 | "scale": "FAHRENHEIT" 193 | } 194 | } 195 | }, 196 | "expectedCapabilityStates": [ 197 | { 198 | "namespace": "Alexa.ThermostatController", 199 | "name": "targetSetpoint", 200 | "value": { 201 | "value": 54, 202 | "scale": "FAHRENHEIT" 203 | } 204 | } 205 | ], 206 | "capabilityTolerances": [ 207 | { 208 | "namespace": "Alexa.ThermostatController", 209 | "name": "targetSetpoint", 210 | "percentThreshold": 2 211 | }, 212 | { 213 | "namespace": "Alexa.ThermostatController", 214 | "name": "thermostatMode", 215 | "percentThreshold": 0 216 | } 217 | ] 218 | } 219 | ] 220 | } -------------------------------------------------------------------------------- /sample_async/README.md: -------------------------------------------------------------------------------- 1 | Readme: https://github.com/alexa/alexa-smarthome/wiki/Sample-Async-Messaging 2 | -------------------------------------------------------------------------------- /sample_lambda/README.md: -------------------------------------------------------------------------------- 1 | Readme: https://github.com/alexa/alexa-smarthome/wiki/Sample-Lambda 2 | -------------------------------------------------------------------------------- /sample_lambda/python/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/__init__.py -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | An implementation of JSON Schema for Python 3 | 4 | The main functionality is provided by the validator classes for each of the 5 | supported JSON Schema versions. 6 | 7 | Most commonly, :func:`validate` is the quickest way to simply validate a given 8 | instance under a schema, and will create a validator for you. 9 | 10 | """ 11 | 12 | from jsonschema.exceptions import ( 13 | ErrorTree, FormatError, RefResolutionError, SchemaError, ValidationError 14 | ) 15 | from jsonschema._format import ( 16 | FormatChecker, draft3_format_checker, draft4_format_checker, 17 | ) 18 | from jsonschema.validators import ( 19 | Draft3Validator, Draft4Validator, RefResolver, validate 20 | ) 21 | 22 | #from jsonschema._version import __version__ 23 | 24 | # flake8: noqa 25 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__main__.py: -------------------------------------------------------------------------------- 1 | from jsonschema.cli import main 2 | main() 3 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/_format.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/_format.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/_utils.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/_utils.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/_validators.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/_validators.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/compat.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/compat.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/exceptions.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/exceptions.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/__pycache__/validators.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/__pycache__/validators.cpython-36.pyc -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/_format.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import re 3 | import socket 4 | 5 | from jsonschema.compat import str_types 6 | from jsonschema.exceptions import FormatError 7 | 8 | 9 | class FormatChecker(object): 10 | """ 11 | A ``format`` property checker. 12 | 13 | JSON Schema does not mandate that the ``format`` property actually do any 14 | validation. If validation is desired however, instances of this class can 15 | be hooked into validators to enable format validation. 16 | 17 | :class:`FormatChecker` objects always return ``True`` when asked about 18 | formats that they do not know how to validate. 19 | 20 | To check a custom format using a function that takes an instance and 21 | returns a ``bool``, use the :meth:`FormatChecker.checks` or 22 | :meth:`FormatChecker.cls_checks` decorators. 23 | 24 | Arguments: 25 | 26 | formats (iterable): 27 | 28 | The known formats to validate. This argument can be used to 29 | limit which formats will be used during validation. 30 | 31 | """ 32 | 33 | checkers = {} 34 | 35 | def __init__(self, formats=None): 36 | if formats is None: 37 | self.checkers = self.checkers.copy() 38 | else: 39 | self.checkers = dict((k, self.checkers[k]) for k in formats) 40 | 41 | def checks(self, format, raises=()): 42 | """ 43 | Register a decorated function as validating a new format. 44 | 45 | Arguments: 46 | 47 | format (str): 48 | 49 | The format that the decorated function will check. 50 | 51 | raises (Exception): 52 | 53 | The exception(s) raised by the decorated function when 54 | an invalid instance is found. 55 | 56 | The exception object will be accessible as the 57 | :attr:`ValidationError.cause` attribute of the resulting 58 | validation error. 59 | 60 | """ 61 | 62 | def _checks(func): 63 | self.checkers[format] = (func, raises) 64 | return func 65 | return _checks 66 | 67 | cls_checks = classmethod(checks) 68 | 69 | def check(self, instance, format): 70 | """ 71 | Check whether the instance conforms to the given format. 72 | 73 | Arguments: 74 | 75 | instance (any primitive type, i.e. str, number, bool): 76 | 77 | The instance to check 78 | 79 | format (str): 80 | 81 | The format that instance should conform to 82 | 83 | 84 | Raises: 85 | 86 | :exc:`FormatError` if instance does not conform to ``format`` 87 | 88 | """ 89 | 90 | if format not in self.checkers: 91 | return 92 | 93 | func, raises = self.checkers[format] 94 | result, cause = None, None 95 | try: 96 | result = func(instance) 97 | except raises as e: 98 | cause = e 99 | if not result: 100 | raise FormatError( 101 | "%r is not a %r" % (instance, format), cause=cause, 102 | ) 103 | 104 | def conforms(self, instance, format): 105 | """ 106 | Check whether the instance conforms to the given format. 107 | 108 | Arguments: 109 | 110 | instance (any primitive type, i.e. str, number, bool): 111 | 112 | The instance to check 113 | 114 | format (str): 115 | 116 | The format that instance should conform to 117 | 118 | Returns: 119 | 120 | bool: Whether it conformed 121 | 122 | """ 123 | 124 | try: 125 | self.check(instance, format) 126 | except FormatError: 127 | return False 128 | else: 129 | return True 130 | 131 | 132 | _draft_checkers = {"draft3": [], "draft4": []} 133 | 134 | 135 | def _checks_drafts(both=None, draft3=None, draft4=None, raises=()): 136 | draft3 = draft3 or both 137 | draft4 = draft4 or both 138 | 139 | def wrap(func): 140 | if draft3: 141 | _draft_checkers["draft3"].append(draft3) 142 | func = FormatChecker.cls_checks(draft3, raises)(func) 143 | if draft4: 144 | _draft_checkers["draft4"].append(draft4) 145 | func = FormatChecker.cls_checks(draft4, raises)(func) 146 | return func 147 | return wrap 148 | 149 | 150 | @_checks_drafts("email") 151 | def is_email(instance): 152 | if not isinstance(instance, str_types): 153 | return True 154 | return "@" in instance 155 | 156 | 157 | _ipv4_re = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") 158 | 159 | 160 | @_checks_drafts(draft3="ip-address", draft4="ipv4") 161 | def is_ipv4(instance): 162 | if not isinstance(instance, str_types): 163 | return True 164 | if not _ipv4_re.match(instance): 165 | return False 166 | return all(0 <= int(component) <= 255 for component in instance.split(".")) 167 | 168 | 169 | if hasattr(socket, "inet_pton"): 170 | @_checks_drafts("ipv6", raises=socket.error) 171 | def is_ipv6(instance): 172 | if not isinstance(instance, str_types): 173 | return True 174 | return socket.inet_pton(socket.AF_INET6, instance) 175 | 176 | 177 | _host_name_re = re.compile(r"^[A-Za-z0-9][A-Za-z0-9\.\-]{1,255}$") 178 | 179 | 180 | @_checks_drafts(draft3="host-name", draft4="hostname") 181 | def is_host_name(instance): 182 | if not isinstance(instance, str_types): 183 | return True 184 | if not _host_name_re.match(instance): 185 | return False 186 | components = instance.split(".") 187 | for component in components: 188 | if len(component) > 63: 189 | return False 190 | return True 191 | 192 | 193 | try: 194 | import rfc3987 195 | except ImportError: 196 | pass 197 | else: 198 | @_checks_drafts("uri", raises=ValueError) 199 | def is_uri(instance): 200 | if not isinstance(instance, str_types): 201 | return True 202 | return rfc3987.parse(instance, rule="URI") 203 | 204 | 205 | try: 206 | import strict_rfc3339 207 | except ImportError: 208 | try: 209 | import isodate 210 | except ImportError: 211 | pass 212 | else: 213 | @_checks_drafts("date-time", raises=(ValueError, isodate.ISO8601Error)) 214 | def is_datetime(instance): 215 | if not isinstance(instance, str_types): 216 | return True 217 | return isodate.parse_datetime(instance) 218 | else: 219 | @_checks_drafts("date-time") 220 | def is_datetime(instance): 221 | if not isinstance(instance, str_types): 222 | return True 223 | return strict_rfc3339.validate_rfc3339(instance) 224 | 225 | 226 | @_checks_drafts("regex", raises=re.error) 227 | def is_regex(instance): 228 | if not isinstance(instance, str_types): 229 | return True 230 | return re.compile(instance) 231 | 232 | 233 | @_checks_drafts(draft3="date", raises=ValueError) 234 | def is_date(instance): 235 | if not isinstance(instance, str_types): 236 | return True 237 | return datetime.datetime.strptime(instance, "%Y-%m-%d") 238 | 239 | 240 | @_checks_drafts(draft3="time", raises=ValueError) 241 | def is_time(instance): 242 | if not isinstance(instance, str_types): 243 | return True 244 | return datetime.datetime.strptime(instance, "%H:%M:%S") 245 | 246 | 247 | try: 248 | import webcolors 249 | except ImportError: 250 | pass 251 | else: 252 | def is_css_color_code(instance): 253 | return webcolors.normalize_hex(instance) 254 | 255 | @_checks_drafts(draft3="color", raises=(ValueError, TypeError)) 256 | def is_css21_color(instance): 257 | if ( 258 | not isinstance(instance, str_types) or 259 | instance.lower() in webcolors.css21_names_to_hex 260 | ): 261 | return True 262 | return is_css_color_code(instance) 263 | 264 | def is_css3_color(instance): 265 | if instance.lower() in webcolors.css3_names_to_hex: 266 | return True 267 | return is_css_color_code(instance) 268 | 269 | 270 | draft3_format_checker = FormatChecker(_draft_checkers["draft3"]) 271 | draft4_format_checker = FormatChecker(_draft_checkers["draft4"]) 272 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/_reflect.py: -------------------------------------------------------------------------------- 1 | # -*- test-case-name: twisted.test.test_reflect -*- 2 | # Copyright (c) Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | """ 6 | Standardized versions of various cool and/or strange things that you can do 7 | with Python's reflection capabilities. 8 | """ 9 | 10 | import sys 11 | 12 | from jsonschema.compat import PY3 13 | 14 | 15 | class _NoModuleFound(Exception): 16 | """ 17 | No module was found because none exists. 18 | """ 19 | 20 | 21 | 22 | class InvalidName(ValueError): 23 | """ 24 | The given name is not a dot-separated list of Python objects. 25 | """ 26 | 27 | 28 | 29 | class ModuleNotFound(InvalidName): 30 | """ 31 | The module associated with the given name doesn't exist and it can't be 32 | imported. 33 | """ 34 | 35 | 36 | 37 | class ObjectNotFound(InvalidName): 38 | """ 39 | The object associated with the given name doesn't exist and it can't be 40 | imported. 41 | """ 42 | 43 | 44 | 45 | if PY3: 46 | def reraise(exception, traceback): 47 | raise exception.with_traceback(traceback) 48 | else: 49 | exec("""def reraise(exception, traceback): 50 | raise exception.__class__, exception, traceback""") 51 | 52 | reraise.__doc__ = """ 53 | Re-raise an exception, with an optional traceback, in a way that is compatible 54 | with both Python 2 and Python 3. 55 | 56 | Note that on Python 3, re-raised exceptions will be mutated, with their 57 | C{__traceback__} attribute being set. 58 | 59 | @param exception: The exception instance. 60 | @param traceback: The traceback to use, or C{None} indicating a new traceback. 61 | """ 62 | 63 | 64 | def _importAndCheckStack(importName): 65 | """ 66 | Import the given name as a module, then walk the stack to determine whether 67 | the failure was the module not existing, or some code in the module (for 68 | example a dependent import) failing. This can be helpful to determine 69 | whether any actual application code was run. For example, to distiguish 70 | administrative error (entering the wrong module name), from programmer 71 | error (writing buggy code in a module that fails to import). 72 | 73 | @param importName: The name of the module to import. 74 | @type importName: C{str} 75 | @raise Exception: if something bad happens. This can be any type of 76 | exception, since nobody knows what loading some arbitrary code might 77 | do. 78 | @raise _NoModuleFound: if no module was found. 79 | """ 80 | try: 81 | return __import__(importName) 82 | except ImportError: 83 | excType, excValue, excTraceback = sys.exc_info() 84 | while excTraceback: 85 | execName = excTraceback.tb_frame.f_globals["__name__"] 86 | # in Python 2 execName is None when an ImportError is encountered, 87 | # where in Python 3 execName is equal to the importName. 88 | if execName is None or execName == importName: 89 | reraise(excValue, excTraceback) 90 | excTraceback = excTraceback.tb_next 91 | raise _NoModuleFound() 92 | 93 | 94 | 95 | def namedAny(name): 96 | """ 97 | Retrieve a Python object by its fully qualified name from the global Python 98 | module namespace. The first part of the name, that describes a module, 99 | will be discovered and imported. Each subsequent part of the name is 100 | treated as the name of an attribute of the object specified by all of the 101 | name which came before it. For example, the fully-qualified name of this 102 | object is 'twisted.python.reflect.namedAny'. 103 | 104 | @type name: L{str} 105 | @param name: The name of the object to return. 106 | 107 | @raise InvalidName: If the name is an empty string, starts or ends with 108 | a '.', or is otherwise syntactically incorrect. 109 | 110 | @raise ModuleNotFound: If the name is syntactically correct but the 111 | module it specifies cannot be imported because it does not appear to 112 | exist. 113 | 114 | @raise ObjectNotFound: If the name is syntactically correct, includes at 115 | least one '.', but the module it specifies cannot be imported because 116 | it does not appear to exist. 117 | 118 | @raise AttributeError: If an attribute of an object along the way cannot be 119 | accessed, or a module along the way is not found. 120 | 121 | @return: the Python object identified by 'name'. 122 | """ 123 | if not name: 124 | raise InvalidName('Empty module name') 125 | 126 | names = name.split('.') 127 | 128 | # if the name starts or ends with a '.' or contains '..', the __import__ 129 | # will raise an 'Empty module name' error. This will provide a better error 130 | # message. 131 | if '' in names: 132 | raise InvalidName( 133 | "name must be a string giving a '.'-separated list of Python " 134 | "identifiers, not %r" % (name,)) 135 | 136 | topLevelPackage = None 137 | moduleNames = names[:] 138 | while not topLevelPackage: 139 | if moduleNames: 140 | trialname = '.'.join(moduleNames) 141 | try: 142 | topLevelPackage = _importAndCheckStack(trialname) 143 | except _NoModuleFound: 144 | moduleNames.pop() 145 | else: 146 | if len(names) == 1: 147 | raise ModuleNotFound("No module named %r" % (name,)) 148 | else: 149 | raise ObjectNotFound('%r does not name an object' % (name,)) 150 | 151 | obj = topLevelPackage 152 | for n in names[1:]: 153 | obj = getattr(obj, n) 154 | 155 | return obj 156 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/_utils.py: -------------------------------------------------------------------------------- 1 | import itertools 2 | import json 3 | import pkgutil 4 | import re 5 | 6 | from jsonschema.compat import str_types, MutableMapping, urlsplit 7 | 8 | 9 | class URIDict(MutableMapping): 10 | """ 11 | Dictionary which uses normalized URIs as keys. 12 | 13 | """ 14 | 15 | def normalize(self, uri): 16 | return urlsplit(uri).geturl() 17 | 18 | def __init__(self, *args, **kwargs): 19 | self.store = dict() 20 | self.store.update(*args, **kwargs) 21 | 22 | def __getitem__(self, uri): 23 | return self.store[self.normalize(uri)] 24 | 25 | def __setitem__(self, uri, value): 26 | self.store[self.normalize(uri)] = value 27 | 28 | def __delitem__(self, uri): 29 | del self.store[self.normalize(uri)] 30 | 31 | def __iter__(self): 32 | return iter(self.store) 33 | 34 | def __len__(self): 35 | return len(self.store) 36 | 37 | def __repr__(self): 38 | return repr(self.store) 39 | 40 | 41 | class Unset(object): 42 | """ 43 | An as-of-yet unset attribute or unprovided default parameter. 44 | 45 | """ 46 | 47 | def __repr__(self): 48 | return "" 49 | 50 | 51 | def load_schema(name): 52 | """ 53 | Load a schema from ./schemas/``name``.json and return it. 54 | 55 | """ 56 | 57 | data = pkgutil.get_data('jsonschema', "schemas/{0}.json".format(name)) 58 | return json.loads(data.decode("utf-8")) 59 | 60 | 61 | def indent(string, times=1): 62 | """ 63 | A dumb version of :func:`textwrap.indent` from Python 3.3. 64 | 65 | """ 66 | 67 | return "\n".join(" " * (4 * times) + line for line in string.splitlines()) 68 | 69 | 70 | def format_as_index(indices): 71 | """ 72 | Construct a single string containing indexing operations for the indices. 73 | 74 | For example, [1, 2, "foo"] -> [1][2]["foo"] 75 | 76 | Arguments: 77 | 78 | indices (sequence): 79 | 80 | The indices to format. 81 | 82 | """ 83 | 84 | if not indices: 85 | return "" 86 | return "[%s]" % "][".join(repr(index) for index in indices) 87 | 88 | 89 | def find_additional_properties(instance, schema): 90 | """ 91 | Return the set of additional properties for the given ``instance``. 92 | 93 | Weeds out properties that should have been validated by ``properties`` and 94 | / or ``patternProperties``. 95 | 96 | Assumes ``instance`` is dict-like already. 97 | 98 | """ 99 | 100 | properties = schema.get("properties", {}) 101 | patterns = "|".join(schema.get("patternProperties", {})) 102 | for property in instance: 103 | if property not in properties: 104 | if patterns and re.search(patterns, property): 105 | continue 106 | yield property 107 | 108 | 109 | def extras_msg(extras): 110 | """ 111 | Create an error message for extra items or properties. 112 | 113 | """ 114 | 115 | if len(extras) == 1: 116 | verb = "was" 117 | else: 118 | verb = "were" 119 | return ", ".join(repr(extra) for extra in extras), verb 120 | 121 | 122 | def types_msg(instance, types): 123 | """ 124 | Create an error message for a failure to match the given types. 125 | 126 | If the ``instance`` is an object and contains a ``name`` property, it will 127 | be considered to be a description of that object and used as its type. 128 | 129 | Otherwise the message is simply the reprs of the given ``types``. 130 | 131 | """ 132 | 133 | reprs = [] 134 | for type in types: 135 | try: 136 | reprs.append(repr(type["name"])) 137 | except Exception: 138 | reprs.append(repr(type)) 139 | return "%r is not of type %s" % (instance, ", ".join(reprs)) 140 | 141 | 142 | def flatten(suitable_for_isinstance): 143 | """ 144 | isinstance() can accept a bunch of really annoying different types: 145 | * a single type 146 | * a tuple of types 147 | * an arbitrary nested tree of tuples 148 | 149 | Return a flattened tuple of the given argument. 150 | 151 | """ 152 | 153 | types = set() 154 | 155 | if not isinstance(suitable_for_isinstance, tuple): 156 | suitable_for_isinstance = (suitable_for_isinstance,) 157 | for thing in suitable_for_isinstance: 158 | if isinstance(thing, tuple): 159 | types.update(flatten(thing)) 160 | else: 161 | types.add(thing) 162 | return tuple(types) 163 | 164 | 165 | def ensure_list(thing): 166 | """ 167 | Wrap ``thing`` in a list if it's a single str. 168 | 169 | Otherwise, return it unchanged. 170 | 171 | """ 172 | 173 | if isinstance(thing, str_types): 174 | return [thing] 175 | return thing 176 | 177 | 178 | def unbool(element, true=object(), false=object()): 179 | """ 180 | A hack to make True and 1 and False and 0 unique for ``uniq``. 181 | 182 | """ 183 | 184 | if element is True: 185 | return true 186 | elif element is False: 187 | return false 188 | return element 189 | 190 | 191 | def uniq(container): 192 | """ 193 | Check if all of a container's elements are unique. 194 | 195 | Successively tries first to rely that the elements are hashable, then 196 | falls back on them being sortable, and finally falls back on brute 197 | force. 198 | 199 | """ 200 | 201 | try: 202 | return len(set(unbool(i) for i in container)) == len(container) 203 | except TypeError: 204 | try: 205 | sort = sorted(unbool(i) for i in container) 206 | sliced = itertools.islice(sort, 1, None) 207 | for i, j in zip(sort, sliced): 208 | if i == j: 209 | return False 210 | except (NotImplementedError, TypeError): 211 | seen = [] 212 | for e in container: 213 | e = unbool(e) 214 | if e in seen: 215 | return False 216 | seen.append(e) 217 | return True 218 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/_validators.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from jsonschema import _utils 4 | from jsonschema.exceptions import FormatError, ValidationError 5 | from jsonschema.compat import iteritems 6 | 7 | 8 | def patternProperties(validator, patternProperties, instance, schema): 9 | if not validator.is_type(instance, "object"): 10 | return 11 | 12 | for pattern, subschema in iteritems(patternProperties): 13 | for k, v in iteritems(instance): 14 | if re.search(pattern, k): 15 | for error in validator.descend( 16 | v, subschema, path=k, schema_path=pattern, 17 | ): 18 | yield error 19 | 20 | 21 | def additionalProperties(validator, aP, instance, schema): 22 | if not validator.is_type(instance, "object"): 23 | return 24 | 25 | extras = set(_utils.find_additional_properties(instance, schema)) 26 | 27 | if validator.is_type(aP, "object"): 28 | for extra in extras: 29 | for error in validator.descend(instance[extra], aP, path=extra): 30 | yield error 31 | elif not aP and extras: 32 | if "patternProperties" in schema: 33 | patterns = sorted(schema["patternProperties"]) 34 | if len(extras) == 1: 35 | verb = "does" 36 | else: 37 | verb = "do" 38 | error = "%s %s not match any of the regexes: %s" % ( 39 | ", ".join(map(repr, sorted(extras))), 40 | verb, 41 | ", ".join(map(repr, patterns)), 42 | ) 43 | yield ValidationError(error) 44 | else: 45 | error = "Additional properties are not allowed (%s %s unexpected)" 46 | yield ValidationError(error % _utils.extras_msg(extras)) 47 | 48 | 49 | def items(validator, items, instance, schema): 50 | if not validator.is_type(instance, "array"): 51 | return 52 | 53 | if validator.is_type(items, "object"): 54 | for index, item in enumerate(instance): 55 | for error in validator.descend(item, items, path=index): 56 | yield error 57 | else: 58 | for (index, item), subschema in zip(enumerate(instance), items): 59 | for error in validator.descend( 60 | item, subschema, path=index, schema_path=index, 61 | ): 62 | yield error 63 | 64 | 65 | def additionalItems(validator, aI, instance, schema): 66 | if ( 67 | not validator.is_type(instance, "array") or 68 | validator.is_type(schema.get("items", {}), "object") 69 | ): 70 | return 71 | 72 | len_items = len(schema.get("items", [])) 73 | if validator.is_type(aI, "object"): 74 | for index, item in enumerate(instance[len_items:], start=len_items): 75 | for error in validator.descend(item, aI, path=index): 76 | yield error 77 | elif not aI and len(instance) > len(schema.get("items", [])): 78 | error = "Additional items are not allowed (%s %s unexpected)" 79 | yield ValidationError( 80 | error % 81 | _utils.extras_msg(instance[len(schema.get("items", [])):]) 82 | ) 83 | 84 | 85 | def minimum(validator, minimum, instance, schema): 86 | if not validator.is_type(instance, "number"): 87 | return 88 | 89 | if schema.get("exclusiveMinimum", False): 90 | failed = instance <= minimum 91 | cmp = "less than or equal to" 92 | else: 93 | failed = instance < minimum 94 | cmp = "less than" 95 | 96 | if failed: 97 | yield ValidationError( 98 | "%r is %s the minimum of %r" % (instance, cmp, minimum) 99 | ) 100 | 101 | 102 | def maximum(validator, maximum, instance, schema): 103 | if not validator.is_type(instance, "number"): 104 | return 105 | 106 | if schema.get("exclusiveMaximum", False): 107 | failed = instance >= maximum 108 | cmp = "greater than or equal to" 109 | else: 110 | failed = instance > maximum 111 | cmp = "greater than" 112 | 113 | if failed: 114 | yield ValidationError( 115 | "%r is %s the maximum of %r" % (instance, cmp, maximum) 116 | ) 117 | 118 | 119 | def multipleOf(validator, dB, instance, schema): 120 | if not validator.is_type(instance, "number"): 121 | return 122 | 123 | if isinstance(dB, float): 124 | quotient = instance / dB 125 | failed = int(quotient) != quotient 126 | else: 127 | failed = instance % dB 128 | 129 | if failed: 130 | yield ValidationError("%r is not a multiple of %r" % (instance, dB)) 131 | 132 | 133 | def minItems(validator, mI, instance, schema): 134 | if validator.is_type(instance, "array") and len(instance) < mI: 135 | yield ValidationError("%r is too short" % (instance,)) 136 | 137 | 138 | def maxItems(validator, mI, instance, schema): 139 | if validator.is_type(instance, "array") and len(instance) > mI: 140 | yield ValidationError("%r is too long" % (instance,)) 141 | 142 | 143 | def uniqueItems(validator, uI, instance, schema): 144 | if ( 145 | uI and 146 | validator.is_type(instance, "array") and 147 | not _utils.uniq(instance) 148 | ): 149 | yield ValidationError("%r has non-unique elements" % (instance,)) 150 | 151 | 152 | def pattern(validator, patrn, instance, schema): 153 | if ( 154 | validator.is_type(instance, "string") and 155 | not re.search(patrn, instance) 156 | ): 157 | yield ValidationError("%r does not match %r" % (instance, patrn)) 158 | 159 | 160 | def format(validator, format, instance, schema): 161 | if validator.format_checker is not None: 162 | try: 163 | validator.format_checker.check(instance, format) 164 | except FormatError as error: 165 | yield ValidationError(error.message, cause=error.cause) 166 | 167 | 168 | def minLength(validator, mL, instance, schema): 169 | if validator.is_type(instance, "string") and len(instance) < mL: 170 | yield ValidationError("%r is too short" % (instance,)) 171 | 172 | 173 | def maxLength(validator, mL, instance, schema): 174 | if validator.is_type(instance, "string") and len(instance) > mL: 175 | yield ValidationError("%r is too long" % (instance,)) 176 | 177 | 178 | def dependencies(validator, dependencies, instance, schema): 179 | if not validator.is_type(instance, "object"): 180 | return 181 | 182 | for property, dependency in iteritems(dependencies): 183 | if property not in instance: 184 | continue 185 | 186 | if validator.is_type(dependency, "object"): 187 | for error in validator.descend( 188 | instance, dependency, schema_path=property, 189 | ): 190 | yield error 191 | else: 192 | dependencies = _utils.ensure_list(dependency) 193 | for dependency in dependencies: 194 | if dependency not in instance: 195 | yield ValidationError( 196 | "%r is a dependency of %r" % (dependency, property) 197 | ) 198 | 199 | 200 | def enum(validator, enums, instance, schema): 201 | if instance not in enums: 202 | yield ValidationError("%r is not one of %r" % (instance, enums)) 203 | 204 | 205 | def ref(validator, ref, instance, schema): 206 | resolve = getattr(validator.resolver, "resolve", None) 207 | if resolve is None: 208 | with validator.resolver.resolving(ref) as resolved: 209 | for error in validator.descend(instance, resolved): 210 | yield error 211 | else: 212 | scope, resolved = validator.resolver.resolve(ref) 213 | validator.resolver.push_scope(scope) 214 | 215 | try: 216 | for error in validator.descend(instance, resolved): 217 | yield error 218 | finally: 219 | validator.resolver.pop_scope() 220 | 221 | 222 | def type_draft3(validator, types, instance, schema): 223 | types = _utils.ensure_list(types) 224 | 225 | all_errors = [] 226 | for index, type in enumerate(types): 227 | if type == "any": 228 | return 229 | if validator.is_type(type, "object"): 230 | errors = list(validator.descend(instance, type, schema_path=index)) 231 | if not errors: 232 | return 233 | all_errors.extend(errors) 234 | else: 235 | if validator.is_type(instance, type): 236 | return 237 | else: 238 | yield ValidationError( 239 | _utils.types_msg(instance, types), context=all_errors, 240 | ) 241 | 242 | 243 | def properties_draft3(validator, properties, instance, schema): 244 | if not validator.is_type(instance, "object"): 245 | return 246 | 247 | for property, subschema in iteritems(properties): 248 | if property in instance: 249 | for error in validator.descend( 250 | instance[property], 251 | subschema, 252 | path=property, 253 | schema_path=property, 254 | ): 255 | yield error 256 | elif subschema.get("required", False): 257 | error = ValidationError("%r is a required property" % property) 258 | error._set( 259 | validator="required", 260 | validator_value=subschema["required"], 261 | instance=instance, 262 | schema=schema, 263 | ) 264 | error.path.appendleft(property) 265 | error.schema_path.extend([property, "required"]) 266 | yield error 267 | 268 | 269 | def disallow_draft3(validator, disallow, instance, schema): 270 | for disallowed in _utils.ensure_list(disallow): 271 | if validator.is_valid(instance, {"type": [disallowed]}): 272 | yield ValidationError( 273 | "%r is disallowed for %r" % (disallowed, instance) 274 | ) 275 | 276 | 277 | def extends_draft3(validator, extends, instance, schema): 278 | if validator.is_type(extends, "object"): 279 | for error in validator.descend(instance, extends): 280 | yield error 281 | return 282 | for index, subschema in enumerate(extends): 283 | for error in validator.descend(instance, subschema, schema_path=index): 284 | yield error 285 | 286 | 287 | def type_draft4(validator, types, instance, schema): 288 | types = _utils.ensure_list(types) 289 | 290 | if not any(validator.is_type(instance, type) for type in types): 291 | yield ValidationError(_utils.types_msg(instance, types)) 292 | 293 | 294 | def properties_draft4(validator, properties, instance, schema): 295 | if not validator.is_type(instance, "object"): 296 | return 297 | 298 | for property, subschema in iteritems(properties): 299 | if property in instance: 300 | for error in validator.descend( 301 | instance[property], 302 | subschema, 303 | path=property, 304 | schema_path=property, 305 | ): 306 | yield error 307 | 308 | 309 | def required_draft4(validator, required, instance, schema): 310 | if not validator.is_type(instance, "object"): 311 | return 312 | for property in required: 313 | if property not in instance: 314 | yield ValidationError("%r is a required property" % property) 315 | 316 | 317 | def minProperties_draft4(validator, mP, instance, schema): 318 | if validator.is_type(instance, "object") and len(instance) < mP: 319 | yield ValidationError( 320 | "%r does not have enough properties" % (instance,) 321 | ) 322 | 323 | 324 | def maxProperties_draft4(validator, mP, instance, schema): 325 | if not validator.is_type(instance, "object"): 326 | return 327 | if validator.is_type(instance, "object") and len(instance) > mP: 328 | yield ValidationError("%r has too many properties" % (instance,)) 329 | 330 | 331 | def allOf_draft4(validator, allOf, instance, schema): 332 | for index, subschema in enumerate(allOf): 333 | for error in validator.descend(instance, subschema, schema_path=index): 334 | yield error 335 | 336 | 337 | def oneOf_draft4(validator, oneOf, instance, schema): 338 | subschemas = enumerate(oneOf) 339 | all_errors = [] 340 | for index, subschema in subschemas: 341 | errs = list(validator.descend(instance, subschema, schema_path=index)) 342 | if not errs: 343 | first_valid = subschema 344 | break 345 | all_errors.extend(errs) 346 | else: 347 | yield ValidationError( 348 | "%r is not valid under any of the given schemas" % (instance,), 349 | context=all_errors, 350 | ) 351 | 352 | more_valid = [s for i, s in subschemas if validator.is_valid(instance, s)] 353 | if more_valid: 354 | more_valid.append(first_valid) 355 | reprs = ", ".join(repr(schema) for schema in more_valid) 356 | yield ValidationError( 357 | "%r is valid under each of %s" % (instance, reprs) 358 | ) 359 | 360 | 361 | def anyOf_draft4(validator, anyOf, instance, schema): 362 | all_errors = [] 363 | for index, subschema in enumerate(anyOf): 364 | errs = list(validator.descend(instance, subschema, schema_path=index)) 365 | if not errs: 366 | break 367 | all_errors.extend(errs) 368 | else: 369 | yield ValidationError( 370 | "%r is not valid under any of the given schemas" % (instance,), 371 | context=all_errors, 372 | ) 373 | 374 | 375 | def not_draft4(validator, not_schema, instance, schema): 376 | if validator.is_valid(instance, not_schema): 377 | yield ValidationError( 378 | "%r is not allowed for %r" % (not_schema, instance) 379 | ) 380 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/cli.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import argparse 3 | import json 4 | import sys 5 | 6 | from jsonschema._reflect import namedAny 7 | from jsonschema.validators import validator_for 8 | 9 | 10 | def _namedAnyWithDefault(name): 11 | if "." not in name: 12 | name = "jsonschema." + name 13 | return namedAny(name) 14 | 15 | 16 | def _json_file(path): 17 | with open(path) as file: 18 | return json.load(file) 19 | 20 | 21 | parser = argparse.ArgumentParser( 22 | description="JSON Schema Validation CLI", 23 | ) 24 | parser.add_argument( 25 | "-i", "--instance", 26 | action="append", 27 | dest="instances", 28 | type=_json_file, 29 | help=( 30 | "a path to a JSON instance (i.e. filename.json)" 31 | "to validate (may be specified multiple times)" 32 | ), 33 | ) 34 | parser.add_argument( 35 | "-F", "--error-format", 36 | default="{error.instance}: {error.message}\n", 37 | help=( 38 | "the format to use for each error output message, specified in " 39 | "a form suitable for passing to str.format, which will be called " 40 | "with 'error' for each error" 41 | ), 42 | ) 43 | parser.add_argument( 44 | "-V", "--validator", 45 | type=_namedAnyWithDefault, 46 | help=( 47 | "the fully qualified object name of a validator to use, or, for " 48 | "validators that are registered with jsonschema, simply the name " 49 | "of the class." 50 | ), 51 | ) 52 | parser.add_argument( 53 | "schema", 54 | help="the JSON Schema to validate with (i.e. filename.schema)", 55 | type=_json_file, 56 | ) 57 | 58 | 59 | def parse_args(args): 60 | arguments = vars(parser.parse_args(args=args or ["--help"])) 61 | if arguments["validator"] is None: 62 | arguments["validator"] = validator_for(arguments["schema"]) 63 | return arguments 64 | 65 | 66 | def main(args=sys.argv[1:]): 67 | sys.exit(run(arguments=parse_args(args=args))) 68 | 69 | 70 | def run(arguments, stdout=sys.stdout, stderr=sys.stderr): 71 | error_format = arguments["error_format"] 72 | validator = arguments["validator"](schema=arguments["schema"]) 73 | 74 | validator.check_schema(arguments["schema"]) 75 | 76 | errored = False 77 | for instance in arguments["instances"] or (): 78 | for error in validator.iter_errors(instance): 79 | stderr.write(error_format.format(error=error)) 80 | errored = True 81 | return errored 82 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/compat.py: -------------------------------------------------------------------------------- 1 | import operator 2 | import sys 3 | 4 | 5 | try: 6 | from collections import MutableMapping, Sequence # noqa 7 | except ImportError: 8 | from collections.abc import MutableMapping, Sequence # noqa 9 | 10 | PY3 = sys.version_info[0] >= 3 11 | 12 | if PY3: 13 | zip = zip 14 | from functools import lru_cache 15 | from io import StringIO 16 | from urllib.parse import ( 17 | unquote, urljoin, urlunsplit, SplitResult, urlsplit as _urlsplit 18 | ) 19 | from urllib.request import urlopen 20 | str_types = str, 21 | int_types = int, 22 | iteritems = operator.methodcaller("items") 23 | else: 24 | from itertools import izip as zip # noqa 25 | from StringIO import StringIO 26 | from urlparse import ( 27 | urljoin, urlunsplit, SplitResult, urlsplit as _urlsplit # noqa 28 | ) 29 | from urllib import unquote # noqa 30 | from urllib2 import urlopen # noqa 31 | str_types = basestring 32 | int_types = int, long 33 | iteritems = operator.methodcaller("iteritems") 34 | 35 | from functools32 import lru_cache 36 | 37 | 38 | # On python < 3.3 fragments are not handled properly with unknown schemes 39 | def urlsplit(url): 40 | scheme, netloc, path, query, fragment = _urlsplit(url) 41 | if "#" in path: 42 | path, fragment = path.split("#", 1) 43 | return SplitResult(scheme, netloc, path, query, fragment) 44 | 45 | 46 | def urldefrag(url): 47 | if "#" in url: 48 | s, n, p, q, frag = urlsplit(url) 49 | defrag = urlunsplit((s, n, p, q, '')) 50 | else: 51 | defrag = url 52 | frag = '' 53 | return defrag, frag 54 | 55 | 56 | # flake8: noqa 57 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/exceptions.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict, deque 2 | import itertools 3 | import pprint 4 | import textwrap 5 | 6 | from jsonschema import _utils 7 | from jsonschema.compat import PY3, iteritems 8 | 9 | 10 | WEAK_MATCHES = frozenset(["anyOf", "oneOf"]) 11 | STRONG_MATCHES = frozenset() 12 | 13 | _unset = _utils.Unset() 14 | 15 | 16 | class _Error(Exception): 17 | def __init__( 18 | self, 19 | message, 20 | validator=_unset, 21 | path=(), 22 | cause=None, 23 | context=(), 24 | validator_value=_unset, 25 | instance=_unset, 26 | schema=_unset, 27 | schema_path=(), 28 | parent=None, 29 | ): 30 | super(_Error, self).__init__( 31 | message, 32 | validator, 33 | path, 34 | cause, 35 | context, 36 | validator_value, 37 | instance, 38 | schema, 39 | schema_path, 40 | parent, 41 | ) 42 | self.message = message 43 | self.path = self.relative_path = deque(path) 44 | self.schema_path = self.relative_schema_path = deque(schema_path) 45 | self.context = list(context) 46 | self.cause = self.__cause__ = cause 47 | self.validator = validator 48 | self.validator_value = validator_value 49 | self.instance = instance 50 | self.schema = schema 51 | self.parent = parent 52 | 53 | for error in context: 54 | error.parent = self 55 | 56 | def __repr__(self): 57 | return "<%s: %r>" % (self.__class__.__name__, self.message) 58 | 59 | def __unicode__(self): 60 | essential_for_verbose = ( 61 | self.validator, self.validator_value, self.instance, self.schema, 62 | ) 63 | if any(m is _unset for m in essential_for_verbose): 64 | return self.message 65 | 66 | pschema = pprint.pformat(self.schema, width=72) 67 | pinstance = pprint.pformat(self.instance, width=72) 68 | return self.message + textwrap.dedent(""" 69 | 70 | Failed validating %r in schema%s: 71 | %s 72 | 73 | On instance%s: 74 | %s 75 | """.rstrip() 76 | ) % ( 77 | self.validator, 78 | _utils.format_as_index(list(self.relative_schema_path)[:-1]), 79 | _utils.indent(pschema), 80 | _utils.format_as_index(self.relative_path), 81 | _utils.indent(pinstance), 82 | ) 83 | 84 | if PY3: 85 | __str__ = __unicode__ 86 | else: 87 | def __str__(self): 88 | return unicode(self).encode("utf-8") 89 | 90 | @classmethod 91 | def create_from(cls, other): 92 | return cls(**other._contents()) 93 | 94 | @property 95 | def absolute_path(self): 96 | parent = self.parent 97 | if parent is None: 98 | return self.relative_path 99 | 100 | path = deque(self.relative_path) 101 | path.extendleft(reversed(parent.absolute_path)) 102 | return path 103 | 104 | @property 105 | def absolute_schema_path(self): 106 | parent = self.parent 107 | if parent is None: 108 | return self.relative_schema_path 109 | 110 | path = deque(self.relative_schema_path) 111 | path.extendleft(reversed(parent.absolute_schema_path)) 112 | return path 113 | 114 | def _set(self, **kwargs): 115 | for k, v in iteritems(kwargs): 116 | if getattr(self, k) is _unset: 117 | setattr(self, k, v) 118 | 119 | def _contents(self): 120 | attrs = ( 121 | "message", "cause", "context", "validator", "validator_value", 122 | "path", "schema_path", "instance", "schema", "parent", 123 | ) 124 | return dict((attr, getattr(self, attr)) for attr in attrs) 125 | 126 | 127 | class ValidationError(_Error): 128 | pass 129 | 130 | 131 | class SchemaError(_Error): 132 | pass 133 | 134 | 135 | class RefResolutionError(Exception): 136 | pass 137 | 138 | 139 | class UnknownType(Exception): 140 | def __init__(self, type, instance, schema): 141 | self.type = type 142 | self.instance = instance 143 | self.schema = schema 144 | 145 | def __unicode__(self): 146 | pschema = pprint.pformat(self.schema, width=72) 147 | pinstance = pprint.pformat(self.instance, width=72) 148 | return textwrap.dedent(""" 149 | Unknown type %r for validator with schema: 150 | %s 151 | 152 | While checking instance: 153 | %s 154 | """.rstrip() 155 | ) % (self.type, _utils.indent(pschema), _utils.indent(pinstance)) 156 | 157 | if PY3: 158 | __str__ = __unicode__ 159 | else: 160 | def __str__(self): 161 | return unicode(self).encode("utf-8") 162 | 163 | 164 | class FormatError(Exception): 165 | def __init__(self, message, cause=None): 166 | super(FormatError, self).__init__(message, cause) 167 | self.message = message 168 | self.cause = self.__cause__ = cause 169 | 170 | def __unicode__(self): 171 | return self.message 172 | 173 | if PY3: 174 | __str__ = __unicode__ 175 | else: 176 | def __str__(self): 177 | return self.message.encode("utf-8") 178 | 179 | 180 | class ErrorTree(object): 181 | """ 182 | ErrorTrees make it easier to check which validations failed. 183 | 184 | """ 185 | 186 | _instance = _unset 187 | 188 | def __init__(self, errors=()): 189 | self.errors = {} 190 | self._contents = defaultdict(self.__class__) 191 | 192 | for error in errors: 193 | container = self 194 | for element in error.path: 195 | container = container[element] 196 | container.errors[error.validator] = error 197 | 198 | container._instance = error.instance 199 | 200 | def __contains__(self, index): 201 | """ 202 | Check whether ``instance[index]`` has any errors. 203 | 204 | """ 205 | 206 | return index in self._contents 207 | 208 | def __getitem__(self, index): 209 | """ 210 | Retrieve the child tree one level down at the given ``index``. 211 | 212 | If the index is not in the instance that this tree corresponds to and 213 | is not known by this tree, whatever error would be raised by 214 | ``instance.__getitem__`` will be propagated (usually this is some 215 | subclass of :class:`LookupError`. 216 | 217 | """ 218 | 219 | if self._instance is not _unset and index not in self: 220 | self._instance[index] 221 | return self._contents[index] 222 | 223 | def __setitem__(self, index, value): 224 | self._contents[index] = value 225 | 226 | def __iter__(self): 227 | """ 228 | Iterate (non-recursively) over the indices in the instance with errors. 229 | 230 | """ 231 | 232 | return iter(self._contents) 233 | 234 | def __len__(self): 235 | """ 236 | Same as :attr:`total_errors`. 237 | 238 | """ 239 | 240 | return self.total_errors 241 | 242 | def __repr__(self): 243 | return "<%s (%s total errors)>" % (self.__class__.__name__, len(self)) 244 | 245 | @property 246 | def total_errors(self): 247 | """ 248 | The total number of errors in the entire tree, including children. 249 | 250 | """ 251 | 252 | child_errors = sum(len(tree) for _, tree in iteritems(self._contents)) 253 | return len(self.errors) + child_errors 254 | 255 | 256 | def by_relevance(weak=WEAK_MATCHES, strong=STRONG_MATCHES): 257 | def relevance(error): 258 | validator = error.validator 259 | return -len(error.path), validator not in weak, validator in strong 260 | return relevance 261 | 262 | 263 | relevance = by_relevance() 264 | 265 | 266 | def best_match(errors, key=relevance): 267 | errors = iter(errors) 268 | best = next(errors, None) 269 | if best is None: 270 | return 271 | best = max(itertools.chain([best], errors), key=key) 272 | 273 | while best.context: 274 | best = min(best.context, key=key) 275 | return best 276 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/schemas/draft3.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-03/schema#", 3 | "dependencies": { 4 | "exclusiveMaximum": "maximum", 5 | "exclusiveMinimum": "minimum" 6 | }, 7 | "id": "http://json-schema.org/draft-03/schema#", 8 | "properties": { 9 | "$ref": { 10 | "format": "uri", 11 | "type": "string" 12 | }, 13 | "$schema": { 14 | "format": "uri", 15 | "type": "string" 16 | }, 17 | "additionalItems": { 18 | "default": {}, 19 | "type": [ 20 | { 21 | "$ref": "#" 22 | }, 23 | "boolean" 24 | ] 25 | }, 26 | "additionalProperties": { 27 | "default": {}, 28 | "type": [ 29 | { 30 | "$ref": "#" 31 | }, 32 | "boolean" 33 | ] 34 | }, 35 | "default": { 36 | "type": "any" 37 | }, 38 | "dependencies": { 39 | "additionalProperties": { 40 | "items": { 41 | "type": "string" 42 | }, 43 | "type": [ 44 | "string", 45 | "array", 46 | { 47 | "$ref": "#" 48 | } 49 | ] 50 | }, 51 | "default": {}, 52 | "type": [ 53 | "string", 54 | "array", 55 | "object" 56 | ] 57 | }, 58 | "description": { 59 | "type": "string" 60 | }, 61 | "disallow": { 62 | "items": { 63 | "type": [ 64 | "string", 65 | { 66 | "$ref": "#" 67 | } 68 | ] 69 | }, 70 | "type": [ 71 | "string", 72 | "array" 73 | ], 74 | "uniqueItems": true 75 | }, 76 | "divisibleBy": { 77 | "default": 1, 78 | "exclusiveMinimum": true, 79 | "minimum": 0, 80 | "type": "number" 81 | }, 82 | "enum": { 83 | "minItems": 1, 84 | "type": "array", 85 | "uniqueItems": true 86 | }, 87 | "exclusiveMaximum": { 88 | "default": false, 89 | "type": "boolean" 90 | }, 91 | "exclusiveMinimum": { 92 | "default": false, 93 | "type": "boolean" 94 | }, 95 | "extends": { 96 | "default": {}, 97 | "items": { 98 | "$ref": "#" 99 | }, 100 | "type": [ 101 | { 102 | "$ref": "#" 103 | }, 104 | "array" 105 | ] 106 | }, 107 | "format": { 108 | "type": "string" 109 | }, 110 | "id": { 111 | "format": "uri", 112 | "type": "string" 113 | }, 114 | "items": { 115 | "default": {}, 116 | "items": { 117 | "$ref": "#" 118 | }, 119 | "type": [ 120 | { 121 | "$ref": "#" 122 | }, 123 | "array" 124 | ] 125 | }, 126 | "maxDecimal": { 127 | "minimum": 0, 128 | "type": "number" 129 | }, 130 | "maxItems": { 131 | "minimum": 0, 132 | "type": "integer" 133 | }, 134 | "maxLength": { 135 | "type": "integer" 136 | }, 137 | "maximum": { 138 | "type": "number" 139 | }, 140 | "minItems": { 141 | "default": 0, 142 | "minimum": 0, 143 | "type": "integer" 144 | }, 145 | "minLength": { 146 | "default": 0, 147 | "minimum": 0, 148 | "type": "integer" 149 | }, 150 | "minimum": { 151 | "type": "number" 152 | }, 153 | "pattern": { 154 | "format": "regex", 155 | "type": "string" 156 | }, 157 | "patternProperties": { 158 | "additionalProperties": { 159 | "$ref": "#" 160 | }, 161 | "default": {}, 162 | "type": "object" 163 | }, 164 | "properties": { 165 | "additionalProperties": { 166 | "$ref": "#", 167 | "type": "object" 168 | }, 169 | "default": {}, 170 | "type": "object" 171 | }, 172 | "required": { 173 | "default": false, 174 | "type": "boolean" 175 | }, 176 | "title": { 177 | "type": "string" 178 | }, 179 | "type": { 180 | "default": "any", 181 | "items": { 182 | "type": [ 183 | "string", 184 | { 185 | "$ref": "#" 186 | } 187 | ] 188 | }, 189 | "type": [ 190 | "string", 191 | "array" 192 | ], 193 | "uniqueItems": true 194 | }, 195 | "uniqueItems": { 196 | "default": false, 197 | "type": "boolean" 198 | } 199 | }, 200 | "type": "object" 201 | } 202 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/schemas/draft4.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "default": {}, 4 | "definitions": { 5 | "positiveInteger": { 6 | "minimum": 0, 7 | "type": "integer" 8 | }, 9 | "positiveIntegerDefault0": { 10 | "allOf": [ 11 | { 12 | "$ref": "#/definitions/positiveInteger" 13 | }, 14 | { 15 | "default": 0 16 | } 17 | ] 18 | }, 19 | "schemaArray": { 20 | "items": { 21 | "$ref": "#" 22 | }, 23 | "minItems": 1, 24 | "type": "array" 25 | }, 26 | "simpleTypes": { 27 | "enum": [ 28 | "array", 29 | "boolean", 30 | "integer", 31 | "null", 32 | "number", 33 | "object", 34 | "string" 35 | ] 36 | }, 37 | "stringArray": { 38 | "items": { 39 | "type": "string" 40 | }, 41 | "minItems": 1, 42 | "type": "array", 43 | "uniqueItems": true 44 | } 45 | }, 46 | "dependencies": { 47 | "exclusiveMaximum": [ 48 | "maximum" 49 | ], 50 | "exclusiveMinimum": [ 51 | "minimum" 52 | ] 53 | }, 54 | "description": "Core schema meta-schema", 55 | "id": "http://json-schema.org/draft-04/schema#", 56 | "properties": { 57 | "$schema": { 58 | "format": "uri", 59 | "type": "string" 60 | }, 61 | "additionalItems": { 62 | "anyOf": [ 63 | { 64 | "type": "boolean" 65 | }, 66 | { 67 | "$ref": "#" 68 | } 69 | ], 70 | "default": {} 71 | }, 72 | "additionalProperties": { 73 | "anyOf": [ 74 | { 75 | "type": "boolean" 76 | }, 77 | { 78 | "$ref": "#" 79 | } 80 | ], 81 | "default": {} 82 | }, 83 | "allOf": { 84 | "$ref": "#/definitions/schemaArray" 85 | }, 86 | "anyOf": { 87 | "$ref": "#/definitions/schemaArray" 88 | }, 89 | "default": {}, 90 | "definitions": { 91 | "additionalProperties": { 92 | "$ref": "#" 93 | }, 94 | "default": {}, 95 | "type": "object" 96 | }, 97 | "dependencies": { 98 | "additionalProperties": { 99 | "anyOf": [ 100 | { 101 | "$ref": "#" 102 | }, 103 | { 104 | "$ref": "#/definitions/stringArray" 105 | } 106 | ] 107 | }, 108 | "type": "object" 109 | }, 110 | "description": { 111 | "type": "string" 112 | }, 113 | "enum": { 114 | "minItems": 1, 115 | "type": "array", 116 | "uniqueItems": true 117 | }, 118 | "exclusiveMaximum": { 119 | "default": false, 120 | "type": "boolean" 121 | }, 122 | "exclusiveMinimum": { 123 | "default": false, 124 | "type": "boolean" 125 | }, 126 | "format": { 127 | "type": "string" 128 | }, 129 | "id": { 130 | "format": "uri", 131 | "type": "string" 132 | }, 133 | "items": { 134 | "anyOf": [ 135 | { 136 | "$ref": "#" 137 | }, 138 | { 139 | "$ref": "#/definitions/schemaArray" 140 | } 141 | ], 142 | "default": {} 143 | }, 144 | "maxItems": { 145 | "$ref": "#/definitions/positiveInteger" 146 | }, 147 | "maxLength": { 148 | "$ref": "#/definitions/positiveInteger" 149 | }, 150 | "maxProperties": { 151 | "$ref": "#/definitions/positiveInteger" 152 | }, 153 | "maximum": { 154 | "type": "number" 155 | }, 156 | "minItems": { 157 | "$ref": "#/definitions/positiveIntegerDefault0" 158 | }, 159 | "minLength": { 160 | "$ref": "#/definitions/positiveIntegerDefault0" 161 | }, 162 | "minProperties": { 163 | "$ref": "#/definitions/positiveIntegerDefault0" 164 | }, 165 | "minimum": { 166 | "type": "number" 167 | }, 168 | "multipleOf": { 169 | "exclusiveMinimum": true, 170 | "minimum": 0, 171 | "type": "number" 172 | }, 173 | "not": { 174 | "$ref": "#" 175 | }, 176 | "oneOf": { 177 | "$ref": "#/definitions/schemaArray" 178 | }, 179 | "pattern": { 180 | "format": "regex", 181 | "type": "string" 182 | }, 183 | "patternProperties": { 184 | "additionalProperties": { 185 | "$ref": "#" 186 | }, 187 | "default": {}, 188 | "type": "object" 189 | }, 190 | "properties": { 191 | "additionalProperties": { 192 | "$ref": "#" 193 | }, 194 | "default": {}, 195 | "type": "object" 196 | }, 197 | "required": { 198 | "$ref": "#/definitions/stringArray" 199 | }, 200 | "title": { 201 | "type": "string" 202 | }, 203 | "type": { 204 | "anyOf": [ 205 | { 206 | "$ref": "#/definitions/simpleTypes" 207 | }, 208 | { 209 | "items": { 210 | "$ref": "#/definitions/simpleTypes" 211 | }, 212 | "minItems": 1, 213 | "type": "array", 214 | "uniqueItems": true 215 | } 216 | ] 217 | }, 218 | "uniqueItems": { 219 | "default": false, 220 | "type": "boolean" 221 | } 222 | }, 223 | "type": "object" 224 | } 225 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/sample_lambda/python/jsonschema/tests/__init__.py -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/tests/compat.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | if sys.version_info[:2] < (2, 7): # pragma: no cover 5 | import unittest2 as unittest 6 | else: 7 | import unittest 8 | 9 | try: 10 | from unittest import mock 11 | except ImportError: 12 | import mock 13 | 14 | 15 | # flake8: noqa 16 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/tests/test_cli.py: -------------------------------------------------------------------------------- 1 | from jsonschema import Draft4Validator, ValidationError, cli 2 | from jsonschema.compat import StringIO 3 | from jsonschema.exceptions import SchemaError 4 | from jsonschema.tests.compat import mock, unittest 5 | 6 | 7 | def fake_validator(*errors): 8 | errors = list(reversed(errors)) 9 | 10 | class FakeValidator(object): 11 | def __init__(self, *args, **kwargs): 12 | pass 13 | 14 | def iter_errors(self, instance): 15 | if errors: 16 | return errors.pop() 17 | return [] 18 | 19 | def check_schema(self, schema): 20 | pass 21 | 22 | return FakeValidator 23 | 24 | 25 | class TestParser(unittest.TestCase): 26 | FakeValidator = fake_validator() 27 | 28 | def setUp(self): 29 | mock_open = mock.mock_open() 30 | patch_open = mock.patch.object(cli, "open", mock_open, create=True) 31 | patch_open.start() 32 | self.addCleanup(patch_open.stop) 33 | 34 | mock_json_load = mock.Mock() 35 | mock_json_load.return_value = {} 36 | patch_json_load = mock.patch("json.load") 37 | patch_json_load.start() 38 | self.addCleanup(patch_json_load.stop) 39 | 40 | def test_find_validator_by_fully_qualified_object_name(self): 41 | arguments = cli.parse_args( 42 | [ 43 | "--validator", 44 | "jsonschema.tests.test_cli.TestParser.FakeValidator", 45 | "--instance", "foo.json", 46 | "schema.json", 47 | ] 48 | ) 49 | self.assertIs(arguments["validator"], self.FakeValidator) 50 | 51 | def test_find_validator_in_jsonschema(self): 52 | arguments = cli.parse_args( 53 | [ 54 | "--validator", "Draft4Validator", 55 | "--instance", "foo.json", 56 | "schema.json", 57 | ] 58 | ) 59 | self.assertIs(arguments["validator"], Draft4Validator) 60 | 61 | 62 | class TestCLI(unittest.TestCase): 63 | def test_draft3_schema_draft4_validator(self): 64 | stdout, stderr = StringIO(), StringIO() 65 | with self.assertRaises(SchemaError): 66 | cli.run( 67 | { 68 | "validator": Draft4Validator, 69 | "schema": { 70 | "anyOf": [ 71 | {"minimum": 20}, 72 | {"type": "string"}, 73 | {"required": True}, 74 | ], 75 | }, 76 | "instances": [1], 77 | "error_format": "{error.message}", 78 | }, 79 | stdout=stdout, 80 | stderr=stderr, 81 | ) 82 | 83 | def test_successful_validation(self): 84 | stdout, stderr = StringIO(), StringIO() 85 | exit_code = cli.run( 86 | { 87 | "validator": fake_validator(), 88 | "schema": {}, 89 | "instances": [1], 90 | "error_format": "{error.message}", 91 | }, 92 | stdout=stdout, 93 | stderr=stderr, 94 | ) 95 | self.assertFalse(stdout.getvalue()) 96 | self.assertFalse(stderr.getvalue()) 97 | self.assertEqual(exit_code, 0) 98 | 99 | def test_unsuccessful_validation(self): 100 | error = ValidationError("I am an error!", instance=1) 101 | stdout, stderr = StringIO(), StringIO() 102 | exit_code = cli.run( 103 | { 104 | "validator": fake_validator([error]), 105 | "schema": {}, 106 | "instances": [1], 107 | "error_format": "{error.instance} - {error.message}", 108 | }, 109 | stdout=stdout, 110 | stderr=stderr, 111 | ) 112 | self.assertFalse(stdout.getvalue()) 113 | self.assertEqual(stderr.getvalue(), "1 - I am an error!") 114 | self.assertEqual(exit_code, 1) 115 | 116 | def test_unsuccessful_validation_multiple_instances(self): 117 | first_errors = [ 118 | ValidationError("9", instance=1), 119 | ValidationError("8", instance=1), 120 | ] 121 | second_errors = [ValidationError("7", instance=2)] 122 | stdout, stderr = StringIO(), StringIO() 123 | exit_code = cli.run( 124 | { 125 | "validator": fake_validator(first_errors, second_errors), 126 | "schema": {}, 127 | "instances": [1, 2], 128 | "error_format": "{error.instance} - {error.message}\t", 129 | }, 130 | stdout=stdout, 131 | stderr=stderr, 132 | ) 133 | self.assertFalse(stdout.getvalue()) 134 | self.assertEqual(stderr.getvalue(), "1 - 9\t1 - 8\t2 - 7\t") 135 | self.assertEqual(exit_code, 1) 136 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/tests/test_format.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tests for the parts of jsonschema related to the :validator:`format` property. 3 | 4 | """ 5 | 6 | from jsonschema.tests.compat import mock, unittest 7 | 8 | from jsonschema import FormatError, ValidationError, FormatChecker 9 | from jsonschema.validators import Draft4Validator 10 | 11 | 12 | class TestFormatChecker(unittest.TestCase): 13 | def setUp(self): 14 | self.fn = mock.Mock() 15 | 16 | def test_it_can_validate_no_formats(self): 17 | checker = FormatChecker(formats=()) 18 | self.assertFalse(checker.checkers) 19 | 20 | def test_it_raises_a_key_error_for_unknown_formats(self): 21 | with self.assertRaises(KeyError): 22 | FormatChecker(formats=["o noes"]) 23 | 24 | def test_it_can_register_cls_checkers(self): 25 | with mock.patch.dict(FormatChecker.checkers, clear=True): 26 | FormatChecker.cls_checks("new")(self.fn) 27 | self.assertEqual(FormatChecker.checkers, {"new": (self.fn, ())}) 28 | 29 | def test_it_can_register_checkers(self): 30 | checker = FormatChecker() 31 | checker.checks("new")(self.fn) 32 | self.assertEqual( 33 | checker.checkers, 34 | dict(FormatChecker.checkers, new=(self.fn, ())) 35 | ) 36 | 37 | def test_it_catches_registered_errors(self): 38 | checker = FormatChecker() 39 | cause = self.fn.side_effect = ValueError() 40 | 41 | checker.checks("foo", raises=ValueError)(self.fn) 42 | 43 | with self.assertRaises(FormatError) as cm: 44 | checker.check("bar", "foo") 45 | 46 | self.assertIs(cm.exception.cause, cause) 47 | self.assertIs(cm.exception.__cause__, cause) 48 | 49 | # Unregistered errors should not be caught 50 | self.fn.side_effect = AttributeError 51 | with self.assertRaises(AttributeError): 52 | checker.check("bar", "foo") 53 | 54 | def test_format_error_causes_become_validation_error_causes(self): 55 | checker = FormatChecker() 56 | checker.checks("foo", raises=ValueError)(self.fn) 57 | cause = self.fn.side_effect = ValueError() 58 | validator = Draft4Validator({"format": "foo"}, format_checker=checker) 59 | 60 | with self.assertRaises(ValidationError) as cm: 61 | validator.validate("bar") 62 | 63 | self.assertIs(cm.exception.__cause__, cause) 64 | -------------------------------------------------------------------------------- /sample_lambda/python/jsonschema/tests/test_jsonschema_test_suite.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test runner for the JSON Schema official test suite 3 | 4 | Tests comprehensive correctness of each draft's validator. 5 | 6 | See https://github.com/json-schema/JSON-Schema-Test-Suite for details. 7 | 8 | """ 9 | 10 | from contextlib import closing 11 | from decimal import Decimal 12 | import glob 13 | import json 14 | import io 15 | import itertools 16 | import os 17 | import re 18 | import subprocess 19 | import sys 20 | 21 | try: 22 | from sys import pypy_version_info 23 | except ImportError: 24 | pypy_version_info = None 25 | 26 | from jsonschema import ( 27 | FormatError, SchemaError, ValidationError, Draft3Validator, 28 | Draft4Validator, FormatChecker, draft3_format_checker, 29 | draft4_format_checker, validate, 30 | ) 31 | from jsonschema.compat import PY3 32 | from jsonschema.tests.compat import mock, unittest 33 | import jsonschema 34 | 35 | 36 | REPO_ROOT = os.path.join(os.path.dirname(jsonschema.__file__), os.path.pardir) 37 | SUITE = os.getenv("JSON_SCHEMA_TEST_SUITE", os.path.join(REPO_ROOT, "json")) 38 | 39 | if not os.path.isdir(SUITE): 40 | raise ValueError( 41 | "Can't find the JSON-Schema-Test-Suite directory. Set the " 42 | "'JSON_SCHEMA_TEST_SUITE' environment variable or run the tests from " 43 | "alongside a checkout of the suite." 44 | ) 45 | 46 | TESTS_DIR = os.path.join(SUITE, "tests") 47 | JSONSCHEMA_SUITE = os.path.join(SUITE, "bin", "jsonschema_suite") 48 | 49 | remotes_stdout = subprocess.Popen( 50 | ["python", JSONSCHEMA_SUITE, "remotes"], stdout=subprocess.PIPE, 51 | ).stdout 52 | 53 | with closing(remotes_stdout): 54 | if PY3: 55 | remotes_stdout = io.TextIOWrapper(remotes_stdout) 56 | REMOTES = json.load(remotes_stdout) 57 | 58 | 59 | def make_case(schema, data, valid, name): 60 | if valid: 61 | def test_case(self): 62 | kwargs = getattr(self, "validator_kwargs", {}) 63 | validate(data, schema, cls=self.validator_class, **kwargs) 64 | else: 65 | def test_case(self): 66 | kwargs = getattr(self, "validator_kwargs", {}) 67 | with self.assertRaises(ValidationError): 68 | validate(data, schema, cls=self.validator_class, **kwargs) 69 | 70 | if not PY3: 71 | name = name.encode("utf-8") 72 | test_case.__name__ = name 73 | 74 | return test_case 75 | 76 | 77 | def maybe_skip(skip, test_case, case, test): 78 | if skip is not None: 79 | reason = skip(case, test) 80 | if reason is not None: 81 | test_case = unittest.skip(reason)(test_case) 82 | return test_case 83 | 84 | 85 | def load_json_cases(tests_glob, ignore_glob="", basedir=TESTS_DIR, skip=None): 86 | if ignore_glob: 87 | ignore_glob = os.path.join(basedir, ignore_glob) 88 | 89 | def add_test_methods(test_class): 90 | ignored = set(glob.iglob(ignore_glob)) 91 | 92 | for filename in glob.iglob(os.path.join(basedir, tests_glob)): 93 | if filename in ignored: 94 | continue 95 | 96 | validating, _ = os.path.splitext(os.path.basename(filename)) 97 | id = itertools.count(1) 98 | 99 | with open(filename) as test_file: 100 | for case in json.load(test_file): 101 | for test in case["tests"]: 102 | name = "test_%s_%s_%s" % ( 103 | validating, 104 | next(id), 105 | re.sub(r"[\W ]+", "_", test["description"]), 106 | ) 107 | assert not hasattr(test_class, name), name 108 | 109 | test_case = make_case( 110 | data=test["data"], 111 | schema=case["schema"], 112 | valid=test["valid"], 113 | name=name, 114 | ) 115 | test_case = maybe_skip(skip, test_case, case, test) 116 | setattr(test_class, name, test_case) 117 | 118 | return test_class 119 | return add_test_methods 120 | 121 | 122 | class TypesMixin(object): 123 | @unittest.skipIf(PY3, "In Python 3 json.load always produces unicode") 124 | def test_string_a_bytestring_is_a_string(self): 125 | self.validator_class({"type": "string"}).validate(b"foo") 126 | 127 | 128 | class DecimalMixin(object): 129 | def test_it_can_validate_with_decimals(self): 130 | schema = {"type": "number"} 131 | validator = self.validator_class( 132 | schema, types={"number": (int, float, Decimal)} 133 | ) 134 | 135 | for valid in [1, 1.1, Decimal(1) / Decimal(8)]: 136 | validator.validate(valid) 137 | 138 | for invalid in ["foo", {}, [], True, None]: 139 | with self.assertRaises(ValidationError): 140 | validator.validate(invalid) 141 | 142 | 143 | def missing_format(checker): 144 | def missing_format(case, test): 145 | format = case["schema"].get("format") 146 | if format not in checker.checkers: 147 | return "Format checker {0!r} not found.".format(format) 148 | elif ( 149 | format == "date-time" and 150 | pypy_version_info is not None and 151 | pypy_version_info[:2] <= (1, 9) 152 | ): 153 | # datetime.datetime is overzealous about typechecking in <=1.9 154 | return "datetime.datetime is broken on this version of PyPy." 155 | return missing_format 156 | 157 | 158 | class FormatMixin(object): 159 | def test_it_returns_true_for_formats_it_does_not_know_about(self): 160 | validator = self.validator_class( 161 | {"format": "carrot"}, format_checker=FormatChecker(), 162 | ) 163 | validator.validate("bugs") 164 | 165 | def test_it_does_not_validate_formats_by_default(self): 166 | validator = self.validator_class({}) 167 | self.assertIsNone(validator.format_checker) 168 | 169 | def test_it_validates_formats_if_a_checker_is_provided(self): 170 | checker = mock.Mock(spec=FormatChecker) 171 | validator = self.validator_class( 172 | {"format": "foo"}, format_checker=checker, 173 | ) 174 | 175 | validator.validate("bar") 176 | 177 | checker.check.assert_called_once_with("bar", "foo") 178 | 179 | cause = ValueError() 180 | checker.check.side_effect = FormatError('aoeu', cause=cause) 181 | 182 | with self.assertRaises(ValidationError) as cm: 183 | validator.validate("bar") 184 | # Make sure original cause is attached 185 | self.assertIs(cm.exception.cause, cause) 186 | 187 | def test_it_validates_formats_of_any_type(self): 188 | checker = mock.Mock(spec=FormatChecker) 189 | validator = self.validator_class( 190 | {"format": "foo"}, format_checker=checker, 191 | ) 192 | 193 | validator.validate([1, 2, 3]) 194 | 195 | checker.check.assert_called_once_with([1, 2, 3], "foo") 196 | 197 | cause = ValueError() 198 | checker.check.side_effect = FormatError('aoeu', cause=cause) 199 | 200 | with self.assertRaises(ValidationError) as cm: 201 | validator.validate([1, 2, 3]) 202 | # Make sure original cause is attached 203 | self.assertIs(cm.exception.cause, cause) 204 | 205 | 206 | if sys.maxunicode == 2 ** 16 - 1: # This is a narrow build. 207 | def narrow_unicode_build(case, test): 208 | if "supplementary Unicode" in test["description"]: 209 | return "Not running surrogate Unicode case, this Python is narrow." 210 | else: 211 | def narrow_unicode_build(case, test): # This isn't, skip nothing. 212 | return 213 | 214 | 215 | @load_json_cases( 216 | "draft3/*.json", 217 | skip=narrow_unicode_build, 218 | ignore_glob="draft3/refRemote.json", 219 | ) 220 | @load_json_cases( 221 | "draft3/optional/format.json", skip=missing_format(draft3_format_checker) 222 | ) 223 | @load_json_cases("draft3/optional/bignum.json") 224 | @load_json_cases("draft3/optional/zeroTerminatedFloats.json") 225 | class TestDraft3(unittest.TestCase, TypesMixin, DecimalMixin, FormatMixin): 226 | validator_class = Draft3Validator 227 | validator_kwargs = {"format_checker": draft3_format_checker} 228 | 229 | def test_any_type_is_valid_for_type_any(self): 230 | validator = self.validator_class({"type": "any"}) 231 | validator.validate(mock.Mock()) 232 | 233 | # TODO: we're in need of more meta schema tests 234 | def test_invalid_properties(self): 235 | with self.assertRaises(SchemaError): 236 | validate({}, {"properties": {"test": True}}, 237 | cls=self.validator_class) 238 | 239 | def test_minItems_invalid_string(self): 240 | with self.assertRaises(SchemaError): 241 | # needs to be an integer 242 | validate([1], {"minItems": "1"}, cls=self.validator_class) 243 | 244 | 245 | @load_json_cases( 246 | "draft4/*.json", 247 | skip=narrow_unicode_build, 248 | ignore_glob="draft4/refRemote.json", 249 | ) 250 | @load_json_cases( 251 | "draft4/optional/format.json", skip=missing_format(draft4_format_checker) 252 | ) 253 | @load_json_cases("draft4/optional/bignum.json") 254 | @load_json_cases("draft4/optional/zeroTerminatedFloats.json") 255 | class TestDraft4(unittest.TestCase, TypesMixin, DecimalMixin, FormatMixin): 256 | validator_class = Draft4Validator 257 | validator_kwargs = {"format_checker": draft4_format_checker} 258 | 259 | # TODO: we're in need of more meta schema tests 260 | def test_invalid_properties(self): 261 | with self.assertRaises(SchemaError): 262 | validate({}, {"properties": {"test": True}}, 263 | cls=self.validator_class) 264 | 265 | def test_minItems_invalid_string(self): 266 | with self.assertRaises(SchemaError): 267 | # needs to be an integer 268 | validate([1], {"minItems": "1"}, cls=self.validator_class) 269 | 270 | 271 | class RemoteRefResolutionMixin(object): 272 | def setUp(self): 273 | patch = mock.patch("jsonschema.validators.requests") 274 | requests = patch.start() 275 | requests.get.side_effect = self.resolve 276 | self.addCleanup(patch.stop) 277 | 278 | def resolve(self, reference): 279 | _, _, reference = reference.partition("http://localhost:1234/") 280 | return mock.Mock(**{"json.return_value": REMOTES.get(reference)}) 281 | 282 | 283 | @load_json_cases("draft3/refRemote.json") 284 | class Draft3RemoteResolution(RemoteRefResolutionMixin, unittest.TestCase): 285 | validator_class = Draft3Validator 286 | 287 | 288 | @load_json_cases("draft4/refRemote.json") 289 | class Draft4RemoteResolution(RemoteRefResolutionMixin, unittest.TestCase): 290 | validator_class = Draft4Validator 291 | -------------------------------------------------------------------------------- /sample_lambda/python/validation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # 5 | # Licensed under the Amazon Software License (the "License"). You may not use this file except in 6 | # compliance with the License. A copy of the License is located at 7 | # 8 | # http://aws.amazon.com/asl/ 9 | # 10 | # or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific 12 | # language governing permissions and limitations under the License. 13 | 14 | """Alexa Smart Home Validation Package Sample Code. 15 | 16 | This module is used by Alexa Smart Home skills to validate their Lambda responses and async 17 | messages before sending them back to Alexa. If an error is found, an exception is thrown so that 18 | the developer can catch the error and do something about it, instead of sending it back to Alexa 19 | and causing an error on the Alexa side. 20 | 21 | This specific package uses the jsonschema (https://github.com/Julian/jsonschema) Python implementation 22 | of the JSON Schema Draft 4 to perform the actual validation against the validation schema. 23 | 24 | """ 25 | 26 | import json 27 | 28 | from jsonschema import validate 29 | 30 | def validate_message(request, response): 31 | 32 | # update below with path to your validation schema 33 | # this path works if you copy the latest validation schema into the same directory as this file 34 | # validation schema: https://github.com/alexa/alexa-smarthome/wiki/Validation-Schema 35 | path_to_validation_schema = "alexa_smart_home_message_schema.json" 36 | 37 | with open(path_to_validation_schema) as json_file: 38 | schema = json.load(json_file) 39 | validate(response, schema) 40 | -------------------------------------------------------------------------------- /sample_messages/Authorization/Authorization.AcceptGrant.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.Authorization", 5 | "name": "AcceptGrant", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820" 8 | }, 9 | "payload": { 10 | "grant": { 11 | "type": "OAuth2.AuthorizationCode", 12 | "code": "ANUbUKCJqlBOpMhwYWxU" 13 | }, 14 | "grantee": { 15 | "type": "BearerToken", 16 | "token": "access-token-from-skill" 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sample_messages/Authorization/Authorization.AcceptGrant.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa.Authorization", 5 | "name": "AcceptGrant.Response", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4" 8 | }, 9 | "payload": {} 10 | } 11 | } -------------------------------------------------------------------------------- /sample_messages/Authorization/ErrorResponse.Authorization.ACCEPT_GRANT_FAILED.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa.Authorization", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "payload": { 11 | "type": "ACCEPT_GRANT_FAILED", 12 | "message": "Failed to handle the AcceptGrant directive because request to Login with Amazon failed" 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /sample_messages/BrightnessController/BrightnessController.AdjustBrightness.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.BrightnessController", 5 | "name": "AdjustBrightness", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "brightnessDelta": -25 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/BrightnessController/BrightnessController.AdjustBrightness.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.BrightnessController", 6 | "name": "brightness", 7 | "value": 50, 8 | "timeOfSample": "2017-02-03T16:20:50.52Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/BrightnessController/BrightnessController.SetBrightness.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.BrightnessController", 5 | "name": "SetBrightness", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "brightness": 75 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/BrightnessController/BrightnessController.SetBrightness.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.BrightnessController", 6 | "name": "brightness", 7 | "value": 75, 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/CameraStreamController/CameraStreamController.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.CameraStreamController", 5 | "name": "InitializeCameraStreams", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "cameraStreams": [ 20 | { 21 | "protocol": "RTSP", 22 | "resolution": { 23 | "width": 1920, 24 | "height": 1080 25 | }, 26 | "authorizationType": "BEARER", 27 | "videoCodec": "H264", 28 | "audioCodec": "AAC" 29 | }, 30 | { 31 | "protocol": "RTSP", 32 | "resolution": { 33 | "width": 1280, 34 | "height": 720 35 | }, 36 | "authorizationType": "BEARER", 37 | "videoCodec": "MPEG2", 38 | "audioCodec": "G711" 39 | } 40 | ] 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /sample_messages/CameraStreamController/CameraStreamController.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.EndpointHealth", 6 | "name": "connectivity", 7 | "value": { 8 | "value": "OK" 9 | }, 10 | "timeOfSample": "2017-09-27T18:30:30.45Z", 11 | "uncertaintyInMilliseconds": 200 12 | } 13 | ] 14 | }, 15 | "event": { 16 | "header": { 17 | "namespace": "Alexa.CameraStreamController", 18 | "name": "Response", 19 | "payloadVersion": "3", 20 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 21 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 22 | }, 23 | "endpoint": { 24 | "scope": { 25 | "type": "BearerToken", 26 | "token": "access-token-from-Amazon" 27 | }, 28 | "endpointId": "endpoint-001" 29 | }, 30 | "payload": { 31 | "cameraStreams": [ 32 | { 33 | "uri": "rtsp://username:password@link.to.video:443/feed1.mp4", 34 | "expirationTime": "2017-09-27T20:30:30.45Z", 35 | "idleTimeoutSeconds": 30, 36 | "protocol": "RTSP", 37 | "resolution": { 38 | "width": 1920, 39 | "height": 1080 40 | }, 41 | "authorizationType": "BASIC", 42 | "videoCodec": "H264", 43 | "audioCodec": "AAC" 44 | }, 45 | { 46 | "uri": "rtsp://username:password@link.to.video:443/feed2.mp4", 47 | "expirationTime": "2017-09-27T20:30:30.45Z", 48 | "idleTimeoutSeconds": 60, 49 | "protocol": "RTSP", 50 | "resolution": { 51 | "width": 1280, 52 | "height": 720 53 | }, 54 | "authorizationType": "DIGEST", 55 | "videoCodec": "MPEG2", 56 | "audioCodec": "G711" 57 | } 58 | ], 59 | "imageUri": "https://username:password@link.to.image/image.jpg" 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /sample_messages/ChangeReport/ChangeReport.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.BrightnessController", 6 | "name": "brightness", 7 | "value": 85, 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "ChangeReport", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4" 28 | }, 29 | "endpoint": { 30 | "scope": { 31 | "type": "BearerToken", 32 | "token": "access-token-from-Amazon" 33 | }, 34 | "endpointId": "endpoint-001" 35 | }, 36 | "payload": { 37 | "change": { 38 | "cause": { 39 | "type": "PHYSICAL_INTERACTION" 40 | }, 41 | "properties": [ 42 | { 43 | "namespace": "Alexa.PowerController", 44 | "name": "powerState", 45 | "value": "ON", 46 | "timeOfSample": "2017-09-27T18:30:30.45Z", 47 | "uncertaintyInMilliseconds": 200 48 | } 49 | ] 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /sample_messages/ChannelController/ChannelController.ChangeChannel.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ChannelController", 5 | "name": "ChangeChannel", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "channel": { 20 | "number": "1234", 21 | "callSign": "KSTATION1", 22 | "affiliateCallSign": "KSTATION2", 23 | "uri": "someUrl" 24 | }, 25 | "channelMetadata": { 26 | "name": "Alternate Channel Name", 27 | "image": "urlToImage" 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /sample_messages/ChannelController/ChannelController.SkipChannels.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ChannelController", 5 | "name": "SkipChannels", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "channelCount": 5 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/ChannelController/ChannelController.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.ChannelController", 6 | "name": "channel", 7 | "value": { 8 | "number": "1234", 9 | "callSign": "callsign1", 10 | "affiliateCallSign": "callsign2" 11 | }, 12 | "timeOfSample": "2017-09-27T18:30:30.45Z", 13 | "uncertaintyInMilliseconds": 200 14 | }, 15 | { 16 | "namespace": "Alexa.EndpointHealth", 17 | "name": "connectivity", 18 | "value": { 19 | "value": "OK" 20 | }, 21 | "timeOfSample": "2017-09-27T18:30:30.45Z", 22 | "uncertaintyInMilliseconds": 200 23 | } 24 | ] 25 | }, 26 | "event": { 27 | "header": { 28 | "namespace": "Alexa", 29 | "name": "Response", 30 | "payloadVersion": "3", 31 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 32 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 33 | }, 34 | "endpoint": { 35 | "scope": { 36 | "type": "BearerToken", 37 | "token": "access-token-from-Amazon" 38 | }, 39 | "endpointId": "endpoint-001" 40 | }, 41 | "payload": {} 42 | } 43 | } -------------------------------------------------------------------------------- /sample_messages/ColorController/ColorController.SetColor.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ColorController", 5 | "name": "SetColor", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "color": { 20 | "hue": 350.5, 21 | "saturation": 0.7138, 22 | "brightness": 0.6524 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /sample_messages/ColorController/ColorController.SetColor.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.ColorController", 6 | "name": "color", 7 | "value": { 8 | "hue": 350.5, 9 | "saturation": 0.7138, 10 | "brightness": 0.6524 11 | }, 12 | "timeOfSample": "2017-09-27T18:30:30.45Z", 13 | "uncertaintyInMilliseconds": 200 14 | }, 15 | { 16 | "namespace": "Alexa.EndpointHealth", 17 | "name": "connectivity", 18 | "value": { 19 | "value": "OK" 20 | }, 21 | "timeOfSample": "2017-09-27T18:30:30.45Z", 22 | "uncertaintyInMilliseconds": 200 23 | } 24 | ] 25 | }, 26 | "event": { 27 | "header": { 28 | "namespace": "Alexa", 29 | "name": "Response", 30 | "payloadVersion": "3", 31 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 32 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 33 | }, 34 | "endpoint": { 35 | "scope": { 36 | "type": "BearerToken", 37 | "token": "access-token-from-Amazon" 38 | }, 39 | "endpointId": "endpoint-001" 40 | }, 41 | "payload": {} 42 | } 43 | } -------------------------------------------------------------------------------- /sample_messages/ColorTemperatureController/ColorTemperatureController.DecreaseColorTemperature.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ColorTemperatureController", 5 | "name": "DecreaseColorTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/ColorTemperatureController/ColorTemperatureController.IncreaseColorTemperature.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ColorTemperatureController", 5 | "name": "IncreaseColorTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/ColorTemperatureController/ColorTemperatureController.SetColorTemperature.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ColorTemperatureController", 5 | "name": "SetColorTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "colorTemperatureInKelvin": 5000 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/ColorTemperatureController/ColorTemperatureController.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.ColorTemperatureController", 6 | "name": "colorTemperatureInKelvin", 7 | "value": 5000, 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/DeferredResponse/DeferredResponse.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa", 5 | "name": "DeferredResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "payload": { 11 | "estimatedDeferralInSeconds": 20 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /sample_messages/Discovery/Discovery.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.Discovery", 5 | "name": "Discover", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820" 8 | }, 9 | "payload": { 10 | "scope": { 11 | "type": "BearerToken", 12 | "token": "access-token-from-skill" 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /sample_messages/ErrorResponse/ErrorResponse.General.ENDPOINT_LOW_POWER.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-Amazon" 14 | }, 15 | "endpointId": "endpoint-001" 16 | }, 17 | "payload": { 18 | "type": "ENDPOINT_LOW_POWER", 19 | "message": "The lock battery is low", 20 | "percentageState": 5 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /sample_messages/ErrorResponse/ErrorResponse.General.TEMPERATURE_VALUE_OUT_OF_RANGE.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-Amazon" 14 | }, 15 | "endpointId": "endpoint-001" 16 | }, 17 | "payload": { 18 | "type": "TEMPERATURE_VALUE_OUT_OF_RANGE", 19 | "message": "The requested temperature of -15 is out of range", 20 | "validRange": { 21 | "minimumValue": { 22 | "value": 15.0, 23 | "scale": "CELSIUS" 24 | }, 25 | "maximumValue": { 26 | "value": 30.0, 27 | "scale": "CELSIUS" 28 | } 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /sample_messages/ErrorResponse/ErrorResponse.General.VALUE_OUT_OF_RANGE.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-Amazon" 14 | }, 15 | "endpointId": "endpoint-001" 16 | }, 17 | "payload": { 18 | "type": "VALUE_OUT_OF_RANGE", 19 | "message": "The color temperature cannot be set to 500", 20 | "validRange": { 21 | "minimumValue": 1000, 22 | "maximumValue": 10000 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /sample_messages/ErrorResponse/ErrorResponse.General.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-Amazon" 14 | }, 15 | "endpointId": "endpoint-001" 16 | }, 17 | "payload": { 18 | "type": "ENDPOINT_UNREACHABLE", 19 | "message": "Unable to reach endpoint-001 because it appears to be offline" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/ErrorResponse/README.md: -------------------------------------------------------------------------------- 1 | These ErrorResponses can be sent as a response to any directive from Alexa, and can opportunistically include context properties. 2 | -------------------------------------------------------------------------------- /sample_messages/InputController/InputController.SelectInput.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.InputController", 5 | "name": "SelectInput", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "input": "HDMI1" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/InputController/InputController.SelectInput.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.InputController", 6 | "name": "input", 7 | "value": "HDMI1", 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/LockController/LockController.Lock.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.LockController", 5 | "name": "Lock", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/LockController/LockController.Lock.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.LockController", 6 | "name": "lockState", 7 | "value": "LOCKED", 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/LockController/LockController.Unlock.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.LockController", 5 | "name": "Unlock", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/LockController/LockController.Unlock.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.LockController", 6 | "name": "lockState", 7 | "value": "UNLOCKED", 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/LockController/README.md: -------------------------------------------------------------------------------- 1 | LockController provides some flexibilty for both fast and slow lock hardware. The directives are the same, but the responses can be different. -------------------------------------------------------------------------------- /sample_messages/PercentageController/PercentageController.AdjustPercentage.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PercentageController", 5 | "name": "AdjustPercentage", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "percentageDelta": -20 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/PercentageController/PercentageController.SetPercentage.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PercentageController", 5 | "name": "SetPercentage", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "percentage": 74 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/PercentageController/PercentageController.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.PercentageController", 6 | "name": "percentage", 7 | "value": 74, 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.FastForward.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "FastForward", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.Next.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "Next", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.Pause.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "Pause", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.Play.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "Play", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.Previous.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "Previous", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.Rewind.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "Rewind", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.StartOver.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "StartOver", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.Stop.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PlaybackController", 5 | "name": "Stop", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PlaybackController/PlaybackController.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.EndpointHealth", 6 | "name": "connectivity", 7 | "value": { 8 | "value": "OK" 9 | }, 10 | "timeOfSample": "2017-09-27T18:30:30.45Z", 11 | "uncertaintyInMilliseconds": 200 12 | } 13 | ] 14 | }, 15 | "event": { 16 | "header": { 17 | "namespace": "Alexa", 18 | "name": "Response", 19 | "payloadVersion": "3", 20 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 21 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 22 | }, 23 | "endpoint": { 24 | "scope": { 25 | "type": "BearerToken", 26 | "token": "access-token-from-Amazon" 27 | }, 28 | "endpointId": "endpoint-001" 29 | }, 30 | "payload": {} 31 | } 32 | } -------------------------------------------------------------------------------- /sample_messages/PowerController/PowerController.TurnOff.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PowerController", 5 | "name": "TurnOff", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PowerController/PowerController.TurnOff.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.PowerController", 6 | "name": "powerState", 7 | "value": "OFF", 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/PowerController/PowerController.TurnOn.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PowerController", 5 | "name": "TurnOn", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/PowerController/PowerController.TurnOn.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.PowerController", 6 | "name": "powerState", 7 | "value": "ON", 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/PowerLevelController/PowerLevelController.AdjustPowerLevel.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PowerLevelController", 5 | "name": "AdjustPowerLevel", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "powerLevelDelta": 3 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/PowerLevelController/PowerLevelController.SetPowerLevel.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.PowerLevelController", 5 | "name": "SetPowerLevel", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "powerLevel": 42 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/PowerLevelController/PowerLevelController.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.PowerLevelController", 6 | "name": "powerLevel", 7 | "value": 42, 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.EndpointHealth", 13 | "name": "connectivity", 14 | "value": { 15 | "value": "OK" 16 | }, 17 | "timeOfSample": "2017-09-27T18:30:30.45Z", 18 | "uncertaintyInMilliseconds": 200 19 | } 20 | ] 21 | }, 22 | "event": { 23 | "header": { 24 | "namespace": "Alexa", 25 | "name": "Response", 26 | "payloadVersion": "3", 27 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 28 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 29 | }, 30 | "endpoint": { 31 | "scope": { 32 | "type": "BearerToken", 33 | "token": "access-token-from-Amazon" 34 | }, 35 | "endpointId": "endpoint-001" 36 | }, 37 | "payload": {} 38 | } 39 | } -------------------------------------------------------------------------------- /sample_messages/README.md: -------------------------------------------------------------------------------- 1 | Readme: https://github.com/alexa/alexa-smarthome/wiki/Sample-Messages 2 | -------------------------------------------------------------------------------- /sample_messages/SceneController/SceneController.Activate.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.SceneController", 5 | "name": "Activate", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/SceneController/SceneController.ActivationStarted.message.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.EndpointHealth", 6 | "name": "connectivity", 7 | "value": { 8 | "value": "OK" 9 | }, 10 | "timeOfSample": "2017-09-27T18:30:30.45Z", 11 | "uncertaintyInMilliseconds": 200 12 | } 13 | ] 14 | }, 15 | "event": { 16 | "header": { 17 | "namespace": "Alexa.SceneController", 18 | "name": "ActivationStarted", 19 | "payloadVersion": "3", 20 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 21 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 22 | }, 23 | "endpoint": { 24 | "scope": { 25 | "type": "BearerToken", 26 | "token": "access-token-from-Amazon" 27 | }, 28 | "endpointId": "endpoint-001" 29 | }, 30 | "payload": { 31 | "cause": { 32 | "type": "VOICE_INTERACTION" 33 | }, 34 | "timestamp": "2017-09-27T18:30:30.45Z" 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /sample_messages/SceneController/SceneController.Deactivate.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.SceneController", 5 | "name": "Deactivate", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/SceneController/SceneController.DeactivationStarted.message.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.EndpointHealth", 6 | "name": "connectivity", 7 | "value": { 8 | "value": "OK" 9 | }, 10 | "timeOfSample": "2017-09-27T18:30:30.45Z", 11 | "uncertaintyInMilliseconds": 200 12 | } 13 | ] 14 | }, 15 | "event": { 16 | "header": { 17 | "namespace": "Alexa.SceneController", 18 | "name": "DeactivationStarted", 19 | "payloadVersion": "3", 20 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 21 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 22 | }, 23 | "endpoint": { 24 | "scope": { 25 | "type": "BearerToken", 26 | "token": "access-token-from-Amazon" 27 | }, 28 | "endpointId": "endpoint-001" 29 | }, 30 | "payload": { 31 | "cause": { 32 | "type": "APP_INTERACTION" 33 | }, 34 | "timestamp": "2017-09-27T18:30:30.45Z" 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /sample_messages/Speaker/Speaker.AdjustVolume.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.Speaker", 5 | "name": "AdjustVolume", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "volume": -20, 20 | "volumeDefault": false 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /sample_messages/Speaker/Speaker.SetMute.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.Speaker", 5 | "name": "SetMute", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "mute": true 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/Speaker/Speaker.SetVolume.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.Speaker", 5 | "name": "SetVolume", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "volume": 50 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/Speaker/Speaker.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.Speaker", 6 | "name": "volume", 7 | "value": 50, 8 | "timeOfSample": "2017-09-27T18:30:30.45Z", 9 | "uncertaintyInMilliseconds": 200 10 | }, 11 | { 12 | "namespace": "Alexa.Speaker", 13 | "name": "muted", 14 | "value": false, 15 | "timeOfSample": "2017-09-27T18:30:30.45Z", 16 | "uncertaintyInMilliseconds": 200 17 | }, 18 | { 19 | "namespace": "Alexa.EndpointHealth", 20 | "name": "connectivity", 21 | "value": { 22 | "value": "OK" 23 | }, 24 | "timeOfSample": "2017-09-27T18:30:30.45Z", 25 | "uncertaintyInMilliseconds": 200 26 | } 27 | ] 28 | }, 29 | "event": { 30 | "header": { 31 | "namespace": "Alexa", 32 | "name": "Response", 33 | "payloadVersion": "3", 34 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 35 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 36 | }, 37 | "endpoint": { 38 | "scope": { 39 | "type": "BearerToken", 40 | "token": "access-token-from-Amazon" 41 | }, 42 | "endpointId": "endpoint-001" 43 | }, 44 | "payload": {} 45 | } 46 | } -------------------------------------------------------------------------------- /sample_messages/StateReport/ReportState.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa", 5 | "name": "ReportState", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "endpointId": "endpoint-001", 12 | "cookie": {}, 13 | "scope": { 14 | "type": "BearerToken", 15 | "token": "access-token-from-skill" 16 | } 17 | }, 18 | "payload": {} 19 | } 20 | } -------------------------------------------------------------------------------- /sample_messages/StateReport/StateReport.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.EndpointHealth", 6 | "name": "connectivity", 7 | "value": { 8 | "value": "OK" 9 | }, 10 | "timeOfSample": "2017-09-27T18:30:30.45Z", 11 | "uncertaintyInMilliseconds": 200 12 | }, 13 | { 14 | "name": "targetSetpoint", 15 | "namespace": "Alexa.ThermostatController", 16 | "value": { 17 | "scale": "CELSIUS", 18 | "value": 25 19 | }, 20 | "timeOfSample": "2017-09-27T18:30:30.45Z", 21 | "uncertaintyInMilliseconds": 200 22 | }, 23 | { 24 | "name": "thermostatMode", 25 | "namespace": "Alexa.ThermostatController", 26 | "value": "AUTO", 27 | "timeOfSample": "2017-09-27T18:30:30.45Z", 28 | "uncertaintyInMilliseconds": 200 29 | }, 30 | { 31 | "name": "temperature", 32 | "namespace": "Alexa.TemperatureSensor", 33 | "value": { 34 | "scale": "CELSIUS", 35 | "value": 20 36 | }, 37 | "timeOfSample": "2017-09-27T18:30:30.45Z", 38 | "uncertaintyInMilliseconds": 200 39 | } 40 | ] 41 | }, 42 | "event": { 43 | "header": { 44 | "namespace": "Alexa", 45 | "name": "StateReport", 46 | "payloadVersion": "3", 47 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 48 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 49 | }, 50 | "endpoint": { 51 | "scope": { 52 | "type": "BearerToken", 53 | "token": "access-token-from-Amazon" 54 | }, 55 | "endpointId": "endpoint-001" 56 | }, 57 | "payload": {} 58 | } 59 | } -------------------------------------------------------------------------------- /sample_messages/StepSpeaker/StepSpeaker.AdjustVolume.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.StepSpeaker", 5 | "name": "AdjustVolume", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "volumeSteps": -20 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/StepSpeaker/StepSpeaker.SetMute.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.StepSpeaker", 5 | "name": "SetMute", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "mute": true 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/StepSpeaker/StepSpeaker.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.EndpointHealth", 6 | "name": "connectivity", 7 | "value": { 8 | "value": "OK" 9 | }, 10 | "timeOfSample": "2017-09-27T18:30:30.45Z", 11 | "uncertaintyInMilliseconds": 200 12 | } 13 | ] 14 | }, 15 | "event": { 16 | "header": { 17 | "namespace": "Alexa", 18 | "name": "Response", 19 | "payloadVersion": "3", 20 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 21 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 22 | }, 23 | "endpoint": { 24 | "scope": { 25 | "type": "BearerToken", 26 | "token": "access-token-from-Amazon" 27 | }, 28 | "endpointId": "endpoint-001" 29 | }, 30 | "payload": {} 31 | } 32 | } -------------------------------------------------------------------------------- /sample_messages/TemperatureSensor/TemperatureSensor.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.TemperatureSensor", 6 | "name": "temperature", 7 | "value": { 8 | "value": 24.0, 9 | "scale": "CELSIUS" 10 | }, 11 | "timeOfSample": "2017-09-27T18:30:30.45Z", 12 | "uncertaintyInMilliseconds": 200 13 | }, 14 | { 15 | "namespace": "Alexa.EndpointHealth", 16 | "name": "connectivity", 17 | "value": { 18 | "value": "OK" 19 | }, 20 | "timeOfSample": "2017-09-27T18:30:30.45Z", 21 | "uncertaintyInMilliseconds": 200 22 | } 23 | ] 24 | }, 25 | "event": { 26 | "header": { 27 | "namespace": "Alexa", 28 | "name": "StateReport", 29 | "payloadVersion": "3", 30 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 31 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 32 | }, 33 | "endpoint": { 34 | "scope": { 35 | "type": "BearerToken", 36 | "token": "access-token-from-Amazon" 37 | }, 38 | "endpointId": "endpoint-001" 39 | }, 40 | "payload": {} 41 | } 42 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ErrorResponse.ThermostatController.General.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-Amazon" 14 | }, 15 | "endpointId": "endpoint-001" 16 | }, 17 | "payload": { 18 | "type": "THERMOSTAT_IS_OFF", 19 | "message": "The thermostat is off, cannot turn on due to safety reasons" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ErrorResponse.ThermostatController.REQUESTED_SETPOINTS_TOO_CLOSE.json: -------------------------------------------------------------------------------- 1 | { 2 | "event": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "ErrorResponse", 6 | "payloadVersion": "3", 7 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-Amazon" 14 | }, 15 | "endpointId": "endpoint-001" 16 | }, 17 | "payload": { 18 | "type": "REQUESTED_SETPOINTS_TOO_CLOSE", 19 | "message": "The requested temperature results in setpoints too close", 20 | "minimumTemperatureDelta": { 21 | "value": 2.0, 22 | "scale": "CELSIUS" 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.AdjustTargetTemperature.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "AdjustTargetTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "targetSetpointDelta": { 20 | "value": -2.0, 21 | "scale": "FAHRENHEIT" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetTargetTemperature.DualMode.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "SetTargetTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "lowerSetpoint": { 20 | "value": 68.0, 21 | "scale": "FAHRENHEIT" 22 | }, 23 | "upperSetpoint": { 24 | "value": 78.0, 25 | "scale": "FAHRENHEIT" 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetTargetTemperature.DualMode.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.ThermostatController", 6 | "name": "lowerSetpoint", 7 | "value": { 8 | "value": 68.0, 9 | "scale": "FAHRENHEIT" 10 | }, 11 | "timeOfSample": "2017-09-27T18:30:30.45Z", 12 | "uncertaintyInMilliseconds": 200 13 | }, 14 | { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "upperSetpoint", 17 | "value": { 18 | "value": 74.0, 19 | "scale": "FAHRENHEIT" 20 | }, 21 | "timeOfSample": "2017-09-27T18:30:30.45Z", 22 | "uncertaintyInMilliseconds": 200 23 | }, 24 | { 25 | "namespace": "Alexa.ThermostatController", 26 | "name": "thermostatMode", 27 | "value": "AUTO", 28 | "timeOfSample": "2017-09-27T18:30:30.45Z", 29 | "uncertaintyInMilliseconds": 200 30 | }, 31 | { 32 | "namespace": "Alexa.EndpointHealth", 33 | "name": "connectivity", 34 | "value": { 35 | "value": "OK" 36 | }, 37 | "timeOfSample": "2017-09-27T18:30:30.45Z", 38 | "uncertaintyInMilliseconds": 200 39 | } 40 | ] 41 | }, 42 | "event": { 43 | "header": { 44 | "namespace": "Alexa", 45 | "name": "Response", 46 | "payloadVersion": "3", 47 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 48 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 49 | }, 50 | "endpoint": { 51 | "scope": { 52 | "type": "BearerToken", 53 | "token": "access-token-from-Amazon" 54 | }, 55 | "endpointId": "endpoint-001" 56 | }, 57 | "payload": {} 58 | } 59 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetTargetTemperature.SingleMode.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "SetTargetTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "targetSetpoint": { 20 | "value": 25.0, 21 | "scale": "CELSIUS" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetTargetTemperature.SingleMode.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.ThermostatController", 6 | "name": "targetSetpoint", 7 | "value": { 8 | "value": 25, 9 | "scale": "CELSIUS" 10 | }, 11 | "timeOfSample": "2017-09-27T18:30:30.45Z", 12 | "uncertaintyInMilliseconds": 200 13 | }, 14 | { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "thermostatMode", 17 | "value": "HEAT", 18 | "timeOfSample": "2017-09-27T18:30:30.45Z", 19 | "uncertaintyInMilliseconds": 200 20 | }, 21 | { 22 | "namespace": "Alexa.EndpointHealth", 23 | "name": "connectivity", 24 | "value": { 25 | "value": "OK" 26 | }, 27 | "timeOfSample": "2017-09-27T18:30:30.45Z", 28 | "uncertaintyInMilliseconds": 200 29 | } 30 | ] 31 | }, 32 | "event": { 33 | "header": { 34 | "namespace": "Alexa", 35 | "name": "Response", 36 | "payloadVersion": "3", 37 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 38 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 39 | }, 40 | "endpoint": { 41 | "scope": { 42 | "type": "BearerToken", 43 | "token": "access-token-from-Amazon" 44 | }, 45 | "endpointId": "endpoint-001" 46 | }, 47 | "payload": {} 48 | } 49 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetTargetTemperature.TripleMode.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "SetTargetTemperature", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "targetSetpoint": { 20 | "value": 73.0, 21 | "scale": "FAHRENHEIT" 22 | }, 23 | "lowerSetpoint": { 24 | "value": 68.0, 25 | "scale": "FAHRENHEIT" 26 | }, 27 | "upperSetpoint": { 28 | "value": 78.0, 29 | "scale": "FAHRENHEIT" 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetTargetTemperature.TripleMode.response.json: -------------------------------------------------------------------------------- 1 | { 2 | "context": { 3 | "properties": [ 4 | { 5 | "namespace": "Alexa.ThermostatController", 6 | "name": "lowerSetpoint", 7 | "value": { 8 | "value": 68.0, 9 | "scale": "FAHRENHEIT" 10 | }, 11 | "timeOfSample": "2017-09-27T18:30:30.45Z", 12 | "uncertaintyInMilliseconds": 200 13 | }, 14 | { 15 | "namespace": "Alexa.ThermostatController", 16 | "name": "targetSetpoint", 17 | "value": { 18 | "value": 72.0, 19 | "scale": "FAHRENHEIT" 20 | }, 21 | "timeOfSample": "2017-09-27T18:30:30.45Z", 22 | "uncertaintyInMilliseconds": 200 23 | }, 24 | { 25 | "namespace": "Alexa.ThermostatController", 26 | "name": "upperSetpoint", 27 | "value": { 28 | "value": 76.0, 29 | "scale": "FAHRENHEIT" 30 | }, 31 | "timeOfSample": "2017-09-27T18:30:30.45Z", 32 | "uncertaintyInMilliseconds": 200 33 | }, 34 | { 35 | "namespace": "Alexa.ThermostatController", 36 | "name": "thermostatMode", 37 | "value": "AUTO", 38 | "timeOfSample": "2017-09-27T18:30:30.45Z", 39 | "uncertaintyInMilliseconds": 200 40 | }, 41 | { 42 | "namespace": "Alexa.EndpointHealth", 43 | "name": "connectivity", 44 | "value": { 45 | "value": "OK" 46 | }, 47 | "timeOfSample": "2017-09-27T18:30:30.45Z", 48 | "uncertaintyInMilliseconds": 200 49 | } 50 | ] 51 | }, 52 | "event": { 53 | "header": { 54 | "namespace": "Alexa", 55 | "name": "Response", 56 | "payloadVersion": "3", 57 | "messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4", 58 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 59 | }, 60 | "endpoint": { 61 | "scope": { 62 | "type": "BearerToken", 63 | "token": "access-token-from-Amazon" 64 | }, 65 | "endpointId": "endpoint-001" 66 | }, 67 | "payload": {} 68 | } 69 | } -------------------------------------------------------------------------------- /sample_messages/ThermostatController/ThermostatController.SetThermostatMode.request.json: -------------------------------------------------------------------------------- 1 | { 2 | "directive": { 3 | "header": { 4 | "namespace": "Alexa.ThermostatController", 5 | "name": "SetThermostatMode", 6 | "payloadVersion": "3", 7 | "messageId": "1bd5d003-31b9-476f-ad03-71d471922820", 8 | "correlationToken": "dFMb0z+PgpgdDmluhJ1LddFvSqZ/jCc8ptlAKulUj90jSqg==" 9 | }, 10 | "endpoint": { 11 | "scope": { 12 | "type": "BearerToken", 13 | "token": "access-token-from-skill" 14 | }, 15 | "endpointId": "endpoint-001", 16 | "cookie": {} 17 | }, 18 | "payload": { 19 | "thermostatMode": { 20 | "value": "COOL" 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /validation_schemas/README.md: -------------------------------------------------------------------------------- 1 | Alexa Smart Home Message JSON Schema 2 | ============================================== 3 | 4 | This directory contains JSON schema for all possible Alexa Smart Home messages sent by a skill to Alexa. 5 | The JSON schema is machine generated and can be used for message validation during your skill development. 6 | For a detailed usage of the JSON schema please go to the following page: 7 | 8 | https://github.com/alexa/alexa-smarthome/wiki/Validation-Schemas 9 | 10 | ### The list of capabilities supported by the JSON schema: 11 | ``` 12 | Alexa 13 | Alexa.Authorization 14 | Alexa.AutomationManagement 15 | Alexa.BrightnessController 16 | Alexa.CameraStreamController 17 | Alexa.ChannelController 18 | Alexa.ColorController 19 | Alexa.ColorTemperatureController 20 | Alexa.ContactSensor 21 | Alexa.Cooking 22 | Alexa.Cooking.PresetController 23 | Alexa.Cooking.TimeController 24 | Alexa.CustomIntent 25 | Alexa.Discovery 26 | Alexa.DoorbellEventSource 27 | Alexa.EndpointHealth 28 | Alexa.EqualizerController 29 | Alexa.EventDetectionSensor 30 | Alexa.InputController 31 | Alexa.InventoryLevelSensor 32 | Alexa.Launcher 33 | Alexa.LockController 34 | Alexa.MediaMetadata 35 | Alexa.ModeController 36 | Alexa.MotionSensor 37 | Alexa.Networking.AccessController 38 | Alexa.Networking.ConnectedDevice 39 | Alexa.Networking.HomeNetworkController 40 | Alexa.PercentageController 41 | Alexa.PlaybackController 42 | Alexa.PowerController 43 | Alexa.PowerLevelController 44 | Alexa.RTCSessionController 45 | Alexa.RangeController 46 | Alexa.RecordController 47 | Alexa.RemoteVideoPlayer 48 | Alexa.SceneController 49 | Alexa.SecurityPanelController 50 | Alexa.SeekController 51 | Alexa.Speaker 52 | Alexa.StepSpeaker 53 | Alexa.TemperatureSensor 54 | Alexa.ThermostatController 55 | Alexa.TimeHoldController 56 | Alexa.ToggleController 57 | Alexa.WakeOnLANController 58 | ``` 59 | -------------------------------------------------------------------------------- /works_with_alexa/WWA_Submission Form.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/alexa-smarthome/a2c905c392a0089668fdb0f9f9bba8fc0b8195b5/works_with_alexa/WWA_Submission Form.xlsx --------------------------------------------------------------------------------