Connected Devices/Projects/Project Link/Taxonomy: Difference between revisions

(→‎Service List: + Mucho details)
(→‎Specific services and channels: Updated camera examples)
 
(25 intermediate revisions by 4 users not shown)
Line 1: Line 1:
== Taxonomy Documentation ==
= Taxonomy Documentation =
Github Link: http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/index.html
Github Link: http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/index.html


== Current REST API Examples ==
= Current REST API =


=== Account ===
== Account ==
* To create account:
* To create account:
** POST http://localhost:3000/users/setup {"email": "a@b.com","username":"admin","password": "00000000"}
** POST http://localhost:3000/users/setup {"email": "a@b.com","username":"admin","password": "00000000"}
Line 10: Line 10:
** POST http://localhost:3000/users/login (Header contains Authorization: Basic <base64 encode of username:password)
** POST http://localhost:3000/users/login (Header contains Authorization: Basic <base64 encode of username:password)


=== Service List ===
== Services ==
 
Services may requested by selector. A service selector is an object with the following fields:
Services may requested by selector. A service selector is an object with the following fields:


* (optional) string `id`: accept only a service with a given id;
* (optional) string `id`: accept only a service with a given id;
* (optional) string array of string `tags`: accept only services with all the tags in the array;
* (optional) string array of string `tags`: accept only services with all the tags in the array;
* (optional) object or array of objects `getters` (see GetterSelector): accept only services with channels matching all the selectors in this array;
* (optional) object or array of objects `channels` (see ChannelSelector): accept only services with channels matching all the selectors in this array;
* (optional) object or array of objects `setters` (see SetterSelector): accept only services with channels matching all the selectors in this array.


The GET accepts 0, 1 or an array of service selectors and will return all the services that match any of the selectors.
Generally, except for (de)assigning tags, '''using an id is considered a bad idea''', as this ties the application to a specific device, and this will fail if the device is replaced (consider that this is equivalent to using an IP address instead of a domain name).


=== List of Services ===
Example with 1 selector:
Example with 1 selector:


* Get services with tag "location: kitchen" and channel kind "OvenTemperature"
* Get services with tag "location: kitchen" and a channel with feature "oven/temperature-celcius"
** GET http://localhost:3000/api/v1/services { tags: "location: kitchen", setters: { kind: "OvenTemperature" } }
** GET http://localhost:3000/api/v1/services { "tags": "location: kitchen", "channels": { "feature": "oven/temperature-celcius" } }


Example with 2 selectors:
Example with 2 selectors:
Line 35: Line 36:
** GET http://localhost:3000/api/v1/services
** GET http://localhost:3000/api/v1/services


=== Channels ===
=== Tags ===
* To use the getter:
 
** PUT http://localhost:3000/api/v1/channels/get {“id”: <getter service id> }
* Assign Tags to a service
* To use the setter: (“value” is for the type of value the user is sending to the foxbox)
** POST http://localhost:3000/api/v1/services/tags {"services": selector(s), "tags": tag(s)}
** PUT http://localhost:3000/api/v1/channels/set {“select”:{“id”: <setter service id>, “value”: {<value type>:{}}}}
 
* Remove Tags of a service
** DELETE http://localhost:3000/api/v1/services/tags {"services": selector(s), "tags": tag(s)}
 
* Example
** POST http://localhost:3000/api/v1/services/tags {"services":[{"id":"thinkerbell-root-service"}],"tags":["location:living-room"] }
 
== Channels ==
 
Channels are designed to be used by selector.
 
A selector is an object with the following fields:
 
* (required for Fetch/Send, optional in other cases) string `feature`: accept only channels that implement a given feature (e.g. "oven/temperature-celcius")
* (optional) string id: accept only a channel with a given id;
* (optional) string `service`: accept only channels of a service with a given id;
* (optional) string|array of string `tags`: accept only channels with all the tags in the array;
* (optional) string|array of string `service_tags`: accept only channels of a service with all the tags in the array;
 
 
Generally, except for (de)assigning tags, '''using an id is considered a bad idea''', as this ties the application to a specific device, and this will fail if the device is replaced (consider that this is equivalent to using an IP address instead of a domain name).
 
 
=== Fetching ===
 
* Fetch values from all channels matching any of the selectors
    POST http://localhost:3000/api/v1/channels selector(s)
 
<br/>
 
Example:
    POST http://localhost:3000/api/v1/channels [{"tags": "location: entrance", "feature": "oven/temperature-celcius"}]
 
=== Sending ===
 
* Send one values to all channels matching any of the selectors:
    PUT http://localhost:3000/api/v1/channels/set {"select": selector(s), "value": value}
 
or
 
* Send a bunch of values to all channels matching any of the selectors:
    PUT http://localhost:3000/api/v1/channels/set [{"select": selector(s), "value": value}, {"select": selector(s), "value": value}, ...]
 
Values are defined by Adapters, so you should check the documentation of individual adapters to see what is possible.
 
 
==== Example (with CURL) ====
 
The following snippet displays "Hello world" on all the devices that support Log, in particular the console.
 
    curl -X PUT http://localhost:3000/api/v1/channels/set -d '{"select":{"feature":"log/append-text"},"value":{"String":"Hello, world"}}'
 
=== Tags ===
 
* Assign Tags to a channel
** POST http://localhost:3000/api/v1/channels/channel/tags {"channel": selector(s), "tags": tag(s)}
 
* Remove Tags of a channel
** DELETE http://localhost:3000/api/v1/channels/channel/tags {"channel": selector(s), "tags": tag(s)}


=== Time ===
= Specific services and channels =
== Time ==
* Get the current time
* Get the current time
** PUT http://localhost:3000/api/v1/channels/get {"id":"getter:timeofday.clock@link.mozilla.org"}
    PUT http://localhost:3000/api/v1/channels/get {"feature":"clock/time-of-day-seconds"}
    PUT http://localhost:3000/api/v1/channels/get {"feature":"clock/time-timestamp-rfc-3339"}


=== Camera ===
== Camera ==
* Take a picture with camera
* Take a picture with camera
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:snapshot.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org"}, "value": {"Unit": {}}}
    PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:snapshot.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org", "feature": "camera/store-snapshot"}, "value": {}}
 
* Get list of images taken
* Get list of images taken
** PUT http://localhost:3000/api/v1/channels/get {"id":"getter:image_list.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org"}
    PUT http://localhost:3000/api/v1/channels/get {"id":"getter:image_list.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org", "feature": "camera/x-image-list"}
 
* Download the last taken picture
* Download the last taken picture
** PUT http://localhost:3000/api/v1/channels/get {"id":"getter:image_newest.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org"}  
    PUT http://localhost:3000/api/v1/channels/get {"id":"getter:image_newest.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org", "feature": "camera/x-latest-image"}
 
* Get list of services that can take image (snapshot)
* Get list of services that can take image (snapshot)
** POST http://localhost:3000/api/v1/services {"setters":[{"kind":{"adapter":"Adapter","kind":"snapshot","type": "Json", "vendor":"DLink"} }]}
    POST http://localhost:3000/api/v1/services {"channels":[{"feature": "camera/store-snapshot"} }]}
 
== Recipe ==
 
A recipe is a set of *rules*.
 
Each rule is triggered when *all* its *conditions* are true. A condition is specified by a set of channels to watch and a range of values that make it true - the condition becomes true once *any* of the channels it watches provides a value that fits the range.
 
Once a rule is triggered, it *executes*. An execution sends one value to a set of channels.
 
 
Once a rule is triggered, it won't be triggered again until at least one of the conditions has become false and true again.
 
Format:
  {
    name: "Some name",
    rules: one or more of {
      conditions: one or more of {
        source: one or more of Selectors (see section on channels)
        feature: see [http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/services/enum.ChannelKind.html#json documentation of channel kinds]
        range: see [http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/values/enum.Range.html#json documentation of ranges]
        duration: (optional) floating point number of seconds
      }
      execute: one or more of {
        destination: one or more Selectors (see section on channels)
        feature: see [http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/services/enum.ChannelKind.html#json documentation of channel kinds]
        value: see [http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/values/enum.Value.html#json documentation of values]
      }
    }
  }
 
 


=== Tags ===
* Assign Tags to a service
** POST http://localhost:3000/api/v1/services/tags {"services":[{"id":"thinkerbell-root-service"}],"tags":["Living Room"] }
** Note: there can be multiple tags, (in array)
* Remove Tags of a service
** DELETE http://localhost:3000/api/v1/services/tags {"services":[{"id":"thinkerbell-root-service"}],"tags":["Living Room"] }
** Same URL, same body
* Query all devices matching the tag
** POST http://localhost:3000/api/v1/services {"tags":["Living"]}
=== Recipe ===
* Send Recipe
* Send Recipe
Example:
    PUT http://localhost:3000/api/v1/channels/set
   
    {
      "select":{
          "kind":"AddThinkerbellRule"
      },
      "value":{
          "ThinkerbellRule":{
            "name":"Hello, Thinkerbell",
            "source":"{\"name\": \"Hello, Thinkerbell\", \"rules\":[{\"conditions\":[{\"source\":[{\"id\":\"OpenZWave/72057594126794752 (Sensor)\"}],\"feature\":\"door/is-open\",\"range\":{\"Eq\":{\"OpenClosed\":\"Open\"}}}],\"execute\":[{\"destination\":[{\"feature\":\"log/append-text\"}],\"feature\":\"log/append-text\",\"value\":{\"String\":\"Closed\"}}]}]}"
          }
      }
    }
* List available Recipes
* List available Recipes


=== WebPush ===
Example:
    POST http://localhost:3000/api/v1/services HTTP/1.1 {"channels": [{"feature": "thinkerbell/source"}]}
 
== WebPush ==
 
* Get current subscriptions
    PUT http://localhost:3000/api/v1/channels/get {"feature": "webpush/subscribe"}
* Get current resources receiving notifications on
    PUT http://localhost:3000/api/v1/channels/get {"feature": "webpush/resource"}
 
* Add push subscription
* Add push subscription
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:subscribe.webpush@link.mozilla.org"}, "value": {"Json": {“subscriptions”:[{“push_uri”:”http://push.service/t54wtresfesfd”,”public_key”:”base64_encoded_key”}]}}}
    PUT http://localhost:3000/api/v1/channels/set {"select": {"feature": "webpush/subscribe"},  
    "value": {"Json": {"subscriptions":[{"push_uri":"http://push.service/t54wtresfesfd","public_key":"base64_encoded_key","auth":"optional_base64_auth_data"}]}}}
 
* Remove push subscription
* Remove push subscription
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:unsubscribe.webpush@link.mozilla.org"}, "value": {"Json": {“subscriptions”:[{“push_uri”:”http://push.service/t54wtresfesfd”,”public_key”:”base64_encoded_key”}]}}}
    PUT http://localhost:3000/api/v1/channels/set {"select": {"feature": "webpush/unsubscribe"},  
    "value": {"Json": {"subscriptions":[{"push_uri":"http://push.service/t54wtresfesfd","public_key":"base64_encoded_key","auth":"optional_base64_auth_data"}]}}}
 
(the following have not been reviewed)
 
* Set resources to receive notifications on
* Set resources to receive notifications on
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:resource.webpush@link.mozilla.org"}, "value": {"Json": {“resources”:[“res1”, “res2”]}}}
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:resource.webpush@link.mozilla.org"}, "value": {"Json": {"resources":["res1", "res2"]}}}
* Get current subscriptions
** PUT http://localhost:3000/api/v1/channels/get {"select": {"id": "getter:subscription.webpush@link.mozilla.org"}, "value": {"Json": {}}}
* Get current resources receiving notifications on
** PUT http://localhost:3000/api/v1/channels/get {"select": {"id": "getter:resource.webpush@link.mozilla.org"}, "value": {"Json": {}}}
* Trigger notification
* Trigger notification
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:notify.webpush@link.mozilla.org"}, "value": {"Json": {“resource”:“res1”,”message”:”push_message_data”}}}
** PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:notify.webpush@link.mozilla.org"}, "value": {"Json": {"resource":"res1","message":"push_message_data"}}}
 
== Lights ==
Sample service entry for a ''Philips Hue Lightstrip Plus'':
  [
    {
      "adapter": "philips_hue@link.mozilla.org",
      "getters": {
        "getter:available.4.001788fffe25681a.philips_hue@link.mozilla.org": {
          "adapter": "philips_hue@link.mozilla.org",
          "id": "getter:available.4.001788fffe25681a.philips_hue@link.mozilla.org",
          "kind": {
            "adapter": "Philips Hue Adapter",
            "kind": "available",
            "typ": "OnOff",
            "vendor": "foxlink@mozilla.com"
          },
          "mechanism": "getter",
          "service": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
          "tags": []
        },
        "getter:power.4.001788fffe25681a.philips_hue@link.mozilla.org": {
          "adapter": "philips_hue@link.mozilla.org",
          "id": "getter:power.4.001788fffe25681a.philips_hue@link.mozilla.org",
          "kind": "LightOn",
          "mechanism": "getter",
          "service": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
          "tags": []
        }
      },
      "id": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
      "properties": {
        "manufacturer": "Philips",
        "model": "LST002",
        "name": "Hue lightstrip plus 1",
        "type": "Light/ColorLight"
      },
      "setters": {
        "setter:power.4.001788fffe25681a.philips_hue@link.mozilla.org": {
          "adapter": "philips_hue@link.mozilla.org",
          "id": "setter:power.4.001788fffe25681a.philips_hue@link.mozilla.org",
          "kind": "LightOn",
          "mechanism": "setter",
          "service": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
          "tags": []
        }
      },
      "tags": [
        "type:Light/ColorLight"
      ]
    }
  ]
 
=== Channels ===
==== getter:availability ====
Response:
{"OnOff":"Off"} when light not ready to receive commands (f.e. no external power)
{"OnOff":"On"} when light ready to receive commands
==== getter:power ====
Response:
{"OnOff":"Off"} when the light is completely turned off
{"OnOff":"On"} when the light is turned on
==== setter:power ====
Value:
{"OnOff":"Off"} to turn the light off
{"OnOff":"On"} to turn the light on
 
=== Examples ===
==== Check availability of an individual light ====
PUT http://localhost:3000/api/v1/channels/get {"id":"channel:available.4.001788fffe25681a.philips_hue@link.mozilla.org"}
 
==== Turn all the lights off ====
PUT http://localhost:3000/api/v1/channels/set {"select":{"feature":"light/is-on"},"value":{"OnOff":"Off"}}

Latest revision as of 11:03, 16 June 2016

Taxonomy Documentation

Github Link: http://fxbox.github.io/taxonomy/doc/foxbox_taxonomy/index.html

Current REST API

Account

Services

Services may requested by selector. A service selector is an object with the following fields:

  • (optional) string `id`: accept only a service with a given id;
  • (optional) string array of string `tags`: accept only services with all the tags in the array;
  • (optional) object or array of objects `channels` (see ChannelSelector): accept only services with channels matching all the selectors in this array;

Generally, except for (de)assigning tags, using an id is considered a bad idea, as this ties the application to a specific device, and this will fail if the device is replaced (consider that this is equivalent to using an IP address instead of a domain name).

List of Services

Example with 1 selector:

  • Get services with tag "location: kitchen" and a channel with feature "oven/temperature-celcius"

Example with 2 selectors:

As a shortcut, providing no argument will locate all services:

Tags

Channels

Channels are designed to be used by selector.

A selector is an object with the following fields:

  • (required for Fetch/Send, optional in other cases) string `feature`: accept only channels that implement a given feature (e.g. "oven/temperature-celcius")
  • (optional) string id: accept only a channel with a given id;
  • (optional) string `service`: accept only channels of a service with a given id;
  • (optional) string|array of string `tags`: accept only channels with all the tags in the array;
  • (optional) string|array of string `service_tags`: accept only channels of a service with all the tags in the array;


Generally, except for (de)assigning tags, using an id is considered a bad idea, as this ties the application to a specific device, and this will fail if the device is replaced (consider that this is equivalent to using an IP address instead of a domain name).


Fetching

  • Fetch values from all channels matching any of the selectors
   POST http://localhost:3000/api/v1/channels selector(s)


Example:

   POST http://localhost:3000/api/v1/channels [{"tags": "location: entrance", "feature": "oven/temperature-celcius"}]

Sending

  • Send one values to all channels matching any of the selectors:
   PUT http://localhost:3000/api/v1/channels/set {"select": selector(s), "value": value}

or

  • Send a bunch of values to all channels matching any of the selectors:
   PUT http://localhost:3000/api/v1/channels/set [{"select": selector(s), "value": value}, {"select": selector(s), "value": value}, ...]

Values are defined by Adapters, so you should check the documentation of individual adapters to see what is possible.


Example (with CURL)

The following snippet displays "Hello world" on all the devices that support Log, in particular the console.

   curl -X PUT http://localhost:3000/api/v1/channels/set -d '{"select":{"feature":"log/append-text"},"value":{"String":"Hello, world"}}'

Tags

Specific services and channels

Time

  • Get the current time
   PUT http://localhost:3000/api/v1/channels/get {"feature":"clock/time-of-day-seconds"}
   PUT http://localhost:3000/api/v1/channels/get {"feature":"clock/time-timestamp-rfc-3339"}

Camera

  • Take a picture with camera
   PUT http://localhost:3000/api/v1/channels/set {"select": {"id": "setter:snapshot.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org", "feature": "camera/store-snapshot"}, "value": {}}
  • Get list of images taken
   PUT http://localhost:3000/api/v1/channels/get {"id":"getter:image_list.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org", "feature": "camera/x-image-list"}
  • Download the last taken picture
   PUT http://localhost:3000/api/v1/channels/get {"id":"getter:image_newest.ae67e622-7a66-465e-bab0-28107b2df980@link.mozilla.org", "feature": "camera/x-latest-image"}
  • Get list of services that can take image (snapshot)
   POST http://localhost:3000/api/v1/services {"channels":[{"feature": "camera/store-snapshot"} }]}

Recipe

A recipe is a set of *rules*.

Each rule is triggered when *all* its *conditions* are true. A condition is specified by a set of channels to watch and a range of values that make it true - the condition becomes true once *any* of the channels it watches provides a value that fits the range.

Once a rule is triggered, it *executes*. An execution sends one value to a set of channels.


Once a rule is triggered, it won't be triggered again until at least one of the conditions has become false and true again.

Format:

 {
   name: "Some name",
   rules: one or more of {
     conditions: one or more of {
       source: one or more of Selectors (see section on channels)
       feature: see documentation of channel kinds
       range: see documentation of ranges
       duration: (optional) floating point number of seconds
     }
     execute: one or more of {
       destination: one or more Selectors (see section on channels)
       feature: see documentation of channel kinds
       value: see documentation of values
     }
   }
 }


  • Send Recipe

Example:

   PUT http://localhost:3000/api/v1/channels/set
   
   {
      "select":{
         "kind":"AddThinkerbellRule"
      },
      "value":{
         "ThinkerbellRule":{
            "name":"Hello, Thinkerbell",
            "source":"{\"name\": \"Hello, Thinkerbell\", \"rules\":[{\"conditions\":[{\"source\":[{\"id\":\"OpenZWave/72057594126794752 (Sensor)\"}],\"feature\":\"door/is-open\",\"range\":{\"Eq\":{\"OpenClosed\":\"Open\"}}}],\"execute\":[{\"destination\":[{\"feature\":\"log/append-text\"}],\"feature\":\"log/append-text\",\"value\":{\"String\":\"Closed\"}}]}]}"
         }
      }
   }
  • List available Recipes

Example:

   POST http://localhost:3000/api/v1/services HTTP/1.1 {"channels": [{"feature": "thinkerbell/source"}]}

WebPush

  • Get current subscriptions
   PUT http://localhost:3000/api/v1/channels/get {"feature": "webpush/subscribe"}
  • Get current resources receiving notifications on
   PUT http://localhost:3000/api/v1/channels/get {"feature": "webpush/resource"}
  • Add push subscription
   PUT http://localhost:3000/api/v1/channels/set {"select": {"feature": "webpush/subscribe"}, 
   "value": {"Json": {"subscriptions":[{"push_uri":"http://push.service/t54wtresfesfd","public_key":"base64_encoded_key","auth":"optional_base64_auth_data"}]}}}
  • Remove push subscription
   PUT http://localhost:3000/api/v1/channels/set {"select": {"feature": "webpush/unsubscribe"}, 
   "value": {"Json": {"subscriptions":[{"push_uri":"http://push.service/t54wtresfesfd","public_key":"base64_encoded_key","auth":"optional_base64_auth_data"}]}}}

(the following have not been reviewed)

Lights

Sample service entry for a Philips Hue Lightstrip Plus:

 [
   {
     "adapter": "philips_hue@link.mozilla.org",
     "getters": {
       "getter:available.4.001788fffe25681a.philips_hue@link.mozilla.org": {
         "adapter": "philips_hue@link.mozilla.org",
         "id": "getter:available.4.001788fffe25681a.philips_hue@link.mozilla.org",
         "kind": {
           "adapter": "Philips Hue Adapter",
           "kind": "available",
           "typ": "OnOff",
           "vendor": "foxlink@mozilla.com"
         },
         "mechanism": "getter",
         "service": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
         "tags": []
       },
       "getter:power.4.001788fffe25681a.philips_hue@link.mozilla.org": {
         "adapter": "philips_hue@link.mozilla.org",
         "id": "getter:power.4.001788fffe25681a.philips_hue@link.mozilla.org",
         "kind": "LightOn",
         "mechanism": "getter",
         "service": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
         "tags": []
       }
     },
     "id": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
     "properties": {
       "manufacturer": "Philips",
       "model": "LST002",
       "name": "Hue lightstrip plus 1",
       "type": "Light/ColorLight"
     },
     "setters": {
       "setter:power.4.001788fffe25681a.philips_hue@link.mozilla.org": {
         "adapter": "philips_hue@link.mozilla.org",
         "id": "setter:power.4.001788fffe25681a.philips_hue@link.mozilla.org",
         "kind": "LightOn",
         "mechanism": "setter",
         "service": "service:4.001788fffe25681a.philips_hue@link.mozilla.org",
         "tags": []
       }
     },
     "tags": [
       "type:Light/ColorLight"
     ]
   }
 ]

Channels

getter:availability

Response:

{"OnOff":"Off"} when light not ready to receive commands (f.e. no external power)
{"OnOff":"On"} when light ready to receive commands

getter:power

Response:

{"OnOff":"Off"} when the light is completely turned off
{"OnOff":"On"} when the light is turned on

setter:power

Value:

{"OnOff":"Off"} to turn the light off
{"OnOff":"On"} to turn the light on

Examples

Check availability of an individual light

PUT http://localhost:3000/api/v1/channels/get {"id":"channel:available.4.001788fffe25681a.philips_hue@link.mozilla.org"}

Turn all the lights off

PUT http://localhost:3000/api/v1/channels/set {"select":{"feature":"light/is-on"},"value":{"OnOff":"Off"}}