|
|
|
# Frontend plugins
|
|
|
|
|
|
|
|
## Speech
|
|
|
|
|
|
|
|
You may include speech support for your plugins. The implementation must reside in the `speech` folder in your plugin.
|
|
|
|
|
|
|
|
You are required to have at least a basic speech handler entry point file. It must be named after `[Plugin]SpeechHandler.js` and must reside in the `speech` folder in your plugin. The system will include all speech handlers upon boot - there is no need to change any bootstrap files to have your plugin working.
|
|
|
|
|
|
|
|
The structure would look like this:
|
|
|
|
|
|
|
|
```bash
|
|
|
|
.
|
|
|
|
├── plugins
|
|
|
|
│ └── WeatherPlugin
|
|
|
|
│ └── speech
|
|
|
|
│ └── WeatherSpeechHandler.js
|
|
|
|
```
|
|
|
|
|
|
|
|
A Speech handler must specify the following data in its default export object:
|
|
|
|
|
|
|
|
* `(Callable) handleSpeech`
|
|
|
|
* `(Object) instructions`
|
|
|
|
|
|
|
|
The `handleSpeech` attribute must be callable that optionally accepts `(text, history)` where the first parameter contains the speech-to-text output from the system speech handler. The second parameter will receive an array with the current speech card history. You can use this array to determine whether context aware speech entries should be handled or not.
|
|
|
|
|
|
|
|
The `(Object) instructions` attribute must contain an object with at least an `(String) icon` and `(Array) examples` attribute. The `examples` attribute must specify at least one example trigger.
|
|
|
|
|
|
|
|
Example code:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
import helpers from '../../../application/plugins/SpeechHandlerHelpers'
|
|
|
|
|
|
|
|
const TRIGGERS = helpers.createTriggers([
|
|
|
|
[handleWeatherForPlace, '((zon(nig)?|regen(t het|achtig)?|onweert?|weer)|((warm|koud|weer) is het)) (.* )?in (?<place>[a-zA-Z-]+)\\??$'],
|
|
|
|
[handleHistory, '(en|ook) (.* )?in (?<place>[a-zA-Z-]+)\\??$']
|
|
|
|
])
|
|
|
|
|
|
|
|
// handleWeatherForPlace(match, history) {}
|
|
|
|
// handleHistory(match, history) {}
|
|
|
|
|
|
|
|
export default {
|
|
|
|
'handleSpeech': helpers.createTriggerRouter(TRIGGERS),
|
|
|
|
'instructions': {
|
|
|
|
'icon': 'wb_sunny',
|
|
|
|
'examples': [
|
|
|
|
'Hoe warm is het in Groningen?',
|
|
|
|
'Regent het in Eindhoven?',
|
|
|
|
'... en in Utrecht?'
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Please note the use of the `createTriggerRouter()` helper function. It will automatically set up a matcher based on the specified regex array. Upon matching one of these regexes, it will route the request to the specified handler function.
|
|
|
|
|
|
|
|
Handler functions, regardless of them being called through the `createTriggerRouter()` or directly from your `handleSpeech()` function will need to return a promise.
|
|
|
|
|
|
|
|
You will need to resolve the promise upon successfully processing the speech request. You must reject the promise if you determine that you are not able to fulfill the request. In that case, the System speech handler will continue searching for other plugins that may be able to handle the request. This is especially important when doing context-aware checks in your speech handlers.
|
|
|
|
|
|
|
|
Have a look at the following code snippet to understand more about the promise that you will need to return in your speech handler functions:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
function handleWeatherForPlace (match, history) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
resolve({
|
|
|
|
response: 'Met 18 graden is het zonnig in ' + match['place'],
|
|
|
|
widget: {
|
|
|
|
component: 'WeatherSpeechCard',
|
|
|
|
temperature: 18,
|
|
|
|
place: match['place']
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This example handler will always resolve the promise. You could imagine the handler calling `reject()` in its promise if the place the user searched for was not found, for example.
|
|
|
|
|
|
|
|
You must resolve your promise by passing an object that implements the following structure:
|
|
|
|
|
|
|
|
* `(String, optional) response`
|
|
|
|
* `(Object, optional) widget`
|
|
|
|
|
|
|
|
If you choose to set the `response` attribute, the system will pass it to the speaker. It must therefor be a string. Please remember that Google's Text to Speech API imposes a limit on the length of this string, though we're not sure what that limit is. Please try to avoid sending huge chunks of text through the `response` attribute either way.
|
|
|
|
|
|
|
|
If you choose to set the `widget` attribute, the system will pass it into the history and render the given `component`. You may also pass extra values into the `widget` object - these will get passed into your component and you may also access them in upcoming speech requests to determine context-aware requests. |
|
|
|
\ No newline at end of file |