thingsboard_api
Version:
Thingsboard REST API implementation
535 lines (460 loc) • 17.2 kB
JavaScript
const axios = require('axios');
// base entity types
const possibleEntityTypes = {
"device": "DEVICE",
"asset": "ASSET",
"view": "ENTITY_VIEW",
};
// Get object id based on device name, and entityType
async function getObjectID(entityName, entityType, tokenFlag = false) {
if (((typeof entityType === "undefined") || (entityType === null)) || ((typeof entityName === "undefined") || (entityName === null))) {
return { error: true, message: 'getObjectID(), Error: entityType or entityName are not defined or null!' };
}
let url = '';
entityName = encodeURI(entityName);
entityName = entityName.replace("&", "%26")
switch (entityType.toUpperCase()) {
case possibleEntityTypes.device:
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/tenant/devices?deviceName=${entityName}`
break;
case possibleEntityTypes.asset:
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/tenant/assets?assetName=${entityName}`;
break;
case possibleEntityTypes.view:
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/tenant/entityViews?entityViewName=${entityName}`;
break;
default:
return { error: true, message: `getObjectID(), Unknown entity type: ${entityType} !` };
}
try {
const response = await axios(url, {
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
// if we don't want to get token,
// return only id
if (!tokenFlag) {
return response.data.id.id;
}
// If token exist and type is device
if ((tokenFlag) && (entityType.toUpperCase() === possibleEntityTypes.device)) {
const token = await getDeviceToken(response.data.id.id);
if (!token) {
// error during get token
return { error: true, message: `getObjectID(), Error: get token error! Name = ${entityName} ID = ${response.data.id.id}` }
}
// return complete obj
return {
id: response.data.id.id,
name: response.data.name,
type: response.data.id.entityType,
device_token: token,
};
}
} catch (err) {
return { error: true, message: `getObjectID(), Error while getting data from server: ${err}` }
}
}
// Get all possible object keys
async function getAllObjectKeys(id, entityType) {
if (((entityType === null) || (typeof entityType == 'undefined')) || ((typeof id === 'undefined') || (id === null))) {
return { error: true, message: `getAllObjectKeys(), Error: type or id are not defined or null!` };
}
const url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/plugins/telemetry/${entityType.toUpperCase()}/${id}/keys/attributes`;
try {
const response = await axios(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
return response.data
} catch (err) {
return { error: true, message: `getAllObjectKeys(), Request error: ${err}` }
}
}
/**
* If keys - null - trying to get all attributes
* @param {String} name
* @param {String} type
* @param {String} keys
*/
async function objectIDandKeys(name, type, keys = null, telemetryFlag = null) {
if (((typeof name === "undefined") || (name === null)) || ((typeof type === "undefined") || (type === null))) {
return { error: true, message: `objectIDandKeys(), Error: type or name are not defined or null!` }
}
const id = await getObjectID(name, type);
// error while getting id
if (id.error) {
return { error: true, message: id.message };
}
let attributeKeys = keys;
if (attributeKeys === null) {
attributeKeys = await getAllObjectKeys(id, type);
if (attributeKeys.error) {
return { error: true, message: `Error while getting keys ${attributeKeys.message}` };
}
}
let url = '';
if (telemetryFlag) {
// get telemetry data with keys and vals
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/plugins/telemetry/${type.toUpperCase()}/${id}/values/timeseries`;
}
// get keys and their values by default
if ((telemetryFlag === null) || !(telemetryFlag)) {
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/plugins/telemetry/${type.toUpperCase()}/${id}/values/attributes?keys=${attributeKeys}`;
}
try {
const response = await axios(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
const payload = response.data;
if (payload.length === 0) {
return { error: true, message: `objectIDandKeys(), Error: empty response payload!` };
}
// if we want to recieve only data with certain key
if (telemetryFlag && payload) {
if (!(keys in payload)) {
return {
error: true,
message: `Key ${keys} is not found in telemetry of object!`
};
}
if (payload[keys].length === 1) {
return {
data: payload[keys][0].value,
id: id,
}
}
}
const result = {
id: id,
name: name,
type: type,
}
// assign attribute keys and its values to object
for (let i = 0; i < payload.length; i++) {
result[payload[i].key] = payload[i].value
}
return result
} catch (err) {
return { error: true, message: `objectIDandKeys(), Error: ${err}` }
}
}
async function getObjectKeys(id, type, keys = null) {
if (((typeof id === "undefined") || (id === null)) || ((typeof type === "undefined") || (type === null))) {
return { error: true, message: "getObjectKeys(), Error: type or id are not defined or null!" }
}
let attributeKeys = keys;
if (attributeKeys === null) {
attributeKeys = await getAllObjectKeys(id, type);
// error while getting attributeKeys
if (attributeKeys.error) {
return { error: true, message: `Get keys error: ${attributeKeys.message }` };
}
}
const url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/plugins/telemetry/${type.toUpperCase()}/${id}/values/attributes?keys=${attributeKeys}`
try {
const response = await axios(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
const payload = response.data;
if (payload.length === 0) {
return [];
}
const result = {
id: id,
type: type,
}
for (let i = 0; i < payload.length; i++) {
result[payload[i].key] = payload[i].value
}
return result
} catch (err) {
return { error: true, message: `getObjectKeys(), ${err}` }
}
}
async function getObjectTelemetry(id, type, keys = null, startTS, endTS, limit) {
if (((typeof id === "undefined") || (id === null)) || ((typeof type === "undefined") || (type === null))) {
return { error: true, message: "getObjectKeys(), Error: type or id are not defined or null!" }
}
let telemetryKeys = keys;
if (telemetryKeys === null) {
return { error: true, message: `Get keys error: keys are null` };
}
const url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/plugins/telemetry/${type.toUpperCase()}/${id}/values/timeseries?keys=${telemetryKeys}&limit=${limit}&startTs=${startTS}&endTs=${endTS}`
try {
const response = await axios(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
const payload = response.data;
if (payload.length === 0) {
return [];
}
const result = {
id: id,
type: type,
}
for (let key in payload) {
result[key] = payload[key]
}
return result
} catch (err) {
return { error: true, message: `getObjectKeys(), ${err}` }
}
}
async function allObjectsIDbyType(customType, tbType, tokenFlag = false) {
if (((typeof customType === "undefined") || (customType === null)) || ((typeof tbType === "undefined") || (tbType === null))) {
return { error: true, message: 'allObjectsIDbyType(), Error: customType or tbType are not defined or null!' };
}
let url = '';
switch (tbType.toUpperCase()) {
case possibleEntityTypes.asset:
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/tenant/assets?type=${encodeURI(customType)}&pageSize=999999999&page=0`
break;
case possibleEntityTypes.device:
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/tenant/devices?type=${encodeURI(customType)}&pageSize=999999999&page=0`
break;
case possibleEntityTypes.view:
url = `http://${process.env.TB_HOST}:${process.env.TB_PORT}/api/tenant/entityViews?type=${encodeURI(customType)}&pageSize=999999999&page=0`
break;
default:
return { error: true, message: `allObjectsIDbyType(), Error: Get unknown TB type ${tbType}; Custom type ${customType}` };
}
if (url.length === 0) {
return { error: true, message: `allObjectsIDbyType(), Error: URL is empty!` };
}
try {
const response = await axios(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
const payload = response.data.data;
if (payload.length === 0) {
return { error: true, message: `allObjectsIDbyType(), Not found objects for Custom type ${customType} & TB type ${tbType}` };
}
let result = [];
for (let i = 0; i < payload.length; i++) {
result.push({
id: payload[i].id.id,
name: payload[i].name,
type: payload[i].type,
entityType: payload[i].id.entityType
});
}
// Set device token for response if it's device and tokenFlag is true
if (tokenFlag && tbType.toUpperCase() === possibleEntityTypes.device) {
for (let i = 0; i < result.length; i++) {
const token = await getDeviceToken(result[i].id);
if (token.error) {
continue;
}
result[i].deviceToken = token;
}
}
return result;
} catch (err) {
return { error: true, message: `allObjectsIDbyType(), Error: ${err}` }
}
}
/**
* If keys - null - trying to get all attributes
* @param {String} name
* @param {String} entity_type asset/device/entity_view
* @param {String} keys
*/
async function allObjectsIDandKeysByType(customType, entityType, keys = null) {
if (((typeof customType === "undefined") || (customType === null)) || ((typeof entityType === "undefined") || (entityType === null))) {
return { error: true, message: `allObjectsIDandKeysByType(), Error: customType or entityType are not defined or null!` };
}
const ids = await allObjectsIDbyType(customType, entityType);
if (ids.error) {
return { error: true, message: `Get ids by custom type error: ${ids.message}` };
}
const result = [];
for (let i = 0; i < ids.length; i++) {
let object = await getObjectKeys(ids[i].id, entityType, keys);
// skip assigning keys to object in case if error!
if (object.error) {
continue;
}
if(object.name){
object.attr_name = object.name
}
object.name = ids[i].name
result.push(object)
}
// In case of keys not found, return ids of objects with names and types
if (result.length === 0) {
return ids;
}
return result
}
/**
* @param {String} name
* @param {String} entity_type asset/device/entity_view
* @param {String} direction 'to'||'from'. to = childs, from = parents
* @param {Integer} level int if 0 or null - all levels
*/
// by default set max level
async function getRelations(name, entity_type, direction, level = 3,id=null) {
// if (level === 0)
// level = 3
if(id === null)
id = await getObjectID(name, entity_type);
if (id.error) {
return { "error": true, "message": id.message }
}
const relDirection = direction.toLowerCase()
let url = "";
switch (relDirection) {
case "to":
url = "http://" + process.env.TB_HOST + ':' + process.env.TB_PORT + "/api/relations/info?fromId=" + id + "&fromType=" + entity_type.toUpperCase();
break;
case "from":
url = "http://" + process.env.TB_HOST + ':' + process.env.TB_PORT + "/api/relations/info?toId=" + id + "&toType=" + entity_type.toUpperCase();
break;
default:
return {
"error": true, "message": `getRelations(), Error: get incorrect direction ${relDirection}`
};
}
if (url.length === 0) {
return { "error": true, "message": "getRelations(), Error: request url length = 0! Can't get relations!" }
}
try {
let response = await axios(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
});
//2ceacf40-78d3-11ea-a1c7-d1e730c27b32
//2ce83730-78d3-11ea-a1c7-d1e730c27b32
//http://84.201.141.244:8080/api/relations/info?fromId=2ceacf40-78d3-11ea-a1c7-d1e730c27b32&fromType=ENTITY_VIEW
const payload = response.data;
if (payload.length === 0) {
return { "error": true, "message": "getRelations(), Error: empty relations data response!" }
}
var answer = []
for (let i = 0; i < payload.length; i++) {
answer.push({
id: payload[i][direction].id,
name: payload[i][direction + 'Name'],
entity_type: payload[i][direction].entityType
})
}
if (level === 1) {
return answer
}
/*
for(let i=0; i< answer.length; i++){
//answer[i].childs = []
for (let ii=level; ii>0; ii--){
//console.log(answer[i])
answer[i].childs = await getRelations(answer[i].name,answer[i].entity_type,direction,ii)
//console.log(answer[i].childs )
}
}
*/
for (let i = 0; i < answer.length; i++) {
answer[i].childs = await getRelations(answer[i].name, answer[i].entity_type, direction, 1);
// go to next item on error! Discuss it in future!
if (answer[i].childs.error) {
continue;
}
}
if (level === 2) {
return answer
}
for (let i = 0; i < answer.length; i++) {
for (let ii = 0; ii < answer[i].childs.length; ii++) {
answer[i].childs[ii].childs = await getRelations(answer[i].childs[ii].name, answer[i].childs[ii].entity_type, direction, 1);
// go to next item on error! Discuss it in future!
if (answer[i].childs[ii].childs.error) {
continue;
}
}
}
return answer
} catch (err) {
return { "error": true, "message": `getRelations(), ${err}` }
}
}
async function getDeviceToken(deviceId) {
if ((typeof deviceId === "undefined") || (deviceId === null)) {
return { "error": true, "message": "getDeviceToken(), Error: deviceId is not defined or null!" }
}
const tokenUrl = "http://" + process.env.TB_HOST + ':' + process.env.TB_PORT + `/api/device/${deviceId}/credentials`;
const credentials = {
"method": 'get',
"url": tokenUrl,
"headers": {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env[tokenRand+'TB_TOKEN']
}
};
try {
const response = await axios(credentials);
if (response.status === 200) {
const token = response.data.credentialsId;
return token;
}
} catch (err) {
return { "error": true, "message": `getDeviceToken(), ${err}` }
}
}
async function getTenants(tenantID) {
const tokenUrl = "http://" + process.env.TB_HOST + ':' + process.env.TB_PORT + `/api/tenant/${tenantID}/users?pageSize=99999&page=0`;
const credentials = {
"method": 'get',
"url": tokenUrl,
"headers": {
'Content-Type': 'application/json',
'X-Authorization': 'Bearer ' + process.env.TB_SYSADMIN_TOKEN
}
};
try {
const response = await axios(credentials);
if (response.status === 200) {
let tenants = []
for(let i in response.data.data){
tenants.push(response.data.data[i].email)
}
return tenants;
}
} catch (err) {
return { "error": true, "message": `getDeviceToken(), ${err}` }
}
}
module.exports = {
objectID: getObjectID,
objectIDandKeys: objectIDandKeys,
allObjectsIDbyType: allObjectsIDbyType,
allObjectsIDandKeysByType: allObjectsIDandKeysByType,
relations: getRelations,
getDeviceToken: getDeviceToken,
getObjectKeys: getObjectKeys,
getAllObjectKeys: getAllObjectKeys,
getObjectTelemetry,
getTenants
};