@enyo-energy/energy-app-sdk 0.0.34 → 0.0.35

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.
Files changed (134) hide show
  1. package/README.md +1083 -15
  2. package/dist/cjs/version.cjs +1 -1
  3. package/dist/cjs/version.d.cts +1 -1
  4. package/dist/version.d.ts +1 -1
  5. package/dist/version.js +1 -1
  6. package/package.json +4 -4
  7. package/dist/cjs/connect-ems-api.cjs +0 -2
  8. package/dist/cjs/connect-ems-api.d.cts +0 -30
  9. package/dist/cjs/connect-ems-permission.enum.cjs +0 -7
  10. package/dist/cjs/connect-ems-permission.enum.d.cts +0 -3
  11. package/dist/cjs/connect-ems-permission.type.cjs +0 -2
  12. package/dist/cjs/connect-ems-permission.type.d.cts +0 -1
  13. package/dist/cjs/connect-package-definition.cjs +0 -14
  14. package/dist/cjs/connect-package-definition.d.cts +0 -57
  15. package/dist/cjs/energy-app-package-configuration.cjs +0 -2
  16. package/dist/cjs/energy-app-package-configuration.d.cts +0 -30
  17. package/dist/cjs/hems-one-energy-app-sdk.cjs +0 -12
  18. package/dist/cjs/hems-one-energy-app-sdk.d.cts +0 -64
  19. package/dist/cjs/mockConnectEmsApi.cjs +0 -167
  20. package/dist/cjs/mockConnectEmsApi.d.cts +0 -10
  21. package/dist/cjs/packages/connect-appliance.cjs +0 -2
  22. package/dist/cjs/packages/connect-appliance.d.cts +0 -24
  23. package/dist/cjs/packages/connect-http-api.cjs +0 -2
  24. package/dist/cjs/packages/connect-http-api.d.cts +0 -15
  25. package/dist/cjs/packages/connect-interval.cjs +0 -2
  26. package/dist/cjs/packages/connect-interval.d.cts +0 -15
  27. package/dist/cjs/packages/connect-modbus.cjs +0 -2
  28. package/dist/cjs/packages/connect-modbus.d.cts +0 -60
  29. package/dist/cjs/packages/connect-network-devices.cjs +0 -2
  30. package/dist/cjs/packages/connect-network-devices.d.cts +0 -40
  31. package/dist/cjs/packages/connect-storage.cjs +0 -2
  32. package/dist/cjs/packages/connect-storage.d.cts +0 -14
  33. package/dist/cjs/types/connect-appliance-type.enum.cjs +0 -10
  34. package/dist/cjs/types/connect-appliance-type.enum.d.cts +0 -6
  35. package/dist/cjs/types/energy-app-settings.cjs +0 -2
  36. package/dist/cjs/types/energy-app-settings.d.cts +0 -74
  37. package/dist/cjs/types/hems-one-appliance.cjs +0 -33
  38. package/dist/cjs/types/hems-one-appliance.d.cts +0 -81
  39. package/dist/cjs/types/hems-one-authentication.cjs +0 -9
  40. package/dist/cjs/types/hems-one-authentication.d.cts +0 -69
  41. package/dist/cjs/types/hems-one-battery-appliance.cjs +0 -2
  42. package/dist/cjs/types/hems-one-battery-appliance.d.cts +0 -6
  43. package/dist/cjs/types/hems-one-charge.cjs +0 -15
  44. package/dist/cjs/types/hems-one-charge.d.cts +0 -82
  45. package/dist/cjs/types/hems-one-charger-appliance.cjs +0 -41
  46. package/dist/cjs/types/hems-one-charger-appliance.d.cts +0 -49
  47. package/dist/cjs/types/hems-one-charging-card.cjs +0 -2
  48. package/dist/cjs/types/hems-one-charging-card.d.cts +0 -11
  49. package/dist/cjs/types/hems-one-data-bus-command.cjs +0 -9
  50. package/dist/cjs/types/hems-one-data-bus-command.d.cts +0 -34
  51. package/dist/cjs/types/hems-one-data-bus-value.cjs +0 -78
  52. package/dist/cjs/types/hems-one-data-bus-value.d.cts +0 -379
  53. package/dist/cjs/types/hems-one-electricity-prices.cjs +0 -2
  54. package/dist/cjs/types/hems-one-electricity-prices.d.cts +0 -63
  55. package/dist/cjs/types/hems-one-energy-tariff.cjs +0 -2
  56. package/dist/cjs/types/hems-one-energy-tariff.d.cts +0 -70
  57. package/dist/cjs/types/hems-one-heatpump-appliance.cjs +0 -19
  58. package/dist/cjs/types/hems-one-heatpump-appliance.d.cts +0 -34
  59. package/dist/cjs/types/hems-one-inverter-appliance.cjs +0 -2
  60. package/dist/cjs/types/hems-one-inverter-appliance.d.cts +0 -3
  61. package/dist/cjs/types/hems-one-meter-appliance.cjs +0 -10
  62. package/dist/cjs/types/hems-one-meter-appliance.d.cts +0 -10
  63. package/dist/cjs/types/hems-one-network-device.cjs +0 -2
  64. package/dist/cjs/types/hems-one-network-device.d.cts +0 -31
  65. package/dist/cjs/types/hems-one-source.enum.cjs +0 -8
  66. package/dist/cjs/types/hems-one-source.enum.d.cts +0 -4
  67. package/dist/cjs/types/hems-one-vehicle.cjs +0 -2
  68. package/dist/cjs/types/hems-one-vehicle.d.cts +0 -12
  69. package/dist/cjs/types/hems-one-websocket-connection.cjs +0 -2
  70. package/dist/cjs/types/hems-one-websocket-connection.d.cts +0 -8
  71. package/dist/connect-ems-api.d.ts +0 -30
  72. package/dist/connect-ems-api.js +0 -1
  73. package/dist/connect-ems-permission.enum.d.ts +0 -3
  74. package/dist/connect-ems-permission.enum.js +0 -4
  75. package/dist/connect-ems-permission.type.d.ts +0 -1
  76. package/dist/connect-ems-permission.type.js +0 -1
  77. package/dist/connect-package-definition.d.ts +0 -57
  78. package/dist/connect-package-definition.js +0 -10
  79. package/dist/energy-app-package-configuration.d.ts +0 -30
  80. package/dist/energy-app-package-configuration.js +0 -1
  81. package/dist/hems-one-energy-app-sdk.d.ts +0 -67
  82. package/dist/hems-one-energy-app-sdk.js +0 -9
  83. package/dist/mockConnectEmsApi.d.ts +0 -10
  84. package/dist/mockConnectEmsApi.js +0 -160
  85. package/dist/packages/connect-appliance.d.ts +0 -24
  86. package/dist/packages/connect-appliance.js +0 -1
  87. package/dist/packages/connect-http-api.d.ts +0 -15
  88. package/dist/packages/connect-http-api.js +0 -1
  89. package/dist/packages/connect-interval.d.ts +0 -15
  90. package/dist/packages/connect-interval.js +0 -1
  91. package/dist/packages/connect-modbus.d.ts +0 -60
  92. package/dist/packages/connect-modbus.js +0 -1
  93. package/dist/packages/connect-network-devices.d.ts +0 -40
  94. package/dist/packages/connect-network-devices.js +0 -1
  95. package/dist/packages/connect-storage.d.ts +0 -14
  96. package/dist/packages/connect-storage.js +0 -1
  97. package/dist/types/connect-appliance-type.enum.d.ts +0 -6
  98. package/dist/types/connect-appliance-type.enum.js +0 -7
  99. package/dist/types/energy-app-settings.d.ts +0 -74
  100. package/dist/types/energy-app-settings.js +0 -1
  101. package/dist/types/hems-one-appliance.d.ts +0 -81
  102. package/dist/types/hems-one-appliance.js +0 -30
  103. package/dist/types/hems-one-authentication.d.ts +0 -69
  104. package/dist/types/hems-one-authentication.js +0 -6
  105. package/dist/types/hems-one-battery-appliance.d.ts +0 -6
  106. package/dist/types/hems-one-battery-appliance.js +0 -1
  107. package/dist/types/hems-one-charge.d.ts +0 -82
  108. package/dist/types/hems-one-charge.js +0 -12
  109. package/dist/types/hems-one-charger-appliance.d.ts +0 -49
  110. package/dist/types/hems-one-charger-appliance.js +0 -38
  111. package/dist/types/hems-one-charging-card.d.ts +0 -11
  112. package/dist/types/hems-one-charging-card.js +0 -1
  113. package/dist/types/hems-one-data-bus-command.d.ts +0 -34
  114. package/dist/types/hems-one-data-bus-command.js +0 -6
  115. package/dist/types/hems-one-data-bus-value.d.ts +0 -379
  116. package/dist/types/hems-one-data-bus-value.js +0 -75
  117. package/dist/types/hems-one-electricity-prices.d.ts +0 -63
  118. package/dist/types/hems-one-electricity-prices.js +0 -1
  119. package/dist/types/hems-one-energy-tariff.d.ts +0 -70
  120. package/dist/types/hems-one-energy-tariff.js +0 -1
  121. package/dist/types/hems-one-heatpump-appliance.d.ts +0 -34
  122. package/dist/types/hems-one-heatpump-appliance.js +0 -16
  123. package/dist/types/hems-one-inverter-appliance.d.ts +0 -3
  124. package/dist/types/hems-one-inverter-appliance.js +0 -1
  125. package/dist/types/hems-one-meter-appliance.d.ts +0 -10
  126. package/dist/types/hems-one-meter-appliance.js +0 -7
  127. package/dist/types/hems-one-network-device.d.ts +0 -31
  128. package/dist/types/hems-one-network-device.js +0 -1
  129. package/dist/types/hems-one-source.enum.d.ts +0 -4
  130. package/dist/types/hems-one-source.enum.js +0 -5
  131. package/dist/types/hems-one-vehicle.d.ts +0 -12
  132. package/dist/types/hems-one-vehicle.js +0 -1
  133. package/dist/types/hems-one-websocket-connection.d.ts +0 -8
  134. package/dist/types/hems-one-websocket-connection.js +0 -1
package/README.md CHANGED
@@ -1,29 +1,624 @@
1
1
  # enyo Energy App SDK
2
2
 
3
- This is the official TypeScript Energy App SDK for enyo. If you want to build your own Energy App to publish it on the enyo Hub, this is the package you need!
3
+ The official TypeScript SDK for building Energy Apps on the enyo platform. Create powerful energy management applications that integrate with inverters, batteries, charging stations, and smart home devices.
4
+
5
+ [![npm version](https://badge.fury.io/js/@enyo-energy%2Fenergy-app-sdk.svg)](https://badge.fury.io/js/@enyo-energy%2Fenergy-app-sdk)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0%2B-blue.svg)](https://www.typescriptlang.org/)
7
+
8
+ ## Table of Contents
9
+
10
+ - [Installation](#installation)
11
+ - [Quick Start](#quick-start)
12
+ - [Core Concepts](#core-concepts)
13
+ - [Energy App Lifecycle](#energy-app-lifecycle)
14
+ - [Package Definition](#package-definition)
15
+ - [Permissions System](#permissions-system)
16
+ - [API Reference](#api-reference)
17
+ - [Lifecycle Management](#lifecycle-management)
18
+ - [System APIs](#system-apis)
19
+ - [Device Communication](#device-communication)
20
+ - [Data Management](#data-management)
21
+ - [Energy Resources](#energy-resources)
22
+ - [User Features](#user-features)
23
+ - [Advanced Modbus Integration](#advanced-modbus-integration)
24
+ - [Examples](#examples)
25
+ - [Basic Energy App](#basic-energy-app)
26
+ - [Device Integration](#device-integration)
27
+ - [Data Bus Messaging](#data-bus-messaging)
28
+ - [Settings Management](#settings-management)
29
+ - [Troubleshooting](#troubleshooting)
30
+ - [CLI Tool](#cli-tool)
4
31
 
5
32
  ## Installation
6
33
 
7
- You can install the package using npm:
34
+ Install the SDK using npm:
35
+
8
36
  ```bash
9
- npm install @enyo/energy-app-sdk
37
+ npm install @enyo-energy/energy-app-sdk
38
+ ```
39
+
40
+ ## Quick Start
41
+
42
+ Create a basic Energy App that responds to system events:
43
+
44
+ ```typescript
45
+ import { EnergyApp, defineEnergyAppPackage, EnergyAppPackageCategory } from '@enyo-energy/energy-app-sdk';
46
+
47
+ // Define your package
48
+ const packageDefinition = defineEnergyAppPackage({
49
+ version: '1',
50
+ packageName: 'my-energy-app',
51
+ categories: [EnergyAppPackageCategory.EnergyManagement],
52
+ storeEntry: [{
53
+ language: 'en',
54
+ title: 'My Energy App',
55
+ shortDescription: 'A simple energy management app',
56
+ description: 'This app demonstrates basic energy management capabilities'
57
+ }],
58
+ permissions: ['Storage', 'SendDataBusValues']
59
+ });
60
+
61
+ // Initialize the Energy App
62
+ const energyApp = new EnergyApp();
63
+
64
+ energyApp.register((packageName: string, version: number) => {
65
+ console.log(`Energy App ${packageName} v${version} is starting...`);
66
+ console.log(`System is ${energyApp.isSystemOnline() ? 'online' : 'offline'}`);
67
+
68
+ // Set app state to running
69
+ energyApp.updateEnergyAppState('running');
70
+
71
+ // Your app logic starts here
72
+ startApp();
73
+ });
74
+
75
+ async function startApp() {
76
+ // Use SDK APIs
77
+ const storage = energyApp.useStorage();
78
+ const dataBus = energyApp.useDataBus();
79
+
80
+ // Store app configuration
81
+ await storage.save('config', { initialized: true, timestamp: Date.now() });
82
+
83
+ // Listen for data bus messages
84
+ dataBus.listenForMessages(['InverterValuesUpdateV1'], (message) => {
85
+ console.log('Received inverter data:', message);
86
+ });
87
+ }
88
+ ```
89
+
90
+ ## Core Concepts
91
+
92
+ ### Energy App Lifecycle
93
+
94
+ Energy Apps follow a specific lifecycle managed by the enyo system:
95
+
96
+ 1. **Initialization**: Your app registers with the system
97
+ 2. **Running**: App performs its main functionality
98
+ 3. **State Management**: App reports its current state
99
+ 4. **Shutdown**: Graceful cleanup when system stops
100
+
101
+ ```typescript
102
+ const energyApp = new EnergyApp();
103
+
104
+ // Register startup callback
105
+ energyApp.register((packageName, version) => {
106
+ console.log(`${packageName} v${version} started`);
107
+ energyApp.updateEnergyAppState('running');
108
+ });
109
+
110
+ // Register shutdown callback
111
+ energyApp.onShutdown(async () => {
112
+ console.log('Cleaning up resources...');
113
+ // Perform cleanup tasks
114
+ });
115
+ ```
116
+
117
+ #### App States
118
+
119
+ - `launching`: Initial state when app is starting up
120
+ - `running`: App is functioning normally
121
+ - `configuration-required`: App needs user configuration
122
+ - `internet-connection-required`: App needs internet connectivity
123
+
124
+ ### Package Definition
125
+
126
+ Every Energy App must be defined using `defineEnergyAppPackage()`:
127
+
128
+ ```typescript
129
+ import {
130
+ defineEnergyAppPackage,
131
+ EnergyAppPackageCategory,
132
+ EnergyAppPermissionTypeEnum
133
+ } from '@enyo-energy/energy-app-sdk';
134
+
135
+ const packageDef = defineEnergyAppPackage({
136
+ version: '1',
137
+ packageName: 'solar-optimizer',
138
+ logo: './assets/logo.png',
139
+ categories: [
140
+ EnergyAppPackageCategory.Inverter,
141
+ EnergyAppPackageCategory.EnergyManagement
142
+ ],
143
+ storeEntry: [
144
+ {
145
+ language: 'en',
146
+ title: 'Solar Optimizer',
147
+ shortDescription: 'Optimize your solar energy production',
148
+ description: 'Advanced solar energy optimization with AI-driven predictions and real-time adjustments.'
149
+ },
150
+ {
151
+ language: 'de',
152
+ title: 'Solar Optimierer',
153
+ shortDescription: 'Optimieren Sie Ihre Solarenergieproduktion',
154
+ description: 'Erweiterte Solarenergie-Optimierung mit KI-gesteuerten Vorhersagen und Echtzeitanpassungen.'
155
+ }
156
+ ],
157
+ permissions: [
158
+ EnergyAppPermissionTypeEnum.Modbus,
159
+ EnergyAppPermissionTypeEnum.SendDataBusValues,
160
+ EnergyAppPermissionTypeEnum.SubscribeDataBus,
161
+ EnergyAppPermissionTypeEnum.Storage
162
+ ],
163
+ options: {
164
+ restrictedInternetAccess: {
165
+ origins: ['api.weather.com', 'solar-forecasting.com']
166
+ },
167
+ deviceDetection: {
168
+ modbus: [{
169
+ unitIds: [1],
170
+ registerAddress: 40001,
171
+ registerSize: 2,
172
+ type: 'string',
173
+ matchingValues: ['SolarMax', 'SMA']
174
+ }]
175
+ }
176
+ }
177
+ });
178
+ ```
179
+
180
+ #### Package Categories
181
+
182
+ - `Inverter`: Solar inverter management
183
+ - `Wallbox`: EV charging station integration
184
+ - `Meter`: Energy metering applications
185
+ - `EnergyManagement`: Overall energy optimization
186
+ - `HeatPump`: Heat pump control systems
187
+ - `BatteryStorage`: Battery management
188
+ - `ClimateControl`: HVAC and climate systems
189
+ - `ElectricityTariff`: Dynamic pricing integration
190
+
191
+ ### Permissions System
192
+
193
+ Energy Apps use a granular permissions system to control access to system resources:
194
+
195
+ #### Core Permissions
196
+
197
+ - **`Storage`**: Access persistent key-value storage
198
+ - **`NetworkDeviceDiscovery`**: Discover devices on the local network
199
+ - **`NetworkDeviceSearch`**: Search for specific network devices
200
+ - **`NetworkDeviceAccess`**: Access discovered network devices
201
+ - **`Modbus`**: Communicate via Modbus protocol
202
+
203
+ #### Data Bus Permissions
204
+
205
+ - **`SendDataBusValues`**: Send sensor data and measurements
206
+ - **`SubscribeDataBus`**: Listen to data from other devices
207
+ - **`SendDataBusCommands`**: Send control commands
208
+
209
+ #### Device Permissions
210
+
211
+ - **`Appliance`**: Manage appliances created by your package
212
+ - **`AllAppliances`**: Access all appliances in the system
213
+ - **`OcppServer`**: Run OCPP server for EV charging
214
+ - **`ChargingCard`**: Manage EV charging cards
215
+ - **`Vehicle`**: Access vehicle information
216
+ - **`Charge`**: Manage charging sessions
217
+
218
+ #### Internet Access
219
+
220
+ - **`RestrictedInternetAccess`**: Access specific internet domains only
221
+
222
+ ## API Reference
223
+
224
+ ### Lifecycle Management
225
+
226
+ #### `register(callback: (packageName: string, version: number) => void)`
227
+
228
+ Register a callback that executes when your Energy App starts:
229
+
230
+ ```typescript
231
+ energyApp.register((packageName, version) => {
232
+ console.log(`${packageName} v${version} is now running`);
233
+ // Initialize your app here
234
+ });
235
+ ```
236
+
237
+ #### `onShutdown(callback: () => Promise<void>)`
238
+
239
+ Register cleanup logic for graceful shutdown:
240
+
241
+ ```typescript
242
+ energyApp.onShutdown(async () => {
243
+ // Close connections
244
+ await modbusClient.disconnect();
245
+ // Save final state
246
+ await storage.save('lastShutdown', Date.now());
247
+ });
248
+ ```
249
+
250
+ #### `updateEnergyAppState(state: EnergyAppStateEnum)`
251
+
252
+ Update your app's current state:
253
+
254
+ ```typescript
255
+ import { EnergyAppStateEnum } from '@enyo-energy/energy-app-sdk';
256
+
257
+ // App needs configuration
258
+ energyApp.updateEnergyAppState(EnergyAppStateEnum.ConfigurationRequired);
259
+
260
+ // App is ready and running
261
+ energyApp.updateEnergyAppState(EnergyAppStateEnum.Running);
262
+ ```
263
+
264
+ ### System APIs
265
+
266
+ #### `isSystemOnline(): boolean`
267
+
268
+ Check system connectivity:
269
+
270
+ ```typescript
271
+ if (energyApp.isSystemOnline()) {
272
+ // Fetch remote data
273
+ syncWithCloud();
274
+ } else {
275
+ // Use cached data
276
+ loadOfflineData();
277
+ }
278
+ ```
279
+
280
+ #### `useFetch(): typeof fetch`
281
+
282
+ Get HTTP client with system configuration:
283
+
284
+ ```typescript
285
+ const fetch = energyApp.useFetch();
286
+
287
+ const response = await fetch('https://api.weather.com/forecast', {
288
+ method: 'GET',
289
+ headers: { 'Authorization': 'Bearer token' }
290
+ });
291
+ ```
292
+
293
+ #### `getSdkVersion(): string`
294
+
295
+ Get the SDK version:
296
+
297
+ ```typescript
298
+ console.log(`Using SDK version: ${energyApp.getSdkVersion()}`);
299
+ ```
300
+
301
+ ### Device Communication
302
+
303
+ #### `useNetworkDevices(): EnergyAppNetworkDevice`
304
+
305
+ Discover and access network devices:
306
+
307
+ ```typescript
308
+ const networkDevices = energyApp.useNetworkDevices();
309
+
310
+ // Discover devices
311
+ const devices = await networkDevices.discover();
312
+
313
+ // Search for specific device types
314
+ const inverters = await networkDevices.search({
315
+ deviceType: 'inverter',
316
+ manufacturer: 'SMA'
317
+ });
318
+
319
+ // Get device details
320
+ const deviceInfo = await networkDevices.getDeviceInfo(device.id);
321
+ ```
322
+
323
+ #### `useModbus(): EnergyAppModbus`
324
+
325
+ Access Modbus communication:
326
+
327
+ ```typescript
328
+ const modbus = energyApp.useModbus();
329
+
330
+ // Connect to device
331
+ const client = await modbus.connect({
332
+ host: '192.168.1.100',
333
+ port: 502,
334
+ unitId: 1
335
+ });
336
+
337
+ // Read holding registers
338
+ const registers = await client.readHoldingRegisters(1001, 10);
339
+
340
+ // Write single register
341
+ await client.writeSingleRegister(2001, 500);
342
+ ```
343
+
344
+ #### `useOcpp(): EnergyAppOcpp`
345
+
346
+ Handle OCPP charging station communication:
347
+
348
+ ```typescript
349
+ const ocpp = energyApp.useOcpp();
350
+
351
+ // Start OCPP server
352
+ const server = ocpp.createServer({
353
+ port: 8080,
354
+ onChargePointConnect: (chargePointId) => {
355
+ console.log(`Charge point ${chargePointId} connected`);
356
+ }
357
+ });
358
+
359
+ // Send remote commands
360
+ await server.sendRemoteStartTransaction(chargePointId, {
361
+ connectorId: 1,
362
+ idTag: 'user123'
363
+ });
364
+ ```
365
+
366
+ ### Data Management
367
+
368
+ #### `useStorage(): EnergyAppStorage`
369
+
370
+ Persistent key-value storage:
371
+
372
+ ```typescript
373
+ const storage = energyApp.useStorage();
374
+
375
+ // Save configuration
376
+ await storage.save('config', {
377
+ inverterHost: '192.168.1.100',
378
+ pollInterval: 30000
379
+ });
380
+
381
+ // Load configuration
382
+ const config = await storage.load<ConfigType>('config');
383
+
384
+ // List all keys
385
+ const keys = await storage.listKeys();
386
+
387
+ // Remove data
388
+ await storage.remove('oldData');
389
+ ```
390
+
391
+ #### `useDataBus(): EnergyAppDataBus`
392
+
393
+ Send and receive system-wide data:
394
+
395
+ ```typescript
396
+ const dataBus = energyApp.useDataBus();
397
+
398
+ // Send inverter data
399
+ dataBus.sendMessage([{
400
+ messageType: 'InverterValuesUpdateV1',
401
+ applianceId: 'inverter-1',
402
+ timestamp: Date.now(),
403
+ values: {
404
+ powerW: 3500,
405
+ energyWh: 25000,
406
+ voltageV: 230
407
+ }
408
+ }]);
409
+
410
+ // Listen for battery updates
411
+ const listenerId = dataBus.listenForMessages(
412
+ ['BatteryValuesUpdateV1'],
413
+ (message) => {
414
+ console.log('Battery SoC:', message.values.stateOfCharge);
415
+ }
416
+ );
417
+
418
+ // Stop listening
419
+ dataBus.unsubscribe(listenerId);
420
+ ```
421
+
422
+ #### `useInterval(): EnergyAppInterval`
423
+
424
+ Manage recurring tasks:
425
+
426
+ ```typescript
427
+ const interval = energyApp.useInterval();
428
+
429
+ // Create recurring data collection
430
+ const intervalId = interval.createInterval('30s', (clockId) => {
431
+ collectSensorData();
432
+ });
433
+
434
+ // Stop interval
435
+ interval.stopInterval(intervalId);
436
+ ```
437
+
438
+ **Available intervals**: `'10s'`, `'30s'`, `'1m'`, `'5m'`, `'1hr'`
439
+
440
+ ### Energy Resources
441
+
442
+ #### `useAppliances(): EnergyAppAppliance`
443
+
444
+ Manage energy appliances:
445
+
446
+ ```typescript
447
+ const appliances = energyApp.useAppliances();
448
+
449
+ // Register new appliance
450
+ const applianceId = await appliances.save({
451
+ name: [{ language: 'en', name: 'Solar Inverter' }],
452
+ type: 'inverter',
453
+ manufacturer: 'SMA',
454
+ model: 'SB5000',
455
+ networkDevice: deviceInfo
456
+ }, undefined);
457
+
458
+ // List your appliances
459
+ const myAppliances = await appliances.list();
460
+
461
+ // Get appliance details
462
+ const appliance = await appliances.getById(applianceId);
463
+
464
+ // Remove appliance
465
+ await appliances.removeById(applianceId);
466
+ ```
467
+
468
+ #### `useVehicle(): EnergyAppVehicle`
469
+
470
+ Access electric vehicle information:
471
+
472
+ ```typescript
473
+ const vehicles = energyApp.useVehicle();
474
+
475
+ // Get all vehicles
476
+ const vehicleList = await vehicles.getVehicles();
477
+
478
+ // Get vehicle details
479
+ const vehicle = await vehicles.getVehicleById(vehicleId);
480
+
481
+ // Update vehicle state
482
+ await vehicles.updateVehicleState(vehicleId, {
483
+ batteryLevel: 80,
484
+ isPluggedIn: true,
485
+ estimatedRange: 320
486
+ });
487
+ ```
488
+
489
+ #### `useCharge(): EnergyAppCharge`
490
+
491
+ Manage charging sessions:
492
+
493
+ ```typescript
494
+ const charging = energyApp.useCharge();
495
+
496
+ // Start charging session
497
+ const sessionId = await charging.startCharge({
498
+ vehicleId: 'vehicle-123',
499
+ connectorId: 1,
500
+ maxPowerKw: 22
501
+ });
502
+
503
+ // Get active sessions
504
+ const sessions = await charging.getActiveSessions();
505
+
506
+ // Stop charging
507
+ await charging.stopCharge(sessionId);
508
+ ```
509
+
510
+ #### `useChargingCard(): EnergyAppChargingCard`
511
+
512
+ Handle charging authentication:
513
+
514
+ ```typescript
515
+ const chargingCards = energyApp.useChargingCard();
516
+
517
+ // Validate charging card
518
+ const isValid = await chargingCards.validateCard('RFID-12345');
519
+
520
+ // Get card information
521
+ const cardInfo = await chargingCards.getCardInfo('RFID-12345');
522
+ ```
523
+
524
+ ### User Features
525
+
526
+ #### `useAuthentication(): EnergyAppAuthentication`
527
+
528
+ Handle user authentication:
529
+
530
+ ```typescript
531
+ const auth = energyApp.useAuthentication();
532
+
533
+ // Get current user
534
+ const user = await auth.getCurrentUser();
535
+
536
+ // Check permissions
537
+ const hasPermission = await auth.hasPermission('admin');
538
+
539
+ // Authenticate action
540
+ const token = await auth.createAuthToken('user-action');
10
541
  ```
11
542
 
12
- Take a look on our CLI to init a project and publish a new Energy App easily.
543
+ #### `useSettings(): EnergyAppSettings`
13
544
 
14
- ## Usage
545
+ Manage app settings and configuration:
15
546
 
16
- Here's a basic example of how to use the client:
547
+ ```typescript
548
+ const settings = energyApp.useSettings();
549
+
550
+ // Add setting configuration
551
+ await settings.addSettingConfig({
552
+ name: 'pollInterval',
553
+ displayName: [{ language: 'en', name: 'Poll Interval (seconds)' }],
554
+ type: 'number',
555
+ defaultValue: '30',
556
+ validation: {
557
+ min: 10,
558
+ max: 300
559
+ }
560
+ });
561
+
562
+ // Update setting value
563
+ await settings.updateSetting('pollInterval', '60');
564
+
565
+ // Listen for setting changes
566
+ settings.listenForSettingsChanges((settingName, newValue) => {
567
+ console.log(`Setting ${settingName} changed to ${newValue}`);
568
+ });
569
+
570
+ // Get all settings
571
+ const allSettings = await settings.getSettingsConfig();
572
+ ```
573
+
574
+ #### `useElectricityPrices(): EnergyAppElectricityPrices`
575
+
576
+ Access electricity pricing information:
17
577
 
18
578
  ```typescript
19
- import { EnergyApp } from '@enyo/energy-app-sdk';
579
+ const prices = energyApp.useElectricityPrices();
20
580
 
21
- const energyAppInstance = new EnergyApp();
581
+ // Get current electricity price
582
+ const currentPrice = await prices.getCurrentPrice();
22
583
 
23
- energyAppInstance.register((packageName: string, version: number) => {
24
- console.log(`network state is ${client.isOnline() ? 'online' : 'offline'}. Package ${packageName} version ${version} is registered.`);
25
- // This starts you Energy App, do all the things in here!
584
+ // Get price forecast
585
+ const forecast = await prices.getPriceForecast({
586
+ hoursAhead: 24
587
+ });
588
+
589
+ // Listen for price changes
590
+ prices.onPriceChange((newPrice) => {
591
+ console.log(`New electricity price: ${newPrice.pricePerKwh} €/kWh`);
592
+ });
593
+ ```
594
+
595
+ #### `useNotification(): EnergyAppNotification`
596
+
597
+ Send notifications to users:
598
+
599
+ ```typescript
600
+ const notifications = energyApp.useNotification();
601
+
602
+ // Send info notification
603
+ await notifications.sendNotification({
604
+ type: 'info',
605
+ title: 'Energy Optimization',
606
+ message: 'Your system is running optimally',
607
+ timestamp: Date.now()
608
+ });
609
+
610
+ // Send warning
611
+ await notifications.sendNotification({
612
+ type: 'warning',
613
+ title: 'High Energy Consumption',
614
+ message: 'Consider reducing energy usage during peak hours'
615
+ });
26
616
 
617
+ // Send critical alert
618
+ await notifications.sendNotification({
619
+ type: 'error',
620
+ title: 'System Fault',
621
+ message: 'Inverter communication lost - please check connection'
27
622
  });
28
623
  ```
29
624
 
@@ -33,7 +628,7 @@ The SDK includes a powerful, vendor-agnostic Modbus implementation for energy ma
33
628
 
34
629
  ### ✨ Features
35
630
 
36
- - **Vendor Agnostic** - Works with SMA, Fronius, Huawei, or any Modbus device via configuration
631
+ - **Vendor Agnostic** - Works with SMA, Fronius or any Modbus device via configuration
37
632
  - **Type Safe** - Full TypeScript support with proper DataBus message types
38
633
  - **Configurable** - Register addresses, data types, scaling all configurable
39
634
  - **Fault Tolerant** - Built-in connection health monitoring and retry logic
@@ -44,12 +639,12 @@ The SDK includes a powerful, vendor-agnostic Modbus implementation for energy ma
44
639
  #### Basic Modbus Setup
45
640
 
46
641
  ```typescript
47
- import { EnergyApp } from '@enyo/energy-app-sdk';
642
+ import { EnergyApp } from '@enyo-energy/energy-app-sdk';
48
643
  import {
49
644
  EnergyAppModbusInverter,
50
645
  EnergyAppModbusBattery,
51
646
  EnergyAppModbusMeter
52
- } from '@enyo/energy-app-sdk';
647
+ } from '@enyo-energy/energy-app-sdk';
53
648
 
54
649
  const energyApp = new EnergyApp();
55
650
  const dependencies = { client: energyApp, randomUUID: () => crypto.randomUUID() };
@@ -213,4 +808,477 @@ The Modbus implementation follows a clean, modular architecture:
213
808
  - **EnergyAppModbusFaultTolerantReader** - Fault-tolerant communication layer
214
809
  - **EnergyAppModbusConnectionHealth** - Connection health monitoring
215
810
 
216
- This modular design ensures maintainability, testability, and extensibility for future enhancements.
811
+ This modular design ensures maintainability, testability, and extensibility for future enhancements.
812
+
813
+ ## Examples
814
+
815
+ ### Basic Energy App
816
+
817
+ A simple energy monitoring application:
818
+
819
+ ```typescript
820
+ import { EnergyApp, defineEnergyAppPackage } from '@enyo-energy/energy-app-sdk';
821
+
822
+ const energyApp = new EnergyApp();
823
+
824
+ energyApp.register(async (packageName, version) => {
825
+ console.log(`Energy Monitor ${version} starting...`);
826
+
827
+ const storage = energyApp.useStorage();
828
+ const dataBus = energyApp.useDataBus();
829
+ const interval = energyApp.useInterval();
830
+
831
+ // Load configuration
832
+ const config = await storage.load('config') || { enabled: true };
833
+
834
+ // Listen for energy data
835
+ dataBus.listenForMessages(['InverterValuesUpdateV1', 'BatteryValuesUpdateV1'],
836
+ (message) => {
837
+ console.log(`Received ${message.messageType}:`, message.values);
838
+ // Store or process energy data
839
+ }
840
+ );
841
+
842
+ // Periodic health check
843
+ interval.createInterval('5m', async () => {
844
+ const isOnline = energyApp.isSystemOnline();
845
+ await storage.save('lastHealthCheck', {
846
+ timestamp: Date.now(),
847
+ online: isOnline
848
+ });
849
+ });
850
+
851
+ energyApp.updateEnergyAppState('running');
852
+ });
853
+ ```
854
+
855
+ ### Device Integration
856
+
857
+ Comprehensive device management with multiple protocols:
858
+
859
+ ```typescript
860
+ import { EnergyApp } from '@enyo-energy/energy-app-sdk';
861
+
862
+ const energyApp = new EnergyApp();
863
+
864
+ energyApp.register(async (packageName, version) => {
865
+ const networkDevices = energyApp.useNetworkDevices();
866
+ const appliances = energyApp.useAppliances();
867
+ const modbus = energyApp.useModbus();
868
+ const dataBus = energyApp.useDataBus();
869
+
870
+ try {
871
+ // Discover network devices
872
+ console.log('Discovering devices...');
873
+ const devices = await networkDevices.discover();
874
+
875
+ for (const device of devices) {
876
+ console.log(`Found device: ${device.hostname} (${device.manufacturer})`);
877
+
878
+ if (device.manufacturer === 'SMA' && device.protocols?.includes('modbus')) {
879
+ // Create Modbus connection
880
+ const client = await modbus.connect({
881
+ host: device.hostname,
882
+ port: 502,
883
+ unitId: 1
884
+ });
885
+
886
+ // Register as appliance
887
+ const applianceId = await appliances.save({
888
+ name: [{ language: 'en', name: `${device.manufacturer} Inverter` }],
889
+ type: 'inverter',
890
+ manufacturer: device.manufacturer,
891
+ model: device.model || 'Unknown',
892
+ networkDevice: device
893
+ }, undefined);
894
+
895
+ // Start data collection
896
+ const interval = energyApp.useInterval();
897
+ interval.createInterval('30s', async () => {
898
+ try {
899
+ // Read power data (example registers)
900
+ const powerRegs = await client.readHoldingRegisters(30775, 2);
901
+ const power = powerRegs.getInt32BE(0);
902
+
903
+ // Send to data bus
904
+ dataBus.sendMessage([{
905
+ messageType: 'InverterValuesUpdateV1',
906
+ applianceId: applianceId,
907
+ timestamp: Date.now(),
908
+ values: {
909
+ powerW: power,
910
+ voltageV: 230, // Read from appropriate register
911
+ frequencyHz: 50
912
+ }
913
+ }]);
914
+
915
+ } catch (error) {
916
+ console.error('Failed to read from device:', error);
917
+ }
918
+ });
919
+ }
920
+ }
921
+
922
+ energyApp.updateEnergyAppState('running');
923
+
924
+ } catch (error) {
925
+ console.error('Device discovery failed:', error);
926
+ energyApp.updateEnergyAppState('configuration-required');
927
+ }
928
+ });
929
+ ```
930
+
931
+ ### Data Bus Messaging
932
+
933
+ Advanced data processing and message routing:
934
+
935
+ ```typescript
936
+ import { EnergyApp } from '@enyo-energy/energy-app-sdk';
937
+
938
+ const energyApp = new EnergyApp();
939
+
940
+ class EnergyDataProcessor {
941
+ private dataBus = energyApp.useDataBus();
942
+ private storage = energyApp.useStorage();
943
+ private lastValues = new Map();
944
+
945
+ async initialize() {
946
+ // Listen for various energy data types
947
+ this.dataBus.listenForMessages([
948
+ 'InverterValuesUpdateV1',
949
+ 'BatteryValuesUpdateV1',
950
+ 'MeterValuesUpdateV1'
951
+ ], (message) => this.processEnergyData(message));
952
+
953
+ // Listen for commands
954
+ this.dataBus.listenForMessages([
955
+ 'SetPowerLimitCommandV1'
956
+ ], (message) => this.handleCommand(message));
957
+ }
958
+
959
+ private async processEnergyData(message: any) {
960
+ const { messageType, applianceId, values, timestamp } = message;
961
+
962
+ // Store latest values
963
+ this.lastValues.set(applianceId, { messageType, values, timestamp });
964
+
965
+ // Calculate aggregated metrics
966
+ await this.calculateSystemMetrics();
967
+
968
+ // Detect anomalies
969
+ this.detectAnomalies(messageType, values);
970
+ }
971
+
972
+ private async calculateSystemMetrics() {
973
+ let totalPowerW = 0;
974
+ let totalEnergyWh = 0;
975
+ let batterySoC = 0;
976
+
977
+ for (const [applianceId, data] of this.lastValues) {
978
+ if (data.messageType === 'InverterValuesUpdateV1') {
979
+ totalPowerW += data.values.powerW || 0;
980
+ totalEnergyWh += data.values.energyWh || 0;
981
+ } else if (data.messageType === 'BatteryValuesUpdateV1') {
982
+ batterySoC = data.values.stateOfCharge || 0;
983
+ }
984
+ }
985
+
986
+ // Send aggregated metrics
987
+ this.dataBus.sendMessage([{
988
+ messageType: 'SystemMetricsUpdateV1',
989
+ applianceId: 'system',
990
+ timestamp: Date.now(),
991
+ values: {
992
+ totalPowerW,
993
+ totalEnergyWh,
994
+ batterySoC,
995
+ systemEfficiency: this.calculateEfficiency()
996
+ }
997
+ }]);
998
+
999
+ // Store historical data
1000
+ await this.storage.save(`metrics_${Date.now()}`, {
1001
+ totalPowerW,
1002
+ totalEnergyWh,
1003
+ batterySoC,
1004
+ timestamp: Date.now()
1005
+ });
1006
+ }
1007
+
1008
+ private detectAnomalies(messageType: string, values: any) {
1009
+ // Example: Detect power spikes
1010
+ if (messageType === 'InverterValuesUpdateV1' && values.powerW > 10000) {
1011
+ const notifications = energyApp.useNotification();
1012
+ notifications.sendNotification({
1013
+ type: 'warning',
1014
+ title: 'High Power Output',
1015
+ message: `Inverter reporting ${values.powerW}W - check for issues`
1016
+ });
1017
+ }
1018
+ }
1019
+
1020
+ private handleCommand(message: any) {
1021
+ console.log('Received command:', message);
1022
+ // Process control commands
1023
+
1024
+ // Send acknowledgment
1025
+ this.dataBus.sendAnswer({
1026
+ originalMessageId: message.id,
1027
+ success: true,
1028
+ timestamp: Date.now()
1029
+ });
1030
+ }
1031
+
1032
+ private calculateEfficiency(): number {
1033
+ // Implement efficiency calculation logic
1034
+ return 95.5;
1035
+ }
1036
+ }
1037
+
1038
+ energyApp.register(async (packageName, version) => {
1039
+ const processor = new EnergyDataProcessor();
1040
+ await processor.initialize();
1041
+
1042
+ console.log('Energy data processor ready');
1043
+ energyApp.updateEnergyAppState('running');
1044
+ });
1045
+ ```
1046
+
1047
+ ### Settings Management
1048
+
1049
+ Dynamic configuration with user interface:
1050
+
1051
+ ```typescript
1052
+ import { EnergyApp } from '@enyo-energy/energy-app-sdk';
1053
+
1054
+ const energyApp = new EnergyApp();
1055
+
1056
+ class ConfigurableEnergyApp {
1057
+ private settings = energyApp.useSettings();
1058
+ private config = {
1059
+ pollIntervalSec: 30,
1060
+ maxPowerW: 5000,
1061
+ enableNotifications: true,
1062
+ priceThreshold: 0.25
1063
+ };
1064
+
1065
+ async initialize() {
1066
+ // Define app settings
1067
+ await this.setupSettings();
1068
+
1069
+ // Load current settings
1070
+ await this.loadSettings();
1071
+
1072
+ // Listen for setting changes
1073
+ this.settings.listenForSettingsChanges((settingName, newValue) => {
1074
+ this.handleSettingChange(settingName, newValue);
1075
+ });
1076
+ }
1077
+
1078
+ private async setupSettings() {
1079
+ const settingConfigs = [
1080
+ {
1081
+ name: 'pollInterval',
1082
+ displayName: [{ language: 'en', name: 'Data Collection Interval (seconds)' }],
1083
+ description: [{ language: 'en', name: 'How often to collect data from devices' }],
1084
+ type: 'number',
1085
+ defaultValue: '30',
1086
+ validation: {
1087
+ min: 10,
1088
+ max: 300
1089
+ }
1090
+ },
1091
+ {
1092
+ name: 'maxPowerLimit',
1093
+ displayName: [{ language: 'en', name: 'Maximum Power Limit (W)' }],
1094
+ type: 'number',
1095
+ defaultValue: '5000',
1096
+ validation: {
1097
+ min: 1000,
1098
+ max: 20000
1099
+ }
1100
+ },
1101
+ {
1102
+ name: 'enableNotifications',
1103
+ displayName: [{ language: 'en', name: 'Enable Notifications' }],
1104
+ type: 'boolean',
1105
+ defaultValue: 'true'
1106
+ },
1107
+ {
1108
+ name: 'electricityPriceThreshold',
1109
+ displayName: [{ language: 'en', name: 'Price Alert Threshold (€/kWh)' }],
1110
+ type: 'number',
1111
+ defaultValue: '0.25',
1112
+ validation: {
1113
+ min: 0.01,
1114
+ max: 1.0,
1115
+ step: 0.01
1116
+ }
1117
+ }
1118
+ ];
1119
+
1120
+ // Add all settings
1121
+ for (const config of settingConfigs) {
1122
+ await this.settings.addSettingConfig(config);
1123
+ }
1124
+ }
1125
+
1126
+ private async loadSettings() {
1127
+ const allSettings = await this.settings.getSettingsConfig();
1128
+
1129
+ for (const setting of allSettings) {
1130
+ switch (setting.name) {
1131
+ case 'pollInterval':
1132
+ this.config.pollIntervalSec = parseInt(setting.currentValue);
1133
+ break;
1134
+ case 'maxPowerLimit':
1135
+ this.config.maxPowerW = parseInt(setting.currentValue);
1136
+ break;
1137
+ case 'enableNotifications':
1138
+ this.config.enableNotifications = setting.currentValue === 'true';
1139
+ break;
1140
+ case 'electricityPriceThreshold':
1141
+ this.config.priceThreshold = parseFloat(setting.currentValue);
1142
+ break;
1143
+ }
1144
+ }
1145
+
1146
+ console.log('Loaded configuration:', this.config);
1147
+ }
1148
+
1149
+ private async handleSettingChange(settingName: string, newValue: string) {
1150
+ console.log(`Setting ${settingName} changed to: ${newValue}`);
1151
+
1152
+ switch (settingName) {
1153
+ case 'pollInterval':
1154
+ this.config.pollIntervalSec = parseInt(newValue);
1155
+ await this.restartDataCollection();
1156
+ break;
1157
+ case 'maxPowerLimit':
1158
+ this.config.maxPowerW = parseInt(newValue);
1159
+ await this.updatePowerLimits();
1160
+ break;
1161
+ case 'enableNotifications':
1162
+ this.config.enableNotifications = newValue === 'true';
1163
+ break;
1164
+ case 'electricityPriceThreshold':
1165
+ this.config.priceThreshold = parseFloat(newValue);
1166
+ await this.updatePriceAlerts();
1167
+ break;
1168
+ }
1169
+ }
1170
+
1171
+ private async restartDataCollection() {
1172
+ // Restart intervals with new timing
1173
+ console.log(`Restarting data collection with ${this.config.pollIntervalSec}s interval`);
1174
+ }
1175
+
1176
+ private async updatePowerLimits() {
1177
+ // Apply new power limits to devices
1178
+ console.log(`Setting maximum power limit to ${this.config.maxPowerW}W`);
1179
+ }
1180
+
1181
+ private async updatePriceAlerts() {
1182
+ // Update electricity price monitoring
1183
+ const prices = energyApp.useElectricityPrices();
1184
+ prices.onPriceChange((newPrice) => {
1185
+ if (this.config.enableNotifications &&
1186
+ newPrice.pricePerKwh > this.config.priceThreshold) {
1187
+
1188
+ const notifications = energyApp.useNotification();
1189
+ notifications.sendNotification({
1190
+ type: 'info',
1191
+ title: 'High Electricity Price',
1192
+ message: `Current price ${newPrice.pricePerKwh}€/kWh exceeds threshold`
1193
+ });
1194
+ }
1195
+ });
1196
+ }
1197
+ }
1198
+
1199
+ energyApp.register(async (packageName, version) => {
1200
+ const app = new ConfigurableEnergyApp();
1201
+ await app.initialize();
1202
+
1203
+ energyApp.updateEnergyAppState('running');
1204
+ console.log('Configurable Energy App ready');
1205
+ });
1206
+ ```
1207
+
1208
+ ## Troubleshooting
1209
+
1210
+ ### Common Issues
1211
+
1212
+ #### `Missing energyAppSdk instance`
1213
+ This error occurs when running outside the enyo runtime environment. For development, ensure your app is properly packaged and deployed to the enyo system.
1214
+
1215
+ #### Permission Denied Errors
1216
+ - Check your package definition includes required permissions
1217
+ - Verify the permission names match exactly (case-sensitive)
1218
+ - Some permissions like `AllAppliances` require special approval
1219
+
1220
+ #### Modbus Connection Failures
1221
+ - Verify network device is reachable
1222
+ - Check Modbus unit ID and register addresses
1223
+ - Ensure device supports the Modbus protocol version you're using
1224
+ - Use connection health monitoring to detect issues
1225
+
1226
+ #### Data Bus Message Not Received
1227
+ - Confirm you have `SubscribeDataBus` permission
1228
+ - Check message type names are exact matches
1229
+ - Verify the listener is registered before messages are sent
1230
+
1231
+ ### Best Practices
1232
+
1233
+ #### Error Handling
1234
+ Always wrap async operations in try-catch blocks:
1235
+
1236
+ ```typescript
1237
+ try {
1238
+ await energyApp.useStorage().save('key', data);
1239
+ } catch (error) {
1240
+ console.error('Storage operation failed:', error);
1241
+ // Handle gracefully
1242
+ }
1243
+ ```
1244
+
1245
+ #### Resource Cleanup
1246
+ Register cleanup handlers for graceful shutdown:
1247
+
1248
+ ```typescript
1249
+ energyApp.onShutdown(async () => {
1250
+ // Clean up intervals
1251
+ interval.stopInterval(intervalId);
1252
+ // Close connections
1253
+ await modbusClient.disconnect();
1254
+ // Save state
1255
+ await storage.save('lastShutdown', Date.now());
1256
+ });
1257
+ ```
1258
+
1259
+ #### State Management
1260
+ Always update your app state appropriately:
1261
+
1262
+ ```typescript
1263
+ // On successful initialization
1264
+ energyApp.updateEnergyAppState('running');
1265
+
1266
+ // When configuration is needed
1267
+ energyApp.updateEnergyAppState('configuration-required');
1268
+
1269
+ // When internet is required
1270
+ energyApp.updateEnergyAppState('internet-connection-required');
1271
+ ```
1272
+
1273
+ ## CLI Tool
1274
+
1275
+ Use the enyo CLI to initialize projects and publish Energy Apps easily. The CLI provides scaffolding, testing, and deployment capabilities for rapid development.
1276
+
1277
+ For CLI documentation and installation instructions, visit the [enyo CLI repository](https://github.com/enyo-energy/enyo-cli).
1278
+
1279
+ ---
1280
+
1281
+ **Package Version:** 0.0.34
1282
+ **SDK Version:** Auto-injected during build
1283
+ **License:** ISC
1284
+ **Repository:** [github.com/enyo-energy/energy-app-sdk](https://github.com/enyo-energy/energy-app-sdk)