Jeedom (En)

Introduction

Pour une documentation en Français, veuillez cliquer ici.

To be able to integrate our powerful voice technology with your Jeedom platform, we developed an official Snips plugin, which allows you to trigger actions/scenarios and get device/sensor values from Jeedom platform by using natural language and speech recognition.

If you have any issues/ questions/ feedbacks or just want to join the discussion with other Snips plugin users, you can always do it through one of these ways:

If you want a 3D casing for your satellites, please find below the two .stl files (bottom and top):

Getting Started

There are 4 main steps you need to follow to set up you snips voice assistant correctly to make it work with your Jeedom platform.

  1. Start

1. Setup a snips device

There are two ways you can setup your Snips-Jeedom system:

  • Snips and Jeedom running separately on two devices (recommended)

  • Snips and Jeedom running on the same devices

No matter which configuration you choose, installing snips software is identical, please refer to the previous section to get your device ready.

2. Having your Jeedom app and deploy assistant

For this step, you are going to use snips web console.

Create a new assistant, give it a name, and then please select French as language option. As shown in Figure 2.2.1.

The app is in French , more languages option will be coming soon.

Figure 2.2.1 Creating a new assistant

Click [Add an App], and then find [JeedomOfficiel], add this to your assistant, as shown in figure 2.2.2

You need to uncheck the "App with Action" parameter since JeedomOfficiel isn't an app with action. Otherwise you will not find it in the app store.

Figure 2.2.2 Add official Jeedom app

Once you are done with these steps, your assistant will be automatically saved. If you want to test it, please click on the microphone icon on the top right, as shown in figure 2.2.3, then simply speak through your computer microphone, you can also type in a query.

Figure 2.2.3 Testing a query

If everything works fine, then we can deploy this assistant to your local device (Raspberry Pi)

Regarding deployments, it has already been addressed within previous chapters, you can find it here.

3.Installation of Snips plugin on Jeedom

You can find Snips Plugin on Jeedom market. Simply direct to the market page then find Snips under free category or search snips like shown in figure 2.3.1

Figure 2.3.1 A Direct to Jeedom Market
Figure 2.3.1 B Find Snips plugin

Once it has been installed, activate the Snips plugin as you do for the other plugins, then click [Relaunch] to install all the necessary dependencies. Once it's done, click [(Re)Start] to make the plugin works. A correctly setting up should look like figure 2.3.2.

Figure 2.3.2 Configuration example

4. Configurate Snips plugin

For now you must properly have Snips plugin installed. If not please make sure you've followed all the stepped covered above.

Now that everything is well installed, one of the most important configuration is to input the correct [IP address of the master snips device] (Plugin configuration page).

  • If you set your snips running separately from Jeedom, you can use command sam devices to find the correct ip address. Alternatively, you can go onto your router's admin page to find it. (If you don't know what is sam command, please check out here)

  • If Snips and Jeedom are both running on the same device, this ip address should always be 127.0.0.1

If we now go to Snips plugin page, there shouldn't by anything. But as long as the configuration information is filled, we can now load the assistant. Click [Load Assistant], then follow the pop-up prompts to have all the intents to be loaded into Jeedom platform (The first time, you should choose [Reload assistant without bindings] option). This step is shown in the figure 2.4.1.

Figure 2.4.1 Loading assistant

Once the assistant is loaded, all the intents will be listed on snips plugin page, shown in figure 2.4.2.

Figure 2.4.2 A loaded assistant

If the snips' site ip address is not correct, this step can not successfully load your assistant.

From now, all the configuration is done, you can start playing with your existing devices.

5. Start

If you already understand how does snips works, that's great. But if you don't, we would simply explain that Snips can capture your oral sentence, transfer it into a structured data set which is composed of intents and slots. In other words, Snips is able to extract the important information from your sentences (regardless of how you pronounce it) and provide you with a data set format (Json) with the important data extracted.

Let's take an example, when you say "Hey snips, turn on the light in the living room", this sentence will be finally converted into a dataset which looks like this:

{
"input": "turn on the light in the living room",
"intent": {
"intentName": "coorfang:lightsSet",
"probability": 0.83969486
},
"slots": [
{
"rawValue": "living room",
"value": {
"kind": "Custom",
"value": "living room"
},
"range": {
"start": 25,
"end": 36
},
"entity": "house_room",
"slotName": "house_room"
}
]
}

In this data set, the intent is detected and slot values will be used in Snips plugin to trigger a speictif action/ scenario etc..

Turn on/off a light

Find the intent which correspond to turn on the light, click it, this will leads you to the binding configuration page. In this example, the lightSetJeedom intent is the one which will be detected and sent to Jeedom.

In the binding configuration page, click [Attach a new binding], give a name to this binding configuration, then you will have a configuration table, as shown in figure 2.5.1

Figure 2.5.1 Attach a new binding

In the configuration page you can specify a condition, or not. Here we consider the condition is living room. So it means that when we say "turn on the light in the living room", this binding will be executed because your pronounced "living room" and in the condition you've indicated "living room".

Basically Snips will listen to your sentence, it will recognize that your sentence belonged to the lightSetJeedomintent (...Snips magic) and will then look for all the configuration file within this intent to see if it can find some matching conditions.

A completed binding configuration looks like figure 2.5.2.

Figure 2.5.2 A finished binding

As you can see, we added an action just like you add it in your Jeedom scenario for instance. This action will be executed when the condition validation is passed.

Note that if you do not give a condition, this binding will be executed when you simply say "Please turn on the light" but not be executed when you say "Please turn on the light in the living room".

About [TTS] message, you can use {#} to indicate where you want to insert a specific system value, then a selection input bar will appear automatically on the right side. As an example, here we would want the TTS to say "Ok I'm turning the living room light on" so we would have to write "Ok I'm turning the {#} light on".

You may note that there is a [Test Play] button. This is designed to let you test the TTS you write, but at the moment, because you haven't pronounced the sentence onto Snips, there is not value in #[Snips-Intents][lightsSetJeedom][house_room]#

variable yet, so the TTS will likely say: "La lumière dans le (...) a été allumée."

Plugin Configurations

IP address of the master snips device

You can put either a hostname or an ip address. If you only have one Snips device, it will uses its own ip address. But if you have satellites (like one in every room), you should indicate the ip address of the master device.

For example, if snips and Jeedom are running on the same device, you can either put "localhost" or "127.0.0.1".

Default feedback

This message will be played when a Jeedom intent has been detected and no corresponding binding has been found. You can use [A|B|C] format to separate different reply responses. Every time, only one of them will be played randomly. A configured default feedback is shown in figure 3.2.1

Figure 3.2.1 Default feedback configuration

Here the TTS will randomly play "Désole, je n'ai pas compris" or "Désolé, je ne trouve pas les actions". You can use as many different responses as you want.

Dynamic Snips TTS

When selecting a snips tts command in binding configuration with this option checked, the reply tts will be played on the device which received the command.

Features

This section will mainly talk about the features which we have built for Snips plugin, each sub-topic will focus on a specific function with some help on how you should be using it.

A. Load/ Delete assistant

1. Load / Reload

Load and reload are called "Load assistant" in the plugin. If you want to have all your current bindings loaded into the new assistant, select "Reload assistant with current binding" option. If you want to load a new blank assistant as start from scratch, use "Reload assistant without bindings". No matter which option you choose, we highly recommend you to export your bindings before reloading. A load option selection box is shown in figure 4.1.1.

Figure 4.1.1 Screenshoot of loading options

Ideally, only reload your assistant if one of these 3 conditions has been changed:

  • You modified an intent name

  • You added / deleted slots

  • You added / deleted intents

In order to let users implement multiple apps (weather, calculation, music ...) within a same assistant, Snips-Jeedom plugin will only load Jeedom related intents. The plugin will only load intents containing 'jeedom' or 'Jeedom' word in the intent name.

Good examples of Jeedom intent name are:

  • MyCustomisedIntentJeedom

  • jeedomMyCustomisedIntent

When you create your homemade intent, be sure to follow this rule.

2. Delete

Delete operations will completely remove all the snips related objects / devices / commands. If you want to delete Snips plugin, you should find a remove button on the plugin configuration page.

B. "OR" condition / synonyms

As snips is an Artificial intelligence voice assistant, synonyms can be handled when a slot is created. But if you want to merge some "bindings" which have different conditions but triggering the same actions, this feature can help you achieve this easily.

For example, in your house living room and dinning room might be sharing the same light. So you may want to say "hey snips, switch on the light in the dinning room" or "hey snips, it's too dark in the living room", in fact these two sentences have two different house_room slots values, but they are sharing the same action, which turns on the same light.

For this situation, you can put both "living room" and "dinning room" as one binding's condition, separate different values by using ,. A completed binding is shown in the following figure 4.2.1.

No matter which house_room you pronounce, the same action will be performed, you don't have to create two bindings.

Figure 4.2.1. Using "OR" condition

Note: If you want to trigger this binding without any condition, please delete all the conditions under [Condition(s)] section. If you just delete the value of the condition, program will consider that the condition is still exist with value "" (empty string).

C . Assign an intensity percentage to light brightness

In this example, we are going to see how to make a query with percentage values such as "Hey snips, please set the light in the living room to 50%". The main difference between 'turn on a light' and 'set a light to a intensity percentage' is the need to assign the slot value into the command for the later one.

Since this operation is lightSetJeedom intent, let's click onto that intent and attach a new binding. For this, you need to choose the action corresponding to "changing brightness", a complete configuration table should like figure 4.3.1.

Figure 4.3.1 Setup for changing brightness

As you can see, the action box is filled by Luminosité command instead of on or off from the former example. If you are an experienced Jeedom user, you may already know that these kind of commands need to be executed with a value. So for this example, we are loading this value from one of the slot value that is coming from this intent, which is intensity_percentage.

Why is there a "value remapping" input area just below the value input box ? Since the type of this slots value selected is built in datatype "snips/percentage", the plugin will automatically detect and display this box.

For the different way to represent an intensity, they may have a different range (typically from 0~100 or 0~255). In order to be able to adapt to all conditions, we made this function to let users adapt that range for various different devices. You should check your device range value in Jeedom (for instance Philips Hue is 0 to 255, Fibaro FGD-212 0 to 99 ...)

D. Increase or dim the light brightness (without using percentage)

If you followed and understood the previous examples, it's easy to understand how does the Snips plugin works. To sum it up, for each action you want to make, the target device must have an action as shown in the following example:

when we want to turn on a light, there is a On command, same for off. When a user want to set a light to a fixed luminosity, there is a luminosity command that can be triggered.

At Snips we believe that besides turning on/off or set a fixed value, a user should also be able to say "Please give me more light in the living room". To achieve this, we defined a corresponding intent, which is calledLightsTurnUpJeedom to increase light brightness and LightsTurnDownJeedomto dim it.

However the difficulty comes when you are about to make a binding configuration for this, because most of the light plugins do not provide an action command to make the light brighter or to dim it down.

The solution is that you can create a scenario which can simulate this operation:

First, let's go to the scenario page, and create a new one, name it as you wish(in our example we named it "Dim the light") In the configuration page (Shown in figure 4.4.1), you do not necessarily have to change anything, not even add a trigger. That's because this scenario will be called/triggered by Snips plugin directly instead of being triggered by a system event.

Figure 4.4.1 Configuration page for "Dim the light"

Then click on to the "scenario" tab, add a new [code] block. Copy and past the following code.

// User configuration
$VARS = array(
"OPERATION" => "DOWN", // Use "UP" or "DOWN"
"LIGHTS" => array(
// Light 1
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip Right][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip Right][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2 // Change in percentage, if 20%, then put 0.2
),
// Light 2
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip Left][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip Left][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2
),
// More light goes here..
));
// Execution
snips::lightBrightnessShift(json_encode($VARS));

Inside this code, two lights are considered as a group. It means they will be turned up or down at the same time. If you have only one in the room, just remove

// Light 2
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip Left][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip Left][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2
),

in the code block. However if you have more that 2 lights in your room, simply add one more configuration array after More light goes here comment.

A code block with a group of 4 lights would look like this:

// User configuration
$VARS = array(
"OPERATION" => "DOWN", // Use "UP" or "DOWN"
"LIGHTS" => array(
// Light 1
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip Right][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip Right][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2 // Change in percentage, if 20%, then put 0.2
),
// Light 2
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip Left][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip Left][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2
),
// Light 3
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip center][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip center][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2
),
// Light 4
array(
"LIGHT_BRIGHTNESS_VALUE" => "#[Apartment][Mirror Strip back][Etat Luminosité]#",
"LIGHT_BRIGHTNESS_ACTION" => "#[Apartment][Mirror Strip back][Luminosité]#",
"MIN_VALUE" => 0,
"MAX_VALUE" => 255, // Max brightness value
"STEP_VALUE" => 0.2
),
// More light goes here..
));
// Execution
snips::lightBrightnessShift(json_encode($VARS));

Before saving, there are a few things under [User configuration] in the code block that needs to be changed (Do this for each light array).

  • "OPERATION"

    • This describes operation, depending on the used intent, put DOWN or UP.

  • "LIGHT_BRIGHTNESS_VALUE"

    • This is the command which contents the brightness value of the light.

  • "LIGHT_BRIGHTNESS_ACTION"

    • This is the action command which can set the light to a fixed brightness.

  • "MIN_VALUE" and "MAX_VALUE"

    • These two defines the brightness range(Typically 0~99 or 0~255).

  • "STEP_VALUE"

    • This describes the value percentage you want to shift every single time, 0.1 would be 10% , 0.2 would be 20% and so on.

Make sure you do not change anything under the [Execution] comment.

For our Jeedom setup, a completed code block to increase brightness for 2 lights should look like figure 4.4.2.

Figure 4.4.2 A completed code block to increase brightness for 2 lights.

In this example, the idea is to explain how you can make this function to work. This code block is basically an action to shift your light up or down. Here we only have one code block which does an operation for a configured group of light.

Once you understand how it works, feel free to add other blocks in your Jeedom scenarios to trigger this action for your living room, bathroom and so on.

E. Dynamic TTS

Snips plugin has a very nice dynamic TTS function, which allows you to add variables to TTS message. To achieve this, create a normal TTS message, then use {#} to replace where the variable should be added. There will be a command input box appearing on the right side

A complete TTS message with variables configured is shown in figure 4.5.1.

Figure 4.5.1 Dynamic tts example

Dynamic TTS also support remapping of a binary value. For example, light / windows device will have a binary info command which indicate if the light / window is switched on/off or open/close, so their value can be either "0" or "1" in the system. However, as human we don't want to here a TTS like "The light is turned 1" or "The window in the kitchen is 0". To solve this issue, when you select a binary command, this value can be remapped to a word. Figure 4.5.2 shows an example of using remapping function.

Figure 4.5.2 Binary value remapping example

F. Non-linear TTS reply

A configured TTS will always be played after its binding has been executed. If there is only one sentence to respond, you may feel it's too "robotic".

Non-linear TTS feedback gives some random responses to make it sound more spontaneous, which allows you to set up a dynamic TTS template. Each time a playing is performed, TTS will generated all the possible sentences and only one of them will be played as feedback randomly.

The template grammar follows original Jeedom logic, using [ ] to contain dynamic list and using | to separate all the different possibilities. A configured example is shown in figure 4.6.1.

Figure 4.6.1 Non-linear TTS example

G. Using Snips-TTS audio player in scenario

Snips TTS player is built as an action command in Jeedom system, which means that you can use it in the other plugin / scenario as well. An example using Snips TTS command in scenario is shown in figure 4.7.1.

Figure 4.7.1 Play "bonjour" on the satellite in bedroom

H. Import / Export binding configurations

A well configured Snips plugin can have couple of bindings for each intent. We strongly suggest you to export it before reloading an assistant. It will export a Json file with all of your bindings so that you can import those in the future in case of an issue / bug.

If you want to have access to these output configuration files, you can do it through SSH, you can find those under:

/var/www/html/plugins/snips/config_backup/xxx.json

Or you can download them via your browser (Replace hostname and config name with yours):

http://hostname/plugins/snips/config_backup/xxx.json

I. Callback Scenario

Snips binding configuration page is designed for most basic use-cases. If you have already used it a little bit, you may notice that a 'snips-binding' configuration is more or less like a sub-function of Jeedom scenario.

So alternatively, instead of creating a couple of binding configurations, you can have one compatible callback scenario to handle all the voice requests for one intent or multiple intents. After specify the callback scenario, you can also check some of the necessary snips_tags passed to the scenario.

The available snips tags are shown below:

Tags

Description

#plugin#

The value is always: snips

#identifier#

The value is composed of Plugin::IntentId::Binding

#intent#

The value is Intent_Name

#<SLOTS>#

This tag is dynamic depending on which slot/ slots are in the coming request. Multi slots value will be combined as one slot value with sign &. For example: if we say: hey snips, turn on the light in the living room and the bedroom. The slot passed will be shown like #house_room#="living room&bedroom"

#siteId#

The value is the id of the device that received voice command

#query#

The value is the text of the request

#probability#

The probability of the detection, between 0 and 1, 1 being sure

The example here uses 2 intents(LightsSetJeedom and LightTurnOffJeedom). Both intents are using the same callback scenario - LightsHandler.

Figure 4.9.1 Use LightHandler scenario for lightsSetJeedom intent
Figure 4.9.2 Use LightHandler scenario for lightsTurnOffJeedom intent

Then we need to create a scenario LightsHandler to handle all the requests. There is nothing special for this scenario, it does not even need to set a trigger since this will be triggered by snips binding but system event. A completed handler scenario is shown in figure 4.9.3.

Figure 4.9.3 Completed Lighthandler scenario

There are 2 main sections for this scenario, the first IF/THEN/ELSE block and the last two IF/THEN/ELSE blocks.

The first section is used to handle some default situation, such as if there is no house_room slot detected, give site_name as the default. If there is a value, then put it into a variable that all the rest part can use.

The second section is to react to different requests following different intents and slots value. There is no action specified in the example screenshoot, but you can fill them with the correct configuration in your house/room.

J.Reset info command value

This is allowing you to embed Snips binding and slots value with some of your existing scenarios. As we know, snips plugin binding can not only execute an action, but also trigger a scenario.

Let's take an example, we have a scenario used to read a customised Xiaomi switch button that can be trigger with different press (Click, double_click, Long_press_click) the different actions will be performed based on how you press the button OR if you pronounce a specific Snips intent value.

An example is show in figure 4.10.1

Figure 4.10.1 Scenario used to switch on TV

In the condition box, Snips slot value can be added as a "OR" condition. This scenario used to be triggered only by a button click, now Snips can also trigger it.

However, an issue arise as some button / device are not "refreshed" once being used. For instance, the "Xiaomi" button has 3 way of being pressed, if you click it once, then the system will store the "click" state variable indefinitely until you click it differently. This is an issue because if you have a complex scenario and values are not reseted then the rest of the scenario might be triggered even if you wanted to trigger only the first block using Snips intent.

The solution is to "reset" the device value using a small code block.

$VAR = '#[Apartment][Cub button][click]#'; // command which need to be reseted
$cmd = cmd::byString($VAR);
$cmd->setCache('value', '');

Alternatively, you can use the trigger function within scenario to strict your condition expression.

So instead of having a simple condition like:

#[salon][netflix_button][clic]#=="click" OU #[snips-intents][TurnOnJeedom][device_name]#=="télévision"

we can strict the condition to:

(trigger(#[salon][netflix_button][clic]#)==1 ET #[salon][netflix_button][clic]#=="click") OU (trigger(#[snips-intents][TurnOnJeedom][device_name]#)==1 ET #[snips-intents][TurnOnJeedom][device_name]#=="télévision" )

K. Use 'ASK' command

Sometime, you may want to set some actions in your scenario, which can use Snips to ask you a question then react according to your answer. For example, we would want Snips to ask us to turn on the light after a specific time. Then we can make a scenario which checks if the sunset flag is set, if so then it would trigger an ask command. An example configuration is shown in figure 4.11.1.

Figure 4.11.1 A use case of ask command

To achieve this function, we need to create an intent which is used to get the answers after a TTS question. On the Snips console, fork the official Jeedom app, create a new intent called GetAskResponseJeedom (You can name it whatever you like) as shown in figure 4.11.2.

Figure 4.11.2 GetAskResponseJeedom intent

We will use this intent to get all possible answers, so it needs a slot which represents this answer value. Since this will be a customized slot, so you have to create it. We named it answer with the required switch checked. (Make it required, if Snips does not get the answer, it will re-ask you again and again.) The example will simply have the answer 'Yes' or 'No', so we name slot_type 'YesNo'. Then add values yes and no with their synonyms. A finished answer slot is shown in figure 4.11.3.

Figure 4.11.3 Answer slot configration

Whit all the necessary components built, you need to re-deploy your assistant and re-load it on jeedom plugin.

Then you will have the GetAskResponseJeedom intent loaded, go to the binding configuration, just add one binding record which assigns the answer value to a jeedom variable.(Shown in figure 4.11.4) Here the variable name is 'answer'.

Figure 4.11.4 GetAskResponseJeedom intent binding configration

After all of these steps, you can start to build your own scenario to use this function. By filling the ask command with all the necessary information:

Input box

Value

Question

Text question message.

Response

Response intent and the answer slot name. Follow the formate :[YOUR_SNIPS_USERNAME:GetAskResponseJeedom](answer) Beware that you need to put your snips username, you can find this on your console profile page.

Variable

The variable to save answer value, should be the same with the one in the GetAskResoonseJeedom binding.

Delay

This is the timeout protecting jeedom from infinite waiting. 10 seconds is recommended.

Command

The command to perform this function. It's your snips TTS devices, called ask

Typically you should put something like #[Snips-Intents][Snips-TTS-default][ask]#

A correctly filled ask command is shown in figure 4.11.5.

Figure 4.11.5 A well filled ask command options

Do not forget to put your snips username before the intent name, otherwise this will not work.

We have created a small demo scenario that shows a complete scenario in figure 4.11.6.

Figure 4.11.6 Demo scenario for ask command

JeedomOfficial APP

Here is the up to date list of intents:

  • OpenCoverJeedom: To open your window, window blind and so on

  • CloveCoverJeedom: To close your window, window blind and so on

  • WindowDevicePauseJeedom: To stop your window (blind) at its current position

  • ThermostatShiftJeedom: To shift up/down the current temperature

  • ThermosatSetJeedom: To set your thermostat(s) to a specific value

  • EntityStateValueJeedom: To collect information on the state of your sensor, eg. "Is my window open?", "What's the humidity level in my bedroom?", "Is the Alarm set in the house?"

  • TurnOnJeedom: To turn ON a device

  • TurnOffJeedom: To turn OFF a device.

  • VolumeDownJeedom: To decrease the volume of your devices (Tv, radio, sonos ...)

  • VolumeUpJeedom: To decrease the volume of your devices (Tv, radio, sonos ...)

  • VolumeMuteJeedom: To mute your devices (Tv, radio, sonos ...)

  • TvChannelJeedom: To select the right channel on your Tv

  • LightsSetJeedom: To set your light(s) to a specific value

  • LightsTurnOffJeedom: To turn OFF your light(s)

  • LightShiftUpJeedom: To increase the brightness of your light(s) without having to set a value

  • LightShiftDownJeedom: To decrease the brightness of your light(s) without having to set a value

You can of course "fork" it, edit/remove/add intents and slots values to personnalise it more.

On top of this app, you can create and add many different apps (of your own) or from the public app store such as Weather (you'll have to connect to an API), calculator, recipes and so on.