diff --git a/README.md b/README.md
index 360e956..0c48e4e 100644
--- a/README.md
+++ b/README.md
@@ -170,7 +170,7 @@ def lambda_handler(event, context):
response = http.request(
'POST',
- '{}/alexa/smarthome'.format(base_url),
+ base_url,
headers={
'Authorization': 'Bearer {}'.format(token),
'Content-Type': 'application/json',
@@ -197,7 +197,7 @@ def lambda_handler(event, context):
* Click on the "Edit" button.
* Click on the "Add environment variable" button.
* Enter "BASE_URL" as the "Key".
-* Enter "https://YOUR_DOMAIN" as the Value.
+* Enter "https://YOUR_DOMAIN/alexa/smarthome" as the Value.
* Click on the "Add environment variable" button.
* Enter "DEBUG" as the "Key".
* Enter "True" as the Value.
diff --git a/alexa/alexa-device.html b/alexa/alexa-device.html
index c2516e7..190c417 100644
--- a/alexa/alexa-device.html
+++ b/alexa/alexa-device.html
@@ -65,6 +65,7 @@
name: { value: "", required: true },
display_categories: { value: [], required: true, validate: function (dc) { return dc && dc.length > 0 } },
topic: { value: "", required: false },
+ topic_filter: { value: false, required: false },
passthru: { value: false, required: false },
a_inputs: { value: ['AUX_1', 'AUX_2', 'AUX_3', 'AUX_4', 'AUX_5', 'AUX_6', 'AUX_7', 'BLURAY', 'CABLE', 'CD', 'COAX_1', 'COAX_2', 'COMPOSITE_1', 'DVD', 'GAME', 'HD_RADIO', 'HDMI_1', 'HDMI_2', 'HDMI_3', 'HDMI_4', 'HDMI_5', 'HDMI_6', 'HDMI_7', 'HDMI_8', 'HDMI_9', 'HDMI_10', 'HDMI_ARC', 'INPUT_1', 'INPUT_2', 'INPUT_3', 'INPUT_4', 'INPUT_5', 'INPUT_6', 'INPUT_7', 'INPUT_8', 'INPUT_9', 'INPUT_10', 'IPOD', 'LINE_1', 'LINE_2', 'LINE_3', 'LINE_4', 'LINE_5', 'LINE_6', 'LINE_7', 'MEDIA_PLAYER', 'OPTICAL_1', 'OPTICAL_2', 'PHONO', 'PLAYSTATION', 'PLAYSTATION_3', 'PLAYSTATION_4', 'SATELLITE', 'SMARTCAST', 'TUNER', 'TV', 'USB_DAC', 'VIDEO_1', 'VIDEO_2', 'VIDEO_3', 'XBOX'], required: false },
i_automation_management: { value: false, required: false },
@@ -1291,9 +1292,15 @@
+
+
+
+
+
+
-
+
diff --git a/alexa/alexa-device.js b/alexa/alexa-device.js
index da08311..1893f51 100644
--- a/alexa/alexa-device.js
+++ b/alexa/alexa-device.js
@@ -224,7 +224,8 @@ module.exports = function (RED) {
//
onInput(msg) {
const node = this;
- const topicArr = String(msg.topic || '').split('/');
+ const topic_str = String(msg.topic || '');
+ const topicArr = topic_str.split('/');
const topic = topicArr[topicArr.length - 1].toUpperCase();
if (node.isVerbose()) node._debug("onInput " + JSON.stringify(msg));
if (node.isVerbose()) node._debug("onInput " + topic);
@@ -366,6 +367,10 @@ module.exports = function (RED) {
}
} else {
let msg1 = msg;
+ console.log("CCHI topic " + node.config.topic + " msg.topic " + topic_str);
+ if (node.config.topic_filter && !topic_str.startsWith(node.config.topic)) {
+ return;
+ }
Object.keys(node.state_types).forEach(function (key) {
if (topic == key.toUpperCase()) {
msg1 = {
diff --git a/alexa/locales/en-US/alexa-device.json b/alexa/locales/en-US/alexa-device.json
index 3ddc86e..93980e8 100644
--- a/alexa/locales/en-US/alexa-device.json
+++ b/alexa/locales/en-US/alexa-device.json
@@ -6,6 +6,7 @@
"name": "Name",
"topic": "Out topic",
"passthru": "If msg arrives on input, pass through to output:",
+ "topic_filter": "Filter incoming messages by topic",
"username": "Username",
"password": "Password",
"secret": "Secret",
diff --git a/alexa/locales/it_IT/alexa-device.json b/alexa/locales/it_IT/alexa-device.json
index 60b2f0b..03602aa 100644
--- a/alexa/locales/it_IT/alexa-device.json
+++ b/alexa/locales/it_IT/alexa-device.json
@@ -6,6 +6,7 @@
"name": "Nome",
"topic": "Topic in uscita",
"passthru": "Se un messaggio arriva in ingresso, invialo in uscita:",
+ "topic_filter": "Filtra i messaggi in ingresso",
"username": "Nome utente",
"password": "Password",
"secret": "Segreto",
diff --git a/docs/index.js b/docs/index.js
new file mode 100644
index 0000000..77529d0
--- /dev/null
+++ b/docs/index.js
@@ -0,0 +1,87 @@
+/**
+ * NodeRED Alexa SmartHome
+ * Copyright 2022 Claudio Chimera .
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ **/
+
+
+const https = require('https')
+const base_url = process.env.BASE_URL
+const d = 'True' == process.env.DEBUG
+
+const { hostname = "localhost", pathname = "/", s_port, protocol } = new URL(base_url);
+const port = s_port ? parseInt(s_port) : protocol === 'https:' ? 443 : 80
+
+if (d) {
+ console.log('url: ' + base_url)
+ console.log('hostname: ' + hostname)
+ console.log('pathname: ' + pathname)
+ console.log('port: ' + port)
+ console.log('protocol: ' + protocol)
+}
+
+const options = {
+ hostname: hostname,
+ path: pathname,
+ method: 'POST',
+ port: port,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+};
+
+function getError(err) {
+ return {
+ 'event': {
+ 'payload': {
+ 'type': 'INTERNAL_ERROR',
+ 'message': err,
+ }
+ }
+ };
+}
+
+exports.handler = async (event) => {
+ if (d) {
+ console.log("event: " + JSON.stringify(event))
+ }
+
+ return new Promise((resolve, reject) => {
+ const req = https.request(options, res => {
+ let rawData = '';
+
+ res.on('data', chunk => {
+ rawData += chunk;
+ });
+
+ res.on('end', () => {
+ try {
+ resolve(JSON.parse(rawData));
+ } catch (err) {
+ if (d) console.log("rawData: " + rawData)
+ resolve(getError(rawData));
+ }
+ });
+ });
+
+ req.on('error', err => {
+ if (d) console.log("reject: " + err)
+ resolve(getError(err));
+ });
+
+ req.write(JSON.stringify(event));
+ req.end();
+ });
+};
diff --git a/lambda-mcs/index.js b/lambda-mcs/index.js
new file mode 100644
index 0000000..58a8240
--- /dev/null
+++ b/lambda-mcs/index.js
@@ -0,0 +1,296 @@
+/**
+ * NodeRED Alexa SmartHome
+ * Copyright 2022 Claudio Chimera .
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ **/
+
+const Alexa = require('ask-sdk-core');
+const i18n = require('i18next');
+const axios = require('axios');
+
+const debug = 'True' == process.env.DEBUG;
+const base_url = process.env.BASE_URL;
+const GIVEN_NAME_PERMISSION = ['alexa::profile:given_name:read'];
+
+if (debug) {
+ console.log('base_url: ' + base_url);
+};
+
+const config = {
+ timeout: 6500,
+ headers: { 'Accept': 'application/json' }
+};
+
+const languageStrings = {
+ en: {
+ translation: {
+ WELCOME_MSG: `Welcome to smart home {{name}}. What i can do for you? `,
+ OK_MSG: 'OK.',
+ REJECTED_MSG: 'No problem.',
+ HELP_MSG: `You can control Your Smart Home?`,
+ GOODBYE_MSG: 'Goodbye!',
+ FALLBACK_MSG: 'Sorry, I don\'t know about that. Please try again.',
+ API_ERROR_MSG: `I'm sorry, I'm having trouble accessing the smart home, Please try again later. `,
+ ERROR_MSG: 'Sorry, there was an error. Please try again.'
+ }
+ },
+ it: {
+ translation: {
+ WELCOME_MSG: `Benvenuto {{name}} nella casa domotica. Cosa posso fare? `,
+ OK_MSG: 'OK.',
+ REJECTED_MSG: 'Nessun problema.',
+ HELP_MSG: 'Posso comunicare con la tua casa domotica. Cosa vuoi fare? ',
+ GOODBYE_MSG: 'A presto!',
+ FALLBACK_MSG: 'Perdonami, penso di non aver capito bene. Riprova.',
+ API_ERROR_MSG: `Sto avendo qualche intoppo contattando la tua casa domotica. Riprova più tardi. `,
+ ERROR_MSG: 'Scusa, c\'è stato un errore. Riprova.'
+ }
+ },
+ es: {
+ translation: {
+ WELCOME_MSG: 'Te doy la bienvenida a Feliz Cumpleaños. Vamos a divertirnos un poco con tu cumpleaños! ',
+ OK_MSG: 'OK.',
+ REJECTED_MSG: 'No pasa nada. Por favor dime la fecha otra vez y lo corregimos.',
+ HELP_MSG: 'Puedes decirme el día, mes y año de tu nacimiento y tomaré nota de ello. También puedes decirme, registra mi cumpleaños y te guiaré. Qué quieres hacer?',
+ GOODBYE_MSG: 'Hasta luego!',
+ FALLBACK_MSG: 'Lo siento, no se nada sobre eso. Por favor inténtalo otra vez.',
+ ERROR_MSG: 'Lo siento, ha habido un problema. Por favor inténtalo otra vez.'
+ }
+ },
+ fr: {
+ translation: {
+ WELCOME_MSG: 'Bienvenue sur la Skill des anniversaires! ',
+ OK_MSG: 'OK.',
+ REJECTED_MSG: 'D\'accord, je ne vais pas prendre en compte cette date. Dites-moi une autre date pour que je puisse l\'enregistrer.',
+ HELP_MSG: 'Je peux me souvenir de votre date de naissance. Dites-moi votre jour, mois et année de naissance ou bien dites-moi simplement \'"enregistre mon anniversaire"\' et je vous guiderai. Quel est votre choix ?',
+ GOODBYE_MSG: 'Au revoir!',
+ FALLBACK_MSG: 'Désolé, je ne sais pas répondre à votre demande. Pouvez-vous reformuler?.',
+ ERROR_MSG: 'Désolé, je n\'ai pas compris. Pouvez-vous reformuler?'
+ }
+ }
+}
+
+const forwardEvent = async function (event) {
+ async function getJsonResponse(event) {
+ const res = await axios.post(base_url, event, config);
+ return res.data;
+ }
+
+ return getJsonResponse(event).then((result) => {
+ return result;
+ }).catch((error) => {
+ console.log("Request error " + error);
+ return null;
+ });
+};
+
+const LaunchRequestHandler = {
+ canHandle(handlerInput) {
+ return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
+ },
+ handle(handlerInput) {
+ // const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
+ const name = "ciccio"; // sessionAttributes['name'] || '';
+ const speechText = handlerInput.t('WELCOME_MSG', {name: name});
+
+ return handlerInput.responseBuilder
+ .speak(speechText)
+ .getResponse();
+ }
+};
+
+const ForwardEventIntentHandler = {
+ canHandle(handlerInput) {
+ return true; // Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
+ // && Alexa.getIntentName(handlerInput.requestEnvelope) === 'ForwardEventIntent';
+ },
+ async handle(handlerInput) {
+ const { requestEnvelope, responseBuilder } = handlerInput;
+ const { intent } = requestEnvelope.request;
+
+ let speechText = handlerInput.t('REJECTED_MSG');
+
+ console.log("CCHI handlerInput.requestEnvelope " + JSON.stringify(handlerInput.requestEnvelope));
+ const res = await forwardEvent(handlerInput.requestEnvelope);
+ console.log("CCHI RES " + JSON.stringify(res));
+
+ if (res) {
+ speechText = handlerInput.t('OK_MSG');
+ } else {
+ const repromptText = handlerInput.t('API_ERROR_MSG');
+ responseBuilder.reprompt(repromptText);
+ }
+
+ return responseBuilder
+ .speak(speechText)
+ .getResponse();
+ }
+};
+
+const HelpIntentHandler = {
+ canHandle(handlerInput) {
+ return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
+ && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
+ },
+ handle(handlerInput) {
+ const speechText = handlerInput.t('HELP_MSG');
+
+ return handlerInput.responseBuilder
+ .speak(speechText)
+ .reprompt(speechText)
+ .getResponse();
+ }
+};
+
+const CancelAndStopIntentHandler = {
+ canHandle(handlerInput) {
+ return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
+ && (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
+ || Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
+ },
+ handle(handlerInput) {
+ const speechText = handlerInput.t('GOODBYE_MSG');
+
+ return handlerInput.responseBuilder
+ .speak(speechText)
+ .getResponse();
+ }
+};
+
+const FallbackIntentHandler = {
+ canHandle(handlerInput) {
+ return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
+ && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.FallbackIntent';
+ },
+ handle(handlerInput) {
+ const speechText = handlerInput.t('FALLBACK_MSG');
+
+ return handlerInput.responseBuilder
+ .speak(speechText)
+ .reprompt(handlerInput.t('HELP_MSG'))
+ .getResponse();
+ }
+};
+
+const SessionEndedRequestHandler = {
+ canHandle(handlerInput) {
+ return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
+ },
+ handle(handlerInput) {
+ console.log(`~~~~ Session ended: ${JSON.stringify(handlerInput.requestEnvelope)}`);
+ return handlerInput.responseBuilder.getResponse();
+ }
+};
+
+const ErrorHandler = {
+ canHandle() {
+ return true;
+ },
+ handle(handlerInput, error) {
+ const speechText = handlerInput.t('ERROR_MSG');
+ console.log(`~~~~ Error handled: ${JSON.stringify(error)}`);
+
+ return handlerInput.responseBuilder
+ .speak(speechText)
+ .reprompt(handlerInput.t('HELP_MSG'))
+ .getResponse();
+ }
+};
+
+const LoggingRequestInterceptor = {
+ process(handlerInput) {
+ console.log(`Incoming request: ${JSON.stringify(handlerInput.requestEnvelope)}`);
+ }
+};
+
+const LoggingResponseInterceptor = {
+ process(handlerInput, response) {
+ console.log(`Outgoing response: ${JSON.stringify(response)}`);
+ }
+};
+
+const LocalisationRequestInterceptor = {
+ process(handlerInput) {
+ const localisationClient = i18n.init({
+ lng: Alexa.getLocale(handlerInput.requestEnvelope),
+ resources: languageStrings,
+ returnObjects: true
+ });
+ localisationClient.localise = function localise() {
+ const args = arguments;
+ const value = i18n.t(...args);
+ if (Array.isArray(value)) {
+ return value[Math.floor(Math.random() * value.length)];
+ }
+ return value;
+ };
+ handlerInput.t = function translate(...args) {
+ return localisationClient.localise(...args);
+ }
+ }
+};
+
+const LoadNameRequestInterceptor = {
+ async process(handlerInput) {
+ const {attributesManager, serviceClientFactory, requestEnvelope} = handlerInput;
+ const sessionAttributes = attributesManager.getSessionAttributes();
+ console.log("LoadNameRequestInterceptor");
+ if (!sessionAttributes['name']){
+ // let's try to get the given name via the Customer Profile API
+ // don't forget to enable this permission in your skill configuratiuon (Build tab -> Permissions)
+ // or you'll get a SessionEndedRequest with an ERROR of type INVALID_RESPONSE
+ // Per our policies you can't make personal data persistent so we limit "name" to session attributes
+ try {
+ const {permissions} = requestEnvelope.context.System.user;
+ if (!(permissions && permissions.consentToken))
+ throw { statusCode: 401, message: 'No permissions available' }; // there are zero permissions, no point in intializing the API
+ const upsServiceClient = serviceClientFactory.getUpsServiceClient();
+ const profileName = await upsServiceClient.getProfileGivenName();
+ if (profileName) { // the user might not have set the name
+ //save to session attributes
+ sessionAttributes['name'] = profileName;
+ }
+ } catch (error) {
+ console.log("LoadNameRequestInterceptor error");
+ console.log(JSON.stringify(error));
+ if (error.statusCode === 401 || error.statusCode === 403) {
+ // the user needs to enable the permissions for given name, let's append a permissions card to the response.
+ handlerInput.responseBuilder.withAskForPermissionsConsentCard(GIVEN_NAME_PERMISSION);
+ }
+ }
+ }
+ }
+};
+
+exports.handler = Alexa.SkillBuilders.custom()
+ .addRequestHandlers(
+ LaunchRequestHandler,
+ HelpIntentHandler,
+ CancelAndStopIntentHandler,
+ FallbackIntentHandler,
+ SessionEndedRequestHandler,
+ ForwardEventIntentHandler
+ )
+ .addErrorHandlers(
+ ErrorHandler)
+ .addRequestInterceptors(
+ LocalisationRequestInterceptor,
+ LoggingRequestInterceptor,
+ //LoadNameRequestInterceptor
+ )
+ .addResponseInterceptors(
+ LoggingResponseInterceptor)
+ .withCustomUserAgent('alexa/node-red/smart-home')
+ .lambda();
diff --git a/lambda-mcs/package.json b/lambda-mcs/package.json
new file mode 100644
index 0000000..5fd3925
--- /dev/null
+++ b/lambda-mcs/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "smart-home",
+ "version": "1.0.0",
+ "description": "Smart Home Custom",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "Claudio Chimera",
+ "license": "GPL-3.0-or-later",
+ "dependencies": {
+ "ask-sdk-core": "^2.12.1",
+ "ask-sdk-model": "^1.38.3",
+ "axios": "^0.27.2",
+ "i18next": "^21.8.16"
+ }
+}
diff --git a/lambda/index.js b/lambda/index.js
new file mode 100644
index 0000000..ec7a418
--- /dev/null
+++ b/lambda/index.js
@@ -0,0 +1,88 @@
+/**
+ * NodeRED Alexa SmartHome
+ * Copyright 2022 Claudio Chimera .
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ **/
+
+
+ const https = require('https')
+ const base_url = process.env.BASE_URL
+ const d = 'True' == process.env.DEBUG
+
+ const { hostname = "localhost", pathname = "/", s_port, protocol } = new URL(base_url);
+ const port = s_port ? parseInt(s_port) : protocol === 'https:' ? 443 : 80
+
+ if (d) {
+ console.log('url: ' + base_url)
+ console.log('hostname: ' + hostname)
+ console.log('pathname: ' + pathname)
+ console.log('port: ' + port)
+ console.log('protocol: ' + protocol)
+ }
+
+ const options = {
+ hostname: hostname,
+ path: pathname,
+ method: 'POST',
+ port: port,
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ };
+
+ function getError(err) {
+ return {
+ 'event': {
+ 'payload': {
+ 'type': 'INTERNAL_ERROR',
+ 'message': err,
+ }
+ }
+ };
+ }
+
+ exports.handler = async (event) => {
+ if (d) {
+ console.log("event: " + JSON.stringify(event))
+ }
+
+ return new Promise((resolve, reject) => {
+ const req = https.request(options, res => {
+ let rawData = '';
+
+ res.on('data', chunk => {
+ rawData += chunk;
+ });
+
+ res.on('end', () => {
+ try {
+ resolve(JSON.parse(rawData));
+ } catch (err) {
+ if (d) console.log("rawData: " + rawData)
+ resolve(getError(rawData));
+ }
+ });
+ });
+
+ req.on('error', err => {
+ if (d) console.log("reject: " + err)
+ resolve(getError(err));
+ });
+
+ req.write(JSON.stringify(event));
+ req.end();
+ });
+ };
+
\ No newline at end of file
diff --git a/lambda/lambda_function.py b/lambda/lambda_function.py
new file mode 100644
index 0000000..0fe9c8d
--- /dev/null
+++ b/lambda/lambda_function.py
@@ -0,0 +1,62 @@
+"""
+NodeRED Alexa SmartHome
+
+Copyright 2022 Claudio Chimera .
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+"""
+
+import os
+import json
+import logging
+import urllib3
+
+_debug = bool(os.environ.get('DEBUG'))
+
+_logger = logging.getLogger('NodeRED-SmartHome')
+_logger.setLevel(logging.DEBUG if _debug else logging.INFO)
+
+
+def lambda_handler(event, context):
+ """Handle incoming Alexa directive."""
+
+ _logger.debug('Event: %s', event)
+
+ base_url = os.environ.get('BASE_URL')
+ assert base_url is not None, 'Please set BASE_URL environment variable'
+
+ http = urllib3.PoolManager(
+ cert_reqs='CERT_REQUIRED',
+ timeout=urllib3.Timeout(connect=2.0, read=10.0)
+ )
+
+ response = http.request(
+ 'POST',
+ base_url,
+ headers={
+ 'Content-Type': 'application/json',
+ },
+ body=json.dumps(event).encode('utf-8'),
+ )
+ if response.status >= 400:
+ return {
+ 'event': {
+ 'payload': {
+ 'type': 'INVALID_AUTHORIZATION_CREDENTIAL'
+ if response.status in (401, 403) else 'INTERNAL_ERROR',
+ 'message': response.data.decode("utf-8"),
+ }
+ }
+ }
+ return json.loads(response.data.decode('utf-8'))
diff --git a/models/it-IT.json b/models/it-IT.json
new file mode 100644
index 0000000..4f17055
--- /dev/null
+++ b/models/it-IT.json
@@ -0,0 +1,49 @@
+{
+ "interactionModel": {
+ "languageModel": {
+ "invocationName": "casa chimera",
+ "intents": [
+ {
+ "name": "AMAZON.CancelIntent",
+ "samples": []
+ },
+ {
+ "name": "AMAZON.HelpIntent",
+ "samples": []
+ },
+ {
+ "name": "AMAZON.StopIntent",
+ "samples": []
+ },
+ {
+ "name": "AMAZON.NavigateHomeIntent",
+ "samples": []
+ },
+ {
+ "name": "AMAZON.FallbackIntent",
+ "samples": []
+ },
+ {
+ "name": "RiavviaDomoticaIntent",
+ "slots": [],
+ "samples": [
+ "Riavvia domotica"
+ ]
+ },
+ {
+ "name": "TemperaturaIntent",
+ "slots": [
+ {
+ "name": "Stanza",
+ "type": "AMAZON.Room"
+ }
+ ],
+ "samples": [
+ "Temperatura {Stanza}"
+ ]
+ }
+ ],
+ "types": []
+ }
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index fb3cd5b..47d2f65 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-contrib-alexa-virtual-smarthome",
- "version": "0.0.30",
+ "version": "0.0.31",
"description": "Node Red Alexa Smarthome node",
"main": "index.js",
"scripts": {
@@ -38,7 +38,7 @@
"devDependencies": {
"http-proxy": "^1.18.1",
"mocha": "^9.2.0",
- "node-red": "^2.0.5",
+ "node-red": "^3.0.2",
"node-red-node-test-helper": "^0.2.7"
},
"dependencies": {
@@ -60,4 +60,4 @@
"directories": {
"test": "test"
}
-}
\ No newline at end of file
+}