UNPKG

hlc-server

Version:

Serves real-time real-world context at a human scale by combining RFID, RTLS and M2M with structured, linked data on the web. We believe in an open Internet of Things.

241 lines (220 loc) 7.09 kB
/** * Copyright reelyActive 2019 * We believe in an open Internet of Things */ // Constants const ELASTICSEARCH_INTERFACE_ROUTE = '/interfaces/elasticsearch'; const QUERY_TEMPLATE_NAMES = [ 'Most recent raddecs', 'Specific transmitterId', 'Prefix transmitterId', 'Aggregate receiverId', 'Aggregate rec/dec/pac', 'Auto-date histogram' ]; // DOM elements let queryTemplates = document.querySelector('#queryTemplates'); let displayCount = document.querySelector('#displayCount'); let queryBox = document.querySelector('#queryBox'); let queryButton = document.querySelector('#queryButton'); let queryResults = document.querySelector('#queryResults'); let responseHits = document.querySelector('#responseHits'); let responseTime = document.querySelector('#responseTime'); let hitsBox = document.querySelector('#hitsBox'); let aggregationsBox = document.querySelector('#aggregationsBox'); // Create query template options QUERY_TEMPLATE_NAMES.forEach(function(element, index) { let option = document.createElement("option"); option.value = index; option.text = element; queryTemplates.add(option, null); }); // Other variables // Other initialisation hide(queryButton); hide(queryResults); // Update the query JSON based on the selected template function updateQuery() { let query = {}; switch(queryTemplates.value) { case '0': // Most recent raddecs query = { "size": 10, "query": { "match_all": {} }, "_source": [ "transmitterId", "transmitterIdType", "receiverId", "receiverIdType", "rssi", "timestamp", "numberOfDecodings", "numberOfReceivers", "numberOfDistinctPackets" ], "sort": [ { "timestamp": { "order": "desc" } } ] }; queryBox.value = JSON.stringify(query, null, 2); break; case '1': // Specific transmitterId query = { "size": 10, "query": { "term": { "transmitterId": "" } }, "_source": [ "receiverId", "receiverIdType", "rssi", "timestamp", "numberOfDecodings", "numberOfReceivers", "numberOfDistinctPackets", "packets" ] }; queryBox.value = JSON.stringify(query, null, 2); break; case '2': // Prefix transmitterId query = { "size": 10, "query": { "prefix": { "transmitterId": "" } }, "_source": [ "transmitterId", "transmitterIdType", "receiverId", "receiverIdType", "rssi", "timestamp", "numberOfDecodings", "numberOfReceivers", "numberOfDistinctPackets" ] }; queryBox.value = JSON.stringify(query, null, 2); break; case '3': // Aggregate receiverId query = { "size": 0, "aggs" : { "receivers" : { "terms" : { "field" : "receiverId.keyword", "order" : { "_count" : "desc" }, "size": 12 } } } }; queryBox.value = JSON.stringify(query, null, 2); break; case '4': // Aggregate rec/dec/pac query = { "size": 0, "aggs" : { "numberOfReceivers" : { "histogram" : { "field" : "numberOfReceivers", "interval" : 1 } }, "numberOfDecodings" : { "histogram" : { "field" : "numberOfDecodings", "interval" : 1, "min_doc_count" : 1 } }, "numberOfDistinctPackets" : { "histogram" : { "field" : "numberOfDistinctPackets", "interval" : 1 } } } }; queryBox.value = JSON.stringify(query, null, 2); break; case '5': // Auto-date histogram query = { "size": 0, "aggs" : { "periods" : { "auto_date_histogram" : { "field" : "timestamp", "buckets" : 12 } } } }; queryBox.value = JSON.stringify(query, null, 2); break; } queryBox.rows = countNumberOfLines(queryBox.value); parseQuery(); } // Parse the query as typed in the box and confirm it is valid JSON function parseQuery() { let query = {}; try { query = JSON.parse(queryBox.value); } catch(error) { queryError.textContent = 'Query must be valid JSON'; hide(queryButton); hide(queryResults); show(queryError); return null; } hide(queryError); show(queryButton); return query; } // Handle the current Elasticsearch query function handleQuery() { let query = parseQuery(); let url = window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + ELASTICSEARCH_INTERFACE_ROUTE; let httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = function() { if(httpRequest.readyState === XMLHttpRequest.DONE) { if(httpRequest.status === 200) { let response = JSON.parse(httpRequest.responseText); updateResults(response); updateHits(response); updateAggregations(response); show(queryResults); } else { queryError.textContent = 'Query returned status ' + httpRequest.status + '. Is Elasticsearch connected and running?'; hide(queryResults); hide(queryButton); show(queryError); } } }; httpRequest.open('POST', url); httpRequest.setRequestHeader('Content-Type', 'application/json'); httpRequest.setRequestHeader('Accept', 'application/json'); httpRequest.send(JSON.stringify(query)); } // Update the results function updateResults(response) { responseHits.textContent = response.hits.total; responseTime.textContent = response.took; } // Update the hits function updateHits(response) { if(!response.hits.hasOwnProperty('hits') || (response.hits.hits.length === 0)) { hide(hitsCard); } else { show(hitsCard); hitsBox.textContent = JSON.stringify(response.hits.hits, null, 2); } } // Update the aggregations function updateAggregations(response) { if(response.hasOwnProperty('aggregations')) { aggregationsBox.textContent = JSON.stringify(response.aggregations, null, 2); show(aggregationsCard); } else { hide(aggregationsCard); } } // Count the number of lines in the given JSON string function countNumberOfLines(jsonString) { return (jsonString.match(/\r?\n/g) || []).length + 1; } // Hide the given element function hide(element) { element.style.display = 'none'; } // Show the given element function show(element) { element.style.display = ''; } // Event listeners queryTemplates.addEventListener('change', updateQuery); queryBox.addEventListener('keyup', parseQuery); queryButton.addEventListener('click', handleQuery);