class ChartTemplateService {
static PAGE_SIZE = 50;
measurementService;
alarmService;
eventService;
inventoryService;
fetchClient;
constructor() {
}
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;
}
* @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);
});
const result = this.flatten(measurements);
result.forEach(f => f.time = new Date(f.time));
return result;
}
/**
* 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);
});
const result = this.flatten(alarms);
result.forEach(f => f.time = new Date(f.time));
return result;
}
/**
* 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);
});
const result = this.flatten(events);
result.forEach(f => f.time = new Date(f.time));
return result;
}
/**
* 指定された 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);
}
}
}