diff --git a/controllers/link.js b/controllers/link.js index ba3b3c2aa..6a0ba2240 100644 --- a/controllers/link.js +++ b/controllers/link.js @@ -19,7 +19,7 @@ function getLinkData(fullEntry, wasAdded) { var linkAddedData = null; if (fullEntry) { - console.log('getLinkData', fullEntry); + // console.log('getLinkData', fullEntry); var linkObjectA = fullEntry['objectA']; var linkObjectB = fullEntry['objectB']; @@ -65,6 +65,7 @@ function getLinkData(fullEntry, wasAdded) { * @param {Link} body */ const newLink = function (objectID, frameID, linkID, body) { + var updateStatus = 'nothing happened'; var foundFrame = utilities.getFrame(objects, objectID, frameID); @@ -77,9 +78,22 @@ const newLink = function (objectID, frameID, linkID, body) { body.frameA === body.frameB && body.nodeA === body.nodeB); - foundFrame.links[linkID] = body; + utilities.forEachLinkInFrame(utilities.getFrame(objects, body.objectA, body.frameA), function (thisLink) { + if (!body.loop) { + console.log('link already exists'); + body.loop = (body.objectA === thisLink.objectA && + body.objectB === thisLink.objectB && + body.frameA === thisLink.frameA && + body.frameB === thisLink.frameB && + body.nodeA === thisLink.nodeA && + body.nodeB === thisLink.nodeB + ); + } + }); + if (!body.loop) { + foundFrame.links[linkID] = body; console.log('added link: ' + linkID); // write the object state to the permanent storage. utilities.writeObjectToFile(objects, objectID, objectsPath, globalVariables.saveToDisk); @@ -230,7 +244,7 @@ const deleteLinkLock = function (objectKey, frameKey, linkKey, password) { return updateStatus; }; -const setup = function(objects_, knownObjects_, socketArray_, globalVariables_, hardwareAPI_, objectsPath_, socketUpdater_) { +const setup = function (objects_, knownObjects_, socketArray_, globalVariables_, hardwareAPI_, objectsPath_, socketUpdater_) { objects = objects_; knownObjects = knownObjects_; socketArray = socketArray_; @@ -246,4 +260,4 @@ module.exports = { addLinkLock: addLinkLock, deleteLinkLock: deleteLinkLock, setup: setup -}; \ No newline at end of file +}; diff --git a/libraries/hardwareInterfaces.js b/libraries/hardwareInterfaces.js index 05a6e91c5..a5dff9eb8 100644 --- a/libraries/hardwareInterfaces.js +++ b/libraries/hardwareInterfaces.js @@ -241,7 +241,7 @@ exports.getKnownObjects = function () { return knownObjects; }; -exports.getSceneGraph = function() { +exports.getSceneGraph = function () { // send acyclic version of sceneGraph by removing linkedVehicles if needed sceneGraphReference.recomputeGraph(); let sceneGraphCopy = {}; @@ -252,18 +252,18 @@ exports.getSceneGraph = function() { return sceneGraphCopy; }; -exports.getWorldGraph = function() { +exports.getWorldGraph = function () { if (!worldGraphReference) { return {}; } return worldGraphReference.compile().getSerializableCopy(); }; -exports.getDistanceOneToMany = function(id1, ids) { +exports.getDistanceOneToMany = function (id1, ids) { sceneGraphReference.recomputeGraph(); let distances = {}; distances[id1] = {}; - ids.forEach(function(id2) { + ids.forEach(function (id2) { let computedDistance = sceneGraphReference.getDistanceBetween(id1, id2); console.log(computedDistance); distances[id1][id2] = computedDistance; @@ -271,7 +271,7 @@ exports.getDistanceOneToMany = function(id1, ids) { return distances; }; -exports.onSceneGraphUpdated = function(callback) { +exports.onSceneGraphUpdated = function (callback) { sceneGraphReference.onUpdate(callback); }; @@ -733,7 +733,7 @@ let setHardwareInterfaceSettingsImpl = null; * @param {Array.} limitToKeys - if provided, only affects the properties of settings whose keys are included in this array * @param {successCallback} callback */ -exports.setHardwareInterfaceSettings = function(interfaceName, settings, limitToKeys, callback) { +exports.setHardwareInterfaceSettings = function (interfaceName, settings, limitToKeys, callback) { return setHardwareInterfaceSettingsImpl(interfaceName, settings, limitToKeys, callback); }; @@ -745,7 +745,7 @@ exports.setHardwareInterfaceSettings = function(interfaceName, settings, limitTo * Complement to setup() which is necessary due to the unique positioning of * the setHardwareInterfaceSettings function */ -exports.setHardwareInterfaceSettingsImpl = function(setHardwareInterfaceSettings) { +exports.setHardwareInterfaceSettingsImpl = function (setHardwareInterfaceSettings) { setHardwareInterfaceSettingsImpl = setHardwareInterfaceSettings; }; diff --git a/libraries/nodeUtilities.js b/libraries/nodeUtilities.js index 94cc5de34..79b241a68 100644 --- a/libraries/nodeUtilities.js +++ b/libraries/nodeUtilities.js @@ -3,14 +3,16 @@ const Link = require('../models/Link'); var linkController; // Pointers populated from server.js with setup() var objects = {}; +var sceneGraph = {}; var knownObjects = {}; var socketArray = {}; var globalVariables = {}; var hardwareAPI = {}; var objectsPath = {}; -exports.setup = function (_objects, _knownObjects, _socketArray, _globalVariables, _hardwareAPI, _objectsPath, _linkController) { +exports.setup = function (_objects, _sceneGraph, _knownObjects, _socketArray, _globalVariables, _hardwareAPI, _objectsPath, _linkController) { objects = _objects; + sceneGraph = _sceneGraph; knownObjects = _knownObjects; socketArray = _socketArray; globalVariables = _globalVariables; @@ -21,33 +23,45 @@ exports.setup = function (_objects, _knownObjects, _socketArray, _globalVariable exports.deepCopy = utilities.deepCopy; -exports.searchNodeByType = function (nodeType, object, tool, node, callback) { - - let thisObject = utilities.getObject(objects, object); - +exports.searchNodeByType = function (nodeType, _object, tool, node, callback) { + let thisObjectKey = _object; + if (!(_object in objects)) { + thisObjectKey = utilities.getObjectIdFromTargetOrObjectFile(_object, objectsPath); + } + let thisObject = utilities.getObject(objects, thisObjectKey); if (!tool && !node) { utilities.forEachFrameInObject(thisObject, function (thisTool, toolKey) { utilities.forEachNodeInFrame(thisTool, function (thisNode, nodeKey) { - if (thisNode.type === nodeType) callback(object, toolKey, nodeKey); + if (thisNode.type === nodeType) callback(thisObjectKey, toolKey, nodeKey); }); }); } else if (!node) { - let thisTool = utilities.getFrame(objects, object, tool); + let thisTool = utilities.getFrame(objects, thisObjectKey, tool); + if (!thisTool) { + thisTool = utilities.getFrame(objects, thisObjectKey, thisObjectKey + tool); + } utilities.forEachNodeInFrame(thisTool, function (thisNode, nodeKey) { - if (thisNode.type === nodeType) callback(object, tool, nodeKey); + if (thisNode.type === nodeType) { + callback(thisObjectKey, tool, nodeKey); + } }); } else if (!tool) { utilities.forEachFrameInObject(thisObject, function (tool, toolKey) { - let thisNode = utilities.getFrame(objects, toolKey, node); + let thisNode = utilities.getFrame(objects, thisObjectKey, toolKey, node); if (!thisNode) { - if (thisNode.type === nodeType) callback(object, toolKey, node); + if (thisNode.type === nodeType) callback(thisObjectKey, toolKey, node); } }); } }; -exports.createLink = function (originObject, originTool, originNode, destinationObject, destinationTool, destinationNode) { +exports.createLink = function (originObject, _originTool, originNode, destinationObject, destinationTool, destinationNode) { + + let originTool = _originTool; + if (!utilities.getFrame(objects, originObject, _originTool)) { + originTool = originObject + _originTool; + } var linkBody = new Link(); linkBody.objectA = originObject; linkBody.frameA = originTool; @@ -63,12 +77,16 @@ exports.deleteLink = function (object, tool, link) { }; exports.getWorldObject = function (object) { - //todo @Ben how do I find out what world object is assosiated with the object? + let thisObject = utilities.getObject(objects, object); + if (thisObject) { + if (thisObject.hasOwnProperty('worldId')) { + return thisObject.worldId; + } + } return null; }; -exports.getWorldLocation = function (object) { - //todo @Ben how do I find out the world location - return null; +exports.getWorldLocation = function (objectID) { + return sceneGraph.getWorldPosition(objectID); }; diff --git a/libraries/recorder.js b/libraries/recorder.js index 7d7c3a72d..e1ffdd1e8 100644 --- a/libraries/recorder.js +++ b/libraries/recorder.js @@ -84,6 +84,7 @@ recorder.recurse = function (obj, objectInTime, keyString) { recorder.getItemFromArray = function (object, array) { let item = object; + if (!item) return null; let returnItem = {}; array.forEach(function (data) { if (data !== '') { @@ -97,6 +98,7 @@ recorder.getItemFromArray = function (object, array) { } // let newItem = item[data]; returnItem = item; + if(item[data]) item = item[data]; } }); diff --git a/libraries/utilities.js b/libraries/utilities.js index c83fc6c01..367af92e6 100644 --- a/libraries/utilities.js +++ b/libraries/utilities.js @@ -116,8 +116,8 @@ exports.createFolder = function (folderVar, objectsPath, debug) { } }); } -/** - if (!fs.existsSync(firstFrame)) { + /** + if (!fs.existsSync(firstFrame)) { fs.mkdirSync(firstFrame, '0766', function (err) { if (err) { console.error(err); @@ -134,7 +134,7 @@ exports.createFolder = function (folderVar, objectsPath, debug) { } // writeObjectToFile(tempFolderName); } -**/ + **/ }; @@ -703,6 +703,7 @@ exports.actionSender = function (action, timeToLive, beatport) { function doesObjectExist(objects, objectKey) { return objects.hasOwnProperty(objectKey); } + exports.doesObjectExist = doesObjectExist; function getObject(objects, objectKey) { @@ -711,6 +712,7 @@ function getObject(objects, objectKey) { } return null; } + exports.getObject = getObject; function doesFrameExist(objects, objectKey, frameKey) { @@ -722,6 +724,7 @@ function doesFrameExist(objects, objectKey, frameKey) { } return false; } + exports.doesFrameExist = doesFrameExist; function getFrame(objects, objectKey, frameKey) { @@ -733,6 +736,7 @@ function getFrame(objects, objectKey, frameKey) { } return null; } + exports.getFrame = getFrame; function doesNodeExist(objects, objectKey, frameKey, nodeKey) { @@ -744,6 +748,7 @@ function doesNodeExist(objects, objectKey, frameKey, nodeKey) { } return false; } + exports.doesNodeExist = doesNodeExist; function getNode(objects, objectKey, frameKey, nodeKey) { @@ -755,6 +760,7 @@ function getNode(objects, objectKey, frameKey, nodeKey) { } return null; } + exports.getNode = getNode; /** @@ -769,6 +775,7 @@ function getObjectAsync(objects, objectKey, callback) { var object = objects[objectKey]; callback(null, object); } + exports.getObjectAsync = getObjectAsync; /** @@ -790,6 +797,7 @@ function getFrameAsync(objects, objectKey, frameKey, callback) { callback(null, object, frame); }); } + exports.getFrameAsync = getFrameAsync; /** @@ -812,6 +820,7 @@ function getNodeAsync(objects, objectKey, frameKey, nodeKey, callback) { callback(null, object, frame, node); }); } + exports.getNodeAsync = getNodeAsync; /** @@ -841,6 +850,7 @@ function getFrameOrNode(objects, objectKey, frameKey, nodeKey, callback) { callback(null, object, frame, node); }); } + exports.getFrameOrNode = getFrameOrNode; function forEachObject(objects, callback) { @@ -849,24 +859,41 @@ function forEachObject(objects, callback) { callback(objects[objectKey], objectKey); } } + exports.forEachObject = forEachObject; function forEachFrameInObject(object, callback) { + if (!object) return; for (var frameKey in object.frames) { if (!object.frames.hasOwnProperty(frameKey)) continue; callback(object.frames[frameKey], frameKey); } } + exports.forEachFrameInObject = forEachFrameInObject; function forEachNodeInFrame(frame, callback) { + if (!frame) return; for (var nodeKey in frame.nodes) { if (!frame.nodes.hasOwnProperty(nodeKey)) continue; callback(frame.nodes[nodeKey], nodeKey); } } + exports.forEachNodeInFrame = forEachNodeInFrame; + +function forEachLinkInFrame(frame, callback) { + if (!frame) return; + for (var nodeKey in frame.links) { + if (!frame.links.hasOwnProperty(nodeKey)) continue; + callback(frame.links[nodeKey], nodeKey); + } +} + +exports.forEachLinkInFrame = forEachLinkInFrame; + + /** * Helper function to return the absolute path to the directory that should contain all * video files for the provided object name. (makes dir if necessary) @@ -888,17 +915,20 @@ function getVideoDir(objectsPath, identityFolderName, isMobile, objectName) { return videoDir; } + exports.getVideoDir = getVideoDir; // Ensures id is alphanumeric or -_ function isValidId(id) { return id.match(/^[A-Za-z0-9_-]+$/); } + exports.isValidId = isValidId; function goesUpDirectory(path) { return path.match(/\.\./); } + exports.goesUpDirectory = goesUpDirectory; function deepCopy(item) { @@ -922,7 +952,7 @@ function deepCopy(item) { exports.deepCopy = deepCopy; -exports.httpGet = function(url) { +exports.httpGet = function (url) { return new Promise((resolve, reject) => { request(url, (error, response, body) => { if (error) reject(error); diff --git a/models/PathPoint.js b/models/PathPoint.js index 192fcca8b..d399fb2bd 100644 --- a/models/PathPoint.js +++ b/models/PathPoint.js @@ -1,3 +1,5 @@ +const Point = require('./Point.js'); + /** * @constructor */ diff --git a/server.js b/server.js index 7335b69a4..1f9f954ae 100644 --- a/server.js +++ b/server.js @@ -618,7 +618,7 @@ var hardwareAPICallbacks = { // set all the initial states for the Hardware Interfaces in order to run with the Server. hardwareAPI.setup(objects, objectLookup, knownObjects, socketArray, globalVariables, __dirname, objectsPath, nodeTypeModules, blockModules, services, version, protocol, serverPort, hardwareAPICallbacks, sceneGraph, worldGraph); -nodeUtilities.setup(objects, knownObjects, socketArray, globalVariables, hardwareAPI, objectsPath, linkController); +nodeUtilities.setup(objects, sceneGraph, knownObjects, socketArray, globalVariables, hardwareAPI, objectsPath, linkController); console.log('Done'); @@ -1088,7 +1088,7 @@ function objectBeatSender(PORT, thisId, thisIp, oneTimeOnly) { var HOST = '255.255.255.255'; - console.log('creating beat for object: ' + thisId); + //console.log('creating beat for object: ' + thisId); objects[thisId].version = version; objects[thisId].protocol = protocol; objects[thisId].port = serverPort; @@ -1100,7 +1100,7 @@ function objectBeatSender(PORT, thisId, thisIp, oneTimeOnly) { } // Objects - console.log('with version number: ' + thisVersionNumber); + // console.log('with version number: ' + thisVersionNumber); var zone = ''; if (objects[thisId].zone) zone = objects[thisId].zone; @@ -1247,7 +1247,7 @@ function objectBeatServer() { } // check if action 'ping' if (msgContent.action === 'ping') { - console.log(msgContent.action); + //console.log(msgContent.action); for (let key in objects) { objectBeatSender(beatPort, key, objects[key].ip, true); } @@ -1278,7 +1278,9 @@ function objectBeatServer() { async function getKnownSceneGraph(ip, port) { // 1. check if we already have an up-to-date sceneGraph from this server let needsThisGraph = true; - if (!needsThisGraph) { return; } // TODO: implement placeholder + if (!needsThisGraph) { + return; + } // TODO: implement placeholder // 2. if not, make an HTTP GET request to the other server's /spatial/sceneGraph endpoint to get it const url = 'http://' + ip + ':' + (port || 8080) + '/spatial/sceneGraph'; @@ -1874,11 +1876,11 @@ function objectWebServer() { // webFrontend realtime messaging webServer.post('/webUI/spatial/locator', function (req, res) { console.log({ - spatial: {locator: JSON.parse(req.body.locator), ip: services.ip }, + spatial: {locator: JSON.parse(req.body.locator), ip: services.ip}, lastEditor: null }); utilities.actionSender({ - spatial: {locator: JSON.parse(req.body.locator), ip: services.ip }, + spatial: {locator: JSON.parse(req.body.locator), ip: services.ip}, lastEditor: null }); res.status(200).send('ok'); @@ -3743,9 +3745,9 @@ var engine = { if (this.internalObjectDestination.blocks) { this.internalObjectDestination = this.internalObjectDestination.blocks[this.blockKey]; - /* for (let key in thisNode.processedData) { - this.internalObjectDestination.data[0][key] = thisNode.processedData[key]; - }*/ + /* for (let key in thisNode.processedData) { + this.internalObjectDestination.data[0][key] = thisNode.processedData[key]; + }*/ this.internalObjectDestination.data[0] = utilities.deepCopy(thisNode.processedData); this.nextLogic = getNode(this.link.objectB, this.link.frameB, this.link.nodeB); @@ -3865,9 +3867,9 @@ var engine = { computeProcessedBlockData: function (thisNode, thisLink, index, internalObjectDestination) { // save data in local destination object; - /* for (let key1 in thisNode.processedData[index]) { - internalObjectDestination.data[key1] = thisNode.processedData[index][key1]; - }*/ + /* for (let key1 in thisNode.processedData[index]) { + internalObjectDestination.data[key1] = thisNode.processedData[index][key1]; + }*/ internalObjectDestination.data = utilities.deepCopy(thisNode.processedData[index]); // trigger hardware API to push data to the objects