Использование слотов в умении для поиска Dynamodb

Я новичок в alexa, nodejs и кодировании в целом, но в настоящее время я пытаюсь создать навык для поиска состояний машины из моей таблицы Dynamodb с использованием даты и времени.

В настоящее время я настроил свои навыки, чтобы заставить alexa и lambda понимать значения моих слотов, но я не уверен, как я могу использовать эти значения для запроса Dynamodb и заставить alexa вызывать состояние для этого соответствующего времени

Моя таблица настроена с первичным ключом и ключом сортировки, которые являются датой и временем, и у меня есть третий столбец для состояния машины.

Я не уверен, следует ли мне настраивать пользовательский слот для состояния машины, поскольку это было бы легко сделать, поскольку есть только 4 возможных состояния.

Вот код, который у меня есть в настоящее время. Не стесняйтесь очищать части или объяснять, как вы пришли к моему решению.

const awsSDK = require('aws-sdk');
const updatedincident = 'updatedincident';
const docClient = new awsSDK.DynamoDB.DocumentClient();

var AWSregion = 'us-east-1';  // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();
AWS.config.update({
    region: "'us-east-1'"
});

const params = {
    TableName: "updatedincident",
    Key:{ date: "2018-03-28",
      time: "04:23",
      state: "Blocked Primary"
    }
};

let GetMachineStateIntent = (context, callback) => {    
  var params = {
    TableName: "updatedincident",
    Key: {
      date: "2018-03-28",
      time: "04:23",
      state: "Blocked Primary"
    }
  };
  dbClient.get(params, function (err, data) {
    if (err) {
       // failed to read from table for some reason..
       console.info('failed to load data item:\n' + JSON.stringify(err, null, 2));
       // let skill tell the user that it couldn't find the data 
       sendResponse(context, callback, {
          output: "the data could not be loaded from your database",
          endSession: false
       });
    } else {
       console.info('loaded data item:\n' + JSON.stringify(data.Item, null, 2));
       // assuming the item has an attribute called "state"..
       sendResponse(context, callback, {
          output: data.Item.state,
          endSession: false
       });
    }
  });
};


function sendResponse(context, callback, responseOptions) {
  if (typeof callback === 'undefined') {
    context.succeed(buildResponse(responseOptions));
  } else {
    callback(null, buildResponse(responseOptions));
  }
}

function buildResponse(options) {
  var alexaResponse = {
    version: "1.0",
    response: {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate = "slow">${options.output}</prosody></speak>`
      },
      shouldEndSession: options.endSession
    }
  };
  if (options.repromptText) {
    alexaResponse.response.reprompt = {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate = "slow">${options.reprompt}</prosody></speak>`
      }
    };
  }
  return alexaResponse;
}

exports.handler = (event, context, callback) => {
  try {
    var request = event.request;
    if (request.type === "LaunchRequest") {
      sendResponse(context, callback, {
        output: "welcome to my skill, I can tell you about the status of machines at different times. what data are you looking for?",
        endSession: false
      });
  }
    else if (request.type === "IntentRequest") {
      if (request.type === "IntentRequest" 
      // make sure the name of the intent matches the one in interaction model
   && request.intent.name == "GetMachineStateIntent") {
    var dateSlot = request.intent.slots.Date != null ?
                   request.intent.slots.Date.value : "unknown date";
    var timeSlot = request.intent.slots.Time != null ?
                   request.intent.slots.Time.value : "unknown time";
                   
    // respond with speech saying back what the skill thinks the user requested
    sendResponse(context, callback, {
       output: "You wanted the machine state at " 
              + timeSlot + " on " + dateSlot,
       endSession: false
    });
    
    
    var ConfirmationHandlers = Alexa.CreateStateHandler(states.CONFIRMATIONMODE, {
    'YesIntent': function () { 
        this.emit("GetMachineStateIntent"); 
    }, 
    'AMAZON.NoIntent': function () { 
        this.response.speak(GetMachineStateIntent); 
        this.emit(':responseReady'); 
    } 
    });


}
      let options = {};         
      if (request.intent.name === "GetMachineStateIntent") {
        GetMachineStateIntent(context, callback);
      } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
        sendResponse(context, callback, {
          output: "ok. good bye!",
          endSession: true
        });
      }
      else if (request.intent.name === "AMAZON.HelpIntent") {
        sendResponse(context, callback, {
          output: "you can ask me about incidents that have happened or states of machines in the past",
          reprompt: "what can I help you with?",
          endSession: false
        });
      }
      else {
        sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
        });
      }
    }
    else if (request.type === "SessionEndedRequest") {
      sendResponse(context, callback, ""); // no response needed
    }
    else {
      // an unexpected request type received.. just say I don't know..
      sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
      });
    }
  } catch (e) {
    // handle the error by logging it and sending back an failure
    console.info('Unexpected error occurred in the skill handler!', e);
    if (typeof callback === 'undefined') {
       context.fail("Unexpected error");
    } else {
       callback("Unexpected error");
    }
  }
};

Обновлять ************

Ответ я получаю в настоящее время в Skill I / O в alexa

	"request": {
		"type": "IntentRequest",
		"requestId": "amzn1.echo-api.request.c515c39e-4ce1-4f28-97ed-30536fa593b9",
		"timestamp": "2018-05-15T08:55:25Z",
		"locale": "en-GB",
		"intent": {
			"name": "GetMachineStateIntent",
			"confirmationStatus": "NONE",
			"slots": {
				"Time": {
					"name": "Time",
					"value": "04:23",
					"confirmationStatus": "NONE"
				},
				"Date": {
					"name": "Date",
					"value": "2018-03-28",
					"confirmationStatus": "NONE"
				}
			}
		},
		"dialogState": "STARTED"
	}
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
535
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Пара наблюдений:

Первый В ветви кода, которая обрабатывает GetMachineStateIntent, вы добавили код для создания обработчиков состояния, но они не были правильно подключены. В лучшем случае этот код ничего не сделает, в худшем - может вызвать некоторые проблемы. Удалите это.

    // take the following lines of code out
    var ConfirmationHandlers = Alexa.CreateStateHandler(states.CONFIRMATIONMODE, {
    'YesIntent': function () { 
        this.emit("GetMachineStateIntent"); 
    }, 
    'AMAZON.NoIntent': function () { 
        this.response.speak(GetMachineStateIntent); 
        this.emit(':responseReady'); 
    } 
    }); 

Второй Параметры запроса, которые вы передаете в свой запрос DynamoDB, жестко запрограммированы. Это означает, что вы всегда будете получать один и тот же результат. Вам необходимо передать значения слотов, которые вы получаете в намерении, в параметры запроса.

  var params = {
    TableName: "updatedincident",
    Key: {
      date: "2018-03-28",
      time: "04:23",
      state: "Blocked Primary"
    }
  };

Они жестко запрограммированы. Вам нужно только указать первичный ключ (date) и ключ сортировки («время»), чтобы вы могли удалить state. А для date и time вы должны изменить значения, которые будут динамически передаваться из dateSlot и timeSlot.


В третьих В ветви кода, которая обрабатывает запросы типа IntentRequest, вы дважды обрабатываете GetMachineStateIntent, и этот код немного избыточен. Перепишите это следующим образом:

   ...
} else if (request.type === "IntentRequest") {
  if (request.intent.name === "GetMachineStateIntent") {
    GetMachineStateIntent(context, callback);
  } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
    sendResponse(context, callback, {
      output: "ok. good bye!",
      endSession: true
    });
  }
  else if (request.intent.name === "AMAZON.HelpIntent") {
    sendResponse(context, callback, {
      output: "you can ask me about incidents that have happened or states of machines in the past",
      reprompt: "what can I help you with?",
      endSession: false
    });
  }
  else {
    sendResponse(context, callback, {
      output: "I don't know that one! please try again!",
      endSession: false
    });
  } 
} else if (request.type === "SessionEndedRequest") {

Четвертый Объяснить это труднее всего. Когда вы запрашиваете состояние машины, вы указываете дату и время, но, предположительно, состояние машины может не храниться в базе данных с отметкой времени, которая точно соответствует значению времени в вашем запросе. Таким образом, вы должны выполнить запрос, который по сути эквивалентен «каково состояние машины на дату X, в самое последнее время до или равное Y».

Сложность заключается в том, что «самое последнее время до или равное Y». Вы должны создать запрос в своей таблице, который выражает это, и вам также придется изменить способ хранения временных меток в таблице со строки на числовой формат, чтобы вы могли легко выразить это неравенство.

Я собираюсь показать здесь, как передать dateSlot и timeSlot для выполнения запроса, но я рекомендую вам изучить, как заставить это работать (возможно, задайте конкретные вопросы, если вы застряли).


Вот ваш код с упомянутыми мною модификациями:

const awsSDK = require('aws-sdk');
const updatedincident = 'updatedincident';
const docClient = new awsSDK.DynamoDB.DocumentClient();

var AWSregion = 'us-east-1';  // us-east-1
var AWS = require('aws-sdk');
var dbClient = new AWS.DynamoDB.DocumentClient();
AWS.config.update({
    region: "'us-east-1'"
});

let GetMachineStateIntent = (context, callback, dateSlot, timeSlot) => {    
  var params = {
    TableName: "updatedincident",
    KeyConditionExpression: '#d = :dVal and #t < :tVal',
    ExpressionAttributeValues: {
       ':dVal': dateSlot,
       ':tVal': timeSlot
    },
    ExpressionAttributeNames: {
       '#d': 'date',
       '#t': 'time'
    },
    ScanIndexForward: false // gets values in reverse order by time 
  };
  dbClient.query(params, function (err, data) {
    if (err) {
       // failed to read from table for some reason..
       console.info('failed to load data item:\n' + JSON.stringify(err, null, 2));
       // let skill tell the user that it couldn't find the data 
       sendResponse(context, callback, {
          output: "the data could not be loaded from your database",
          endSession: false
       });
    } else {
       let dataItem = data.Items[0];           
console.info('loaded data item:\n' + JSON.stringify(dataItem, null, 2));
       // assuming the item has an attribute called "state"..
       sendResponse(context, callback, {
          output: dataItem.state,
          endSession: false
       });
    }
  });
};


function sendResponse(context, callback, responseOptions) {
  if (typeof callback === 'undefined') {
    context.succeed(buildResponse(responseOptions));
  } else {
    callback(null, buildResponse(responseOptions));
  }
}

function buildResponse(options) {
  var alexaResponse = {
    version: "1.0",
    response: {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate = "slow">${options.output}</prosody></speak>`
      },
      shouldEndSession: options.endSession
    }
  };
  if (options.repromptText) {
    alexaResponse.response.reprompt = {
      outputSpeech: {
        "type": "SSML",
        "ssml": `<speak><prosody rate = "slow">${options.reprompt}</prosody></speak>`
      }
    };
  }
  return alexaResponse;
}

exports.handler = (event, context, callback) => {
  try {
    var request = event.request;
    if (request.type === "LaunchRequest") {
      sendResponse(context, callback, {
        output: "welcome to my skill, I can tell you about the status of machines at different times. what data are you looking for?",
        endSession: false
      });
    } else if (request.type === "IntentRequest") {
      if (request.intent.name === "GetMachineStateIntent") {
        var dateSlot = request.intent.slots.Date != null 
             ? request.intent.slots.Date.value : null;
        var timeSlot = request.intent.slots.Time != null
             ? request.intent.slots.Time.value : null;
        // pass the slot values to the GetMachineStateIntent function
        GetMachineStateIntent(context, callback, dateSlot, timeSlot);
      } else if (request.intent.name === "AMAZON.StopIntent" || request.intent.name === "AMAZON.CancelIntent") {
        sendResponse(context, callback, {
          output: "ok. good bye!",
          endSession: true
        });
      }
      else if (request.intent.name === "AMAZON.HelpIntent") {
        sendResponse(context, callback, {
          output: "you can ask me about incidents that have happened or states of machines in the past",
          reprompt: "what can I help you with?",
          endSession: false
        });
      }
      else {
        sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
        });
      }
    }
    else if (request.type === "SessionEndedRequest") {
      sendResponse(context, callback, ""); // no response needed
    }
    else {
      // an unexpected request type received.. just say I don't know..
      sendResponse(context, callback, {
          output: "I don't know that one! please try again!",
          endSession: false
      });
    }
  } catch (e) {
    // handle the error by logging it and sending back an failure
    console.info('Unexpected error occurred in the skill handler!', e);
    if (typeof callback === 'undefined') {
       context.fail("Unexpected error");
    } else {
       callback("Unexpected error");
    }
  }
};

Привет, я добавил ваши изменения, но теперь я получаю «данные не могут быть загружены из вашей базы данных». Я вижу, что вводятся мои значения даты и времени, но не получаю ответа. Мне нужно будет изменить мою модель взаимодействия? Также можно добавить подтверждение, например: «Вы хотите, чтобы состояние было в (время) в (дата)?» когда пользователь отвечает "да" или "нет"?

zuba 14.05.2018 11:44

Просто хотел добавить элемент, который я хочу вызвать, это dataItem.State.

zuba 14.05.2018 15:13

Кажется, не может получить никакого ответа от Alexa, кроме «данные не могут быть загружены из вашей базы данных». Моя дата и время отформатированы правильно, и я вижу по Алексе, что мои время и дата вводятся правильно.

zuba 15.05.2018 10:53

Я добавил то, что в настоящее время получаю от ввода / вывода навыков alexa, когда я ввожу дату и время

zuba 15.05.2018 10:58

также посмотрите мой последний пост, чтобы узнать, что я получаю в CloudWatch

zuba 16.05.2018 17:57

@zuba Я посмотрел на другой вопрос, который вы разместили, и да, возникла проблема с параметрами запроса; Я опубликовал ответ там, но я обновил и этот здесь

Mike Dinescu 18.05.2018 04:49

Другие вопросы по теме