Published
Edited
Feb 7, 2022
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
class ChartTemplateService {
static PAGE_SIZE = 50;

measurementService;
alarmService;
eventService;
inventoryService;
fetchClient;

constructor() {
}

/**
* Things Cloud に接続するために基本認証を使用して静的関数を設定します
* クラスメソッドを利用する場合、最初に呼び出す必要があります
*
* @param {string} url Things Cloud 接続URL 'https://{{your tenant}}.je1.thingscloud.ntt.com'
* @param {string} user
* @param {string} password
*/
async init(url, user, password) {
const client = await c8y.Client.authenticate({ user, password }, url);

this.measurementService = client.measurement;
this.alarmService = client.alarm;
this.eventService = client.event;
this.inventoryService = client.inventory;
this.inventoryBinaryService = client.inventoryBinary;
this.fetchClient = client.core;
}

/**
* deviceId, measurementsFilterで指定されたデバイスのMeasurement情報を
* 取得し、フラット化された(階層的なオブジェクト構造があった場合、ルートに設定した)
* オブジェクトの配列として返却します。
*
* @param {string} deviceId deviceId or groupId
* @param {object} measurementsFilter フィルタ情報
*
* @returns Measurement配列
*/
async getMeasurementsArray(
deviceId, measurementsFilter
) {
let deviceIds = await this.getSubAssets(deviceId);
let measurements = [];
const promises = deviceIds.map(async (deviceId) => {
return (await this.getMeasurements({deviceId, filter: measurementsFilter})).data;
});
const measurementsList = await Promise.all(promises);
measurementsList.forEach(result => {
measurements = measurements.concat(result);
});
return this.flatten(measurements);
}

/**
* deviceId, alarmsFilterで指定されたデバイスのAlarm情報を
* 取得し、フラット化された(階層的なオブジェクト構造があった場合、ルートに設定した)
* オブジェクトの配列として返却します。
*
* @param {string} deviceId deviceId or groupId
* @param {object} alarmsFilter フィルタ情報
*
* @returns Alarm配列
*/
async getAlarmsArray(deviceId, alarmsFilter) {
let deviceIds = await this.getSubAssets(deviceId);
let alarms = [];
const promises = deviceIds.map(async (deviceId) => {
return (await this.getAlarms({ deviceId, filter: alarmsFilter})).data;
});
const alarmsList = await Promise.all(promises);
alarmsList.forEach(result => {
alarms = alarms.concat(result);
});
return this.flatten(alarms);
}

/**
* deviceId, eventsFilterで指定されたデバイスのEvent情報を
* 取得し、フラット化された(階層的なオブジェクト構造があった場合、ルートに設定した)
* オブジェクトの配列として返却します。
*
* @param {string} deviceId deviceId or groupId
* @param {object} eventsFilter フィルタ情報
*
* @returns Event配列
*/
async getEventsArray(deviceId, eventsFilter) {
let deviceIds = await this.getSubAssets(deviceId);
let events = [];
const promises = deviceIds.map(async (deviceId) => {
return (await this.getEvents({ deviceId, filter: eventsFilter})).data;
});
const eventsList = await Promise.all(promises);
eventsList.forEach(result => {
events = events.concat(result);
});
return this.flatten(events);
}

/**
* 指定された object の配列に関し、各 object の階層を平坦化し 1 層に変換します。
* 例: [{a: 1, b: {c: 5}}] ---> [{a: 1, b_c: 5}]
* object 値に配列を含む場合、配列内の object は平坦化されないことに注意して下さい。
* 例: [{a: 1, b: [{c: 5}]}] ---> [{a: 1, b: [{c: 5}]}] (変更なし)
*
* @private
* @param objectArray object の配列
*
* @return 各要素が平坦化(つなぎ文字は _)された object の配列(Plot で利用可能な形式)
*/
flatten( obj ) {
function _flatten( parent, parentKey, obj ) {
const keys = Object.keys(obj);
if (keys.length == 0) return parent;
if (parentKey) delete parent[parentKey];
keys.forEach( key => {
const v = obj[key];
const ckey = parentKey + ((parentKey !== '')?'_':'') + key;
if ( v !== null && typeof v === 'object' && !Array.isArray(v)) {
_flatten(parent, ckey, v);
} else {
if (parent !== obj) {
parent[ckey] = v;
}
}
});
}
obj.forEach( obj => _flatten(obj, '', obj) )
return obj;
}

/**
* Things Cloud に接続し、Alarm 一覧を取得する
*
* @private
* @param {object} param
*
* @returns Promise<IResultList<IAlarm>>
*/
async getAlarms(param) {
// 渡された filter を変更すると解決しづらいバグにつながるため、deep copy
const requestFilter = (param.filter)? JSON.parse(JSON.stringify(param.filter)) : {};
if (param.deviceId) {
requestFilter.source = param.deviceId;
}
requestFilter.withTotalPages = true;

return await this.alarmService.list(requestFilter);
}
/**
* Things Cloud に接続し、Event 一覧を取得する
*
* @private
* @param {object} param
*
* @returns Promise<IResultList<IEvent>>
*/
async getEvents(param) {
// 渡された filter を変更すると解決しづらいバグにつながるため、deep copy
const requestFilter = (param.filter)? JSON.parse(JSON.stringify(param.filter)) : {};
if (param.deviceId) {
requestFilter.source = param.deviceId;
}
requestFilter.withTotalPages = true;

return await this.eventService.list(requestFilter);
}

/**
* Things Cloud に接続し、Measurement 一覧を取得する
*
* @private
* @param {object} param
*
* @returns Promise<IResultList<IMeasurement>>
*/
async getMeasurements(param) {
// 渡された filter を変更すると解決しづらいバグにつながるため、deep copy
const requestFilter = (param.filter)? JSON.parse(JSON.stringify(param.filter)) : {};
if (param.deviceId) {
requestFilter.source = param.deviceId;
}
return await this.measurementService.list(requestFilter);
}
/**
* MO ID に対し、サブアセットを取得する。
* ID がデバイスの場合、単独のデバイスが設定され、アセットの場合、再帰的に
* 子アセットのデバイスが設定される。
*
* @private
* @param {string} moId MO ID
*
* @returns Promise デバイスIDの配列
*/
async getSubAssets(moId) {
const mos = await this.getSubAssetMOs(moId);
return mos.map( mo => mo.id );
}

/**
* MO ID に対し、サブアセットを取得する。
* ID がデバイスの場合、単独のデバイスが設定され、アセットの場合、再帰的に
* 子アセットのデバイスが設定される。
*
* @private
* @param {string} moId MO ID
*
* @returns Promise デバイス ManagedObject の配列
*/
async getSubAssetMOs(moId) {
const devices = [];
await this.getSubAssetMOsImpl(moId, devices);
return devices;
}

/**
* デバイスかグループを判断し、デバイスの場合はdevicesへpush、
* グループの場合は再帰的に関数を呼び出す。
*
* @private
* @param {string} moId moId
* @param {IManagedObject[]} devices デバイス情報のリスト
*
* @returns Promise<void>
*/
async getSubAssetMOsImpl(moId, devices) {
const res = await this.inventoryService.detail(moId);
if (res.data.childAssets.references.length > 0) {
// 指定されたのはグループ
for (const data of res.data.childAssets.references) {
await this.getSubAssetMOsImpl(data.managedObject.id, devices); // 再帰
}
} else {
// 指定されたのはデバイス
if (devices.map( mo => mo.id).indexOf(res.data.id) > -1) return;
devices.push(res.data);
}
}
}

Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more