Hardware components | ||||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
| ||||||
| ||||||
| ||||||
Hand tools and fabrication machines | ||||||
|
Monitor your baby's breathing, rollover, crying, and temperature in a Smart Button! App proactively alerts you about stomach sleeping, stoppage in breathing movements, falls and unusual activity of your baby.
The Smart Button snaps easily and securely on the baby's clothing and won't fall off. It works optimally when placed in the same room with your smartphone. It uses Bluetooth Low Energy technology which is built for the Internet of Things and produces much less radio frequency power than standard video/audio baby monitors and smartphones.
Compared with back sleeping, stomach sleeping carries between 1.7 and 12.9 times the risk of SIDS:
Following link provide detail steps on how to connect SensorTile to Watson IoT to send all the sensor data to the cloud.
Build the Dashboard and Logic of sending SMS trigger using Node-RedImport the the JSON provided into node-red:
Follow the following tutorial on how to setup Alexa skill kit and use the code on the bottom for the Lambda function:
[
{
"id": "94cfccb8.475e5",
"type": "change",
"z": "9a3b30e7.e7d3a",
"name": "Extract Temperature",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.d.Temperature",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 545,
"y": 150,
"wires": [
[
"e5778a32.5b3d38"
]
]
},
{
"id": "891ffcf0.7d87d",
"type": "change",
"z": "9a3b30e7.e7d3a",
"name": "Extract Accelerometer X",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.d.X",
"tot": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "X",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 555,
"y": 210,
"wires": [
[
"1ef3873b.1bb189"
]
]
},
{
"id": "e96e920b.36bad",
"type": "change",
"z": "9a3b30e7.e7d3a",
"name": "Extract Accelerometer Y",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.d.Y",
"tot": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "Y",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 555,
"y": 250,
"wires": [
[
"1ef3873b.1bb189"
]
]
},
{
"id": "48f968e3.d4d798",
"type": "change",
"z": "9a3b30e7.e7d3a",
"name": "Extract Accelerometer Z",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.d.Z",
"tot": "msg"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "Z",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 555,
"y": 290,
"wires": [
[
"1ef3873b.1bb189",
"5558fb4d.8798a4",
"8f91cae8.861868"
]
]
},
{
"id": "4466822e.f8a0ec",
"type": "switch",
"z": "9a3b30e7.e7d3a",
"name": "SensorTile Event Types",
"property": "eventType",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "Temperature",
"vt": "str"
},
{
"t": "eq",
"v": "Accelerometer",
"vt": "str"
},
{
"t": "eq",
"v": "Mic Level",
"vt": "str"
}
],
"checkall": "true",
"outputs": 3,
"x": 255,
"y": 250,
"wires": [
[
"94cfccb8.475e5"
],
[
"891ffcf0.7d87d",
"e96e920b.36bad",
"48f968e3.d4d798"
],
[
"8b7c86dc.a54cd8"
]
]
},
{
"id": "8b7c86dc.a54cd8",
"type": "change",
"z": "9a3b30e7.e7d3a",
"name": "Extract Microphone level",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "payload.d.Mic",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 555,
"y": 350,
"wires": [
[
"a5e994.ee09967",
"a74e167f.401388"
]
]
},
{
"id": "809bf588.62fbc8",
"type": "ibmiot in",
"z": "9a3b30e7.e7d3a",
"authentication": "boundService",
"apiKey": "",
"inputType": "evt",
"deviceId": "C07A2E305C4D",
"applicationId": "",
"deviceType": "+",
"eventType": "+",
"commandType": "",
"format": "json",
"name": "IBM IoT",
"service": "registered",
"allDevices": true,
"allApplications": "",
"allDeviceTypes": true,
"allEvents": true,
"allCommands": "",
"allFormats": "",
"qos": 0,
"x": 55,
"y": 167,
"wires": [
[
"f383f7f1.72c348",
"f3f6c29b.a57de"
]
]
},
{
"id": "3e63e37d.0d0e3c",
"type": "comment",
"z": "9a3b30e7.e7d3a",
"name": "WIoTP via API keys",
"info": "Registered Device",
"x": 101,
"y": 119,
"wires": []
},
{
"id": "c03bb406.03f968",
"type": "debug",
"z": "9a3b30e7.e7d3a",
"name": "",
"active": false,
"console": "false",
"complete": "true",
"x": 353.75000381469727,
"y": 168.25000190734863,
"wires": []
},
{
"id": "98eac4d1.ae06d8",
"type": "debug",
"z": "9a3b30e7.e7d3a",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 686.5277824401855,
"y": 499.0278081893921,
"wires": []
},
{
"id": "f383f7f1.72c348",
"type": "delay",
"z": "9a3b30e7.e7d3a",
"name": "",
"pauseType": "rate",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": true,
"x": 212.5,
"y": 169.50000381469727,
"wires": [
[
"4466822e.f8a0ec",
"c03bb406.03f968"
]
]
},
{
"id": "e5778a32.5b3d38",
"type": "ui_chart",
"z": "9a3b30e7.e7d3a",
"name": "",
"group": "a879ac54.d2c46",
"order": 3,
"width": 0,
"height": 0,
"label": "Temperature",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "",
"ymax": "",
"removeOlder": "10",
"removeOlderPoints": "",
"removeOlderUnit": "60",
"cutout": 0,
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"useOldStyle": true,
"x": 775,
"y": 150,
"wires": [
[],
[]
]
},
{
"id": "1ef3873b.1bb189",
"type": "ui_chart",
"z": "9a3b30e7.e7d3a",
"name": "",
"group": "a879ac54.d2c46",
"order": 4,
"width": 0,
"height": 0,
"label": "Accelerometer",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "",
"ymax": "",
"removeOlder": "10",
"removeOlderPoints": "",
"removeOlderUnit": "60",
"cutout": 0,
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"useOldStyle": true,
"x": 837.5000152587891,
"y": 213.75000190734863,
"wires": [
[],
[]
]
},
{
"id": "a5e994.ee09967",
"type": "ui_chart",
"z": "9a3b30e7.e7d3a",
"name": "",
"group": "a879ac54.d2c46",
"order": 5,
"width": 0,
"height": 0,
"label": "Microphone",
"chartType": "line",
"legend": "false",
"xformat": "HH:mm:ss",
"interpolate": "linear",
"nodata": "",
"dot": false,
"ymin": "",
"ymax": "",
"removeOlder": "10",
"removeOlderPoints": "",
"removeOlderUnit": "60",
"cutout": 0,
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"useOldStyle": true,
"x": 775,
"y": 350,
"wires": [
[],
[]
]
},
{
"id": "a74e167f.401388",
"type": "switch",
"z": "9a3b30e7.e7d3a",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "gte",
"v": "50",
"vt": "num"
}
],
"checkall": "true",
"outputs": 1,
"x": 758.2500076293945,
"y": 385.0000057220459,
"wires": [
[]
]
},
{
"id": "39aec6e9.2e010a",
"type": "switch",
"z": "9a3b30e7.e7d3a",
"name": "Shake",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "Shake",
"vt": "str"
}
],
"checkall": "true",
"outputs": 1,
"x": 668.3333549499512,
"y": 451.4444227218628,
"wires": [
[
"bb96af4.e54825"
]
]
},
{
"id": "bb96af4.e54825",
"type": "function",
"z": "9a3b30e7.e7d3a",
"name": "Send SMS",
"func": "msg.url = 'https://rest.nexmo.com/sms/json';\nmsg.headers = {\n 'content-type': 'application/json',\n};\n\nvar data = {\"api_key\":\"_\",\n\"api_secret\":\"_\",\n\"to\":\"T Number\",\n\"from\":\"From Number\",\n\"text\":\"I am okay\"}; \nmsg.payload = JSON.stringify(data);\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 803.8888549804688,
"y": 449.2221984863281,
"wires": [
[
"f3ad53c0.7db21"
]
]
},
{
"id": "f3ad53c0.7db21",
"type": "http request",
"z": "9a3b30e7.e7d3a",
"name": "",
"method": "POST",
"ret": "obj",
"url": "",
"tls": "",
"x": 961.2499542236328,
"y": 449.4999752044678,
"wires": [
[]
]
},
{
"id": "d1f77a2d.d12df8",
"type": "function",
"z": "9a3b30e7.e7d3a",
"name": "Extract Activity",
"func": "switch(msg.payload.d.Activity) {\n case 0:\n msg.payload = \"NoActivity\";\n break;\n case 1:\n msg.payload = \"Standing\";\n break;\n case 2:\n msg.payload = \"Walking\";\n break;\n case 3:\n msg.payload = \"FastWalking\";\n break;\n case 4:\n msg.payload = \"Jogging\";\n break;\n case 5:\n msg.payload = \"Biking\";\n break;\n case 6:\n msg.payload = \"Drivin\";\n break;\n default:\n msg.payload = \"Unkown\";\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 508.12500762939453,
"y": 578.2500076293945,
"wires": [
[
"f7083456.1763b8"
]
]
},
{
"id": "df7e29f3.924768",
"type": "function",
"z": "9a3b30e7.e7d3a",
"name": "Extract Position",
"func": "switch(msg.payload.d[\"Carry Position\"]) {\n case 0:\n msg.payload = \"Unkown\";\n break;\n case 1:\n msg.payload = \"OnDesk\";\n break;\n case 2:\n msg.payload = \"InHand\";\n break;\n case 3:\n msg.payload = \"NearHead\";\n break;\n case 4:\n msg.payload = \"ShirtPocket\";\n break;\n case 5:\n msg.payload = \"TrousersPocket\";\n break;\n case 6:\n msg.payload = \"ArmSwing\";\n break;\n default:\n msg.payload = \"Unkown\";\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 506.87500762939453,
"y": 637.0000085830688,
"wires": [
[
"31ea8505.6e16aa"
]
]
},
{
"id": "280aaa43.c2b086",
"type": "function",
"z": "9a3b30e7.e7d3a",
"name": "Extract Gesture",
"func": "if (msg.payload.d[\"Mems Gesture\"] == 3){\n msg.payload = \"Shake\";\n}\nreturn msg;\n\n",
"outputs": 1,
"noerr": 0,
"x": 505,
"y": 477,
"wires": [
[
"39aec6e9.2e010a",
"98eac4d1.ae06d8"
]
]
},
{
"id": "f7083456.1763b8",
"type": "ui_text",
"z": "9a3b30e7.e7d3a",
"group": "a879ac54.d2c46",
"order": 1,
"width": 0,
"height": 0,
"name": "",
"label": "Activity",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 683.1250114440918,
"y": 578.2500076293945,
"wires": []
},
{
"id": "31ea8505.6e16aa",
"type": "ui_text",
"z": "9a3b30e7.e7d3a",
"group": "a879ac54.d2c46",
"order": 2,
"width": 0,
"height": 0,
"name": "",
"label": "Carry Position",
"format": "{{msg.payload}}",
"layout": "row-spread",
"x": 701.8750076293945,
"y": 634.5000085830688,
"wires": []
},
{
"id": "42fae9c3.56d378",
"type": "function",
"z": "9a3b30e7.e7d3a",
"name": "Send Emergency SMS",
"func": "msg.url = 'https://rest.nexmo.com/sms/json';\nmsg.headers = {\n 'content-type': 'application/json',\n};\n\nvar data = {\"api_key\":\"_\",\n\"api_secret\":\"_\",\n\"to\":\"T Number\",\n\"from\":\"From Number\",\n\"text\":\"Emergency : Falling down\"}; \nmsg.payload = JSON.stringify(data);\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 985.0000152587891,
"y": 277.00000286102295,
"wires": [
[
"54ba7306.1d536c"
]
]
},
{
"id": "54ba7306.1d536c",
"type": "http request",
"z": "9a3b30e7.e7d3a",
"name": "",
"method": "POST",
"ret": "obj",
"url": "",
"tls": "",
"x": 949.8610992431641,
"y": 333.527774810791,
"wires": [
[]
]
},
{
"id": "5558fb4d.8798a4",
"type": "switch",
"z": "9a3b30e7.e7d3a",
"name": "Fall Detection",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "gte",
"v": "1500",
"vt": "num"
}
],
"checkall": "true",
"outputs": 1,
"x": 780.0000152587891,
"y": 278.25000286102295,
"wires": [
[
"42fae9c3.56d378"
]
]
},
{
"id": "8f91cae8.861868",
"type": "debug",
"z": "9a3b30e7.e7d3a",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 893.1250114440918,
"y": 240.75000190734863,
"wires": []
},
{
"id": "f3f6c29b.a57de",
"type": "switch",
"z": "9a3b30e7.e7d3a",
"name": "SensorTile Event Types",
"property": "eventType",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "Mems Gesture",
"vt": "str"
},
{
"t": "eq",
"v": "Activity",
"vt": "str"
},
{
"t": "eq",
"v": "Carry Position",
"vt": "str"
}
],
"checkall": "true",
"outputs": 3,
"x": 248.75,
"y": 440.7500057220459,
"wires": [
[
"280aaa43.c2b086"
],
[
"d1f77a2d.d12df8"
],
[
"df7e29f3.924768"
]
]
},
{
"id": "a879ac54.d2c46",
"type": "ui_group",
"z": "",
"name": "Elderly Monitor",
"tab": "64da1951.2dc478",
"disp": true,
"width": "6"
},
{
"id": "64da1951.2dc478",
"type": "ui_tab",
"z": "",
"name": "Home",
"icon": "dashboard",
"order": 1
}
]
'use strict';
var https = require('https');
// https is a default part of Node.JS. Read the developer doc: https://nodejs.org/api/https.html
// try other APIs such as the current bitcoin price : https://btc-e.com/api/2/btc_usd/ticker returns ticker.last
function httpsGet(callback) {
// Update these options with the details of the web service you would like to call
var options = {
host: 'sensorelderly.mybluemix.net',
path: '/status',
method: 'GET',
// if x509 certs are required:
// key: fs.readFileSync('certs/my-key.pem'),
// cert: fs.readFileSync('certs/my-cert.pem')
};
var req = https.request(options, res => {
res.setEncoding('utf8');
var returnData = "";
res.on('data', chunk => {
returnData = returnData + chunk;
});
res.on('end', () => {
// we have now received the raw return data in the returnData variable.
// We can see it in the log output via:
console.log(JSON.stringify(returnData));
// we may need to parse through it to extract the needed data
var status = JSON.parse(returnData);
callback(status); // this will execute whatever function the caller defined, with one argument
});
});
req.end();
}
// --------------- Helpers that build all of the responses -----------------------
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
return {
outputSpeech: {
type: 'PlainText',
text: output,
},
card: {
type: 'Simple',
title: `SessionSpeechlet - ${title}`,
content: `SessionSpeechlet - ${output}`,
},
reprompt: {
outputSpeech: {
type: 'PlainText',
text: repromptText,
},
},
shouldEndSession,
};
}
function buildResponse(sessionAttributes, speechletResponse) {
return {
version: '1.0',
sessionAttributes,
response: speechletResponse,
};
}
// --------------- Functions that control the skill's behavior -----------------------
function getWelcomeResponse(callback) {
// If we wanted to initialize the session to have some attributes we could add those here.
const sessionAttributes = {};
const cardTitle = 'Welcome';
const speechOutput = 'Welcome to baby button.';
// If the user either does not reply to the welcome message or says something that is not
// understood, they will be prompted again with this text.
const repromptText = 'You can ask me the status of the baby';
const shouldEndSession = false;
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
function handleSessionEndRequest(callback) {
const cardTitle = 'Session Ended';
const speechOutput = 'Thank you for checking baby status';
// Setting this to true ends the session and exits the skill.
const shouldEndSession = true;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, null, shouldEndSession));
}
function getStatus(intent, session, callback) {
const cardTitle = intent.name;
let repromptText = '';
let sessionAttributes = {};
const shouldEndSession = true;
let speechOutput = '';
httpsGet((myResult) => {
console.log("received : " + myResult);
let crying = myResult.crying;
let rollover = myResult.rollover;
if(crying == "yes"){
speechOutput = 'The baby is crying. And rollover status is ' + rollover;
}else{
speechOutput = 'The baby is not crying. And rollover status is ' + rollover;
}
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
);
}
// --------------- Events -----------------------
/**
* Called when the session starts.
*/
function onSessionStarted(sessionStartedRequest, session) {
console.log(`onSessionStarted requestId=${sessionStartedRequest.requestId}, sessionId=${session.sessionId}`);
}
/**
* Called when the user launches the skill without specifying what they want.
*/
function onLaunch(launchRequest, session, callback) {
console.log(`onLaunch requestId=${launchRequest.requestId}, sessionId=${session.sessionId}`);
// Dispatch to your skill's launch.
getWelcomeResponse(callback);
}
/**
* Called when the user specifies an intent for this skill.
*/
function onIntent(intentRequest, session, callback) {
console.log(`onIntent requestId=${intentRequest.requestId}, sessionId=${session.sessionId}`);
const intent = intentRequest.intent;
const intentName = intentRequest.intent.name;
// Dispatch to your skill's intent handlers
if (intentName === 'Status') {
getStatus(intent, session, callback);
} else if (intentName === 'AMAZON.HelpIntent') {
getWelcomeResponse(callback);
} else if (intentName === 'AMAZON.StopIntent' || intentName === 'AMAZON.CancelIntent') {
handleSessionEndRequest(callback);
} else {
throw new Error('Invalid intent');
}
}
/**
* Called when the user ends the session.
* Is not called when the skill returns shouldEndSession=true.
*/
function onSessionEnded(sessionEndedRequest, session) {
console.log(`onSessionEnded requestId=${sessionEndedRequest.requestId}, sessionId=${session.sessionId}`);
// Add cleanup logic here
}
// --------------- Main handler -----------------------
// Route the incoming request based on type (LaunchRequest, IntentRequest,
// etc.) The JSON body of the request is provided in the event parameter.
exports.handler = (event, context, callback) => {
try {
console.log(`event.session.application.applicationId=${event.session.application.applicationId}`);
/**
* Uncomment this if statement and populate with your skill's application ID to
* prevent someone else from configuring a skill that sends requests to this function.
*/
/*
if (event.session.application.applicationId !== 'amzn1.echo-sdk-ams.app.[unique-value-here]') {
callback('Invalid Application ID');
}
*/
if (event.session.new) {
onSessionStarted({ requestId: event.request.requestId }, event.session);
}
if (event.request.type === 'LaunchRequest') {
onLaunch(event.request,
event.session,
(sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
} else if (event.request.type === 'IntentRequest') {
onIntent(event.request,
event.session,
(sessionAttributes, speechletResponse) => {
callback(null, buildResponse(sessionAttributes, speechletResponse));
});
} else if (event.request.type === 'SessionEndedRequest') {
onSessionEnded(event.request, event.session);
callback();
}
} catch (err) {
callback(err);
}
};
Comments