class C8yService {
static MEASUREMENT_PAGE_SIZE = 50;
static ALARM_PAGE_SIZE = 50;
static EVENT_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 = {
// fragmentType: '',
// dateFrom: new Date("2020-01-01"),
// dateTo: new Date("2200-01-01"),
// pageSize: C8yService.MEASUREMENT_PAGE_SIZE,
// }
// ) {
// const filter = {
// source: deviceId,
// dateFrom: param.dateFrom.toISOString(),
// dateTo: param.dateTo.toISOString(),
// revert: true,
// pageSize: param.pageSize
// };
// if (param.fragmentType) filter.type = param.fragmentType;
// return this.measurementService.list(filter);
// }
getMeasurements(param) {
// 渡された filter を変更すると解決しづらいバグにつながるため、deep copy
const requestFilter = (param.filter)? JSON.parse(JSON.stringify(param.filter)) : {};
if (param.deviceId) {
requestFilter.source = param.deviceId;
}
return this.measurementService.list(requestFilter);
}
/**
* デバイスの Alarm 情報を取得する
*
* @param param {deviceId?, filter?} デバイスID, alarm 取得の際に指定する filter
*
* @returns IResultList<IAlarm> の Promise
*/
// getAlarms(param) {
// if (!param.filter) param.filter = {};
// if (param.deviceId) {
// param.filter.source = param.deviceId;
// }
// param.filter.withTotalPages = true;
// return this.alarmService.list(param.filter);
// }
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 this.alarmService.list(requestFilter);
}
/**
* デバイスの Event 情報を取得する
*
* @param param {deviceId?, filter?} デバイスID, event 取得の際に指定する filter
*
* @returns ResultList<IEvent> の Promise
*/
// getEvents(param) {
// if (!param.filter) param.filter = {};
// if (param.deviceId) {
// param.filter.source = param.deviceId;
// }
// if (!param.filter.pageSize) {
// param.filter.pageSize = C8yService.EVENT_PAGE_SIZE;
// }
// param.filter.withTotalPages = true;
// return this.eventService.list(param.filter);
// }
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 this.eventService.list(requestFilter);
}
/**
* 指定されたデバイスから報告された最後の Measurement を取得する。
* 最近の Measurement の Promise が返却される。
*
* @param deviceId デバイスID
* @param fragmentType measurement の fragmentType
*
* @returns 最近の IMeasurement の Promise
*/
getLastMeasurement(
deviceId,
fragmentType
) {
const filter = {
type: fragmentType,
revert: true,
dateFrom: "2000-01-01",
source: deviceId,
pageSize: 1
};
return this.measurementService.list(filter).then(resultList => resultList.data[0]);
}
/**
* MO ID をキーに MO を取得する
*
* @param moId MO ID
*
* @returns 指定IDの MO 詳細情報
*/
getParentAssetId(moId) {
const query = {
id: moId,
};
const filter = {
withParents: true,
};
return this.inventoryService.listQuery(query, filter);
}
/**
* MO ID をキーに MO を取得する
*
* @param moId MO ID
*
* @returns 指定IDの MO 詳細情報
*/
getMO(moId) {
return this.inventoryService.detail(moId);
}
/**
* リアルタイムにイベント等を取得するための Realtime オブジェクトを取得する
*
* @returns Realtime のインスタンス
*/
//getRealtime() {
// return new Realtime(this.fetchClient);
//}
/**
* Things Cloud デバイスID、外部IDタイプを指定して外部IDを取得する
*
* @param deviceId デバイスID
* @param externalIdType 外部IDタイプ
* @returns 外部IDで解決する Promise(見つからない場合、null で解決)
*/
async getExternalId(
deviceId,
externalIdType
) {
const externalIds = await this.identityService.list(deviceId);
for (const element of externalIds.data) {
if (element.type === externalIdType) return element.externalId;
}
return null;
}
/**
* 複数デバイスの最新 Event 各1件を取得する
*
* @param deviceIds デバイスIDの配列
* @param fragmentType カスタムフラグメント名
*
* @returns 各デバイスの最新 Event の配列
*/
getLatestEvents(deviceIds, fragmentType = "com_ImageDownloadable") {
const latestEvents = deviceIds.map((data) => {
const filter = {
dateFrom: "2020-01-01",
revert: false,
fragmentType: fragmentType,
pageSize: 1,
source: data,
};
return this.eventService.list(filter);
});
return Promise.all(latestEvents);
}
/**
* 指定アラームID のアラームステータスを更新する
*
* @param alarmId アラームID
* @param alarmStatus アラームステータス
*
* @returns 更新後のアラーム
*/
updateAlarmStatus(
alarmId,
alarmStatus
) {
const entity = {
id: alarmId,
status: alarmStatus,
};
return this.alarmService.update(entity);
}
/**
* 指定された Binary データを inventory の binary として保存します
*
* @param binaryData バイナリデータ(画像など)
*
* @returns 保存後の IManagaedObjectBinary
*/
createBinary(binaryData) {
return this.inventoryBinaryService.create(binaryData);
}
/**
* 指定 ID の InventoryBinary を取得する
*
* @param binaryId InventoryBinary ID
*
* @returns IfetchResponse の Promise
*/
getBinary(binaryId) {
return this.inventoryBinaryService.download(binaryId);
}
/**
* MO ID に対し、サブアセットを取得する。
* ID がデバイスの場合、単独のデバイスが設定され、アセットの場合、再帰的に
* 子アセットのデバイスが設定される。
*
* @param {string} moId MO ID
*
* @returns デバイスIDの配列
*/
async getSubAssets(moId){
const mos = await this.getSubAssetMOs(moId);
return mos.map( mo => mo.id );
}
/**
* MO ID に対し、サブアセットを取得する。
* ID がデバイスの場合、単独のデバイスが設定され、アセットの場合、再帰的に
* 子アセットのデバイスが設定される。
*
* @param {string} moId MO ID
*
* @returns デバイス ManagedObject の配列
*/
async getSubAssetMOs(moId) {
const devices = [];
await this.getSubAssetMOsImpl(moId, devices);
return devices;
}
async getSubAssetMOsImpl(moId, devices) {
const res = await this.getMO(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);
}
}
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;
}
}
});
}
// _flatten(obj, '', obj);
obj.forEach( obj => _flatten(obj, '', obj) )
return obj;
}
async getMeasurementsArray(
deviceId,
measurementsFilter
) {
let deviceIds = await this.getSubAssets(deviceId);
let measurements = [];
const promises = deviceIds.map(async (deviceId) => {
return (await this.getMeasurements({ deviceId: deviceId, filter: measurementsFilter})).data;
});
const measurementsList = await Promise.all(promises);
measurementsList.forEach(result => {
measurements = measurements.concat(result);
});
return this.flatten(measurements);
}
async getAlarmsArray(deviceId, alarmsFilter) {
let deviceIds = await this.getSubAssets(deviceId);
let alarms = [];
const promises = deviceIds.map(async (deviceId) => {
return (await this.getAlarms({ deviceId: deviceId, filter: alarmsFilter})).data;
});
const alarmsList = await Promise.all(promises);
alarmsList.forEach(result => {
alarms = alarms.concat(result);
});
return this.flatten(alarms);
}
async getEventsArray(deviceId, eventsFilter) {
let deviceIds = await this.getSubAssets(deviceId);
let events = [];
const promises = deviceIds.map(async (deviceId) => {
return (await this.getEvents({ deviceId: deviceId, filter: eventsFilter})).data;
});
const eventsList = await Promise.all(promises);
eventsList.forEach(result => {
events = events.concat(result);
});
return this.flatten(events);
}
}