@enyo-energy/energy-app-sdk 0.0.38 → 0.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -83,7 +83,7 @@ export declare class ApplianceManager {
83
83
  * @param appliance The appliance to cache
84
84
  * @param networkDevice Optional network device for identifier extraction
85
85
  */
86
- private updateCache;
86
+ protected updateCache(appliance: EnyoAppliance, networkDevice?: EnyoNetworkDevice): void;
87
87
  /**
88
88
  * Clears the internal cache.
89
89
  */
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryApplianceManager = void 0;
4
+ const enyo_appliance_js_1 = require("../../types/enyo-appliance.cjs");
5
+ const appliance_manager_js_1 = require("./appliance-manager.cjs");
6
+ /**
7
+ * Demo implementation of ApplianceManager that stores all data in memory.
8
+ * This class provides the same interface as ApplianceManager but doesn't
9
+ * use energyApp.useAppliances() for persistence.
10
+ */
11
+ class InMemoryApplianceManager extends appliance_manager_js_1.ApplianceManager {
12
+ memoryStore = new Map();
13
+ nextId = 1;
14
+ networkDevicesStore = new Map();
15
+ /**
16
+ * Creates a new DemoApplianceManager instance.
17
+ * @param energyApp The EnergyApp instance (not used for persistence in demo)
18
+ * @param config Configuration options for the manager
19
+ */
20
+ constructor(energyApp, config) {
21
+ super(energyApp, config);
22
+ }
23
+ /**
24
+ * Creates or updates an appliance in memory.
25
+ * @param config The appliance configuration
26
+ * @param existingApplianceId Optional ID of an existing appliance to update
27
+ * @returns The ID of the created or updated appliance
28
+ */
29
+ async createOrUpdateAppliance(config, existingApplianceId) {
30
+ const applianceId = existingApplianceId || `appliance_${this.nextId++}`;
31
+ // Build network device IDs list
32
+ const networkDeviceIds = config.networkDevices?.map(d => d.id) ?? [];
33
+ // Get existing metadata if updating
34
+ const existingAppliance = existingApplianceId ? this.memoryStore.get(existingApplianceId) : null;
35
+ // Merge metadata with defaults and existing values
36
+ const metadata = {
37
+ connectionType: config.metadata?.connectionType ||
38
+ existingAppliance?.metadata?.connectionType ||
39
+ enyo_appliance_js_1.EnyoApplianceConnectionType.Connector,
40
+ state: config.metadata?.state ||
41
+ existingAppliance?.metadata?.state ||
42
+ enyo_appliance_js_1.EnyoApplianceStateEnum.Connected,
43
+ ...config.metadata
44
+ };
45
+ // Build appliance data
46
+ const applianceData = {
47
+ id: applianceId,
48
+ name: config.name,
49
+ type: config.type,
50
+ networkDeviceIds,
51
+ metadata,
52
+ ...(config.topology && { topology: config.topology })
53
+ };
54
+ // Add type-specific metadata
55
+ if (config.typeMetadata) {
56
+ Object.assign(applianceData, config.typeMetadata);
57
+ }
58
+ // Save to memory store
59
+ this.memoryStore.set(applianceId, applianceData);
60
+ // Store network devices if provided
61
+ if (config.networkDevices) {
62
+ this.networkDevicesStore.set(applianceId, config.networkDevices);
63
+ }
64
+ // Update cache
65
+ this.updateCache(applianceData, config.networkDevices?.[0]);
66
+ console.log(`[DEMO] ${existingApplianceId ? 'Updated' : 'Created'} appliance ${applianceId} of type ${config.type}`);
67
+ return applianceId;
68
+ }
69
+ /**
70
+ * Gets an appliance by ID from memory.
71
+ * @param applianceId The ID of the appliance
72
+ * @returns The appliance or null if not found
73
+ */
74
+ async getApplianceById(applianceId) {
75
+ return this.memoryStore.get(applianceId) || null;
76
+ }
77
+ /**
78
+ * Gets all appliances from memory.
79
+ * @returns Array of all appliances
80
+ */
81
+ async getAllAppliances() {
82
+ return Array.from(this.memoryStore.values());
83
+ }
84
+ /**
85
+ * Gets network devices associated with an appliance.
86
+ * @param appliance The appliance
87
+ * @returns Array of network devices
88
+ */
89
+ async getNetworkDevicesForApplianceDemo(appliance) {
90
+ return this.networkDevicesStore.get(appliance.id) || [];
91
+ }
92
+ /**
93
+ * Finds appliances by their identifier using the configured strategy.
94
+ * @param identifier The identifier to search for
95
+ * @returns Array of matching appliances
96
+ */
97
+ async findByIdentifier(identifier) {
98
+ const matches = [];
99
+ const strategy = this.getIdentifierStrategy();
100
+ for (const appliance of this.memoryStore.values()) {
101
+ const networkDevices = await this.getNetworkDevicesForApplianceDemo(appliance);
102
+ const extractedId = strategy.extract(appliance, networkDevices[0]);
103
+ if (extractedId === identifier) {
104
+ matches.push(appliance);
105
+ this.updateCache(appliance, networkDevices[0]);
106
+ }
107
+ }
108
+ return matches;
109
+ }
110
+ /**
111
+ * Finds an appliance using multiple strategies.
112
+ * @param searchValue The value to search for
113
+ * @param strategies Array of strategies to try
114
+ * @returns The first matching result or undefined
115
+ */
116
+ async findWithStrategies(searchValue, strategies) {
117
+ for (const strategy of strategies) {
118
+ for (const appliance of this.memoryStore.values()) {
119
+ const networkDevices = await this.getNetworkDevicesForApplianceDemo(appliance);
120
+ const identifier = strategy.extract(appliance, networkDevices[0]);
121
+ if (identifier === searchValue) {
122
+ return {
123
+ appliance,
124
+ identifier,
125
+ strategy: strategy.name
126
+ };
127
+ }
128
+ }
129
+ }
130
+ return undefined;
131
+ }
132
+ /**
133
+ * Gets all appliances of a specific type.
134
+ * @param type The appliance type to filter by
135
+ * @returns Array of appliances of the specified type
136
+ */
137
+ async getAppliancesByType(type) {
138
+ return Array.from(this.memoryStore.values()).filter(a => a.type === type);
139
+ }
140
+ /**
141
+ * Updates the state of an appliance in memory.
142
+ * @param applianceId The ID of the appliance to update
143
+ * @param connectionType The new connection type
144
+ * @param state The new state
145
+ */
146
+ async updateApplianceState(applianceId, connectionType, state) {
147
+ const appliance = this.memoryStore.get(applianceId);
148
+ if (appliance) {
149
+ appliance.metadata = {
150
+ ...appliance.metadata,
151
+ connectionType,
152
+ state
153
+ };
154
+ this.memoryStore.set(applianceId, appliance);
155
+ this.updateCache(appliance);
156
+ console.log(`[DEMO] Updated appliance ${applianceId} state to ${state}`);
157
+ }
158
+ else {
159
+ throw new Error(`Appliance ${applianceId} not found`);
160
+ }
161
+ }
162
+ /**
163
+ * Updates metadata for an appliance in memory.
164
+ * @param applianceId The ID of the appliance
165
+ * @param metadata The metadata to update
166
+ */
167
+ async updateApplianceMetadata(applianceId, metadata) {
168
+ const appliance = this.memoryStore.get(applianceId);
169
+ if (appliance) {
170
+ appliance.metadata = {
171
+ ...appliance.metadata,
172
+ ...metadata
173
+ };
174
+ this.memoryStore.set(applianceId, appliance);
175
+ this.updateCache(appliance);
176
+ console.log(`[DEMO] Updated metadata for appliance ${applianceId}`);
177
+ }
178
+ else {
179
+ throw new Error(`Appliance ${applianceId} not found`);
180
+ }
181
+ }
182
+ /**
183
+ * Removes an appliance from memory.
184
+ * @param applianceId The ID of the appliance to remove
185
+ */
186
+ async removeAppliance(applianceId) {
187
+ if (this.memoryStore.has(applianceId)) {
188
+ this.memoryStore.delete(applianceId);
189
+ this.networkDevicesStore.delete(applianceId);
190
+ // Clean up cache (from parent class)
191
+ this.clearCache();
192
+ console.log(`[DEMO] Removed appliance ${applianceId}`);
193
+ }
194
+ else {
195
+ throw new Error(`Appliance ${applianceId} not found`);
196
+ }
197
+ }
198
+ /**
199
+ * Performs a bulk update on multiple appliances in memory.
200
+ * @param updates Array of updates to perform
201
+ * @returns Results of the bulk update operation
202
+ */
203
+ async bulkUpdate(updates) {
204
+ const succeeded = [];
205
+ const failed = [];
206
+ for (const update of updates) {
207
+ try {
208
+ const appliance = this.memoryStore.get(update.applianceId);
209
+ if (appliance) {
210
+ const updatedAppliance = {
211
+ ...appliance,
212
+ ...update.data,
213
+ id: appliance.id // Ensure ID is preserved
214
+ };
215
+ this.memoryStore.set(update.applianceId, updatedAppliance);
216
+ this.updateCache(updatedAppliance);
217
+ succeeded.push(update.applianceId);
218
+ }
219
+ else {
220
+ failed.push(update.applianceId);
221
+ }
222
+ }
223
+ catch (error) {
224
+ console.error(`[DEMO] Bulk update failed for ${update.applianceId}: ${error}`);
225
+ failed.push(update.applianceId);
226
+ }
227
+ }
228
+ console.log(`[DEMO] Bulk update completed: ${succeeded.length} succeeded, ${failed.length} failed`);
229
+ return { succeeded, failed };
230
+ }
231
+ /**
232
+ * Gets statistics about the managed appliances in memory.
233
+ * @returns Statistics object
234
+ */
235
+ async getStatistics() {
236
+ const appliances = Array.from(this.memoryStore.values());
237
+ const byType = {};
238
+ const byState = {};
239
+ for (const appliance of appliances) {
240
+ // Count by type
241
+ byType[appliance.type] = (byType[appliance.type] ?? 0) + 1;
242
+ // Count by state
243
+ const state = appliance.metadata?.state ?? 'unknown';
244
+ byState[state] = (byState[state] ?? 0) + 1;
245
+ }
246
+ return {
247
+ total: appliances.length,
248
+ byType,
249
+ byState,
250
+ cached: this.memoryStore.size
251
+ };
252
+ }
253
+ /**
254
+ * Refreshes the cache with all appliances from memory.
255
+ */
256
+ async refreshCache() {
257
+ this.clearCache();
258
+ for (const appliance of this.memoryStore.values()) {
259
+ const networkDevices = await this.getNetworkDevicesForApplianceDemo(appliance);
260
+ this.updateCache(appliance, networkDevices[0]);
261
+ }
262
+ }
263
+ /**
264
+ * Clears all data from memory (for testing purposes).
265
+ */
266
+ clearAllData() {
267
+ this.memoryStore.clear();
268
+ this.networkDevicesStore.clear();
269
+ this.clearCache();
270
+ this.nextId = 1;
271
+ console.log('[DEMO] All data cleared from memory');
272
+ }
273
+ /**
274
+ * Gets the current size of the memory store.
275
+ * @returns The number of appliances in memory
276
+ */
277
+ getMemoryStoreSize() {
278
+ return this.memoryStore.size;
279
+ }
280
+ }
281
+ exports.InMemoryApplianceManager = InMemoryApplianceManager;
@@ -0,0 +1,119 @@
1
+ import type { EnergyApp } from "../../index.cjs";
2
+ import type { EnyoNetworkDevice } from "../../types/enyo-network-device.cjs";
3
+ import { EnyoAppliance, EnyoApplianceConnectionType, EnyoApplianceMetadata, EnyoApplianceStateEnum, EnyoApplianceTypeEnum } from "../../types/enyo-appliance.cjs";
4
+ import { ApplianceConfig, ApplianceManager, ApplianceManagerConfig, FindResult } from "./appliance-manager.cjs";
5
+ import { IdentifierStrategy } from "./identifier-strategies.cjs";
6
+ /**
7
+ * Demo implementation of ApplianceManager that stores all data in memory.
8
+ * This class provides the same interface as ApplianceManager but doesn't
9
+ * use energyApp.useAppliances() for persistence.
10
+ */
11
+ export declare class InMemoryApplianceManager extends ApplianceManager {
12
+ private memoryStore;
13
+ private nextId;
14
+ private networkDevicesStore;
15
+ /**
16
+ * Creates a new DemoApplianceManager instance.
17
+ * @param energyApp The EnergyApp instance (not used for persistence in demo)
18
+ * @param config Configuration options for the manager
19
+ */
20
+ constructor(energyApp: EnergyApp, config?: ApplianceManagerConfig);
21
+ /**
22
+ * Creates or updates an appliance in memory.
23
+ * @param config The appliance configuration
24
+ * @param existingApplianceId Optional ID of an existing appliance to update
25
+ * @returns The ID of the created or updated appliance
26
+ */
27
+ createOrUpdateAppliance(config: ApplianceConfig, existingApplianceId?: string): Promise<string>;
28
+ /**
29
+ * Gets an appliance by ID from memory.
30
+ * @param applianceId The ID of the appliance
31
+ * @returns The appliance or null if not found
32
+ */
33
+ getApplianceById(applianceId: string): Promise<EnyoAppliance | null>;
34
+ /**
35
+ * Gets all appliances from memory.
36
+ * @returns Array of all appliances
37
+ */
38
+ getAllAppliances(): Promise<EnyoAppliance[]>;
39
+ /**
40
+ * Gets network devices associated with an appliance.
41
+ * @param appliance The appliance
42
+ * @returns Array of network devices
43
+ */
44
+ protected getNetworkDevicesForApplianceDemo(appliance: EnyoAppliance): Promise<EnyoNetworkDevice[]>;
45
+ /**
46
+ * Finds appliances by their identifier using the configured strategy.
47
+ * @param identifier The identifier to search for
48
+ * @returns Array of matching appliances
49
+ */
50
+ findByIdentifier(identifier: string): Promise<EnyoAppliance[]>;
51
+ /**
52
+ * Finds an appliance using multiple strategies.
53
+ * @param searchValue The value to search for
54
+ * @param strategies Array of strategies to try
55
+ * @returns The first matching result or undefined
56
+ */
57
+ findWithStrategies(searchValue: string, strategies: IdentifierStrategy[]): Promise<FindResult | undefined>;
58
+ /**
59
+ * Gets all appliances of a specific type.
60
+ * @param type The appliance type to filter by
61
+ * @returns Array of appliances of the specified type
62
+ */
63
+ getAppliancesByType(type: EnyoApplianceTypeEnum): Promise<EnyoAppliance[]>;
64
+ /**
65
+ * Updates the state of an appliance in memory.
66
+ * @param applianceId The ID of the appliance to update
67
+ * @param connectionType The new connection type
68
+ * @param state The new state
69
+ */
70
+ updateApplianceState(applianceId: string, connectionType: EnyoApplianceConnectionType, state: EnyoApplianceStateEnum): Promise<void>;
71
+ /**
72
+ * Updates metadata for an appliance in memory.
73
+ * @param applianceId The ID of the appliance
74
+ * @param metadata The metadata to update
75
+ */
76
+ updateApplianceMetadata(applianceId: string, metadata: Partial<EnyoApplianceMetadata> & {
77
+ connectionType: EnyoApplianceConnectionType;
78
+ }): Promise<void>;
79
+ /**
80
+ * Removes an appliance from memory.
81
+ * @param applianceId The ID of the appliance to remove
82
+ */
83
+ removeAppliance(applianceId: string): Promise<void>;
84
+ /**
85
+ * Performs a bulk update on multiple appliances in memory.
86
+ * @param updates Array of updates to perform
87
+ * @returns Results of the bulk update operation
88
+ */
89
+ bulkUpdate(updates: Array<{
90
+ applianceId: string;
91
+ data: Partial<Omit<EnyoAppliance, 'id'>>;
92
+ }>): Promise<{
93
+ succeeded: string[];
94
+ failed: string[];
95
+ }>;
96
+ /**
97
+ * Gets statistics about the managed appliances in memory.
98
+ * @returns Statistics object
99
+ */
100
+ getStatistics(): Promise<{
101
+ total: number;
102
+ byType: Record<string, number>;
103
+ byState: Record<string, number>;
104
+ cached: number;
105
+ }>;
106
+ /**
107
+ * Refreshes the cache with all appliances from memory.
108
+ */
109
+ refreshCache(): Promise<void>;
110
+ /**
111
+ * Clears all data from memory (for testing purposes).
112
+ */
113
+ clearAllData(): void;
114
+ /**
115
+ * Gets the current size of the memory store.
116
+ * @returns The number of appliances in memory
117
+ */
118
+ getMemoryStoreSize(): number;
119
+ }
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DemoDataBus = void 0;
4
+ /**
5
+ * Demo implementation of EnergyAppDataBus that logs messages to console
6
+ * and maintains an in-memory message history and listener registry.
7
+ */
8
+ class DemoDataBus {
9
+ enableConsoleLogging;
10
+ messageHistory = [];
11
+ listeners = new Map();
12
+ nextListenerId = 1;
13
+ maxHistorySize = 1000;
14
+ /**
15
+ * Creates a new DemoDataBus instance.
16
+ * @param enableConsoleLogging Whether to log messages to console (default: true)
17
+ * @param maxHistorySize Maximum number of messages to keep in history (default: 1000)
18
+ */
19
+ constructor(enableConsoleLogging = true, maxHistorySize) {
20
+ this.enableConsoleLogging = enableConsoleLogging;
21
+ if (maxHistorySize !== undefined) {
22
+ this.maxHistorySize = maxHistorySize;
23
+ }
24
+ }
25
+ /**
26
+ * Sends messages to the data bus (logs to console and notifies listeners).
27
+ * @param messages Array of messages to send
28
+ * @param options Optional send options (not used in demo)
29
+ */
30
+ sendMessage(messages, options) {
31
+ for (const message of messages) {
32
+ // Log to console if enabled
33
+ if (this.enableConsoleLogging) {
34
+ console.log('[DEMO DataBus] Message sent:', {
35
+ id: message.id,
36
+ type: message.message,
37
+ applianceId: message.applianceId,
38
+ timestamp: message.timestampIso,
39
+ data: message.data
40
+ });
41
+ }
42
+ // Add to history
43
+ this.addToHistory(message);
44
+ // Notify listeners
45
+ this.notifyListeners(message);
46
+ }
47
+ }
48
+ /**
49
+ * Sends an answer message to the data bus.
50
+ * @param answer The answer message to send
51
+ * @param options Optional send options (not used in demo)
52
+ */
53
+ sendAnswer(answer, options) {
54
+ // Log to console if enabled
55
+ if (this.enableConsoleLogging) {
56
+ console.log('[DEMO DataBus] Answer sent:', {
57
+ id: answer.id,
58
+ type: answer.message,
59
+ status: answer.data.status,
60
+ applianceId: answer.applianceId,
61
+ timestamp: answer.timestampIso
62
+ });
63
+ }
64
+ // Add to history
65
+ this.addToHistory(answer);
66
+ // Notify listeners
67
+ this.notifyListeners(answer);
68
+ }
69
+ /**
70
+ * Registers a listener for specific message types.
71
+ * @param types Array of message types to listen for
72
+ * @param listener Callback function to invoke when matching messages are received
73
+ * @returns Listener ID that can be used to unsubscribe
74
+ */
75
+ listenForMessages(types, listener) {
76
+ const listenerId = `listener_${this.nextListenerId++}`;
77
+ this.listeners.set(listenerId, {
78
+ types,
79
+ callback: listener
80
+ });
81
+ if (this.enableConsoleLogging) {
82
+ console.log(`[DEMO DataBus] Listener ${listenerId} registered for types:`, types);
83
+ }
84
+ return listenerId;
85
+ }
86
+ /**
87
+ * Unsubscribes a listener from the data bus.
88
+ * @param listenerId The ID of the listener to unsubscribe
89
+ */
90
+ unsubscribe(listenerId) {
91
+ if (this.listeners.has(listenerId)) {
92
+ const listener = this.listeners.get(listenerId);
93
+ this.listeners.delete(listenerId);
94
+ if (this.enableConsoleLogging) {
95
+ console.log(`[DEMO DataBus] Listener ${listenerId} unsubscribed`);
96
+ }
97
+ }
98
+ else {
99
+ console.warn(`[DEMO DataBus] Attempted to unsubscribe non-existent listener: ${listenerId}`);
100
+ }
101
+ }
102
+ /**
103
+ * Adds a message to the history, maintaining the maximum size limit.
104
+ * @param message The message to add to history
105
+ */
106
+ addToHistory(message) {
107
+ this.messageHistory.push(message);
108
+ // Trim history if it exceeds the maximum size
109
+ if (this.messageHistory.length > this.maxHistorySize) {
110
+ this.messageHistory = this.messageHistory.slice(-this.maxHistorySize);
111
+ }
112
+ }
113
+ /**
114
+ * Notifies all registered listeners that match the message type.
115
+ * @param message The message to notify listeners about
116
+ */
117
+ notifyListeners(message) {
118
+ for (const [listenerId, listener] of this.listeners.entries()) {
119
+ if (listener.types.includes(message.message)) {
120
+ try {
121
+ listener.callback(message);
122
+ if (this.enableConsoleLogging) {
123
+ console.log(`[DEMO DataBus] Notified listener ${listenerId} of ${message.message}`);
124
+ }
125
+ }
126
+ catch (error) {
127
+ console.error(`[DEMO DataBus] Error in listener ${listenerId}:`, error);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ /**
133
+ * Gets the message history.
134
+ * @param limit Optional limit on the number of messages to return
135
+ * @returns Array of messages from history
136
+ */
137
+ getMessageHistory(limit) {
138
+ if (limit && limit > 0) {
139
+ return this.messageHistory.slice(-limit);
140
+ }
141
+ return [...this.messageHistory];
142
+ }
143
+ /**
144
+ * Gets messages of specific types from history.
145
+ * @param types Array of message types to filter by
146
+ * @param limit Optional limit on the number of messages to return
147
+ * @returns Filtered array of messages
148
+ */
149
+ getMessagesByType(types, limit) {
150
+ const filtered = this.messageHistory.filter(msg => types.includes(msg.message));
151
+ if (limit && limit > 0) {
152
+ return filtered.slice(-limit);
153
+ }
154
+ return filtered;
155
+ }
156
+ /**
157
+ * Gets messages for a specific appliance from history.
158
+ * @param applianceId The appliance ID to filter by
159
+ * @param limit Optional limit on the number of messages to return
160
+ * @returns Filtered array of messages
161
+ */
162
+ getMessagesByAppliance(applianceId, limit) {
163
+ const filtered = this.messageHistory.filter(msg => msg.applianceId === applianceId);
164
+ if (limit && limit > 0) {
165
+ return filtered.slice(-limit);
166
+ }
167
+ return filtered;
168
+ }
169
+ /**
170
+ * Clears the message history.
171
+ */
172
+ clearHistory() {
173
+ this.messageHistory = [];
174
+ if (this.enableConsoleLogging) {
175
+ console.log('[DEMO DataBus] Message history cleared');
176
+ }
177
+ }
178
+ /**
179
+ * Gets the current number of registered listeners.
180
+ * @returns The number of active listeners
181
+ */
182
+ getListenerCount() {
183
+ return this.listeners.size;
184
+ }
185
+ /**
186
+ * Gets information about all registered listeners.
187
+ * @returns Array of listener information
188
+ */
189
+ getListenerInfo() {
190
+ return Array.from(this.listeners.entries()).map(([id, listener]) => ({
191
+ id,
192
+ types: listener.types
193
+ }));
194
+ }
195
+ /**
196
+ * Enables or disables console logging.
197
+ * @param enabled Whether to enable console logging
198
+ */
199
+ setConsoleLogging(enabled) {
200
+ this.enableConsoleLogging = enabled;
201
+ console.log(`[DEMO DataBus] Console logging ${enabled ? 'enabled' : 'disabled'}`);
202
+ }
203
+ /**
204
+ * Simulates receiving a message from an external source.
205
+ * This is useful for testing listeners without actually sending messages.
206
+ * @param message The message to simulate receiving
207
+ */
208
+ simulateIncomingMessage(message) {
209
+ if (this.enableConsoleLogging) {
210
+ console.log('[DEMO DataBus] Simulating incoming message:', {
211
+ id: message.id,
212
+ type: message.message,
213
+ applianceId: message.applianceId
214
+ });
215
+ }
216
+ // Add to history
217
+ this.addToHistory(message);
218
+ // Notify listeners
219
+ this.notifyListeners(message);
220
+ }
221
+ /**
222
+ * Gets statistics about the data bus usage.
223
+ * @returns Statistics object
224
+ */
225
+ getStatistics() {
226
+ const now = new Date();
227
+ const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
228
+ const messagesByType = {};
229
+ let messagesInLastHour = 0;
230
+ for (const message of this.messageHistory) {
231
+ // Count by type
232
+ messagesByType[message.message] = (messagesByType[message.message] ?? 0) + 1;
233
+ // Count messages in last hour
234
+ if (new Date(message.timestampIso) > oneHourAgo) {
235
+ messagesInLastHour++;
236
+ }
237
+ }
238
+ return {
239
+ totalMessages: this.messageHistory.length,
240
+ messagesByType,
241
+ activeListeners: this.listeners.size,
242
+ messagesInLastHour
243
+ };
244
+ }
245
+ }
246
+ exports.DemoDataBus = DemoDataBus;