diff --git a/queries/js/IoT_Embla/Philips_Hue/fuse_search.js b/queries/js/IoT_Embla/Philips_Hue/fuse_search.js index cb921d4c..78ed6e7d 100644 --- a/queries/js/IoT_Embla/Philips_Hue/fuse_search.js +++ b/queries/js/IoT_Embla/Philips_Hue/fuse_search.js @@ -1,22 +1,32 @@ +/* +Fuzzy search function that returns an object in the form of {result: (Object), score: (Number)} +* @param {String} query - The search term +* @param {Object} data - The data to search +*/ function philipsFuzzySearch(query, data) { + // Restructure data to be searchable by name var newData = Object.keys(data).map(function (key) { return { ID: key, info: data[key] }; }); - console.log("new data: ", newData); + // Fuzzy search for the query term (returns an array of objects) var fuse = new Fuse(newData, { keys: ["info", "info.name"], + includeScore: true, shouldSort: true, threshold: 0.5, }); + let searchResult = fuse.search(query); - let searchTerm = query; - let result = fuse.search(searchTerm); - - console.log("result: ", result); - if (result[0] === undefined) { + let resultObject = new Object(); + console.log("result: ", searchResult); + if (searchResult[0] === undefined) { console.log("no match found"); return null; } else { - return result[0].item; + // Structure the return object to be in the form of {result: (Object), score: (Number)} + resultObject.result = searchResult[0].item; + resultObject.score = searchResult[0].score; + console.log("resultObject :", resultObject); + return resultObject; } } diff --git a/queries/js/IoT_Embla/Philips_Hue/set_lights.js b/queries/js/IoT_Embla/Philips_Hue/set_lights.js index a364eb54..49bc4e03 100644 --- a/queries/js/IoT_Embla/Philips_Hue/set_lights.js +++ b/queries/js/IoT_Embla/Philips_Hue/set_lights.js @@ -2,19 +2,20 @@ // Constants to be used when setting lights from HTML // var BRIDGE_IP = "192.168.1.68"; -// var USERNAME = "p3obluiXT13IbHMpp4X63ZvZnpNRdbqqMt723gy2"; +// var USERNAME = "MQH9DVv1lhgaOKN67uVox4fWNc9iu3j5g7MmdDUr"; // TODO: Implement a hotfix for Ikea Tradfri bulbs, since it can only take one argument at a time -/* Gets a target for the given query and sets the state of the target to the given state using a fetch request. - * query - the query to find the target e.g. "eldhús" - * state - the state to set the target to e.g. "{"on": true}" or "{"scene": "energize"}" + +/** Gets a target for the given query and sets the state of the target to the given state using a fetch request. + * @param {String} query - the query to find the target e.g. "eldhús" or "lampi" + * @param {String} state - the state to set the target to e.g. "{"on": true}" or "{"scene": "energize"}" */ function setLights(query, state) { - let parsed_state = JSON.parse(state); + let parsedState = JSON.parse(state); let promiseList = [getAllGroups(), getAllLights()]; let sceneName; - if (parsed_state.scene) { - sceneName = parsed_state.scene; + if (parsedState.scene) { + sceneName = parsedState.scene; promiseList.push(getAllScenes()); } // Get all lights and all groups from the API (and all scenes if "scene" was a paramater) @@ -27,25 +28,26 @@ function setLights(query, state) { } catch (e) { console.log("No scene in state"); } + // Get the target object for the given query let targetObject = getTargetObject(query, allLights, allGroups); - console.log("targetObject: ", targetObject); if (targetObject === undefined) { return "Ekki tókst að finna ljós"; } + + // Check if state includes a scene or a brightness change if (sceneName) { - let sceneID = getSceneID(parsed_state.scene, allScenes); + let sceneID = getSceneID(parsedState.scene, allScenes); if (sceneID === undefined) { return "Ekki tókst að finna senu"; } else { - parsed_state.scene = sceneID; // Change the scene parameter to the scene ID - state = JSON.stringify(parsed_state); + parsedState.scene = sceneID; // Change the scene parameter to the scene ID + state = JSON.stringify(parsedState); } + } else if (parsedState.bri_inc) { + state = JSON.stringify(parsedState); } - // Check if state includes a scene or a brightness change - else if (parsed_state.bri_inc) { - state = JSON.stringify(parsed_state); - } + // Send data to API let url = targetObject.url; fetch(`http://${BRIDGE_IP}/api/${USERNAME}/${url}`, { @@ -62,35 +64,54 @@ function setLights(query, state) { }); } -/** Finds a matching light or group and returns an object with the ID, name and url for the target */ +/** Finds a matching light or group and returns an object with the ID, name and url for the target + * @param {String} query - the query to find the target e.g. "eldhús" + * @param {Array} allLights - an object of all lights from the API + * @param {Array} allGroups - an object of all groups from the API + */ function getTargetObject(query, allLights, allGroups) { - let targetObject; + let targetObject, selection, url; let lightsResult = philipsFuzzySearch(query, allLights); let groupsResult = philipsFuzzySearch(query, allGroups); - if (lightsResult != null) { + if (lightsResult != null && groupsResult != null) { + // Found a match for a light group and a light + selection = + lightsResult.score < groupsResult.score // Select the light with the highest score + ? lightsResult + : groupsResult; + url = + selection === lightsResult // Set url based on selection + ? `lights/${lightsResult.result.ID}/state` + : `groups/${groupsResult.result.ID}/action`; + } else if (lightsResult != null && groupsResult == null) { // Found a match for a single light - targetObject = { - id: lightsResult.ID, - type: "light", - url: `lights/${lightsResult.ID}/state`, - }; - } else if (groupsResult != null) { + selection = lightsResult; + url = `lights/${selection.result.ID}/state`; + } else if (groupsResult != null && lightsResult == null) { // Found a match for a light group - targetObject = { - id: groupsResult.ID, - type: "group", - url: `groups/${groupsResult.ID}/action`, - }; + selection = groupsResult; + url = `groups/${selection.result.ID}/action`; + } else { + return; } + + targetObject = { + id: selection.result.ID, + url: url, + }; return targetObject; } -/** Returns the ID for a given scene name using fuzzy search */ +/** Returns the ID for a given scene name using fuzzy search + * @param {String} sceneName - the name of the scene to find + * @param {Object} allScenes - an array of all scenes from the API + */ function getSceneID(scene_name, allScenes) { let scenesResult = philipsFuzzySearch(scene_name, allScenes); + console.log("sceneResult :", scenesResult); if (scenesResult != null) { - return scenesResult.ID; + return scenesResult.result.ID; } else { return; } @@ -119,3 +140,45 @@ function queryTestFromHTML() { setLights(query, `{"scene": "${scene}"}`); } } + +// /** Finds a matching light or group and returns an object with the ID, name and url for the target +// * @param {String} query - the query to find the target e.g. "eldhús" +// * @param {Object} allLights - an array of all lights from the API +// * @param {Object} allGroups - an array of all groups from the API +// */ +// function getTargetObjectOLD(query, allLights, allGroups) { +// let targetObject; +// let lightsResult = philipsFuzzySearch(query, allLights); +// let groupsResult = philipsFuzzySearch(query, allGroups); +// console.log("lightsResult: ", lightsResult); +// console.log("groupsResult: ", groupsResult); + +// if (lightsResult != null && groupsResult == null) { +// // Found a match for a single light +// targetObject = { +// id: lightsResult.result.ID, +// type: "light", +// url: `lights/${lightsResult.result.ID}/state`, +// }; +// } else if (groupsResult != null && lightsResult == null) { +// // Found a match for a light group +// targetObject = { +// id: groupsResult.result.ID, +// type: "group", +// url: `groups/${groupsResult.result.ID}/action`, +// }; +// } else if (groupsResult != null && lightsResult != null) { +// let lightsScore = lightsResult.score; +// let groupsScore = groupsResult.score; +// let selection = lightsScore > groupsScore ? lightsResult : groupsResult; +// console.log("selection :", selection); +// // Found a match for a light group and a light +// targetObject = { +// id: lightsResult.result.ID, +// type: "light", +// url: `lights/${lightsResult.result.ID}/state`, +// }; +// } +// console.log("targetObject: ", targetObject); +// return targetObject; +// }