@alwaysai/device-agent 0.0.13 → 0.0.15

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 (151) hide show
  1. package/lib/application-control/backup.js +3 -3
  2. package/lib/application-control/backup.js.map +1 -1
  3. package/lib/application-control/index.d.ts +4 -4
  4. package/lib/application-control/index.d.ts.map +1 -1
  5. package/lib/application-control/index.js +1 -4
  6. package/lib/application-control/index.js.map +1 -1
  7. package/lib/application-control/install.d.ts +1 -1
  8. package/lib/application-control/install.d.ts.map +1 -1
  9. package/lib/application-control/install.js +41 -54
  10. package/lib/application-control/install.js.map +1 -1
  11. package/lib/application-control/models.d.ts +0 -4
  12. package/lib/application-control/models.d.ts.map +1 -1
  13. package/lib/application-control/models.js +13 -22
  14. package/lib/application-control/models.js.map +1 -1
  15. package/lib/application-control/status.d.ts +0 -6
  16. package/lib/application-control/status.d.ts.map +1 -1
  17. package/lib/application-control/status.js +3 -19
  18. package/lib/application-control/status.js.map +1 -1
  19. package/lib/application-control/utils.d.ts +3 -0
  20. package/lib/application-control/utils.d.ts.map +1 -1
  21. package/lib/application-control/utils.js +50 -21
  22. package/lib/application-control/utils.js.map +1 -1
  23. package/lib/cloud-connection/bootstrap-provision.d.ts +1 -1
  24. package/lib/cloud-connection/bootstrap-provision.d.ts.map +1 -1
  25. package/lib/cloud-connection/bootstrap-provision.js +9 -9
  26. package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
  27. package/lib/cloud-connection/cmd-status.d.ts +8 -0
  28. package/lib/cloud-connection/cmd-status.d.ts.map +1 -0
  29. package/lib/cloud-connection/cmd-status.js +62 -0
  30. package/lib/cloud-connection/cmd-status.js.map +1 -0
  31. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +10 -2
  32. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  33. package/lib/cloud-connection/device-agent-cloud-connection.js +156 -66
  34. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  35. package/lib/cloud-connection/device-agent.d.ts.map +1 -1
  36. package/lib/cloud-connection/device-agent.js +4 -3
  37. package/lib/cloud-connection/device-agent.js.map +1 -1
  38. package/lib/cloud-connection/live-updates-handler.d.ts +10 -18
  39. package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
  40. package/lib/cloud-connection/live-updates-handler.js +50 -50
  41. package/lib/cloud-connection/live-updates-handler.js.map +1 -1
  42. package/lib/cloud-connection/messages.d.ts +3 -1
  43. package/lib/cloud-connection/messages.d.ts.map +1 -1
  44. package/lib/cloud-connection/messages.js +13 -1
  45. package/lib/cloud-connection/messages.js.map +1 -1
  46. package/lib/cloud-connection/passthrough-handler.d.ts +11 -0
  47. package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -0
  48. package/lib/cloud-connection/passthrough-handler.js +59 -0
  49. package/lib/cloud-connection/passthrough-handler.js.map +1 -0
  50. package/lib/cloud-connection/publisher.d.ts +1 -0
  51. package/lib/cloud-connection/publisher.d.ts.map +1 -1
  52. package/lib/cloud-connection/publisher.js +14 -0
  53. package/lib/cloud-connection/publisher.js.map +1 -1
  54. package/lib/cloud-connection/shadow-handler.d.ts +2 -3
  55. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  56. package/lib/cloud-connection/shadow-handler.js +18 -4
  57. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  58. package/lib/cloud-connection/shadow-handler.test.d.ts +2 -0
  59. package/lib/cloud-connection/shadow-handler.test.d.ts.map +1 -0
  60. package/lib/cloud-connection/shadow-handler.test.js +321 -0
  61. package/lib/cloud-connection/shadow-handler.test.js.map +1 -0
  62. package/lib/environment.d.ts +1 -0
  63. package/lib/environment.d.ts.map +1 -1
  64. package/lib/environment.js +3 -2
  65. package/lib/environment.js.map +1 -1
  66. package/lib/index.js +2 -2
  67. package/lib/index.js.map +1 -1
  68. package/lib/infrastructure/agent-config.d.ts +15 -48
  69. package/lib/infrastructure/agent-config.d.ts.map +1 -1
  70. package/lib/infrastructure/agent-config.js.map +1 -1
  71. package/lib/infrastructure/agent-config.test.js +0 -6
  72. package/lib/infrastructure/agent-config.test.js.map +1 -1
  73. package/lib/infrastructure/system-id.js +2 -2
  74. package/lib/infrastructure/system-id.js.map +1 -1
  75. package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
  76. package/lib/infrastructure/tokens-and-device-cfg.js +5 -9
  77. package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
  78. package/lib/local-connection/rabbitmq-connection.d.ts +4 -0
  79. package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -0
  80. package/lib/local-connection/rabbitmq-connection.js +58 -0
  81. package/lib/local-connection/rabbitmq-connection.js.map +1 -0
  82. package/lib/subcommands/app/app.d.ts +4 -3
  83. package/lib/subcommands/app/app.d.ts.map +1 -1
  84. package/lib/subcommands/app/app.js +78 -27
  85. package/lib/subcommands/app/app.js.map +1 -1
  86. package/lib/subcommands/app/index.js +2 -2
  87. package/lib/subcommands/device/clean.js +4 -4
  88. package/lib/subcommands/device/clean.js.map +1 -1
  89. package/lib/subcommands/device/device.d.ts +1 -1
  90. package/lib/subcommands/device/device.d.ts.map +1 -1
  91. package/lib/subcommands/device/device.js +9 -10
  92. package/lib/subcommands/device/device.js.map +1 -1
  93. package/lib/subcommands/index.d.ts +0 -1
  94. package/lib/subcommands/index.d.ts.map +1 -1
  95. package/lib/subcommands/login.d.ts +0 -1
  96. package/lib/subcommands/login.d.ts.map +1 -1
  97. package/lib/subcommands/login.js +1 -9
  98. package/lib/subcommands/login.js.map +1 -1
  99. package/lib/util/directories.d.ts +11 -12
  100. package/lib/util/directories.d.ts.map +1 -1
  101. package/lib/util/directories.js +24 -29
  102. package/lib/util/directories.js.map +1 -1
  103. package/lib/util/fetch-with-timeout.d.ts +4 -0
  104. package/lib/util/fetch-with-timeout.d.ts.map +1 -0
  105. package/lib/util/fetch-with-timeout.js +15 -0
  106. package/lib/util/fetch-with-timeout.js.map +1 -0
  107. package/lib/util/logger.js +1 -0
  108. package/lib/util/logger.js.map +1 -1
  109. package/lib/util/require-logged-in-and-paid-plan.d.ts +2 -0
  110. package/lib/util/require-logged-in-and-paid-plan.d.ts.map +1 -0
  111. package/lib/util/require-logged-in-and-paid-plan.js +18 -0
  112. package/lib/util/require-logged-in-and-paid-plan.js.map +1 -0
  113. package/package.json +20 -32
  114. package/readme.md +100 -89
  115. package/src/application-control/backup.ts +3 -3
  116. package/src/application-control/index.ts +0 -6
  117. package/src/application-control/install.ts +53 -73
  118. package/src/application-control/models.ts +7 -19
  119. package/src/application-control/status.ts +3 -19
  120. package/src/application-control/utils.ts +61 -22
  121. package/src/cloud-connection/bootstrap-provision.ts +13 -10
  122. package/src/cloud-connection/cmd-status.ts +71 -0
  123. package/src/cloud-connection/device-agent-cloud-connection.ts +211 -102
  124. package/src/cloud-connection/device-agent.ts +7 -4
  125. package/src/cloud-connection/live-updates-handler.ts +79 -86
  126. package/src/cloud-connection/messages.ts +22 -1
  127. package/src/cloud-connection/passthrough-handler.ts +67 -0
  128. package/src/cloud-connection/publisher.ts +21 -0
  129. package/src/cloud-connection/shadow-handler.test.ts +361 -0
  130. package/src/cloud-connection/shadow-handler.ts +28 -7
  131. package/src/environment.ts +4 -1
  132. package/src/index.ts +2 -2
  133. package/src/infrastructure/agent-config.test.ts +0 -7
  134. package/src/infrastructure/agent-config.ts +24 -2
  135. package/src/infrastructure/system-id.ts +1 -1
  136. package/src/infrastructure/tokens-and-device-cfg.ts +8 -13
  137. package/src/local-connection/rabbitmq-connection.ts +53 -0
  138. package/src/subcommands/app/app.ts +82 -31
  139. package/src/subcommands/app/index.ts +4 -4
  140. package/src/subcommands/device/clean.ts +4 -4
  141. package/src/subcommands/device/device.ts +13 -13
  142. package/src/subcommands/login.ts +1 -9
  143. package/src/util/directories.ts +31 -29
  144. package/src/util/fetch-with-timeout.ts +18 -0
  145. package/src/util/logger.ts +2 -0
  146. package/src/util/require-logged-in-and-paid-plan.ts +16 -0
  147. package/lib/cloud-connection/app-install-status.d.ts +0 -16
  148. package/lib/cloud-connection/app-install-status.d.ts.map +0 -1
  149. package/lib/cloud-connection/app-install-status.js +0 -53
  150. package/lib/cloud-connection/app-install-status.js.map +0 -1
  151. package/src/cloud-connection/app-install-status.ts +0 -62
@@ -3,11 +3,11 @@ const awsIot = require('aws-iot-device-sdk');
3
3
  import { getIoTCoreEndpointUrl } from '../infrastructure/urls';
4
4
  import { existsSync } from 'fs';
5
5
  import {
6
- getPrivateKeyFilePath,
7
- getCertificateFilePath,
8
- BOOTSTRAP_DEVICE_PRIVATE_KEY_FILE_PATH,
6
+ BOOTSTRAP_PRIVATE_KEY_FILE_PATH,
9
7
  AWS_ROOT_CERTIFICATE_FILE_PATH,
10
- BOOTSTRAP_CERTIFICATES_DIR_PATH
8
+ BOOTSTRAP_CERTIFICATES_DIR_PATH,
9
+ DEVICE_PRIVATE_KEY_FILE_PATH,
10
+ DEVICE_CERTIFICATE_FILE_PATH
11
11
  } from '../util/directories';
12
12
  import {
13
13
  keyMirrors,
@@ -31,18 +31,21 @@ import {
31
31
  uninstallApp,
32
32
  updateAppCfg
33
33
  } from '../application-control';
34
- import { AppConfigUpdate, ShadowHandler } from './shadow-handler';
34
+ import { AppConfigUpdate, ShadowHandler, ShadowTopics } from './shadow-handler';
35
35
  import { Publisher } from './publisher';
36
36
  import { LiveUpdatesHandler } from './live-updates-handler';
37
37
  import { bootstrapProvision } from './bootstrap-provision';
38
- import { AppInstallStatusManager } from './app-install-status';
39
38
  import { AppConfig } from '@alwaysai/app-configuration-schemas';
39
+ import { CmdStatusManager } from './cmd-status';
40
+ import { PassthroughHandler, runChannel } from './passthrough-handler';
41
+ import { ALWAYSAI_ANALYTICS_PASSTHROUGH } from '../environment';
42
+ import { getAppInstallStatusMessage } from './messages';
40
43
 
41
44
  export class DeviceAgentCloudConnection {
42
45
  private shadowHandler: ShadowHandler;
43
- private publisher: Publisher;
46
+ public publisher: Publisher;
47
+ private cmdStatusMgr: CmdStatusManager;
44
48
  private liveUpdatesHandler: LiveUpdatesHandler;
45
- private appInstallStatusMgr: AppInstallStatusManager;
46
49
  private device = awsIot.device;
47
50
 
48
51
  private clientId = getDeviceUuid();
@@ -51,38 +54,62 @@ export class DeviceAgentCloudConnection {
51
54
  // FIXME: Add support for multiple simultaneous project updates
52
55
  private newAppCfgQueue: AppConfig[] = [];
53
56
 
54
- private handleAppStateControl(payload: AppStateControlPacket) {
57
+ private async handleAppStateControl(payload: AppStateControlPacket) {
55
58
  const { baseCommand, projectId } = payload;
56
59
  switch (baseCommand) {
57
60
  case keyMirrors.appStateControl.start:
58
- startApp({ projectId });
61
+ await startApp({ projectId });
59
62
  break;
60
63
  case keyMirrors.appStateControl.stop:
61
- stopApp({ projectId });
64
+ await stopApp({ projectId });
62
65
  break;
63
66
  case keyMirrors.appStateControl.restart:
64
- restartApp({ projectId });
67
+ await restartApp({ projectId });
65
68
  break;
66
69
  }
67
70
  }
68
71
 
69
- private handleAppVersionControl(payload: AppVersionControlPacket) {
70
- const { projectId, appReleaseHash } = payload;
71
- const signedUrlsRequest = { projectId, appReleaseHash };
72
- this.publishCloudRequest({
73
- messageType: keyMirrors.agentMessageType.signed_urls_request,
74
- signedUrlsRequest
75
- });
72
+ private async handleAppVersionControl(payload: AppVersionControlPacket) {
73
+ switch (payload.baseCommand) {
74
+ case keyMirrors.appVersionControl.install: {
75
+ const { projectId, appReleaseHash } = payload;
76
+ await this.cmdStatusMgr.start(projectId);
77
+ await this.liveUpdatesHandler.enableAppInstallStatus({
78
+ projectId,
79
+ appReleaseHash
80
+ });
81
+
82
+ const signedUrlsRequest = { projectId, appReleaseHash };
83
+ await this.publishCloudRequest({
84
+ messageType: keyMirrors.agentMessageType.signed_urls_request,
85
+ signedUrlsRequest
86
+ });
87
+ break;
88
+ }
89
+ case keyMirrors.appVersionControl.uninstall: {
90
+ const { projectId } = payload;
91
+ await this.atomicApplicationUninstall(projectId);
92
+ break;
93
+ }
94
+ default:
95
+ logger.warn(
96
+ `Ignore App Version Control packet: ${JSON.stringify(
97
+ payload,
98
+ null,
99
+ 2
100
+ )}`
101
+ );
102
+ }
76
103
  }
77
104
 
78
105
  private handleDeviceCommand = async (packet: any) => {
79
106
  // TODO
80
107
  };
81
108
 
82
- private handleAgentCommand(message: LiveUpdatesToggleMessage) {
109
+ private async handleAgentCommand(message: LiveUpdatesToggleMessage) {
83
110
  switch (message.messageType) {
84
111
  case keyMirrors.clientMessageType.live_state_updates:
85
- this.liveUpdatesHandler.update(message.liveUpdatesToggles);
112
+ await this.liveUpdatesHandler.handleToggles(message.liveUpdatesToggles);
86
113
  break;
87
114
  default:
88
115
  logger.error(
@@ -100,6 +127,49 @@ export class DeviceAgentCloudConnection {
100
127
  this.device.subscribe(topic);
101
128
  }
102
129
 
130
+ private async atomicApplicationUninstall(projectId: string) {
131
+ const appReleaseHash = await AgentConfigFile().getAppVersion({
132
+ projectId
133
+ });
134
+ await this.cmdStatusMgr.start(projectId);
135
+ await this.liveUpdatesHandler.enableAppInstallStatus({
136
+ projectId,
137
+ appReleaseHash
138
+ });
139
+ try {
140
+ await uninstallApp({ projectId });
141
+ this.shadowHandler.deleteProjectShadow(projectId);
142
+
143
+ await this.cmdStatusMgr.stop(projectId);
144
+ await this.liveUpdatesHandler.disableAppInstallStatus({
145
+ projectId
146
+ });
147
+ // Send final status message
148
+ this.publisher.publishToClient(
149
+ await getAppInstallStatusMessage(
150
+ keyMirrors.appInstallStatus.success,
151
+ '',
152
+ appReleaseHash
153
+ )
154
+ );
155
+ } catch (e) {
156
+ logger.error(`Failed to uninstall ${projectId}: ${e}`);
157
+ const message: string = e.message;
158
+ await this.cmdStatusMgr.stop(projectId);
159
+ await this.liveUpdatesHandler.disableAppInstallStatus({
160
+ projectId
161
+ });
162
+ // Send final status message
163
+ this.publisher.publishToClient(
164
+ await getAppInstallStatusMessage(
165
+ keyMirrors.appInstallStatus.failure,
166
+ message,
167
+ appReleaseHash
168
+ )
169
+ );
170
+ }
171
+ }
172
+
103
173
  // eslint-disable-next-line
104
174
  private async atomicApplicationUpdate<T extends any[], R extends any>(
105
175
  func: (...args: T) => R,
@@ -107,53 +177,67 @@ export class DeviceAgentCloudConnection {
107
177
  projectId: string,
108
178
  appReleaseHash: string
109
179
  ) {
110
- this.appInstallStatusMgr.update(
111
- appReleaseHash,
112
- keyMirrors.appInstallStatus.in_progress
113
- );
114
-
115
- this.liveUpdatesHandler.update({
116
- appInstallStatus: { toggle: true, appReleaseHash }
180
+ await this.cmdStatusMgr.start(projectId);
181
+ await this.liveUpdatesHandler.enableAppInstallStatus({
182
+ projectId,
183
+ appReleaseHash
117
184
  });
118
185
 
119
186
  // Install the app and models
120
187
  try {
121
188
  const out: R = await func(...args);
122
- this.appInstallStatusMgr.update(
123
- appReleaseHash,
124
- keyMirrors.appInstallStatus.success
125
- );
126
- this.liveUpdatesHandler.update({
127
- appInstallStatus: { toggle: false, appReleaseHash }
189
+ await this.cmdStatusMgr.stop(projectId);
190
+ await this.liveUpdatesHandler.disableAppInstallStatus({
191
+ projectId
128
192
  });
193
+ // Send final status message
194
+ this.publisher.publishToClient(
195
+ await getAppInstallStatusMessage(
196
+ keyMirrors.appInstallStatus.success,
197
+ '',
198
+ appReleaseHash
199
+ )
200
+ );
129
201
 
130
202
  // update app config shadow for project
131
203
  await this.shadowHandler.publishAppState(projectId);
132
204
  return out;
133
205
  } catch (e) {
134
- logger.error(e);
206
+ logger.error(`Failed to install ${projectId}: ${e}`);
135
207
  const message: string = e.message;
136
208
 
137
209
  // uninstall the failed app to put system back in good state
210
+ // TODO: Replace this with rollback
138
211
  await uninstallApp({ projectId });
139
- this.appInstallStatusMgr.update(
140
- appReleaseHash,
141
- keyMirrors.appInstallStatus.failure,
142
- message
143
- );
144
- this.liveUpdatesHandler.update({
145
- appInstallStatus: { toggle: false, appReleaseHash }
146
- });
212
+ this.shadowHandler.deleteProjectShadow(projectId);
147
213
 
148
- // delete shadow for project
149
- // FIXME: Why do we delete the shadow? Doesn't this delete it for all projects?
150
- this.shadowHandler.deleteProjectShadow();
214
+ await this.cmdStatusMgr.stop(projectId);
215
+ await this.liveUpdatesHandler.disableAppInstallStatus({
216
+ projectId
217
+ });
218
+ // Send final status message
219
+ this.publisher.publishToClient(
220
+ await getAppInstallStatusMessage(
221
+ keyMirrors.appInstallStatus.failure,
222
+ message,
223
+ appReleaseHash
224
+ )
225
+ );
151
226
  }
152
227
  }
153
228
 
154
- private async handleAppConfigUpdates(appConfgUpdates: AppConfigUpdate[]) {
155
- for (const appConfigUpdate of appConfgUpdates) {
229
+ private async handleAppConfigUpdates(appCfgUpdates: AppConfigUpdate[]) {
230
+ for (const appConfigUpdate of appCfgUpdates) {
156
231
  const { projectId, newAppCfg, updatedModels } = appConfigUpdate;
232
+ const appReleaseHash = await AgentConfigFile().getAppVersion({
233
+ projectId
234
+ });
235
+ await this.cmdStatusMgr.start(projectId);
236
+ await this.liveUpdatesHandler.enableAppInstallStatus({
237
+ projectId,
238
+ appReleaseHash
239
+ });
240
+
157
241
  if (updatedModels && Object.keys(updatedModels).length) {
158
242
  // Publish request for model urls
159
243
  this.newAppCfgQueue.push(newAppCfg);
@@ -193,12 +277,14 @@ export class DeviceAgentCloudConnection {
193
277
  }
194
278
  }
195
279
 
196
- // Public Methods
280
+ /*=================================================================
281
+ Public interface
282
+ =================================================================*/
197
283
 
198
284
  constructor() {
199
285
  this.device = awsIot.device({
200
- keyPath: getPrivateKeyFilePath(),
201
- certPath: getCertificateFilePath(),
286
+ keyPath: DEVICE_PRIVATE_KEY_FILE_PATH,
287
+ certPath: DEVICE_CERTIFICATE_FILE_PATH,
202
288
  caPath: AWS_ROOT_CERTIFICATE_FILE_PATH,
203
289
  clientId: this.clientId,
204
290
  host: this.host,
@@ -207,11 +293,8 @@ export class DeviceAgentCloudConnection {
207
293
  });
208
294
  this.publisher = new Publisher(this.device, this.clientId);
209
295
  this.shadowHandler = new ShadowHandler(this.clientId, this.publisher);
210
- this.appInstallStatusMgr = new AppInstallStatusManager();
211
- this.liveUpdatesHandler = new LiveUpdatesHandler(
212
- this.publisher,
213
- this.appInstallStatusMgr
214
- );
296
+ this.cmdStatusMgr = new CmdStatusManager();
297
+ this.liveUpdatesHandler = new LiveUpdatesHandler(this.publisher);
215
298
 
216
299
  this.subscribe(this.toDeviceTopic);
217
300
  this.subscribe(this.shadowHandler.shadowTopics.projects.getAccepted);
@@ -222,6 +305,18 @@ export class DeviceAgentCloudConnection {
222
305
  return this.clientId;
223
306
  }
224
307
 
308
+ public getToDeviceTopic() {
309
+ return this.toDeviceTopic;
310
+ }
311
+
312
+ public getShadowTopics(): ShadowTopics {
313
+ return this.shadowHandler.shadowTopics;
314
+ }
315
+
316
+ public isCmdInProgress(projectId: string): boolean {
317
+ return this.cmdStatusMgr.isCmdInProgress(projectId);
318
+ }
319
+
225
320
  public async handleClientMessage({
226
321
  topic,
227
322
  message
@@ -229,18 +324,29 @@ export class DeviceAgentCloudConnection {
229
324
  topic: string;
230
325
  message: ClientMessage;
231
326
  }) {
327
+ const valid = validateClientMessage(message);
328
+ if (!valid) {
329
+ logger.error(
330
+ `Error validating message: ${JSON.stringify(
331
+ { topic, message, errors: validateClientMessage.errors },
332
+ null,
333
+ 2
334
+ )}`
335
+ );
336
+ return;
337
+ }
232
338
  const payload = message.payload;
233
339
  switch (payload.messageType) {
234
340
  case keyMirrors.clientMessageType.app_state_control: {
235
- this.handleAppStateControl(payload.appStateControl);
341
+ await this.handleAppStateControl(payload.appStateControl);
236
342
  break;
237
343
  }
238
344
  case keyMirrors.clientMessageType.app_version_control: {
239
- this.handleAppVersionControl(payload.appVersionControl);
345
+ await this.handleAppVersionControl(payload.appVersionControl);
240
346
  break;
241
347
  }
242
348
  case keyMirrors.clientMessageType.live_state_updates: {
243
- this.handleAgentCommand(payload);
349
+ await this.handleAgentCommand(payload);
244
350
  break;
245
351
  }
246
352
  case keyMirrors.clientMessageType.app_install_cloud_response: {
@@ -271,9 +377,10 @@ export class DeviceAgentCloudConnection {
271
377
 
272
378
  const newAppCfg = this.newAppCfgQueue.shift();
273
379
  if (newAppCfg === undefined) {
274
- throw new Error(
380
+ logger.error(
275
381
  'Unknown error while updating models via application config! No config present for model update.'
276
382
  );
383
+ return;
277
384
  }
278
385
 
279
386
  await this.atomicApplicationUpdate(
@@ -303,11 +410,35 @@ export class DeviceAgentCloudConnection {
303
410
  }
304
411
  }
305
412
 
413
+ public async handleMessage(topic: string, message: ClientMessage | any) {
414
+ logger.debug(
415
+ `Received message: ${JSON.stringify({ topic, message }, null, 2)}`
416
+ );
417
+ switch (topic) {
418
+ case this.shadowHandler.shadowTopics.projects.getAccepted:
419
+ case this.shadowHandler.shadowTopics.projects.updateDelta: {
420
+ const appConfigUpdates = await this.shadowHandler.handleShadowTopic({
421
+ topic,
422
+ payload: message.state
423
+ });
424
+ await this.handleAppConfigUpdates(appConfigUpdates);
425
+ break;
426
+ }
427
+ case this.toDeviceTopic:
428
+ await this.handleClientMessage({
429
+ topic,
430
+ message
431
+ });
432
+ break;
433
+ default:
434
+ logger.error(`Unexpected topic, ignoring! ${topic}`);
435
+ }
436
+ }
437
+
306
438
  public async setupHandlers() {
307
439
  this.device.on('connect', (connack: any) => {
308
440
  logger.info('Device Agent has connected to the cloud');
309
441
 
310
- // Get shadow updates
311
442
  this.shadowHandler.getShadowUpdates();
312
443
  });
313
444
 
@@ -321,47 +452,15 @@ export class DeviceAgentCloudConnection {
321
452
  );
322
453
  });
323
454
 
455
+ this.device.on('error', function (error) {
456
+ const errorString = error.message.toString();
457
+ logger.error(`${errorString}`);
458
+ });
459
+
324
460
  this.device.on('message', async (topic: string, payload: string) => {
325
461
  try {
326
462
  const jsonPacket = JSON.parse(payload);
327
- logger.debug(
328
- `Received message: ${JSON.stringify({ topic, jsonPacket }, null, 2)}`
329
- );
330
-
331
- if (Object.prototype.hasOwnProperty.call(jsonPacket, 'state')) {
332
- if (jsonPacket.clientToken === this.getClientId()) {
333
- logger.debug(
334
- `Ignoring message sent from self: ${JSON.stringify(
335
- { topic, jsonPacket },
336
- null,
337
- 2
338
- )}`
339
- );
340
- return;
341
- }
342
-
343
- const appConfigUpdates = await this.shadowHandler.handleShadowTopic({
344
- topic,
345
- payload: jsonPacket.state
346
- });
347
- await this.handleAppConfigUpdates(appConfigUpdates);
348
- } else {
349
- const valid = validateClientMessage(jsonPacket);
350
- if (!valid) {
351
- logger.error(
352
- `Error validating message: ${JSON.stringify(
353
- validateClientMessage.errors,
354
- null,
355
- 2
356
- )}`
357
- );
358
- } else {
359
- this.handleClientMessage({
360
- topic,
361
- message: jsonPacket
362
- });
363
- }
364
- }
463
+ await this.handleMessage(topic, jsonPacket);
365
464
  } catch (error) {
366
465
  logger.error(`Error parsing message: ${error}`);
367
466
  }
@@ -371,15 +470,25 @@ export class DeviceAgentCloudConnection {
371
470
  logger.warn(`Device Agent is offline ${new Date().toLocaleString()}`);
372
471
  });
373
472
  }
473
+
474
+ public stop() {
475
+ this.device.end();
476
+ }
374
477
  }
375
478
 
376
479
  export async function runDeviceAgentCloudInterface() {
377
480
  // FIXME: Check for KeyPath as well
378
- if (existsSync(getCertificateFilePath())) {
481
+ if (existsSync(DEVICE_CERTIFICATE_FILE_PATH)) {
379
482
  const deviceAgent = new DeviceAgentCloudConnection();
380
483
  await deviceAgent.setupHandlers();
381
- } else if (existsSync(BOOTSTRAP_DEVICE_PRIVATE_KEY_FILE_PATH())) {
382
- bootstrapProvision();
484
+ if (ALWAYSAI_ANALYTICS_PASSTHROUGH === true) {
485
+ const publisher = deviceAgent.publisher;
486
+ const passthroughHandler = new PassthroughHandler(publisher);
487
+ await passthroughHandler.setup();
488
+ await runChannel(passthroughHandler);
489
+ }
490
+ } else if (existsSync(BOOTSTRAP_PRIVATE_KEY_FILE_PATH())) {
491
+ await bootstrapProvision();
383
492
  } else if (existsSync(BOOTSTRAP_CERTIFICATES_DIR_PATH())) {
384
493
  throw new Error(
385
494
  "Device has not been created using 'aai-agent device init' or there has been an issue with device initialization"
@@ -3,7 +3,7 @@ const awsIot = require('aws-iot-device-sdk');
3
3
  import {
4
4
  DEVICE_PRIVATE_KEY_FILE_NAME,
5
5
  CERTIFICATE_OWNERSHIP_TOKEN_FILE_NAME,
6
- DEVICE_CLAIM_ID_FILE_NAME,
6
+ DEVICE_ID_FILE_NAME,
7
7
  DEVICE_CERTIFICATE_FILE_NAME
8
8
  } from '../util/directories';
9
9
  import { getDeviceUuid } from '../util/get-device-id';
@@ -66,6 +66,9 @@ export class BootstrapAgent extends DeviceAgent {
66
66
  public async handleAwsCertificateTopics(topic: string, payload: any) {
67
67
  switch (topic) {
68
68
  case '$aws/certificates/create/json/accepted': {
69
+ logger.debug(
70
+ `Received Certs: ${JSON.stringify(JSON.parse(payload), null, 2)}`
71
+ );
69
72
  const {
70
73
  certificateId,
71
74
  certificatePem,
@@ -76,13 +79,13 @@ export class BootstrapAgent extends DeviceAgent {
76
79
  const certSpawner = JsSpawner({ path: LOCAL_CERT_AND_KEY_DIR });
77
80
 
78
81
  await certSpawner.writeFile(
79
- DEVICE_CERTIFICATE_FILE_NAME(),
82
+ DEVICE_CERTIFICATE_FILE_NAME,
80
83
  certificatePem
81
84
  );
82
85
 
83
- await certSpawner.writeFile(DEVICE_PRIVATE_KEY_FILE_NAME(), privateKey);
86
+ await certSpawner.writeFile(DEVICE_PRIVATE_KEY_FILE_NAME, privateKey);
84
87
 
85
- await certSpawner.writeFile(DEVICE_CLAIM_ID_FILE_NAME(), certificateId);
88
+ await certSpawner.writeFile(DEVICE_ID_FILE_NAME, certificateId);
86
89
 
87
90
  await certSpawner.writeFile(
88
91
  CERTIFICATE_OWNERSHIP_TOKEN_FILE_NAME,