@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
809 lines (779 loc) • 33.2 kB
JavaScript
import { ComputedPropertiesService, hookComputedProperty } from '@c8y/ngx-components/asset-properties';
import * as i0 from '@angular/core';
import { inject, Injector, Injectable } from '@angular/core';
import { MeasurementService, InventoryService, AlarmService, EventService, OperationService } from '@c8y/client';
import { MeasurementRealtimeService, DatePipe, ManagedObjectRealtimeService, AlarmRealtimeService, EventRealtimeService, OperationRealtimeService } from '@c8y/ngx-components';
import { from, map, filter, startWith, take, switchMap, distinctUntilChanged, pairwise, share, NEVER, scan, tap, of, catchError, combineLatest, merge } from 'rxjs';
import { gettext } from '@c8y/ngx-components/gettext';
import { get } from 'lodash-es';
const RESULT_TYPES$1 = {
VALUE: { name: 'VALUE', value: 1, label: gettext('Only value') },
VALUE_UNIT: { name: 'VALUE_UNIT', value: 2, label: gettext('Value and unit') },
VALUE_UNIT_TIME: { name: 'VALUE_UNIT_TIME', value: 3, label: gettext('Value, unit and time') },
OBJECT: { name: 'OBJECT', value: 4, label: gettext('Complete object') }
};
const DEFAULT_DECIMAL_PLACES = 2;
class LastMeasurementStrategy {
constructor(config, injector) {
this.config = config;
this.measurementService = injector.get(MeasurementService);
this.measurementRealtime = injector.get(MeasurementRealtimeService);
this.datePipe = injector.get(DatePipe);
this.datapoint = config.dp.filter(dp => dp.__active)[0];
}
fetchCurrentValue() {
const measurementFilter = {
valueFragmentSeries: this.datapoint.series,
valueFragmentType: this.datapoint.fragment,
pageSize: 1,
revert: true,
dateFrom: '1970-01-01',
source: this.datapoint.__target.id
};
return from(this.measurementService.list(measurementFilter)).pipe(map(({ data }) => data[0]), filter(measurement => !!measurement), map(measurement => this.formatMeasurement(measurement)));
}
createRealtimeStream(initialValue) {
return this.measurementRealtime
.onCreateOfSpecificMeasurement$(this.datapoint.fragment, this.datapoint.series, this.datapoint.__target)
.pipe(map(measurement => this.formatMeasurement(measurement)), startWith(initialValue));
}
formatMeasurement(measurement) {
const resultType = this.config?.resultType;
const fragment = this.datapoint.fragment;
const series = this.datapoint.series;
const decimalPlaces = this.config?.numberOfDecimalPlaces ?? DEFAULT_DECIMAL_PLACES;
const value = this.formatValue(measurement[fragment][series].value, decimalPlaces);
const unit = measurement[fragment][series].unit;
if (resultType === RESULT_TYPES$1.VALUE.value) {
return value;
}
else if (resultType === RESULT_TYPES$1.VALUE_UNIT.value) {
return `${value} ${unit}`;
}
else if (resultType === RESULT_TYPES$1.VALUE_UNIT_TIME.value) {
const date = this.datePipe.transform(new Date(measurement.time), 'short');
return `${date} | ${value} ${unit}`;
}
else if (resultType === RESULT_TYPES$1.OBJECT.value) {
return { ...measurement[fragment][series], value: parseFloat(value).toFixed(decimalPlaces) };
}
return '';
}
formatValue(value, decimalPlaces) {
const numericValue = typeof value === 'string' ? parseFloat(value) : value;
if (isNaN(numericValue)) {
return String(value);
}
return numericValue.toFixed(decimalPlaces);
}
}
/**
* Generic handler for realtime values following the three modes pattern
* Closed for modification but open for extension through strategies
*/
class RealtimeValueHandler {
constructor(strategy, config) {
this.strategy = strategy;
this.config = {
refetchOnResume: true,
preserveValueOnPause: true
};
if (config) {
this.config = { ...this.config, ...config };
}
}
/**
* Creates an Observable based on the metadata mode
*/
getValue(metadata = { mode: 'realtime' }) {
if (metadata.mode === 'singleValue') {
return this.strategy.fetchCurrentValue().pipe(take(1));
}
if (metadata.mode === 'realtime' && !metadata.realtimeControl$) {
return this.handleUncontrolledRealtime();
}
if (metadata.mode === 'realtime' && metadata.realtimeControl$) {
return this.handleControlledRealtime(metadata.realtimeControl$);
}
}
handleUncontrolledRealtime() {
return this.strategy
.fetchCurrentValue()
.pipe(switchMap(initialValue => this.strategy.createRealtimeStream(initialValue)));
}
handleControlledRealtime(control$) {
const controlWithPrevious$ = control$.pipe(distinctUntilChanged(), startWith(null), pairwise(), share());
return controlWithPrevious$.pipe(switchMap(([previous, current]) => {
if (!current) {
// Realtime is disabled
if (previous === null) {
// Initial emission while disabled
return this.strategy.fetchCurrentValue().pipe(take(1));
}
else if (this.config.preserveValueOnPause) {
// Was previously enabled - preserve last value
return NEVER;
}
else {
// Don't preserve value - fetch current
return this.strategy.fetchCurrentValue().pipe(take(1));
}
}
else {
// Realtime is enabled
if (this.config.refetchOnResume || previous === null) {
// Re-fetch current value and start streaming
return this.strategy
.fetchCurrentValue()
.pipe(switchMap(currentValue => this.strategy.createRealtimeStream(currentValue)));
}
else {
// Continue with realtime stream without re-fetching
return this.strategy.createRealtimeStream(null);
}
}
}));
}
}
/**
* Creates an Observable that tracks the latest measurement value for a specific datapoint.
* Combines initial server fetch with real-time measurement updates.
*
* @param config - Measurement configuration (datapoint, result type, etc.)
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<string> - Stream of measurement string values
*/
function lastMeasurementValue(config, metadata = { mode: 'realtime' }) {
const injector = inject(Injector);
const strategy = new LastMeasurementStrategy(config, injector);
const handler = new RealtimeValueHandler(strategy);
return handler.getValue(metadata);
}
const lastMeasurement = {
name: 'lastMeasurement',
contextType: ['device', 'asset', 'group'],
prop: {
c8y_JsonSchema: {
properties: {
lastMeasurement: {
label: 'Last measurement',
type: 'string'
}
}
},
name: 'lastMeasurement',
label: gettext('Last measurement'),
type: 'string',
config: { dp: [], resultType: 1 },
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-last-measurement-config.component-yfc45-l_.mjs').then(m => m.ComputedPropertyLastMeasurementConfigComponent),
value: ({ config }) => {
return lastMeasurementValue(config);
}
};
class ChildCountStrategy {
constructor(asset, childType, injector) {
this.asset = asset;
this.childType = childType;
this.inventoryService = injector.get(InventoryService);
this.moRealtimeService = injector.get(ManagedObjectRealtimeService);
}
fetchCurrentValue() {
return from(this.inventoryService.detail(this.asset.id, { withChildren: true })).pipe(map(resp => resp?.data?.[this.childType]?.references?.length || 0));
}
createRealtimeStream(initialValue) {
return this.moRealtimeService.onAll$(this.asset.id).pipe(map(resp => resp?.data?.[this.childType]?.references?.length || 0), startWith(initialValue));
}
}
/**
* Shared function that tracks the count of child items (devices or assets) for a specific managed object.
* Supports real-time updates when child items are added or removed.
*
* @param asset - The managed object to track child items for
* @param childType - Type of child items ('childDevices' or 'childAssets')
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<number> - Stream of child items count values
*/
function childCountValue(asset, metadata = { mode: 'realtime' }, childType) {
const injector = inject(Injector);
const strategy = new ChildCountStrategy(asset, childType, injector);
const handler = new RealtimeValueHandler(strategy);
return handler.getValue(metadata);
}
const childAssetsCount = {
name: 'childAssetsCount',
contextType: ['group', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
childAssetsCount: {
label: 'Number of child assets',
type: 'number'
}
}
},
name: 'childAssetsCount',
label: gettext('Number of child assets'),
type: 'number',
computed: true,
isEditable: false,
isStandardProperty: true
},
value: ({ context, metadata }) => childAssetsCountValue(context, metadata)
};
/**
* Creates an Observable that tracks the count of child assets for a specific asset.
* Supports real-time updates when child assets are added or removed.
*
* @param asset - The managed object (asset) to track child assets for
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<number> - Stream of child assets count values
*/
function childAssetsCountValue(asset, metadata = { mode: 'realtime' }) {
return childCountValue(asset, metadata, 'childAssets');
}
/**
* Base class for count-based strategies
* Provides common accumulation logic
*/
class CountStrategyBase {
createRealtimeStream(initialValue) {
return this.getRealtimeIncrement$().pipe(scan((count, increment) => count + increment, initialValue), startWith(initialValue));
}
}
class AlarmCountStrategy extends CountStrategyBase {
constructor(config, asset, dateFrom, injector) {
super();
this.config = config;
this.asset = asset;
this.dateFrom = dateFrom;
this.alarmService = injector.get(AlarmService);
this.alarmRealtimeService = injector.get(AlarmRealtimeService);
this.startTime = new Date();
}
fetchCurrentValue() {
const severities = Object.keys(this.config.severities || {}).filter(key => this.config.severities[key]);
const filters = {
source: this.asset.id,
dateFrom: this.dateFrom.toISOString(),
type: this.config.type,
pageSize: 1,
withTotalElements: true,
...(severities.length && { severity: severities.join(',') })
};
return from(this.alarmService.list(filters)).pipe(map(resp => resp?.paging?.totalElements || 0), tap(() => (this.startTime = new Date())) // Update start time after fetch
);
}
getRealtimeIncrement$() {
return this.alarmRealtimeService.onAll$(this.asset.id).pipe(map(({ data }) => data), filter(alarm => alarm.type === this.config.type &&
this.config.severities[alarm.severity] &&
new Date(alarm.creationTime) > this.startTime), tap(() => (this.startTime = new Date())), map(() => 1) // Each matching alarm increments by 1
);
}
}
/**
* Creates an Observable that tracks alarm count for a specific asset.
* When real-time is paused and resumed, it re-fetches the current count from server
* to account for alarms that occurred during the pause.
*
* @param config - Alarm filtering configuration (type, severities, etc.)
* @param asset - The managed object (device/asset) to track alarms for
* @param dateFrom - Start date for counting alarms
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<number> - Stream of alarm count values
*/
function alarmCountValue(config, asset, dateFrom, metadata = { mode: 'realtime' }) {
const injector = inject(Injector);
const strategy = new AlarmCountStrategy(config, asset, dateFrom, injector);
const handler = new RealtimeValueHandler(strategy);
return handler.getValue(metadata);
}
const alarmCount3Months = {
name: 'alarmCount3Months',
contextType: ['device', 'group', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
alarmCount3Months: {
label: 'Alarm count 3 months',
type: 'number'
}
}
},
name: 'alarmCount3Months',
label: gettext('Alarm count 3 months'),
type: 'number',
config: { type: '' },
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-alarm-count-config.component-Zygcid6r.mjs').then(m => m.ComputedPropertyAlarmCountConfigComponent),
value: ({ config, context, metadata }) => alarmCount3MonthsValue(config, context, metadata)
};
function alarmCount3MonthsValue(config, asset, metadata) {
const threeMonthsAgo = new Date();
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
return alarmCountValue(config, asset, threeMonthsAgo, metadata);
}
const alarmCountToday = {
name: 'alarmCountToday',
contextType: ['device', 'group', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
alarmCountToday: {
label: 'Alarm count today',
type: 'number'
}
}
},
name: 'alarmCountToday',
label: gettext('Alarm count today'),
type: 'number',
config: { type: '' },
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-alarm-count-config.component-Zygcid6r.mjs').then(m => m.ComputedPropertyAlarmCountConfigComponent),
value: ({ config, context, metadata }) => alarmCountTodayValue(config, context, metadata)
};
function alarmCountTodayValue(config, asset, metadata) {
const oneDayAgo = new Date();
oneDayAgo.setDate(oneDayAgo.getDate() - 1);
return alarmCountValue(config, asset, oneDayAgo, metadata);
}
class EventCountStrategy extends CountStrategyBase {
constructor(config, asset, dateFrom, injector) {
super();
this.config = config;
this.asset = asset;
this.dateFrom = dateFrom;
this.eventService = injector.get(EventService);
this.eventRealtimeService = injector.get(EventRealtimeService);
}
fetchCurrentValue() {
const filters = {
source: this.asset.id,
dateFrom: this.dateFrom.toISOString(),
type: this.config.type,
pageSize: 1,
withTotalElements: true
};
return from(this.eventService.list(filters)).pipe(map(resp => resp?.paging?.totalElements || 0));
}
getRealtimeIncrement$() {
return this.eventRealtimeService.onAll$(this.asset.id).pipe(map(({ data }) => data), filter(event => event.type === this.config.type && new Date(event.time) >= this.dateFrom), map(() => 1));
}
}
/**
* Creates an Observable that tracks event count for a specific asset.
* When real-time is paused and resumed, it re-fetches the current count from server
* to account for events that occurred during the pause.
*
* @param config - Event filtering configuration (type, etc.)
* @param asset - The managed object (device/asset) to track events for
* @param dateFrom - Start date for counting events
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<number> - Stream of event count values
*/
function eventCountValue(config, asset, dateFrom, metadata = { mode: 'realtime' }) {
const injector = inject(Injector);
const strategy = new EventCountStrategy(config, asset, dateFrom, injector);
const handler = new RealtimeValueHandler(strategy);
return handler.getValue(metadata);
}
const eventCountToday = {
name: 'eventCountToday',
contextType: ['device', 'group', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
eventCountToday: {
label: 'Event count today',
type: 'number'
}
}
},
name: 'eventCountToday',
label: gettext('Event count today'),
type: 'number',
config: { type: '' },
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-event-count-config.component-DzAGrG1d.mjs').then(m => m.ComputedPropertyEventCountConfigComponent),
value: ({ config, context, metadata }) => eventCountTodayValue(config, context, metadata)
};
function eventCountTodayValue(config, asset, metadata) {
const today = new Date();
today.setHours(0, 0, 0, 0);
return eventCountValue(config, asset, today, metadata);
}
const eventCount3Months = {
name: 'eventCount3Months',
contextType: ['device', 'group', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
eventCount3Months: {
label: 'Event count 3 months',
type: 'number'
}
}
},
name: 'eventCount3Months',
label: gettext('Event count 3 months'),
type: 'number',
config: { type: '' },
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-event-count-config.component-DzAGrG1d.mjs').then(m => m.ComputedPropertyEventCountConfigComponent),
value: ({ config, context, metadata }) => eventCount3MonthsValue(config, context, metadata)
};
function eventCount3MonthsValue(config, asset, metadata) {
const threeMonthsAgo = new Date();
threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
return eventCountValue(config, asset, threeMonthsAgo, metadata);
}
const configurationSnapshot = {
name: 'configurationSnapshot',
contextType: ['device', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
configurationSnapshot: {
label: 'Configuration snapshot',
type: 'string'
}
}
},
contextType: ['device', 'asset'],
name: 'configurationSnapshot',
label: gettext('Configuration snapshot'),
type: 'string',
config: { legacy: true },
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-configuration-snapshot-config.component-Dz3efcEU.mjs').then(m => m.ConfigurationSnapshotConfigComponent),
value: ({ config, context }) => configurationSnapshotValue(config, context)
};
function configurationSnapshotValue(config, asset) {
if (config.legacy) {
const configId = asset.c8y_ConfigurationDump?.id;
if (!configId) {
return of(null);
}
const injector = inject(Injector);
const inventoryService = injector.get(InventoryService);
return from(inventoryService.detail(configId)).pipe(switchMap(({ data }) => {
return of(data?.name);
}));
}
else {
const fragment = `c8y_Configuration_${config.type}`;
return of(asset[fragment]?.name);
}
}
const childDevicesCount = {
name: 'childDevicesCount',
contextType: ['group', 'device', 'asset'],
prop: {
c8y_JsonSchema: {
properties: {
childDevicesCount: {
label: 'Number of child devices',
type: 'number'
}
}
},
name: 'childDevicesCount',
label: gettext('Number of child devices'),
type: 'number',
computed: true,
isEditable: false,
isStandardProperty: true
},
value: ({ context, metadata }) => childDevicesCountValue(context, metadata)
};
/**
* Creates an Observable that tracks the count of child devices for a specific asset.
* Supports real-time updates when child devices are added or removed.
*
* @param asset - The managed object (asset) to track child devices for
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<number> - Stream of child devices count values
*/
function childDevicesCountValue(asset, metadata = { mode: 'realtime' }) {
return childCountValue(asset, metadata, 'childDevices');
}
class LastDeviceMessageStrategy {
constructor(asset, injector) {
this.asset = asset;
this.measurementService = injector.get(MeasurementService);
this.measurementRealtime = injector.get(MeasurementRealtimeService);
this.eventService = injector.get(EventService);
this.eventRealtimeService = injector.get(EventRealtimeService);
this.alarmService = injector.get(AlarmService);
this.alarmRealtimeService = injector.get(AlarmRealtimeService);
this.operationService = injector.get(OperationService);
this.operationRealtimeService = injector.get(OperationRealtimeService);
this.startTime = new Date();
}
fetchCurrentValue() {
const fetchFilter = {
source: this.asset.id,
pageSize: 1,
revert: true
};
const fetchLatestMeasurement = () => {
return from(this.measurementService.list(fetchFilter)).pipe(map(resp => resp.data?.[0]?.time || null), catchError(() => of(null)));
};
const fetchLatestEvent = () => {
return from(this.eventService.list(fetchFilter)).pipe(map(resp => resp.data?.[0]?.time || null), catchError(() => of(null)));
};
const fetchLatestAlarm = () => {
return from(this.alarmService.list(fetchFilter)).pipe(map(resp => resp.data?.[0]?.time || null), catchError(() => of(null)));
};
const fetchLatestOperation = () => {
return from(this.operationService.list(fetchFilter)).pipe(map(resp => resp.data?.[0]?.creationTime || null), catchError(() => of(null)));
};
return combineLatest([
fetchLatestMeasurement(),
fetchLatestEvent(),
fetchLatestAlarm(),
fetchLatestOperation()
]).pipe(map(timestamps => {
const validTimestamps = timestamps.filter(Boolean);
if (validTimestamps.length === 0) {
return null;
}
const latest = validTimestamps.reduce((latest, current) => {
return new Date(current) > new Date(latest) ? current : latest;
});
// Update start time for realtime filtering
this.startTime = new Date();
return latest;
}));
}
createRealtimeStream(initialValue) {
const measurementStream$ = this.measurementRealtime.onAll$(this.asset.id).pipe(map(({ data }) => data.time), filter(time => new Date(time) > this.startTime));
const eventStream$ = this.eventRealtimeService.onAll$(this.asset.id).pipe(map(({ data }) => data.time), filter(time => new Date(time) > this.startTime));
const alarmStream$ = this.alarmRealtimeService.onAll$(this.asset.id).pipe(map(({ data }) => data.time), filter(time => time && new Date(time) > this.startTime));
const operationStream$ = this.operationRealtimeService.onAll$(this.asset.id).pipe(map(({ data }) => data.creationTime), filter(time => time && new Date(time) > this.startTime));
return merge(measurementStream$, eventStream$, alarmStream$, operationStream$).pipe(scan((latestTimestamp, newTimestamp) => {
return new Date(newTimestamp) > new Date(latestTimestamp) ? newTimestamp : latestTimestamp;
}, initialValue), startWith(initialValue));
}
}
/**
* Gets the latest timestamp from events, alarms, measurements, and operations for a device.
* Returns the most recent timestamp across all these sources.
*
* @param asset - The managed object (device/asset) to track
* @param metadata - Configuration controlling the behavior of the function
* @returns Observable<string> - Stream of latest timestamp values
*/
function getLastDeviceMessage(asset, metadata = { mode: 'realtime' }) {
const injector = inject(Injector);
const strategy = new LastDeviceMessageStrategy(asset, injector);
const handler = new RealtimeValueHandler(strategy);
return handler.getValue(metadata);
}
const lastDeviceMessage = {
name: 'lastDeviceMessage',
contextType: ['device'],
prop: {
c8y_JsonSchema: {
properties: {
lastDeviceMessage: {
label: 'Last device message',
type: 'string'
}
}
},
name: 'lastDeviceMessage',
label: gettext('Last device message'),
printFormat: 'datetime',
type: 'string',
computed: true,
isEditable: false,
isStandardProperty: true
},
value: ({ context }) => {
return getLastDeviceMessage(context);
}
};
const RESULT_TYPES = {
RAW_VALUE: { name: 'RAW_VALUE', value: 'RAW_VALUE', label: gettext('Raw value') },
ENUM_VALUE: { name: 'ENUM_VALUE', value: 'ENUM_VALUE', label: gettext('Enum value') }
};
class FieldbusService {
constructor() {
this.inventory = inject(InventoryService);
this.computedProperties = inject(ComputedPropertiesService);
}
async getDeviceTypeOf(fieldbusDevice) {
const typeRef = fieldbusDevice?.c8y_ModbusDevice?.type;
if (!typeRef) {
throw new Error('Provided device is missing c8y_ModbusDevice.type.');
}
const match = /^\/inventory\/managedObjects\/(\d+)$/.exec(typeRef);
if (!match) {
throw new Error(`Provided Fieldbus type reference ${typeRef} has invalid format, expected: /inventory/managedObjects/{id}`);
}
const deviceTypeId = match[1];
try {
const { data } = await this.inventory.detail(deviceTypeId);
return data;
}
catch (ex) {
const errorMessage = ex instanceof Error ? ex.message : String(ex);
throw new Error(`Could not fetch Fieldbus device type with ID ${deviceTypeId}: ${errorMessage}.`);
}
}
async migrateFieldbusProperty(legacyProperty, fieldbusDevice) {
if (!legacyProperty.fieldbus) {
throw new Error('Provided property is not a legacy Fieldbus property.');
}
const computedPropertyName = 'fieldbusItemStatus';
const computedProperty = await this.computedProperties.getByName(computedPropertyName);
const [statusPropertyName, itemName] = legacyProperty.keyPath;
const itemType = statusPropertyName === 'c8y_CoilStatus' ? 'c8y_Coil' : 'c8y_Register';
const deviceType = await this.getDeviceTypeOf(fieldbusDevice);
const itemListPropertyName = `${itemType}s`;
const itemList = deviceType[itemListPropertyName] || [];
const item = itemList.find(i => i.name === itemName);
const resultType = item.enumValues ? 'ENUM_VALUE' : 'RAW_VALUE';
return {
...computedProperty.prop,
active: true,
temporary: true,
asset: {
id: fieldbusDevice.id,
name: fieldbusDevice.name
},
config: {
itemName,
itemType,
resultType
}
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FieldbusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FieldbusService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: FieldbusService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
class FieldbusItemStatusStrategy {
constructor(asset, config, injector) {
this.asset = asset;
this.config = config;
this.inventoryService = injector.get(InventoryService);
this.moRealtimeService = injector.get(ManagedObjectRealtimeService);
this.fieldbusService = injector.get(FieldbusService);
}
fetchCurrentValue() {
return from(this.inventoryService.detail(this.asset.id)).pipe(switchMap(({ data }) => this.getStatus(data)));
}
createRealtimeStream(initialValue) {
return this.moRealtimeService.onAll$(this.asset.id).pipe(switchMap(({ data }) => this.getStatus(data)), startWith(initialValue));
}
async getStatus(fieldbusDevice) {
const fieldbusDeviceType = await this.getFieldbusDeviceType(fieldbusDevice);
if (!fieldbusDeviceType) {
return null;
}
const itemListPropertyName = `${this.config.itemType}s`;
const statusPropertyName = `${this.config.itemType}Status`;
const items = fieldbusDeviceType[itemListPropertyName] ?? [];
const item = items.find(i => i.name === this.config.itemName);
const statusProperty = get(fieldbusDevice, statusPropertyName);
const rawValue = get(statusProperty, this.config.itemName);
if (this.config.resultType === RESULT_TYPES.ENUM_VALUE.value && item?.enumValues) {
return item.enumValues[rawValue] ?? rawValue;
}
else {
return rawValue;
}
}
async getFieldbusDeviceType(fieldbusDevice) {
if (this._fieldbusDeviceType === undefined) {
try {
this._fieldbusDeviceType = await this.fieldbusService.getDeviceTypeOf(fieldbusDevice);
}
catch (ex) {
this._fieldbusDeviceType = null;
}
}
return this._fieldbusDeviceType;
}
}
const fieldbusItemStatus = {
name: 'fieldbusItemStatus',
contextType: ['device'],
prop: {
c8y_JsonSchema: {
properties: {
fieldbusItemStatus: {
label: gettext('Fieldbus item status'),
type: ['number', 'string']
}
}
},
name: 'fieldbusItemStatus',
label: gettext('Fieldbus item status'),
type: ['number', 'string'],
config: {
itemName: null,
itemType: null,
resultType: 'RAW_VALUE'
},
computed: true,
isEditable: false,
isStandardProperty: true
},
loadConfigComponent: () => import('./c8y-ngx-components-computed-asset-properties-fieldbus-item-status-config.component-DgWGXzEx.mjs').then(m => m.FieldbusItemStatusConfigComponent),
value: ({ config, context }) => fieldbusItemStatusValue(context, config)
};
function fieldbusItemStatusValue(asset, config, metadata = { mode: 'realtime' }) {
const injector = inject(Injector);
const strategy = new FieldbusItemStatusStrategy(asset, config, injector);
const handler = new RealtimeValueHandler(strategy);
return handler.getValue(metadata);
}
const computedAssetPropertiesProviders = [
AlarmRealtimeService,
EventRealtimeService,
MeasurementRealtimeService,
OperationRealtimeService,
ManagedObjectRealtimeService,
hookComputedProperty([
lastMeasurement,
lastDeviceMessage,
childAssetsCount,
childDevicesCount,
alarmCount3Months,
alarmCountToday,
eventCountToday,
eventCount3Months,
configurationSnapshot,
fieldbusItemStatus
])
];
/**
* Generated bundle index. Do not edit.
*/
export { DEFAULT_DECIMAL_PLACES as D, FieldbusService as F, RESULT_TYPES$1 as R, RESULT_TYPES as a, computedAssetPropertiesProviders as c };
//# sourceMappingURL=c8y-ngx-components-computed-asset-properties-c8y-ngx-components-computed-asset-properties-CHZX7ALq.mjs.map