@enyo-energy/energy-app-sdk 0.0.37 → 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.
- package/dist/cjs/implementations/appliances/appliance-manager.cjs +399 -0
- package/dist/cjs/implementations/appliances/appliance-manager.d.cts +191 -0
- package/dist/cjs/implementations/appliances/identifier-strategies.cjs +180 -0
- package/dist/cjs/implementations/appliances/identifier-strategies.d.cts +140 -0
- package/dist/cjs/implementations/appliances/in-memory-appliance-manager.cjs +281 -0
- package/dist/cjs/implementations/appliances/in-memory-appliance-manager.d.cts +119 -0
- package/dist/cjs/implementations/data-bus/demo-data-bus.cjs +246 -0
- package/dist/cjs/implementations/data-bus/demo-data-bus.d.cts +111 -0
- package/dist/cjs/implementations/modbus/EnergyAppModbusDataTypeConverter.d.cts +2 -2
- package/dist/cjs/implementations/modbus/EnergyAppModbusFaultTolerantReader.cjs +76 -0
- package/dist/cjs/implementations/modbus/EnergyAppModbusFaultTolerantReader.d.cts +31 -1
- package/dist/cjs/implementations/modbus/EnergyAppModbusRegisterMapper.d.cts +2 -2
- package/dist/cjs/implementations/modbus/interfaces.d.cts +7 -93
- package/dist/cjs/implementations/modbus/sunspec/sunspec-devices.cjs +342 -0
- package/dist/cjs/implementations/modbus/sunspec/sunspec-devices.d.cts +95 -0
- package/dist/cjs/implementations/modbus/sunspec/sunspec-modbus-client.cjs +433 -0
- package/dist/cjs/implementations/modbus/sunspec/sunspec-modbus-client.d.cts +171 -0
- package/dist/cjs/index.cjs +2 -3
- package/dist/cjs/index.d.cts +2 -3
- package/dist/cjs/types/enyo-data-bus-value.d.cts +2 -1
- package/dist/cjs/version.cjs +1 -1
- package/dist/cjs/version.d.cts +1 -1
- package/dist/implementations/appliances/appliance-manager.d.ts +191 -0
- package/dist/implementations/appliances/appliance-manager.js +395 -0
- package/dist/implementations/appliances/demo-appliance-manager.d.ts +118 -0
- package/dist/implementations/appliances/demo-appliance-manager.js +277 -0
- package/dist/implementations/appliances/identifier-strategies.d.ts +140 -0
- package/dist/implementations/appliances/identifier-strategies.js +171 -0
- package/dist/implementations/appliances/in-memory-appliance-manager.d.ts +119 -0
- package/dist/implementations/appliances/in-memory-appliance-manager.js +277 -0
- package/dist/implementations/data-bus/demo-data-bus.d.ts +111 -0
- package/dist/implementations/data-bus/demo-data-bus.js +242 -0
- package/dist/implementations/modbus/EnergyAppModbusDataTypeConverter.d.ts +2 -2
- package/dist/implementations/modbus/EnergyAppModbusFaultTolerantReader.d.ts +31 -1
- package/dist/implementations/modbus/EnergyAppModbusFaultTolerantReader.js +76 -0
- package/dist/implementations/modbus/EnergyAppModbusRegisterMapper.d.ts +2 -2
- package/dist/implementations/modbus/interfaces.d.ts +7 -93
- package/dist/implementations/modbus/sunspec/sunspec-devices.d.ts +95 -0
- package/dist/implementations/modbus/sunspec/sunspec-devices.js +335 -0
- package/dist/implementations/modbus/sunspec/sunspec-modbus-client.d.ts +171 -0
- package/dist/implementations/modbus/sunspec/sunspec-modbus-client.js +429 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -3
- package/dist/types/enyo-data-bus-value.d.ts +2 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strategy that uses the network device ID as the identifier.
|
|
3
|
+
* This is the default strategy for most appliances.
|
|
4
|
+
*/
|
|
5
|
+
export class NetworkDeviceIdStrategy {
|
|
6
|
+
name = 'networkDeviceId';
|
|
7
|
+
/**
|
|
8
|
+
* Extracts the network device ID.
|
|
9
|
+
* @param appliance The appliance (not used in this strategy)
|
|
10
|
+
* @param networkDevice The network device to get the ID from
|
|
11
|
+
* @returns The network device ID or undefined
|
|
12
|
+
*/
|
|
13
|
+
extract(appliance, networkDevice) {
|
|
14
|
+
return networkDevice?.id;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Strategy that uses the appliance's serial number as the identifier.
|
|
19
|
+
* Useful when appliances can move between network devices.
|
|
20
|
+
*/
|
|
21
|
+
export class SerialNumberStrategy {
|
|
22
|
+
name = 'serialNumber';
|
|
23
|
+
/**
|
|
24
|
+
* Extracts the serial number from the appliance metadata.
|
|
25
|
+
* @param appliance The appliance to extract the serial number from
|
|
26
|
+
* @returns The serial number or undefined
|
|
27
|
+
*/
|
|
28
|
+
extract(appliance) {
|
|
29
|
+
return appliance.metadata?.serialNumber;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Strategy that uses a custom metadata field as the identifier.
|
|
34
|
+
* Allows using any field from the appliance metadata.
|
|
35
|
+
*/
|
|
36
|
+
export class CustomMetadataStrategy {
|
|
37
|
+
fieldName;
|
|
38
|
+
name;
|
|
39
|
+
/**
|
|
40
|
+
* Creates a strategy that uses a custom metadata field.
|
|
41
|
+
* @param fieldName The name of the metadata field to use as identifier
|
|
42
|
+
*/
|
|
43
|
+
constructor(fieldName) {
|
|
44
|
+
this.fieldName = fieldName;
|
|
45
|
+
this.name = `metadata.${String(fieldName)}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Extracts the custom field value from the appliance metadata.
|
|
49
|
+
* @param appliance The appliance to extract the field from
|
|
50
|
+
* @returns The field value or undefined
|
|
51
|
+
*/
|
|
52
|
+
extract(appliance) {
|
|
53
|
+
const value = appliance.metadata?.[this.fieldName];
|
|
54
|
+
return value !== undefined ? String(value) : undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Strategy that combines multiple identifiers to create a composite key.
|
|
59
|
+
* Useful when a single identifier is not unique enough.
|
|
60
|
+
*/
|
|
61
|
+
export class CompositeIdentifierStrategy {
|
|
62
|
+
strategies;
|
|
63
|
+
separator;
|
|
64
|
+
name;
|
|
65
|
+
/**
|
|
66
|
+
* Creates a strategy that combines multiple strategies.
|
|
67
|
+
* @param strategies The strategies to combine
|
|
68
|
+
* @param separator The separator to use between identifier parts
|
|
69
|
+
*/
|
|
70
|
+
constructor(strategies, separator = ':') {
|
|
71
|
+
this.strategies = strategies;
|
|
72
|
+
this.separator = separator;
|
|
73
|
+
this.name = `composite(${strategies.map(s => s.name).join('+')})`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Extracts and combines identifiers from multiple strategies.
|
|
77
|
+
* @param appliance The appliance to extract identifiers from
|
|
78
|
+
* @param networkDevice The network device if available
|
|
79
|
+
* @returns The combined identifier or undefined if any part is missing
|
|
80
|
+
*/
|
|
81
|
+
extract(appliance, networkDevice) {
|
|
82
|
+
const parts = [];
|
|
83
|
+
for (const strategy of this.strategies) {
|
|
84
|
+
const value = strategy.extract(appliance, networkDevice);
|
|
85
|
+
if (!value) {
|
|
86
|
+
return undefined; // All parts must be present
|
|
87
|
+
}
|
|
88
|
+
parts.push(value);
|
|
89
|
+
}
|
|
90
|
+
return parts.join(this.separator);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Strategy that tries multiple strategies in order and uses the first available identifier.
|
|
95
|
+
* Useful for fallback scenarios.
|
|
96
|
+
*/
|
|
97
|
+
export class FallbackIdentifierStrategy {
|
|
98
|
+
strategies;
|
|
99
|
+
name;
|
|
100
|
+
/**
|
|
101
|
+
* Creates a strategy that tries multiple strategies in order.
|
|
102
|
+
* @param strategies The strategies to try in order
|
|
103
|
+
*/
|
|
104
|
+
constructor(strategies) {
|
|
105
|
+
this.strategies = strategies;
|
|
106
|
+
this.name = `fallback(${strategies.map(s => s.name).join('|')})`;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Tries strategies in order and returns the first available identifier.
|
|
110
|
+
* @param appliance The appliance to extract identifiers from
|
|
111
|
+
* @param networkDevice The network device if available
|
|
112
|
+
* @returns The first available identifier or undefined
|
|
113
|
+
*/
|
|
114
|
+
extract(appliance, networkDevice) {
|
|
115
|
+
for (const strategy of this.strategies) {
|
|
116
|
+
const value = strategy.extract(appliance, networkDevice);
|
|
117
|
+
if (value) {
|
|
118
|
+
return value;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Factory class for creating common identifier strategies.
|
|
126
|
+
*/
|
|
127
|
+
export class IdentifierStrategyFactory {
|
|
128
|
+
/**
|
|
129
|
+
* Creates the default network device ID strategy.
|
|
130
|
+
*/
|
|
131
|
+
static networkDeviceId() {
|
|
132
|
+
return new NetworkDeviceIdStrategy();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Creates a serial number strategy.
|
|
136
|
+
*/
|
|
137
|
+
static serialNumber() {
|
|
138
|
+
return new SerialNumberStrategy();
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Creates a custom metadata field strategy.
|
|
142
|
+
* @param fieldName The metadata field to use
|
|
143
|
+
*/
|
|
144
|
+
static customMetadata(fieldName) {
|
|
145
|
+
return new CustomMetadataStrategy(fieldName);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Creates a composite strategy that combines multiple identifiers.
|
|
149
|
+
* @param strategies The strategies to combine
|
|
150
|
+
* @param separator The separator between parts
|
|
151
|
+
*/
|
|
152
|
+
static composite(strategies, separator) {
|
|
153
|
+
return new CompositeIdentifierStrategy(strategies, separator);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Creates a fallback strategy that tries multiple strategies in order.
|
|
157
|
+
* @param strategies The strategies to try
|
|
158
|
+
*/
|
|
159
|
+
static fallback(strategies) {
|
|
160
|
+
return new FallbackIdentifierStrategy(strategies);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Creates a strategy that prefers serial number but falls back to network device ID.
|
|
164
|
+
*/
|
|
165
|
+
static serialNumberOrDeviceId() {
|
|
166
|
+
return new FallbackIdentifierStrategy([
|
|
167
|
+
new SerialNumberStrategy(),
|
|
168
|
+
new NetworkDeviceIdStrategy()
|
|
169
|
+
]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { EnergyApp } from "../../index.js";
|
|
2
|
+
import type { EnyoNetworkDevice } from "../../types/enyo-network-device.js";
|
|
3
|
+
import { EnyoAppliance, EnyoApplianceConnectionType, EnyoApplianceMetadata, EnyoApplianceStateEnum, EnyoApplianceTypeEnum } from "../../types/enyo-appliance.js";
|
|
4
|
+
import { ApplianceConfig, ApplianceManager, ApplianceManagerConfig, FindResult } from "./appliance-manager.js";
|
|
5
|
+
import { IdentifierStrategy } from "./identifier-strategies.js";
|
|
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,277 @@
|
|
|
1
|
+
import { EnyoApplianceConnectionType, EnyoApplianceStateEnum } from "../../types/enyo-appliance.js";
|
|
2
|
+
import { ApplianceManager } from "./appliance-manager.js";
|
|
3
|
+
/**
|
|
4
|
+
* Demo implementation of ApplianceManager that stores all data in memory.
|
|
5
|
+
* This class provides the same interface as ApplianceManager but doesn't
|
|
6
|
+
* use energyApp.useAppliances() for persistence.
|
|
7
|
+
*/
|
|
8
|
+
export class InMemoryApplianceManager extends ApplianceManager {
|
|
9
|
+
memoryStore = new Map();
|
|
10
|
+
nextId = 1;
|
|
11
|
+
networkDevicesStore = new Map();
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new DemoApplianceManager instance.
|
|
14
|
+
* @param energyApp The EnergyApp instance (not used for persistence in demo)
|
|
15
|
+
* @param config Configuration options for the manager
|
|
16
|
+
*/
|
|
17
|
+
constructor(energyApp, config) {
|
|
18
|
+
super(energyApp, config);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Creates or updates an appliance in memory.
|
|
22
|
+
* @param config The appliance configuration
|
|
23
|
+
* @param existingApplianceId Optional ID of an existing appliance to update
|
|
24
|
+
* @returns The ID of the created or updated appliance
|
|
25
|
+
*/
|
|
26
|
+
async createOrUpdateAppliance(config, existingApplianceId) {
|
|
27
|
+
const applianceId = existingApplianceId || `appliance_${this.nextId++}`;
|
|
28
|
+
// Build network device IDs list
|
|
29
|
+
const networkDeviceIds = config.networkDevices?.map(d => d.id) ?? [];
|
|
30
|
+
// Get existing metadata if updating
|
|
31
|
+
const existingAppliance = existingApplianceId ? this.memoryStore.get(existingApplianceId) : null;
|
|
32
|
+
// Merge metadata with defaults and existing values
|
|
33
|
+
const metadata = {
|
|
34
|
+
connectionType: config.metadata?.connectionType ||
|
|
35
|
+
existingAppliance?.metadata?.connectionType ||
|
|
36
|
+
EnyoApplianceConnectionType.Connector,
|
|
37
|
+
state: config.metadata?.state ||
|
|
38
|
+
existingAppliance?.metadata?.state ||
|
|
39
|
+
EnyoApplianceStateEnum.Connected,
|
|
40
|
+
...config.metadata
|
|
41
|
+
};
|
|
42
|
+
// Build appliance data
|
|
43
|
+
const applianceData = {
|
|
44
|
+
id: applianceId,
|
|
45
|
+
name: config.name,
|
|
46
|
+
type: config.type,
|
|
47
|
+
networkDeviceIds,
|
|
48
|
+
metadata,
|
|
49
|
+
...(config.topology && { topology: config.topology })
|
|
50
|
+
};
|
|
51
|
+
// Add type-specific metadata
|
|
52
|
+
if (config.typeMetadata) {
|
|
53
|
+
Object.assign(applianceData, config.typeMetadata);
|
|
54
|
+
}
|
|
55
|
+
// Save to memory store
|
|
56
|
+
this.memoryStore.set(applianceId, applianceData);
|
|
57
|
+
// Store network devices if provided
|
|
58
|
+
if (config.networkDevices) {
|
|
59
|
+
this.networkDevicesStore.set(applianceId, config.networkDevices);
|
|
60
|
+
}
|
|
61
|
+
// Update cache
|
|
62
|
+
this.updateCache(applianceData, config.networkDevices?.[0]);
|
|
63
|
+
console.log(`[DEMO] ${existingApplianceId ? 'Updated' : 'Created'} appliance ${applianceId} of type ${config.type}`);
|
|
64
|
+
return applianceId;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Gets an appliance by ID from memory.
|
|
68
|
+
* @param applianceId The ID of the appliance
|
|
69
|
+
* @returns The appliance or null if not found
|
|
70
|
+
*/
|
|
71
|
+
async getApplianceById(applianceId) {
|
|
72
|
+
return this.memoryStore.get(applianceId) || null;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Gets all appliances from memory.
|
|
76
|
+
* @returns Array of all appliances
|
|
77
|
+
*/
|
|
78
|
+
async getAllAppliances() {
|
|
79
|
+
return Array.from(this.memoryStore.values());
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets network devices associated with an appliance.
|
|
83
|
+
* @param appliance The appliance
|
|
84
|
+
* @returns Array of network devices
|
|
85
|
+
*/
|
|
86
|
+
async getNetworkDevicesForApplianceDemo(appliance) {
|
|
87
|
+
return this.networkDevicesStore.get(appliance.id) || [];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Finds appliances by their identifier using the configured strategy.
|
|
91
|
+
* @param identifier The identifier to search for
|
|
92
|
+
* @returns Array of matching appliances
|
|
93
|
+
*/
|
|
94
|
+
async findByIdentifier(identifier) {
|
|
95
|
+
const matches = [];
|
|
96
|
+
const strategy = this.getIdentifierStrategy();
|
|
97
|
+
for (const appliance of this.memoryStore.values()) {
|
|
98
|
+
const networkDevices = await this.getNetworkDevicesForApplianceDemo(appliance);
|
|
99
|
+
const extractedId = strategy.extract(appliance, networkDevices[0]);
|
|
100
|
+
if (extractedId === identifier) {
|
|
101
|
+
matches.push(appliance);
|
|
102
|
+
this.updateCache(appliance, networkDevices[0]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return matches;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Finds an appliance using multiple strategies.
|
|
109
|
+
* @param searchValue The value to search for
|
|
110
|
+
* @param strategies Array of strategies to try
|
|
111
|
+
* @returns The first matching result or undefined
|
|
112
|
+
*/
|
|
113
|
+
async findWithStrategies(searchValue, strategies) {
|
|
114
|
+
for (const strategy of strategies) {
|
|
115
|
+
for (const appliance of this.memoryStore.values()) {
|
|
116
|
+
const networkDevices = await this.getNetworkDevicesForApplianceDemo(appliance);
|
|
117
|
+
const identifier = strategy.extract(appliance, networkDevices[0]);
|
|
118
|
+
if (identifier === searchValue) {
|
|
119
|
+
return {
|
|
120
|
+
appliance,
|
|
121
|
+
identifier,
|
|
122
|
+
strategy: strategy.name
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Gets all appliances of a specific type.
|
|
131
|
+
* @param type The appliance type to filter by
|
|
132
|
+
* @returns Array of appliances of the specified type
|
|
133
|
+
*/
|
|
134
|
+
async getAppliancesByType(type) {
|
|
135
|
+
return Array.from(this.memoryStore.values()).filter(a => a.type === type);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Updates the state of an appliance in memory.
|
|
139
|
+
* @param applianceId The ID of the appliance to update
|
|
140
|
+
* @param connectionType The new connection type
|
|
141
|
+
* @param state The new state
|
|
142
|
+
*/
|
|
143
|
+
async updateApplianceState(applianceId, connectionType, state) {
|
|
144
|
+
const appliance = this.memoryStore.get(applianceId);
|
|
145
|
+
if (appliance) {
|
|
146
|
+
appliance.metadata = {
|
|
147
|
+
...appliance.metadata,
|
|
148
|
+
connectionType,
|
|
149
|
+
state
|
|
150
|
+
};
|
|
151
|
+
this.memoryStore.set(applianceId, appliance);
|
|
152
|
+
this.updateCache(appliance);
|
|
153
|
+
console.log(`[DEMO] Updated appliance ${applianceId} state to ${state}`);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
throw new Error(`Appliance ${applianceId} not found`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Updates metadata for an appliance in memory.
|
|
161
|
+
* @param applianceId The ID of the appliance
|
|
162
|
+
* @param metadata The metadata to update
|
|
163
|
+
*/
|
|
164
|
+
async updateApplianceMetadata(applianceId, metadata) {
|
|
165
|
+
const appliance = this.memoryStore.get(applianceId);
|
|
166
|
+
if (appliance) {
|
|
167
|
+
appliance.metadata = {
|
|
168
|
+
...appliance.metadata,
|
|
169
|
+
...metadata
|
|
170
|
+
};
|
|
171
|
+
this.memoryStore.set(applianceId, appliance);
|
|
172
|
+
this.updateCache(appliance);
|
|
173
|
+
console.log(`[DEMO] Updated metadata for appliance ${applianceId}`);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
throw new Error(`Appliance ${applianceId} not found`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Removes an appliance from memory.
|
|
181
|
+
* @param applianceId The ID of the appliance to remove
|
|
182
|
+
*/
|
|
183
|
+
async removeAppliance(applianceId) {
|
|
184
|
+
if (this.memoryStore.has(applianceId)) {
|
|
185
|
+
this.memoryStore.delete(applianceId);
|
|
186
|
+
this.networkDevicesStore.delete(applianceId);
|
|
187
|
+
// Clean up cache (from parent class)
|
|
188
|
+
this.clearCache();
|
|
189
|
+
console.log(`[DEMO] Removed appliance ${applianceId}`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
throw new Error(`Appliance ${applianceId} not found`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Performs a bulk update on multiple appliances in memory.
|
|
197
|
+
* @param updates Array of updates to perform
|
|
198
|
+
* @returns Results of the bulk update operation
|
|
199
|
+
*/
|
|
200
|
+
async bulkUpdate(updates) {
|
|
201
|
+
const succeeded = [];
|
|
202
|
+
const failed = [];
|
|
203
|
+
for (const update of updates) {
|
|
204
|
+
try {
|
|
205
|
+
const appliance = this.memoryStore.get(update.applianceId);
|
|
206
|
+
if (appliance) {
|
|
207
|
+
const updatedAppliance = {
|
|
208
|
+
...appliance,
|
|
209
|
+
...update.data,
|
|
210
|
+
id: appliance.id // Ensure ID is preserved
|
|
211
|
+
};
|
|
212
|
+
this.memoryStore.set(update.applianceId, updatedAppliance);
|
|
213
|
+
this.updateCache(updatedAppliance);
|
|
214
|
+
succeeded.push(update.applianceId);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
failed.push(update.applianceId);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.error(`[DEMO] Bulk update failed for ${update.applianceId}: ${error}`);
|
|
222
|
+
failed.push(update.applianceId);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
console.log(`[DEMO] Bulk update completed: ${succeeded.length} succeeded, ${failed.length} failed`);
|
|
226
|
+
return { succeeded, failed };
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Gets statistics about the managed appliances in memory.
|
|
230
|
+
* @returns Statistics object
|
|
231
|
+
*/
|
|
232
|
+
async getStatistics() {
|
|
233
|
+
const appliances = Array.from(this.memoryStore.values());
|
|
234
|
+
const byType = {};
|
|
235
|
+
const byState = {};
|
|
236
|
+
for (const appliance of appliances) {
|
|
237
|
+
// Count by type
|
|
238
|
+
byType[appliance.type] = (byType[appliance.type] ?? 0) + 1;
|
|
239
|
+
// Count by state
|
|
240
|
+
const state = appliance.metadata?.state ?? 'unknown';
|
|
241
|
+
byState[state] = (byState[state] ?? 0) + 1;
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
total: appliances.length,
|
|
245
|
+
byType,
|
|
246
|
+
byState,
|
|
247
|
+
cached: this.memoryStore.size
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Refreshes the cache with all appliances from memory.
|
|
252
|
+
*/
|
|
253
|
+
async refreshCache() {
|
|
254
|
+
this.clearCache();
|
|
255
|
+
for (const appliance of this.memoryStore.values()) {
|
|
256
|
+
const networkDevices = await this.getNetworkDevicesForApplianceDemo(appliance);
|
|
257
|
+
this.updateCache(appliance, networkDevices[0]);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Clears all data from memory (for testing purposes).
|
|
262
|
+
*/
|
|
263
|
+
clearAllData() {
|
|
264
|
+
this.memoryStore.clear();
|
|
265
|
+
this.networkDevicesStore.clear();
|
|
266
|
+
this.clearCache();
|
|
267
|
+
this.nextId = 1;
|
|
268
|
+
console.log('[DEMO] All data cleared from memory');
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Gets the current size of the memory store.
|
|
272
|
+
* @returns The number of appliances in memory
|
|
273
|
+
*/
|
|
274
|
+
getMemoryStoreSize() {
|
|
275
|
+
return this.memoryStore.size;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { EnergyAppDataBus, EnergyAppDataBusSendDataOptions } from "../../packages/energy-app-data-bus.js";
|
|
2
|
+
import { EnyoDataBusMessage, EnyoDataBusMessageAnswer, EnyoDataBusMessageEnum } from "../../types/enyo-data-bus-value.js";
|
|
3
|
+
/**
|
|
4
|
+
* Demo implementation of EnergyAppDataBus that logs messages to console
|
|
5
|
+
* and maintains an in-memory message history and listener registry.
|
|
6
|
+
*/
|
|
7
|
+
export declare class DemoDataBus implements EnergyAppDataBus {
|
|
8
|
+
private enableConsoleLogging;
|
|
9
|
+
private messageHistory;
|
|
10
|
+
private listeners;
|
|
11
|
+
private nextListenerId;
|
|
12
|
+
private maxHistorySize;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new DemoDataBus instance.
|
|
15
|
+
* @param enableConsoleLogging Whether to log messages to console (default: true)
|
|
16
|
+
* @param maxHistorySize Maximum number of messages to keep in history (default: 1000)
|
|
17
|
+
*/
|
|
18
|
+
constructor(enableConsoleLogging?: boolean, maxHistorySize?: number);
|
|
19
|
+
/**
|
|
20
|
+
* Sends messages to the data bus (logs to console and notifies listeners).
|
|
21
|
+
* @param messages Array of messages to send
|
|
22
|
+
* @param options Optional send options (not used in demo)
|
|
23
|
+
*/
|
|
24
|
+
sendMessage(messages: EnyoDataBusMessage[], options?: EnergyAppDataBusSendDataOptions): void;
|
|
25
|
+
/**
|
|
26
|
+
* Sends an answer message to the data bus.
|
|
27
|
+
* @param answer The answer message to send
|
|
28
|
+
* @param options Optional send options (not used in demo)
|
|
29
|
+
*/
|
|
30
|
+
sendAnswer(answer: EnyoDataBusMessageAnswer, options?: EnergyAppDataBusSendDataOptions): void;
|
|
31
|
+
/**
|
|
32
|
+
* Registers a listener for specific message types.
|
|
33
|
+
* @param types Array of message types to listen for
|
|
34
|
+
* @param listener Callback function to invoke when matching messages are received
|
|
35
|
+
* @returns Listener ID that can be used to unsubscribe
|
|
36
|
+
*/
|
|
37
|
+
listenForMessages(types: EnyoDataBusMessageEnum[], listener: (entry: EnyoDataBusMessage) => void): string;
|
|
38
|
+
/**
|
|
39
|
+
* Unsubscribes a listener from the data bus.
|
|
40
|
+
* @param listenerId The ID of the listener to unsubscribe
|
|
41
|
+
*/
|
|
42
|
+
unsubscribe(listenerId: string): void;
|
|
43
|
+
/**
|
|
44
|
+
* Adds a message to the history, maintaining the maximum size limit.
|
|
45
|
+
* @param message The message to add to history
|
|
46
|
+
*/
|
|
47
|
+
private addToHistory;
|
|
48
|
+
/**
|
|
49
|
+
* Notifies all registered listeners that match the message type.
|
|
50
|
+
* @param message The message to notify listeners about
|
|
51
|
+
*/
|
|
52
|
+
private notifyListeners;
|
|
53
|
+
/**
|
|
54
|
+
* Gets the message history.
|
|
55
|
+
* @param limit Optional limit on the number of messages to return
|
|
56
|
+
* @returns Array of messages from history
|
|
57
|
+
*/
|
|
58
|
+
getMessageHistory(limit?: number): EnyoDataBusMessage[];
|
|
59
|
+
/**
|
|
60
|
+
* Gets messages of specific types from history.
|
|
61
|
+
* @param types Array of message types to filter by
|
|
62
|
+
* @param limit Optional limit on the number of messages to return
|
|
63
|
+
* @returns Filtered array of messages
|
|
64
|
+
*/
|
|
65
|
+
getMessagesByType(types: EnyoDataBusMessageEnum[], limit?: number): EnyoDataBusMessage[];
|
|
66
|
+
/**
|
|
67
|
+
* Gets messages for a specific appliance from history.
|
|
68
|
+
* @param applianceId The appliance ID to filter by
|
|
69
|
+
* @param limit Optional limit on the number of messages to return
|
|
70
|
+
* @returns Filtered array of messages
|
|
71
|
+
*/
|
|
72
|
+
getMessagesByAppliance(applianceId: string, limit?: number): EnyoDataBusMessage[];
|
|
73
|
+
/**
|
|
74
|
+
* Clears the message history.
|
|
75
|
+
*/
|
|
76
|
+
clearHistory(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Gets the current number of registered listeners.
|
|
79
|
+
* @returns The number of active listeners
|
|
80
|
+
*/
|
|
81
|
+
getListenerCount(): number;
|
|
82
|
+
/**
|
|
83
|
+
* Gets information about all registered listeners.
|
|
84
|
+
* @returns Array of listener information
|
|
85
|
+
*/
|
|
86
|
+
getListenerInfo(): Array<{
|
|
87
|
+
id: string;
|
|
88
|
+
types: EnyoDataBusMessageEnum[];
|
|
89
|
+
}>;
|
|
90
|
+
/**
|
|
91
|
+
* Enables or disables console logging.
|
|
92
|
+
* @param enabled Whether to enable console logging
|
|
93
|
+
*/
|
|
94
|
+
setConsoleLogging(enabled: boolean): void;
|
|
95
|
+
/**
|
|
96
|
+
* Simulates receiving a message from an external source.
|
|
97
|
+
* This is useful for testing listeners without actually sending messages.
|
|
98
|
+
* @param message The message to simulate receiving
|
|
99
|
+
*/
|
|
100
|
+
simulateIncomingMessage(message: EnyoDataBusMessage): void;
|
|
101
|
+
/**
|
|
102
|
+
* Gets statistics about the data bus usage.
|
|
103
|
+
* @returns Statistics object
|
|
104
|
+
*/
|
|
105
|
+
getStatistics(): {
|
|
106
|
+
totalMessages: number;
|
|
107
|
+
messagesByType: Record<string, number>;
|
|
108
|
+
activeListeners: number;
|
|
109
|
+
messagesInLastHour: number;
|
|
110
|
+
};
|
|
111
|
+
}
|