From f92c5daea57cbd4d63e544b135b18ab60e69e98c Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Sun, 21 Oct 2018 23:49:38 -0700 Subject: [PATCH 1/8] tutorial for writing device class --- doc/thingpedia-device-class.md | 111 +++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/doc/thingpedia-device-class.md b/doc/thingpedia-device-class.md index ff529bea0..be20a8c4d 100644 --- a/doc/thingpedia-device-class.md +++ b/doc/thingpedia-device-class.md @@ -1,2 +1,113 @@ # Writing Device Class in ThingTalk +[[toc]] + +Device class describes how the device will be loaded by the system, how it will +be configured, and what it does. +In the following, we will continue using The Cat API as an example to illustrate +how to write your own device class. The device class of it looks like this: + +```tt +class @com.thecatapi { + import loader from @org.thingpedia.v2(); + import config from @org.thingpedia.config.none(); + + query get(in opt count: Number, + out image_id: Entity(com.thecatapi:image_id), + out picture_url: Entity(tt:picture), + out link: Entity(tt:url)) + #_[canonical="get cat on thecatapi"] + #_[confirmation="cat pictures"] + #[doc="get `count` many cat pictures"]; +} +``` +The name of a device class is as defined in the device metadata with an additional `@` +sign in front. The device class has two types of statements: import statements and function declaration statements. +Each statement terminates with a semicolon. + +## Import statements +The import statements import modules `loader` and `config` for the device, +to specify how the device will be loaded by the system and how it will be initially configured +or authenticated. + +Mixin `@org.thingpedia.v2()` provides the most flexible loader module, which allows +the user to supply additional JS package code to customized the configuration of the device +and the behavior of each function. +Other mixins for loader include `@org.thingpedia.rss` and `@org.thingpedia.generic_rest.v1`. +They give users the ability to write a device with standard RSS and RESTful interfaces without any JS code. +For more details, please refer to [declarative Thingpedia entries](/doc/thingpedia-device-with-zero-code.md). + +Mixin `@org.thingpedia.config.none` provides the basic config module for devices require no authentication +or those only require an API key. +More options such as OAuth and IoT discovery are described in +[complete guide for authentication and discovery](/doc/thingpedia-device-intro-auth-n-discovery.md). + +## Function declarations +The user interacts with your Thingpedia device through two types of functions: queries and actions. +Thus, the first step is to decide on what queries and actions you should expose. + +The only requirement imposed from Thingpedia is that queries are free of side-effects and can return results (as output arguments), +and actions have side effects, and cannot return results. Other than that, the design of which functions to include is highly device specific. + +### Qualifiers +Additional qualifier can be used to specify the property of the query. +A query is `monitorable` if it's meaningful to monitor its return value and get triggered. +A query is a `list` query if it normally returns multiple results. + +For example, a query to return latest emails would be considered both `monitorable` and `list`, +and its declaration will look like: +```tt +monitorable list latest_emails (...); +``` + +For The Cat API, it returns a random cat every time, so it's not reasonable to monitor it. +It also returns a single cat by default, so we also don't mark it as `list`. + +### Parameters +To take full advantage of the functionality we provided in ThingTalk (filtering, chaining, etc.), +every parameter needed for ___both input and output___ should be listed. +An argument is described as follows: +```tt +[in req | in opt | out] : +``` + +A parameter can be either `in req` (required input), `in opt` (optional input), or `out` (output). +The `type` of a parameter could be: String, Number, Boolean, Date, Time, Location, +Entity(...), Enum(...), Measure(...), etc. +For the full list, see the [ThingTalk reference](/doc/thingtalk-reference.md) + +For The Cat API, we have only a query to return random cat pictures. +It takes an optional input parameter `count` of type Number, +and 3 output parameters of type Entities: `image_id`, `picture_url`, and `link`. + +### Annotations +Annotations are used to provide additional information to the corresponding code. +Annotations always comes after the code and before the semicolon. +There are two types of annotations: natural language annotation and implementation annotation. + +#### Natural language annotation +Natural language annotation, as its name, is the annotation related to natural language +and it will be translated to different languages based on users' profile. +It's denoted by `#_[=]`. + +Here is a list of required natural language annotations for functions: +- `canonical`: The canonical form of the function name, used by the semantic parser (certain versions); +it's a good idea to omit stop words for this, and to use a longer expression. +You must omit all parameters from the canonical form. +- `confirmation`: A string used to construct the final confirmation question before a rule is created +or an action is invoked. For actions, use the imperative form, e.g. “send a message”, +and for query use the noun-phrase form e.g. “cat pictures” instead of “get cat pictures”. +You can refer to required arguments with `$argname` or `${argname}` (the latter is only needed if +the argument is immediately followed by a letter number or underscore). + +#### Implementation annotation +Implementation annotation is used for describing the implementation details of a function. +This is denoted by `#[=]` (without the underscore as in natural language annotation). + +Here is a list of required implementation annotations for functions: +- `doc`: This is used for documentation for developers. +- `poll_interval` (required for monitorable query): This is used to specify how often the query will be fired +if it is monitored. It takes a time interval, e.g., `#[poll_interval=5min]`. + + + From 507c5127cee14905b5b632d80ac89194087ba61b Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Mon, 22 Oct 2018 13:24:04 -0700 Subject: [PATCH 2/8] tutorial for adding nl examples --- doc/thingpedia-device-class.md | 6 +- ...hingpedia-device-intro-example-commands.md | 81 +++++++++---------- 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/doc/thingpedia-device-class.md b/doc/thingpedia-device-class.md index be20a8c4d..2f6736797 100644 --- a/doc/thingpedia-device-class.md +++ b/doc/thingpedia-device-class.md @@ -46,7 +46,7 @@ More options such as OAuth and IoT discovery are described in The user interacts with your Thingpedia device through two types of functions: queries and actions. Thus, the first step is to decide on what queries and actions you should expose. -The only requirement imposed from Thingpedia is that queries are free of side-effects and can return results (as output arguments), +The only requirement imposed from Thingpedia is that queries are free of side-effects and can return results (as output parameters), and actions have side effects, and cannot return results. Other than that, the design of which functions to include is highly device specific. ### Qualifiers @@ -66,7 +66,7 @@ It also returns a single cat by default, so we also don't mark it as `list`. ### Parameters To take full advantage of the functionality we provided in ThingTalk (filtering, chaining, etc.), every parameter needed for ___both input and output___ should be listed. -An argument is described as follows: +An parameter is described as follows: ```tt [in req | in opt | out] : ``` @@ -93,7 +93,7 @@ It's denoted by `#_[=]`. Here is a list of required natural language annotations for functions: - `canonical`: The canonical form of the function name, used by the semantic parser (certain versions); it's a good idea to omit stop words for this, and to use a longer expression. -You must omit all parameters from the canonical form. +You must omit all arguments from the canonical form. - `confirmation`: A string used to construct the final confirmation question before a rule is created or an action is invoked. For actions, use the imperative form, e.g. “send a message”, and for query use the noun-phrase form e.g. “cat pictures” instead of “get cat pictures”. diff --git a/doc/thingpedia-device-intro-example-commands.md b/doc/thingpedia-device-intro-example-commands.md index 30f544702..57a3efe67 100644 --- a/doc/thingpedia-device-intro-example-commands.md +++ b/doc/thingpedia-device-intro-example-commands.md @@ -1,50 +1,47 @@ # Writing Example Commands for Your Device -[[toc]] - -## Composable Examples -ThingTalk can compose multiple primitive commands to create a complicated compound command. -To leverage the full power of ThingTalk, we recommend to write composable example commands as follows. - -Instead of writing full programs, write parts using lambda syntax introduced in [ThingTalk introduction](/doc/thingtalk-intro.md). -Use twitter as an example. The query to get tweets in my timeline can be declared using the following syntax. -```JSON -Utterance: tweets from my timeline -Program: let table x := @com.twitter.home_timeline(); +To get natural language support, +a `dataset` is required to supply example commands for your device. +In the following, we will continue using The Cat API as an example. +Its `dataset.tt` file looks like this: + +```tt +dataset @com.thecatapi { + query := @com.thecatapi.get() + #_[utterances=["a cat picture","a random cat picture","cats"]]; + + query (p_count :Number) := @com.thecatapi.get(count=p_count) + #_[utterances=["${p_count:const} cat pictures"]]; +} ``` -The corresponding utterance of a query should be a __noun phrase__. In this case, it should be `tweets from anyone i follow` or `tweets from my timeline`. -When we compose the sentence, we will add generic verbs before the noun phrase such as `get`, `show`. -If you want to use a non-generic verb, put a comma `,` before your utterance. For example get the translation of some text might want to use the command-specific verb `translate`, -thus we can write the utterance as "_, translate the text_". -For streams like the following one, write the utterance in as a __when phrase__: "_when i tweet_". -```JSON -Utterance: when i tweet -Program: let stream x := monitor (@com.twitter.my_tweets()); -``` +Similar to device class, the name of the dataset is as defined in the device metadata +with the `@` sign. -For actions, just write the full sentence. So the following sentence will have utterance like "_post `$p_status` on twitter_" or "_tweet `$p_status`_". -Note that, for all examples, the arguments of the lambda expression should be named by the original argument name defined in the channel -with a prefix of `p_`. -```JSON -Utterance: tweet $p_status -Program: let action x := \(p_status :String) -> @com.twitter.post(status=p_status); +Instead of writing full programs, we write parts using code snippet syntax introduced in +[ThingTalk introduction](/doc/thingtalk-intro.md#code-snippet), plus the `utterances` +natural language annotation. +In The Cat API, the query to get cats can be declared using the following syntax: +```tt +query := @com.thecatapi.get() +#_[utterances=["a cat picture","a random cat picture","cats"]]; +``` +The `utterances` annotation takes a list of strings to show different ways to +express the same function. +Similar to the `confirmation` annotation for functions as introduced in device class, +the corresponding utterance of a query should be a noun phrase, and the one of +an action should be a verb phrase in imperative form. + +Arguments can also be used in the dataset, and they can be referred in the +utterances with `$argname`: +```tt +query (p_count :Number) := @com.thecatapi.get(count=p_count) +#_[utterances=["$p_count cat pictures"]]; ``` -Note that `$` is used to indicate parameters, if you want to use dollar sign for things like currency, use `$$`. - - -## Stand-alone Examples -All the examples introduced above can be combined and compose more complicated sentences -by concatenating the natural language utterances with some conjunctions and verbs. -However, in some cases, you might want a very specific utterance for your command, -or even an example for compound command, which won't be natural to use as part of some other sentences. -In this case, one can write the full program. - -For example, if we want a stand-alone command "automatically retweet anyone i follow", -to avoid being composed, we can write the following ThingTalk program -instead of the lambda expression: -```JSON -Utterance: automatically retweet anyone i follow -Program: monitor (@com.twitter.home_timeline()) => @com.twitter.retweet(tweet_id=tweet_id); +A query can be monitored to create a _stream_ if it's marked as monitorable. +For example, a stream to monitor my latest emails can be declared as follows: +```tt +stream := monitor (@com.email.inbox()) +#_[utterances=["when i receive an email"]] ``` From 50de719c7b5e3ce9874dc059b83e145380aa2522 Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Mon, 22 Oct 2018 13:30:31 -0700 Subject: [PATCH 3/8] grammar --- doc/thingpedia-device-class.md | 12 ++++++------ doc/thingpedia-device-intro-example-commands.md | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/thingpedia-device-class.md b/doc/thingpedia-device-class.md index 2f6736797..fe825b704 100644 --- a/doc/thingpedia-device-class.md +++ b/doc/thingpedia-device-class.md @@ -37,9 +37,9 @@ Other mixins for loader include `@org.thingpedia.rss` and `@org.thingpedia.gener They give users the ability to write a device with standard RSS and RESTful interfaces without any JS code. For more details, please refer to [declarative Thingpedia entries](/doc/thingpedia-device-with-zero-code.md). -Mixin `@org.thingpedia.config.none` provides the basic config module for devices require no authentication -or those only require an API key. -More options such as OAuth and IoT discovery are described in +Mixin `@org.thingpedia.config.none` provides the basic config module for devices +that require no authentication or those only require an API key. +More options such as OAuth and IoT discovery are described in the [complete guide for authentication and discovery](/doc/thingpedia-device-intro-auth-n-discovery.md). ## Function declarations @@ -66,7 +66,7 @@ It also returns a single cat by default, so we also don't mark it as `list`. ### Parameters To take full advantage of the functionality we provided in ThingTalk (filtering, chaining, etc.), every parameter needed for ___both input and output___ should be listed. -An parameter is described as follows: +A parameter is described as follows: ```tt [in req | in opt | out] : ``` @@ -82,7 +82,7 @@ and 3 output parameters of type Entities: `image_id`, `picture_url`, and `link`. ### Annotations Annotations are used to provide additional information to the corresponding code. -Annotations always comes after the code and before the semicolon. +Annotations always come after the code and before the semicolon. There are two types of annotations: natural language annotation and implementation annotation. #### Natural language annotation @@ -98,7 +98,7 @@ You must omit all arguments from the canonical form. or an action is invoked. For actions, use the imperative form, e.g. “send a message”, and for query use the noun-phrase form e.g. “cat pictures” instead of “get cat pictures”. You can refer to required arguments with `$argname` or `${argname}` (the latter is only needed if -the argument is immediately followed by a letter number or underscore). +the argument is immediately followed by a letter, number, or underscore). #### Implementation annotation Implementation annotation is used for describing the implementation details of a function. diff --git a/doc/thingpedia-device-intro-example-commands.md b/doc/thingpedia-device-intro-example-commands.md index 57a3efe67..f9e300a90 100644 --- a/doc/thingpedia-device-intro-example-commands.md +++ b/doc/thingpedia-device-intro-example-commands.md @@ -15,7 +15,7 @@ dataset @com.thecatapi { } ``` -Similar to device class, the name of the dataset is as defined in the device metadata +Similar to the device class, the name of the dataset is as defined in the device metadata with the `@` sign. Instead of writing full programs, we write parts using code snippet syntax introduced in @@ -30,7 +30,7 @@ The `utterances` annotation takes a list of strings to show different ways to express the same function. Similar to the `confirmation` annotation for functions as introduced in device class, the corresponding utterance of a query should be a noun phrase, and the one of -an action should be a verb phrase in imperative form. +an action should be a verb phrase in the imperative form. Arguments can also be used in the dataset, and they can be referred in the utterances with `$argname`: From e1de073634d213f72424b18e4d5a4b8eb226bf7b Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Mon, 22 Oct 2018 17:54:17 -0700 Subject: [PATCH 4/8] More on sidebar --- doc/thingpedia-annotations.md | 2 ++ doc/thingpedia-error-handling.md | 3 +++ ...ands.md => thingpedia-tutorial-dataset.md} | 0 ...ass.md => thingpedia-tutorial-manifest.md} | 0 ...device-intro.md => thingpedia-tutorial.md} | 4 +-- doc/thingtalk-intro.md | 2 +- views/thingpedia_dev_sidebar.pug | 25 +++++++++++-------- 7 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 doc/thingpedia-annotations.md create mode 100644 doc/thingpedia-error-handling.md rename doc/{thingpedia-device-intro-example-commands.md => thingpedia-tutorial-dataset.md} (100%) rename doc/{thingpedia-device-class.md => thingpedia-tutorial-manifest.md} (100%) rename doc/{thingpedia-device-intro.md => thingpedia-tutorial.md} (98%) diff --git a/doc/thingpedia-annotations.md b/doc/thingpedia-annotations.md new file mode 100644 index 000000000..a6e5c7e6e --- /dev/null +++ b/doc/thingpedia-annotations.md @@ -0,0 +1,2 @@ +# Thingpedia Annotation Reference +//TODO \ No newline at end of file diff --git a/doc/thingpedia-error-handling.md b/doc/thingpedia-error-handling.md new file mode 100644 index 000000000..93dfe569b --- /dev/null +++ b/doc/thingpedia-error-handling.md @@ -0,0 +1,3 @@ +# Error Handling + +//TODO \ No newline at end of file diff --git a/doc/thingpedia-device-intro-example-commands.md b/doc/thingpedia-tutorial-dataset.md similarity index 100% rename from doc/thingpedia-device-intro-example-commands.md rename to doc/thingpedia-tutorial-dataset.md diff --git a/doc/thingpedia-device-class.md b/doc/thingpedia-tutorial-manifest.md similarity index 100% rename from doc/thingpedia-device-class.md rename to doc/thingpedia-tutorial-manifest.md diff --git a/doc/thingpedia-device-intro.md b/doc/thingpedia-tutorial.md similarity index 98% rename from doc/thingpedia-device-intro.md rename to doc/thingpedia-tutorial.md index 3f7607519..d417c6329 100644 --- a/doc/thingpedia-device-intro.md +++ b/doc/thingpedia-tutorial.md @@ -73,7 +73,7 @@ function behavior. This will be introduced in detail [later](#writing-js-device- All devices published on Thingpedia must include _device manifest_ written in ThingTalk, i.e., `manifest.tt`. It defines the _device class_ you want to create whose name is the `ID` defined in the metadata. -Check [Writing Device Class](/doc/thingpedia-device-class.md) for the instructions on +Check [Writing Device Class](/doc/thingpedia-tutorial-manifest.md) for the instructions on how to write a device class. A ThingTalk editor is provided to help you write it, which can be found at the @@ -91,7 +91,7 @@ The examples provide both documentation for the user The accuracy of the parser heavily relies on the quality and quantity of examples. Thus, developers are recommended to write as many example commands as possible to cover all possible usage of your device. -Check [Writing Example Commands for Your Device](/doc/thingpedia-device-intro-example-commands.md) +Check [Writing Example Commands for Your Device](/doc/thingpedia-tutorial-dataset.md) for detailed instruction on how to write the examples. --- diff --git a/doc/thingtalk-intro.md b/doc/thingtalk-intro.md index eebca1989..42d6968c4 100644 --- a/doc/thingtalk-intro.md +++ b/doc/thingtalk-intro.md @@ -145,7 +145,7 @@ stream (keyword : String) := monitor @com.foxnews.get(), title =~ keyword; ``` Code snippets are used to provide composable examples for devices in Thingpedia, -as detailed [in their guide](/doc/thingpedia-device-intro-example-commands.md). +as detailed [in their guide](/doc/thingpedia-tutorial-dataset.md). ## Advanced Topics ### Joins diff --git a/views/thingpedia_dev_sidebar.pug b/views/thingpedia_dev_sidebar.pug index 341c2e377..2c3567988 100644 --- a/views/thingpedia_dev_sidebar.pug +++ b/views/thingpedia_dev_sidebar.pug @@ -22,18 +22,18 @@ nav#doc-sidebar li(class=(currentPage === 'thingtalk-intro' ? 'current' : '')) a(href='/thingpedia/developers/thingtalk-intro.md') Introduction to ThingTalk - li(class=(['thingpedia-device-intro', 'thingpedia-device-intro-auth-n-discovery', 'thingpedia-device-intro-example-commands', 'thingpedia-device-with-zero-code', 'thingpedia-device-class'].indexOf(currentPage) >= 0 ? 'current' : '')) + li(class=(['thingpedia-tutorial', 'thingpedia-device-intro-auth-n-discovery', 'thingpedia-tutorial-dataset', 'thingpedia-device-with-zero-code', 'thingpedia-tutorial-manifest', 'thingpedia-error-handling'].indexOf(currentPage) >= 0 ? 'current' : '')) p.doc-sidebar-subtitle For Thingpedia Contributors p.doc-sidebar-subsubtitle Tutorials ul - li(class=(currentPage === 'thingpedia-device-intro' ? 'current' : '')) - a(href='/thingpedia/developers/thingpedia-device-intro.md') Writing Thingpedia Entries + li(class=(currentPage === 'thingpedia-tutorial' ? 'current' : '')) + a(href='/thingpedia/developers/thingpedia-tutorial.md') Writing Thingpedia Entries - li(class=(currentPage === 'thingpedia-device-class' ? 'current' : '')) - a(href='/thingpedia/developers/thingpedia-device-class.md') Writing Device Class + li(class=(currentPage === 'thingpedia-tutorial-manifest' ? 'current' : '')) + a(href='/thingpedia/developers/thingpedia-tutorial-manifest.md') Writing Device Class - li(class=(currentPage === 'thingpedia-device-intro-example-commands' ? 'current' : '')) - a(href='/thingpedia/developers/thingpedia-device-intro-example-commands.md') Adding Natural Language + li(class=(currentPage === 'thingpedia-tutorial-dataset' ? 'current' : '')) + a(href='/thingpedia/developers/thingpedia-tutorial-dataset.md') Adding Natural Language p.doc-sidebar-subsubtitle Topic Guides ul @@ -43,16 +43,19 @@ nav#doc-sidebar li(class=(currentPage === 'thingpedia-device-with-zero-code' ? 'current' : '')) a(href='/thingpedia/developers/thingpedia-device-with-zero-code.md') Declarative Thingpedia Entries + li(class=(currentPage === 'thingpedia-error-handling' ? 'current' : '')) + a(href='/thingpedia/developers/thingpedia-error-handling.md') Error Handling + li(class=(['my-api', 'almond-dialog-api-reference'].indexOf(currentPage) >= 0 ? 'current' : '')) - p.doc-sidebar-subtitle For Almond Integrators + a.doc-sidebar-subtitle For Almond Integrators ul li(class=(currentPage === 'my-api' ? 'current' : '')) a(href='/thingpedia/developers/my-api.md') Web Almond API li(class=(currentPage === 'almond-dialog-api-reference' ? 'current' : '')) a(href='/thingpedia/developers/almond-dialog-api-reference.md') Almond Dialog API - li(class=(['thingtalk-reference', 'thingpedia-helpers'].indexOf(currentPage) >= 0 ? 'current' : '')) - p.doc-sidebar-subtitle Reference Manuals + li(class=(['thingtalk-reference', 'thingpedia-helpers', 'thingpedia-annotations'].indexOf(currentPage) >= 0 ? 'current' : '')) + a.doc-sidebar-subtitle Reference Manuals ul li(class=(currentPage === 'thingtalk-reference' ? 'current' : '')) a(href='/thingpedia/developers/thingtalk-reference.md') ThingTalk Reference @@ -60,6 +63,8 @@ nav#doc-sidebar a(href='/thingpedia/entities') ThingTalk Entity Types li a(href='/thingpedia/strings') Available String Datasets + li(class=(currentPage === 'thingpedia-annotations' ? 'current' : '')) + a(href='/thingpedia/developers/thingpedia-annotations.md') Thingpedia Annotation Reference li(class=(currentPage === 'thingpedia-helpers' ? 'current' : '')) a(href='/thingpedia/developers/thingpedia-helpers.md') Thingpedia Device API Reference li From 4ba1feeb685af0fec86c17bb42ad2cdf96be171b Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Mon, 22 Oct 2018 18:17:24 -0700 Subject: [PATCH 5/8] Minor fixes for tutorials --- doc/thingpedia-tutorial-manifest.md | 14 +++++++------- doc/thingpedia-tutorial.md | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/thingpedia-tutorial-manifest.md b/doc/thingpedia-tutorial-manifest.md index fe825b704..ed4cb68ae 100644 --- a/doc/thingpedia-tutorial-manifest.md +++ b/doc/thingpedia-tutorial-manifest.md @@ -85,22 +85,19 @@ Annotations are used to provide additional information to the corresponding code Annotations always come after the code and before the semicolon. There are two types of annotations: natural language annotation and implementation annotation. -#### Natural language annotation +#### Natural language annotations Natural language annotation, as its name, is the annotation related to natural language and it will be translated to different languages based on users' profile. It's denoted by `#_[=]`. -Here is a list of required natural language annotations for functions: -- `canonical`: The canonical form of the function name, used by the semantic parser (certain versions); -it's a good idea to omit stop words for this, and to use a longer expression. -You must omit all arguments from the canonical form. -- `confirmation`: A string used to construct the final confirmation question before a rule is created +Each function is required to have `confirmation` natural language annotation: +A string used to construct the final confirmation question before a rule is created or an action is invoked. For actions, use the imperative form, e.g. “send a message”, and for query use the noun-phrase form e.g. “cat pictures” instead of “get cat pictures”. You can refer to required arguments with `$argname` or `${argname}` (the latter is only needed if the argument is immediately followed by a letter, number, or underscore). -#### Implementation annotation +#### Implementation annotations Implementation annotation is used for describing the implementation details of a function. This is denoted by `#[=]` (without the underscore as in natural language annotation). @@ -110,4 +107,7 @@ Here is a list of required implementation annotations for functions: if it is monitored. It takes a time interval, e.g., `#[poll_interval=5min]`. +A lot more optional annotations are supported in ThingTalk - for not only functions but also parameters and +device classes. +Refer to [annotation reference](/doc/thingpedia-annotations.md) for the full list. diff --git a/doc/thingpedia-tutorial.md b/doc/thingpedia-tutorial.md index d417c6329..123f70337 100644 --- a/doc/thingpedia-tutorial.md +++ b/doc/thingpedia-tutorial.md @@ -32,7 +32,7 @@ You can find a collective list of public APIs from [toddmotto/public-apis](https --- -## Writing metadata +## Writing the metadata First, you will need to fill some basic _metadata_ about your device, including `ID`, `Name`, `Description`, `Category`, and `Icon`. @@ -69,7 +69,7 @@ function behavior. This will be introduced in detail [later](#writing-js-device- --- -## Writing manifest +## Writing the manifest All devices published on Thingpedia must include _device manifest_ written in ThingTalk, i.e., `manifest.tt`. It defines the _device class_ you want to create whose name is the `ID` defined in the metadata. @@ -81,7 +81,7 @@ A ThingTalk editor is provided to help you write it, which can be found at the --- -## Writing dataset +## Writing the dataset In addition to the device manifest, developers are also required to provide example natural language utterances corresponding to the functions supported by the device in `dataset.tt`. @@ -95,7 +95,7 @@ Check [Writing Example Commands for Your Device](/doc/thingpedia-tutorial-datase for detailed instruction on how to write the examples. --- -## Writing JS device package +## Writing the JS device package Depending on the type of your device, you might need to provide a _device package_ containing the Javascript code to describe more details about how the device is configured and how each function behaves. @@ -258,7 +258,7 @@ Note that, we used [`Array.prototype.map()`](https://developer.mozilla.org/en-US to create the returned Array. Don't be fooled by the final `return` statement, we are still returning an Array. -### First JS package: The Cat API +### The first JS package: The Cat API Put all the components together, we have The Cat API code as follows. Since no library other than `thingpedia` is needed for this package. We can simply upload the `.js` file, and the `.zip` package will be generated automatically. From 55b9c7a9625b126e6e9ddad50ab74104cde66db4 Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Mon, 22 Oct 2018 18:21:56 -0700 Subject: [PATCH 6/8] Shrink more --- doc/thingpedia-tutorial-dataset.md | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/doc/thingpedia-tutorial-dataset.md b/doc/thingpedia-tutorial-dataset.md index f9e300a90..7573ebb30 100644 --- a/doc/thingpedia-tutorial-dataset.md +++ b/doc/thingpedia-tutorial-dataset.md @@ -21,11 +21,6 @@ with the `@` sign. Instead of writing full programs, we write parts using code snippet syntax introduced in [ThingTalk introduction](/doc/thingtalk-intro.md#code-snippet), plus the `utterances` natural language annotation. -In The Cat API, the query to get cats can be declared using the following syntax: -```tt -query := @com.thecatapi.get() -#_[utterances=["a cat picture","a random cat picture","cats"]]; -``` The `utterances` annotation takes a list of strings to show different ways to express the same function. Similar to the `confirmation` annotation for functions as introduced in device class, @@ -33,15 +28,11 @@ the corresponding utterance of a query should be a noun phrase, and the one of an action should be a verb phrase in the imperative form. Arguments can also be used in the dataset, and they can be referred in the -utterances with `$argname`: -```tt -query (p_count :Number) := @com.thecatapi.get(count=p_count) -#_[utterances=["$p_count cat pictures"]]; -``` +utterances with `$argname` as in the second example provided in the dataset for The Cat API. A query can be monitored to create a _stream_ if it's marked as monitorable. For example, a stream to monitor my latest emails can be declared as follows: ```tt stream := monitor (@com.email.inbox()) -#_[utterances=["when i receive an email"]] +#_[utterances=["when i receive an email", "when a new email comes in"]]; ``` From d76ad90346c7499e6496bb29740b2fad59b9f1d8 Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Tue, 23 Oct 2018 10:34:40 -0700 Subject: [PATCH 7/8] Address the comments --- doc/thingpedia-nl-support.md | 3 + doc/thingpedia-tutorial-js-package.md | 198 +++++++++++++++++++++++++ doc/thingpedia-tutorial-manifest.md | 21 +-- doc/thingpedia-tutorial.md | 200 +------------------------- views/thingpedia_dev_sidebar.pug | 7 +- 5 files changed, 220 insertions(+), 209 deletions(-) create mode 100644 doc/thingpedia-nl-support.md create mode 100644 doc/thingpedia-tutorial-js-package.md diff --git a/doc/thingpedia-nl-support.md b/doc/thingpedia-nl-support.md new file mode 100644 index 000000000..36c3b6669 --- /dev/null +++ b/doc/thingpedia-nl-support.md @@ -0,0 +1,3 @@ +# Natural Language Support for Devices in Thingpedia + +//TODO \ No newline at end of file diff --git a/doc/thingpedia-tutorial-js-package.md b/doc/thingpedia-tutorial-js-package.md new file mode 100644 index 000000000..202a8f4fd --- /dev/null +++ b/doc/thingpedia-tutorial-js-package.md @@ -0,0 +1,198 @@ +# Writing JS Device Packages +Depending on the type of your device, you might need +to provide a _device package_ containing the Javascript code +to describe more details about how the device is configured and how each function behaves. +This package will need to be uploaded at the metadata page before you submit. + +### The layout of a device package +The Thingpedia API assumes a precise layout for a device package, which +must be a zip file containing exactly the JS files and the package.json, +as well as any dependency you need. You should not assume any nodejs +module beyond the 'thingpedia' module illustrated here - if you need any, +bundle them in your zip file. + +If there is no dependency needed and all your code is in one file, you can +also upload the file directly, and we will generate the package.json and zip file for you. + +If you are using a Mac, please use command line to compress the folder: +`zip -r xx.zip your-folder-name`. +Compressing from the right-click menu in Mac will create a new folder which +makes the system fail to find the files in the root directory. + +The primary entry point (i.e., the one named as "main" in package.json) +should be a _device class_. You would instantiate the device class +from the API and set it directly to `module.exports`, as in + +```javascript +const Tp = require('thingpedia'); + +module.exports = class MyDeviceClass extends Tp.BaseDevice { + constructor(engine, state) { + super(engine, state); + // constructor + } + + // other methods of device class +}; +``` + +(Our code and examples make heavy use of modern JavaScript features, also known as ES2015. +If you are not familiar with the class syntax, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)) + +Then, for each query or action you want to expose, you would +add functions to your device class with prefix `get_` or `do_` respectively. +So for example, if +you want to expose query `get` for The Cat API, +you would modify your `device.js` as follows: + +```javascript +const Tp = require('thingpedia'); + +module.exports = class CatAPIDevice extends Tp.BaseDevice { + constructor(engine, state) { + super(engine, state); + // constructor + } + + get_get() { + // return cat pictures + } +}; +``` + +### The `BaseDevice` API + +When you create a device class, you declare +a subclass of [`Tp.BaseDevice`](https://github.com/Stanford-Mobisocial-IoT-Lab/thingpedia-api/blob/master/lib/base_device.js), +the base class of all device classes. + +To construct the subclass, three properties are required: `uniqueId`, `name`, and `description` +Different from the `ID` in the metadata, `uniqueId` uniquely identifies the device **instance** +of a user. For example, a user may configure two different Twitter accounts, and they will need +different IDs in Almond. A common way is to concatenate the device ID, a dash, and then a specific +ID for the corresponding account. E.g., `"com.twitter" + this.state.userId`. +Similarly, `name` and `description` will be used in [My Almond](/me) and they should be different +for different accounts, so that users can easily tell which account an instance associates with. +For example, for Twitter, the name could be `"Twitter Account for " + this.state.screenName`. + +For The Cat API, since it is a public service and there will be only one instance for each user, +we can just use the same ID, name, and description in metadata: + +```javascript +constructor(engine, state) { + super(engine, state); + + this.uniqueId = 'com.thecatapi'; + this.name = "The Cat API"; + this.description = "Where every day is Caturday!"; +} +``` + +The full reference of the `BaseDevice` class is given in the [Thingpedia interface reference](/doc/thingpedia-helpers.md#class-basedevice). + +### Handling authentication and discovery + +Unlike The Cat API, lots of devices will require some kind of authentication. +Three ways to do +authentication are supported, including `basic` (traditional username and +password), `oauth2` (OAuth 1.0 and 2.0 style authentication), and `discovery` +(authentication by discovery and local interactive paring). Here's a +[complete guide for authentication and discovery](/doc/thingpedia-device-intro-auth-n-discovery.md). + +### HTTP helpers + +Our system provides a generic interface `Tp.Helpers.Http` for basic HTTP request. +These are wrappers for [nodejs http API](https://nodejs.org/api/http.html) +with a Promise interface. + +Two of the most useful interfaces are probably +`Tp.Helpers.Http.get()` and `Tp.Helpers.Http.post()`, which deal with HTTP GET request +and POST request, respectively. We will see an example in practice in the next section. + +A full list of the available APIs can be found in +[Thingpedia interface reference](/doc/thingpedia-helpers.md#module-helpers-http) + +### Query and action +Recall that we separate Thingpedia functions in two different types: query and action. +A query returns data and makes no side effect, while action does not return any data but makes side effect to the world. + +Both query and action take an Object to get the value of input parameters. +For example, `get` function in The Cat API has one input parameter `count`, thus the function will look like: +```javascript +get_get({ count }) { + // returns $count cat pictures +} +``` + +A Query always returns an array of Object specifies the value of each output parameter. +For example, `get` function in The Cat API has 3 output parameters `image_id`, `pictuer_url`, and `link`, +the output should look like: +```javascript +get_get({ count }) { + ... + return [{ image_id: ..., picture_url: ..., link: ... }]; +} +``` + +Now let's implement the `get` function for The Cat API for real with HTTP helpers. +The function should look like this: +```javascript +get_get({ count }) { + count = count || 1; // fetch 1 cat by default + const url = URL + '&results_per_page=' + count; + return Tp.Helpers.Http.get(url).then((result) => Tp.Helpers.Xml.parseString(result)) + .then((parsed) => { + const array = parsed.response.data[0].images[0].image; + return array.map((image) => { + return { image_id: image.id[0], + picture_url: image.url[0], + link: 'http://thecatapi.com/?id=' + image.id[0] }; + }); + }); +} +``` + +`count` is an optional input parameter, we set it to 1 if it's left unspecified. +Then we call `Tp.Helpers.Http.get()` to the URL of the API endpoint. +The Cat API returns the result in `XML` format, so we parse it with `Tp.Helpers.Xml.parseString()` +to extract a JS Object. +Then we find the values we need and assign them to the corresponding parameters for return. +Note that, we used [`Array.prototype.map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) +to create the returned Array. +Don't be fooled by the final `return` statement, we are still returning an Array. + +### The first JS package: The Cat API +Put all the components together, we have The Cat API code as follows. +Since no library other than `thingpedia` is needed for this package. We can simply upload the `.js` file, +and the `.zip` package will be generated automatically. +```javascript +"use strict"; + +const Tp = require('thingpedia'); + +const URL = 'http://thecatapi.com/api/images/get?api_key=&format=xml&type=jpg,png'; + +module.exports = class CatAPIDevice extends Tp.BaseDevice { + constructor(engine, state) { + super(engine, state); + + this.uniqueId = 'com.thecatapi'; + this.name = "The Cat API"; + this.description = "Where every day is Caturday!"; + } + + get_get({ count }) { + count = count || 1; + const url = URL + '&results_per_page=' + count; + return Tp.Helpers.Http.get(url).then((result) => Tp.Helpers.Xml.parseString(result)) + .then((parsed) => { + const array = parsed.response.data[0].images[0].image; + return array.map((image) => { + return { image_id: image.id[0], + picture_url: image.url[0], + link: 'http://thecatapi.com/?id=' + image.id[0] }; + }); + }); + } +}; +``` \ No newline at end of file diff --git a/doc/thingpedia-tutorial-manifest.md b/doc/thingpedia-tutorial-manifest.md index ed4cb68ae..eb4655532 100644 --- a/doc/thingpedia-tutorial-manifest.md +++ b/doc/thingpedia-tutorial-manifest.md @@ -1,18 +1,18 @@ -# Writing Device Class in ThingTalk +# Writing Device Classes in ThingTalk [[toc]] Device class describes how the device will be loaded by the system, how it will be configured, and what it does. In the following, we will continue using The Cat API as an example to illustrate -how to write your own device class. The device class of it looks like this: +how to write your own device class. Its device class looks like this: ```tt class @com.thecatapi { import loader from @org.thingpedia.v2(); import config from @org.thingpedia.config.none(); - query get(in opt count: Number, + list query get(in opt count: Number, out image_id: Entity(com.thecatapi:image_id), out picture_url: Entity(tt:picture), out link: Entity(tt:url)) @@ -52,7 +52,7 @@ and actions have side effects, and cannot return results. Other than that, the d ### Qualifiers Additional qualifier can be used to specify the property of the query. A query is `monitorable` if it's meaningful to monitor its return value and get triggered. -A query is a `list` query if it normally returns multiple results. +A query is a `list` query if it returns multiple results. For example, a query to return latest emails would be considered both `monitorable` and `list`, and its declaration will look like: @@ -61,11 +61,12 @@ monitorable list latest_emails (...); ``` For The Cat API, it returns a random cat every time, so it's not reasonable to monitor it. -It also returns a single cat by default, so we also don't mark it as `list`. +It returns multiple cat pictures (with the `count` input parameter), +so we mark it as `list`. ### Parameters To take full advantage of the functionality we provided in ThingTalk (filtering, chaining, etc.), -every parameter needed for ___both input and output___ should be listed. +every parameter needed for ___both input and output___ must be listed. A parameter is described as follows: ```tt [in req | in opt | out] : @@ -88,7 +89,7 @@ There are two types of annotations: natural language annotation and implementati #### Natural language annotations Natural language annotation, as its name, is the annotation related to natural language and it will be translated to different languages based on users' profile. -It's denoted by `#_[=]`. +It's denoted by `#_[=]`. Each function is required to have `confirmation` natural language annotation: A string used to construct the final confirmation question before a rule is created @@ -98,8 +99,8 @@ You can refer to required arguments with `$argname` or `${argname}` (the latter the argument is immediately followed by a letter, number, or underscore). #### Implementation annotations -Implementation annotation is used for describing the implementation details of a function. -This is denoted by `#[=]` (without the underscore as in natural language annotation). +Implementation annotations are used for describing certain implementation characteristics of a function. +They are denoted by `#[=]` (without the underscore used by natural language annotations). Here is a list of required implementation annotations for functions: - `doc`: This is used for documentation for developers. @@ -108,6 +109,6 @@ if it is monitored. It takes a time interval, e.g., `#[poll_interval=5min]`. A lot more optional annotations are supported in ThingTalk - for not only functions but also parameters and -device classes. +device classes. They will give you better user experience and better natural language support for your device. Refer to [annotation reference](/doc/thingpedia-annotations.md) for the full list. diff --git a/doc/thingpedia-tutorial.md b/doc/thingpedia-tutorial.md index 123f70337..1abecea94 100644 --- a/doc/thingpedia-tutorial.md +++ b/doc/thingpedia-tutorial.md @@ -65,7 +65,7 @@ shown in the device list when users use `help` in Almond. `JS Device Package` is an optional package depending on the type of your device specified in the manifest. It contains the JS code describing the details of the configuration and -function behavior. This will be introduced in detail [later](#writing-js-device-package) in this tutorial. +function behavior. This will be introduced in detail [later](#writing-js-device-package) in the tutorial. --- @@ -76,9 +76,6 @@ It defines the _device class_ you want to create whose name is the `ID` defined Check [Writing Device Class](/doc/thingpedia-tutorial-manifest.md) for the instructions on how to write a device class. -A ThingTalk editor is provided to help you write it, which can be found at the -[creation page](/thingpedia/upload/create). - --- ## Writing the dataset @@ -100,199 +97,8 @@ Depending on the type of your device, you might need to provide a _device package_ containing the Javascript code to describe more details about how the device is configured and how each function behaves. This package will need to be uploaded at the metadata page before you submit. - -### The layout of a device package -The Thingpedia API assumes a precise layout for a device package, which -must be a zip file containing exactly the JS files and the package.json, -as well as any dependency you need. You should not assume any nodejs -module beyond the 'thingpedia' module illustrated here - if you need any, -bundle them in your zip file. - -If there is no dependency needed and all your code is in one file, you can -also upload the file directly, and we will generate the package.json and zip file for you. - -If you are using a Mac, please use command line to compress the folder: -`zip -r xx.zip your-folder-name`. -Compressing from the right-click menu in Mac will create a new folder which -makes the system fail to find the files in the root directory. - -The primary entry point (i.e., the one named as "main" in package.json) -should be a _device class_. You would instantiate the device class -from the API and set it directly to `module.exports`, as in - -```javascript -const Tp = require('thingpedia'); - -module.exports = class MyDeviceClass extends Tp.BaseDevice { - constructor(engine, state) { - super(engine, state); - // constructor - } - - // other methods of device class -}; -``` - -(Our code and examples make heavy use of modern JavaScript features, also known as ES2015. -If you are not familiar with the class syntax, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)) - -Then, for each query or action you want to expose, you would -add functions to your device class with prefix `get_` or `do_` respectively. -So for example, if -you want to expose query `get` for The Cat API, -you would modify your `device.js` as follows: - -```javascript -const Tp = require('thingpedia'); - -module.exports = class CatAPIDevice extends Tp.BaseDevice { - constructor(engine, state) { - super(engine, state); - // constructor - } - - get_get() { - // return cat pictures - } -}; -``` - -### The `BaseDevice` API - -When you create a device class, you declare -a subclass of [`Tp.BaseDevice`](https://github.com/Stanford-Mobisocial-IoT-Lab/thingpedia-api/blob/master/lib/base_device.js), -the base class of all device classes. - -To construct the subclass, three properties are required: `uniqueId`, `name`, and `description` -Different from the `ID` in the metadata, `uniqueId` uniquely identifies the device **instance** -of a user. For example, a user may configure two different Twitter accounts, and they will need -different IDs in Almond. A common way is to concatenate the device ID, a dash, and then a specific -ID for the corresponding account. E.g., `"com.twitter" + this.state.userId`. -Similarly, `name` and `description` will be used in [My Almond](/me) and they should be different -for different accounts, so that users can easily tell which account an instance associates with. -For example, for Twitter, the name could be `"Twitter Account for " + this.state.screenName`. - -For The Cat API, since it is a public service and there will be only one instance for each user, -we can just use the same ID, name, and description in metadata: - -```javascript -constructor(engine, state) { - super(engine, state); - - this.uniqueId = 'com.thecatapi'; - this.name = "The Cat API"; - this.description = "Where every day is Caturday!"; -} -``` - -The full reference of the `BaseDevice` class is given in the [Thingpedia interface reference](/doc/thingpedia-helpers.md#class-basedevice). - -### Handling authentication and discovery - -Unlike The Cat API, lots of devices will require some kind of authentication. -Three ways to do -authentication are supported, including `basic` (traditional username and -password), `oauth2` (OAuth 1.0 and 2.0 style authentication), and `discovery` -(authentication by discovery and local interactive paring). Here's a -[complete guide for authentication and discovery](/doc/thingpedia-device-intro-auth-n-discovery.md). - -### HTTP helpers - -Our system provides a generic interface `Tp.Helpers.Http` for basic HTTP request. -These are wrappers for [nodejs http API](https://nodejs.org/api/http.html) -with a Promise interface. - -Two of the most useful interfaces are probably -`Tp.Helpers.Http.get()` and `Tp.Helpers.Http.post()`, which deal with HTTP GET request -and POST request, respectively. We will see an example in practice in the next section. - -A full list of the available APIs can be found in -[Thingpedia interface reference](/doc/thingpedia-helpers.md#module-helpers-http) - -### Query and action -Recall that we separate Thingpedia functions in two different types: query and action. -A query returns data and makes no side effect, while action does not return any data but makes side effect to the world. - -Both query and action take an Object to get the value of input parameters. -For example, `get` function in The Cat API has one input parameter `count`, thus the function will look like: -```javascript -get_get({ count }) { - // returns $count cat pictures -} -``` - -A Query always returns an array of Object specifies the value of each output parameter. -For example, `get` function in The Cat API has 3 output parameters `image_id`, `pictuer_url`, and `link`, -the output should look like: -```javascript -get_get({ count }) { - ... - return [{ image_id: ..., picture_url: ..., link: ... }]; -} -``` - -Now let's implement the `get` function for The Cat API for real with HTTP helpers. -The function should look like this: -```javascript -get_get({ count }) { - count = count || 1; // fetch 1 cat by default - const url = URL + '&results_per_page=' + count; - return Tp.Helpers.Http.get(url).then((result) => Tp.Helpers.Xml.parseString(result)) - .then((parsed) => { - const array = parsed.response.data[0].images[0].image; - return array.map((image) => { - return { image_id: image.id[0], - picture_url: image.url[0], - link: 'http://thecatapi.com/?id=' + image.id[0] }; - }); - }); -} -``` - -`count` is an optional input parameter, we set it to 1 if it's left unspecified. -Then we call `Tp.Helpers.Http.get()` to the URL of the API endpoint. -The Cat API returns the result in `XML` format, so we parse it with `Tp.Helpers.Xml.parseString()` -to extract a JS Object. -Then we find the values we need and assign them to the corresponding parameters for return. -Note that, we used [`Array.prototype.map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) -to create the returned Array. -Don't be fooled by the final `return` statement, we are still returning an Array. - -### The first JS package: The Cat API -Put all the components together, we have The Cat API code as follows. -Since no library other than `thingpedia` is needed for this package. We can simply upload the `.js` file, -and the `.zip` package will be generated automatically. -```javascript -"use strict"; - -const Tp = require('thingpedia'); - -const URL = 'http://thecatapi.com/api/images/get?api_key=&format=xml&type=jpg,png'; - -module.exports = class CatAPIDevice extends Tp.BaseDevice { - constructor(engine, state) { - super(engine, state); - - this.uniqueId = 'com.thecatapi'; - this.name = "The Cat API"; - this.description = "Where every day is Caturday!"; - } - - get_get({ count }) { - count = count || 1; - const url = URL + '&results_per_page=' + count; - return Tp.Helpers.Http.get(url).then((result) => Tp.Helpers.Xml.parseString(result)) - .then((parsed) => { - const array = parsed.response.data[0].images[0].image; - return array.map((image) => { - return { image_id: image.id[0], - picture_url: image.url[0], - link: 'http://thecatapi.com/?id=' + image.id[0] }; - }); - }); - } -}; -``` +Check [Writing JS Device Packages](/doc/thingpedia-tutorial-js-package.md) +for its tutorial. --- diff --git a/views/thingpedia_dev_sidebar.pug b/views/thingpedia_dev_sidebar.pug index 2c3567988..c894231ed 100644 --- a/views/thingpedia_dev_sidebar.pug +++ b/views/thingpedia_dev_sidebar.pug @@ -22,7 +22,7 @@ nav#doc-sidebar li(class=(currentPage === 'thingtalk-intro' ? 'current' : '')) a(href='/thingpedia/developers/thingtalk-intro.md') Introduction to ThingTalk - li(class=(['thingpedia-tutorial', 'thingpedia-device-intro-auth-n-discovery', 'thingpedia-tutorial-dataset', 'thingpedia-device-with-zero-code', 'thingpedia-tutorial-manifest', 'thingpedia-error-handling'].indexOf(currentPage) >= 0 ? 'current' : '')) + li(class=(['thingpedia-tutorial', 'thingpedia-device-intro-auth-n-discovery', 'thingpedia-tutorial-dataset', 'thingpedia-device-with-zero-code', 'thingpedia-tutorial-manifest', 'thingpedia-error-handling', 'thingpedia-nl-support'].indexOf(currentPage) >= 0 ? 'current' : '')) p.doc-sidebar-subtitle For Thingpedia Contributors p.doc-sidebar-subsubtitle Tutorials ul @@ -30,13 +30,16 @@ nav#doc-sidebar a(href='/thingpedia/developers/thingpedia-tutorial.md') Writing Thingpedia Entries li(class=(currentPage === 'thingpedia-tutorial-manifest' ? 'current' : '')) - a(href='/thingpedia/developers/thingpedia-tutorial-manifest.md') Writing Device Class + a(href='/thingpedia/developers/thingpedia-tutorial-manifest.md') Writing Device Classes li(class=(currentPage === 'thingpedia-tutorial-dataset' ? 'current' : '')) a(href='/thingpedia/developers/thingpedia-tutorial-dataset.md') Adding Natural Language p.doc-sidebar-subsubtitle Topic Guides ul + li(class=(currentPage === 'thingpedia-nl-support' ? 'current' : '')) + a(href='/thingpedia/developers/thingpedia-nl-support.md') Natural Language Support for Devices + li(class=(currentPage === 'thingpedia-device-intro-auth-n-discovery' ? 'current' : '')) a(href='/thingpedia/developers/thingpedia-device-intro-auth-n-discovery.md') Authentication & Discovery From 037343587227e64a2554a53b205718900b5be230 Mon Sep 17 00:00:00 2001 From: Silei Xu Date: Tue, 23 Oct 2018 14:48:55 -0700 Subject: [PATCH 8/8] Minor changes --- doc/thingpedia-tutorial-js-package.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/thingpedia-tutorial-js-package.md b/doc/thingpedia-tutorial-js-package.md index 202a8f4fd..8e3185c63 100644 --- a/doc/thingpedia-tutorial-js-package.md +++ b/doc/thingpedia-tutorial-js-package.md @@ -1,8 +1,10 @@ # Writing JS Device Packages -Depending on the type of your device, you might need -to provide a _device package_ containing the Javascript code -to describe more details about how the device is configured and how each function behaves. -This package will need to be uploaded at the metadata page before you submit. +If you choose to use the loader provided by `@org.thingpdedia.v2` in your manifest, +a _device package_ is required for your device. +It contains the Javascript code describing the details about how your device +will be configured and how each function behaves. +In the following, this tutorial will continue using The Cat API as an example +to show how the package is organized and how to write it. ### The layout of a device package The Thingpedia API assumes a precise layout for a device package, which @@ -163,8 +165,8 @@ Don't be fooled by the final `return` statement, we are still returning an Array ### The first JS package: The Cat API Put all the components together, we have The Cat API code as follows. -Since no library other than `thingpedia` is needed for this package. We can simply upload the `.js` file, -and the `.zip` package will be generated automatically. +Since no library other than `thingpedia` is needed for this package. We can simply upload the `.js` file +in the metadata page, and the `.zip` package will be generated automatically. ```javascript "use strict";