(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jiboServiceClients = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o { return response.hasOwnProperty('currentErrorId'); }, (err, response) => { if (err) { callback(err, null); } else { callback(null, response.currentErrorId); } }); } exports.getCurrentErrorId = getCurrentErrorId; function getErrorCount(callback) { WebCommunication_1.WebCommunication.sendMessage(WebCommunication_1.WebCommunication.RequestType.POST, _httpInterface + '/getErrorCount', {}, (response) => { return response.hasOwnProperty('errorCount'); }, (err, response) => { if (err) { callback(err, null); } else { callback(null, response.errorCount); } }); } exports.getErrorCount = getErrorCount; function subscribeError(errorCode, callback) { if (_subscribeErrorHttpRequest.request) { _subscribeErrorHttpRequest.request.abort(); } _subscribeErrorHttpRequest.data = errorCode; _subscribeErrorHttpRequest.request = WebCommunication_1.WebCommunication.sendMessage(WebCommunication_1.WebCommunication.RequestType.POST, _httpInterface + '/subscribeError', { errorCode: errorCode }, (response) => { return response.subscribedErrorId === errorCode; }, (err, response) => { _subscribeErrorHttpRequest = { request: null, data: null }; callback(err, response); }); } exports.subscribeError = subscribeError; function processedError(errorCode, callback) { WebCommunication_1.WebCommunication.sendMessage(WebCommunication_1.WebCommunication.RequestType.POST, _httpInterface + '/processedError', { errorCode: errorCode }, () => { return true; }, (err, response) => { let processedError = (!err) ? response.processedError : false; callback(err, { processedError: processedError }); }); } exports.processedError = processedError; },{"../utils/WebCommunication":25}],2:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_client_framework_1 = require("jibo-client-framework"); const LPSService_1 = require("./LPSService"); let httpUrl = null; let http = null; let isInitialized = false; function init(service, parentLog, cb) { if (!service.host || typeof service.host !== 'string') { throw new Error(`Missing required service.host`); } httpUrl = "http://" + service.host + ":" + service.port; isInitialized = true; http = new jibo_client_framework_1.HTTPClient(service.host, service.port); cb(); } exports.init = init; function createIdentity(data, cb) { _sendIdentityRequest('/identity/create', data, cb); } exports.createIdentity = createIdentity; function removeIdentity(data, cb) { _sendIdentityRequest('/identity/remove', data, cb); } exports.removeIdentity = removeIdentity; function getIdentityList(cb) { let request = new XMLHttpRequest(); request.open('GET', httpUrl + '/identity/list', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { if (request.response) { let response; let error = null; try { response = JSON.parse(request.response); } catch (e) { response = null; error = e; } cb(error, response); } else { cb('No data received from identity service', null); } } else { let msg = 'Identity service unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } cb(msg, null); } } }; request.send(); } exports.getIdentityList = getIdentityList; function getTrainingPhotoMetadata(looperId, photoIndex, cb) { let request = new XMLHttpRequest(); request.open('GET', `${httpUrl}/identity/detection?name=${looperId}&kind=face&index=${photoIndex}`, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { if (request.response) { let response; let error = null; try { response = JSON.parse(request.response); } catch (e) { response = null; error = e; } if (response.detection) { cb(error, response.detection); } else { cb('data received from identity service does not include detection property', response); } } else { cb('No data received from identity service', null); } } else { let msg = 'Identity service unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } cb(msg, null); } } }; request.send(); } exports.getTrainingPhotoMetadata = getTrainingPhotoMetadata; function getTrainingPhotoURI(looperId, photoIndex) { const path = '/identity/photo'; const queryString = `?name=${looperId}&index=${photoIndex}&kind=face`; return `${httpUrl}${path}${queryString}`; } exports.getTrainingPhotoURI = getTrainingPhotoURI; function sendTrainingRequest(data, cb) { const path = '/lps/identity/train'; _sendIdentityRequest(path, data, cb, LPSService_1.lps.httpUrl); } exports.sendTrainingRequest = sendTrainingRequest; function _sendIdentityRequest(path, data, cb, httpUrlOverride) { if (httpUrl === undefined) { cb('Identity service is not initialized', null); return; } let params = {}; if (!data.hasOwnProperty('name')) { cb("Identity data must have 'name' property", null); return; } if (!data.hasOwnProperty('kind')) { data.kind = "face"; } params.name = data.name; params.kind = data.kind; let request = new XMLHttpRequest(); request.open("POST", (httpUrlOverride || httpUrl) + path, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status < 300) { cb(); } else { let msg = 'Identity service unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } let errorData = null; if (request.response) { try { errorData = JSON.parse(request.response); } catch (e) { errorData = 'Response is not JSON.'; } } cb(msg, errorData); } } }; request.send(JSON.stringify(params)); } },{"./LPSService":3,"jibo-client-framework":undefined}],3:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_typed_events_1 = require("jibo-typed-events"); const async = require("async"); const jibo_client_framework_1 = require("jibo-client-framework"); const id_1 = require("./id"); const detectors_1 = require("./detectors"); let log; let lpsData = {}; lpsData.motionData = { cameras: [], entities: [], ts: [0, 0] }; lpsData.audioData = { entities: [], ts: [0, 0] }; let httpUrl; let lpsServiceUrl; let motionSocket; let audioSocket; let _demandDetectQueue = []; let _demandDetectRedetect = false; let _lightingQuality = 0; let _lightingLevel = 0; let _sectors = []; class lps { static get httpUrl() { return httpUrl; } static get motionData() { return lpsData.motionData; } static get audioData() { return lpsData.audioData; } static get lightingQuality() { return _lightingQuality; } static get lightingLevel() { return _lightingLevel; } } exports.lps = lps; (function (lps) { class LPSEvents extends jibo_typed_events_1.EventContainer { constructor() { super(...arguments); this.audio = new jibo_typed_events_1.Event('LPS Audio Event'); this.motion = new jibo_typed_events_1.Event('LPS Motion Event'); } } lps.LPSEvents = LPSEvents; lps.events = new LPSEvents(); lps.identity = new id_1.default(lps); lps.detector = new detectors_1.default(); function getClosestVisualEntity() { let entity; if (lpsData.motionData !== undefined && lpsData.motionData.entities !== undefined && lpsData.motionData.entities.length > 0) { entity = lpsData.motionData.entities[0]; } return entity; } lps.getClosestVisualEntity = getClosestVisualEntity; function getVisualEntityById(id) { let entity; for (let i = 0; i < lpsData.motionData.entities.length; i++) { let itr = lpsData.motionData.entities[i]; if (itr && (itr.id === id)) { entity = itr; break; } } return entity; } lps.getVisualEntityById = getVisualEntityById; function getClosestAudibleEntity() { let entity; if (lpsData.audioData !== undefined && lpsData.audioData.entities !== undefined && lpsData.audioData.entities.length > 0) { entity = lpsData.audioData.entities[0]; } return entity; } lps.getClosestAudibleEntity = getClosestAudibleEntity; function getAudibleEntityById(id) { let entity; for (let i = 0; i < lpsData.audioData.entities.length; i++) { let itr = lpsData.audioData.entities[i]; if (itr && (itr.id === id)) { entity = itr; break; } } return entity; } lps.getAudibleEntityById = getAudibleEntityById; function getCameraParameters(cameraID, cb) { if (httpUrl === undefined) { cb('Identity service is not initialized', null); return; } let params = {}; params.cameraId = cameraID; let request = new XMLHttpRequest(); request.open("GET", httpUrl + '/lps/camera/calibration?cameraId=' + cameraID, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { try { const data = JSON.parse(request.response); cb(null, data); } catch (e) { const errorData = 'Response is not JSON.'; cb(errorData, null); } } else { let msg = 'LPS service unavailable:'; if (request.statusText !== undefined && request.statusText !== "") { msg += request.statusText; } let errorData = null; if (request.response) { try { errorData = JSON.parse(request.response); } catch (e) { errorData = 'Response is not JSON.'; } } cb(msg, errorData); } } }; request.send(); } lps.getCameraParameters = getCameraParameters; function getFaces(cameraID, cb, kind, initTracks = false) { if (httpUrl === undefined) { cb('Identity service is not initialized', null); return; } let params = {}; params.camera_id = cameraID; params.kind = kind; params.init_tracks = initTracks; let request = new XMLHttpRequest(); request.open("POST", httpUrl + '/lps/faces', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { try { const data = JSON.parse(request.response); cb(null, data); } catch (e) { const errorData = 'Response is not JSON.'; cb(errorData, null); } } else { let msg = 'LPS service unavailable:'; if (request.statusText !== undefined && request.statusText !== "") { msg += request.statusText; } let errorData = null; if (request.response) { try { errorData = JSON.parse(request.response); } catch (e) { errorData = 'Response is not JSON.'; } } cb(msg, errorData); } } }; request.send(JSON.stringify(params)); } lps.getFaces = getFaces; function demandDetect(cameraID, redetect, cb) { log.debug("demandDetect", cameraID, redetect); if (!!_demandDetectQueue.length) { if (_demandDetectRedetect === redetect) { _demandDetectQueue.push(cb); return; } else { cb('Cannot Demand Detect while call with redetect:' + _demandDetectRedetect + ' is in progress', null); return; } } _demandDetectRedetect = redetect; _demandDetectQueue.push(cb); if (httpUrl === undefined) { _clearDemandDetectCallbacks('LPS service is not initialized', null); return; } const data = { 'camera_id': cameraID, 'roi': { 'left': 0, 'top': 0, 'right': 640, 'bottom': 360 }, 'redetect': redetect }; const request = new XMLHttpRequest(); request.open('POST', httpUrl + '/lps/demand_detect', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { if (request.response) { let response = {}; try { response = JSON.parse(request.response); _clearDemandDetectCallbacks(null, response.detections); } catch (e) { cb(e, null); } } else { _clearDemandDetectCallbacks('No data received from LPS demand detection', null); } } else { let msg = 'Demand Detect failure:'; if (request.statusText !== undefined && request.statusText !== '') { msg += request.statusText; } _clearDemandDetectCallbacks(msg, null); } } }; request.send(JSON.stringify(data)); } lps.demandDetect = demandDetect; function _clearDemandDetectCallbacks(err, data) { _demandDetectQueue.forEach((callback) => { callback(err, data); }); _demandDetectQueue = []; } lps._clearDemandDetectCallbacks = _clearDemandDetectCallbacks; function readBarcode(cb) { if (httpUrl === undefined) { cb('Barcode service is not initialized', null); return; } let request = new XMLHttpRequest(); request.open("GET", httpUrl + '/lps/barcode', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { if (request.response) { let response = JSON.parse(request.response); cb(null, response.barcodes); } else { cb('No data received from barcode service', null); } } else { let msg = 'Barcode service unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } cb(msg, null); } } }; request.send(); } lps.readBarcode = readBarcode; function setPresence(presenceData, cb) { if (httpUrl === undefined) { cb('LPS Service is not initialized', null); return; } let request = new XMLHttpRequest(); request.open("POST", httpUrl + '/lps/presence', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { if (request.response) { const response = JSON.parse(request.response); cb(null, response); } else { cb('No data received from barcode service', null); } } else { let msg = 'Failed to set presence'; if (request.statusText !== undefined && request.statusText !== "") { msg += request.statusText; } cb(msg, null); } } }; request.send(JSON.stringify(presenceData)); } lps.setPresence = setPresence; function init(service, parentLog, cb) { log = parentLog.createChild('LPS'); lpsServiceUrl = "ws:" + service.host + ":" + service.port; httpUrl = "http://" + service.host + ":" + service.port; async.parallel([ _createMotionSocket, _createAudioSocket ], cb); lps.identity.init(parentLog); lps.detector.init(parentLog); } lps.init = init; function _createMotionSocket(cb) { motionSocket = new jibo_client_framework_1.WSClient(lpsServiceUrl + "/lps/visual_awareness"); motionSocket.on('error', () => { console.error(`Error opening visual awareness socket at ${lpsServiceUrl}/visual_awareness`); }); motionSocket.on('message', (data) => { lpsData.motionData = data; lps.events.motion.emit(data); if (data.awareness && data.awareness.sectors) { _extractSectorInformation(data.awareness.sectors); } }); cb(); } lps._createMotionSocket = _createMotionSocket; function _createAudioSocket(cb) { audioSocket = new jibo_client_framework_1.WSClient(lpsServiceUrl + "/lps/audible_awareness"); audioSocket.on('error', () => { console.error(`Error opening audible awareness socket at ${lpsServiceUrl}/audible_awareness`); }); audioSocket.on('message', (data) => { lpsData.audioData = data; if (data.entities.length) { lps.events.audio.emit(data); } }); cb(); } lps._createAudioSocket = _createAudioSocket; function _extractSectorInformation(sectors) { _sectors = sectors; _sectors.sort((sect1, sect2) => { if (sect1.visibility) { return sect2.visibility.value - sect1.visibility.value; } }); _lightingLevel = (_sectors[0].lightingLevel.value + _sectors[1].lightingLevel.value + _sectors[2].lightingLevel.value) / 3; _lightingQuality = (_sectors[0].lightingQuality.value + _sectors[1].lightingQuality.value + _sectors[2].lightingQuality.value) / 3; } lps._extractSectorInformation = _extractSectorInformation; })(lps = exports.lps || (exports.lps = {})); },{"./detectors":16,"./id":23,"async":undefined,"jibo-client-framework":undefined,"jibo-typed-events":undefined}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_client_framework_1 = require("jibo-client-framework"); let mediaManagerServiceUrl; let httpClient; let isInitialized = false; class mediaManager { static delete(contentID, immediate, deleteLocal, deleteRemote, mediaType, callback) { if (!isInitialized) { return callback(new Error('Media Manager service is not initialized!')); } let data = { contentID: contentID, immediate: immediate, deleteLocal: deleteLocal, deleteRemote: deleteRemote, type: mediaType }; httpClient.postJSON('/media-manager/delete', data, callback); } } exports.mediaManager = mediaManager; (function (mediaManager) { let MediaType; (function (MediaType) { MediaType["image"] = "image"; MediaType["recording"] = "recording"; MediaType["thumb"] = "thumb"; MediaType["thumb_robot"] = "thumb_robot"; MediaType["audio"] = "audio"; })(MediaType = mediaManager.MediaType || (mediaManager.MediaType = {})); function init(service, parentLog, callback) { if (!service.host || typeof service.host !== 'string') { throw new Error(`Missing required service.host`); } mediaManagerServiceUrl = "http://" + service.host + ":" + service.port; isInitialized = true; httpClient = new jibo_client_framework_1.HTTPClient(service.host, service.port); process.nextTick(callback); } mediaManager.init = init; function adopt(contentIDs, mediaType, callback) { if (!isInitialized) { return callback(new Error('Media Manager service is not initialized!')); } let data = { contentIDs: contentIDs, mediaType: mediaType, }; httpClient.postJSON('/media-manager/adopt', data, callback); } mediaManager.adopt = adopt; function upload(contentID, immediate, keepLocal, mediaType, reference, callback) { if (!isInitialized) { return callback(new Error('Media Manager service is not initialized!')); } let data = { contentID: contentID, immediate: immediate, keepLocal: keepLocal, type: mediaType, reference: reference }; httpClient.postJSON('/media-manager/upload', data, callback); } mediaManager.upload = upload; function download(contentID, immediate, mediaType, callback) { if (!isInitialized) { return callback(new Error('Media Manager service is not initialized!')); } let data = { contentID: contentID, immediate: immediate, type: mediaType }; httpClient.postJSON('/media-manager/download', data, callback); } mediaManager.download = download; })(mediaManager = exports.mediaManager || (exports.mediaManager = {})); },{"jibo-client-framework":undefined}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_client_framework_1 = require("jibo-client-framework"); let mediaServiceUrl; let http; let httpUrl; let isInitialized = false; let _recording = false; class media { static get recording() { return _recording; } } exports.media = media; (function (media) { let PhotoType; (function (PhotoType) { PhotoType[PhotoType["DEBUG"] = 0] = "DEBUG"; PhotoType[PhotoType["PREVIEW"] = 1] = "PREVIEW"; PhotoType[PhotoType["HALF"] = 1] = "HALF"; PhotoType[PhotoType["SNAP"] = 2] = "SNAP"; PhotoType[PhotoType["FULL"] = 2] = "FULL"; PhotoType[PhotoType["FOUR_MP"] = 3] = "FOUR_MP"; PhotoType[PhotoType["LARGE"] = 3] = "LARGE"; })(PhotoType = media.PhotoType || (media.PhotoType = {})); let CameraID; (function (CameraID) { CameraID[CameraID["LEFT"] = 0] = "LEFT"; CameraID[CameraID["RIGHT"] = 1] = "RIGHT"; })(CameraID = media.CameraID || (media.CameraID = {})); function init(service, parentLog, cb) { if (!service.host || typeof service.host !== 'string') { throw new Error(`Missing required service.host`); } mediaServiceUrl = "http://" + service.host + ":" + service.port; isInitialized = true; http = new jibo_client_framework_1.HTTPClient(service.host, service.port); httpUrl = "http://" + service.host + ":" + service.port; process.nextTick(cb); } media.init = init; function takePhoto(camera, photoType, filters, store, callback) { if (!isInitialized) { return callback(new Error('Service not initialized')); } if (camera !== CameraID.LEFT && camera !== CameraID.RIGHT) { camera = CameraID.RIGHT; } if (photoType === undefined || (photoType < PhotoType.DEBUG || photoType > PhotoType.FOUR_MP)) { photoType = PhotoType.SNAP; } if (!filters) { filters = []; } let data = { 'camera': camera, 'type': photoType, 'filters': filters }; http.postJSON('/media/photo', data, (err, response) => { if (err) { callback(err); } else { callback(null, response); } }); } media.takePhoto = takePhoto; function storePhoto(buffer, id, thumbnails, callback) { let data = { buffer: buffer && buffer.toString('base64'), id: id || '', thumbnails: thumbnails }; http.postJSON('/media/photo/store', data, (err, response) => { if (err) { callback(err); } else { callback(null, response); } }); } media.storePhoto = storePhoto; function getUrl(id) { return mediaServiceUrl + `/media/photo/get?id=${id}`; } media.getUrl = getUrl; function getPreviewUrl(id) { return mediaServiceUrl + `/media/photo?id=${id}`; } media.getPreviewUrl = getPreviewUrl; function setViewfinder(data, callback) { if (!isInitialized) { return callback(new Error('Service not initialized')); } let params = {}; if (!data.hasOwnProperty('enable')) { callback("Preview service data must have 'enable' property", null); return; } if (!data.hasOwnProperty('width')) { data.width = 1280; } if (!data.hasOwnProperty('height')) { data.height = 720; } if (!data.hasOwnProperty('x')) { data.x = 0; } if (!data.hasOwnProperty('y')) { data.y = 0; } if (!data.hasOwnProperty('camera')) { data.camera = CameraID.RIGHT; } params.enable = data.enable; params.camera = data.camera; params.window = { width: data.width, height: data.height, x: data.x, y: data.y }; let request = new XMLHttpRequest(); request.open("POST", httpUrl + '/media/preview/control', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { callback(); } else { let msg = 'Preview service unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg, null); } } }; request.send(JSON.stringify(params)); } media.setViewfinder = setViewfinder; function getViewfinder(callback) { if (!isInitialized) { return callback(new Error('Service not initialized')); } let request = new XMLHttpRequest(); request.open("GET", httpUrl + '/media/preview/control', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 299) { if (request.response) { let response = {}; try { response = JSON.parse(request.response); callback(null, response); } catch (e) { callback(e); } } else { callback('No data received from media service', null); } } else { let msg = 'Preview service unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg, null); } } }; request.send(); } media.getViewfinder = getViewfinder; function startRecording(options, callback) { if (_recording === true) { throw new Error("jibo.media.MediaService.startRecording() was called twice. Call jibo.media.MediaService.stopRecording() before calling it again."); } let payload = { "meta": {} }; if (options.audio) { payload.audioRec = { volume: 1, source: "ASRIn.monitor" }; } if (options.video) { payload.videoRec = { width: options.video.width || 640, height: options.video.height || 360 }; } _recording = true; _stopRecording((err) => { if (err) { callback(err); return; } http.postJSON("/media/recording/start", payload, (err, response) => { if (err) { callback(err); return; } callback(null, { id: response.id }); }); }); } media.startRecording = startRecording; function stopRecording(callback) { if (_recording === false) { throw new Error("jibo.media.MediaService.stopRecording() was called when there was no recording in progress."); } _stopRecording((err) => { _recording = false; if (err) { callback(err); return; } callback(null); }); } media.stopRecording = stopRecording; function playRecording(options, callback) { let payload = { source: options.id, audio: { volume: 1 } }; http.postJSON("/media/recording/play", payload, (err, response) => { if (err) { callback(err); return; } callback(null); }); } media.playRecording = playRecording; function _stopRecording(callback) { let payload = { id: 0, cmd: "stop" }; http.postJSON("/media/recording/control", payload, (err) => { if (err) { callback(err); return; } callback(null); }); } })(media = exports.media || (exports.media = {})); },{"jibo-client-framework":undefined}],6:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); let httpInterface; let initialized = false; function init(service, parentLog, callback) { httpInterface = "http://" + service.host + ":" + service.port; initialized = true; callback(); } exports.init = init; function log(type, description = '') { if (!initialized) { return; } let request = new XMLHttpRequest(); request.open("POST", httpInterface + '/log', true); request.send(JSON.stringify({ time: now(), type, description })); } exports.log = log; function now() { return performance.timing.navigationStart + performance.now(); } exports.now = now; },{}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); let _httpInterface = null; let _initialized = false; function init(service, parentLog, callback) { _httpInterface = "http://" + service.host + ":" + service.port; _initialized = true; callback(); } exports.init = init; function backupRobot(callback) { _sendRequest('/backup-robot', callback); } exports.backupRobot = backupRobot; function backupStatus(callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/backup-status', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.backupRobot response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null, response.data); } else { callback(new Error(response.message)); } } }; request.send(); } exports.backupStatus = backupStatus; function otaDownloadAndInstall(callback) { _sendRequest('/ota-update', callback); } exports.otaDownloadAndInstall = otaDownloadAndInstall; function otaDownloadStatus(callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/download-status', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.otaDownloadStatus response is not JSON. Timed out or bad format?' + e)); } if (request.status === 200) { callback(null, response.data); } else { callback(new Error(response.message)); } } }; request.send(); } exports.otaDownloadStatus = otaDownloadStatus; function otaCheckUpdates(callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/check-updates', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.otaCheckUpdates response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null, response.data); } else { callback(new Error(response.message)); } } }; request.send(); } exports.otaCheckUpdates = otaCheckUpdates; function addJob(schedule, skillData, callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/add', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.addJob response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null, response.job); } else { callback(new Error(response.message)); } } }; request.send(JSON.stringify({ schedule, skillData })); } exports.addJob = addJob; function removeJob(jobId, callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/remove', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.removeJob response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null); } else { callback(new Error(response.message)); } } }; request.send(JSON.stringify({ jobId })); } exports.removeJob = removeJob; function listJobs(callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/list', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.listJobs response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null, response.jobs); } else { callback(new Error(response.message)); } } }; request.send(); } exports.listJobs = listJobs; function hasJob(jobId, callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + '/has-job', true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler.hasJob response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null, response.jobData); } else { callback(new Error(response.message)); } } }; request.send(JSON.stringify({ jobId })); } exports.hasJob = hasJob; function _sendRequest(url, callback) { if (!_initialized) { return callback(new Error('Scheduler Service not initialized.')); } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + url, true); request.onreadystatechange = () => { if (request.readyState === 4) { let response = null; try { response = JSON.parse(request.response); } catch (e) { return callback(new Error('Scheduler ' + url + ' response is not JSON. Timed out or bad format? ' + e)); } if (request.status === 200) { callback(null); } else { callback(new Error(response.message)); } } }; request.send(); } },{}],8:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const WebCommunication_1 = require("../utils/WebCommunication"); let _httpInterface; let _wsInterface; let _initialized; function init(service, parentLog, callback) { _httpInterface = "http://" + service.host + ":" + service.port; _wsInterface = "ws:" + service.host + ":" + service.port; _initialized = true; callback(); } exports.init = init; function hasBackupData(callback) { WebCommunication_1.WebCommunication.sendMessage(WebCommunication_1.WebCommunication.RequestType.GET, _httpInterface + '/hasBackupData', {}, (response, status) => { return (response.hasOwnProperty('isReady') && status === 200); }, (err, response) => { if (err) { callback(err, null); } else { callback(null, Boolean(response.isReady)); } }); } exports.hasBackupData = hasBackupData; function isUGCKeyReady(callback) { WebCommunication_1.WebCommunication.sendMessage(WebCommunication_1.WebCommunication.RequestType.GET, _httpInterface + '/UGCKeyReady', {}, (response, status) => { return (response.hasOwnProperty('isReady') && status === 200); }, (err, response) => { if (err) { callback(err, null); } else { callback(null, Boolean(response.isReady)); } }); } exports.isUGCKeyReady = isUGCKeyReady; },{"../utils/WebCommunication":25}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_client_framework_1 = require("jibo-client-framework"); const jibo_typed_events_1 = require("jibo-typed-events"); const ServiceOwner_1 = require("../utils/ServiceOwner"); let log; exports.notifications = { type: "", channel: "", ts: [0, 0], data: {} }; exports.onShutdown = new jibo_typed_events_1.Event('Shutdown'); exports.httpInterface = null; let socketUrl = null; let NotificationSocket = null; function init(service, parentLog, cb) { log = parentLog.createChild('SystemManager'); exports.httpInterface = "http://" + service.host + ":" + service.port; socketUrl = "ws:" + service.host + ":" + service.port; getVersion((error, currentVersion) => { if (error) { cb(error); return; } const versions = ServiceOwner_1.ServiceOwner.versions; if (versions && !versions.supported(currentVersion)) { cb(`Platform version check failed! Skill allows version ${versions.requiresPlatform} but your current version is ${currentVersion}.`); } else { _createNotificationSocket(cb); } }); } exports.init = init; function _createNotificationSocket(cb) { NotificationSocket = new jibo_client_framework_1.WSClient(socketUrl + "/system_notifications"); NotificationSocket.on('error', () => { log.warn(`Error opening system notifications socket at ${socketUrl}/system_notifications`); }); NotificationSocket.on('message', (data) => { try { exports.notifications = data; if (exports.notifications && exports.notifications.type === 'ShutdownWarning') { exports.onShutdown.emit(exports.notifications); } else { log.warn('unhandled System Notification: ', exports.notifications); } } catch (e) { log.warn('System notification event data is not JSON format. ', e); } }); cb(); } function getVersion(callback) { getDisplayVersion((error, version) => { if (version) { let verMatch = version.trim().match('(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)'); if (verMatch.length) { callback(null, verMatch[0]); } else { callback(`Invalid platform version ${version}`, null); } } else { callback(`Could not retrieve platform version from ${version}`, null); } }); } exports.getVersion = getVersion; function getDisplayVersion(callback) { _handleGET("/version", "version", callback); } exports.getDisplayVersion = getDisplayVersion; function getCredentials(callback) { _handleGET("/credentials", undefined, (error, data) => { if (error || !data) { return callback((!error ? "No credentials set" : error), null); } if (!data.hasOwnProperty("accessKeyId") || data["accessKeyId"].length === 0) { return callback("No credentials set"); } if (!data.hasOwnProperty("secretAccessKey") || data["secretAccessKey"].length === 0) { return callback("No credentials set"); } if (!data.hasOwnProperty("region") || data["region"].length === 0) { return callback("No credentials set"); } callback(null, data); }); } exports.getCredentials = getCredentials; function setCredentials(creds, callback) { if (!creds) { callback("No credentials given"); return; } let request = new XMLHttpRequest(); let body = ""; try { body = JSON.stringify(creds); } catch (e) { callback("Credentials are not valid JSON"); return; } request.open("POST", exports.httpInterface + "/credentials", true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 204) { callback(); } else { let msg = 'System Manager is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg); } } }; log.info("credentials requested:", body); request.send(body); } exports.setCredentials = setCredentials; function getMode(callback) { _handleGET("/mode", "mode", callback); } exports.getMode = getMode; function setMode(_mode, callback) { if (!_mode) { callback("No mode given"); return; } let request = new XMLHttpRequest(); let body = ""; try { body = JSON.stringify({ mode: _mode }); } catch (e) { callback("Mode request is not valid JSON"); return; } request.open("POST", exports.httpInterface + "/mode", true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 204) { callback(); } else { let msg = 'System Manager is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg); } } }; log.info("mode requested:", body); request.send(body); } exports.setMode = setMode; function getCurrentTime(callback) { _handleGET("/time/current", "time", callback); } exports.getCurrentTime = getCurrentTime; function syncTime(callback) { _handlePOST("/time/synchronize", callback); log.info("Sync time requested"); } exports.syncTime = syncTime; function getTimeZone(callback) { _handleGET("/time/zone", "timezone", callback); } exports.getTimeZone = getTimeZone; function wipe(callback) { _handlePOST("/system/wipe", callback); } exports.wipe = wipe; function backup(callback) { _handlePOST("/system/backup", callback); } exports.backup = backup; function restore(callback) { _handlePOST("/system/restore", callback); } exports.restore = restore; function poweroff(callback) { _handlePOST("/power/off", callback); } exports.poweroff = poweroff; function reboot(callback) { _handlePOST("/power/reboot", callback); } exports.reboot = reboot; function forceLogs(callback) { let request = new XMLHttpRequest(); request.open("POST", exports.httpInterface + "/logs/upload", true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { let response = {}; try { response = JSON.parse(request.response); } catch (e) { return callback(e); } if (response.result === "error") { callback(response.error); } } else { callback("ForceLogs failed- return status " + request.status); } } else { callback(null); } }; request.send(); } exports.forceLogs = forceLogs; function checkForUpdates(callback, filter) { let url = "/update"; if (filter && typeof filter === 'string') { url = url + '/' + filter; } _handleGET(url, null, (err, response) => { if (err) { callback(err, null); return; } if (response && response.hasOwnProperty("updates")) { callback(null, response.updates); return; } let errMsg = "Service temporarily unavailable"; if (response && response.hasOwnProperty("error")) { errMsg = response.error; } callback(errMsg, null); }); } exports.checkForUpdates = checkForUpdates; function downloadUpdates(data, callback) { if (!data || !data.hasOwnProperty('ids') || data.ids.length === 0) { callback('No IDs given.'); return; } let request = new XMLHttpRequest(); request.open("PUT", exports.httpInterface + "/update", true); request.previousText = ""; request.onreadystatechange = () => { if (request.readyState > 2) { if (request.status === 200) { if (request.responseText) { let newResponse = request.responseText.substring(request.previousText.length); let lastIdx = newResponse.lastIndexOf('}'); if (lastIdx !== -1) { lastIdx += 1; let firstIdx = newResponse.lastIndexOf('{', lastIdx); if (firstIdx !== -1) { newResponse = newResponse.substring(firstIdx, lastIdx); let cbData = JSON.parse(newResponse); callback(null, cbData); request.previousText = request.responseText.substring(0, request.responseText.lastIndexOf('}') + 1); } } } else { callback('No data received from OTA service', null); } } else { let msg = 'System Manager is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg, null); } } }; getVersion((error, version) => { if (error) { callback("Cannot retrieve platform version to check compatibility. Download aborted.", null); } else { let body = {}; if (version === "0.12.1") { body = { "id": data.ids[0] }; } else { body = { "ids": data.ids }; } request.send(JSON.stringify(body)); } }); } exports.downloadUpdates = downloadUpdates; function installUpdates(data, callback) { if (!data || !data.hasOwnProperty('ids') || data.ids.length === 0) { callback('No IDs given.'); return; } let request = new XMLHttpRequest(); request.open("POST", exports.httpInterface + "/update", true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { if (request.response && request.response.length > 0) { let response = {}; try { response = JSON.parse(request.response); } catch (e) { return callback(e); } callback(response.error); } else { callback(); } } } }; let body = { "ids": data.ids }; log.info("Install updates requested:", body); request.send(JSON.stringify(body)); } exports.installUpdates = installUpdates; function _handleGET(url, property, callback) { let request = new XMLHttpRequest(); request.open("GET", exports.httpInterface + url, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { let response = JSON.parse(request.response); let data = (property ? response[property] : response); callback(null, data); } else { let msg = 'System Manager is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg, null); } } }; request.send(); } function _handlePOST(url, callback) { let request = new XMLHttpRequest(); request.open("POST", exports.httpInterface + url, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 204) { callback(); } else { let msg = 'System Manager is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg); } } }; request.send(); } function getIdentity(callback) { _handleGET("/identity", undefined, (error, response) => { if (error) { callback("Could not retrieve identity from Jibo", null); } else { callback(null, { "name": response.name, "wifi_mac": response.wifi_mac, "serial_number": response.serial_number }); } }); } exports.getIdentity = getIdentity; },{"../utils/ServiceOwner":24,"jibo-client-framework":undefined,"jibo-typed-events":undefined}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const async = require("async"); const jibo_client_framework_1 = require("jibo-client-framework"); const jibo_typed_events_1 = require("jibo-typed-events"); const jibo_common_types_1 = require("jibo-common-types"); const TouchHandler_1 = require("./TouchHandler"); let log; let bodyOutput; let bs = new jibo_common_types_1.BodyState(); let bodyHttpInterface; let audioHttpInterface; let socketUrl; let powerSource; let hatchOpen = false; let isMoving = false; let _inputEnergy; let miscSocket; let touchSocket; let powerSocket; let axisSocket; let imuSocket; let touchHandler; class system { static set output(_output) { bodyOutput = _output; } static get pluggedIn() { return (bs.powerState.source === 'EXTERNAL'); } static get batteryCharging() { return (bs.powerState.battery.charge_rate >= 0.1); } static get batteryChargeRate() { return bs.powerState.battery.charge_rate; } static get padState() { return touchHandler.touchState.pad_state; } static get inputEnergy() { return _inputEnergy; } } exports.system = system; (function (system) { class SystemEvents extends jibo_typed_events_1.EventContainer { constructor() { super(); this.touchChanged = new jibo_typed_events_1.Event('System Touch Change Event'); this.inputEnergy = new jibo_typed_events_1.Event('Audio Input Energy changes'); this.touchOn = new jibo_typed_events_1.Event('A Touch Pad Has Been Touched From None'); this.touchOff = new jibo_typed_events_1.Event('All Touch Pads Turned Off'); this.axisFaultOn = new jibo_typed_events_1.Event('Motor Axis Fault On'); this.axisFaultOff = new jibo_typed_events_1.Event('Motor Axis Fault Off'); this.hatchOpen = new jibo_typed_events_1.Event("Jibo's hatch was opened"); this.hatchClose = new jibo_typed_events_1.Event("Jibo's hatch was closed"); this.pluggedIn = new jibo_typed_events_1.Event('Jibo was plugged in'); this.unplugged = new jibo_typed_events_1.Event('Jibo was unplugged'); } } system.SystemEvents = SystemEvents; system.events = new SystemEvents(); function initBody(service, parentLog, callback) { log = parentLog.createChild("SystemService"); touchHandler = new TouchHandler_1.TouchHandler(system.events, parentLog); bodyHttpInterface = "http://" + service.host + ":" + service.port; socketUrl = "ws:" + service.host + ":" + service.port; async.parallel([ _createMiscSocket, _createTouchSocket, _createPowerSocket, _createAxisSocket, _createIMUSocket ], callback); } system.initBody = initBody; function getBatteryTemperature() { return bs.powerState.battery.temp; } system.getBatteryTemperature = getBatteryTemperature; function getBatteryLevel() { return (bs.powerState.battery.capacity / bs.powerState.battery.max_capacity) * 100; } system.getBatteryLevel = getBatteryLevel; function getSystemVoltage() { return bs.powerState.vsys; } system.getSystemVoltage = getSystemVoltage; function getMainBoardTemperature() { return bs.miscState.main_board_temp; } system.getMainBoardTemperature = getMainBoardTemperature; function getCPUTemperature() { return bs.miscState.cpu_temp; } system.getCPUTemperature = getCPUTemperature; function getTouchState() { return touchHandler.touchState; } system.getTouchState = getTouchState; function getFanSpeed(callback) { _getSystemSetting("fan_speed", callback); } system.getFanSpeed = getFanSpeed; function getFanMode(callback) { _getSystemSetting("fan_mode", callback); } system.getFanMode = getFanMode; function getBacklight(callback) { _getSystemSetting("lcd_backlight", callback); } system.getBacklight = getBacklight; function setBacklight(value, callback) { if ((value < 0.0) || (value > 1.0)) { return callback(`Backlight brightness value of ${value} is out of range [0.0 - 1.0].`); } getFanMode((fanModeError, fanMode) => { if (fanModeError) { callback(fanModeError); } else { getFanSpeed((fanSpeedError, fan) => { if (fanSpeedError) { callback(fanSpeedError); } else { const body = { "lcd_backlight": value, "fan_speed": fan, "fan_mode": fanMode, }; const request = new XMLHttpRequest(); const uri = bodyHttpInterface + '/settings'; request.open("POST", uri, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 204) { callback(null); } else { let message = 'Body service is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { message = request.statusText; } callback(message); } } }; request.send(JSON.stringify(body)); } }); } }); } system.setBacklight = setBacklight; function getMasterVolume(callback) { _getMixerSetting((error, settings) => { if (error) { callback(error); } else { callback(null, settings.master.playbackVolume); } }); } system.getMasterVolume = getMasterVolume; function setMasterVolume(value, cb) { if (isNaN(value)) { let error = value + ' is not a number. Please pick a value between [0.0 - 1.0].'; cb(error); return; } if (value < 0.0 || value > 1.0) { let error = 'Master volume of ' + value + ' is out of range [0.0 - 1.0].'; cb(error); return; } _getMixerSetting((error, settings) => { if (error) { cb(error); } else { let request = new XMLHttpRequest(); let uri = audioHttpInterface + '/mixer'; request.open("POST", uri, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 204) { cb(null); } else { let msg = 'Audio Service is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } cb(msg); } } }; settings.master.playbackVolume = value; request.send(JSON.stringify(settings)); } }); } system.setMasterVolume = setMasterVolume; function initAudio(service, parentLog, callback) { audioHttpInterface = "http://" + service.host + ":" + service.port; _inputEnergy = { ts: [], db_rms: 0.0, db_high: 0.0, db_mid: 0.0, db_low: 0.0 }; const audioSocketUrl = "ws:" + service.host + ":" + service.port; const energySocket = new jibo_client_framework_1.WSClient(audioSocketUrl + "/input_energy"); energySocket.on('error', () => { log.warn(`Error opening audio input energy socket at ${audioSocketUrl}/input_energy`); }); energySocket.on('message', (data) => { _inputEnergy = data; system.events.inputEnergy.emit(_inputEnergy); }); callback(); } system.initAudio = initAudio; function _getMixerSetting(cb) { if (!audioHttpInterface) { cb('Audio Service is not available', null); return; } let request = new XMLHttpRequest(); request.open("GET", audioHttpInterface + '/mixer', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { if (request.response) { let response = JSON.parse(request.response); cb(null, response); } else { cb('No data received from audio service', null); } } else { let msg = 'Audio service is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } cb(msg, null); } } }; request.send(); } function _createMiscSocket(callback) { miscSocket = new jibo_client_framework_1.WSClient(socketUrl + "/misc"); miscSocket.on('error', () => { log.warn(`Error opening misc state socket at ${socketUrl}/misc`); }); miscSocket.on('message', (data) => { bs.miscState = data; if (data.hatch_open && !hatchOpen) { hatchOpen = true; log.debug("hatch open"); system.events.hatchOpen.emit(); } else if (!data.hatch_open && hatchOpen) { hatchOpen = false; log.debug("hatch closed"); system.events.hatchClose.emit(); } }); callback(); } function _createTouchSocket(callback) { touchSocket = new jibo_client_framework_1.WSClient(socketUrl + "/touch"); touchSocket.on('error', () => { log.warn(`Error opening touch state socket at ${socketUrl}/touch`); }); touchSocket.on('message', (data) => { touchHandler.acceptTouch(data); }); callback(); } function _createPowerSocket(callback) { powerSocket = new jibo_client_framework_1.WSClient(socketUrl + "/power"); powerSocket.on('error', () => { log.warn(`Error opening power state socket at ${socketUrl}/power`); }); powerSocket.on('message', (data) => { bs.powerState = data; powerSource = powerSource || data.source; if (bs.powerState.source === jibo_common_types_1.PowerSource.BATTERY && powerSource === jibo_common_types_1.PowerSource.EXTERNAL) { powerSource = jibo_common_types_1.PowerSource.BATTERY; log.debug("unplugged"); system.events.unplugged.emit(); } else if (bs.powerState.source === jibo_common_types_1.PowerSource.EXTERNAL && powerSource === jibo_common_types_1.PowerSource.BATTERY) { powerSource = jibo_common_types_1.PowerSource.EXTERNAL; log.debug("plugged in"); system.events.pluggedIn.emit(); } }); callback(); } function _createAxisSocket(cb) { let axisIsFaulting = false; axisSocket = new jibo_client_framework_1.WSClient(socketUrl + "/axis_state"); axisSocket.on('error', () => { log.warn(`Error opening axis state socket at ${socketUrl}/axis_state`); }); axisSocket.on('message', (data) => { const pelvisStatus = data.pelvis.fault_status; const torsoStatus = data.torso.fault_status; const neckStatus = data.neck.fault_status; const isFaulting = pelvisStatus || torsoStatus || neckStatus; if (isFaulting && !axisIsFaulting) { axisIsFaulting = true; system.events.axisFaultOn.emit(data); } else if (!isFaulting && axisIsFaulting) { axisIsFaulting = false; system.events.axisFaultOff.emit(); } }); cb(); } function _createIMUSocket(cb) { imuSocket = new jibo_client_framework_1.WSClient(socketUrl + "/imu"); imuSocket.on('error', () => { log.warn(`Error opening axis state socket at ${socketUrl}/imu`); }); imuSocket.on('message', (data) => { bs.imuState = data; isMoving = isMoving || data.moving; if (data.moving && !isMoving) { isMoving = true; } else if (isMoving && !data.moving) { isMoving = false; } }); cb(); } function _getSystemSetting(setting, callback) { if (bodyHttpInterface === undefined) { return callback('Body Service is not available', null); } const request = new XMLHttpRequest(); request.open("GET", bodyHttpInterface + '/settings', true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { if (request.response) { const response = JSON.parse(request.response); callback(null, response[setting]); } else { callback('No data received from body service', null); } } else { let message = 'Body service is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { message = request.statusText; } callback(message, null); } } }; request.send(); } })(system = exports.system || (exports.system = {})); },{"./TouchHandler":12,"async":undefined,"jibo-client-framework":undefined,"jibo-common-types":undefined,"jibo-typed-events":undefined}],11:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const async = require("async"); const jibo_client_framework_1 = require("jibo-client-framework"); const jibo_typed_events_1 = require("jibo-typed-events"); let log; var TTSMode; (function (TTSMode) { TTSMode["SSML"] = "ssml"; TTSMode["TEXT"] = "text"; })(TTSMode = exports.TTSMode || (exports.TTSMode = {})); var TTSLocale; (function (TTSLocale) { TTSLocale["EN_US"] = "en-us"; })(TTSLocale = exports.TTSLocale || (exports.TTSLocale = {})); var TTSVoice; (function (TTSVoice) { TTSVoice["GRIFFIN"] = "griffin"; })(TTSVoice = exports.TTSVoice || (exports.TTSVoice = {})); var TTSBoolean; (function (TTSBoolean) { TTSBoolean["TRUE"] = "TRUE"; TTSBoolean["FALSE"] = "FALSE"; })(TTSBoolean = exports.TTSBoolean || (exports.TTSBoolean = {})); const APIPath = { TOKENS: '/tts_tokens', PHONES: '/tts_phones', STOP: '/tts_stop', SPEAK: '/tts_speak', TIMING: '/tts_token_times', EFFECTS: '/tts_effects', ANALYSIS: '/tts_analysis', POS_TOKENS: '/tts_lex', POS_TAGGING: '/tts_pos_tagging' }; var PedalsActions; (function (PedalsActions) { PedalsActions["START"] = "START"; PedalsActions["STOP"] = "STOP"; PedalsActions["UPDATE"] = "UPDATE"; })(PedalsActions = exports.PedalsActions || (exports.PedalsActions = {})); const defaultTTSReqBody = { prompt: '', locale: TTSLocale.EN_US, voice: TTSVoice.GRIFFIN, mode: TTSMode.TEXT }; const defaultPOSReqBody = { text: '', locale: TTSLocale.EN_US, tokens: [] }; exports.word = new jibo_typed_events_1.Event('Word'); exports.phone = new jibo_typed_events_1.Event('Phone'); exports.effect = new jibo_typed_events_1.Event('Effect'); exports.analysis = new jibo_typed_events_1.Event('Analysis'); exports.stopped = new jibo_typed_events_1.Event('Stopped'); exports.isInitialized = false; exports.isTalking = false; exports.isStopping = false; let effectsSocket; let httpInterface; let socketUrl; function init(service, parentLog, cb) { if (!service.host || typeof service.host !== 'string') { throw new Error(`Missing required service.host`); } log = parentLog.createChild("TTS"); httpInterface = "http://" + service.host + ":" + service.port; socketUrl = "ws:" + service.host + ":" + service.port; let effectsSocketCreator = (cb) => { let handler = (socket) => { effectsSocket = socket; cb(); }; createSocket(APIPath.EFFECTS, "tts sound effects", exports.effect)(handler); }; async.parallel([ createSocket(APIPath.TOKENS, "tts tokens", exports.word), createSocket(APIPath.PHONES, "tts phones", exports.phone), createSocket(APIPath.ANALYSIS, "tts analysis", exports.analysis), effectsSocketCreator ], () => { exports.isInitialized = true; cb(); }); } exports.init = init; function createSocket(path, socketDescription, emitter) { return (cb) => { let socket = new jibo_client_framework_1.WSClient(socketUrl + path); socket.on('error', () => { log.error(`Error opening ${socketDescription} socket at ${socketUrl}${path}`); }); socket.on('message', (data) => { log.debug(data); if (data) { emitter.emit(data); } }); cb(socket); }; } function speak(text, arg1, arg2) { const { options, callback } = _getOptionsAndCallback(arg1, arg2); const prom = new Promise((resolve, reject) => { if (!exports.isInitialized) { return reject('TTS service is not initialized!'); } let doSpeak = () => { if (options.skipWordEvents) { _sendTTSRequest(text, options, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); } else { getWordTimings(text, options, (err, timings) => { if (err) { reject(err); } else { _dispatchWordSchedule(timings); _sendTTSRequest(text, options, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); } }); } }; if (exports.isStopping) { exports.stopped.once(() => { doSpeak(); }); } else if (exports.isTalking) { stop(doSpeak); } else { doSpeak(); } }); if (typeof callback === 'function') { prom.then((result) => { callback(null); }, (err) => { callback(err); }); } else { return prom; } } exports.speak = speak; function stop(callback) { const prom = new Promise((resolve, reject) => { if (!exports.isInitialized) { return reject('TTS service is not initialized!'); } exports.isStopping = true; exports.isTalking = false; let request = new XMLHttpRequest(); request.timeout = 2000; request.onreadystatechange = () => { let requestIsDone = request.readyState === 4; let isErrorStatus = request.status < 200 || request.status >= 400; if (requestIsDone && request.status === 200) { exports.isStopping = false; exports.stopped.emit(); resolve(); } else if (requestIsDone && isErrorStatus) { exports.isStopping = false; exports.stopped.emit(); reject(new Error(`TTS.stop request failed with status: ${request.status}`)); } }; request.open("GET", httpInterface + APIPath.STOP, true); request.send(null); }); if (typeof callback === 'function') { prom.then((result) => { callback(null); }, (err) => { callback(err); }); } else { return prom; } } exports.stop = stop; function getWordTimings(text, arg1, arg2) { const { options, callback } = _getOptionsAndCallback(arg1, arg2); const prom = new Promise((resolve, reject) => { if (!exports.isInitialized) { return reject('TTS service is not initialized!'); } if (typeof text !== 'string') { throw new TypeError(`Invalid params: ${text}, ${TTSMode}`); } let request = new XMLHttpRequest(); let requestBody = JSON.parse(JSON.stringify(defaultTTSReqBody)); requestBody.prompt = text; requestBody.duration_stretch = options.duration_stretch || requestBody.duration_stretch; requestBody.pitchBandwidth = options.pitchBandwidth || requestBody.pitchBandwidth; requestBody.pitch = options.pitch || requestBody.pitch; requestBody.mode = options.mode || requestBody.mode; requestBody.cached = options.cached || requestBody.cached; requestBody = JSON.stringify(requestBody); request.open('POST', httpInterface + APIPath.TIMING, true); request.onreadystatechange = () => { let requestIsDone = request.readyState === 4; let isErrorStatus = request.status < 200 || request.status >= 400; if (requestIsDone && request.status === 200) { let msg; try { msg = JSON.parse(request.response); } catch (err) { reject(err); } if (msg) { if (msg.Status && msg.Status === 'ERROR') { reject(msg); } else { resolve(msg); } } } else if (requestIsDone && isErrorStatus) { reject(new Error(`Request failed with status: ${request.status}`)); } }; request.send(requestBody); }); if (typeof callback === 'function') { prom.then((result) => { callback(null, result); }, (err) => { callback(err); }); } else { return prom; } } exports.getWordTimings = getWordTimings; function startEffect(name, value) { _validateEffectNameParam(name); _validateEffectValueParam(value); let requestBody = { 'name': name, 'action': PedalsActions.START, 'param': ("" + value) }; effectsSocket.send(JSON.stringify(requestBody)); } exports.startEffect = startEffect; function stopEffect(name) { _validateEffectNameParam(name); let requestBody = { 'name': name, 'action': PedalsActions.STOP, 'param': "0" }; effectsSocket.send(JSON.stringify(requestBody)); } exports.stopEffect = stopEffect; function updateEffect(name, value) { _validateEffectNameParam(name); _validateEffectValueParam(value); let requestBody = { 'name': name, 'action': PedalsActions.UPDATE, 'param': ("" + value) }; effectsSocket.send(JSON.stringify(requestBody)); } exports.updateEffect = updateEffect; function getPOSTokens(text, arg1, arg2) { const { callback } = _getOptionsAndCallback(arg1, arg2); const prom = new Promise((resolve, reject) => { if (!exports.isInitialized) { return reject('TTS service is not initialized!'); } if (typeof text !== 'string') { throw new TypeError(`Invalid params: ${text}, ${TTSMode}`); } if (text === "") { let response = { tokens: [] }; resolve(response); return; } let requestBody = JSON.parse(JSON.stringify(defaultPOSReqBody)); requestBody.text = text; requestBody = JSON.stringify(requestBody); let url = httpInterface + APIPath.POS_TOKENS; _sendPOSRequest(requestBody, url, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); }); if (typeof callback === 'function') { prom.then((result) => { callback(null, result); }, (err) => { callback(err); }); } else { return prom; } } exports.getPOSTokens = getPOSTokens; function getPOSTags(tokens, arg1, arg2) { const { callback } = _getOptionsAndCallback(arg1, arg2); const prom = new Promise((resolve, reject) => { if (!exports.isInitialized) { return reject('TTS service is not initialized!'); } if (tokens.length === 0) { let response = { tokentags: [] }; resolve(response); return; } let requestBody = JSON.parse(JSON.stringify(defaultPOSReqBody)); requestBody.tokens = tokens; requestBody = JSON.stringify(requestBody); let url = httpInterface + APIPath.POS_TAGGING; _sendPOSRequest(requestBody, url, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); }); if (typeof callback === 'function') { prom.then((result) => { callback(null, result); }, (err) => { callback(err); }); } else { return prom; } } exports.getPOSTags = getPOSTags; function _getOptionsAndCallback(arg1, arg2) { let options = {}; let callback; if (!arg1 && !arg2) { options = {}; } else if (typeof arg1 === 'object' && !arg2) { options = arg1; } else if (typeof arg1 === 'function' && !arg2) { callback = arg1; } else if (typeof arg1 === 'object' && typeof arg2 === 'function') { options = arg1; callback = arg2; } return { options, callback }; } function _dispatchWordSchedule(wordTimings) { let start = Date.now(); let index = 0; let timings = wordTimings.tokentimes.tokens .filter(token => (token.name !== '/pau/' && token.name !== '' && token.name !== '' && token.name !== '' && token.name !== '[lpau]')); let handleWord = () => { let wordObj = timings[index]; exports.word.emit({ token: wordObj.name, timestamp: wordObj.start, status: 'PLAY', moreinfo: [] }); index++; if (index < timings.length) { let nextTime = 1000 * timings[index].start; let current = Date.now() - start; setTimeout(handleWord, Math.max(nextTime - current, 0)); } }; if (timings.length) { let nextTime = 1000 * timings[index].start; setTimeout(handleWord, nextTime); } } function _sendPOSRequest(payload, url, callback) { let request = new XMLHttpRequest(); request.open('POST', url, true); request.onreadystatechange = () => { let requestIsDone = request.readyState === 4; if (requestIsDone) { if (request.status === 200) { try { let response = JSON.parse(request.response); callback(null, response); } catch (err) { callback(err); } } else { callback(new Error(`Request failed with status: ${request.status}`)); } } }; request.send(payload); } function _sendTTSRequest(text, options, callback) { let request = new XMLHttpRequest(); let requestBody = JSON.parse(JSON.stringify(defaultTTSReqBody)); requestBody.prompt = text; if (options.duration_stretch) { requestBody.duration_stretch = options.duration_stretch; } if (options.pitchBandwidth) { requestBody.pitchBandwidth = options.pitchBandwidth; } if (options.pitch) { requestBody.pitch = options.pitch; } if (options.volume) { requestBody.volume = options.volume; } if (options.whisper) { requestBody.whisper = options.whisper; } if (options.cached) { requestBody.cached = options.cached; } if (options.earlyStopTime) { requestBody.earlyStopTime = options.earlyStopTime; } requestBody.mode = options.mode || requestBody.mode; requestBody = JSON.stringify(requestBody); request.open("POST", httpInterface + APIPath.SPEAK, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 204) { exports.isTalking = false; callback(); } else { let msg = 'TTS Service is unavailable'; if (request.statusText !== undefined && request.statusText !== "") { msg = request.statusText; } callback(msg); } } }; exports.isTalking = true; request.send(requestBody); } function _validateEffectNameParam(name) { if (typeof name !== 'string') { throw new TypeError(`Invalid params, name must be string: ${name}`); } if (!effectsSocket) { throw new Error('Effect socket not initialized.'); } } function _validateEffectValueParam(value) { if (typeof value === 'number') { if (value < 0 || value > 1) { throw new TypeError(`Value out of range [0, 1]: ${value}`); } } else if (typeof value !== 'string') { throw new TypeError(`Value must either be a number or string: ${value}`); } } },{"async":undefined,"jibo-client-framework":undefined,"jibo-typed-events":undefined}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_common_types_1 = require("jibo-common-types"); const ServiceOwner_1 = require("../utils/ServiceOwner"); let log; class TouchHandler { constructor(releaseEvents, parentLog) { log = parentLog.createChild("System.Touch"); this.touchState = new jibo_common_types_1.TouchState(); this._lastPadState = [false, false, false, false, false, false]; this.events = releaseEvents; } acceptTouch(touchState) { this.touchState = touchState; if (touchState.changed.length) { this.events.touchChanged.emit(touchState); } if (this._arrayHas(this._lastPadState, true)) { if (!this._arrayHas(this.touchState.pad_state, true)) { log.debug("touchOff", this.touchState.pad_state); this.events.touchOff.emit(this.touchState.pad_state); } } else { if (this._arrayHas(this.touchState.pad_state, true)) { log.debug("touchOn", this.touchState.pad_state); this.events.touchOn.emit(this.touchState.pad_state); if (ServiceOwner_1.ServiceOwner.globalEvents) { ServiceOwner_1.ServiceOwner.globalEvents.touchStop.emit(this.touchState.pad_state); } } } this._lastPadState = this.touchState.pad_state; } _arrayHas(array, member) { return array.indexOf(member) > -1; } } exports.TouchHandler = TouchHandler; exports.default = TouchHandler; },{"../utils/ServiceOwner":24,"jibo-common-types":undefined}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); let log; let _httpInterface; let _wsInterface; let _initialized = false; let _isConnected = false; function init(service, parentLog, callback) { log = parentLog.createChild("WifiService"); _httpInterface = "http://" + service.host + ":" + service.port; _wsInterface = "ws:" + service.host + ":" + service.port; _initialized = true; callback(); } exports.init = init; function isConnected() { return _isConnected; } exports.isConnected = isConnected; function addNetwork(networkData, minVerifyTime, callback) { log.info('addNetwork called'); let data = { networkData: networkData, minVerifyTime: minVerifyTime }; _sendWifiCommandWithErrorCode('/add_network', data, callback); } exports.addNetwork = addNetwork; function selectNetwork(_ssid, callback) { let data = { ssid: _ssid }; _sendWifiCommand('/select_network', data, callback); } exports.selectNetwork = selectNetwork; function removeNetwork(_ssid, callback) { let data = { ssid: _ssid }; _sendWifiCommand('/remove_network', data, callback); } exports.removeNetwork = removeNetwork; function removeAllNetworks(callback) { _sendWifiCommand('/remove_all', null, callback); } exports.removeAllNetworks = removeAllNetworks; function getCurrentNetwork(callback) { _getWifiData('/get_current_network', (error, response) => { if (error) { return callback(error); } callback(null, response.stats); }); } exports.getCurrentNetwork = getCurrentNetwork; function getSavedNetworks(callback) { _getWifiData('/get_saved_networks', (error, response) => { if (error) { return callback(error); } callback(null, response.networks); }); } exports.getSavedNetworks = getSavedNetworks; function verifyConnection(callback) { _sendWifiCommandWithErrorCode('/verify_connection', null, (err) => { _isConnected = !err; callback(err); }); } exports.verifyConnection = verifyConnection; function _sendWifiCommandWithErrorCode(path, data, callback) { if (!_initialized) { callback({ code: 666, description: "Wifi service is unavailable" }); return; } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + path, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { callback(); } else { let response; try { response = JSON.parse(request.response); } catch (err) { log.error('_sendWifiCommandWithErrorCode JSON Parse error: ', err, ' request: ', request.response); response = err; } callback(response); } } }; if (data) { request.send(JSON.stringify(data)); } else { request.send(); } } function _sendWifiCommand(path, data, callback) { if (!_initialized) { callback(new Error("Wifi service is unavailable")); return; } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + path, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { callback(); } else { let response; let error; try { response = JSON.parse(request.response); error = response.error; } catch (err) { log.error('_sendWifiCommand JSON Parse error: ', err, ' request: ', request.response); error = err; } callback(new Error(error)); } } }; if (data) { request.send(JSON.stringify(data)); } else { request.send(); } } function _getWifiData(path, callback) { if (!_initialized) { callback(new Error("Wifi service is unavailable")); return; } let request = new XMLHttpRequest(); request.open("POST", _httpInterface + path, true); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.readyState === 4) { let response; let error; try { response = JSON.parse(request.response); error = response.error; } catch (err) { error = err; log.error('_getWifiData JSON Parse error: ', err, ' request: ', request.response); } if (request.status === 200) { callback(null, response); } else { callback(new Error(error)); } } } }; request.send(); } var NetworkType; (function (NetworkType) { NetworkType[NetworkType["DHCP"] = 0] = "DHCP"; NetworkType[NetworkType["STATIC"] = 1] = "STATIC"; })(NetworkType = exports.NetworkType || (exports.NetworkType = {})); },{}],14:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const AmbientTrigger_1 = require("../utils/AmbientTrigger"); const SystemService_1 = require("../../SystemService"); const TunableDebug_1 = require("../utils/TunableDebug"); class AmbientAudioSpike extends AmbientTrigger_1.AmbientTrigger { constructor() { super('AmbientAudioSpike', { baselineSize: 2400, recentSize: 20, triggerSensitivity: 1.9, triggerTimeout: 500, minimumRecentMean: -55, alwaysEmitAbove: -30, minimumBaselineStdDev: 2.7, }); } init(parentLog) { super.init(parentLog); TunableDebug_1.TunableDebug.setup(this); SystemService_1.system.events.inputEnergy.on((data) => this.addSample(data.db_rms)); } } exports.AmbientAudioSpike = AmbientAudioSpike; },{"../../SystemService":10,"../utils/AmbientTrigger":17,"../utils/TunableDebug":19}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const AmbientAudioSpike_1 = require("./AmbientAudio/AmbientAudioSpike"); class Detector { constructor() { this.ambientAudioSpike = new AmbientAudioSpike_1.AmbientAudioSpike(); } init(parentLog) { this.ambientAudioSpike.init(parentLog); } } exports.default = Detector; },{"./AmbientAudio/AmbientAudioSpike":14}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const DetectorService_1 = require("./DetectorService"); exports.default = DetectorService_1.default; },{"./DetectorService":15}],17:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_typed_events_1 = require("jibo-typed-events"); const OnlineMeanAndVariance_1 = require("./OnlineMeanAndVariance"); class AmbientTrigger { constructor(name, options) { this.trigger = new jibo_typed_events_1.Event(`Ambient trigger`); this.name = name; this.options = Object.assign({}, options); this.resetSize(options.baselineSize, options.recentSize); } resetSize(baselineSize, recentSize) { this.options.baselineSize = baselineSize; this.options.recentSize = recentSize; this.samples = new Array(baselineSize + recentSize); this.sampleCount = 0; this.lastEmissionTime = 0; this.baselineStats = new OnlineMeanAndVariance_1.OnlineMeanAndVariance(); this.recentStats = new OnlineMeanAndVariance_1.OnlineMeanAndVariance(); } setTriggerSensitivity(value) { this.options.triggerSensitivity = value; } init(parentLog) { this.log = parentLog.createChild(this.name); } addSample(value) { if (!this.baselineFilled()) { this.samples[this.sampleCount] = value; this.baselineStats.add(value); } else if (!this.recentFilled()) { this.samples[this.sampleCount] = value; this.recentStats.add(value); } else { const recentPointer = this.mod((this.sampleCount + this.options.baselineSize), (this.options.baselineSize + this.options.recentSize)); const oldestBaselineIndex = this.mod((recentPointer - this.options.baselineSize), (this.options.baselineSize + this.options.recentSize)); const oldestBaseline = this.samples[oldestBaselineIndex]; this.samples[oldestBaselineIndex] = value; this.baselineStats.remove(oldestBaseline); this.baselineStats.add(this.samples[recentPointer]); this.recentStats.remove(this.samples[recentPointer]); this.recentStats.add(value); } this.sampleCount++; const triggerStats = this.shouldTrigger(); if (triggerStats) { const baselineThresholdPoint = this.baselineStats.mean() + this.options.triggerSensitivity * this.baselineStats.stdDev(); this.log.debug(`Triggering ${this.name} event with BaselineMean:${this.baselineStats.mean().toFixed(2)} stdev:${this.baselineStats.stdDev().toFixed(2)} RecentMean:${this.recentStats.mean().toFixed(2)} TriggerAt:${baselineThresholdPoint.toFixed(2)}`); this.lastEmissionTime = Date.now(); this.trigger.emit(triggerStats); } } baselineFilled() { return (this.sampleCount >= this.options.baselineSize); } recentFilled() { return (this.sampleCount >= (this.options.baselineSize + this.options.recentSize)); } noRecentEmission() { return ((Date.now() - this.lastEmissionTime) > this.options.triggerTimeout); } shouldTrigger() { let triggerStats; if (!this.conditionMet()) { return triggerStats; } const enoughSamples = (this.sampleCount > this.options.baselineSize + this.options.recentSize); const positionOnGaussian = this.baselineStats.mean() + this.options.triggerSensitivity * this.baselineStats.stdDev(); if (enoughSamples && this.recentStats.mean() > (0.6 * positionOnGaussian)) { this.log.debug(`Audio spike detected but conditions aren't met. BaselineMean:${this.baselineStats.mean().toFixed(2)} RecentMean:${this.recentStats.mean().toFixed(2)} TriggerAt:${positionOnGaussian.toFixed(2)}`); } triggerStats = { baselineMean: this.baselineStats.mean(), baselineStdDev: this.baselineStats.stdDev(), recentMean: this.recentStats.mean(), recentDeviationFromBaseline: ((this.recentStats.mean() - this.baselineStats.mean()) / this.baselineStats.stdDev()), }; return triggerStats; } conditionMet() { let conditionsMet = false; const enoughSamples = (this.sampleCount > this.options.baselineSize + this.options.recentSize); const noRecentEmissions = this.noRecentEmission(); if (enoughSamples && noRecentEmissions) { if (this.options.alwaysEmitAbove && (this.recentStats.mean() >= this.options.alwaysEmitAbove)) { this.log.info(`Always Emit with ${this.recentStats.mean()}.`); conditionsMet = true; } else { const baselineStdDev = this.baselineStats.stdDev(); const positionOnGaussian = this.baselineStats.mean() + this.options.triggerSensitivity * baselineStdDev; let highEnoughRecent = true; if (this.options.minimumRecentMean && (this.recentStats.mean() < this.options.minimumRecentMean)) { this.log.debug(`Not triggering due to low recent: ${this.recentStats.mean()}`); highEnoughRecent = false; } let sufficientDeviation = true; if (this.options.minimumBaselineStdDev) { sufficientDeviation = (baselineStdDev >= this.options.minimumBaselineStdDev); } conditionsMet = highEnoughRecent && sufficientDeviation && (this.recentStats.mean() > positionOnGaussian); } } return conditionsMet; } mod(n, m) { return ((n % m) + m) % m; } } exports.AmbientTrigger = AmbientTrigger; },{"./OnlineMeanAndVariance":18,"jibo-typed-events":undefined}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class OnlineMeanAndVariance { constructor() { this._n = 0; this._mean = 0; this._m2 = 0; } add(value) { const delta = value - this._mean; this._n++; this._mean += delta / this._n; this._m2 += delta * (value - this._mean); } remove(value) { const delta = value - this._mean; this._n--; this._mean -= delta / this._n; this._m2 -= (value - this._mean) * delta; } numSamples() { return this._n; } mean() { return this._mean; } meanSquared() { return this._m2; } variance() { return this._m2 / (this._n); } stdDev() { return Math.sqrt(this.variance()); } } exports.OnlineMeanAndVariance = OnlineMeanAndVariance; },{}],19:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); let tunable = null; try { tunable = require('jibo-tunable'); } catch (e) { } const WIN_CIRC = 'Detectors'; class TunableDebug { static setup(audioTrigger) { if (tunable) { const T = tunable.Tunable; let baselineSize = 2400; T.getNumberField('Baseline audio length', baselineSize, 200, 4000, -1, WIN_CIRC).events.change.on(value => { baselineSize = Math.floor(value); }); let recentSize = 20; T.getNumberField('Recent audio length', recentSize, 5, 200, -1, WIN_CIRC).events.change.on(value => { recentSize = Math.floor(value); }); T.getButtonField(`Change buffer lengths`, WIN_CIRC).events.change.on(() => { audioTrigger.resetSize(baselineSize, recentSize); }); T.getNumberField('Set ambient noise threshold', 2.2, 0, 5, -1, WIN_CIRC).events.change.on(value => { audioTrigger.setTriggerSensitivity(value); }); } } } exports.TunableDebug = TunableDebug; },{"jibo-tunable":undefined}],20:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const animation_utilities_1 = require("animation-utilities"); const jibo_common_types_1 = require("jibo-common-types"); exports.EXTRA_LPS_PROPERTIES = [ 'was_in_fov' ]; let log; let convTechLog; class DataConverter { constructor(events) { this.MS_IDENTITY_DECAY = 30000; this.lastHJId = -1; this.events = events; this._presences = new Map(); this._lastSpokeTime = animation_utilities_1.Clock.currentTime(); this.entities = new Map(); this._mostRecentSpeaker = null; this.msOfLastSpeakerUpdate = Number.MIN_SAFE_INTEGER; this.currentIdentifiedEntities = new Map(); this.identifiedEntityDecayMap = new Map(); this.lastVisionTimestamp = null; } init(parentLog) { log = parentLog.createChild("DataConverter"); convTechLog = log.createChild("ConvTechSpeakerID"); } mostRecentSpeaker(msAge) { const nowMs = Date.now(); const msSinceUpdate = nowMs - this.msOfLastSpeakerUpdate; if (msSinceUpdate > msAge) { log.info("Returning null speaker due to staleness."); return null; } if (this._mostRecentSpeaker && this._mostRecentSpeaker.idInfo) { log.info(`Returning Speaker ${this._mostRecentSpeaker.idInfo.id}.`); } else { log.info("Returning null speaker."); } return this._mostRecentSpeaker; } get lastSpokeTime() { return this._lastSpokeTime; } set lastSpokeTime(time) { throw new Error('Cannot set last spoke time external to ID module.'); } get presences() { return this._presences; } set presences(pres) { throw new Error('Cannot set presences.'); } get visibleFaces() { let visibleFaces = new Map(); this.entities.forEach((entity) => { if (jibo_common_types_1.VisualEntityDescriptionType.fromString(entity.description) === jibo_common_types_1.VisualEntityDescriptionType.PERSON && entity.in_fov) { visibleFaces.set(entity.id, entity); } }); return visibleFaces; } set visibleFaces(pres) { throw new Error('Cannot set presences.'); } get people() { let peopleEntities = new Map(); this.entities.forEach((entity) => { if (jibo_common_types_1.VisualEntityDescriptionType.fromString(entity.description) === jibo_common_types_1.VisualEntityDescriptionType.PERSON) { peopleEntities.set(entity.id, entity); } }); return peopleEntities; } set people(people) { throw new Error('Cannot set visible people.'); } acceptAwareness(data) { let dataTimestamp = [data.ts[0], data.ts[1]]; if (this.lastVisionTimestamp === null || !(this.lastVisionTimestamp[0] === dataTimestamp[0] && this.lastVisionTimestamp[1] === dataTimestamp[1])) { this.lastVisionTimestamp = dataTimestamp; this.extractEntities(data.entities); } } acceptAudio(data) { if (!data.entities) { log.warn("No audio entities in 'acceptAudio'"); return; } let entity = null; let highestID = this.lastHJId; for (let aei = 0; aei < data.entities.length; aei++) { let running = data.entities[aei]; if (running.type === jibo_common_types_1.AudioLPSEntityType.HOT_WORD || running.type === jibo_common_types_1.AudioLPSEntityType.SPEAKER_ID) { if (highestID - running.id > 3) { highestID = -1; } if (running.id > highestID) { entity = running; highestID = running.id; } } } if (entity) { let hjData = { primary: { position: entity.position, confidence: entity.confidence } }; const alternates = entity.alternates; if (alternates && alternates.length) { hjData.alternate = { position: alternates[0].location, confidence: alternates[0].confidence }; } this.lastHJId = entity.id; this.events.hjEvent.emit(hjData); } } acceptSpeakerId(data) { log.debug("acceptSpeakerId", data); this._lastSpokeTime = animation_utilities_1.Clock.currentTime(); let speaker_score = 0; let speaker_id; let high_confidence; let accepted = false; if (data.speakers.length) { data.speakers.forEach((speakerCandidate) => { if (!speaker_id || speaker_score < speakerCandidate.score) { speaker_id = speakerCandidate.speaker; speaker_score = speakerCandidate.score; accepted = speakerCandidate.accepted; high_confidence = speakerCandidate.high_confidence; } }); } convTechLog.info(`Speaker ID: ${speaker_id} | accepted: ${accepted} | confidence: ${high_confidence} | score: ${speaker_score}`); if (accepted) { this._mostRecentSpeaker = new jibo_common_types_1.SpeakerRecord(); this._mostRecentSpeaker.idInfo = { id: speaker_id, highConfidence: high_confidence, score: speaker_score, accepted: accepted }; this.checkIdentifiedEntity(speaker_id, new jibo_common_types_1.PresenceRecord({ name: speaker_id, kind: jibo_common_types_1.SensoryType.VOICE }), jibo_common_types_1.IdentificationSource.AUDIO); this.msOfLastSpeakerUpdate = Date.now(); log.info("Most recent speaker accepted."); } else { this.invalidateMostRecentSpeaker(); log.info("Most recent speaker invalidated by rejected speaker id."); } } extractEntities(entities) { let seenKeys = new Set(); for (let vei = 0; vei < entities.length; vei++) { const platformTrackedEntity = entities[vei]; seenKeys.add(platformTrackedEntity.id); let serviceTrackedEntity = this.entities.get(platformTrackedEntity.id); let entityName = platformTrackedEntity.id_summary.name; let checkId = false; let platformEntityIsKnown = this.entityIsIdentifiedPerson(platformTrackedEntity); if (serviceTrackedEntity) { if (platformEntityIsKnown) { if (this.entityIsIdentifiedPerson(serviceTrackedEntity)) { if (platformTrackedEntity.id_summary.name !== serviceTrackedEntity.id_summary.name) { checkId = true; this.removeIdentifiedEntity(serviceTrackedEntity.id_summary.name, jibo_common_types_1.IdentificationSource.VISUAL); } } else { checkId = true; } } exports.EXTRA_LPS_PROPERTIES.forEach((property) => { platformTrackedEntity[property] = serviceTrackedEntity[property]; }); this.entities.set(platformTrackedEntity.id, platformTrackedEntity); } else { checkId = (platformEntityIsKnown) ? true : false; this.entities.set(platformTrackedEntity.id, platformTrackedEntity); } if (checkId) { this.checkIdentifiedEntity(entityName, new jibo_common_types_1.PresenceRecord({ name: platformTrackedEntity.id_summary.name, kind: jibo_common_types_1.SensoryType.PERSON }), jibo_common_types_1.IdentificationSource.VISUAL); } } this.clearEntities(seenKeys); } clearEntities(seenKeys) { this.entities.forEach((entity, id) => { const senseType = jibo_common_types_1.VisualEntityDescriptionType.fromString(entity.description); if (entity.in_fov && !entity.was_in_fov && senseType === jibo_common_types_1.VisualEntityDescriptionType.PERSON) { this.entities.get(id).was_in_fov = true; log.info("visible face started", entity.id); this.events.visibleFaceStarted.emit(entity); } else if (entity.was_in_fov && !entity.in_fov && senseType === jibo_common_types_1.VisualEntityDescriptionType.PERSON) { this.entities.get(id).was_in_fov = false; log.info("visible face stopped", entity.id); this.events.visibleFaceStopped.emit(entity); } if (!seenKeys.has(id)) { if (senseType === jibo_common_types_1.VisualEntityDescriptionType.PERSON) { if (entity.in_fov) { log.info("visible face stopped", entity.id); this.events.visibleFaceStopped.emit(entity); } log.info("deleting person entity", entity.id); this.removeIdentifiedEntity(entity.id_summary.name, jibo_common_types_1.IdentificationSource.VISUAL); } this.entities.delete(id); } }); } checkIdentifiedEntity(name, presence, source) { if (source === jibo_common_types_1.IdentificationSource.AUDIO) { presence.audioIdentified = true; } else if (source === jibo_common_types_1.IdentificationSource.VISUAL) { presence.visualIdentified = true; } else { log.error("Unrecognized identification source."); } let storedPresenceRecord = this.currentIdentifiedEntities.get(name); if (!storedPresenceRecord) { log.debug("Emitting idAcquired from source:", source); this.currentIdentifiedEntities.set(name, presence); this.events.idAcquired.emit(presence); } else { storedPresenceRecord.visualIdentified = storedPresenceRecord.visualIdentified || presence.visualIdentified; storedPresenceRecord.audioIdentified = storedPresenceRecord.audioIdentified || presence.audioIdentified; this.currentIdentifiedEntities.set(name, storedPresenceRecord); } if (this.identifiedEntityDecayMap.has(name)) { clearTimeout(this.identifiedEntityDecayMap.get(name)); this.identifiedEntityDecayMap.delete(name); } if (source === jibo_common_types_1.IdentificationSource.AUDIO) { this.removeIdentifiedEntity(name, source); } } removeIdentifiedEntity(name, source) { let storedPresenceRecord = this.currentIdentifiedEntities.get(name); if (!storedPresenceRecord) { log.debug("Asked to remove nonexistant identified entity."); return; } if (source === jibo_common_types_1.IdentificationSource.VISUAL) { storedPresenceRecord.visualIdentified = false; } else if (source === jibo_common_types_1.IdentificationSource.AUDIO) { storedPresenceRecord.audioIdentified = false; } if (!storedPresenceRecord.visualIdentified && !storedPresenceRecord.audioIdentified) { if (this.identifiedEntityDecayMap.has(name)) { log.warn("Attempting to set decay timer for an already decaying entity. This is likely indicative of a bug."); } else { this.identifiedEntityDecayMap.set(name, setTimeout(() => { log.debug("Emitting idLost from source:", source); this.currentIdentifiedEntities.delete(name); this.events.idLost.emit(); this.identifiedEntityDecayMap.delete(name); }, this.MS_IDENTITY_DECAY)); } } else { this.currentIdentifiedEntities.set(name, storedPresenceRecord); } } entityIsIdentifiedPerson(entity) { let entityType = jibo_common_types_1.VisualEntityDescriptionType.fromString(entity.description); let summaryKind = jibo_common_types_1.SensoryType.fromString(entity.id_summary.kind); let entityName = entity.id_summary.name; let isIdentifiedPerson = (entityType === jibo_common_types_1.VisualEntityDescriptionType.PERSON && summaryKind !== jibo_common_types_1.SensoryType.UNKNOWN && entityName !== jibo_common_types_1.IDLabels.NOT_TRAINED && entityName !== jibo_common_types_1.IDLabels.UNKNOWN); return isIdentifiedPerson; } invalidateMostRecentSpeaker() { if (!this._mostRecentSpeaker) { return; } this._mostRecentSpeaker = null; this.msOfLastSpeakerUpdate = Number.MIN_SAFE_INTEGER; } } exports.DataConverter = DataConverter; },{"animation-utilities":undefined,"jibo-common-types":undefined}],21:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jibo_typed_events_1 = require("jibo-typed-events"); class IdentityEvents extends jibo_typed_events_1.EventContainer { constructor() { super(); this.presenceStarted = new jibo_typed_events_1.Event("Presence Started"); this.presenceEnded = new jibo_typed_events_1.Event("Presence Ended"); this.idAcquired = new jibo_typed_events_1.Event("ID Acquired"); this.idLost = new jibo_typed_events_1.Event("ID Lost"); this.visibleFaceStarted = new jibo_typed_events_1.Event("Visible Face Started"); this.visibleFaceStopped = new jibo_typed_events_1.Event("Visible Face Stopped"); this.hjEvent = new jibo_typed_events_1.Event("New HJ Event"); } } exports.IdentityEvents = IdentityEvents; },{"jibo-typed-events":undefined}],22:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const IDEvents_1 = require("./IDEvents"); const DataConverter_1 = require("./DataConverter"); const ServiceOwner_1 = require("../../utils/ServiceOwner"); const jibo_common_types_1 = require("jibo-common-types"); let log; class Identity { constructor(lpsService) { this.events = new IDEvents_1.IdentityEvents(); this.intervalHandle = null; this.wakeHandlerFunction = null; this.lps = lpsService; this.dataConverter = new DataConverter_1.DataConverter(this.events); } init(parentLog) { if (this.intervalHandle !== null || this.wakeHandlerFunction !== null) { log.warn("IDEvents being initted, but it is already initted!"); return; } log = parentLog.createChild("ID"); this.dataConverter.init(parentLog.createChild('Identity')); this.lps.events.motion.on(data => this.dataConverter.acceptAwareness(data)); this.lps.events.audio.on(data => this.dataConverter.acceptAudio(data)); if (!ServiceOwner_1.ServiceOwner.jetstream) { log.info('IDEvents initted without jetstream'); } else { ServiceOwner_1.ServiceOwner.jetstream.events.speakerID.on(data => this.dataConverter.acceptSpeakerId(data)); } } isAnyonePresent() { log.debug("isAnyonePresent? ", this.dataConverter.people.size > 0); return this.dataConverter.people.size > 0; } isAnyoneVisible() { const visible = this.dataConverter.visibleFaces.size > 0; log.debug("isAnyoneVisible? ", visible); return visible; } getPresentPersons() { let people = []; this.dataConverter.people.forEach((person) => { people.push({ id: person.id_summary.name, type: person.id_summary.kind, confidence: person.confidence }); }); return people; } getVisiblePersons() { let people = []; for (let entity of this.dataConverter.visibleFaces.values()) { people.push({ id: entity.id_summary.name, type: entity.id_summary.kind, confidence: entity.confidence }); } return people; } setPresentPerson(id, callback) { const presenceData = new jibo_common_types_1.PresenceRecord({ 'name': id, 'kind': jibo_common_types_1.SensoryType.PERSON, 'present': true, 'confidence': 1 }); this.lps.setPresence(presenceData, callback); } getActiveSpeaker(age = 30000) { const mostRecent = this.dataConverter.mostRecentSpeaker(age); log.debug("most recent speaker", mostRecent); if (mostRecent) { if (mostRecent.idInfo) { log.debug("getActiveSpeaker. entity: ", mostRecent.entity, "id: ", mostRecent.idInfo.id, "is high confidence: ", mostRecent.idInfo.highConfidence); } else { log.debug("getActiveSpeaker. entity: ", mostRecent.entity); } } else { log.debug("getActiveSpeaker. None."); } return mostRecent; } getVisibleFaces() { return this.dataConverter.visibleFaces; } } exports.default = Identity; },{"../../utils/ServiceOwner":24,"./DataConverter":20,"./IDEvents":21,"jibo-common-types":undefined}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const IdentityService_1 = require("./IdentityService"); exports.default = IdentityService_1.default; },{"./IdentityService":22}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class ServiceOwner { static init(owner) { this._owner = owner; } static get analytics() { return this._owner.analytics; } static get jetstream() { return this._owner.jetstream; } static get versions() { return this._owner.versions; } static get globalEvents() { return this._owner.globalEvents; } } exports.ServiceOwner = ServiceOwner; },{}],25:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var RequestType; (function (RequestType) { RequestType[RequestType["POST"] = 0] = "POST"; RequestType[RequestType["GET"] = 1] = "GET"; })(RequestType = exports.RequestType || (exports.RequestType = {})); exports.ErrorStatus = { ABORTED: "ABORTED", NETWORK_ERROR: "NETWORK_ERROR", DATA_ERROR: "DATA_ERROR" }; class WebCommunication { static get ErrorStatus() { return exports.ErrorStatus; } static sendMessage(requestType, path, data, dataVerification, cb) { let requestTypeString = this.RequestType[requestType]; let requestPath = path; let request = new XMLHttpRequest(); request.open(requestTypeString, requestPath, true); request.onload = () => { let response = null; try { response = request.response ? JSON.parse(request.response) : request.response; if (!dataVerification(response, request.status)) { let error = new Error(`Client expected different response from server: ${request.response}`); error.name = exports.ErrorStatus.DATA_ERROR; cb(error, null, request.status); return; } } catch (ex) { let error = new Error(`Server sent back invalid json: ${request.response}, exception: ${ex}`); error.name = exports.ErrorStatus.DATA_ERROR; cb(error, null, request.status); return; } cb(null, response, request.status); }; request.onabort = () => { let error = new Error(`request aborted for path: ${requestPath} with data: ${JSON.stringify(data)}`); error.name = exports.ErrorStatus.ABORTED; cb(error, null, request.status); }; request.onerror = () => { let error = new Error(`request failed for path: ${requestPath} with data: ${JSON.stringify(data)}`); error.name = exports.ErrorStatus.NETWORK_ERROR; cb(error, null, request.status); }; request.send(JSON.stringify(data)); return request; } } WebCommunication.RequestType = RequestType; exports.WebCommunication = WebCommunication; exports.default = WebCommunication; },{}],26:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); if (!global.XMLHttpRequest) { global.XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; Object.defineProperty(global.XMLHttpRequest.prototype, 'response', { get: function () { if (this.responseType === 'json') { try { this.__response = JSON.parse(this.responseText); } catch (e) { this.responseType = null; } } if (this.__response) { return this.__response; } return this.responseXML || this.responseText; } }); } const jibo_log_1 = require("jibo-log"); const async = require("async"); const ServiceOwner_1 = require("./utils/ServiceOwner"); const log = new jibo_log_1.Log('SF.ServiceClients'); const services = {}; const errors = require("./services/ErrorService"); exports.errors = errors; services['error-service'] = errors.init; const ics = require("./services/IdentityCreationService"); exports.ics = ics; services.identity = ics.init; const LPSService_1 = require("./services/LPSService"); exports.lps = LPSService_1.lps; services.lps = LPSService_1.lps.init; const MediaService_1 = require("./services/MediaService"); exports.media = MediaService_1.media; services.media = MediaService_1.media.init; const MediaManagerService_1 = require("./services/MediaManagerService"); exports.mediaManager = MediaManagerService_1.mediaManager; services['media-manager'] = MediaManagerService_1.mediaManager.init; const performance = require("./services/PerformanceService"); exports.performance = performance; services.performance = performance.init; const scheduler = require("./services/SchedulerService"); exports.scheduler = scheduler; services.scheduler = scheduler.init; const secureTransferService = require("./services/SecureTransferService"); exports.secureTransferService = secureTransferService; services['secure-transfer'] = secureTransferService.init; const systemManager = require("./services/SystemManager"); exports.systemManager = systemManager; services['system-manager'] = systemManager.init; const SystemService_1 = require("./services/SystemService"); exports.system = SystemService_1.system; services.body = SystemService_1.system.initBody; services.audio = SystemService_1.system.initAudio; const tts = require("./services/TTSService"); exports.tts = tts; services.tts = tts.init; const wifi = require("./services/WifiService"); exports.wifi = wifi; services.wifi = wifi.init; var WebCommunication_1 = require("./utils/WebCommunication"); exports.web = WebCommunication_1.WebCommunication; function init(owner, records, callback, initWrapper) { ServiceOwner_1.ServiceOwner.init(owner); const tasks = []; records.forEach((service) => { const initFunction = services[service.name]; if (initFunction) { let actualInit = (callback) => { initFunction(service, log, callback); }; if (initWrapper) { actualInit = initWrapper(actualInit, service.name); } tasks.push(actualInit); } }); async.parallel(tasks, callback); } exports.init = init; },{"./services/ErrorService":1,"./services/IdentityCreationService":2,"./services/LPSService":3,"./services/MediaManagerService":4,"./services/MediaService":5,"./services/PerformanceService":6,"./services/SchedulerService":7,"./services/SecureTransferService":8,"./services/SystemManager":9,"./services/SystemService":10,"./services/TTSService":11,"./services/WifiService":13,"./utils/ServiceOwner":24,"./utils/WebCommunication":25,"async":undefined,"jibo-log":undefined,"xmlhttprequest":undefined}]},{},[26])(26) }); //# sourceMappingURL=jibo-service-clients.js.map