diff --git a/src/specificClass.js b/src/specificClass.js index 8317f2e..989eec1 100644 --- a/src/specificClass.js +++ b/src/specificClass.js @@ -116,66 +116,138 @@ class Machine { } /*------------------- Register child events -------------------*/ - registerOnChildEvents() { - this.logger.debug('Setting up child event listeners'); +registerOnChildEvents() { + this.logger.debug('Setting up child event listeners'); - // ✅ Use utility to get sensors (but keep your manual control) - const sensors = this.childRegistrationUtils.getChildrenOfType('measurement', 'sensor'); - - if (sensors.length === 0) { - this.logger.warn('No measurement sensors found to register events for'); - return; - } + const sensors = this.childRegistrationUtils.getChildrenOfType('measurement', 'sensor'); + + if (sensors.length === 0) { + this.logger.warn('No measurement sensors found to register events for'); + return; + } - this.logger.debug(`Found ${sensors.length} sensors to register events for`); - - // ✅ Register events for each sensor - sensors.forEach(sensor => { - switch (sensor.config.asset.type) { - case 'pressure': - this.logger.debug(`Registering pressure events for sensor: ${sensor.config.general.name}`); - // upstream pressure handling - sensor.measurements.emitter.on('pressure.measured.upstream', (eventData) => { - this.logger.debug(`🔄 Upstream pressure from ${eventData.childName}: ${eventData.value} ${eventData.unit}`); - // Update the measured pressure - this.updateMeasuredPressure(eventData.value, 'upstream', eventData); - }); - - // downstream pressure handling - sensor.measurements.emitter.on('pressure.measured.downstream', (eventData) => { - this.logger.debug(`🔄 Downstream pressure from ${eventData.childName}: ${eventData.value} ${eventData.unit}`); - // Update the measured pressure - this.updateMeasuredPressure(eventData.value, 'downstream', eventData); - }); - break; - case 'flow': - this.logger.debug(`Registering flow events for sensor: ${sensor.config.general.name}`); - // upstream flow handling - sensors.forEach(sensor => { - sensor.measurements.emitter.on('flow.measured.upstream', (eventData) => { - this.logger.debug(`🔄 Upstream flow from ${eventData.childName}: ${eventData.value} ${eventData.unit}`); - this.updateMeasuredFlow(eventData.value, 'upstream', eventData); - }); - // downstream flow handling - sensor.measurements.emitter.on('flow.measured.downstream', (eventData) => { - this.logger.debug(`🔄 Downstream flow from ${eventData.childName}: ${eventData.value} ${eventData.unit}`); - this.updateMeasuredFlow(eventData.value, 'downstream', eventData); - }); - }); - break; - - default: - this.logger.warn(`Unknown sensor type: ${sensor.config.asset.type}. No events registered.`); - break; - } - }); - - // ✅ Log registration summary - this.logger.info(`✅ Event listeners registered for ${sensors.length} measurement sensors`); - - // ✅ Optional: Debug child structure - this.childRegistrationUtils.logChildStructure(); + this.logger.debug(`Found ${sensors.length} sensors to register events for`); + + // Group sensors by type and position to detect duplicates + const sensorGroups = new Map(); // Key: "type_position", Value: array of sensors + + sensors.forEach(sensor => { + const position = sensor.config.functionality.positionVsParent; + const measurementType = sensor.config.asset.type; + const key = `${measurementType}_${position}`; + + if (!sensorGroups.has(key)) { + sensorGroups.set(key, []); } + sensorGroups.get(key).push(sensor); + }); + + // Set up event handlers based on whether we have single or multiple sensors + sensorGroups.forEach((sensorsArray, key) => { + const [measurementType, position] = key.split('_'); + + if (sensorsArray.length === 1) { + // ✅ Single sensor - direct handler + const sensor = sensorsArray[0]; + this._registerSingleSensorEvents(sensor, measurementType, position); + + } else { + // ✅ Multiple sensors - averaging handler with warning + const sensorNames = sensorsArray.map(s => s.config.general.name).join(', '); + this.logger.warn(`⚠️ Multiple ${measurementType} sensors at ${position} position: ${sensorNames}. Using automatic averaging.`); + + this._registerMultipleSensorEvents(sensorsArray, measurementType, position); + } + }); + + this.logger.info(`✅ Event listeners registered for ${sensors.length} measurement sensors`); + this.childRegistrationUtils.logChildStructure(); +} + +// Handle single sensor (no averaging needed) +_registerSingleSensorEvents(sensor, measurementType, position) { + const sensorName = sensor.config.general.name; + const eventName = `${measurementType}.measured.${position}`; + + this.logger.debug(`Registering single ${measurementType} sensor: ${sensorName} at ${position}`); + + sensor.measurements.emitter.on(eventName, (eventData) => { + this.logger.debug(`🔄 ${position} ${measurementType} from ${eventData.childName}: ${eventData.value} ${eventData.unit}`); + + // Store directly in parent's measurement container + this.measurements + .type(measurementType) + .variant("measured") + .position(position) + .value(eventData.value, eventData.timestamp, eventData.unit); + + // Call the appropriate handler + this._callMeasurementHandler(measurementType, eventData.value, position, eventData); + }); + + this.logger.debug(`✅ Registered single sensor event: ${eventName}`); +} + +// Handle multiple sensors (with automatic averaging) +_registerMultipleSensorEvents(sensorsArray, measurementType, position) { + const eventName = `${measurementType}.measured.${position}`; + const sensorCount = sensorsArray.length; + + this.logger.debug(`Registering ${sensorCount} ${measurementType} sensors at ${position} with averaging`); + + // Register event handler for each sensor in the group + sensorsArray.forEach(sensor => { + sensor.measurements.emitter.on(eventName, (eventData) => { + this.logger.debug(`🔄 ${position} ${measurementType} from ${eventData.childName}: ${eventData.value} ${eventData.unit} (will be averaged)`); + + // Store individual sensor value in parent's measurement container + this.measurements + .type(measurementType) + .variant("measured") + .position(position) + .value(eventData.value, eventData.timestamp, eventData.unit); + + // Get the average from measurement container + const averageValue = this.measurements + .type(measurementType) + .variant("measured") + .position(position) + .getAverage(); + + this.logger.debug(`📊 Average ${position} ${measurementType} from ${sensorCount} sensors: ${averageValue}`); + + // Call the handler with the averaged value + this._callMeasurementHandler(measurementType, averageValue, position, eventData); + }); + }); + + this.logger.debug(`✅ Registered ${sensorCount} sensor events with averaging: ${eventName}`); +} + +// Centralized handler dispatcher +_callMeasurementHandler(measurementType, value, position, context) { + switch (measurementType) { + case 'pressure': + this.updateMeasuredPressure(value, position, context); + break; + + case 'flow': + this.updateMeasuredFlow(value, position, context); + break; + + case 'temperature': + this.updateMeasuredTemperature(value, position, context); + break; + + default: + this.logger.warn(`No handler for measurement type: ${measurementType}`); + // Generic handler - just update position + this.updatePosition(); + break; + } +} + +//---------------- END child stuff -------------// // Method to assess drift using errorMetrics assessDrift(measurement, processMin, processMax) { @@ -522,8 +594,8 @@ class Machine { // Store in parent's measurement container (your existing logic) this.measurements.type("pressure").variant("measured").position(position).value(value, context.timestamp, context.unit); - - // Your existing logic + + // Determine what kind of value to use as pressure (upstream , downstream or difference) const pressure = this.getMeasuredPressure(); this.updatePosition();