├── common ├── version.yaml ├── servers.yaml ├── headers.yaml ├── responses.yaml ├── security.yaml ├── schemas.yaml └── paths.yaml ├── cloud ├── servers.yaml ├── info.yaml └── paths.yaml ├── local ├── servers.yaml ├── info.yaml └── paths.yaml ├── ci ├── test.sh └── validate_with_refs.py ├── .gitignore ├── misc └── smart-by-bond-fans-for-control-systems │ ├── build.sh │ ├── smart-by-bond-fans-for-control-systems.pdf │ └── smart-by-bond-fans-for-control-systems.md ├── bonds ├── examples.yaml ├── schemas.yaml └── paths.yaml ├── Dockerfile ├── actions ├── schemas.yaml ├── group-paths.yaml ├── channel-paths.yaml └── paths.yaml ├── template.hbs ├── cloud.yaml ├── Makefile ├── users ├── schemas.yaml └── paths.yaml ├── locale ├── schemas.yaml └── paths.yaml ├── debug ├── beau.yaml ├── wifi.yaml ├── leds.yaml ├── livelog.yaml ├── si446x.yaml ├── rfman.yaml └── schemas.yaml ├── bridge ├── schemas.yaml └── paths.yaml ├── LICENSE ├── commands ├── schemas.yaml └── paths.yaml ├── api ├── bpup.yaml ├── bhk.yaml └── mqtt.yaml ├── sys ├── schemas.yaml ├── paths.yaml └── indicate.yaml ├── README.md ├── vrc ├── schemas.yaml └── paths.yaml ├── local.yaml ├── groups ├── schemas.yaml └── paths.yaml ├── token ├── paths.yaml └── schemas.yaml ├── scenes ├── schemas.yaml └── paths.yaml ├── keys ├── paths.yaml └── schemas.yaml ├── skeds ├── schemas.yaml ├── paths.yaml ├── group-paths.yaml ├── scene-paths.yaml └── channel-paths.yaml ├── .circleci └── config.yml ├── channels ├── paths.yaml └── schemas.yaml ├── signal ├── schemas.yaml └── paths.yaml ├── network └── schemas.yaml ├── weather_sensor ├── paths.yaml └── schemas.yaml ├── sidekicks └── schemas.yaml └── devices └── schemas.yaml /common/version.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | "2.0" 3 | -------------------------------------------------------------------------------- /cloud/servers.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - url: https://api.bondhome.io 3 | description: Cloud API 4 | -------------------------------------------------------------------------------- /common/servers.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - url: https://192.168.0.100/ 3 | description: Local API 4 | -------------------------------------------------------------------------------- /local/servers.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - url: https://192.168.0.100/ 3 | description: Local API 4 | -------------------------------------------------------------------------------- /ci/test.sh: -------------------------------------------------------------------------------- 1 | pip3 install openapi-spec-validator 2 | python3 ci/validate_with_refs.py local.yaml 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv/ 2 | docs.html 3 | node_modules 4 | package-lock.json 5 | package.json 6 | redoc-static.html 7 | -------------------------------------------------------------------------------- /misc/smart-by-bond-fans-for-control-systems/build.sh: -------------------------------------------------------------------------------- 1 | export F=smart-by-bond-fans-for-control-systems 2 | pandoc $F.md -o $F.pdf && open $F.pdf 3 | -------------------------------------------------------------------------------- /bonds/examples.yaml: -------------------------------------------------------------------------------- 1 | list: 2 | - firmware_version: 1.1.2 3 | id: AA00001 4 | location: Room 5 | 6 | - firmware_version: 1.1.3 7 | id: AA00002 8 | location: null 9 | -------------------------------------------------------------------------------- /local/info.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bond Local API 3 | version: "v3.0.0" 4 | x-logo: 5 | url: https://s3.amazonaws.com/docs-cloud.appbond.com/bond.png 6 | description: 7 | $ref: ../common/info.yaml#/description 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM cimg/node:21.1.0 2 | 3 | RUN npm install redoc && npm install -g redoc-cli 4 | 5 | WORKDIR /code 6 | 7 | COPY . /code 8 | 9 | CMD ["redoc-cli", "bundle", "local.yaml", "-o=docs.html"] 10 | -------------------------------------------------------------------------------- /misc/smart-by-bond-fans-for-control-systems/smart-by-bond-fans-for-control-systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bondhome/api-v2/HEAD/misc/smart-by-bond-fans-for-control-systems/smart-by-bond-fans-for-control-systems.pdf -------------------------------------------------------------------------------- /cloud/info.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bond Cloud API 3 | version: 4 | $ref: ../common/info.yaml#/version 5 | description: 6 | $ref: ../common/info.yaml#/description 7 | x-logo: 8 | url: https://s3.amazonaws.com/bond-api-docs/bond.png 9 | -------------------------------------------------------------------------------- /common/headers.yaml: -------------------------------------------------------------------------------- 1 | PaginationHeader: 2 | BONDAPI-NEXT-PAGE: 3 | description: Pagination next page 4 | schema: 5 | type: number 6 | BONDAPI-PREVIOUS-PAGE: 7 | description: Pagination previous page 8 | schema: 9 | type: number 10 | -------------------------------------------------------------------------------- /actions/schemas.yaml: -------------------------------------------------------------------------------- 1 | Actions: 2 | example: 3 | - TurnOn 4 | - TurnOff 5 | type: string 6 | Args: 7 | type: object 8 | properties: 9 | field: 10 | type: string 11 | example: speed 12 | value: 13 | type: string 14 | example: 70% 15 | -------------------------------------------------------------------------------- /bonds/schemas.yaml: -------------------------------------------------------------------------------- 1 | Bond: 2 | properties: 3 | id: 4 | example: AA00001 5 | type: string 6 | firmware_version: 7 | allowEmptyValue: true 8 | example: 1.1.2 9 | type: string 10 | location: 11 | allowEmptyValue: true 12 | example: Room 13 | type: string 14 | required: 15 | - id 16 | -------------------------------------------------------------------------------- /template.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} 5 | 6 | 7 | 13 | {{{ redocHead }}} 14 | 15 | 16 | {{{ redocHTML }}} 17 | 18 | 19 | -------------------------------------------------------------------------------- /cloud.yaml: -------------------------------------------------------------------------------- 1 | openapi: "3.0.1" 2 | 3 | components: 4 | responses: 5 | $ref: common/responses.yaml 6 | schema: 7 | $ref: common/schemas.yaml 8 | securitySchemes: 9 | $ref: common/security.yaml 10 | 11 | paths: 12 | $ref: cloud/paths.yaml 13 | 14 | servers: 15 | $ref: cloud/servers.yaml 16 | 17 | info: 18 | $ref: cloud/info.yaml 19 | 20 | x-tagGroups: 21 | - name: Bonds and Users 22 | tags: 23 | - Bonds 24 | - Users 25 | - name: Devices 26 | tags: 27 | - Devices 28 | - Device State 29 | - Device Properties 30 | - Device Actions 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ahab: 2 | redoc-cli bundle local.yaml && open redoc-static.html 3 | 4 | build: 5 | docker build -t olibra.docs . 6 | 7 | run_cloud: 8 | docker run --rm -v ${PWD}:/code -p 8080:8080 olibra.docs redoc-cli serve cloud.yaml -t template.hbs -w 9 | 10 | run_local: 11 | docker run --rm -v ${PWD}:/code -p 8080:8080 olibra.docs redoc-cli serve local.yaml -t template.hbs -w 12 | 13 | bundle_cloud: 14 | docker run --rm -v ${PWD}:/code -p 8080:8080 olibra.docs redoc-cli bundle cloud.yaml -t template.hbs 15 | 16 | bundle_local: 17 | docker run --rm -v ${PWD}:/code -p 8080:8080 olibra.docs redoc-cli bundle local.yaml -t template.hbs 18 | 19 | test: 20 | ./ci/test.sh 21 | 22 | -------------------------------------------------------------------------------- /users/schemas.yaml: -------------------------------------------------------------------------------- 1 | User: 2 | properties: 3 | email: 4 | example: user@email.com 5 | type: string 6 | feature_group: 7 | default: C 8 | example: A 9 | type: string 10 | id: 11 | example: 1 12 | readOnly: true 13 | type: number 14 | password: 15 | example: secret 16 | format: password 17 | type: string 18 | writeOnly: true 19 | required: 20 | - email 21 | - password 22 | 23 | UserCollection: 24 | additionalProperties: 25 | $ref: '#/User' 26 | example: 27 | '1': 28 | email: user@email.com 29 | feature_group: B 30 | id: 1 31 | password: secretpass 32 | '2': 33 | email: anotheruser@email.com 34 | feature_group: C 35 | id: 2 36 | password: secretpass 37 | type: object 38 | -------------------------------------------------------------------------------- /locale/schemas.yaml: -------------------------------------------------------------------------------- 1 | Locale: 2 | properties: 3 | compliance_region: 4 | example: au 5 | type: string 6 | description: | 7 | Region for radio frequency compliance. 8 | This option must be set by the client (Bond Home app) during setup. 9 | String is a two-digit country code (ISO 3166-1 alpha-2). 10 | Supported options: 11 | - us: USA, Canada, Mexico 12 | - au: Australia [v2.15] 13 | - il: Israel [v4.12] 14 | - eu: Europe [v4.12] 15 | compliance_regions: 16 | example: [us, au, il, eu] 17 | type: array 18 | items: 19 | type: string 20 | description: | 21 | [Added in v4.12] 22 | List of compliance regions supported by this Bond. 23 | Setting any region not on the list will return a 400 error. -------------------------------------------------------------------------------- /cloud/paths.yaml: -------------------------------------------------------------------------------- 1 | /bonds: 2 | get: 3 | $ref: ../bonds/paths.yaml#/GetList 4 | 5 | /v2: 6 | get: 7 | $ref: ../bonds/paths.yaml#/Get 8 | parameters: 9 | - in: path 10 | name: id 11 | required: true 12 | schema: 13 | type: number 14 | 15 | /devices: 16 | get: 17 | $ref: ../devices/paths.yaml#/GetList 18 | 19 | /devices/{id}: 20 | get: 21 | $ref: ../devices/paths.yaml#/Get 22 | parameters: 23 | - in: path 24 | name: id 25 | required: true 26 | schema: 27 | type: number 28 | 29 | /devices/{id}/actions/{action}: 30 | put: 31 | $ref: ../actions/paths.yaml#/Put 32 | parameters: 33 | - in: path 34 | name: id 35 | required: true 36 | schema: 37 | type: number 38 | - in: path 39 | name: action 40 | required: true 41 | schema: 42 | type: string 43 | -------------------------------------------------------------------------------- /debug/beau.yaml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - in: path 3 | name: partition 4 | required: true 5 | schema: 6 | type: string 7 | get: 8 | responses: 9 | '200': 10 | content: 11 | application/json: 12 | schema: 13 | $ref: schemas.yaml#/BeauDb 14 | description: Database statistics 15 | summary: Get database statistics 16 | description: | 17 | Get some statistics about the main Bond database such as free space available. 18 | 19 | This endpoint exists for each of the partitions on the product which 20 | use the Beau database format: 21 | - `"db"` - the main read-write database where devices and settings are stored 22 | - `"id"` - the read-only partition containing Bond ID and certificates 23 | - `"state"` - contains state of each device [Bridges only] 24 | tags: 25 | - Database 26 | -------------------------------------------------------------------------------- /bridge/schemas.yaml: -------------------------------------------------------------------------------- 1 | Bridge: 2 | properties: 3 | location: 4 | example: My Room 5 | type: string 6 | name: 7 | example: My Bridge 8 | type: string 9 | bluelight: 10 | example: 127 11 | type: integer 12 | description: | 13 | Amount of blue light emitted from the Bond when it's idle: at `0` the light is off, 14 | and at `255` the light is at its maximum brightness. 15 | frequencies: 16 | readOnly: true 17 | example: [[38, 38], [433050, 434079]] 18 | type: array 19 | items: 20 | type: array 21 | items: 22 | type: integer 23 | description: | 24 | List of intervals (inclusive) of supported frequencies, 25 | in kHz. Values less than 1000 refer to IR rather than RF. 26 | Clients should prevent users from selecting frequencies outside 27 | this range to avoid 400 errors on transmit and scan endpoints. 28 | [added in v2.15] 29 | -------------------------------------------------------------------------------- /debug/wifi.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '200': 4 | content: 5 | application/json: 6 | schema: 7 | $ref: schemas.yaml#/Wifi 8 | description: Wi-Fi power settings 9 | summary: Get Wi-Fi power settings 10 | description: | 11 | The `shutdown` field indicates the power state of the Wi-Fi (+BLE) radio: 12 | - `0`: normal operation 13 | - `1`: low-power shutdown mode 14 | 15 | If the `shutdown` field is not present, assume normal operation. 16 | tags: 17 | - WiFi 18 | patch: 19 | requestBody: 20 | content: 21 | application/json: 22 | schema: 23 | $ref: schemas.yaml#/Wifi 24 | responses: 25 | '200': 26 | description: Wi-Fi power settings changed 27 | summary: Change Wi-Fi power settings 28 | description: | 29 | Set `shutdown` to `1` or `0` to control the Wi-Fi (+BLE) radio power level. A value 30 | of `1` turns this radio off. 31 | 32 | These settings do not persist past reboot. 33 | tags: 34 | - WiFi -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Bond Home Documentation License 2 | Copyright 2020 Olibra LLC. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and compiled forms with or without modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions must retain the above copyright notice, this list of conditions, and the following disclaimer. 8 | 9 | THIS DOCUMENTATION IS PROVIDED BY OLIBRA LLC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OLIBRA LLC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /debug/leds.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '200': 4 | content: 5 | application/json: 6 | schema: 7 | $ref: schemas.yaml#/Leds 8 | description: LED state 9 | summary: Get LED state 10 | description: | 11 | Get status from the BLED driver. 12 | 13 | If `manual` is `0`, `value` reflects the instantaneous value of the LEDs, 14 | and may change rapidly and automatically. 15 | tags: 16 | - LEDs 17 | patch: 18 | requestBody: 19 | content: 20 | application/json: 21 | schema: 22 | $ref: schemas.yaml#/Leds 23 | responses: 24 | '200': 25 | description: LED state was changed successfully 26 | '400': 27 | description: Error parsing request 28 | '500': 29 | description: Driver error 30 | summary: Manually control LEDs 31 | description: | 32 | Use this endpoint to manually control LEDs, such as during factory test. 33 | Be sure to use the `manual` field to prevent `value` from being overridden 34 | from automatic LED control. 35 | 36 | If `manual` is `0` or absent, `value` may still be set, but may be overridden 37 | at any time. 38 | tags: 39 | - LEDs -------------------------------------------------------------------------------- /debug/livelog.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '204': 4 | description: LiveLog disabled 5 | '200': 6 | content: 7 | application/json: 8 | schema: 9 | $ref: schemas.yaml#/LiveLog 10 | description: LiveLog configuration 11 | summary: Get LiveLog configuration 12 | description: | 13 | Get the current configuration of the LiveLog component. 14 | tags: 15 | - LiveLog 16 | put: 17 | requestBody: 18 | content: 19 | application/json: 20 | schema: 21 | $ref: schemas.yaml#/LiveLog 22 | responses: 23 | '200': 24 | description: LiveLog configured 25 | '400': 26 | description: Error parsing request 27 | summary: Configure LiveLog 28 | description: | 29 | Instructs Bond to start sending UDP packets to specified IP address and port. 30 | Every log message is sent in a seperate UDP packet. 31 | Depending on log verbosity, this may cause serious performance problems, 32 | so use wisely. 33 | 34 | This setting does not persist reboot. 35 | tags: 36 | - LiveLog 37 | delete: 38 | responses: 39 | '204': 40 | description: LiveLog disabled 41 | summary: Disable LiveLog 42 | tags: 43 | - LiveLog -------------------------------------------------------------------------------- /common/responses.yaml: -------------------------------------------------------------------------------- 1 | BadRequest: 2 | content: 3 | application/json: 4 | schema: 5 | $ref: schemas.yaml#/BadRequest 6 | description: Bad request 7 | Conflict: 8 | content: 9 | application/json: 10 | schema: 11 | $ref: schemas.yaml#/Conflict 12 | description: Conflict 13 | Forbidden: 14 | content: 15 | application/json: 16 | schema: 17 | $ref: schemas.yaml#/Forbidden 18 | description: Forbidden 19 | InternalServerError: 20 | content: 21 | application/json: 22 | schema: 23 | $ref: schemas.yaml#/InternalServerError 24 | description: Internal Server Error 25 | NotFound: 26 | content: 27 | application/json: 28 | schema: 29 | $ref: schemas.yaml#/NotFound 30 | description: Not Found 31 | Unauthorized: 32 | content: 33 | application/json: 34 | schema: 35 | $ref: schemas.yaml#/Unauthorized 36 | description: Unauthorized 37 | Created: 38 | content: 39 | application/json: 40 | schema: 41 | $ref: schemas.yaml#/Created 42 | description: Resource Created 43 | Locked: 44 | content: 45 | application/json: 46 | schema: 47 | $ref: schemas.yaml#/Locked 48 | description: Resource is Locked 49 | -------------------------------------------------------------------------------- /debug/si446x.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '200': 4 | content: 5 | application/json: 6 | schema: 7 | $ref: schemas.yaml#/Fcc 8 | description: SubGHz Transceiver State 9 | summary: Get low-level radio state 10 | description: | 11 | Use this endpoint only as part of an FCC or factory test program. 12 | tags: 13 | - Debug 14 | patch: 15 | requestBody: 16 | content: 17 | application/json: 18 | schema: 19 | $ref: schemas.yaml#/Fcc 20 | responses: 21 | '200': 22 | description: FCC control accepted 23 | '400': 24 | description: Error parsing request 25 | '500': 26 | description: Driver error 27 | summary: Manually manipulate radio 28 | description: | 29 | All these settings require `manual` to be set before they take effect. 30 | 31 | Use this endpoint only as part of an FCC or factory test program. 32 | 33 | NOTE: In production firmware, FCC compliance is ensured via power, 34 | frequency, and antenna restrictions on this endpoint. 35 | If a setting beyond FCC limits is requested, a `200` will be returned, 36 | but upon subsequent GET, the values may either be unchanged or truncated. 37 | tags: 38 | - Debug -------------------------------------------------------------------------------- /actions/group-paths.yaml: -------------------------------------------------------------------------------- 1 | ActionPath: 2 | put: 3 | $ref: ../actions/group-paths.yaml#/Put 4 | parameters: 5 | - in: path 6 | name: action_name 7 | required: true 8 | schema: 9 | type: string 10 | - in: path 11 | name: group_id 12 | required: true 13 | schema: 14 | type: number 15 | 16 | Put: 17 | requestBody: 18 | content: 19 | application/json: 20 | schema: 21 | type: object 22 | example: 23 | argument: 4 24 | responses: 25 | '200': 26 | description: Action executed 27 | content: 28 | application/json: 29 | schema: 30 | type: object 31 | example: 32 | argument: 4 33 | '400': 34 | $ref: ../common/responses.yaml#/BadRequest 35 | '401': 36 | $ref: ../common/responses.yaml#/Unauthorized 37 | '500': 38 | $ref: ../common/responses.yaml#/InternalServerError 39 | summary: Execute a Group Action 40 | description: | 41 | `action_name` is the name of the action from the `actions` list in 42 | the response to GET `/groups/{group_id}`. 43 | 44 | This endpoint blocks until confirmation that the Bond has executed 45 | the Action on all member Devices. Timeout shall be no more than 7 seconds. 46 | 47 | To check the resulting state, the client may query 48 | `/groups/{group_id}/state`, but the member Device States are also updated. 49 | tags: 50 | - Group Actions 51 | security: 52 | - OAuth: ["oauth2"] 53 | -------------------------------------------------------------------------------- /commands/schemas.yaml: -------------------------------------------------------------------------------- 1 | Command: 2 | type: object 3 | properties: 4 | name: 5 | example: Light 6 | type: string 7 | description: | 8 | Name of corresponding button displayed in Bond App 9 | action: 10 | example: SetSpeed 11 | type: string 12 | description: | 13 | Action which should be triggered when button is pressed. 14 | argument: 15 | example: 3 16 | nullable: true 17 | description: | 18 | Argument of `action`. If absent, no argument will be used. 19 | May be any JSON value, not only an object. 20 | icon: 21 | example: speed_3 22 | type: string 23 | description: | 24 | Icon slug. (This is the base of the name of the icon to use to represent 25 | this command in the App.) 26 | category_name: 27 | example: fan 28 | type: string 29 | description: | 30 | The category in which to group this command. 31 | button_type: 32 | example: tap 33 | type: string 34 | description: | 35 | The type of button to use for this command. 36 | hidden: 37 | example: true 38 | type: boolean 39 | description: | 40 | Whether to hide this command in the mobile app. Useful for exposing an 41 | action, but not showing its command on the device panel. 42 | required: 43 | - name 44 | - action 45 | 46 | CommandList: 47 | type: object 48 | example: 49 | _: "7fc1e84b" 50 | 3b20f300: 51 | _: "9a5e1136" 52 | 4ad874d2: 53 | _: "84819a9f" 54 | a94328bc: 55 | _: "23141efa" 56 | d87d6ef2: 57 | _: "2425a8bc" 58 | -------------------------------------------------------------------------------- /bridge/paths.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '200': 4 | content: 5 | application/json: 6 | schema: 7 | $ref: schemas.yaml#/Bridge 8 | description: Get Bridge info 9 | '401': 10 | $ref: ../common/responses.yaml#/Unauthorized 11 | '404': 12 | $ref: ../common/responses.yaml#/NotFound 13 | '500': 14 | $ref: ../common/responses.yaml#/InternalServerError 15 | security: 16 | - OAuth: ["oauth2"] 17 | summary: Get Bridge info 18 | tags: 19 | - Bridge 20 | 21 | patch: 22 | requestBody: 23 | content: 24 | application/json: 25 | schema: 26 | $ref: schemas.yaml#/Bridge 27 | responses: 28 | '200': 29 | content: 30 | application/json: 31 | schema: 32 | $ref: schemas.yaml#/Bridge 33 | description: Change Bridge info 34 | '401': 35 | $ref: ../common/responses.yaml#/Unauthorized 36 | '404': 37 | $ref: ../common/responses.yaml#/NotFound 38 | '500': 39 | $ref: ../common/responses.yaml#/InternalServerError 40 | security: 41 | - BasicAuth: [] 42 | summary: Change Bridge info 43 | tags: 44 | - Bridge 45 | 46 | delete: 47 | responses: 48 | '204': 49 | description: Reset Bridge info 50 | '401': 51 | $ref: ../common/responses.yaml#/Unauthorized 52 | '404': 53 | $ref: ../common/responses.yaml#/NotFound 54 | '500': 55 | $ref: ../common/responses.yaml#/InternalServerError 56 | security: 57 | - BasicAuth: [] 58 | summary: Reset Bridge info 59 | description: | 60 | After deletion, default values will be restored. 61 | tags: 62 | - Bridge 63 | -------------------------------------------------------------------------------- /locale/paths.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '200': 4 | content: 5 | application/json: 6 | schema: 7 | $ref: schemas.yaml#/Locale 8 | description: Get Locale info 9 | '401': 10 | $ref: ../common/responses.yaml#/Unauthorized 11 | '404': 12 | $ref: ../common/responses.yaml#/NotFound 13 | '500': 14 | $ref: ../common/responses.yaml#/InternalServerError 15 | security: 16 | - OAuth: ["oauth2"] 17 | summary: Get Locale info 18 | tags: 19 | - Locale 20 | 21 | patch: 22 | requestBody: 23 | content: 24 | application/json: 25 | schema: 26 | $ref: schemas.yaml#/Locale 27 | responses: 28 | '200': 29 | content: 30 | application/json: 31 | schema: 32 | $ref: schemas.yaml#/Locale 33 | description: Change Locale info 34 | '401': 35 | $ref: ../common/responses.yaml#/Unauthorized 36 | '404': 37 | $ref: ../common/responses.yaml#/NotFound 38 | '500': 39 | $ref: ../common/responses.yaml#/InternalServerError 40 | security: 41 | - BasicAuth: [] 42 | summary: Change Locale info 43 | tags: 44 | - Locale 45 | 46 | delete: 47 | responses: 48 | '204': 49 | description: Reset Locale info 50 | '401': 51 | $ref: ../common/responses.yaml#/Unauthorized 52 | '404': 53 | $ref: ../common/responses.yaml#/NotFound 54 | '500': 55 | $ref: ../common/responses.yaml#/InternalServerError 56 | security: 57 | - BasicAuth: [] 58 | summary: Reset Locale info 59 | description: | 60 | After deletion, default values will be restored. 61 | tags: 62 | - Locale 63 | -------------------------------------------------------------------------------- /api/bpup.yaml: -------------------------------------------------------------------------------- 1 | Schema: 2 | type: object 3 | properties: 4 | broadcast: 5 | example: true 6 | type: boolean 7 | description: | 8 | If true, the Bond will broadcast all state updates on port 30007 9 | (disabled by default) 10 | 11 | Path: 12 | patch: 13 | requestBody: 14 | content: 15 | application/json: 16 | schema: 17 | $ref: ./bpup.yaml#/Schema 18 | responses: 19 | '200': 20 | description: BPUP Reconfigured 21 | '401': 22 | $ref: ../common/responses.yaml#/Unauthorized 23 | '500': 24 | $ref: ../common/responses.yaml#/InternalServerError 25 | security: 26 | - BasicAuth: [] 27 | summary: Configure BPUP Transport 28 | description: | 29 | Configure the Bond's BPUP transport. 30 | tags: 31 | - BPUP 32 | get: 33 | responses: 34 | '200': 35 | description: BPUP Configuration 36 | content: 37 | application/json: 38 | schema: 39 | $ref: ./bpup.yaml#/Schema 40 | '401': 41 | $ref: ../common/responses.yaml#/Unauthorized 42 | '500': 43 | $ref: ../common/responses.yaml#/InternalServerError 44 | security: 45 | - BasicAuth: [] 46 | summary: Get BPUP Configuration 47 | tags: 48 | - BPUP 49 | delete: 50 | responses: 51 | '204': 52 | description: BPUP config reset to default 53 | '401': 54 | $ref: ../common/responses.yaml#/Unauthorized 55 | '500': 56 | $ref: ../common/responses.yaml#/InternalServerError 57 | security: 58 | - BasicAuth: [] 59 | summary: Reset BPUP Config to defaults 60 | tags: 61 | - BPUP 62 | -------------------------------------------------------------------------------- /common/security.yaml: -------------------------------------------------------------------------------- 1 | OAuth: 2 | type: oauth2 3 | description: | 4 | Bond API implements OAuth for authentication and every request must be authenticated with access tokens, to receive data or send bond actions. 5 | 6 | ## tl;dr 7 | 8 | Register an account on Bond App, require for tokens and user access token to obtain permission to use Bond API. 9 | 10 | ## Bond API 11 | 12 | First of all, to obtain access to Bond API, it's necessary signing up on Bond App and set up a Bond. After that, it's possible to require a list of tokens: 13 | 14 | - id_token: used to identify itself on Bond API; 15 | - access_token: used to grant access to Bond API; 16 | - refresh_token: used to generate another token if expired. 17 | 18 | Then it could be possible to access Bond API. See some examples: 19 | 20 | ``` 21 | curl -H 'Authorization: Bearer eyJraWQi...OiJwUk' \ 22 | https://api.bondhome.io/bonds 23 | 24 | [{ 25 | "id": "AA01234", 26 | "firmware_version": "v123" 27 | }] 28 | ``` 29 | 30 | ``` 31 | curl -XPOST -H 'Authorization: Basic YWlmMzkzcmltcTRw...rOTNkbDB' \ 32 | -d 'grant_type=refresh_token&refresh_token=eyJjdHki...OiJKV1Q' \ 33 | https://api.bondhome.io/oauth/token 34 | 35 | { 36 | "id_token": "AbC...123", 37 | "access_token": "dEf...456", 38 | "expires": 3600, 39 | "token_type": "Bearer" 40 | } 41 | ``` 42 | 43 | See more: 44 | 45 | * https://tools.ietf.org/html/rfc6749 46 | * https://oauth.net/2/ 47 | 48 | flows: 49 | authorizationCode: 50 | refreshUrl: https://api.bondapp.io/oauth2/token 51 | scopes: 52 | read:bonds: read your bonds 53 | read:devices: read your devices 54 | write:actions: execute an action 55 | -------------------------------------------------------------------------------- /common/schemas.yaml: -------------------------------------------------------------------------------- 1 | ErrorBaseSchema: 2 | properties: 3 | _error_id: 4 | example: 1 5 | type: number 6 | BadRequest: 7 | allOf: 8 | - $ref: '#/ErrorBaseSchema' 9 | - properties: 10 | _error_msg: 11 | example: The resource wasn't created because of a validation problem (This field will have a description of the problem) 12 | type: string 13 | type: object 14 | Conflict: 15 | allOf: 16 | - $ref: '#/ErrorBaseSchema' 17 | - properties: 18 | _error_msg: 19 | example: The resource wasn't created because of a field conflict 20 | type: string 21 | type: object 22 | Forbidden: 23 | allOf: 24 | - $ref: '#/ErrorBaseSchema' 25 | - properties: 26 | _error_msg: 27 | example: You don't have the authorization to access this resource 28 | type: string 29 | type: object 30 | InternalServerError: 31 | allOf: 32 | - $ref: '#/ErrorBaseSchema' 33 | - properties: 34 | _error_msg: 35 | example: Something unexpected happened (this field will have a description of the problem) 36 | type: string 37 | type: object 38 | NotFound: 39 | allOf: 40 | - $ref: '#/ErrorBaseSchema' 41 | - properties: 42 | _error_msg: 43 | example: Resource not found 44 | type: string 45 | type: object 46 | Unauthorized: 47 | allOf: 48 | - $ref: '#/ErrorBaseSchema' 49 | - properties: 50 | _error_msg: 51 | example: You need authentication credentials to continue 52 | type: string 53 | type: object 54 | Created: 55 | properties: 56 | _id: 57 | example: "01234567" 58 | type: string 59 | description: id of new device 60 | type: object 61 | Locked: 62 | allOf: 63 | - $ref: '#/ErrorBaseSchema' 64 | - properties: 65 | _error_msg: 66 | example: Device is locked with non expired higher priority 67 | type: string 68 | type: object -------------------------------------------------------------------------------- /sys/schemas.yaml: -------------------------------------------------------------------------------- 1 | Power: 2 | type: object 3 | properties: 4 | poe_active: 5 | example: true 6 | type: boolean 7 | description: | 8 | True if the unit is being supplied PoE. 9 | usb_active: 10 | example: false 11 | type: boolean 12 | description: | 13 | True if the unit is being supplied USB. 14 | 15 | NOTE: multiple supplies may be simultaneously active. 16 | Time: 17 | type: object 18 | properties: 19 | unix_time: 20 | example: 1581708795 21 | type: number 22 | description: | 23 | Absolute time, in seconds since the UNIX epoch. 24 | 25 | Starts at zero at first boot for most products (with no backup battery). 26 | Automatically set via NTP (unless NTP has been disabled or 27 | the NTP server is unreachable), at which time `time_set` is set. 28 | time_set: 29 | example: true 30 | type: boolean 31 | description: | 32 | If false, then time has not (yet) been set or determined via NTP. 33 | 34 | Device Schedules do not run unless `time_set` is true. 35 | tz: 36 | example: America/Sao_Paulo 37 | type: string 38 | nullable: true 39 | description: | 40 | Timezone string, as per tz_database. 41 | 42 | `null` if unset. 43 | 44 | The current list of supported timezones is given at 45 | https://bond-updates.s3.amazonaws.com/tz_meta.json 46 | grid: 47 | example: FN30aw 48 | type: string 49 | nullable: true 50 | description: | 51 | Approximate geolocation of Bond unit, 52 | expressed as a 6-character Maidenhead Grid Locator. 53 | This information is used to calculate the sunrise and sunset 54 | times for Device Schedules. 55 | 56 | Regex: `([A-R]{2}[0-9]{2}[a-r]{2})?` 57 | 58 | `null` if unset. 59 | 60 | See: https://en.wikipedia.org/wiki/Maidenhead_Locator_System 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bond API V2 2 | 3 | Source code to documentation for the Bond V2 API, used by Bond Bridge and Smart by Bond products. This is the _Local API_ used within the home Wi-Fi network. 4 | 5 | To *read* the docs, please go here: http://docs-local.appbond.com/ 6 | 7 | ## Contribuing 8 | 9 | We welcome corrections and improvements to the API documentation. Please open a PR! 10 | 11 | By submitting a PR, you are agreeing to have your contribution licensed under the same terms as the rest of the docs. See LICENSE file. 12 | 13 | ## Prerequisite 14 | 15 | To be able to build and run this project, you need to have Docker and Node.js installed. 16 | If you don't know if you have Docker and Node.js or don't know their versions, check it using 17 | ``` 18 | docker -v 19 | node -v 20 | ``` 21 | 22 | * Docker can be installed from [their webiste](https://www.docker.com/products/docker-desktop). 23 | * Node.js can be installed from [their website](https://nodejs.org/en/download/) or updated using `n` ([see instructions](https://nodejs.org/en/download/package-manager/#n)) 24 | * The minimum Node.js required version is 14. 25 | 26 | ## Build image 27 | 28 | ``` 29 | make build 30 | ``` 31 | 32 | ## Run cloud or local documentation 33 | 34 | ### Cloud 35 | 36 | ``` 37 | make build 38 | make run_cloud 39 | ``` 40 | 41 | ### Local 42 | 43 | ``` 44 | make build 45 | make run_local 46 | ``` 47 | 48 | ## Bundle cloud or local documentation 49 | 50 | ### Cloud 51 | 52 | ``` 53 | make build 54 | make bundle_cloud 55 | ``` 56 | 57 | ### Private 58 | 59 | ``` 60 | make build 61 | make bundle_local 62 | ``` 63 | 64 | ## Tests 65 | 66 | This command should be running with python3 and pyyaml instaled 67 | 68 | 69 | ``` 70 | make test 71 | ``` 72 | 73 | 74 | ## Read documentation 75 | 76 | Open browser at [localhost:8080](http://localhost:8080). 77 | 78 | ## Specification 79 | 80 | - [OpenAPI](https://github.com/OAI/OpenAPI-Specification) 81 | - [Swagger](https://swagger.io/docs/specification/about/) 82 | - [API Handyman](https://apihandyman.io/the-story-behind-the-design-of-everyday-apis-book/) 83 | -------------------------------------------------------------------------------- /vrc/schemas.yaml: -------------------------------------------------------------------------------- 1 | Vrc: 2 | properties: 3 | enabled: 4 | example: true 5 | type: boolean 6 | description: | 7 | When enabled, the `vrc/keystream` endpoint becomes available. 8 | 9 | When enabling Vrc for one device, all other device's Vrcs are 10 | implicitely disabled. 11 | 12 | VrcKeystream: 13 | type: object 14 | properties: 15 | seq: 16 | example: 3210 17 | type: integer 18 | description: | 19 | Sequence number which client should increments for request. 20 | 21 | DESIGN NOTE: Actually it's not clear that we need this. The request ID 22 | already serves to prevent duplicate actions. 23 | event: 24 | example: HOLD 25 | type: string 26 | description: | 27 | Event which occured on the specified key. Possibilities are: 28 | - TAP -- sent if a brief (< 300 ms) press and release occurs on one or more 29 | keys. If keys are tapped together (say, within 200 ms), 30 | only a single TAP event should be sent with `key` specifying both. 31 | - DOUBLE_TAP (unsupported) 32 | - HOLD_START -- sent after 300 ms of a key being held down. 33 | If two keys are starting to be pressed within 300 ms of eachother, 34 | only a single HOLD_START event should be sent. 35 | - HOLD -- sent every 300 ms while keys are held. 36 | - HOLD_END -- sent when a held key is released, where only the 37 | released keys are specified in `key`. If some keys are still 38 | held, they will continue to send `HOLD`. 39 | 40 | key: 41 | example: [1, 3] 42 | type: array 43 | description: | 44 | list of 1-based key numbers. Must be non-empty. 45 | 46 | In the case of a single key, an integer may be sent instead of an array. 47 | hold_ms: 48 | example: 1760 49 | type: integer 50 | description: | 51 | Length of time for which key(s) has been held, in milliseconds. 52 | Only provided for HOLD and HOLD_END events. 53 | 54 | For multiple keys, this is the time since the last change 55 | of keys pressed. 56 | -------------------------------------------------------------------------------- /local.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | openapi: "3.0.2" 3 | 4 | info: 5 | $ref: local/info.yaml 6 | 7 | servers: 8 | $ref: local/servers.yaml 9 | 10 | paths: 11 | $ref: local/paths.yaml 12 | 13 | x-tagGroups: 14 | - name: Devices 15 | tags: 16 | - Devices 17 | - Device State 18 | - Device Properties 19 | - Device Actions 20 | - Device Remote Address 21 | - Device Reload 22 | - Power Cycle State 23 | - name: Commands 24 | tags: 25 | - Device Commands 26 | - Device Command Signal 27 | - Device Command Transmit 28 | - name: Groups 29 | tags: 30 | - Groups 31 | - Group Devices 32 | - Group State 33 | - Group Properties 34 | - Group Actions 35 | - name: Scenes 36 | tags: 37 | - Scenes 38 | - name: Schedules 39 | tags: 40 | - Device Schedules 41 | - Group Schedules 42 | - Scene Schedules 43 | - Channel Schedules 44 | - name: Virtual Remote Control 45 | tags: 46 | - Virtual Remote Control 47 | - name: Sidekick 48 | tags: 49 | - Sidekick 50 | - Sidekick Learn 51 | - Keystream 52 | - Channels 53 | - Channel Actions 54 | - Quick Action Keys 55 | - name: Weather Sensor 56 | tags: 57 | - Weather Sensor 58 | - Weather Sensor Properties 59 | - Weather Sensor State 60 | - Weather Sensor Test 61 | - name: Bridge 62 | tags: 63 | - Bridge 64 | - name: Signals 65 | tags: 66 | - Transmit 67 | - Scan 68 | - Scan Result 69 | - Rssi 70 | - name: API 71 | tags: 72 | - Token 73 | - MQTT 74 | - BPUP 75 | - HomeKit 76 | - name: Network 77 | tags: 78 | - Wi-Fi Scan 79 | - Wi-Fi Station 80 | - Ethernet 81 | - Network Watchdog 82 | - name: System 83 | tags: 84 | - Upgrade 85 | - Version 86 | - Backup 87 | - Reset 88 | - Reboot 89 | - Time 90 | - Power 91 | - Locale 92 | - Indicate 93 | - name: Debug 94 | tags: 95 | - Database 96 | - LiveLog 97 | - LEDs 98 | - WiFi 99 | - RF Manager 100 | -------------------------------------------------------------------------------- /groups/schemas.yaml: -------------------------------------------------------------------------------- 1 | Group: 2 | properties: 3 | name: 4 | example: Kitchen Shades 5 | type: string 6 | devices: 7 | description: | 8 | List of member Device IDs. 9 | 10 | This field may be set during Group creation, 11 | or may be updated using PATCH. 12 | type: array 13 | example: 14 | - "aabbccdd" 15 | - "11223344" 16 | - "deadbeef" 17 | types: 18 | readOnly: true 19 | description: | 20 | For values, see `type` field of Device schema. 21 | 22 | Type is automatically set by the Bond Bridge to be the set of types of the 23 | underlying devices. Note that 24 | Group types is always an array, even if it has zero or one element. 25 | 26 | When devies of multiple types are mixed in a single Group, 27 | this `types` lists each type. 28 | For example, a Ceiling Fan (CF) and a Light (LT) combined would be 29 | ["CF", "LT"] (with the order being aribitrary). 30 | example: 31 | - "MS" 32 | type: array 33 | locations: 34 | readOnly: true 35 | example: 36 | - Kitchen 37 | type: array 38 | description: | 39 | Similar to `types`, if all Devices in the Group are in the same Location, 40 | this field will be an array with a single string. However, when Devices 41 | from multiple Locations are combined in one Group, this field lists 42 | each unique Location in arbitrary order. 43 | actions: 44 | readOnly: true 45 | type: array 46 | example: 47 | - "Open" 48 | - "Close" 49 | - "Preset" 50 | description: | 51 | The list of available Actions on the Group. 52 | This is the intersection of Actions for the Devices in the Group. 53 | In other words, the Group Actions are those Actions which are common 54 | to all Devices in the Group. 55 | state: 56 | readOnly: true 57 | type: object 58 | example: 59 | _: "ad9bcde4" 60 | required: 61 | - name 62 | 63 | GroupList: 64 | type: object 65 | example: 66 | _: "7fc1e84b" 67 | 3b20f300: 68 | _: "9a5e1136" 69 | 4caf6472: 70 | _: "409d124b" 71 | State: 72 | example: 73 | open: 1 74 | -------------------------------------------------------------------------------- /actions/channel-paths.yaml: -------------------------------------------------------------------------------- 1 | ActionPath: 2 | put: 3 | $ref: ../actions/channel-paths.yaml#/Put 4 | parameters: 5 | - in: path 6 | name: action_name 7 | required: true 8 | schema: 9 | type: string 10 | - in: path 11 | name: channel_id 12 | required: true 13 | schema: 14 | type: string 15 | pattern: '^(0|[1-9]|1[0-5])$' 16 | 17 | Put: 18 | requestBody: 19 | content: 20 | application/json: 21 | schema: 22 | type: object 23 | example: 24 | argument: 4 25 | responses: 26 | '200': 27 | description: Action executed 28 | content: 29 | application/json: 30 | schema: 31 | type: object 32 | example: 33 | argument: 4 34 | '400': 35 | $ref: ../common/responses.yaml#/BadRequest 36 | '401': 37 | $ref: ../common/responses.yaml#/Unauthorized 38 | '404': 39 | $ref: ../common/responses.yaml#/NotFound 40 | '500': 41 | $ref: ../common/responses.yaml#/InternalServerError 42 | summary: Execute a Channel Action 43 | description: | 44 | **[v4.24+] [MT-1500 only] Development and testing endpoint** 45 | 46 | `action_name` is the name of the action from the `actions` list in 47 | the response to GET `/channels/{channel_id}`. 48 | 49 | This endpoint executes an action directly on a channel by transmitting 50 | via the configured RF technology/protocol for that channel. 51 | 52 | **Note:** Mate is not intended to act as a bridge. This endpoint is 53 | provided for development and testing purposes only, allowing 54 | verification that channels are properly configured and actions 55 | execute correctly. It is directly analogous to the device and group 56 | action endpoints. 57 | 58 | This endpoint blocks until confirmation that Mate has transmitted 59 | the action. Timeout shall be no more than 7 seconds. 60 | 61 | Available actions depend on the channel's configured technology and 62 | channel type. Common actions include: 63 | - Shade channels: Raise, Lower, Hold, SetPosition, Preset 64 | - Light channels: TurnLightOn, TurnLightOff, SetBrightness 65 | 66 | See the channels endpoint documentation for the full list of available 67 | actions per channel. 68 | tags: 69 | - Channel Actions 70 | security: 71 | - OAuth: ["oauth2"] 72 | -------------------------------------------------------------------------------- /token/paths.yaml: -------------------------------------------------------------------------------- 1 | get: 2 | responses: 3 | '200': 4 | content: 5 | application/json: 6 | schema: 7 | $ref: schemas.yaml#/TokenGet 8 | description: Local token status 9 | '401': 10 | $ref: ../common/responses.yaml#/Unauthorized 11 | summary: Get Local API Token 12 | description: | 13 | Request token for accessing Bond over local network. 14 | 15 | If `locked` is true, reply will contain neither `token` nor `account_code`. 16 | 17 | Typical use case for this endpoint is: 18 | 19 | - request GET, finding that the endpoint is locked 20 | - perform PATCH with `"locked": 0`, the correct `pin`, 21 | and your `account_code` (if you want to take ownership of the Bond) 22 | - request GET again to get `token` 23 | - perform PATCH with `"locked": 1` 24 | 25 | Alternatively, user may perform the proof-of-ownership event 26 | (such as holding down the Power button on a SBB remote for 5 sec), 27 | which will unlock the endpoint. In that case, the API client should 28 | poll GET waiting for unlock. 29 | 30 | Lastly, this endpoint is unlocked for 10 minutes following power cycle. 31 | 32 | Note: The token is not required for /sys/version and /token endpoints. 33 | However, all other endpoints require token to be provided in a BOND-Token 34 | HTTP header. 35 | tags: 36 | - Token 37 | 38 | patch: 39 | requestBody: 40 | content: 41 | application/json: 42 | schema: 43 | $ref: schemas.yaml#/TokenPatch 44 | responses: 45 | '200': 46 | content: 47 | application/json: 48 | schema: 49 | $ref: schemas.yaml#/TokenPatch 50 | description: Token unlocked 51 | '400': 52 | $ref: ../common/responses.yaml#/BadRequest 53 | '401': 54 | $ref: ../common/responses.yaml#/Unauthorized 55 | '500': 56 | $ref: ../common/responses.yaml#/InternalServerError 57 | summary: Add Bond to an Account (or Unlock Token) 58 | description: | 59 | If locked, provide `pin` (located on the product label) to unlock this endpoint. 60 | If `pin` is not provided or incorrect, a 401 will be returned. 61 | 62 | If an `account_code` is provided, saves it to the Bond. When the Bond communicates 63 | with the backend, the Bond will be added to the account associated with 64 | `account_code`. You can find your `account_code` on the user screen in the mobile 65 | app. 66 | 67 | You can also use this endpoint to simply find out your Bond's locked `token` 68 | by providing a `pin` 69 | tags: 70 | - Token 71 | -------------------------------------------------------------------------------- /scenes/schemas.yaml: -------------------------------------------------------------------------------- 1 | Scene: 2 | type: object 3 | properties: 4 | name: 5 | example: Privacy 6 | type: string 7 | actors: 8 | description: | 9 | Array of actions to be executed when the Scene is run. 10 | 11 | This field must contain at least one action during Scene creation. 12 | It may be updated using PATCH. 13 | 14 | This field may be missing for imorted Scenes, 15 | which means that the Scene is opaque (i.e. the Bond Bridge does not know 16 | what the Scene does) and may only be edited on the partner system it was 17 | imported from. See `imported_from` field. 18 | type: array 19 | example: 20 | - {"device": "aabbccdd", "action": "TurnOn"} 21 | - {"group": "11223344", "action": "SetBrightness", "argument": 50} 22 | types: 23 | readOnly: true 24 | description: | 25 | For values, see `type` field of Device schema. 26 | 27 | Automatically set by the Bond Bridge to be the set of types of the 28 | underlying devices. Note that Scene types is always an array, even if it has zero or one element. 29 | In the event that a Scene contains Groups, the types of the underlying devices 30 | are used to determine the Scene types array. 31 | 32 | When devies of multiple types are mixed in a single Scene, 33 | this `types` lists each type. 34 | For example, a Ceiling Fan (CF) and a Light (LT) combined would be 35 | ["CF", "LT"] (with the order being aribitrary). 36 | example: 37 | - "MS" 38 | type: array 39 | locations: 40 | readOnly: true 41 | example: 42 | - Kitchen 43 | type: array 44 | description: | 45 | Similar to `types`, if all Devices in the Scene are in the same Location, 46 | this field will be an array with a single string. However, when Devices 47 | from multiple Locations are combined in one Scene, this field lists 48 | each unique Location in arbitrary order. 49 | imported_from: 50 | description: | 51 | If the Scene was imported from a Managed Technology (that is, a parter control system), 52 | this field contains the ID of the partner system. The corresponding endpoint on the 53 | Bridge for managing this technology is `api/{imported_from}` and the WebGUI is 54 | at `http://{bridge_ip_address}/{imported_from}`. 55 | type: string 56 | example: "powerview" 57 | required: 58 | - name 59 | 60 | SceneList: 61 | type: object 62 | example: 63 | _: "7fc1e84b" 64 | 3b20f300: 65 | _: "9a5e1136" 66 | 4caf6472: 67 | _: "409d124b" 68 | -------------------------------------------------------------------------------- /debug/rfman.yaml: -------------------------------------------------------------------------------- 1 | Schema: 2 | type: object 3 | properties: 4 | log_signals: 5 | example: false 6 | type: boolean 7 | silence_tx: 8 | example: false 9 | type: boolean 10 | 11 | Path: 12 | get: 13 | responses: 14 | '200': 15 | content: 16 | application/json: 17 | schema: 18 | $ref: "#/Schema" 19 | description: RF manager configuration 20 | summary: Get RF Manager configuration 21 | # TODO: this should be shared with the PATCH description, $ref is acting odd though 22 | description: | 23 | (Bond Bridge only) 24 | Intended for use in debugging signal generation. All values false by default, 25 | and changes do not persist past reboot. 26 | 27 | `silence_tx` stops the Bond Bridge 28 | from transmitting anything. It should otherwise behave normally: the LEDs flash, 29 | device state should change, etc. 30 | 31 | `log_signals` causes all signals to be sent to sent to any listeners as they 32 | are generated. They are sent on the topic `debug/rfman/signal`, and could be 33 | monitored by a BPUP client listening on this topic. This is intended as a testing 34 | tool, to verify whether signals are generated as expected. 35 | tags: 36 | - RF Manager 37 | patch: 38 | requestBody: 39 | content: 40 | application/json: 41 | schema: 42 | $ref: "#/Schema" 43 | responses: 44 | '200': 45 | description: RF Manager configured 46 | content: 47 | application/json: 48 | schema: 49 | $ref: "#/Schema" 50 | '400': 51 | description: Error parsing request 52 | summary: Configure RF Manager 53 | description: | 54 | (Bond Bridge only) 55 | Intended for use in debugging signal generation. All values false by default, 56 | and changes do not persist past reboot. 57 | 58 | `silence_tx` stops the Bond Bridge 59 | from transmitting anything. It should otherwise behave normally: the LEDs flash, 60 | device state should change, etc. 61 | 62 | `log_signals` causes all signals to be sent to sent to any listeners as they 63 | are generated. They are sent on the topic `debug/rfman/signal`, and could be 64 | monitored by a BPUP client listening on this topic. This is intended as a testing 65 | tool, to verify whether signals are generated as expected. 66 | tags: 67 | - RF Manager 68 | delete: 69 | responses: 70 | '204': 71 | description: RF Manager settings reset 72 | summary: Reset RF Manager settings 73 | tags: 74 | - RF Manager 75 | -------------------------------------------------------------------------------- /sys/paths.yaml: -------------------------------------------------------------------------------- 1 | PowerPath: 2 | get: 3 | $ref: ../sys/paths.yaml#/PowerGet 4 | PowerGet: 5 | responses: 6 | '200': 7 | description: Power Supply info 8 | content: 9 | application/json: 10 | schema: 11 | $ref: schemas.yaml#/Power 12 | '401': 13 | $ref: ../common/responses.yaml#/Unauthorized 14 | '404': 15 | $ref: ../common/responses.yaml#/NotFound 16 | '500': 17 | $ref: ../common/responses.yaml#/InternalServerError 18 | summary: Get power supply info 19 | description: | 20 | Get information about Power Supply status (which supply is active). 21 | 22 | Sent gratuitously upon change to active supplies. 23 | tags: 24 | - Power 25 | TimePath: 26 | get: 27 | $ref: ../sys/paths.yaml#/TimeGet 28 | patch: 29 | $ref: ../sys/paths.yaml#/TimePatch 30 | delete: 31 | $ref: ../sys/paths.yaml#/TimeDelete 32 | TimeGet: 33 | responses: 34 | '200': 35 | description: Time info 36 | content: 37 | application/json: 38 | schema: 39 | $ref: schemas.yaml#/Time 40 | '401': 41 | $ref: ../common/responses.yaml#/Unauthorized 42 | '404': 43 | $ref: ../common/responses.yaml#/NotFound 44 | '500': 45 | $ref: ../common/responses.yaml#/InternalServerError 46 | summary: Get time info 47 | description: | 48 | Get information about Bond system time, timezone, and grid location. 49 | tags: 50 | - Time 51 | TimeDelete: 52 | responses: 53 | '204': 54 | description: Time info reset 55 | '401': 56 | $ref: ../common/responses.yaml#/Unauthorized 57 | '404': 58 | $ref: ../common/responses.yaml#/NotFound 59 | '500': 60 | $ref: ../common/responses.yaml#/InternalServerError 61 | summary: Reset time info to defaults 62 | description: | 63 | Forget time, timezone, and grid location. 64 | 65 | As a consequence, all skeds will be immediately disabled (enabled=false). 66 | tags: 67 | - Time 68 | TimePatch: 69 | requestBody: 70 | content: 71 | application/json: 72 | schema: 73 | $ref: schemas.yaml#/Time 74 | responses: 75 | '200': 76 | description: Time info updated 77 | '400': 78 | $ref: ../common/responses.yaml#/BadRequest 79 | '401': 80 | $ref: ../common/responses.yaml#/Unauthorized 81 | '404': 82 | $ref: ../common/responses.yaml#/NotFound 83 | '500': 84 | $ref: ../common/responses.yaml#/InternalServerError 85 | summary: Modify time info 86 | description: | 87 | Set timezone, grid location, and/or time. 88 | 89 | If `tz` is set to `null`, all skeds based on a local time (mark=midnight) will 90 | be disabled. 91 | 92 | Likewise, if `grid` is set to `null`, all skeds based on solar marks will be 93 | disabled. 94 | tags: 95 | - Time 96 | -------------------------------------------------------------------------------- /api/bhk.yaml: -------------------------------------------------------------------------------- 1 | Schema: 2 | type: object 3 | properties: 4 | enabled: 5 | example: false 6 | type: boolean 7 | description: | 8 | - `false`: HomeKit logic and operations will not be executed. All settings remains in device database. (default) 9 | - `true`: HomeKit logic and operations will run. 10 | paired: 11 | example: false 12 | type: boolean 13 | readOnly: true 14 | description: | 15 | When enabled is false, paired will always be false. 16 | When enabled is true, paired means: 17 | - `false`: Bond is not paired to an account and is discoverable by the HomeKit Protocol. (default) 18 | - `true`: Bond is paired and is not discoverable. 19 | setup_code: 20 | example: "12341234" 21 | type: string 22 | readOnly: true 23 | description: | 24 | The HomeKit Setup Code is your Bond PIN two times. 25 | For example, if your Bond PIN is "1234", your HomeKit Setup Code is "12341234". 26 | 27 | Path: 28 | get: 29 | responses: 30 | '200': 31 | description: Bond HomeKit configuration. 32 | content: 33 | application/json: 34 | schema: 35 | $ref: ./bhk.yaml#/Schema 36 | '401': 37 | $ref: ../common/responses.yaml#/Unauthorized 38 | '500': 39 | $ref: ../common/responses.yaml#/InternalServerError 40 | security: 41 | - BasicAuth: [] 42 | summary: Get Bond HomeKit configuration. 43 | tags: 44 | - HomeKit 45 | patch: 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: ./bhk.yaml#/Schema 51 | responses: 52 | '200': 53 | description: Bond HomeKit enabled info updated. 54 | '400': 55 | $ref: ../common/responses.yaml#/BadRequest 56 | '401': 57 | $ref: ../common/responses.yaml#/Unauthorized 58 | '500': 59 | $ref: ../common/responses.yaml#/InternalServerError 60 | security: 61 | - BasicAuth: [] 62 | summary: Enable or disable the Bond HomeKit integration. 63 | tags: 64 | - HomeKit 65 | delete: 66 | responses: 67 | '204': 68 | description: | 69 | Bond HomeKit info reseted. 70 | That means the Bond will delete all info, unpairing if paired and set enabled to default (0). 71 | If you have not removed the Bond from your account on Home app, the Bond and its devices 72 | will show as not responding. You can remove from the Home app later as usual. 73 | '401': 74 | $ref: ../common/responses.yaml#/Unauthorized 75 | '500': 76 | $ref: ../common/responses.yaml#/InternalServerError 77 | security: 78 | - BasicAuth: [] 79 | summary: Reset Bond HomeKit configuration, unpairing if paired. 80 | tags: 81 | - HomeKit 82 | -------------------------------------------------------------------------------- /keys/paths.yaml: -------------------------------------------------------------------------------- 1 | KeysPath: 2 | get: 3 | $ref: paths.yaml#/Get 4 | patch: 5 | $ref: paths.yaml#/Patch 6 | 7 | Get: 8 | responses: 9 | '200': 10 | content: 11 | application/json: 12 | schema: 13 | $ref: schemas.yaml#/KeyConfiguration 14 | description: Key configuration returned 15 | '401': 16 | $ref: ../common/responses.yaml#/Unauthorized 17 | '404': 18 | $ref: ../common/responses.yaml#/NotFound 19 | '500': 20 | $ref: ../common/responses.yaml#/InternalServerError 21 | summary: Get Quick Action Button configuration 22 | description: | 23 | Get the current configuration for all three Quick Action Buttons (K1, K2, K3) 24 | on Mate Pro (MT-1500). 25 | 26 | Each button can be configured to operate in one of three modes: 27 | - cta: Display a call-to-action message prompting users to open the Bond Home app 28 | - goto: Jump to a specified channel 29 | - keystream: Execute programmable actions via key_links 30 | 31 | Default configuration: 32 | - K1: cta mode 33 | - K2: cta mode 34 | - K3: cta mode 35 | tags: 36 | - Quick Action Keys 37 | 38 | Patch: 39 | requestBody: 40 | content: 41 | application/json: 42 | schema: 43 | $ref: schemas.yaml#/KeyConfiguration 44 | responses: 45 | '200': 46 | description: Key configuration modified 47 | '400': 48 | $ref: ../common/responses.yaml#/BadRequest 49 | '401': 50 | $ref: ../common/responses.yaml#/Unauthorized 51 | '404': 52 | $ref: ../common/responses.yaml#/NotFound 53 | '500': 54 | $ref: ../common/responses.yaml#/InternalServerError 55 | summary: Modify Quick Action Button configuration 56 | description: | 57 | Modify the configuration for Quick Action Buttons on Mate Pro (MT-1500). 58 | 59 | You can update one or more buttons in a single request. Only include the 60 | buttons you want to modify. 61 | 62 | Mode switching behavior: 63 | - Switching from cta mode: Once a button is changed from cta to goto or keystream 64 | mode, it cannot be switched back to cta mode. 65 | 66 | - Switching from keystream to goto mode: Previously configured key_links 67 | are hidden in the app but preserved. They can be viewed again by switching 68 | back to keystream mode. 69 | 70 | - Switching from goto to keystream mode: The button will resume transmitting 71 | BondSync signals and executing any previously configured key_links. 72 | 73 | Physical programming: 74 | When a button is in goto mode, users can set the target channel by holding 75 | the button for 2 seconds while on the desired channel. This updates the 76 | `channel` field in the configuration. 77 | 78 | Note: When mode=goto, the `channel` field is required. When mode=keystream or mode=cta, 79 | the `channel` field is ignored. 80 | tags: 81 | - Quick Action Keys 82 | -------------------------------------------------------------------------------- /actions/paths.yaml: -------------------------------------------------------------------------------- 1 | ActionPath: 2 | put: 3 | $ref: ../actions/paths.yaml#/Put 4 | parameters: 5 | - in: path 6 | name: action_name 7 | required: true 8 | schema: 9 | type: string 10 | - in: path 11 | name: device_id 12 | required: true 13 | schema: 14 | type: number 15 | 16 | Put: 17 | requestBody: 18 | content: 19 | application/json: 20 | schema: 21 | $ref: schemas.yaml#/Args 22 | type: object 23 | properties: 24 | _lock_priority: 25 | type: number 26 | optional: true 27 | description: | 28 | The priority number desired for the lock, from 1 to 999. 29 | If not specified, defaults to the default priority of 100. 30 | _lock_expiration: 31 | type: number 32 | description: | 33 | The expiration time desired for the lock, in miliseconds. Use 0 for 34 | acquiring the lock with immediate expiration. 35 | example: 36 | argument: 4 37 | _lock_priority: 50 38 | _lock_expiration: 5000 39 | responses: 40 | '200': 41 | description: Action executed [since v2.12.4] 42 | content: 43 | application/json: 44 | schema: 45 | type: object 46 | example: 47 | argument: 4 48 | _lock_priority: 50 49 | _lock_expiration: 4900 50 | '204': 51 | description: Action executed [prior to v2.12.4] 52 | '400': 53 | $ref: ../common/responses.yaml#/BadRequest 54 | '401': 55 | $ref: ../common/responses.yaml#/Unauthorized 56 | '423': 57 | $ref: ../common/responses.yaml#/Locked 58 | '500': 59 | $ref: ../common/responses.yaml#/InternalServerError 60 | summary: Execute a device action 61 | description: | 62 | `action_name` is the name of the action from the `actions` list in 63 | the response to GET `/devices/{device_id}`. 64 | 65 | This endpoint blocks until confirmation that the Bond has executed 66 | the action. Timeout shall be no more than 7 seconds. 67 | 68 | To check the resulting state, the client may query 69 | `/devices/{device_id}/state`. 70 | 71 | See the Features section to learn what the various actions mean, 72 | and what argument is expected, if any. 73 | For example, the action `SetSpeed` takes an integer parameter 74 | which is the desired speed number. 75 | 76 | When performing an action, the device can be locked with a priority and 77 | expiration time, using the optional fields `_lock_priority` and `_lock_expiration`. 78 | 79 | Any other action that has a lower priority (higher priority number) will not 80 | be executed if the `_lock_expiration` is not expired. Actions with higher 81 | priority (lower priority number) will be executed and will acquire the lock. 82 | 83 | If `_lock_priority` is not specified, the default value `100` is assumed. 84 | tags: 85 | - Device Actions 86 | security: 87 | - OAuth: ["oauth2"] 88 | -------------------------------------------------------------------------------- /keys/schemas.yaml: -------------------------------------------------------------------------------- 1 | KeyConfiguration: 2 | type: object 3 | description: | 4 | Configuration for the three Quick Action Buttons (K1, K2, K3) on Mate Pro (MT-1500). 5 | 6 | Each button can be independently configured to operate in one of three modes: 7 | - cta: Display a call-to-action message prompting users to open the Bond Home app 8 | - goto: Jump to a specified channel when pressed 9 | - keystream: Execute programmable actions configured in key_links (BondSync or built-in scenes) 10 | 11 | Default configuration: 12 | - K1: cta mode 13 | - K2: cta mode 14 | - K3: cta mode 15 | 16 | Note: Once a button is configured to goto or keystream mode, it cannot be set back to cta mode. 17 | properties: 18 | "1": 19 | $ref: '#/KeyConfig' 20 | "2": 21 | $ref: '#/KeyConfig' 22 | "3": 23 | $ref: '#/KeyConfig' 24 | example: 25 | "1": 26 | mode: cta 27 | "2": 28 | mode: keystream 29 | "3": 30 | mode: goto 31 | channel: 15 32 | 33 | KeyConfig: 34 | type: object 35 | properties: 36 | mode: 37 | type: string 38 | enum: [cta, goto, keystream] 39 | description: | 40 | Button operation mode: 41 | 42 | - `cta`: Call To Action mode (default). Pressing the button displays a 43 | message on the LED matrix prompting users to open the Bond Home app. 44 | This mode encourages app discovery for users who may not be aware of 45 | scheduling, channel visibility, and programmable action features. 46 | Once changed to goto or keystream mode, a button cannot be set back to cta. 47 | 48 | - `goto`: Pressing the button jumps to the specified channel. 49 | The target channel can be set via the `channel` field or by physically 50 | holding the button for 2 seconds while on the desired channel. 51 | 52 | - `keystream`: The button transmits BondSync signals and/or executes 53 | programmable actions configured in the sidekick's `key_links` field. 54 | This mode enables integration with Bond Bridge devices, groups, scenes, 55 | and built-in scenes (actions on Mate channels). 56 | 57 | When switching from keystream to goto mode, previously configured key_links 58 | are hidden in the app but preserved in the system. Switching back to keystream 59 | mode will restore the hidden key_links in the app UI. 60 | 61 | Default mode for all buttons is `cta`. 62 | channel: 63 | type: integer 64 | description: | 65 | Target channel for goto mode (required when mode=goto). 66 | 67 | Valid values: 68 | - 0-15: Jump to the specified channel 69 | - -1: Jump to whichever channel is currently selected (dynamic goto) 70 | 71 | To set the target channel physically on the device: 72 | Hold the Quick Action Button for 2 seconds while on the desired channel. 73 | 74 | Not used when mode=cta or mode=keystream. 75 | example: 5 76 | required: 77 | - mode 78 | example: 79 | mode: goto 80 | channel: 5 81 | -------------------------------------------------------------------------------- /token/schemas.yaml: -------------------------------------------------------------------------------- 1 | TokenGet: 2 | properties: 3 | locked: 4 | example: 0 5 | type: integer 6 | description: | 7 | If 1, means that client must provide pin to unlock. 8 | 9 | Alternatively, the Bond user may perform an out-of-band proof-of-ownership event 10 | on the physical Bond unit to cause this field to become 0. 11 | token: 12 | example: "8f514567acaf9869" 13 | type: string 14 | description: | 15 | Token for controlling this Bond over local network. 16 | 17 | Required to be provided as an HTTP header for all local communications. 18 | 19 | This is a hex representation of a random uint64, 20 | which is regenerated on Bond factory reset. 21 | 22 | Only provided if locked is 0. 23 | account_code: 24 | example: "1234567890" 25 | type: string 26 | description: | 27 | Account code previously set by PATCH. 28 | 29 | Only provided if locked is 0. 30 | nonce: 31 | example: "876a2b14c55b3e5a" 32 | type: string 33 | description: | 34 | Random 64-bit hex string generated whenever client sets account_code, 35 | even if accound_code is unmodified. 36 | pin_attempts_left: 37 | example: 9 38 | type: integer 39 | description: | 40 | Number of times which the PIN may be guessed. 41 | 42 | Once `pin_attempts_left` reaches 0, user must either use an 43 | out-of-band proof-of-ownership event, or reboot/power-cycle the Bond. 44 | disable: 45 | example: false 46 | type: boolean 47 | description: | 48 | If disabled, HTTP and other local APIs will not require token to function. 49 | Only disable on trusted networks, and only when using fixed IP addresses 50 | to avoid controlling the wrong Bond. Defaults to false, i.e., token required by default. 51 | Available as of firmware v2.10.2. 52 | TokenPatch: 53 | properties: 54 | locked: 55 | example: 0 56 | type: integer 57 | description: | 58 | If 1, means that the client wants to immediately re-lock this endpoint. 59 | 60 | If 0, means that the client wants to unlock the endpoint. 61 | account_code: 62 | example: "1234567890" 63 | type: string 64 | description: | 65 | 10-digit account code, used to specify which account to associate the Bond with. 66 | 67 | (Absolute maximum for this field is 16 alpha-numeric characters) 68 | 69 | This does NOT include any checksum digits which may be added when displayed 70 | for the customer in the app, and required by the Bond WebGUI to eliminate typo issues. 71 | pin: 72 | example: "1234" 73 | type: string 74 | description: | 75 | Pin number, if required, as part of unlocking procedure. 76 | disable: 77 | example: false 78 | type: boolean 79 | description: | 80 | If disabled, HTTP and other local APIs will not require token to function. 81 | Only disable on trusted networks, and only when using fixed IP addresses 82 | to avoid controlling the wrong Bond. Defaults to false, i.e., token required by default. 83 | -------------------------------------------------------------------------------- /bonds/paths.yaml: -------------------------------------------------------------------------------- 1 | GetList: 2 | parameters: 3 | - example: 1.1.2 4 | in: path 5 | name: firmware_versioin 6 | schema: 7 | type: string 8 | responses: 9 | 200: 10 | content: 11 | application/json: 12 | schema: 13 | type: array 14 | items: 15 | $ref: schemas.yaml#/Bond 16 | example: 17 | $ref: examples.yaml#/list 18 | description: List bonds 19 | 401: 20 | $ref: ../common/responses.yaml#/Unauthorized 21 | 500: 22 | $ref: ../common/responses.yaml#/InternalServerError 23 | security: 24 | - OAuth: ["oauth2"] 25 | summary: List bonds 26 | tags: 27 | - Bonds 28 | Post: 29 | requestBody: 30 | content: 31 | application/json: 32 | schema: 33 | $ref: schemas.yaml#/Bond 34 | responses: 35 | '201': 36 | content: 37 | application/json: 38 | schema: 39 | $ref: schemas.yaml#/Bond 40 | description: Bond was successfully created 41 | '400': 42 | $ref: ../common/responses.yaml#/BadRequest 43 | '401': 44 | $ref: ../common/responses.yaml#/Unauthorized 45 | '409': 46 | $ref: ../common/responses.yaml#/Conflict 47 | '500': 48 | $ref: ../common/responses.yaml#/InternalServerError 49 | summary: Create new bond 50 | tags: 51 | - Bonds 52 | Get: 53 | responses: 54 | '200': 55 | content: 56 | application/json: 57 | schema: 58 | $ref: schemas.yaml#/Bond 59 | description: Get specific bond 60 | '401': 61 | $ref: ../common/responses.yaml#/Unauthorized 62 | '404': 63 | $ref: ../common/responses.yaml#/NotFound 64 | '500': 65 | $ref: ../common/responses.yaml#/InternalServerError 66 | security: 67 | - OAuth: ["oauth2"] 68 | summary: Get specific bond 69 | tags: 70 | - Bonds 71 | Patch: 72 | requestBody: 73 | content: 74 | application/json: 75 | schema: 76 | properties: 77 | firmware_version: 78 | example: 1.1.2 79 | type: string 80 | location: 81 | example: Room 82 | type: string 83 | type: object 84 | responses: 85 | '200': 86 | content: 87 | application/json: 88 | schema: 89 | $ref: schemas.yaml#/Bond 90 | description: Change specific bond field 91 | '401': 92 | $ref: ../common/responses.yaml#/Unauthorized 93 | '404': 94 | $ref: ../common/responses.yaml#/NotFound 95 | '500': 96 | $ref: ../common/responses.yaml#/InternalServerError 97 | security: 98 | - OAuth: ["oauth2"] 99 | summary: Change specific bond field 100 | tags: 101 | - Bonds 102 | Delete: 103 | responses: 104 | '204': 105 | description: Remove specific bond 106 | '401': 107 | $ref: ../common/responses.yaml#/Unauthorized 108 | '404': 109 | $ref: ../common/responses.yaml#/NotFound 110 | '500': 111 | $ref: ../common/responses.yaml#/InternalServerError 112 | security: 113 | - OAuth: ["oauth2"] 114 | summary: Remove specific bond 115 | tags: 116 | - Bonds 117 | -------------------------------------------------------------------------------- /vrc/paths.yaml: -------------------------------------------------------------------------------- 1 | VrcPath: 2 | get: 3 | $ref: ../vrc/paths.yaml#/Get 4 | patch: 5 | $ref: ../vrc/paths.yaml#/Patch 6 | parameters: 7 | - in: path 8 | name: device_id 9 | required: true 10 | schema: 11 | type: number 12 | description: testing 123 13 | 14 | VrcKeystreamPath: 15 | put: 16 | $ref: ../vrc/paths.yaml#/PutKey 17 | parameters: 18 | - in: path 19 | name: device_id 20 | required: true 21 | schema: 22 | type: number 23 | description: testing 123 24 | 25 | Get: 26 | description: | 27 | Check enabled status of virtual remote for specified device. 28 | responses: 29 | '200': 30 | content: 31 | application/json: 32 | schema: 33 | $ref: schemas.yaml#/Vrc 34 | description: Get Vrc info 35 | '401': 36 | $ref: ../common/responses.yaml#/Unauthorized 37 | '404': 38 | $ref: ../common/responses.yaml#/NotFound 39 | '500': 40 | $ref: ../common/responses.yaml#/InternalServerError 41 | security: 42 | - OAuth: ["oauth2"] 43 | summary: Get Vrc info 44 | tags: 45 | - Virtual Remote Control 46 | 47 | Patch: 48 | requestBody: 49 | required: true 50 | content: 51 | application/json: 52 | schema: 53 | $ref: schemas.yaml#/Vrc 54 | responses: 55 | '200': 56 | content: 57 | application/json: 58 | schema: 59 | $ref: schemas.yaml#/Vrc 60 | description: Enable or disable Vrc 61 | '401': 62 | $ref: ../common/responses.yaml#/Unauthorized 63 | '404': 64 | $ref: ../common/responses.yaml#/NotFound 65 | '500': 66 | $ref: ../common/responses.yaml#/InternalServerError 67 | security: 68 | - BasicAuth: [] 69 | summary: Enable or disable Vrc 70 | tags: 71 | - Virtual Remote Control 72 | 73 | PutKey: 74 | requestBody: 75 | required: true 76 | content: 77 | application/json: 78 | schema: 79 | $ref: schemas.yaml#/VrcKeystream 80 | responses: 81 | '200': 82 | content: 83 | application/json: 84 | schema: 85 | $ref: schemas.yaml#/VrcKeystream 86 | description: Send a virtual key event 87 | '401': 88 | $ref: ../common/responses.yaml#/Unauthorized 89 | '404': 90 | $ref: ../common/responses.yaml#/NotFound 91 | '500': 92 | $ref: ../common/responses.yaml#/InternalServerError 93 | security: 94 | - BasicAuth: [] 95 | summary: Send a virtual key event 96 | description: | 97 | Example: 98 | 99 | User Behavior: 100 | - user taps 1 101 | - then holds 1 102 | - adds 2 103 | - taps 3 104 | - adds 3 105 | - then releases 1 and 2 at same time 106 | - then releases 3 107 | 108 | Events sent: 109 | 110 | {event: TAP, key: 1} 111 | {event: HOLD_START, key: 1} 112 | {event: HOLD, key: 1, hold_ms:301} 113 | {event: HOLD, key: 1, hold_ms:604} 114 | {event: HOLD_START, key: 2} 115 | {event: HOLD, key: [1, 2], hold_ms:302} 116 | {event: TAP, key: 3} 117 | {event: HOLD, key: [1, 2], hold_ms:602} 118 | {event: HOLD_START, key: 3} 119 | {event: HOLD_END key: [1, 2], hold_ms: 20} 120 | {event: HOLD, key: 3, hold_ms:320} 121 | {event: HOLD_END key: 3, hold_ms: 400} 122 | 123 | tags: 124 | - Virtual Remote Control 125 | -------------------------------------------------------------------------------- /skeds/schemas.yaml: -------------------------------------------------------------------------------- 1 | Sked: 2 | type: object 3 | properties: 4 | enabled: 5 | example: True 6 | type: boolean 7 | description: | 8 | If false, schedule will never execute, but will remain in Bond database. 9 | 10 | Oneshot schedules (with `days_of_week` all False) automatically 11 | disable after executing once. 12 | 13 | Defaults to true on PUT and POST. 14 | action: 15 | example: SetBrightness 16 | type: string 17 | description: | 18 | Action which will be run on actor when schedule executes. 19 | Required for Device, Group, and Channel actors. Must not be set for Scene actors. 20 | If action requires an argument, `argument` field is required. 21 | 22 | For Channel schedules (MT-1500): 23 | - Common shade actions: Raise, Lower, Stop, SetPosition, Preset 24 | - Light actions: TurnLightOn, TurnLightOff, SetBrightness 25 | - Note: Open/Close are not available for channel schedules 26 | argument: 27 | example: 80 28 | description: | 29 | Argument to action, if needed. 30 | seconds: 31 | example: -3600 32 | type: integer 33 | description: | 34 | Time at which schedule should execute, relative to `mark`, 35 | in seconds. Negative numbers indicate "before" the mark, 36 | positive numbers indicate "after" the mark. 37 | days_of_week: 38 | example: [false, true, true, true, true, true, false] 39 | type: array 40 | items: 41 | type: boolean 42 | description: | 43 | Days of week on which the schedule should execute. 44 | 45 | First element is for Sunday, last element is for Saturday. 46 | 47 | The example value is for a schedules that executes only on weekdays. 48 | 49 | Special case: if array is all `false`, the sked will run exactly once 50 | and will then disable itself (enabled=false). This is rendered on UIs as 51 | a "Run Once" option. 52 | 53 | Default: run every day, that is, array of 7 trues 54 | mark: 55 | example: sunset 56 | type: string 57 | description: | 58 | Event which serves as the benchmark for the daily relative time. 59 | Options are: 60 | - `midnight`: `seconds` is the time in seconds 61 | since midnight in the timezone specified by the sys/time endpoint. 62 | 63 | - `sunrise`: `seconds` is seconds before or after local sunrise, 64 | as calculated using the Grid Locator (see sys/time endpoint). 65 | 66 | - `sunset`: like sunrise but when the sun goes down! 67 | 68 | - `dawn`: `seconds` is seconds before or after local civil dawn: 69 | that is, when it gets light outside before sunrise. 70 | This is when sun is 6 degrees below the horizon. 71 | 72 | - `dusk`: like dawn, but for civil dusk: when it actually gets dark 73 | some time after sunset, when the sun has descending 6 degrees below the horizon. 74 | 75 | **For our beloved customers near or within the Arctic Circle:** please note that 76 | there will be periods of days around the solstices that 77 | schedules based on the solar marks will not execute. 78 | required: 79 | - action 80 | - seconds 81 | - mark 82 | - days_of_week 83 | 84 | SkedList: 85 | type: object 86 | example: 87 | _: "7fc1e84b" 88 | 3b20f300: 89 | _: "9a5e1136" 90 | 4ad874d2: 91 | _: "84819a9f" 92 | a94328bc: 93 | _: "23141efa" 94 | d87d6ef2: 95 | _: "2425a8bc" 96 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | test: 4 | docker: 5 | - image: python:3.6-alpine 6 | steps: 7 | - checkout 8 | - run: 9 | name: Install openapi_spec_validator 10 | command: pip install openapi-spec-validator 11 | - run: 12 | name: Validate local docs 13 | command: python -m openapi_spec_validator local.yaml 14 | build: 15 | docker: 16 | - image: cimg/node:21.1 17 | steps: 18 | - checkout 19 | - run: 20 | name: Install redoc 21 | command: npm install redoc && sudo npm install -g redoc-cli 22 | - run: 23 | name: Create bundle html file for local api 24 | command: redoc-cli bundle local.yaml -o=./local.html 25 | - save_cache: 26 | key: build-{{ .Revision }} 27 | paths: 28 | - local.html 29 | deploy: 30 | docker: 31 | - image: python:3.7-alpine 32 | steps: 33 | - checkout 34 | - restore_cache: 35 | key: build-{{ .Revision }} 36 | - run: 37 | name: Install awscli 38 | command: python3 -m pip install awscli 39 | - run: 40 | name: Deploy to AWS 41 | command: | 42 | aws s3 cp --acl "public-read" /home/circleci/project/local.html s3://bond-api-docs/$(echo $CIRCLE_BRANCH | sed -e "s/\//-/g")-local.html 43 | - run: 44 | name: Comment on PR with S3 link 45 | command: | 46 | apk add --no-cache curl jq 47 | PR_RESPONSE=$(curl -s -H "Authorization: token $GH_TOKEN" "https://api.github.com/repos/bondhome/api-v2/pulls?head=bondhome:$CIRCLE_BRANCH") 48 | echo "GitHub API Response: $PR_RESPONSE" 49 | RESPONSE_TYPE=$(echo "$PR_RESPONSE" | jq -r 'type') 50 | if [ "$RESPONSE_TYPE" = "array" ]; then 51 | PR_COUNT=$(echo "$PR_RESPONSE" | jq '. | length') 52 | if [ "$PR_COUNT" -gt 0 ]; then 53 | PR_NUMBER=$(echo "$PR_RESPONSE" | jq '.[0].number') 54 | S3_URL="https://bond-api-docs.s3.amazonaws.com/$(echo $CIRCLE_BRANCH | sed -e "s/\//-/g")-local.html" 55 | COMMENT_PAYLOAD=$(printf '{ "body": "The rendered doc is at: %s" }' "$S3_URL") 56 | curl -X POST -H "Authorization: token $GH_TOKEN" -H "Content-Type: application/json" -d "$COMMENT_PAYLOAD" "https://api.github.com/repos/bondhome/api-v2/issues/$PR_NUMBER/comments" 57 | else 58 | echo "No PR found for branch $CIRCLE_BRANCH, skipping comment" 59 | fi 60 | else 61 | echo "GitHub API returned non-array response (type: $RESPONSE_TYPE)" 62 | fi 63 | deploy_master: 64 | docker: 65 | - image: python:3.7-alpine 66 | steps: 67 | - checkout 68 | - restore_cache: 69 | key: build-{{ .Revision }} 70 | - run: 71 | name: Install awscli 72 | command: python3 -m pip install awscli 73 | - run: 74 | name: Deploy to AWS (master) 75 | command: | 76 | aws s3 cp --acl "public-read" /home/circleci/project/local.html s3://docs-local.appbond.com/index.html 77 | workflows: 78 | version: 2 79 | build-test-and-deploy: 80 | jobs: 81 | - test 82 | - build 83 | - deploy: 84 | context: 85 | - aws 86 | requires: 87 | - build 88 | - deploy_master: 89 | context: 90 | - aws 91 | requires: 92 | - build 93 | - test 94 | filters: 95 | branches: 96 | only: 97 | - master 98 | -------------------------------------------------------------------------------- /channels/paths.yaml: -------------------------------------------------------------------------------- 1 | ChannelsPath: 2 | get: 3 | $ref: paths.yaml#/GetList 4 | 5 | ChannelPath: 6 | parameters: 7 | - in: path 8 | name: channel_id 9 | required: true 10 | schema: 11 | type: string 12 | pattern: '^(0|[1-9]|1[0-5])$' 13 | description: | 14 | Channel ID: "0" for All channel, or "1" through "15" for individual channels. 15 | get: 16 | $ref: paths.yaml#/Get 17 | patch: 18 | $ref: paths.yaml#/Patch 19 | 20 | GetList: 21 | description: | 22 | Returns a list of all channels. 23 | 24 | Applies to Mate Pro (MT-1500) and Sidekick Blue (SKS-500-B). 25 | 26 | Mate Pro supports 16 channels: channel 0 (All) and 15 individual channels (1-15). 27 | 28 | Each channel can be configured with a different technology (RF protocol). 29 | Channel 0 (All) is a special channel that broadcasts to all paired motors. 30 | The hash tree structure indicates when channel metadata has changed. 31 | responses: 32 | '200': 33 | content: 34 | application/json: 35 | schema: 36 | $ref: schemas.yaml#/ChannelList 37 | description: Channel list with hashes 38 | '401': 39 | $ref: ../common/responses.yaml#/Unauthorized 40 | '404': 41 | $ref: ../common/responses.yaml#/NotFound 42 | '500': 43 | $ref: ../common/responses.yaml#/InternalServerError 44 | summary: Get list of channels 45 | tags: 46 | - Channels 47 | 48 | Get: 49 | responses: 50 | '200': 51 | content: 52 | application/json: 53 | schema: 54 | $ref: schemas.yaml#/Channel 55 | description: Channel object returned 56 | '401': 57 | $ref: ../common/responses.yaml#/Unauthorized 58 | '404': 59 | $ref: ../common/responses.yaml#/NotFound 60 | '500': 61 | $ref: ../common/responses.yaml#/InternalServerError 62 | summary: Get specific channel 63 | description: | 64 | Get information about a specific channel. 65 | 66 | Applies to Mate Pro (MT-1500) and Sidekick Blue (SKS-500-B). 67 | 68 | Channel 0 is the "All" channel that broadcasts to all paired motors. 69 | Channel 0 only supports name, label, and enabled fields. 70 | 71 | Channels 1-15 are for controlling specific motors or groups of motors. 72 | Each channel can be independently configured with: 73 | - A custom name and label (displayed on device's LED matrix) 74 | - A technology/protocol (R-number identifier) 75 | - Technology-specific parameters (addresses, frequencies, etc.) 76 | - Channel type (auto-inferred from technology) 77 | - Available actions (for schedules and built-in scenes) 78 | - Visibility state (enabled/disabled) 79 | tags: 80 | - Channels 81 | 82 | Patch: 83 | requestBody: 84 | content: 85 | application/json: 86 | schema: 87 | $ref: schemas.yaml#/Channel 88 | responses: 89 | '200': 90 | description: Channel modified 91 | '400': 92 | $ref: ../common/responses.yaml#/BadRequest 93 | '401': 94 | $ref: ../common/responses.yaml#/Unauthorized 95 | '404': 96 | $ref: ../common/responses.yaml#/NotFound 97 | '500': 98 | $ref: ../common/responses.yaml#/InternalServerError 99 | summary: Modify channel metadata 100 | description: | 101 | Modifies metadata of a channel, such as name, label, technology assignment, 102 | and visibility state. 103 | 104 | Applies to Mate Pro (MT-1500) and Sidekick Blue (SKS-500-B). 105 | 106 | For channel 0 (All), only name, label, and enabled fields can be modified. 107 | 108 | For channels 1-15, changing the technology template may affect available 109 | pairing procedures, required properties, compatible motors and devices, 110 | channel type, and available actions. 111 | tags: 112 | - Channels 113 | -------------------------------------------------------------------------------- /users/paths.yaml: -------------------------------------------------------------------------------- 1 | Delete: 2 | responses: 3 | '204': 4 | description: Remove specific user 5 | '401': 6 | $ref: ../common/responses.yaml#/Unauthorized 7 | '404': 8 | $ref: ../common/responses.yaml#/NotFound 9 | '500': 10 | $ref: ../common/responses.yaml#/InternalServerError 11 | security: 12 | - BasicAuth: [] 13 | summary: Remove specific user 14 | tags: 15 | - Users 16 | Get: 17 | responses: 18 | '200': 19 | content: 20 | application/json: 21 | schema: 22 | $ref: schemas.yaml#/User 23 | description: Get specific user 24 | '401': 25 | $ref: ../common/responses.yaml#/Unauthorized 26 | '404': 27 | $ref: ../common/responses.yaml#/NotFound 28 | '500': 29 | $ref: ../common/responses.yaml#/InternalServerError 30 | security: 31 | - BasicAuth: [] 32 | summary: Get specific user 33 | tags: 34 | - Users 35 | GetList: 36 | parameters: 37 | - example: A 38 | in: path 39 | name: feature_group 40 | schema: 41 | type: string 42 | responses: 43 | '200': 44 | content: 45 | application/json: 46 | schema: 47 | $ref: schemas.yaml#/UserCollection 48 | description: List active users 49 | headers: 50 | $ref: ../common/headers.yaml#/PaginationHeader 51 | '401': 52 | $ref: ../common/responses.yaml#/Unauthorized 53 | '500': 54 | $ref: ../common/responses.yaml#/InternalServerError 55 | security: 56 | - BasicAuth: [] 57 | summary: List active users 58 | tags: 59 | - Users 60 | Patch: 61 | requestBody: 62 | content: 63 | application/json: 64 | schema: 65 | properties: 66 | feature_group: 67 | default: C 68 | example: A 69 | type: string 70 | password: 71 | example: secretpass 72 | format: password 73 | type: string 74 | writeOnly: true 75 | type: object 76 | responses: 77 | '200': 78 | content: 79 | application/json: 80 | schema: 81 | $ref: schemas.yaml#/User 82 | description: Change specific user field 83 | '401': 84 | $ref: ../common/responses.yaml#/Unauthorized 85 | '404': 86 | $ref: ../common/responses.yaml#/NotFound 87 | '500': 88 | $ref: ../common/responses.yaml#/InternalServerError 89 | security: 90 | - BasicAuth: [] 91 | summary: Change specific user field 92 | tags: 93 | - Users 94 | Post: 95 | requestBody: 96 | content: 97 | application/json: 98 | schema: 99 | $ref: schemas.yaml#/User 100 | responses: 101 | '201': 102 | content: 103 | application/json: 104 | schema: 105 | $ref: schemas.yaml#/User 106 | description: User was successfully created 107 | '400': 108 | $ref: ../common/responses.yaml#/BadRequest 109 | '401': 110 | $ref: ../common/responses.yaml#/Unauthorized 111 | '409': 112 | $ref: ../common/responses.yaml#/Conflict 113 | '500': 114 | $ref: ../common/responses.yaml#/InternalServerError 115 | summary: Create new user 116 | tags: 117 | - Users 118 | GetAuth: 119 | parameters: 120 | - name: response_type 121 | example: code 122 | in: path 123 | schema: 124 | type: string 125 | - name: client_id 126 | example: 542a7dc16ae348c38ade1be593a65097 127 | in: path 128 | schema: 129 | type: string 130 | - name: redirect_uri 131 | example: https://api.bondapp.io/redirect 132 | in: path 133 | schema: 134 | type: string 135 | - name: state 136 | example: 6a1fd11c91db4d9489cb693f57914b4b 137 | in: path 138 | schema: 139 | type: string 140 | -------------------------------------------------------------------------------- /sys/indicate.yaml: -------------------------------------------------------------------------------- 1 | IndicatePath: 2 | get: 3 | $ref: '#/IndicateGet' 4 | patch: 5 | $ref: '#/IndicatePatch' 6 | 7 | IndicateGet: 8 | responses: 9 | '200': 10 | description: Indicate status 11 | content: 12 | application/json: 13 | schema: 14 | $ref: '#/IndicateSchema' 15 | '401': 16 | $ref: ../common/responses.yaml#/Unauthorized 17 | '404': 18 | $ref: ../common/responses.yaml#/NotFound 19 | '500': 20 | $ref: ../common/responses.yaml#/InternalServerError 21 | summary: Get indication status 22 | description: | 23 | [Mate Pro (MT-1500) only] [v4.26+] 24 | 25 | Get the current status of visual indication animations. 26 | 27 | Returns the remaining duration (in seconds) for any active animation, 28 | or 0 if no animation is running. 29 | tags: 30 | - Indicate 31 | 32 | IndicatePatch: 33 | requestBody: 34 | content: 35 | application/json: 36 | schema: 37 | $ref: '#/IndicatePatchSchema' 38 | responses: 39 | '200': 40 | description: Indicate status updated 41 | content: 42 | application/json: 43 | schema: 44 | $ref: '#/IndicateSchema' 45 | '400': 46 | $ref: ../common/responses.yaml#/BadRequest 47 | '401': 48 | $ref: ../common/responses.yaml#/Unauthorized 49 | '404': 50 | $ref: ../common/responses.yaml#/NotFound 51 | '500': 52 | $ref: ../common/responses.yaml#/InternalServerError 53 | summary: Trigger visual indication 54 | description: | 55 | [Mate Pro (MT-1500) only] [v4.26+] 56 | 57 | Trigger or cancel visual indication animations on the device. 58 | 59 | Set a field to 1-30 to trigger that animation for the specified number of seconds. 60 | Set to 0 to cancel an ongoing animation. 61 | 62 | The `identify` and `commit` animations are mutually exclusive: triggering one 63 | automatically cancels the other. 64 | 65 | Authentication: Requires either unlocked token (locked=0) OR valid token in 66 | request header. Does not affect token locked state or discovery age. 67 | tags: 68 | - Indicate 69 | 70 | IndicateSchema: 71 | type: object 72 | description: | 73 | [Mate Pro (MT-1500) only] [v4.26+] 74 | 75 | Visual indication animations displayed on the device's LED matrix. 76 | 77 | All animations: 78 | - Accept duration 0-30 seconds (0 cancels, 1-30 triggers) 79 | - Use the currently configured brightness setting 80 | - Can be dismissed early by pressing any button on the device 81 | - Are mutually exclusive (triggering one cancels any other) 82 | 83 | On GET, values indicate remaining seconds of the animation, or 0 if inactive. 84 | properties: 85 | identify: 86 | example: 0 87 | type: integer 88 | description: | 89 | Radar/sonar animation: expanding concentric circles from center. 90 | 91 | Used to locate a specific Mate among multiple deployed units, 92 | helping users avoid setting up or modifying the wrong device. 93 | commit: 94 | example: 3 95 | type: integer 96 | description: | 97 | Checkmark animation: brief confirmation indicator. 98 | 99 | Used to confirm that a change has been applied, such as modifying 100 | channel technology from the app. 101 | 102 | IndicatePatchSchema: 103 | type: object 104 | description: | 105 | Provide exactly one field to trigger that animation. 106 | properties: 107 | identify: 108 | example: 10 109 | type: integer 110 | description: | 111 | Radar/sonar animation duration in seconds (0-30). 112 | commit: 113 | example: 3 114 | type: integer 115 | description: | 116 | Checkmark animation duration in seconds (0-30). 117 | example: 118 | identify: 10 119 | -------------------------------------------------------------------------------- /skeds/paths.yaml: -------------------------------------------------------------------------------- 1 | SkedsPath: 2 | parameters: 3 | - in: path 4 | name: device_id 5 | required: true 6 | schema: 7 | type: string 8 | get: 9 | $ref: ../skeds/paths.yaml#/GetList 10 | post: 11 | $ref: ../skeds/paths.yaml#/Post 12 | 13 | SkedPath: 14 | parameters: 15 | - in: path 16 | name: device_id 17 | required: true 18 | schema: 19 | type: string 20 | - in: path 21 | name: sked_id 22 | required: true 23 | schema: 24 | type: string 25 | get: 26 | $ref: ../skeds/paths.yaml#/Get 27 | patch: 28 | $ref: ../skeds/paths.yaml#/Patch 29 | delete: 30 | $ref: ../skeds/paths.yaml#/Delete 31 | 32 | Post: 33 | requestBody: 34 | content: 35 | application/json: 36 | schema: 37 | $ref: schemas.yaml#/Sked 38 | responses: 39 | '201': 40 | $ref: ../common/responses.yaml#/Created 41 | '400': 42 | $ref: ../common/responses.yaml#/BadRequest 43 | '401': 44 | $ref: ../common/responses.yaml#/Unauthorized 45 | '500': 46 | $ref: ../common/responses.yaml#/InternalServerError 47 | summary: Create new Device Schedule 48 | description: | 49 | Creates a Device Schedule under a specific Device. 50 | 51 | If the timezone or location settings in `sys/time` are not set, 52 | a 400 error may result depending on what `mark` is requested. 53 | Specifically, the following requests will result in an 400 error: 54 | 55 | - POSTed `mark` is `midnight` but `sys/time.tz` is `null` 56 | - POSTed `mark` is `dawn`, `dusk`, `sunrise`, or `sunset`, but `sys/time.grid` or `sys/time.tz` is `null` 57 | 58 | tags: 59 | - Device Schedules 60 | 61 | Patch: 62 | requestBody: 63 | content: 64 | application/json: 65 | schema: 66 | $ref: schemas.yaml#/Sked 67 | responses: 68 | '200': 69 | description: Device Schedule modified 70 | '400': 71 | $ref: ../common/responses.yaml#/BadRequest 72 | '401': 73 | $ref: ../common/responses.yaml#/Unauthorized 74 | '404': 75 | $ref: ../common/responses.yaml#/NotFound 76 | '500': 77 | $ref: ../common/responses.yaml#/InternalServerError 78 | summary: Modify an existing Device Schedule 79 | description: | 80 | Modifies any fields of an existing Device Schedule. 81 | tags: 82 | - Device Schedules 83 | 84 | GetList: 85 | description: | 86 | Returns a list of sked_ids and the corresponding sked hashes. 87 | Please see the "Hash Tree" documentation for an explanation of hashes. 88 | responses: 89 | '200': 90 | content: 91 | application/json: 92 | schema: 93 | $ref: schemas.yaml#/SkedList 94 | description: Device Schedule list returned 95 | '401': 96 | $ref: ../common/responses.yaml#/Unauthorized 97 | '404': 98 | $ref: ../common/responses.yaml#/NotFound 99 | '500': 100 | $ref: ../common/responses.yaml#/InternalServerError 101 | summary: Get list of Device Schedules 102 | tags: 103 | - Device Schedules 104 | 105 | Get: 106 | responses: 107 | '200': 108 | content: 109 | application/json: 110 | schema: 111 | $ref: schemas.yaml#/Sked 112 | description: Device Schedule object returned 113 | '401': 114 | $ref: ../common/responses.yaml#/Unauthorized 115 | '404': 116 | $ref: ../common/responses.yaml#/NotFound 117 | '500': 118 | $ref: ../common/responses.yaml#/InternalServerError 119 | summary: Get specific Device Schedule 120 | description: | 121 | Get information about a Device Schedule. 122 | tags: 123 | - Device Schedules 124 | 125 | Delete: 126 | responses: 127 | '204': 128 | description: Device Schedule deleted 129 | '401': 130 | $ref: ../common/responses.yaml#/Unauthorized 131 | '404': 132 | $ref: ../common/responses.yaml#/NotFound 133 | '500': 134 | $ref: ../common/responses.yaml#/InternalServerError 135 | summary: Delete a Device Schedule 136 | description: | 137 | Deletes specified Device Schedule. 138 | Naturally, the Device Schedule will be canceled. 139 | tags: 140 | - Device Schedules 141 | -------------------------------------------------------------------------------- /skeds/group-paths.yaml: -------------------------------------------------------------------------------- 1 | SkedsPath: 2 | parameters: 3 | - in: path 4 | name: group_id 5 | required: true 6 | schema: 7 | type: string 8 | get: 9 | $ref: ../skeds/group-paths.yaml#/GetList 10 | post: 11 | $ref: ../skeds/group-paths.yaml#/Post 12 | 13 | SkedPath: 14 | parameters: 15 | - in: path 16 | name: group_id 17 | required: true 18 | schema: 19 | type: string 20 | - in: path 21 | name: sked_id 22 | required: true 23 | schema: 24 | type: string 25 | get: 26 | $ref: ../skeds/group-paths.yaml#/Get 27 | patch: 28 | $ref: ../skeds/group-paths.yaml#/Patch 29 | delete: 30 | $ref: ../skeds/group-paths.yaml#/Delete 31 | 32 | Post: 33 | requestBody: 34 | content: 35 | application/json: 36 | schema: 37 | $ref: schemas.yaml#/Sked 38 | responses: 39 | '201': 40 | $ref: ../common/responses.yaml#/Created 41 | '400': 42 | $ref: ../common/responses.yaml#/BadRequest 43 | '401': 44 | $ref: ../common/responses.yaml#/Unauthorized 45 | '500': 46 | $ref: ../common/responses.yaml#/InternalServerError 47 | summary: Create new Group Schedule 48 | description: | 49 | Creates a Group Schedule under a specific Group. 50 | 51 | If the timezone or location settings in `sys/time` are not set, 52 | a 400 error may result depending on what `mark` is requested. 53 | Specifically, the following requests will result in an 400 error: 54 | 55 | - POSTed `mark` is `midnight` but `sys/time.tz` is `null` 56 | - POSTed `mark` is `dawn`, `dusk`, `sunrise`, or `sunset`, but `sys/time.grid` or `sys/time.tz` is `null` 57 | 58 | tags: 59 | - Group Schedules 60 | 61 | Patch: 62 | requestBody: 63 | content: 64 | application/json: 65 | schema: 66 | $ref: schemas.yaml#/Sked 67 | responses: 68 | '200': 69 | description: Group Schedule modified 70 | '400': 71 | $ref: ../common/responses.yaml#/BadRequest 72 | '401': 73 | $ref: ../common/responses.yaml#/Unauthorized 74 | '404': 75 | $ref: ../common/responses.yaml#/NotFound 76 | '500': 77 | $ref: ../common/responses.yaml#/InternalServerError 78 | summary: Modify an existing Group Schedule 79 | description: | 80 | Modifies any fields of an existing Group Schedule. 81 | tags: 82 | - Group Schedules 83 | 84 | GetList: 85 | description: | 86 | Returns a list of sked_ids and the corresponding sked hashes. 87 | Please see the "Hash Tree" documentation for an explanation of hashes. 88 | responses: 89 | '200': 90 | content: 91 | application/json: 92 | schema: 93 | $ref: schemas.yaml#/SkedList 94 | description: Group Schedule list returned 95 | '401': 96 | $ref: ../common/responses.yaml#/Unauthorized 97 | '404': 98 | $ref: ../common/responses.yaml#/NotFound 99 | '500': 100 | $ref: ../common/responses.yaml#/InternalServerError 101 | summary: Get list of Group Schedules 102 | tags: 103 | - Group Schedules 104 | 105 | Get: 106 | responses: 107 | '200': 108 | content: 109 | application/json: 110 | schema: 111 | $ref: schemas.yaml#/Sked 112 | description: Group Schedule object returned 113 | '401': 114 | $ref: ../common/responses.yaml#/Unauthorized 115 | '404': 116 | $ref: ../common/responses.yaml#/NotFound 117 | '500': 118 | $ref: ../common/responses.yaml#/InternalServerError 119 | summary: Get specific Group Schedule 120 | description: | 121 | Get information about a Group Schedule. 122 | tags: 123 | - Group Schedules 124 | 125 | Delete: 126 | responses: 127 | '204': 128 | description: Group Schedule deleted 129 | '401': 130 | $ref: ../common/responses.yaml#/Unauthorized 131 | '404': 132 | $ref: ../common/responses.yaml#/NotFound 133 | '500': 134 | $ref: ../common/responses.yaml#/InternalServerError 135 | summary: Delete a Group Schedule 136 | description: | 137 | Deletes specified Group Schedule. 138 | Naturally, the Group Schedule will be canceled. 139 | tags: 140 | - Group Schedules 141 | -------------------------------------------------------------------------------- /signal/schemas.yaml: -------------------------------------------------------------------------------- 1 | Signal: 2 | required: 3 | - freq 4 | - data 5 | - bps 6 | - encoding 7 | type: object 8 | properties: 9 | freq: 10 | example: 434000 11 | type: number 12 | description: | 13 | Frequency in kHz: 14 | - `>= 1000` is RF 15 | - `< 1000` is IR 16 | 17 | Bond Bridge can only receive IR signals at or near 38 kHz, 18 | and will report all IR signals as 38 kHz. 19 | 20 | Bond Bridge currently transmits all IR signals at 38 kHz also. 21 | modulation: 22 | example: OOK 23 | type: string 24 | description: | 25 | - `OOK` = on-off keying 26 | - `GFSK` = gaussian frequency-shift keying 27 | 28 | If not provided, defaults to `OOK`. 29 | data: 30 | example: "110100110110H" 31 | type: string 32 | description: | 33 | String representation of data bits to be transmitted. 34 | 35 | The maximum length of the data string is 6144 bytes. 36 | encoding: 37 | example: "cq" 38 | type: string 39 | description: | 40 | Specifies the encoding of the data string. 41 | 42 | In all cases, the duration of each bit is 1/`bps` seconds. 43 | 44 | ### CQ encoding (`"cq"`) 45 | 46 | This is a simple encoding where bits are represented using `0` and `1`, 47 | with some abbreviations for sequences of bits. 48 | 49 | Each character represents one or more bits: 50 | 51 | - `0` single zero bit 52 | - `1` single one bit 53 | - `C` 2^0 (1) zero bits 54 | - `D` 2^1 (2) zero bits 55 | - `E` 2^2 (4) zero bits 56 | - `F` 2^3 (8) zero bits 57 | - ... 58 | - `Q` 2^14 (16384) zero bits 59 | - `c` thru `q` are just like `C` thru `Q`, but for one bits 60 | - `A` the three bits 110 61 | - `B` the three bits 011 62 | 63 | ### Hex (`"hex"`) 64 | 65 | This is a simple encoding where the data string consists of hex bytes. 66 | Each hex byte represents 8 bits of data. 67 | 68 | Hex encoding is currently limited to only work at `40000` bps. 69 | 70 | This is the default encoding for scan results. 71 | 72 | bps: 73 | example: 1000 74 | type: number 75 | description: | 76 | Bitrate of `data`. Range is 100 to 40000. 77 | reps: 78 | example: 12 79 | type: number 80 | description: | 81 | Number of times that data should be repeated. 82 | 83 | If not provided, `1` is assumed. 84 | use_scan: 85 | example: true 86 | type: boolean 87 | writeOnly: true 88 | description: | 89 | If present and true, the Signal recorded by the most recent scan will 90 | be used, with all other fields ignored 91 | Scan: 92 | type: object 93 | properties: 94 | freq: 95 | example: 434000 96 | type: number 97 | description: | 98 | Frequency to scan in kHz. 99 | 100 | If not provided, scan will search all RF frequencies, but not IR. 101 | 102 | Specify `38` to explicitly scan IR. 103 | modulation: 104 | example: OOK 105 | type: string 106 | description: | 107 | - `OOK` = on-off keying 108 | - `GFSK` = gaussian frequency-shift keying 109 | 110 | If not provided, defaults to `OOK`. 111 | 112 | Only applicable to RF. 113 | 114 | (GFSK scanning currently unimplemented.) 115 | running: 116 | example: false 117 | readOnly: true 118 | description: | 119 | If true, scan is running. 120 | total_timeout: 121 | example: 30 122 | type: number 123 | readOnly: true 124 | description: | 125 | The time from scan start to scan timeout, in 126 | seconds. 127 | success: 128 | example: true 129 | readOnly: true 130 | description: | 131 | If true, a signal was found. 132 | Rssi: 133 | example: 134 | format: 135 | - freq 136 | - rssi 137 | results: 138 | - - 350000 139 | - 80 140 | - - 351000 141 | - 87 142 | - - 352000 143 | - 92 144 | type: object 145 | -------------------------------------------------------------------------------- /skeds/scene-paths.yaml: -------------------------------------------------------------------------------- 1 | SkedsPath: 2 | parameters: 3 | - in: path 4 | name: scene_id 5 | required: true 6 | schema: 7 | type: string 8 | get: 9 | $ref: ../skeds/scene-paths.yaml#/GetList 10 | post: 11 | $ref: ../skeds/scene-paths.yaml#/Post 12 | 13 | SkedPath: 14 | parameters: 15 | - in: path 16 | name: scene_id 17 | required: true 18 | schema: 19 | type: string 20 | - in: path 21 | name: sked_id 22 | required: true 23 | schema: 24 | type: string 25 | get: 26 | $ref: ../skeds/scene-paths.yaml#/Get 27 | patch: 28 | $ref: ../skeds/scene-paths.yaml#/Patch 29 | delete: 30 | $ref: ../skeds/scene-paths.yaml#/Delete 31 | 32 | Post: 33 | requestBody: 34 | content: 35 | application/json: 36 | schema: 37 | $ref: schemas.yaml#/Sked 38 | responses: 39 | '201': 40 | $ref: ../common/responses.yaml#/Created 41 | '400': 42 | $ref: ../common/responses.yaml#/BadRequest 43 | '401': 44 | $ref: ../common/responses.yaml#/Unauthorized 45 | '500': 46 | $ref: ../common/responses.yaml#/InternalServerError 47 | summary: Create new Scene Schedule 48 | description: | 49 | Creates a Scene Schedule under a specific Scene. 50 | 51 | Note that `action` must not be set for Scene Schedules. 52 | 53 | If the timezone or location settings in `sys/time` are not set, 54 | a 400 error may result depending on what `mark` is requested. 55 | Specifically, the following requests will result in an 400 error: 56 | 57 | - POSTed `mark` is `midnight` but `sys/time.tz` is `null` 58 | - POSTed `mark` is `dawn`, `dusk`, `sunrise`, or `sunset`, but `sys/time.grid` or `sys/time.tz` is `null` 59 | 60 | tags: 61 | - Scene Schedules 62 | 63 | Patch: 64 | requestBody: 65 | content: 66 | application/json: 67 | schema: 68 | $ref: schemas.yaml#/Sked 69 | responses: 70 | '200': 71 | description: Scene Schedule modified 72 | '400': 73 | $ref: ../common/responses.yaml#/BadRequest 74 | '401': 75 | $ref: ../common/responses.yaml#/Unauthorized 76 | '404': 77 | $ref: ../common/responses.yaml#/NotFound 78 | '500': 79 | $ref: ../common/responses.yaml#/InternalServerError 80 | summary: Modify an existing Scene Schedule 81 | description: | 82 | Modifies any fields of an existing Scene Schedule. 83 | tags: 84 | - Scene Schedules 85 | 86 | GetList: 87 | description: | 88 | Returns a list of sked_ids and the corresponding sked hashes. 89 | Please see the "Hash Tree" documentation for an explanation of hashes. 90 | responses: 91 | '200': 92 | content: 93 | application/json: 94 | schema: 95 | $ref: schemas.yaml#/SkedList 96 | description: Scene Schedule list returned 97 | '401': 98 | $ref: ../common/responses.yaml#/Unauthorized 99 | '404': 100 | $ref: ../common/responses.yaml#/NotFound 101 | '500': 102 | $ref: ../common/responses.yaml#/InternalServerError 103 | summary: Get list of Scene Schedules 104 | tags: 105 | - Scene Schedules 106 | 107 | Get: 108 | responses: 109 | '200': 110 | content: 111 | application/json: 112 | schema: 113 | $ref: schemas.yaml#/Sked 114 | description: Scene Schedule object returned 115 | '401': 116 | $ref: ../common/responses.yaml#/Unauthorized 117 | '404': 118 | $ref: ../common/responses.yaml#/NotFound 119 | '500': 120 | $ref: ../common/responses.yaml#/InternalServerError 121 | summary: Get specific Scene Schedule 122 | description: | 123 | Get information about a Scene Schedule. 124 | tags: 125 | - Scene Schedules 126 | 127 | Delete: 128 | responses: 129 | '204': 130 | description: Scene Schedule deleted 131 | '401': 132 | $ref: ../common/responses.yaml#/Unauthorized 133 | '404': 134 | $ref: ../common/responses.yaml#/NotFound 135 | '500': 136 | $ref: ../common/responses.yaml#/InternalServerError 137 | summary: Delete a Scene Schedule 138 | description: | 139 | Deletes specified Scene Schedule. 140 | Naturally, the Scene Schedule will be canceled. 141 | tags: 142 | - Scene Schedules 143 | -------------------------------------------------------------------------------- /channels/schemas.yaml: -------------------------------------------------------------------------------- 1 | Channel: 2 | type: object 3 | properties: 4 | name: 5 | example: "North Screen" 6 | type: string 7 | description: | 8 | User-facing name of the channel, displayed in the app. 9 | Maximum length: 64 bytes of UTF-8. 10 | label: 11 | example: "N Screen" 12 | type: string 13 | description: | 14 | [MT-1500 only] 15 | Optional display label shown on the device's LED matrix. 16 | Limited to A-Z, a-z, 0-9, space, and "-" characters. 17 | Maximum length: 20 characters. 18 | When not set, the device may display an abbreviated version of the name. 19 | Allows separating the full name (for app display) from a shorter label 20 | (for the more limited matrix display). 21 | template: 22 | example: "RMS12" 23 | type: string 24 | description: | 25 | Technology template assigned to this channel (R-number identifier). 26 | Determines the RF protocol used for motor control. 27 | Uses the same R-number format as the devices API. 28 | 29 | Not present for channel 0 (All channel). 30 | properties: 31 | type: object 32 | description: | 33 | Technology-specific properties for this channel. 34 | Contents vary based on the assigned `template`. 35 | 36 | Not present for channel 0 (All channel). 37 | properties: 38 | mfg: 39 | example: 0 40 | type: integer 41 | description: | 42 | Manufacturer code or technology identifier. 43 | pairing_assets_key: 44 | example: "" 45 | type: string 46 | description: | 47 | Reference to pairing assets or instructions. 48 | example: 49 | mfg: 0 50 | pairing_assets_key: "" 51 | type: 52 | readOnly: true 53 | example: "MS" 54 | type: string 55 | description: | 56 | [v4.24+] [MT-1500 only] 57 | Channel type, automatically inferred from the configured technology template. 58 | Uses the same enumeration as devices: 59 | - `MS`: Motorized Window Coverings (Shades, Screens, Drapes, Awnings) 60 | - `LT`: Light 61 | - `CF`: Ceiling Fan 62 | - `GX`: Generic device 63 | - `FP`: Fireplace 64 | - `BD`: Bidet 65 | 66 | Channels configured for Relay mode have type `MS`. 67 | 68 | Not present for channel 0. 69 | enabled: 70 | example: true 71 | type: boolean 72 | description: | 73 | [v4.24+] [MT-1500 only] 74 | Channel visibility toggle. When false, the channel is hidden from the 75 | physical cycling interface (skipped when pressing Channel +/- buttons) 76 | and appears grayed out in the app. 77 | 78 | All channel configuration (name, technology, schedules, etc.) is preserved 79 | when a channel is disabled. 80 | 81 | When channel 0 (All) is disabled, it is skipped during physical cycling. 82 | For bitmap-based protocols (ARC, Gaposa, etc.), disabled individual channels 83 | are masked from the channel 0 bitmap. For RTS and other protocols where 84 | channel 0 has its own address, the signal transmits normally. 85 | 86 | Schedules configured for disabled channels will not execute. 87 | 88 | Defaults to true. 89 | actions: 90 | readOnly: true 91 | type: array 92 | items: 93 | type: string 94 | example: 95 | - "Raise" 96 | - "Lower" 97 | - "Stop" 98 | - "SetPosition" 99 | description: | 100 | [v4.24+] [MT-1500 only] 101 | List of actions available on this channel, determined by the channel's 102 | technology and type. Used for configuring schedules and built-in scenes. 103 | 104 | Common actions by type: 105 | - Motorized Shades (MS): Raise, Lower, Stop, SetPosition, Preset 106 | - Lights (LT): TurnLightOn, TurnLightOff, SetBrightness 107 | 108 | Note: Unlike devices, channels do not expose a Features field or maintain state. 109 | The actions list may include any action supported by the technology without 110 | strict atomicity requirements. 111 | 112 | Not present for channel 0. 113 | 114 | ChannelList: 115 | type: object 116 | description: | 117 | Hash tree of all channels on this Mate Pro. 118 | Channel IDs range from "0" to "15". 119 | Channel "0" is the "All" channel. 120 | example: 121 | _: "7fc1e84b" 122 | "0": 123 | _: "a1b2c3d4" 124 | "1": 125 | _: "84819a9f" 126 | "2": 127 | _: "23141efa" 128 | "3": 129 | _: "2425a8bc" 130 | "4": 131 | _: "2425a8bc" 132 | "5": 133 | _: "2425a8bc" 134 | "6": 135 | _: "2425a8bc" 136 | "7": 137 | _: "2425a8bc" 138 | "8": 139 | _: "2425a8bc" 140 | "9": 141 | _: "2425a8bc" 142 | "10": 143 | _: "2425a8bc" 144 | "11": 145 | _: "2425a8bc" 146 | "12": 147 | _: "2425a8bc" 148 | "13": 149 | _: "2425a8bc" 150 | "14": 151 | _: "2425a8bc" 152 | "15": 153 | _: "2425a8bc" 154 | -------------------------------------------------------------------------------- /api/mqtt.yaml: -------------------------------------------------------------------------------- 1 | Schema: 2 | type: object 3 | properties: 4 | host: 5 | example: my-mqtt-server.myhome.com 6 | type: string 7 | description: | 8 | IP address or domain name of the MQTT broker. 9 | If set to empty string, the default Bond Cloud server will be used. 10 | port: 11 | example: 8883 12 | type: number 13 | description: | 14 | Specify a different port number for the MQTT broker. 15 | If set to 0, the Bond Cloud default port number will be used (8883). 16 | Note that the communication is secured by TLS (SSL). 17 | cert_set: 18 | example: true 19 | type: boolean 20 | readOnly: true 21 | description: | 22 | If true, a custom Bond certificate has been loaded. 23 | If false, the Bond's default certificate will be used. 24 | cert: 25 | example: "certificate_goes_here" 26 | type: string 27 | writeOnly: true 28 | description: | 29 | Specify a custom Bond certificate. 30 | Typically, this is the Bond-specific certificate 31 | concatenated with the Bond-signing CA certificate. 32 | Write to empty string to go back to the Bond's default certificate. 33 | key_set: 34 | example: true 35 | type: boolean 36 | readOnly: true 37 | description: | 38 | If true, a custom Bond private key has been loaded. 39 | If false, the Bond's default private key will be used. 40 | key: 41 | example: "key_goes_here" 42 | type: string 43 | writeOnly: true 44 | description: | 45 | Specify a custom Bond private key. 46 | Write to empty string to go back to the Bond's default private key. 47 | server_cert_set: 48 | example: true 49 | type: boolean 50 | readOnly: true 51 | description: | 52 | If true, a custom server CA has been loaded. 53 | If false, the Bond Cloud CA will be used. 54 | enabled: 55 | example: true 56 | type: boolean 57 | description: | 58 | [Added in v3.3.3] 59 | If true (default), Bond will attempt MQTT connection. If MQTT connection fails, Bond becomes discoverable again via Config AP. 60 | If false, Bond will not attempt MQTT connection and Config AP will remain deactivated. 61 | server_cert: 62 | example: "certificate_goes_here" 63 | type: string 64 | writeOnly: true 65 | description: | 66 | Specify a custom MQTT server CA. 67 | Set to empty string to return to default. 68 | server_cert_check: 69 | example: true 70 | type: boolean 71 | description: | 72 | Set to false to disable verification of the MQTT server CA. 73 | It is strongly recommend to leave this option enabled, 74 | because otherwise a man-in-the-middle attack is possible. 75 | 76 | Path: 77 | patch: 78 | requestBody: 79 | content: 80 | application/json: 81 | schema: 82 | $ref: ./mqtt.yaml#/Schema 83 | responses: 84 | '200': 85 | description: MQTT Reconfigured 86 | '401': 87 | $ref: ../common/responses.yaml#/Unauthorized 88 | '500': 89 | $ref: ../common/responses.yaml#/InternalServerError 90 | security: 91 | - BasicAuth: [] 92 | summary: Configure MQTT Transport 93 | description: | 94 | IMPORTANT NOTE: MQTT redirection is currently untested. If you have a use 95 | case for this API, please let us know on [the forums](https://forum.bondhome.io/) 96 | so that we can better prioritize implementing this API. 97 | 98 | Configure the Bond's MQTT Transport, which is used for communication 99 | with the Bond Cloud or an offline MQTT broker. 100 | Note that Bond uses MQTT over TLS with certificate-based authentication. 101 | Password-based authentication is not supported. 102 | 103 | Some advanced users may elect to run their own MQTT brokers, 104 | so this endpoint allows customizing of the MQTT broker address 105 | and the various related security settings. 106 | 107 | Note that any manipulation of this endpoint will result in the 108 | Bond disconnecting from Bond Cloud, and therefore integrations 109 | and control away from home will become unavailable. 110 | 111 | NOTE: All settings only take effect after reboot. 112 | tags: 113 | - MQTT 114 | get: 115 | responses: 116 | '204': 117 | description: No custom MQTT configuration found 118 | '200': 119 | description: MQTT Configuration 120 | content: 121 | application/json: 122 | schema: 123 | $ref: ./mqtt.yaml#/Schema 124 | '401': 125 | $ref: ../common/responses.yaml#/Unauthorized 126 | '500': 127 | $ref: ../common/responses.yaml#/InternalServerError 128 | security: 129 | - BasicAuth: [] 130 | summary: Get MQTT Configuration 131 | tags: 132 | - MQTT 133 | delete: 134 | responses: 135 | '204': 136 | description: MQTT config reset to default 137 | '401': 138 | $ref: ../common/responses.yaml#/Unauthorized 139 | '500': 140 | $ref: ../common/responses.yaml#/InternalServerError 141 | security: 142 | - BasicAuth: [] 143 | summary: Reset MQTT Config to defaults 144 | tags: 145 | - MQTT 146 | 147 | -------------------------------------------------------------------------------- /local/paths.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | /v2/debug/rfman: 3 | $ref: ../debug/rfman.yaml#/Path 4 | /v2/debug/leds: 5 | $ref: ../debug/leds.yaml 6 | /v2/debug/livelog: 7 | $ref: ../debug/livelog.yaml 8 | /v2/debug/wifi: 9 | $ref: ../debug/wifi.yaml 10 | /v2/debug/beau/{partition}: 11 | $ref: ../debug/beau.yaml 12 | /v2/bridge: 13 | $ref: ../bridge/paths.yaml 14 | /v2/sys/locale: 15 | $ref: ../locale/paths.yaml 16 | /v2/devices: 17 | $ref: ../devices/paths.yaml#/DevicesPath 18 | /v2/devices/{device_id}: 19 | $ref: ../devices/paths.yaml#/DevicePath 20 | /v2/devices/{device_id}/state: 21 | $ref: ../devices/paths.yaml#/StatePath 22 | /v2/devices/{device_id}/addr: 23 | $ref: ../devices/paths.yaml#/RemoteAddrPath 24 | /v2/devices/{device_id}/reload: 25 | $ref: ../devices/paths.yaml#/ReloadPath 26 | /v2/devices/{device_id}/properties: 27 | $ref: ../devices/paths.yaml#/PropertiesPath 28 | /v2/devices/{device_id}/power_cycle_state: 29 | $ref: ../devices/paths.yaml#/PowerCycleStatePath 30 | /v2/devices/{device_id}/actions/{action_name}: 31 | $ref: ../actions/paths.yaml#/ActionPath 32 | /v2/devices/{device_id}/commands: 33 | $ref: ../commands/paths.yaml#/CommandsPath 34 | /v2/devices/{device_id}/commands/{command_id}: 35 | $ref: ../commands/paths.yaml#/CommandPath 36 | /v2/devices/{device_id}/commands/{command_id}/signal: 37 | $ref: ../signal/paths.yaml#/SignalsPath 38 | /v2/devices/{device_id}/commands/{command_id}/tx: 39 | $ref: ../signal/paths.yaml#/SignalTxPath 40 | /v2/devices/{device_id}/skeds: 41 | $ref: ../skeds/paths.yaml#/SkedsPath 42 | /v2/devices/{device_id}/skeds/{sked_id}: 43 | $ref: ../skeds/paths.yaml#/SkedPath 44 | /v2/devices/{device_id}/vrc: 45 | $ref: ../vrc/paths.yaml#/VrcPath 46 | /v2/devices/{device_id}/vrc/keystream: 47 | $ref: ../vrc/paths.yaml#/VrcKeystreamPath 48 | /v2/groups: 49 | $ref: ../groups/paths.yaml#/GroupsPath 50 | /v2/groups/{group_id}: 51 | $ref: ../groups/paths.yaml#/GroupPath 52 | /v2/groups/{group_id}/state: 53 | $ref: ../groups/paths.yaml#/StatePath 54 | /v2/groups/{group_id}/properties: 55 | $ref: ../groups/paths.yaml#/PropertiesPath 56 | /v2/groups/{group_id}/actions/{action_name}: 57 | $ref: ../actions/group-paths.yaml#/ActionPath 58 | /v2/groups/{group_id}/skeds: 59 | $ref: ../skeds/group-paths.yaml#/SkedsPath 60 | /v2/groups/{group_id}/skeds/{sked_id}: 61 | $ref: ../skeds/group-paths.yaml#/SkedPath 62 | /v2/scenes: 63 | $ref: ../scenes/paths.yaml#/ScenesPath 64 | /v2/scenes/{scene_id}: 65 | $ref: ../scenes/paths.yaml#/ScenePath 66 | /v2/scenes/{scene_id}/run: 67 | $ref: ../scenes/paths.yaml#/RunPath 68 | /v2/scenes/{scene_id}/skeds: 69 | $ref: ../skeds/scene-paths.yaml#/SkedsPath 70 | /v2/scenes/{scene_id}/skeds/{sked_id}: 71 | $ref: ../skeds/scene-paths.yaml#/SkedPath 72 | /v2/sidekicks: 73 | $ref: ../sidekicks/paths.yaml#/SidekicksPath 74 | /v2/sidekicks/{sk_id}: 75 | $ref: ../sidekicks/paths.yaml#/SidekickPath 76 | /v2/sidekicks/{sk_id}/keystream: 77 | $ref: ../sidekicks/paths.yaml#/KeystreamPath 78 | /v2/sidekicks/_learn: 79 | $ref: ../sidekicks/paths.yaml#/LearnPath 80 | /v2/signal/tx: 81 | $ref: ../signal/paths.yaml#/TxPath 82 | /v2/signal/rssi: 83 | $ref: ../signal/paths.yaml#/SignalRssiPath 84 | /v2/signal/scan: 85 | $ref: ../signal/paths.yaml#/SignalScanPath 86 | /v2/signal/scan/signal: 87 | $ref: ../signal/paths.yaml#/SignalScanSignalPath 88 | /v2/token: 89 | $ref: ../token/paths.yaml 90 | /v2/api/mqtt: 91 | $ref: ../api/mqtt.yaml#/Path 92 | /v2/api/bpup: 93 | $ref: ../api/bpup.yaml#/Path 94 | /v2/api/bhk: 95 | $ref: ../api/bhk.yaml#/Path 96 | /v2/sys/wifi/scan: 97 | $ref: ../network/paths.yaml#/WifiScanPath 98 | /v2/sys/wifi/sta: 99 | $ref: ../network/paths.yaml#/WifiStaPath 100 | /v2/sys/wifi/watchdog: 101 | $ref: ../network/paths.yaml#/WifiWatchDogPath 102 | /v2/sys/eth: 103 | $ref: ../network/paths.yaml#/EthPath 104 | /v2/sys/upgrade: 105 | $ref: ../network/paths.yaml#/WifiUpgradePath 106 | /v2/sys/version: 107 | $ref: ../network/paths.yaml#/WifiVersionPath 108 | /v2/sys/reset: 109 | $ref: ../network/paths.yaml#/WifiResetPath 110 | /v2/sys/reboot: 111 | $ref: ../network/paths.yaml#/WifiRebootPath 112 | /v2/sys/time: 113 | $ref: ../sys/paths.yaml#/TimePath 114 | /v2/sys/power: 115 | $ref: ../sys/paths.yaml#/PowerPath 116 | /v2/sys/indicate: 117 | $ref: ../sys/indicate.yaml#/IndicatePath 118 | /v2/sys/backup: 119 | get: 120 | $ref: ../firmware/paths.yaml#/BackupGet 121 | put: 122 | $ref: ../firmware/paths.yaml#/BackupPut 123 | delete: 124 | $ref: ../firmware/paths.yaml#/BackupDelete 125 | /v2/sidekicks/{ws_id}: 126 | $ref: ../weather_sensor/paths.yaml#/WeatherSensorSidekicksPath 127 | /v2/sidekicks/{ws_id}/properties: 128 | $ref: ../weather_sensor/paths.yaml#/PropertiesPath 129 | /v2/sidekicks/{ws_id}/state: 130 | $ref: ../weather_sensor/paths.yaml#/StatePath 131 | /v2/sidekicks/{ws_id}/test: 132 | $ref: ../weather_sensor/paths.yaml#/TestPath 133 | /v2/channels: 134 | $ref: ../channels/paths.yaml#/ChannelsPath 135 | /v2/channels/{channel_id}: 136 | $ref: ../channels/paths.yaml#/ChannelPath 137 | /v2/channels/{channel_id}/actions/{action_name}: 138 | $ref: ../actions/channel-paths.yaml#/ActionPath 139 | /v2/channels/{channel_id}/skeds: 140 | $ref: ../skeds/channel-paths.yaml#/SkedsPath 141 | /v2/channels/{channel_id}/skeds/{sked_id}: 142 | $ref: ../skeds/channel-paths.yaml#/SkedPath 143 | /v2/keys: 144 | $ref: ../keys/paths.yaml#/KeysPath 145 | -------------------------------------------------------------------------------- /skeds/channel-paths.yaml: -------------------------------------------------------------------------------- 1 | SkedsPath: 2 | parameters: 3 | - in: path 4 | name: channel_id 5 | required: true 6 | schema: 7 | type: string 8 | pattern: '^(0|[1-9]|1[0-5])$' 9 | description: | 10 | Channel ID: "0" for All channel, or "1" through "15" for individual channels. 11 | get: 12 | $ref: ../skeds/channel-paths.yaml#/GetList 13 | post: 14 | $ref: ../skeds/channel-paths.yaml#/Post 15 | 16 | SkedPath: 17 | parameters: 18 | - in: path 19 | name: channel_id 20 | required: true 21 | schema: 22 | type: string 23 | pattern: '^(0|[1-9]|1[0-5])$' 24 | description: | 25 | Channel ID: "0" for All channel, or "1" through "15" for individual channels. 26 | - in: path 27 | name: sked_id 28 | required: true 29 | schema: 30 | type: string 31 | get: 32 | $ref: ../skeds/channel-paths.yaml#/Get 33 | patch: 34 | $ref: ../skeds/channel-paths.yaml#/Patch 35 | delete: 36 | $ref: ../skeds/channel-paths.yaml#/Delete 37 | 38 | Post: 39 | requestBody: 40 | content: 41 | application/json: 42 | schema: 43 | $ref: schemas.yaml#/Sked 44 | responses: 45 | '201': 46 | $ref: ../common/responses.yaml#/Created 47 | '400': 48 | $ref: ../common/responses.yaml#/BadRequest 49 | '401': 50 | $ref: ../common/responses.yaml#/Unauthorized 51 | '500': 52 | $ref: ../common/responses.yaml#/InternalServerError 53 | summary: Create new Channel Schedule 54 | description: | 55 | Creates a Channel Schedule for a specific channel on Mate Pro (MT-1500). 56 | 57 | Channel schedules allow autonomous time-based or solar-based automation 58 | without requiring a Bond Bridge. The onboard RTC maintains ±15 minute 59 | accuracy over one year. 60 | 61 | Limits: 62 | - Up to 6 schedules per channel (advertised/tested limit) 63 | - Up to 12 schedules total across all channels (advertised/tested limit) 64 | - Schedules on disabled channels will not execute 65 | 66 | If the timezone or location settings in `sys/time` are not set, 67 | a 400 error may result depending on what `mark` is requested. 68 | Specifically, the following requests will result in a 400 error: 69 | 70 | - POSTed `mark` is `midnight` but `sys/time.tz` is `null` 71 | - POSTed `mark` is `dawn`, `dusk`, `sunrise`, or `sunset`, but `sys/time.grid` or `sys/time.tz` is `null` 72 | 73 | Available actions depend on the channel type. Common actions: 74 | - Motorized Shades (MS): Raise, Lower, Stop, SetPosition, Preset 75 | - Lights (LT): TurnLightOn, TurnLightOff, SetBrightness 76 | 77 | Note: Open and Close actions are not available for channel schedules, 78 | as Mate does not track the inversion between Raise/Lower and Open/Close 79 | for different shade types (e.g., awnings). 80 | 81 | tags: 82 | - Channel Schedules 83 | 84 | Patch: 85 | requestBody: 86 | content: 87 | application/json: 88 | schema: 89 | $ref: schemas.yaml#/Sked 90 | responses: 91 | '200': 92 | description: Channel Schedule modified 93 | '400': 94 | $ref: ../common/responses.yaml#/BadRequest 95 | '401': 96 | $ref: ../common/responses.yaml#/Unauthorized 97 | '404': 98 | $ref: ../common/responses.yaml#/NotFound 99 | '500': 100 | $ref: ../common/responses.yaml#/InternalServerError 101 | summary: Modify an existing Channel Schedule 102 | description: | 103 | Modifies any fields of an existing Channel Schedule on Mate Pro (MT-1500). 104 | 105 | Note that modifying the action or time may cause the schedule to exceed 106 | capacity limits if other schedules exist. 107 | tags: 108 | - Channel Schedules 109 | 110 | GetList: 111 | description: | 112 | Returns a list of sked_ids and the corresponding sked hashes for a channel. 113 | Please see the "Hash Tree" documentation for an explanation of hashes. 114 | 115 | Applies to Mate Pro (MT-1500) channels. 116 | responses: 117 | '200': 118 | content: 119 | application/json: 120 | schema: 121 | $ref: schemas.yaml#/SkedList 122 | description: Channel Schedule list returned 123 | '401': 124 | $ref: ../common/responses.yaml#/Unauthorized 125 | '404': 126 | $ref: ../common/responses.yaml#/NotFound 127 | '500': 128 | $ref: ../common/responses.yaml#/InternalServerError 129 | summary: Get list of Channel Schedules 130 | tags: 131 | - Channel Schedules 132 | 133 | Get: 134 | responses: 135 | '200': 136 | content: 137 | application/json: 138 | schema: 139 | $ref: schemas.yaml#/Sked 140 | description: Channel Schedule object returned 141 | '401': 142 | $ref: ../common/responses.yaml#/Unauthorized 143 | '404': 144 | $ref: ../common/responses.yaml#/NotFound 145 | '500': 146 | $ref: ../common/responses.yaml#/InternalServerError 147 | summary: Get specific Channel Schedule 148 | description: | 149 | Get information about a Channel Schedule on Mate Pro (MT-1500). 150 | tags: 151 | - Channel Schedules 152 | 153 | Delete: 154 | responses: 155 | '204': 156 | description: Channel Schedule deleted 157 | '401': 158 | $ref: ../common/responses.yaml#/Unauthorized 159 | '404': 160 | $ref: ../common/responses.yaml#/NotFound 161 | '500': 162 | $ref: ../common/responses.yaml#/InternalServerError 163 | summary: Delete a Channel Schedule 164 | description: | 165 | Deletes specified Channel Schedule on Mate Pro (MT-1500). 166 | Naturally, the Channel Schedule will be canceled. 167 | tags: 168 | - Channel Schedules 169 | -------------------------------------------------------------------------------- /ci/validate_with_refs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import yaml 4 | import json 5 | from pathlib import Path 6 | from openapi_spec_validator import openapi_v30_spec_validator, openapi_v31_spec_validator 7 | 8 | def resolve_json_pointer(obj, pointer): 9 | """Resolve a JSON pointer like '/description' or '/schemas/User'""" 10 | if not pointer or pointer == '#': 11 | return obj 12 | if pointer.startswith('#/'): 13 | pointer = pointer[2:] 14 | parts = pointer.split('/') 15 | result = obj 16 | for part in parts: 17 | if isinstance(result, dict): 18 | if part not in result: 19 | raise KeyError(f"'{part}' does not exist in keys: {list(result.keys())}") 20 | result = result[part] 21 | elif isinstance(result, list): 22 | result = result[int(part)] 23 | else: 24 | raise ValueError(f"Cannot resolve pointer {pointer}") 25 | return result 26 | 27 | def resolve_refs(obj, base_path, file_cache=None, current_file_content=None, debug=False): 28 | """Recursively resolve $ref references in a dict/list""" 29 | if file_cache is None: 30 | file_cache = {} 31 | 32 | if isinstance(obj, dict): 33 | if '$ref' in obj and len(obj) == 1: 34 | # This is a reference object 35 | ref_str = obj['$ref'] 36 | 37 | if ref_str.startswith('#/'): 38 | # Internal reference - resolve it using current file content 39 | if current_file_content is not None: 40 | pointer_part = ref_str[2:] # Remove '#/' 41 | resolved = resolve_json_pointer(current_file_content, pointer_part) 42 | return resolve_refs(resolved, base_path, file_cache, current_file_content) 43 | else: 44 | # No context to resolve internal reference, leave it 45 | return obj 46 | elif '#/' in ref_str: 47 | # External file reference with JSON pointer 48 | file_part, pointer_part = ref_str.split('#/', 1) 49 | 50 | # Handle relative paths 51 | if file_part.startswith('./') or file_part.startswith('../') or file_part.startswith('/'): 52 | ref_file = base_path / file_part 53 | else: 54 | # No path prefix - treat as relative to base_path 55 | ref_file = base_path / file_part 56 | 57 | # Cache file contents to avoid re-reading 58 | cache_key = str(ref_file.resolve()) 59 | if cache_key not in file_cache: 60 | with open(ref_file, 'r') as f: 61 | file_cache[cache_key] = yaml.safe_load(f) 62 | 63 | ref_content = file_cache[cache_key] 64 | # Resolve the JSON pointer 65 | resolved = resolve_json_pointer(ref_content, pointer_part) 66 | # Use ref_content as the new current_file_content for resolving internal refs 67 | return resolve_refs(resolved, ref_file.parent, file_cache, ref_content) 68 | else: 69 | # External file reference without pointer 70 | if ref_str.startswith('./') or ref_str.startswith('../') or ref_str.startswith('/'): 71 | ref_file = base_path / ref_str 72 | else: 73 | # No path prefix - treat as relative to base_path 74 | ref_file = base_path / ref_str 75 | 76 | cache_key = str(ref_file.resolve()) 77 | if cache_key not in file_cache: 78 | with open(ref_file, 'r') as f: 79 | file_cache[cache_key] = yaml.safe_load(f) 80 | ref_content = file_cache[cache_key] 81 | return resolve_refs(ref_content, ref_file.parent, file_cache, ref_content) 82 | else: 83 | # Regular dict - recurse into values 84 | return {k: resolve_refs(v, base_path, file_cache, current_file_content) for k, v in obj.items()} 85 | elif isinstance(obj, list): 86 | return [resolve_refs(item, base_path, file_cache, current_file_content) for item in obj] 87 | else: 88 | return obj 89 | 90 | def main(): 91 | if len(sys.argv) < 2: 92 | print("Usage: validate_with_refs.py ") 93 | sys.exit(1) 94 | 95 | spec_file = Path(sys.argv[1]) 96 | 97 | try: 98 | # Load the spec 99 | with open(spec_file, 'r') as f: 100 | spec_dict = yaml.safe_load(f) 101 | 102 | # Resolve all external file references 103 | spec_dict = resolve_refs(spec_dict, spec_file.parent) 104 | 105 | # Detect version 106 | openapi_version = spec_dict.get('openapi', spec_dict.get('swagger', '')) 107 | 108 | if openapi_version.startswith('3.0'): 109 | validator = openapi_v30_spec_validator 110 | elif openapi_version.startswith('3.1'): 111 | validator = openapi_v31_spec_validator 112 | else: 113 | raise ValueError(f"Unsupported OpenAPI version: {openapi_version}") 114 | 115 | # DEBUG: Save resolved spec for inspection 116 | with open('/tmp/resolved_spec.json', 'w') as f: 117 | json.dump(spec_dict, f, indent=2) 118 | 119 | # Validate the spec 120 | validator.validate(spec_dict) 121 | print(f"{spec_file}: OK") 122 | 123 | except Exception as e: 124 | print(f"{spec_file}: Validation Error:", file=sys.stderr) 125 | print(f"{type(e).__name__}: {e}", file=sys.stderr) 126 | import traceback 127 | traceback.print_exc(file=sys.stderr) 128 | sys.exit(1) 129 | 130 | if __name__ == "__main__": 131 | main() 132 | -------------------------------------------------------------------------------- /debug/schemas.yaml: -------------------------------------------------------------------------------- 1 | Wifi: 2 | type: object 3 | properties: 4 | shutdown: 5 | example: 1 6 | type: number 7 | Leds: 8 | type: object 9 | properties: 10 | n: 11 | example: 5 12 | type: number 13 | description: | 14 | Number of LEDs present. 15 | readOnly: true 16 | manual: 17 | example: 1 18 | type: number 19 | description: | 20 | - `0` : LEDs behave normally (default) 21 | - `1` : LED automatic control disabled, will remain fixed as set 22 | value: 23 | example: "FF000000FF000000FFFFFFFF000000" 24 | type: string 25 | description: | 26 | Concatinated 24-bit RGB hex values for each of the `n` LEDs. 27 | 28 | In the example, the 5 LEDs are set to Red, Green, Blue, White, 29 | and Off, respectively. 30 | Fcc: 31 | type: object 32 | properties: 33 | enabled: 34 | example: 0 35 | type: number 36 | description: | 37 | - `0` : Bond radio operates normally; settings on this endpoint are ignored 38 | - `1` : Bond in RF test mode; settings here take effect 39 | mode: 40 | example: 0 41 | type: number 42 | description: | 43 | Controls the RF mode: 44 | - `0`: transceiver shutdown 45 | - `1`: RX fixed frequency 46 | - `2`: RX continuous scan 47 | - `3`: TX simulated packet continuously 48 | - `4`: TX brief burst 49 | - `5`: TX CW 50 | 51 | See enum `fcc_cli_mode_t` in bond-core firmware. 52 | modulation: 53 | example: 1 54 | type: number 55 | description: | 56 | - `0`: OOK 57 | - `1`: GFSK 58 | 59 | See enum `fcc_cli_modulation_t` in bond-core firmware. 60 | duty: 61 | example: 75 62 | type: number 63 | description: | 64 | Duty cycle of transmission (relevent for OOK and GFSK when in 65 | "TX simulated packet" and "TX brief burst" modes. 66 | power: 67 | example: 127 68 | type: number 69 | description: | 70 | Power level, from 0-127. 71 | 72 | Note: In production-firmware, power-level is restricted per frequency 73 | and duty-cycle for compliance. 74 | freq: 75 | example: 434000 76 | type: number 77 | description: | 78 | Frequency in integer kHz. 79 | 80 | Note: In production-firmware, frequency is restricted to authorized 81 | ranges. 82 | ant: 83 | example: 2 84 | type: number 85 | description: | 86 | Select antenna number (valid values: 1, 5, 2, 3). 87 | 88 | Antenna selection is ephemeral and will be overridden by other settings. 89 | 90 | Note: In production-firmware, this field is read-only. 91 | rssi: 92 | example: 104 93 | type: number 94 | readOnly: true 95 | description: | 96 | RSSI as measured at current frequency, if in an RX mode. 97 | LiveLog: 98 | type: object 99 | properties: 100 | ip: 101 | example: "192.168.1.102" 102 | type: string 103 | port: 104 | example: 1337 105 | type: number 106 | BeauDb: 107 | type: object 108 | properties: 109 | live_records: 110 | example: 20 111 | type: string 112 | description: | 113 | Number of "live" records in the database. 114 | dead_records: 115 | example: 33 116 | type: string 117 | description: | 118 | Number of "dead" records in the database. 119 | These are records marked for deletion but which have not yet been 120 | erased through compaction. 121 | empty_pages: 122 | example: 0 123 | type: string 124 | description: | 125 | Number of pages which are entirely empty. 126 | This will be large initially, then reduce to 1 (the swap page). 127 | This may be 0 for older databases and in case of power loss 128 | during compaction, however it should go back to 1 after the next 129 | compaction as a new swap page results. 130 | total_dead: 131 | example: 110824 132 | type: string 133 | description: | 134 | Total amount of memory used by dead records. 135 | Dead records are counted as free space. 136 | total_free: 137 | example: 900421 138 | type: string 139 | description: | 140 | Total free space in database (including dead space), in bytes. 141 | max_free: 142 | example: 4002 143 | type: string 144 | description: | 145 | Maximum freespace of any page, in bytes, 146 | excepting the swap page (a single empty page kept to permit 147 | compaction). 148 | In current (v2.6) implementation, this is the typical limit on 149 | the largest record which can be written to the database. 150 | total_head: 151 | example: 900421 152 | type: string 153 | description: | 154 | Total free space in database (including dead space), in bytes. 155 | min_head: 156 | example: 15 157 | type: string 158 | description: | 159 | Minimum amount of headroom of any page, in bytes. 160 | This dictates the smallest record which could result in a compaction. 161 | compactions: 162 | example: 1 163 | type: string 164 | description: | 165 | Number of compactions performed since boot. 166 | size: 167 | example: 1048576 168 | type: string 169 | description: | 170 | Total size of database, in bytes. 171 | page_size: 172 | example: 4096 173 | type: string 174 | description: | 175 | Size of each page, in bytes. 176 | dirty: 177 | example: false 178 | type: boolean 179 | description: | 180 | Indicates that a write failed and database is in an inconsistant state. -------------------------------------------------------------------------------- /signal/paths.yaml: -------------------------------------------------------------------------------- 1 | SignalsPath: 2 | parameters: 3 | - in: path 4 | name: device_id 5 | required: true 6 | schema: 7 | type: string 8 | - in: path 9 | name: command_id 10 | required: true 11 | schema: 12 | type: string 13 | get: 14 | $ref: ../commands/paths.yaml#/SignalGet 15 | put: 16 | $ref: ../commands/paths.yaml#/SignalPut 17 | patch: 18 | $ref: ../commands/paths.yaml#/SignalPatch 19 | delete: 20 | $ref: ../commands/paths.yaml#/SignalDelete 21 | 22 | SignalTxPath: 23 | parameters: 24 | - in: path 25 | name: device_id 26 | required: true 27 | schema: 28 | type: string 29 | - in: path 30 | name: command_id 31 | required: true 32 | schema: 33 | type: string 34 | put: 35 | $ref: ../commands/paths.yaml#/TxPut 36 | 37 | SignalRssiPath: 38 | get: 39 | $ref: ../signal/paths.yaml#/RssiGet 40 | 41 | SignalScanPath: 42 | put: 43 | $ref: ../signal/paths.yaml#/ScanPut 44 | get: 45 | $ref: ../signal/paths.yaml#/ScanGet 46 | delete: 47 | $ref: ../signal/paths.yaml#/ScanDelete 48 | TxPath: 49 | delete: 50 | $ref: ../signal/paths.yaml#/TxDelete 51 | put: 52 | $ref: ../signal/paths.yaml#/TxPut 53 | 54 | SignalScanSignalPath: 55 | get: 56 | $ref: ../signal/paths.yaml#/ScanSignalGet 57 | 58 | TxPut: 59 | requestBody: 60 | content: 61 | application/json: 62 | schema: 63 | $ref: schemas.yaml#/Signal 64 | responses: 65 | '204': 66 | description: Signal transmit started 67 | '400': 68 | $ref: ../common/responses.yaml#/BadRequest 69 | '401': 70 | $ref: ../common/responses.yaml#/Unauthorized 71 | '500': 72 | $ref: ../common/responses.yaml#/InternalServerError 73 | summary: Transmit a Signal 74 | description: | 75 | Transmit an RF or IR signal from a Bond Bridge. 76 | 77 | If `use_scan` is present and true, the signal recorded by the previous scan 78 | will be used, and all other fields will be ignored 79 | tags: 80 | - Transmit 81 | TxDelete: 82 | responses: 83 | '204': 84 | description: Signal transmission canceled 85 | '400': 86 | $ref: ../common/responses.yaml#/BadRequest 87 | '401': 88 | $ref: ../common/responses.yaml#/Unauthorized 89 | '404': 90 | $ref: ../common/responses.yaml#/NotFound 91 | '500': 92 | $ref: ../common/responses.yaml#/InternalServerError 93 | summary: Cancel a Transmission 94 | description: | 95 | If a Signal is being transmitted, it is immediately interrupted, 96 | and a 204 is returned. 97 | 98 | A 204 is also returned even if there was no Signal being transmitted. 99 | 100 | NOTE: Internally, this flushes the radio command queue, 101 | so any requested transmissions which were queued 102 | waiting for an earlier tranmission to complete will also be canceled. 103 | This also cancels any queued scans, but does not cancel a scan already in progress. 104 | 105 | tags: 106 | - Transmit 107 | ScanPut: 108 | requestBody: 109 | content: 110 | application/json: 111 | schema: 112 | $ref: schemas.yaml#/Scan 113 | responses: 114 | '201': 115 | description: Signal transmit started 116 | '400': 117 | $ref: ../common/responses.yaml#/BadRequest 118 | '401': 119 | $ref: ../common/responses.yaml#/Unauthorized 120 | '500': 121 | $ref: ../common/responses.yaml#/InternalServerError 122 | summary: Start a Scan 123 | description: | 124 | Start scanning for RF/IR signals. 125 | tags: 126 | - Scan 127 | ScanGet: 128 | responses: 129 | '200': 130 | description: Scan info returned 131 | content: 132 | application/json: 133 | schema: 134 | $ref: schemas.yaml#/Scan 135 | '401': 136 | $ref: ../common/responses.yaml#/Unauthorized 137 | '404': 138 | $ref: ../common/responses.yaml#/NotFound 139 | '500': 140 | $ref: ../common/responses.yaml#/InternalServerError 141 | summary: Check scan progress 142 | description: | 143 | Get information about a scan in progress, 144 | or the last completed scan. 145 | tags: 146 | - Scan 147 | ScanDelete: 148 | responses: 149 | '204': 150 | description: Scan canceled 151 | '401': 152 | $ref: ../common/responses.yaml#/Unauthorized 153 | '404': 154 | $ref: ../common/responses.yaml#/NotFound 155 | '500': 156 | $ref: ../common/responses.yaml#/InternalServerError 157 | summary: Cancel a Scan 158 | description: | 159 | Immediately stop scanning, and delete results. 160 | tags: 161 | - Scan 162 | ScanSignalGet: 163 | responses: 164 | '200': 165 | description: Signal resulting from scan 166 | content: 167 | application/json: 168 | schema: 169 | $ref: schemas.yaml#/Signal 170 | '401': 171 | $ref: ../common/responses.yaml#/Unauthorized 172 | '404': 173 | $ref: ../common/responses.yaml#/NotFound 174 | '500': 175 | $ref: ../common/responses.yaml#/InternalServerError 176 | summary: Get Signal from a Scan 177 | description: | 178 | Get the signal resulting from the most recent scan 179 | tags: 180 | - Scan Result 181 | RssiGet: 182 | responses: 183 | '200': 184 | description: Receive Signal Strength 185 | content: 186 | application/json: 187 | schema: 188 | $ref: schemas.yaml#/Rssi 189 | '401': 190 | $ref: ../common/responses.yaml#/Unauthorized 191 | '404': 192 | $ref: ../common/responses.yaml#/NotFound 193 | '500': 194 | $ref: ../common/responses.yaml#/InternalServerError 195 | summary: Get Receive Signal Strength Indication (RSSI) 196 | description: | 197 | Sweeps over the frequency range supported by the product, 198 | and returns a list of frequency-rssi ordered pairs. 199 | 200 | This is useful for determining tuning of antennas. 201 | tags: 202 | - Rssi 203 | -------------------------------------------------------------------------------- /common/paths.yaml: -------------------------------------------------------------------------------- 1 | /v2/devices: 2 | get: 3 | $ref: ../devices/paths.yaml#/GetList 4 | post: 5 | $ref: ../devices/paths.yaml#/Post 6 | /v2/devices/{device_id}: 7 | delete: 8 | $ref: ../devices/paths.yaml#/Delete 9 | get: 10 | $ref: ../devices/paths.yaml#/Get 11 | parameters: 12 | - in: path 13 | name: device_id 14 | required: true 15 | schema: 16 | type: number 17 | patch: 18 | $ref: ../devices/paths.yaml#/Patch 19 | /v2/devices/{device_id}/state: 20 | get: 21 | $ref: ../devices/paths.yaml#/GetState 22 | patch: 23 | $ref: ../devices/paths.yaml#/PatchState 24 | parameters: 25 | - in: path 26 | name: device_id 27 | required: true 28 | schema: 29 | type: number 30 | /v2/devices/{device_id}/actions/{action_name}: 31 | put: 32 | $ref: ../actions/paths.yaml#/Put 33 | parameters: 34 | - in: path 35 | name: action_name 36 | required: true 37 | schema: 38 | type: number 39 | - in: path 40 | name: device_id 41 | required: true 42 | schema: 43 | type: number 44 | /v2/devices/{device_id}/commands: 45 | get: 46 | $ref: ../commands/paths.yaml#/GetList 47 | post: 48 | $ref: ../commands/paths.yaml#/Post 49 | /v2/devices/{device_id}/commands/{command_id}: 50 | get: 51 | $ref: ../commands/paths.yaml#/Get 52 | patch: 53 | $ref: ../commands/paths.yaml#/Patch 54 | delete: 55 | $ref: ../commands/paths.yaml#/Delete 56 | /v2/devices/{device_id}/commands/{command_id}/signal: 57 | get: 58 | $ref: ../commands/paths.yaml#/SignalGet 59 | put: 60 | $ref: ../commands/paths.yaml#/SignalPut 61 | patch: 62 | $ref: ../commands/paths.yaml#/SignalPatch 63 | delete: 64 | $ref: ../commands/paths.yaml#/SignalDelete 65 | /v2/devices/{device_id}/addr: 66 | get: 67 | $ref: ../commands/paths.yaml#/GetRemoteAddr 68 | patch: 69 | $ref: ../commands/paths.yaml#/PatchRemoteAddr 70 | delete: 71 | $ref: ../commands/paths.yaml#/DeleteRemoteAddr 72 | /v2/devices/{device_id}/commands/{command_id}/tx: 73 | put: 74 | $ref: ../commands/paths.yaml#/TxPut 75 | /v2/devices/{device_id}/skeds: 76 | get: 77 | $ref: ../skeds/paths.yaml#/GetList 78 | post: 79 | $ref: ../skeds/paths.yaml#/Post 80 | /v2/devices/{device_id}/skeds/{sked_id}: 81 | get: 82 | $ref: ../skeds/paths.yaml#/Get 83 | patch: 84 | $ref: ../skeds/paths.yaml#/Patch 85 | delete: 86 | $ref: ../skeds/paths.yaml#/Delete 87 | /v2/bridge: 88 | get: 89 | $ref: ../devices/paths.yaml#/GetBridge 90 | patch: 91 | $ref: ../devices/paths.yaml#/PatchBridge 92 | delete: 93 | $ref: ../devices/paths.yaml#/DeleteBridge 94 | /v2/signal/tx: 95 | delete: 96 | $ref: ../signal/paths.yaml#/TxDelete 97 | put: 98 | $ref: ../signal/paths.yaml#/TxPut 99 | /v2/signal/rssi: 100 | get: 101 | $ref: ../signal/paths.yaml#/RssiGet 102 | /v2/signal/scan: 103 | put: 104 | $ref: ../signal/paths.yaml#/ScanPut 105 | get: 106 | $ref: ../signal/paths.yaml#/ScanGet 107 | delete: 108 | $ref: ../signal/paths.yaml#/ScanDelete 109 | /v2/signal/scan/signal: 110 | get: 111 | $ref: ../signal/paths.yaml#/ScanSignalGet 112 | #/v2: 113 | # delete: 114 | # $ref: ../bonds/paths.yaml#/Delete 115 | # get: 116 | # $ref: ../bonds/paths.yaml#/Get 117 | # patch: 118 | # $ref: ../bonds/paths.yaml#/Patch 119 | /users: 120 | get: 121 | $ref: ../users/paths.yaml#/GetList 122 | post: 123 | $ref: ../users/paths.yaml#/Post 124 | /users/{user_id}: 125 | delete: 126 | $ref: ../users/paths.yaml#/Delete 127 | get: 128 | $ref: ../users/paths.yaml#/Get 129 | parameters: 130 | - in: path 131 | name: user_id 132 | required: true 133 | schema: 134 | type: number 135 | patch: 136 | $ref: ../users/paths.yaml#/Patch 137 | /v2/sys/wifi/sta: 138 | get: 139 | $ref: ../network/paths.yaml#/StaGet 140 | put: 141 | $ref: ../network/paths.yaml#/StaPut 142 | delete: 143 | $ref: ../network/paths.yaml#/StaDelete 144 | /v2/sys/wifi/scan: 145 | get: 146 | $ref: ../network/paths.yaml#/ScanGet 147 | /v2/sys/wifi/watchdog: 148 | get: 149 | $ref: ../network/paths.yaml#/WatchdogGet 150 | patch: 151 | $ref: ../network/paths.yaml#/WatchdogPatch 152 | /v2/sys/time: 153 | get: 154 | $ref: ../sys/paths.yaml#/TimeGet 155 | patch: 156 | $ref: ../sys/paths.yaml#/TimePatch 157 | delete: 158 | $ref: ../sys/paths.yaml#/TimeDelete 159 | /v2/sys/power: 160 | get: 161 | $ref: ../sys/paths.yaml#/PowerGet 162 | /v2/sys/upgrade: 163 | get: 164 | $ref: ../firmware/paths.yaml#/Get 165 | put: 166 | $ref: ../firmware/paths.yaml#/Put 167 | delete: 168 | $ref: ../firmware/paths.yaml#/Delete 169 | /v2/sys/version: 170 | get: 171 | $ref: ../firmware/paths.yaml#/VersionGet 172 | /v2/sys/free: 173 | get: 174 | $ref: ../firmware/paths.yaml#/FreeGet 175 | /v2/sys/reset: 176 | put: 177 | $ref: ../firmware/paths.yaml#/ResetPut 178 | /v2/sys/reboot: 179 | put: 180 | $ref: ../firmware/paths.yaml#/RebootPut 181 | /v2/sys/log: 182 | get: 183 | $ref: ../firmware/paths.yaml#/LogGet 184 | put: 185 | $ref: ../firmware/paths.yaml#/LogPut 186 | delete: 187 | $ref: ../firmware/paths.yaml#/LogDelete 188 | /v2/token: 189 | get: 190 | $ref: ../token/paths.yaml#/Get 191 | put: 192 | $ref: ../token/paths.yaml#/Patch 193 | /v2/api/mqtt: 194 | get: 195 | $ref: ../api/paths.yaml#/MqttGet 196 | patch: 197 | $ref: ../api/paths.yaml#/MqttPatch 198 | delete: 199 | $ref: ../api/paths.yaml#/MqttDelete 200 | /v2/api/bpup: 201 | get: 202 | $ref: ../api/paths.yaml#/BPUPGet 203 | patch: 204 | $ref: ../api/paths.yaml#/BPUPPatch 205 | delete: 206 | $ref: ../api/paths.yaml#/BPUPDelete 207 | /v2/api/bhk: 208 | get: 209 | $ref: ../api/paths.yaml#/BHKGet 210 | patch: 211 | $ref: ../api/paths.yaml#/BHKPatch 212 | delete: 213 | $ref: ../api/paths.yaml#/BHKDelete 214 | /v2/debug/wifi: 215 | get: 216 | $ref: ../debug/paths.yaml#/WifiGet 217 | patch: 218 | $ref: ../debug/paths.yaml#/WifiPatch 219 | /v2/debug/leds: 220 | get: 221 | $ref: ../debug/paths.yaml#/LedsGet 222 | patch: 223 | $ref: ../debug/paths.yaml#/LedsPatch 224 | /v2/debug/si446x: 225 | get: 226 | $ref: ../debug/paths.yaml#/FccGet 227 | patch: 228 | $ref: ../debug/paths.yaml#/FccPatch 229 | /v2/debug/livelog: 230 | get: 231 | $ref: ../debug/paths.yaml#/LiveLogGet 232 | put: 233 | $ref: ../debug/paths.yaml#/LiveLogPut 234 | delete: 235 | $ref: ../debug/paths.yaml#/LiveLogDelete 236 | /v2/debug/beau/db: 237 | get: 238 | $ref: ../debug/paths.yaml#/BeauDbGet 239 | -------------------------------------------------------------------------------- /scenes/paths.yaml: -------------------------------------------------------------------------------- 1 | ScenesPath: 2 | get: 3 | description: | 4 | Returns a list of Scene IDs and the corresponding Scene hashes. 5 | The hashes change if any part of the Scene (its name, state, type, etc.) 6 | has changed. The hash is not updated if underlying Actors (Devices and/or Groups) are updated 7 | in a way which does not effect the Scene state or type. 8 | 9 | Scenes are supported on Bridges and on Smart by Bond. 10 | Scenes may span multiple Bonds (Bridges and SBB devices) by using the same 11 | Scene ID on each Bond. See the introductory section "Groups and Scenes". 12 | responses: 13 | '200': 14 | content: 15 | application/json: 16 | schema: 17 | $ref: schemas.yaml#/SceneList 18 | description: List Scenes 19 | '401': 20 | $ref: ../common/responses.yaml#/Unauthorized 21 | '500': 22 | $ref: ../common/responses.yaml#/InternalServerError 23 | security: 24 | - OAuth: ["oauth2"] 25 | summary: List your Scenes 26 | tags: 27 | - Scenes 28 | post: 29 | requestBody: 30 | content: 31 | application/json: 32 | schema: 33 | $ref: ../scenes/schemas.yaml#/Scene 34 | responses: 35 | '201': 36 | $ref: ../common/responses.yaml#/Created 37 | '400': 38 | $ref: ../common/responses.yaml#/BadRequest 39 | '401': 40 | $ref: ../common/responses.yaml#/Unauthorized 41 | '409': 42 | $ref: ../common/responses.yaml#/Conflict 43 | '500': 44 | $ref: ../common/responses.yaml#/InternalServerError 45 | summary: Create new Scene 46 | description: | 47 | For the creation of a Scene distributed across multiple Bonds, 48 | clients should provide a 64-bit ID for the Scene and provide that 49 | same ID in each Scene POST request in the `_id` field. See 50 | introductory section "Groups and Scenes" for detail. If the `_id` 51 | field is not provided, a random ID will be assigned as with 52 | POST requests to other enumerations. 53 | 54 | A Scene is created containing the actor IDs and actions to execute in the `actors` array. 55 | 56 | Note that `types` and `locations` fields cannot be specified when 57 | creating a Scene: these fields are calculated based on the member Devices. 58 | tags: 59 | - Scenes 60 | 61 | ScenePath: 62 | get: 63 | $ref: ../scenes/paths.yaml#/Get 64 | parameters: 65 | - in: path 66 | name: scene_id 67 | required: true 68 | schema: 69 | type: number 70 | patch: 71 | $ref: ../scenes/paths.yaml#/Patch 72 | delete: 73 | $ref: ../scenes/paths.yaml#/Delete 74 | 75 | RunPath: 76 | put: 77 | $ref: ../scenes/paths.yaml#/Run 78 | parameters: 79 | - in: path 80 | name: scene_id 81 | required: true 82 | schema: 83 | type: number 84 | 85 | GetList: 86 | responses: 87 | '200': 88 | content: 89 | application/json: 90 | schema: 91 | $ref: schemas.yaml#/SceneList 92 | description: List active Scenes 93 | '401': 94 | $ref: ../common/responses.yaml#/Unauthorized 95 | '500': 96 | $ref: ../common/responses.yaml#/InternalServerError 97 | security: 98 | - OAuth: ["oauth2"] 99 | summary: List your Scenes 100 | tags: 101 | - Scenes 102 | Post: 103 | requestBody: 104 | content: 105 | application/json: 106 | schema: 107 | $ref: schemas.yaml#/Scene 108 | responses: 109 | '201': 110 | $ref: ../common/responses.yaml#/Created 111 | '400': 112 | $ref: ../common/responses.yaml#/BadRequest 113 | '401': 114 | $ref: ../common/responses.yaml#/Unauthorized 115 | '409': 116 | $ref: ../common/responses.yaml#/Conflict 117 | '500': 118 | $ref: ../common/responses.yaml#/InternalServerError 119 | summary: Create new Scene 120 | tags: 121 | - Scenes 122 | Get: 123 | description: | 124 | Scenes are a set of actions to run on Devices and/or Groups 125 | with a single request. 126 | responses: 127 | '200': 128 | content: 129 | application/json: 130 | schema: 131 | $ref: schemas.yaml#/Scene 132 | description: Get Scene 133 | '401': 134 | $ref: ../common/responses.yaml#/Unauthorized 135 | '404': 136 | $ref: ../common/responses.yaml#/NotFound 137 | '500': 138 | $ref: ../common/responses.yaml#/InternalServerError 139 | security: 140 | - OAuth: ["oauth2"] 141 | summary: Get Scene 142 | tags: 143 | - Scenes 144 | Patch: 145 | requestBody: 146 | content: 147 | application/json: 148 | schema: 149 | $ref: schemas.yaml#/Scene 150 | responses: 151 | '200': 152 | content: 153 | application/json: 154 | schema: 155 | $ref: schemas.yaml#/Scene 156 | description: Change Scene field 157 | '401': 158 | $ref: ../common/responses.yaml#/Unauthorized 159 | '404': 160 | $ref: ../common/responses.yaml#/NotFound 161 | '500': 162 | $ref: ../common/responses.yaml#/InternalServerError 163 | security: 164 | - BasicAuth: [] 165 | summary: Change Scene field 166 | description: | 167 | The `actors` list may be PATCHed to perform a bulk change to the membership in the scene. 168 | 169 | If the `actors` list is PATCHed to empty, the scene shard will vanish. 170 | That is, the scene shard will be removed from the scenes enumeration. 171 | The scenes enumeration will be sent as a gratuitous GET response. 172 | tags: 173 | - Scenes 174 | Delete: 175 | responses: 176 | '204': 177 | description: Delete Scene 178 | '401': 179 | $ref: ../common/responses.yaml#/Unauthorized 180 | '404': 181 | $ref: ../common/responses.yaml#/NotFound 182 | '500': 183 | $ref: ../common/responses.yaml#/InternalServerError 184 | security: 185 | - BasicAuth: [] 186 | summary: Delete Scene 187 | description: | 188 | The entire Scene is deleted. 189 | tags: 190 | - Scenes 191 | 192 | Run: 193 | description: | 194 | Execute specified Scene. 195 | Each actor will be executed individually. 196 | 197 | For shade hembar alignment on supported technologies, 198 | please use a Group as an actor in the Scene. 199 | responses: 200 | '204': 201 | description: Scene executed 202 | '401': 203 | $ref: ../common/responses.yaml#/Unauthorized 204 | '404': 205 | $ref: ../common/responses.yaml#/NotFound 206 | '500': 207 | $ref: ../common/responses.yaml#/InternalServerError 208 | security: 209 | - OAuth: ["oauth2"] 210 | summary: Execute Scene 211 | tags: 212 | - Scenes 213 | -------------------------------------------------------------------------------- /network/schemas.yaml: -------------------------------------------------------------------------------- 1 | Watchdog: 2 | properties: 3 | rwdg_disable: 4 | example: false 5 | type: boolean 6 | description: | 7 | - `true`: disable Bond Cloud watchdog 8 | - `false`: enable Bond Cloud watchdog (default) 9 | 10 | If enabled, Bond will reboot if not connected to Bond Cloud 11 | within first 10 minutes of boot, or if disconnected for 3 minutes. 12 | 13 | Watchdog does not run if Bond is in Wi-Fi Setup mode. 14 | 15 | NOTE: Any communication with the Bond over the HTTP transport 16 | will reset the timer as if the Bond were connected to the cloud. 17 | rwdg_timer_ms: 18 | example: 60000 19 | type: number 20 | readOnly: true 21 | description: | 22 | Number of milliseconds left on watchdog timer before Bond will reboot 23 | by itself to attempt to reconnect to the Bond cloud. 24 | NOTE: If `rwdg_disable` is true, then Bond will not actually reboot, 25 | but timer will continue to tick down. 26 | Sta: 27 | properties: 28 | status: 29 | example: 2 30 | type: number 31 | description: | 32 | Indication of whether the Wi-Fi settings have been successful: 33 | - -4 = Wi-Fi not configured 34 | - -3 = disabled because Ethernet is selected 35 | - -2 = authentication failure 36 | - -1 = network not found 37 | - 0 = attempting to connect 38 | - 1 = connected, but no IP address yet 39 | - 2 = connected with IP address assigned 40 | - 3 = connected to cloud (MQTT) 41 | ssid: 42 | example: bGlua3N5cw== 43 | type: string 44 | nullable: true 45 | description: Can be `null` if it's not set. 46 | bssid: 47 | example: "001122334455" 48 | type: string 49 | nullable: true 50 | description: Can be `null` if it's not set. 51 | bssid_set: 52 | readOnly: true 53 | example: true 54 | type: boolean 55 | mac: 56 | example: '30aea48fa8e8' 57 | type: string 58 | readOnly: true 59 | static_ip_set: 60 | example: false 61 | type: boolean 62 | description: | 63 | [changed in v2.16.2] 64 | If true on write, the ip, gw, netmask fields are required. 65 | If false on write, the ip, gw, netmask fields will be ignored 66 | and DHCP configured. 67 | ip: 68 | example: '192.168.1.42' 69 | type: string 70 | nullable: true 71 | description: Can be `null` if it's not connected. 72 | gw: 73 | example: '192.168.1.1' 74 | type: string 75 | nullable: true 76 | description: Can be `null` if it's not connected. 77 | netmask: 78 | example: '255.255.255.0' 79 | type: string 80 | nullable: true 81 | description: Can be `null` if it's not connected. 82 | dns_set: 83 | example: true 84 | type: boolean 85 | description: | 86 | [changed in v2.16.2] 87 | If true on write, the dns and dns_alt fields are required. 88 | If false on write, the dns and dns_alt fields will be ignored 89 | and the default dns behavior will take effect. 90 | dns: 91 | example: '8.8.8.8' 92 | type: string 93 | nullable: true 94 | description: Can be `null` if it's not connected. 95 | dns_alt: 96 | example: '8.8.4.4' 97 | type: string 98 | nullable: true 99 | description: Can be `null` if it's not connected. 100 | password: 101 | example: cGFzc3dvcmQ= 102 | format: password 103 | type: string 104 | nullable: true 105 | writeOnly: true 106 | description: Can be `null` if it's not set. 107 | Eth: 108 | properties: 109 | status: 110 | example: 2 111 | type: number 112 | description: | 113 | - 0 = no link 114 | - 1 = link, but no IP address yet 115 | - 2 = link and IP address assigned 116 | - 3 = connected to cloud (MQTT) 117 | mac: 118 | example: '30aea48fa8e8' 119 | type: string 120 | readOnly: true 121 | static_ip_set: 122 | example: false 123 | type: boolean 124 | description: | 125 | [changed in v2.16.2] 126 | If true on write, the ip, gw, netmask fields are required. 127 | If false on write, the ip, gw, netmask fields will be ignored 128 | and DHCP configured. 129 | ip: 130 | example: '192.168.1.42' 131 | type: string 132 | gw: 133 | example: '192.168.1.1' 134 | type: string 135 | netmask: 136 | example: '255.255.255.0' 137 | type: string 138 | dns_set: 139 | example: true 140 | type: boolean 141 | description: | 142 | [changed in v2.16.2] 143 | If true on write, the dns and dns_alt fields are required. 144 | If false on write, the dns and dns_alt fields will be ignored 145 | and the default dns behavior will take effect. 146 | dns: 147 | example: '8.8.8.8' 148 | type: string 149 | dns_alt: 150 | example: '8.8.4.4' 151 | type: string 152 | Scan: 153 | example: 154 | hidden_requires_bssid: true 155 | format: 156 | - ssid 157 | - bssid 158 | - auth 159 | - ch 160 | - signal 161 | results: 162 | - - REIyQzk1 163 | - 00A423DB2C9D 164 | - 4 165 | - 1 166 | - 90 167 | - - b2xpYnJhIGFpcnBvcnQgMQ== 168 | - 4C3275C649C4 169 | - 3 170 | - 11 171 | - 74 172 | - - UGxheVNpZ2h0XzVH 173 | - 003E5D921274 174 | - 4 175 | - 6 176 | - 73 177 | - - b2xpYnJhIG1pZmkgMw== 178 | - 101331C514C7 179 | - 3 180 | - 6 181 | - 61 182 | - - S0VFQk9YIFcxNTBOUg== 183 | - D8EB97B1B322 184 | - 0 185 | - 11 186 | - 60 187 | - - VmVyaXpvbi1NQkhBMTAtMTRDNy1ndWVzdA== 188 | - 121331C514C8 189 | - 3 190 | - 6 191 | - 60 192 | - - b2xpYnJhIGFpcnBvcnQgMQ== 193 | - 9801A7E7ABD4 194 | - 3 195 | - 6 196 | - 57 197 | - - b3B0aW11bXdpZmlfUGFzc3BvaW50 198 | - E00EDA137575 199 | - 5 200 | - 1 201 | - 39 202 | - - NkMxNDYw 203 | - 0072826C1468 204 | - 4 205 | - 1 206 | - 36 207 | - - UkRMRiBXaS1GaSBOZXR3b3Jr 208 | - 881FA13633AA 209 | - 3 210 | - 1 211 | - 33 212 | - - SFAtUHJpbnQtRjEtT2ZmaWNlamV0IFBybyA4NjAw 213 | - 28924ABF85F1 214 | - 3 215 | - 6 216 | - 30 217 | - - Wm9oYXIgYWlycG9ydA== 218 | - 00F76FCDE89C 219 | - 3 220 | - 11 221 | - 28 222 | - - aWM= 223 | - 149182C06087 224 | - 3 225 | - 1 226 | - 26 227 | - - bWVkaWFsaW5r 228 | - 14358B0B1920 229 | - 2 230 | - 1 231 | - 24 232 | -------------------------------------------------------------------------------- /commands/paths.yaml: -------------------------------------------------------------------------------- 1 | CommandsPath: 2 | parameters: 3 | - in: path 4 | name: device_id 5 | required: true 6 | schema: 7 | type: string 8 | get: 9 | $ref: ../commands/paths.yaml#/GetList 10 | post: 11 | $ref: ../commands/paths.yaml#/Post 12 | 13 | CommandPath: 14 | parameters: 15 | - in: path 16 | name: device_id 17 | required: true 18 | schema: 19 | type: string 20 | - in: path 21 | name: command_id 22 | required: true 23 | schema: 24 | type: string 25 | get: 26 | $ref: ../commands/paths.yaml#/Get 27 | patch: 28 | $ref: ../commands/paths.yaml#/Patch 29 | delete: 30 | $ref: ../commands/paths.yaml#/Delete 31 | 32 | Post: 33 | requestBody: 34 | content: 35 | application/json: 36 | schema: 37 | $ref: schemas.yaml#/Command 38 | responses: 39 | '201': 40 | $ref: ../common/responses.yaml#/Created 41 | '400': 42 | $ref: ../common/responses.yaml#/BadRequest 43 | '401': 44 | $ref: ../common/responses.yaml#/Unauthorized 45 | '500': 46 | $ref: ../common/responses.yaml#/InternalServerError 47 | summary: Create new Command 48 | description: | 49 | Creates a Command under a specific Device. 50 | tags: 51 | - Device Commands 52 | Patch: 53 | requestBody: 54 | content: 55 | application/json: 56 | schema: 57 | $ref: schemas.yaml#/Command 58 | responses: 59 | '200': 60 | description: Command modified 61 | '400': 62 | $ref: ../common/responses.yaml#/BadRequest 63 | '401': 64 | $ref: ../common/responses.yaml#/Unauthorized 65 | '404': 66 | $ref: ../common/responses.yaml#/NotFound 67 | '500': 68 | $ref: ../common/responses.yaml#/InternalServerError 69 | summary: Modify an existing Command 70 | description: | 71 | Modifies any fields of an existing Command. 72 | tags: 73 | - Device Commands 74 | GetList: 75 | description: | 76 | Returns a list of command IDs and the corresponding command hashes. 77 | Please see the "Hash Tree" documentation for an explanation of hashes. 78 | responses: 79 | '200': 80 | content: 81 | application/json: 82 | schema: 83 | $ref: schemas.yaml#/CommandList 84 | description: Command list returned 85 | '401': 86 | $ref: ../common/responses.yaml#/Unauthorized 87 | '404': 88 | $ref: ../common/responses.yaml#/NotFound 89 | '500': 90 | $ref: ../common/responses.yaml#/InternalServerError 91 | summary: Get list of Commands 92 | tags: 93 | - Device Commands 94 | Get: 95 | responses: 96 | '200': 97 | content: 98 | application/json: 99 | schema: 100 | $ref: schemas.yaml#/Command 101 | description: Command object returned 102 | '401': 103 | $ref: ../common/responses.yaml#/Unauthorized 104 | '404': 105 | $ref: ../common/responses.yaml#/NotFound 106 | '500': 107 | $ref: ../common/responses.yaml#/InternalServerError 108 | summary: Get specific Command 109 | description: | 110 | Get information about a Command. 111 | tags: 112 | - Device Commands 113 | Delete: 114 | responses: 115 | '204': 116 | description: Command deleted 117 | '401': 118 | $ref: ../common/responses.yaml#/Unauthorized 119 | '404': 120 | $ref: ../common/responses.yaml#/NotFound 121 | '500': 122 | $ref: ../common/responses.yaml#/InternalServerError 123 | summary: Delete a Command 124 | description: | 125 | Deletes specified Command. 126 | 127 | Any associated Signal will be implicitly deleted. 128 | tags: 129 | - Device Commands 130 | SignalPut: 131 | requestBody: 132 | content: 133 | application/json: 134 | schema: 135 | $ref: ../signal/schemas.yaml#/Signal 136 | responses: 137 | '200': 138 | description: Signal set 139 | '400': 140 | $ref: ../common/responses.yaml#/BadRequest 141 | '401': 142 | $ref: ../common/responses.yaml#/Unauthorized 143 | '500': 144 | $ref: ../common/responses.yaml#/InternalServerError 145 | summary: Store new Signal 146 | description: | 147 | Creates a Signal associated with this Command. 148 | tags: 149 | - Device Command Signal 150 | SignalPatch: 151 | requestBody: 152 | content: 153 | application/json: 154 | schema: 155 | $ref: ../signal/schemas.yaml#/Signal 156 | responses: 157 | '200': 158 | description: Signal modified 159 | '400': 160 | $ref: ../common/responses.yaml#/BadRequest 161 | '401': 162 | $ref: ../common/responses.yaml#/Unauthorized 163 | '404': 164 | $ref: ../common/responses.yaml#/NotFound 165 | '500': 166 | $ref: ../common/responses.yaml#/InternalServerError 167 | summary: Modify an existing Signal 168 | description: | 169 | Modifies any fields of an existing Signal. 170 | tags: 171 | - Device Command Signal 172 | SignalGet: 173 | responses: 174 | '200': 175 | description: Signal returned 176 | content: 177 | application/json: 178 | schema: 179 | $ref: ../signal/schemas.yaml#/Signal 180 | '401': 181 | $ref: ../common/responses.yaml#/Unauthorized 182 | '404': 183 | $ref: ../common/responses.yaml#/NotFound 184 | '500': 185 | $ref: ../common/responses.yaml#/InternalServerError 186 | summary: Get Signal associated with Command 187 | description: | 188 | Get signal associated with this command. 189 | tags: 190 | - Device Command Signal 191 | SignalDelete: 192 | responses: 193 | '204': 194 | description: Signal deleted 195 | '401': 196 | $ref: ../common/responses.yaml#/Unauthorized 197 | '404': 198 | $ref: ../common/responses.yaml#/NotFound 199 | '500': 200 | $ref: ../common/responses.yaml#/InternalServerError 201 | summary: Delete a Signal 202 | description: | 203 | Deletes specified Signal. 204 | 205 | Attempts to use the corresponding Actions will return 500 until 206 | a new Signal is associated with this Command or the Command is deleted. 207 | tags: 208 | - Device Command Signal 209 | TxPut: 210 | requestBody: 211 | content: 212 | application/json: 213 | example: 214 | {} 215 | responses: 216 | '204': 217 | description: Command transmitted 218 | '400': 219 | $ref: ../common/responses.yaml#/BadRequest 220 | '401': 221 | $ref: ../common/responses.yaml#/Unauthorized 222 | '500': 223 | $ref: ../common/responses.yaml#/InternalServerError 224 | summary: Transmit Command 225 | description: | 226 | Transmits the signal associated with the command. 227 | 228 | Note: This does NOT execute the associated Action, 229 | but rather just transmits the signal as if it had been PUT to signal/tx, 230 | so the device state will not be updated and light gating will not be checked. 231 | tags: 232 | - Device Command Transmit 233 | -------------------------------------------------------------------------------- /weather_sensor/paths.yaml: -------------------------------------------------------------------------------- 1 | SidekicksPath: 2 | get: 3 | $ref: ../weather_sensor/paths.yaml#/GetList 4 | post: 5 | $ref: ../weather_sensor/paths.yaml#/Post 6 | 7 | WeatherSensorSidekicksPath: 8 | parameters: 9 | - in: path 10 | name: ws_id 11 | required: true 12 | schema: 13 | type: string 14 | get: 15 | $ref: ../weather_sensor/paths.yaml#/Get 16 | patch: 17 | $ref: ../weather_sensor/paths.yaml#/Patch 18 | delete: 19 | $ref: ../weather_sensor/paths.yaml#/Delete 20 | 21 | Post: 22 | requestBody: 23 | content: 24 | application/json: 25 | schema: 26 | $ref: schemas.yaml#/WeatherSensor 27 | responses: 28 | '201': 29 | $ref: ../common/responses.yaml#/Created 30 | '400': 31 | $ref: ../common/responses.yaml#/BadRequest 32 | '401': 33 | $ref: ../common/responses.yaml#/Unauthorized 34 | '500': 35 | $ref: ../common/responses.yaml#/InternalServerError 36 | summary: Add a Weather Sensor to Bridge. 37 | description: | 38 | Adds a Weather Sensor by ID. The Weather Sensor ID shall be specified by client 39 | in the `_id` field of POST request body. The newly created resource 40 | can be found at `sidekicks/{ws_id}` where `ws_id` is the ID provided 41 | in `_id`. 42 | tags: 43 | - Weather Sensor 44 | 45 | Patch: 46 | requestBody: 47 | content: 48 | application/json: 49 | schema: 50 | $ref: schemas.yaml#/WeatherSensor 51 | responses: 52 | '200': 53 | description: Sidekick modified 54 | '400': 55 | $ref: ../common/responses.yaml#/BadRequest 56 | '401': 57 | $ref: ../common/responses.yaml#/Unauthorized 58 | '404': 59 | $ref: ../common/responses.yaml#/NotFound 60 | '500': 61 | $ref: ../common/responses.yaml#/InternalServerError 62 | summary: Modify an existing Weather Sensor metadata and links 63 | description: | 64 | Modifies metadata and/or links of a Weather Sensor. 65 | Please, refer to Sidekick explanation of linking/unlinking of actions. 66 | tags: 67 | - Weather Sensor 68 | 69 | Get: 70 | responses: 71 | '200': 72 | content: 73 | application/json: 74 | schema: 75 | $ref: schemas.yaml#/WeatherSensor 76 | description: Weather Sensor object returned 77 | '401': 78 | $ref: ../common/responses.yaml#/Unauthorized 79 | '404': 80 | $ref: ../common/responses.yaml#/NotFound 81 | '500': 82 | $ref: ../common/responses.yaml#/InternalServerError 83 | summary: Get specific Weather Sensor 84 | description: | 85 | Get information about a Weather Sensor. 86 | 87 | In the Bond architecture, all Bond products 88 | capable of commanding devices through the Bridge are 89 | considered different kinds of Sidekicks. 90 | This is why the Weather Sensor appears in the `/sidekicks/{ws_id}` tree. 91 | 92 | For the Weather Sensor, devices are linked using `event_links`, 93 | where a different event number means 94 | one of the possible weather events. 95 | 96 | For a complete explanation of how patch logic works for modifying 97 | linked devices, refer to the `sidekick` documentation. 98 | tags: 99 | - Weather Sensor 100 | 101 | Delete: 102 | responses: 103 | '204': 104 | description: Sidekick deleted 105 | '401': 106 | $ref: ../common/responses.yaml#/Unauthorized 107 | '404': 108 | $ref: ../common/responses.yaml#/NotFound 109 | '500': 110 | $ref: ../common/responses.yaml#/InternalServerError 111 | summary: Delete a Weather Sensor 112 | description: | 113 | Deletes specified Weather Sensor. 114 | tags: 115 | - Weather Sensor 116 | 117 | PropertiesPath: 118 | get: 119 | $ref: ../weather_sensor/paths.yaml#/PropertiesGet 120 | patch: 121 | $ref: ../weather_sensor/paths.yaml#/PropertiesPatch 122 | parameters: 123 | - in: path 124 | name: ws_id 125 | required: true 126 | schema: 127 | type: string 128 | 129 | PropertiesGet: 130 | responses: 131 | '200': 132 | content: 133 | application/json: 134 | schema: 135 | $ref: schemas.yaml#/Properties 136 | description: Weather Sensor properties object 137 | '401': 138 | $ref: ../common/responses.yaml#/Unauthorized 139 | '404': 140 | $ref: ../common/responses.yaml#/NotFound 141 | '500': 142 | $ref: ../common/responses.yaml#/InternalServerError 143 | summary: Get properties of a Weather Sensor. 144 | description: | 145 | This endpoint is used to get the current properties of a Weather Sensor. 146 | tags: 147 | - Weather Sensor Properties 148 | 149 | PropertiesPatch: 150 | responses: 151 | '200': 152 | content: 153 | application/json: 154 | schema: 155 | $ref: schemas.yaml#/Properties 156 | description: Weather Sensor properties object 157 | '400': 158 | $ref: ../common/responses.yaml#/BadRequest 159 | '401': 160 | $ref: ../common/responses.yaml#/Unauthorized 161 | '404': 162 | $ref: ../common/responses.yaml#/NotFound 163 | '500': 164 | $ref: ../common/responses.yaml#/InternalServerError 165 | summary: Modify properties of a Weather Sensor. 166 | description: | 167 | This endpoint is used to modify the properties of a Weather Sensor. 168 | Use this call to modify detection thresholds and enabling/disabling features. 169 | tags: 170 | - Weather Sensor Properties 171 | 172 | StatePath: 173 | get: 174 | $ref: ../weather_sensor/paths.yaml#/StateGet 175 | parameters: 176 | - in: path 177 | name: ws_id 178 | required: true 179 | schema: 180 | type: string 181 | 182 | StateGet: 183 | responses: 184 | '200': 185 | content: 186 | application/json: 187 | schema: 188 | $ref: schemas.yaml#/State 189 | description: Get Weather Sensor state 190 | '401': 191 | $ref: ../common/responses.yaml#/Unauthorized 192 | '404': 193 | $ref: ../common/responses.yaml#/NotFound 194 | '500': 195 | $ref: ../common/responses.yaml#/InternalServerError 196 | summary: Get Weather Sensor current state 197 | description: | 198 | Get the current state of a Weather Sensor. This object 199 | includes the last measurement and flags indicating the status of the sensor. 200 | tags: 201 | - Weather Sensor State 202 | 203 | TestPath: 204 | put: 205 | $ref: ../weather_sensor/paths.yaml#/TestPut 206 | parameters: 207 | - in: path 208 | name: ws_id 209 | required: true 210 | schema: 211 | type: string 212 | 213 | TestPut: 214 | responses: 215 | '200': 216 | description: Test/Simulation of weather event requested. 217 | content: 218 | application/json: 219 | schema: 220 | type: object 221 | example: 222 | event_name: rain 223 | '400': 224 | $ref: ../common/responses.yaml#/BadRequest 225 | '401': 226 | $ref: ../common/responses.yaml#/Unauthorized 227 | '404': 228 | $ref: ../common/responses.yaml#/NotFound 229 | '500': 230 | $ref: ../common/responses.yaml#/InternalServerError 231 | summary: Test/simulate weather events, triggering linked actions. 232 | description: | 233 | Execute all linked actions for the specified event type. Usefull for 234 | simulating weather events to check if device actions are configured 235 | as expected. 236 | 237 | Object member `event_name` must be the event of interest. Allowed values are: 238 | - `wind`: for simulating the wind event. 239 | - `rain`: for simulating the rain event. 240 | - `sun_high`: for simulating the sun level event. 241 | tags: 242 | - Weather Sensor Test -------------------------------------------------------------------------------- /weather_sensor/schemas.yaml: -------------------------------------------------------------------------------- 1 | WeatherSensor: 2 | type: object 3 | properties: 4 | _id: 5 | writeOnly: true 6 | example: "WEAXX12345" 7 | type: string 8 | description: | 9 | Provided only on POST request to specify the Weather Sensor ID. 10 | name: 11 | example: My Weather Sensor 12 | type: string 13 | description: | 14 | Name of Weather Sensor on Bond Home app and suggested name for 15 | control system integrations. 16 | location: 17 | example: My garden 18 | type: string 19 | description: | 20 | Location of Weather Sensor. 21 | event_links: 22 | example: {"1":[{"device:": "xxyyzzww", "action": "TurnOn"}], "2":[{"device": "aabbccdd", "action": "SetPosition", "argument": 75}], "3":[]} 23 | type: object 24 | description: | 25 | Object describes every link between weather events from this Weather Sensor and the 26 | device, group, and scene actions which they trigger. 27 | (In future will permit specifying `group` or `scene` instead of `device`.) 28 | 29 | Each weather event maps to an event number: 30 | - `1` = Wind event: triggered when wind speed reaches configured level 31 | - `2` = Rain event: triggered when starts to rain 32 | - `3` = Sun event: triggered when sun intensity reaches configured level 33 | 34 | Each event number maps to an array, each element of which is called 35 | a "event link". Each event link has two or three fields: 36 | - `device`: which device will act in response to the weather event 37 | - `action`: action to call on device 38 | - `argument`: (optional) argument to above action, such as position percentage 39 | signal: 40 | readOnly: true 41 | example: 97 42 | type: integer 43 | description: | 44 | Signal quality indication, range 1-100. 45 | Note that, to avoid hash thrashing, 46 | changes in this signal indication do not cause 47 | an update to the endpoint hashes. Clients wishing to check 48 | signal strength must explicitly query this endpoint. 49 | battery: 50 | readOnly: true 51 | example: 80 52 | type: integer 53 | description: | 54 | Weather Sensor battery remaining in percentage, range 1-100. 55 | model: 56 | readOnly: true 57 | example: BWS-1000 58 | type: string 59 | description: | 60 | User-facing model number of Weather Sensor. 61 | type: 62 | readOnly: True 63 | example: weather_sensor 64 | type: string 65 | description: | 66 | Indicates the type of Sidekick, always return `weather_sensor`. 67 | 68 | Properties: 69 | type: object 70 | properties: 71 | feature_wind: 72 | example: True 73 | type: boolean 74 | description: | 75 | Enable or disable the wind detection functionality. 76 | feature_rain: 77 | example: True 78 | type: boolean 79 | description: | 80 | Enable or disable the rain detection functionality. 81 | feature_sun: 82 | example: True 83 | type: boolean 84 | description: | 85 | Enable or disable the sunlight intensity detection functionality. 86 | feature_wind_push: 87 | example: True 88 | type: boolean 89 | description: | 90 | Enable or disable the push notification for when the wind speed approaches the configured threshold. 91 | wind_threshold_dms: 92 | example: 85 93 | type: integer 94 | description: | 95 | Wind detection threshold in decimeters/second. 96 | sun_threshold_level: 97 | example: 5 98 | type: integer 99 | description: | 100 | Sun level threshold. From 1 (lowest intensity) to 8 (highest intensity). 101 | wind_ignore: 102 | example: True 103 | type: boolean 104 | description: | 105 | Ignore wind detections for a specified amount of time. 106 | When setting to true, requires setting `wind_ignore_expiration`. 107 | wind_ignore_expiration: 108 | example: 3600 109 | type: integer 110 | description: | 111 | Number of seconds for ignoring wind detections. 112 | 113 | State: 114 | type: object 115 | properties: 116 | status: 117 | example: triggered_wind 118 | type: string 119 | readOnly: true 120 | description: | 121 | String indicating the current status of the Weather Sensor. 122 | Possible values are: 123 | - `idle` 124 | - `triggered_wind` 125 | - `triggered_rain` 126 | - `triggered_sun_high` 127 | - `triggered_wind_manual` 128 | data_wind_speed_dms: 129 | example: 32 130 | type: integer 131 | readOnly: True 132 | description: | 133 | Last measurement of wind speed in decimeters/second. 134 | data_rain_mmh: 135 | example: 2 136 | type: integer 137 | readOnly: True 138 | description: | 139 | Last measurement of rain rate in milimeters/hour. 140 | data_sun_level: 141 | example: 6 142 | type: integer 143 | readOnly: True 144 | description: | 145 | Last measurement of sun level. 146 | data_unixtime: 147 | example: 1696479511 148 | type: integer 149 | readOnly: True 150 | description: | 151 | Unixtime of the last data measurements. 152 | is_raining: 153 | example: False 154 | type: boolean 155 | readOnly: True 156 | description: | 157 | Flag indicating if it is currently raining or not. 158 | battery_voltage_dV: 159 | example: 24 160 | type: integer 161 | readOnly: True 162 | description: | 163 | Current state of the Weather Sensor solar battery in decivolts. 164 | battery_2_voltage_dV: 165 | example: 24 166 | type: integer 167 | readOnly: True 168 | description: | 169 | Current state of the Weather Sensor backup battery (AA cells) in decivolts. 170 | battery: 171 | example: 80 172 | type: integer 173 | readOnly: True 174 | description: | 175 | Current state of the Weather Sensor solar battery in percentage, range 1-100. 176 | battery_2: 177 | example: 80 178 | type: integer 179 | readOnly: True 180 | description: | 181 | Current state of the Weather Sensor backup battery in percentage, range 1-100. 182 | status_flag_unstable: 183 | type: boolean 184 | example: false 185 | readOnly: True 186 | description: | 187 | Flag indicating if Weather Sensor data rate is lower than expected. 188 | status_flag_no_data: 189 | type: boolean 190 | example: false 191 | readOnly: True 192 | description: | 193 | Flag indicating if Weather Sensor data is missing for more than 30 minutes. 194 | status_flag_battery_low: 195 | type: boolean 196 | example: false 197 | readOnly: True 198 | description: | 199 | Flag indicating if solar battery is running low. 200 | status_flag_battery_2_low: 201 | example: True 202 | type: boolean 203 | readOnly: True 204 | description: | 205 | Flag indicating if backup battery (AA cells) is running low. 206 | status_flag_low_temperature: 207 | example: True 208 | type: boolean 209 | readOnly: True 210 | description: | 211 | Flag indicating if Weather Sensor temperature is low, recommending operation with external 12V supply. 212 | data_temperature_dc: 213 | example: 212 214 | type: integer 215 | readOnly: True 216 | description: | 217 | Last measurement of the temperature in deci-Celsius. 218 | data_humidity_percent: 219 | example: 65 220 | type: integer 221 | readOnly: True 222 | description: | 223 | Last measurement of the humidity in percentage (0 to 100). -------------------------------------------------------------------------------- /misc/smart-by-bond-fans-for-control-systems/smart-by-bond-fans-for-control-systems.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: A Guide to the Smart by Bond Ceiling Fan API for Control System Programmers 3 | author: Bond Home 4 | date: 19 Feb 2022 5 | header-includes: | 6 | \usepackage{fancyhdr} 7 | \pagestyle{fancy} 8 | ... 9 | 10 | Only a small subset of the Bond Local API (http://docs-local.appbond.com/) is required for integration of smart fans into control systems. The following is a brief self-contained guide to discovery, control, and state feedback. 11 | 12 | ## Discovery 13 | 14 | There are two discovery mechanisms. mDNS may be already supported by libraries on the control system, but is somewhat slow to resolve and overall quite complex. BPUP is a simple proprietary discovery protocol: it requires fewer system resources and resolves faster than mDNS. 15 | 16 | ### mDNS discovery 17 | 18 | Smart by Bond fans advertise their HTTP API via mDNS service `_bond._tcp`. 19 | 20 | To discover on MacOS, do: 21 | 22 | dns-sd -Z _bond._tcp . 23 | 24 | Or on Linux: 25 | 26 | avahi-browse -a | grep bond 27 | 28 | The mDNS reply contains a serial number, for example: 29 | 30 | KSMJBCE72801 31 | 32 | Note that mDNS discovery should be run with several retries to ensure that all Smart by Bond fans are discovered. 33 | 34 | 35 | ### BPUP discovery 36 | 37 | An alternative discovery technique uses a simple Bond-proprietary protocol called BPUP. Here's a quick rundown: 38 | 39 | Control system sends a broadcast UDP packet with destination port 30007 and data containing a single newline character. On a POSIX system, this can be done using: 40 | 41 | echo | socat -t1 STDIO UDP4-DATAGRAM:255.255.255.255:30007,broadcast 42 | 43 | All Smart by Bond units on the subnet will reply directly to the control system with a newline-terminated JSON object containing their serial number and firmware version. Here's example output from the above `socat` command: 44 | 45 | {"B":"PPCTAXX88799","d":0,"v":"v3.0.6-beta"} 46 | {"B":"KSMJBCE72801","d":0,"v":"v3.0.9-alpha"} 47 | {"B":"BD25020","d":0,"v":"v2.29.2.1-beta"} 48 | {"B":"TWCTAXX88792","d":0,"v":"v3.0.9-alpha"} 49 | {"B":"TWCTBXX88806","d":0,"v":"v3.0.9-alpha"} 50 | 51 | 52 | ## Check Device Type 53 | 54 | The device type may determined by querying the API. However, it is far simpler to check the first letter of the serial number. 55 | 56 | All Smart by Bond fans have serial numbers starting with `K`. 57 | 58 | 59 | ## Obtaining API Token 60 | 61 | In order to access most API endpoints, a token string is required. 62 | 63 | The token may be obtained from the Device Settings screen in the Bond Home app, or alternatively, it may be obtained automatically by instructing the user to hold the "Stop or Power" button on the fan remote control for 10 seconds while the control system queries the `token` endpoint: 64 | 65 | curl -i http://192.168.86.241/v2/token 66 | 67 | After 5 seconds of receiving the Power signal from the remote, the token will become "unlocked" and is sent in the reply: 68 | 69 | {"locked":0,"token":"2f6eaf536ae6779c",...} 70 | 71 | NOTE: The time required for holding the Power/Stop button is actually 5 seconds, but we instruct users to hold for 10 seconds to ensure they do not release too early. 72 | 73 | After the control system has memorized the token, it is recommended that it relock the token endpoint: 74 | 75 | curl -i http://192.168.86.241/v2/token -X PATCH -d '{"locked":1}' 76 | 77 | 78 | 79 | ## Determining Device Configuration 80 | 81 | To determine which features may be controlled on a Smart by Bond fan, the control system should query the `state` endpoint: 82 | 83 | 84 | curl -iH "Bond-Token: 2f6eaf536ae6779c" 85 | http://192.168.86.241/v2/devices/1/state 86 | 87 | A typical reply is: 88 | 89 | {"power":0, 90 | "speed":4, 91 | "light":0, 92 | "brightness":100, 93 | "brightness_cycle_phase":-1, 94 | "timer":0, 95 | "breeze":[0,50,50], 96 | "direction":-1, 97 | "_":"cc897346", 98 | "__":"cc897346"} 99 | 100 | A brief description of each important feature is as follows: 101 | 102 | - `power`: on/off state of fan motor 103 | - `speed`: fan motor speed (integral speed number) 104 | - `light`: on/off state of fan light 105 | - `brightness`: light brightness (percentage) 106 | - `direction`: summer (1) or winter (-1) direction of fan motor 107 | 108 | All fans will have `power` and `speed`. 109 | Some fans have no light. 110 | Others have non-dimmable lights, and so have `light` but no `brightness`. 111 | Most fans have dimmable lights, and so have both `light` and `brightness`. 112 | The `direction` feature is available on select AC fans and all DC fans. 113 | 114 | To determine the maximum fan speed, the control system must query the `properties` endpoint and check the `max_speed` variable: 115 | 116 | curl -iH "Bond-Token: 2f6eaf536ae6779c" 117 | http://192.168.86.241/v2/devices/1/properties 118 | 119 | {"max_speed":6, 120 | "feature_light":true, 121 | "feature_brightness":true, 122 | "breeze_max_speed":6, 123 | "breeze_min_speed":1, 124 | "breeze_period":30, 125 | "_":"3569eb3a", 126 | "__":"3569eb3a"} 127 | 128 | ## Fan and Light Control 129 | 130 | 131 | The fan is controlled by sending PUT requests with a JSON object as body to the desired `actions` endpoint. Certain actions require an `argument` to be specified, otherwise the JSON object will be empty. Here are the essentials: 132 | 133 | To turn the light off: 134 | 135 | curl -iH "Bond-Token: 2f6eaf536ae6779c" 136 | http://192.168.86.241/v2/devices/1/actions/TurnLightOff 137 | -X PUT -d {} 138 | 139 | 140 | To turn the light on, replace `TurnLightOff` with `TurnLightOn`. 141 | 142 | To set brightness to 42%: 143 | 144 | curl -iH "Bond-Token: 2f6eaf536ae6779c" 145 | http://192.168.86.241/v2/devices/1/actions/SetBrightness 146 | -X PUT -d '{"argument":42}' 147 | 148 | To set the fan to Speed #5: 149 | 150 | curl -iH "Bond-Token: 2f6eaf536ae6779c" 151 | http://192.168.86.241/v2/devices/1/actions/SetSpeed 152 | -X PUT -d '{"argument":5}' 153 | 154 | To turn fan motor on (remembering previous speed), and to turn it off, use `TurnOn` and `TurnOff` actions respectively. 155 | 156 | To set fan to winter direction: 157 | 158 | curl -iH "Bond-Token: 2f6eaf536ae6779c" 159 | http://192.168.86.241/v2/devices/1/actions/SetDirection 160 | -X PUT -d '{"argument":-1}' 161 | 162 | For summer direction, use an argument of `1` rather than `-1`. 163 | 164 | 165 | When integrating with a toggle button UI that does not provide state feedback to the user, it is recommended to use the `ToggleLight` or `TogglePower` actions. 166 | 167 | 168 | ## State Feedback 169 | 170 | 171 | The fan may be also operated via the Bond Home app or the fan's remote control. Therefore some state feedback mechanism to the control system is desirable. 172 | 173 | The control system may simply poll the `state` endpoint. 174 | 175 | Alternatively, the control system may obtain state feedback via the BPUP protocol. To do this, the control system need only continue to send a single broadcast datagram on port 30007 once every 60 seconds. The immediate replies from the fans can serve as an ongoing discoverability and reachability mechanism. Furthermore, whenever the state of the fan changes, the control system will receive a BPUP reply containing the new state data: 176 | 177 | {"B":"ZZBL12345", 178 | "d":0, 179 | "v":"v2.18.2", 180 | "t":"devices/1/state", 181 | "i":"00112233bbeeeeff", 182 | "s":200, 183 | "m":0, 184 | "f":255, 185 | "b":{"_":"ab9284ef","power":1,"speed":2}}\n 186 | 187 | The control system should ensure that serial number (`B`) matches an integrated device, and furthermore that the topic `t` is `devices/1/state`. The state information is available in the body (`b`) object. The other key-value pairs may be safely ignored. 188 | 189 | Here is a one-liner which will collect state feedback from all Smart by Bond devices on the network with a single command: 190 | 191 | while true; do echo; sleep 60; done | 192 | socat -t1 STDIO UDP4-DATAGRAM:255.255.255.255:30007,broadcast 193 | 194 | -------------------------------------------------------------------------------- /sidekicks/schemas.yaml: -------------------------------------------------------------------------------- 1 | Sidekick: 2 | type: object 3 | properties: 4 | _id: 5 | writeOnly: true 6 | example: "SNAXX12345" 7 | type: string 8 | description: | 9 | Provided only on POST request to specify the Sidekick ID. 10 | name: 11 | example: My Sidekick 12 | type: string 13 | description: | 14 | Name of Sidekick on Bond Home app and suggested name for 15 | control system integrations. 16 | location: 17 | example: My Room 18 | type: string 19 | description: | 20 | Location of Sidekick. 21 | keys: 22 | readOnly: true 23 | example: 3 24 | type: integer 25 | description: | 26 | Number of keys available on this Sidekick. 27 | May change after creation due to user changing mode. 28 | chans: 29 | readOnly: true 30 | example: 5 31 | type: integer 32 | description: | 33 | Number of channels available on this Sidekick. 34 | May change after creation due to user changing mode. 35 | chan_links: 36 | example: {"1":[{"device":"aabbccdd", "direct": 1}, {"device":"11223344", "direct": 0}],"2":[],"3":[],"4":[],"5":[]} 37 | type: object 38 | description: | 39 | Object describes every link between channels of this Sidekick and the 40 | devices which they control. (In future will permit specifying `group` 41 | instead of `device`.) 42 | 43 | Each channel number maps to an array, each element of which is called 44 | a "channel link". Each link has two fields: 45 | 46 | - `device`: device id channel is linked to 47 | - `direct`: 48 | - 0 = channel configured for relay 49 | - 1 = channel configured for correct direct technology 50 | - -1 = channel configured for incorrect direct technology, Bridge will relay signal. 51 | 52 | Note that there are valid circumstances where `direct` field is -1. 53 | For example, a channel may be linked to an RTS motor and an ARC motor. 54 | The user can only pick a single direct technology, for example RTS. 55 | The ARC motor will then be in the -1 case. 56 | 57 | key_links: 58 | example: {"1":[{"event":"TAP", "channel": 5, "action": "Raise"}], "2":[{"event":"DOUBLE_TAP", "device": "aabbccdd", "action": "SetPosition", "argument": 75}], "3":[{"event":"TAP", "channel": -1, "action": "Stop"}]} 59 | type: object 60 | description: | 61 | Object describes every link between key events from this Sidekick and the 62 | device, group, scene, or channel actions which they trigger. 63 | 64 | For Mate Pro (MT-1500), key_links are used for "built-in scenes" - programmable 65 | actions that can target channels on the Mate itself, in addition to BondSync 66 | integration with Bond Bridge devices, groups, and scenes. 67 | 68 | Each key number maps to an array, each element of which is called 69 | a "key link". Each key link has the following fields: 70 | 71 | - `event`: which key event to trigger on 72 | - `TAP` 73 | - `DOUBLE_TAP` 74 | - `HOLD_START` 75 | - `HOLD` 76 | - `HOLD_END` 77 | 78 | - Actor (choose one): 79 | - `device`: device id to control (BondSync integration) 80 | - `group`: group id to control (future) 81 | - `scene`: scene id to run (future) 82 | - `channel`: [MT-1500 only] channel number to control (0-15, or -1 for "current channel") 83 | 84 | - `action`: action to execute on the actor 85 | - For devices: device action (e.g., SetPosition, TurnOn) 86 | - For channels: channel action (e.g., Raise, Lower, TurnLightOn) 87 | 88 | - `argument`: (optional) argument to action, such as position percentage 89 | 90 | Special channel values (MT-1500 only): 91 | - 0-15: Execute action on the specified channel 92 | - -1: Execute action on whichever channel is currently selected ("current channel") 93 | 94 | When channel=-1, the available actions are the union of all channel actions. 95 | If the current channel doesn't support the specified action at the time the 96 | key is pressed, nothing happens (no error indication on device). 97 | signal: 98 | readOnly: true 99 | example: 97 100 | type: integer 101 | description: | 102 | Signal quality indication, range 1-100. 103 | Note that, to avoid hash thrashing, 104 | changes in this signal indication do not cause 105 | an update to the endpoint hashes. Clients wishing to check 106 | signal strength must explicitly query this endpoint. 107 | battery: 108 | readOnly: true 109 | example: 80 110 | type: integer 111 | description: | 112 | Sidekick battery remaining, range 1-100. 113 | Values may be limited to: 114 | - 90: battery OK (Green) 115 | - 30: low battery (Yellow) (replace witin ~1 year from when first indicated low) 116 | - 10: battery critical (Red) (may fail at any time, or may already be failing) 117 | model: 118 | readOnly: true 119 | example: SKN-386 120 | type: string 121 | description: | 122 | User-facing model number of Sidekick. 123 | 124 | 125 | Keystream: 126 | type: object 127 | properties: 128 | seq: 129 | example: 3210 130 | type: integer 131 | description: | 132 | Sequence number which increments each time this Sidekick transmits 133 | a BondSync signal. Usually not needed by integrations. 134 | event: 135 | example: TAP 136 | type: string 137 | description: | 138 | Event which occured on the specified key. Possibilities are: 139 | - TAP 140 | - DOUBLE_TAP 141 | - HOLD_START 142 | - HOLD 143 | - HOLD_END 144 | key: 145 | example: 3 146 | type: integer 147 | description: | 148 | 1-based key number. 149 | hold_ms: 150 | example: 1760 151 | type: integer 152 | description: | 153 | Length of time for which key has been held, in milliseconds. 154 | Only provided for HOLD and HOLD_END events. 155 | 156 | SidekickList: 157 | type: object 158 | example: 159 | _: "7fc1e84b" 160 | 3b20f300: 161 | _: "9a5e1136" 162 | 4ad874d2: 163 | _: "84819a9f" 164 | a94328bc: 165 | _: "23141efa" 166 | d87d6ef2: 167 | _: "2425a8bc" 168 | 169 | Learn: 170 | type: object 171 | properties: 172 | learn_window_ms: 173 | example: 60000 174 | type: integer 175 | readOnly: true 176 | description: | 177 | Duration of learn window (milliseconds). 178 | learn_window_remaining_ms: 179 | example: 1100 180 | type: integer 181 | readOnly: true 182 | description: | 183 | Milliseconds remaining before learn window closes. 184 | learn_window_open: 185 | example: true 186 | type: boolean 187 | description: | 188 | Whether new Sidekick can be learned. 189 | True iff learn_window_remaining_ms is nonzero. 190 | learn_count: 191 | example: 0 192 | type: integer 193 | readOnly: true 194 | description: | 195 | Number of times a new Sidekick has been learned on this boot. 196 | Useful in UI design to know that the learn process completed, 197 | even if the learned address is the same. 198 | new_id: 199 | example: "SHXXX12345" 200 | type: string 201 | readOnly: true 202 | description: | 203 | ID of the newly learned Sidekick, if any. 204 | Populated when a new Sidekick successfully links during the learn window. 205 | [v4.24+] This field is cleared when opening a new learn window. 206 | pattern: 207 | example: "^SH" 208 | type: string 209 | writeOnly: true 210 | maxLength: 32 211 | description: | 212 | [v4.24+] Optional regex pattern to filter devices during learning (max 32 characters). 213 | Only devices whose IDs match this pattern will be accepted during the learn window. 214 | Example: "^SH" accepts only Sidekick devices (IDs starting with SH). 215 | If not specified, all device types are accepted (backward compatible). 216 | -------------------------------------------------------------------------------- /devices/schemas.yaml: -------------------------------------------------------------------------------- 1 | Device: 2 | properties: 3 | name: 4 | example: My Fan 5 | type: string 6 | type: 7 | description: | 8 | - `CF` : Ceiling Fan 9 | - `FP` : Fireplace 10 | - `MS` : Motorized Window Coverings (Shades, Screens, Drapes) and Awnings 11 | - `GX` : Generic device 12 | - `LT` : Light 13 | - `BD` : Bidet 14 | 15 | This `type` field does not impact the functionality of the device. 16 | The `type` field should be used by API clients to improve the user experience. 17 | For example, the Bond Home app uses this field to determine what icon to show 18 | when browsing a list of Devices on the Bridge. 19 | 20 | The `type` field *may* be used by integrations to determine the category of interface to be selected 21 | when such a selection is mandated by the platform. For example, Google Assistant integration 22 | requires developers to choose a device type such as Fan or Light. 23 | however we strongly encourage developers to implement the functional aspects of integrations based on 24 | Features (i.e., available Actions, State variables, and Properties). 25 | example: "CF" 26 | type: string 27 | subtype: 28 | description: | 29 | [Added in v2.21] 30 | 31 | The subtype field is used to distinguish between categories of devices sublter than the `type` field permits. 32 | 33 | Currently, subtype is only used for Motorized Window Coverings and Awnings (`type = MS`), with the following options: 34 | 35 | - `ROLLER`: a roller blackout shade which blocks light and provides privacy 36 | - `SHEER`: a shade which permits light to pass and does not provide privacy 37 | - `AWNING`: an outdoor patio covering 38 | 39 | This field does not impact functionality in any way. 40 | Furthermore, the `subtype` field must only be used for analytics and aesthetic purposes by the API client. 41 | New subtypes may be introduced without notice. API clients should always be prepared to fall back to a reasonable 42 | default based on the device `type`. 43 | 44 | The `subtype` field is not limited by the firmware, but rather specified by Bond internally and included 45 | in Device creation requests from the Bond Home app. 46 | 47 | WARNING: Although currently it is not the case, at some point the same `subtype` string may be re-used with 48 | different meanings between different device `types`. To take a hypothetical example, we may have a gas-powered 49 | fireplace device (`type = FP, subtype = GAS`) but also a gas-powered bidet (`type = BD, subtype = GAS`). 50 | example: "AWNING" 51 | type: string 52 | template: 53 | description: | 54 | An internal name describing what sort of protocol the remote represented 55 | by the device implements. Upon a POST with a valid template string, the 56 | device self-populates its panel with some default controls, initializes 57 | its state, and finds a script to define its behavior. 58 | 59 | Most templated devices need additional parameters, such as an address 60 | `addr`, frequency `freq`, bits per second `bps`, and length of the zeros 61 | between repetititions `zero_gap`. These should be specified in an object 62 | `properties` in the POST body. 63 | example: "A1" 64 | type: string 65 | location: 66 | example: Kitchen 67 | type: string 68 | actions: 69 | readOnly: true 70 | type: array 71 | example: 72 | - "TurnOn" 73 | - "TurnOff" 74 | - "TogglePower" 75 | - "SetSpeed" 76 | - "IncreaseSpeed" 77 | - "DecreaseSpeed" 78 | properties: 79 | readOnly: true 80 | type: object 81 | example: 82 | _: "84cd8a43" 83 | state: 84 | readOnly: true 85 | type: object 86 | example: 87 | _: "ad9bcde4" 88 | commands: 89 | readOnly: true 90 | type: object 91 | example: 92 | _: "ad9bcde4" 93 | required: 94 | - name 95 | - type 96 | 97 | DeviceList: 98 | type: object 99 | example: 100 | _: "7fc1e84b" 101 | 3b20f300: 102 | _: "9a5e1136" 103 | 4caf6472: 104 | _: "409d124b" 105 | State: 106 | example: 107 | breeze: 108 | - 1 109 | - 0.2 110 | - 0.9 111 | brightness: 75 112 | light: 1 113 | power: 0 114 | speed: 2 115 | timer: 3599 116 | properties: 117 | _lock_priority: 118 | type: number 119 | description: | 120 | Device lock priority number. 121 | _lock_expiration: 122 | type: number 123 | description: | 124 | Remaining time for expiration of the lock, in miliseconds. 125 | 126 | Properties: 127 | properties: 128 | trust_state: 129 | example: false 130 | type: boolean 131 | description: | 132 | Whether or not the Bond should trust its toggleable state belief. 133 | This is the confidence the Bond has that this device's state 134 | belief is accurate, and is only present if a "Toggle" command is present 135 | (for `power`, `light`, `direction`, etc.), and is `false` by default. 136 | (Bridge-only) 137 | addr: 138 | readOnly: true 139 | example: "10101" 140 | type: string 141 | description: (Bridge-only) 142 | freq: 143 | readOnly: true 144 | example: 434300 145 | type: integer 146 | description: (Bridge-only) 147 | bps: 148 | readOnly: true 149 | example: 3000 150 | type: integer 151 | description: (Bridge-only) 152 | zero_gap: 153 | readOnly: true 154 | example: 30 155 | type: integer 156 | description: (Bridge-only) 157 | 158 | PowerCycleState: 159 | properties: 160 | enabled: 161 | example: false 162 | type: boolean 163 | description: | 164 | If true, device will revert to specified state after power loss. 165 | If false, device will maintain previous state across power loss 166 | ("Last State" feature). 167 | state: 168 | example: {"light": 1, "brightness": 100, "power": 0, "speed": 3} 169 | type: object 170 | description: | 171 | State to revert to after power loss. 172 | Same schema as for Device state. 173 | 174 | Bridge: 175 | properties: 176 | location: 177 | example: My Room 178 | type: string 179 | name: 180 | example: My Bridge 181 | type: string 182 | bluelight: 183 | example: 127 184 | type: int 185 | 186 | RemoteAddr: 187 | properties: 188 | addr: 189 | example: ["dead", "0f2a", "0002", "0003"] 190 | type: array 191 | items: 192 | type: string 193 | description: | 194 | Learned remote address(es) in hexadecimal, 195 | may be patched only with a single address string to be added. 196 | addr_slots: 197 | example: 5 198 | type: integer 199 | readOnly: true 200 | description: | 201 | Maximum number of addresses which can be learned by this device. 202 | Typical values are 1 (for devices whose corresponding transmitters 203 | ship with DIP switches, allowing the user to manually put all 204 | transmitters on the same address) and 5 (for devices where each 205 | transmitter is shipped with a random address). 206 | learn_window_ms: 207 | example: 60000 208 | type: integer 209 | readOnly: true 210 | description: | 211 | Duration of learn window (milliseconds). 212 | learn_window_remaining_ms: 213 | example: 1100 214 | type: integer 215 | readOnly: true 216 | description: | 217 | Milliseconds remaining before learn window closes. 218 | learn_window_open: 219 | example: true 220 | type: boolean 221 | description: | 222 | Whether new address can be learned via RF. 223 | True iff learn_window_remaining_ms is nonzero. 224 | learn_count: 225 | example: 0 226 | type: integer 227 | readOnly: true 228 | description: | 229 | Number of times a new address has been learned on this boot. 230 | Useful in UI design to know that the learn process completed, 231 | even if the learned address is the same. 232 | addr0_is_dip: 233 | example: True 234 | type: boolean 235 | description: | 236 | If present and true, indicates that the receiver has DIP switches 237 | which may be adjusted to set the zeroth address. 238 | -------------------------------------------------------------------------------- /groups/paths.yaml: -------------------------------------------------------------------------------- 1 | GroupsPath: 2 | get: 3 | description: | 4 | Returns a list of Group IDs and the corresponding Group hashes. 5 | The hashes change if any part of the Group (its name, state, type, etc.) 6 | has changed. The hash is not updated if underlying Devices are updated 7 | in a way which does not effect the Group state or type. 8 | 9 | Groups are supported on Bridges and on Smart by Bond. 10 | Groups may span multiple Bonds (Bridges and SBB devices) by using the same 11 | Group ID on each Bond. See the introductory section "Groups and Scenes". 12 | responses: 13 | '200': 14 | content: 15 | application/json: 16 | schema: 17 | $ref: schemas.yaml#/GroupList 18 | description: List Groups 19 | '401': 20 | $ref: ../common/responses.yaml#/Unauthorized 21 | '500': 22 | $ref: ../common/responses.yaml#/InternalServerError 23 | security: 24 | - OAuth: ["oauth2"] 25 | summary: List your Groups 26 | tags: 27 | - Groups 28 | post: 29 | requestBody: 30 | content: 31 | application/json: 32 | schema: 33 | $ref: ../groups/schemas.yaml#/Group 34 | responses: 35 | '201': 36 | $ref: ../common/responses.yaml#/Created 37 | '400': 38 | $ref: ../common/responses.yaml#/BadRequest 39 | '401': 40 | $ref: ../common/responses.yaml#/Unauthorized 41 | '409': 42 | $ref: ../common/responses.yaml#/Conflict 43 | '500': 44 | $ref: ../common/responses.yaml#/InternalServerError 45 | summary: Create new Group 46 | description: | 47 | For the creation of a Group distributed across multiple Bonds, 48 | clients should provide a 64-bit ID for the Group and provide that 49 | same ID in each Group POST request in the `_id` field. See 50 | introductory section "Groups and Scenes" for detail. If the `_id` 51 | field is not provided, a random ID will be assigned as with 52 | POST requests to other enumerations. 53 | 54 | A Group is created containing the device IDs in the `devices` array. 55 | Using the `devices` field requires 56 | the client to predetermine what devices are compatible in the sense 57 | of having a non-empty Actions intersection. If even a single device is 58 | incompatible, then the entire POST will fail with a 400 error. 59 | 60 | Note that `types` and `locations` fields cannot be specified when 61 | creating a Group: these fields are calculated based on the member Devices. 62 | tags: 63 | - Groups 64 | 65 | GroupPath: 66 | get: 67 | $ref: ../groups/paths.yaml#/Get 68 | parameters: 69 | - in: path 70 | name: group_id 71 | required: true 72 | schema: 73 | type: number 74 | patch: 75 | $ref: ../groups/paths.yaml#/Patch 76 | delete: 77 | $ref: ../groups/paths.yaml#/Delete 78 | 79 | StatePath: 80 | get: 81 | $ref: ../groups/paths.yaml#/GetState 82 | parameters: 83 | - in: path 84 | name: group_id 85 | required: true 86 | schema: 87 | type: number 88 | 89 | PropertiesPath: 90 | get: 91 | $ref: ../groups/paths.yaml#/GetProperties 92 | patch: 93 | $ref: ../groups/paths.yaml#/PatchProperties 94 | parameters: 95 | - in: path 96 | name: group_id 97 | required: true 98 | schema: 99 | type: number 100 | GetProperties: 101 | responses: 102 | '200': 103 | content: 104 | application/json: 105 | schema: 106 | $ref: ../devices/schemas.yaml#/Properties 107 | description: Get Group properties 108 | '401': 109 | $ref: ../common/responses.yaml#/Unauthorized 110 | '404': 111 | $ref: ../common/responses.yaml#/NotFound 112 | '500': 113 | $ref: ../common/responses.yaml#/InternalServerError 114 | security: 115 | - OAuth: ["oauth2"] 116 | summary: Get Group properties 117 | description: | 118 | See the Features section above for other properties which may be available 119 | on your Groups. 120 | 121 | Similar to the Group State object, the Properties available for a Group 122 | are those Properties which exist on every Device in the Group. 123 | If all Devices have the same value for a Property, then that value will 124 | be provided here. If Devices do not agree on a value, then that Property 125 | will be listed but with a `null` value. 126 | tags: 127 | - Group Properties 128 | 129 | PatchProperties: 130 | requestBody: 131 | content: 132 | application/json: 133 | schema: 134 | $ref: ../devices/schemas.yaml#/Properties 135 | responses: 136 | '200': 137 | description: Properties updated 138 | '401': 139 | $ref: ../common/responses.yaml#/Unauthorized 140 | '404': 141 | $ref: ../common/responses.yaml#/NotFound 142 | '500': 143 | $ref: ../common/responses.yaml#/InternalServerError 144 | security: 145 | - OAuth: ["oauth2"] 146 | summary: Update properties 147 | description: | 148 | PATCHing one or more Group Properties implicitely PATCHes those Properties 149 | on all Devices in the Group. Gratuitous PATCH replies are sent for each 150 | Device before this PATCH reply returns. If any errors occur in any of the 151 | underlying Device PATCH requests, this request will return a 500 error 152 | and the Devices' Properties will be left in undefined condition. 153 | 154 | Example: If you set up 8 individual shades in your kitchen and then add 155 | them all to a Group, you can then, with a single request, enable or disable 156 | the `feature_position` Property to enable/disable the "slider" feature. 157 | tags: 158 | - Group Properties 159 | 160 | GetList: 161 | responses: 162 | '200': 163 | content: 164 | application/json: 165 | schema: 166 | $ref: schemas.yaml#/GroupList 167 | description: List active Groups 168 | '401': 169 | $ref: ../common/responses.yaml#/Unauthorized 170 | '500': 171 | $ref: ../common/responses.yaml#/InternalServerError 172 | security: 173 | - OAuth: ["oauth2"] 174 | summary: List your Groups 175 | tags: 176 | - Groups 177 | Post: 178 | requestBody: 179 | required: true 180 | content: 181 | application/json: 182 | schema: 183 | $ref: schemas.yaml#/Group 184 | responses: 185 | '201': 186 | $ref: ../common/responses.yaml#/Created 187 | '400': 188 | $ref: ../common/responses.yaml#/BadRequest 189 | '401': 190 | $ref: ../common/responses.yaml#/Unauthorized 191 | '409': 192 | $ref: ../common/responses.yaml#/Conflict 193 | '500': 194 | $ref: ../common/responses.yaml#/InternalServerError 195 | summary: Create new Group 196 | tags: 197 | - Groups 198 | Get: 199 | description: | 200 | Groups are collections of Devices. 201 | responses: 202 | '200': 203 | content: 204 | application/json: 205 | schema: 206 | $ref: schemas.yaml#/Group 207 | description: Get Group 208 | '401': 209 | $ref: ../common/responses.yaml#/Unauthorized 210 | '404': 211 | $ref: ../common/responses.yaml#/NotFound 212 | '500': 213 | $ref: ../common/responses.yaml#/InternalServerError 214 | security: 215 | - OAuth: ["oauth2"] 216 | summary: Get Group 217 | tags: 218 | - Groups 219 | Patch: 220 | requestBody: 221 | required: true 222 | content: 223 | application/json: 224 | schema: 225 | $ref: schemas.yaml#/Group 226 | responses: 227 | '200': 228 | content: 229 | application/json: 230 | schema: 231 | $ref: schemas.yaml#/Group 232 | description: Change Group field 233 | '401': 234 | $ref: ../common/responses.yaml#/Unauthorized 235 | '404': 236 | $ref: ../common/responses.yaml#/NotFound 237 | '500': 238 | $ref: ../common/responses.yaml#/InternalServerError 239 | security: 240 | - BasicAuth: [] 241 | summary: Change Group field 242 | description: | 243 | The `devices` list may be PATCHed to perform a bulk change to the membership in the group. 244 | A 400 error is returned if the devices are incompatible. 245 | 246 | If the `devices` list is PATCHed to empty, the group shard will vanish. 247 | That is, the group shard will be removed from the groups enumeration. 248 | The groups enumeration will be sent as a gratuitous GET response. 249 | tags: 250 | - Groups 251 | Delete: 252 | responses: 253 | '204': 254 | description: Delete Group 255 | '401': 256 | $ref: ../common/responses.yaml#/Unauthorized 257 | '404': 258 | $ref: ../common/responses.yaml#/NotFound 259 | '500': 260 | $ref: ../common/responses.yaml#/InternalServerError 261 | security: 262 | - BasicAuth: [] 263 | summary: Delete Group 264 | description: | 265 | The entire Group is deleted. 266 | tags: 267 | - Groups 268 | 269 | GetState: 270 | responses: 271 | '200': 272 | content: 273 | application/json: 274 | schema: 275 | $ref: schemas.yaml#/State 276 | description: Get Group State 277 | '401': 278 | $ref: ../common/responses.yaml#/Unauthorized 279 | '404': 280 | $ref: ../common/responses.yaml#/NotFound 281 | '500': 282 | $ref: ../common/responses.yaml#/InternalServerError 283 | security: 284 | - OAuth: ["oauth2"] 285 | summary: Get Group State 286 | description: | 287 | Group State lists those state variables which are common to all member 288 | Devices. If all member Devices have the same value for a particular state 289 | variable, then the Group variable will take that value. However, if member 290 | Devices differ in value, then the Group variable will take the value `null`. 291 | 292 | Note that Group states cannot be PATCHed. 293 | tags: 294 | - Group State 295 | --------------------------------------------------------------------------------