@alwaysai/device-agent 2.0.1 → 2.0.2

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 (67) hide show
  1. package/lib/application-control/install.d.ts.map +1 -1
  2. package/lib/application-control/install.js +5 -1
  3. package/lib/application-control/install.js.map +1 -1
  4. package/lib/cloud-connection/connection-manager.d.ts +4 -6
  5. package/lib/cloud-connection/connection-manager.d.ts.map +1 -1
  6. package/lib/cloud-connection/connection-manager.js +23 -35
  7. package/lib/cloud-connection/connection-manager.js.map +1 -1
  8. package/lib/cloud-connection/device-agent-cloud-connection.d.ts +3 -1
  9. package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
  10. package/lib/cloud-connection/device-agent-cloud-connection.js +51 -40
  11. package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
  12. package/lib/cloud-connection/publisher.d.ts +3 -2
  13. package/lib/cloud-connection/publisher.d.ts.map +1 -1
  14. package/lib/cloud-connection/publisher.js +8 -4
  15. package/lib/cloud-connection/publisher.js.map +1 -1
  16. package/lib/cloud-connection/shadow-handler.d.ts +1 -0
  17. package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
  18. package/lib/cloud-connection/shadow-handler.js +3 -0
  19. package/lib/cloud-connection/shadow-handler.js.map +1 -1
  20. package/lib/cloud-connection/shadow-handler.test.js +5 -2
  21. package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
  22. package/lib/cloud-connection/transaction-manager.d.ts +1 -3
  23. package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
  24. package/lib/cloud-connection/transaction-manager.js +1 -2
  25. package/lib/cloud-connection/transaction-manager.js.map +1 -1
  26. package/lib/cloud-connection/transaction-manager.test.js +12 -24
  27. package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
  28. package/lib/environment.d.ts +3 -0
  29. package/lib/environment.d.ts.map +1 -1
  30. package/lib/environment.js +12 -1
  31. package/lib/environment.js.map +1 -1
  32. package/lib/jobs/job-handler.d.ts +1 -1
  33. package/lib/jobs/job-handler.d.ts.map +1 -1
  34. package/lib/jobs/job-handler.js +4 -4
  35. package/lib/jobs/job-handler.js.map +1 -1
  36. package/lib/subcommands/app/analytics.d.ts.map +1 -1
  37. package/lib/subcommands/app/analytics.js +2 -3
  38. package/lib/subcommands/app/analytics.js.map +1 -1
  39. package/lib/subcommands/app/env-vars.d.ts.map +1 -1
  40. package/lib/subcommands/app/env-vars.js +4 -6
  41. package/lib/subcommands/app/env-vars.js.map +1 -1
  42. package/lib/subcommands/app/models.d.ts.map +1 -1
  43. package/lib/subcommands/app/models.js +2 -3
  44. package/lib/subcommands/app/models.js.map +1 -1
  45. package/lib/subcommands/app/shadow.d.ts.map +1 -1
  46. package/lib/subcommands/app/shadow.js +4 -6
  47. package/lib/subcommands/app/shadow.js.map +1 -1
  48. package/lib/subcommands/app/version.d.ts.map +1 -1
  49. package/lib/subcommands/app/version.js +6 -9
  50. package/lib/subcommands/app/version.js.map +1 -1
  51. package/package.json +1 -1
  52. package/readme.md +16 -4
  53. package/src/application-control/install.ts +8 -3
  54. package/src/cloud-connection/connection-manager.ts +24 -37
  55. package/src/cloud-connection/device-agent-cloud-connection.ts +94 -88
  56. package/src/cloud-connection/publisher.ts +28 -23
  57. package/src/cloud-connection/shadow-handler.test.ts +6 -2
  58. package/src/cloud-connection/shadow-handler.ts +4 -0
  59. package/src/cloud-connection/transaction-manager.test.ts +13 -44
  60. package/src/cloud-connection/transaction-manager.ts +1 -4
  61. package/src/environment.ts +18 -0
  62. package/src/jobs/job-handler.ts +4 -4
  63. package/src/subcommands/app/analytics.ts +2 -3
  64. package/src/subcommands/app/env-vars.ts +4 -6
  65. package/src/subcommands/app/models.ts +2 -3
  66. package/src/subcommands/app/shadow.ts +4 -6
  67. package/src/subcommands/app/version.ts +7 -8
@@ -1,23 +1,11 @@
1
- import {
2
- EnvVars,
3
- ToClientStatusResponseMessage,
4
- generateTxId,
5
- keyMirrors,
6
- buildToClientStatusResponseMessage
7
- } from '@alwaysai/device-agent-schemas';
1
+ import { EnvVars, generateTxId } from '@alwaysai/device-agent-schemas';
8
2
  import { TransactionManager } from './transaction-manager';
9
3
  import { v4 as uuidv4 } from 'uuid';
10
- import { Publisher } from './publisher';
11
4
  import { LiveUpdatesHandler } from './live-updates-handler';
12
5
  import { AppConfigUpdate, ShadowUpdate } from './shadow-handler';
13
6
  import { AppContent } from './device-agent-message-handler';
14
7
  import { AppConfig } from '@alwaysai/app-configuration-schemas';
15
8
 
16
- const mockClient = {
17
- publish: jest.fn()
18
- };
19
- const clientId = 'test-client';
20
-
21
9
  const mockLiveUpdatesHandler = {
22
10
  enable: jest.fn(),
23
11
  disable: jest.fn()
@@ -25,7 +13,6 @@ const mockLiveUpdatesHandler = {
25
13
 
26
14
  describe('Test Transaction Manager', () => {
27
15
  let txnMgr: TransactionManager;
28
- let publisher: Publisher;
29
16
  const func_complete: () => Promise<boolean> = jest
30
17
  .fn()
31
18
  .mockResolvedValue(true);
@@ -34,8 +21,7 @@ describe('Test Transaction Manager', () => {
34
21
  .mockResolvedValue(false);
35
22
 
36
23
  beforeEach(() => {
37
- publisher = new Publisher(mockClient, clientId);
38
- txnMgr = new TransactionManager(publisher, mockLiveUpdatesHandler);
24
+ txnMgr = new TransactionManager(mockLiveUpdatesHandler);
39
25
  jest.clearAllMocks();
40
26
  });
41
27
 
@@ -63,29 +49,22 @@ describe('Test Transaction Manager', () => {
63
49
  const txId = generateTxId();
64
50
  const projectId = generateRandomProjectId();
65
51
 
66
- const successFn = (txId: string) => {
67
- const msg = buildToClientStatusResponseMessage(
68
- clientId,
69
- { status: keyMirrors.statusResponse.success },
70
- txId
71
- );
72
- publisher.publishToClient(msg);
73
- };
52
+ const successFn = jest.fn();
53
+ const errorFn = jest.fn();
74
54
 
75
55
  await txnMgr.runTransactionStep({
76
56
  func: func_complete,
77
57
  projectId,
78
58
  txId,
79
59
  start: true,
80
- successFn
60
+ successFn,
61
+ errorFn
81
62
  });
82
63
  expect(txnMgr.isOngoingTransaction(txId)).toBe(false);
83
64
  expect(txnMgr.isOngoingTransactionForProjectID(projectId)).toBe(false);
84
65
  expect(txnMgr.isAnyOngoingTransaction()).toBe(false);
85
- const msg: ToClientStatusResponseMessage = JSON.parse(
86
- mockClient.publish.mock.calls[0][1]
87
- );
88
- expect(msg.payload.status).toBe(keyMirrors.statusResponse.success);
66
+ expect(successFn).toBeCalledTimes(1);
67
+ expect(errorFn).toBeCalledTimes(0);
89
68
  });
90
69
 
91
70
  test('Start a new transaction and complete in second step', async () => {
@@ -214,17 +193,8 @@ describe('Test Transaction Manager', () => {
214
193
  const txId = generateTxId();
215
194
  const projectId = generateRandomProjectId();
216
195
 
217
- const errorFn = (txId: string, errorMsg: string) => {
218
- const msg = buildToClientStatusResponseMessage(
219
- clientId,
220
- {
221
- status: keyMirrors.statusResponse.failure,
222
- message: errorMsg
223
- },
224
- txId
225
- );
226
- publisher.publishToClient(msg);
227
- };
196
+ const successFn = jest.fn();
197
+ const errorFn = jest.fn();
228
198
 
229
199
  await txnMgr.runTransactionStep({
230
200
  func: jest.fn().mockImplementation(() => {
@@ -234,15 +204,14 @@ describe('Test Transaction Manager', () => {
234
204
  txId,
235
205
  start: true,
236
206
  stepName: 'step1',
207
+ successFn,
237
208
  errorFn
238
209
  });
239
210
  expect(txnMgr.isOngoingTransaction(txId)).toBe(false);
240
211
  expect(txnMgr.isOngoingTransactionForProjectID(projectId)).toBe(false);
241
212
  expect(txnMgr.isAnyOngoingTransaction()).toBe(false);
242
- const msg: ToClientStatusResponseMessage = JSON.parse(
243
- mockClient.publish.mock.calls[0][1]
244
- );
245
- expect(msg.payload.status).toBe(keyMirrors.statusResponse.failure);
213
+ expect(successFn).toBeCalledTimes(0);
214
+ expect(errorFn).toBeCalledTimes(1);
246
215
  });
247
216
 
248
217
  test('Complete ongoing transaction', async () => {
@@ -4,7 +4,6 @@ import {
4
4
  keyMirrors
5
5
  } from '@alwaysai/device-agent-schemas';
6
6
  import { LiveUpdatesHandler } from './live-updates-handler';
7
- import { Publisher } from './publisher';
8
7
  import { logger } from '../util/logger';
9
8
  import { keyMirror, stringifyError } from 'alwaysai/lib/util';
10
9
  import { CodedError } from '@carnesen/coded-error';
@@ -30,7 +29,6 @@ export class TransactionManager {
30
29
  private detailsByTx: Record<string, TransactionDetails> = {};
31
30
  private detailsByProject: Record<string, TransactionDetails> = {};
32
31
  private readonly liveUpdatesHandler: LiveUpdatesHandler;
33
- private publisher: Publisher;
34
32
  private async startTransaction(
35
33
  txId: string,
36
34
  projectId: string,
@@ -96,10 +94,9 @@ export class TransactionManager {
96
94
  logger.info(`Updated transaction:\n${JSON.stringify(txDetails, null, 2)}`);
97
95
  }
98
96
 
99
- constructor(publisher: Publisher, liveUpdatesHandler: LiveUpdatesHandler) {
97
+ constructor(liveUpdatesHandler: LiveUpdatesHandler) {
100
98
  this.detailsByTx = {};
101
99
  this.detailsByProject = {};
102
- this.publisher = publisher;
103
100
  this.liveUpdatesHandler = liveUpdatesHandler;
104
101
  }
105
102
 
@@ -1,4 +1,6 @@
1
+ import { TargetHardware } from 'alwaysai/lib/core/app';
1
2
  import { platform } from 'os';
3
+ import { logger } from './util/logger';
2
4
 
3
5
  export const ALWAYSAI_OS_PLATFORM = parseOsPlatform(
4
6
  process.env.ALWAYSAI_OS_PLATFORM
@@ -22,6 +24,22 @@ export const ALWAYSAI_LOCAL_CONNECTION_PORT =
22
24
  process.env.ALWAYSAI_LOCAL_CONNECTION_PORT;
23
25
  export const ALWAYSAI_LOCAL_CONNECTION_ANALYTICS_ROUTING_KEY =
24
26
  process.env.ALWAYSAI_LOCAL_CONNECTION_ANALYTICS_ROUTING_KEY;
27
+ export const ALWAYSAI_TARGET_HW_OVERRIDE =
28
+ process.env.ALWAYSAI_TARGET_HW_OVERRIDE;
29
+
30
+ export function parseTargetHW(
31
+ hardwareType?: string
32
+ ): TargetHardware | undefined {
33
+ const target = hardwareType ? TargetHardware[hardwareType] : undefined;
34
+ if (!target && hardwareType) {
35
+ logger.error(
36
+ `Incorrect TargetHardware: ${hardwareType}. Ignoring the environment variable. Allowed TargetHardware types: ${Object.keys(
37
+ TargetHardware
38
+ )}`
39
+ );
40
+ }
41
+ return target;
42
+ }
25
43
 
26
44
  function parseOsPlatform(str: string | undefined): NodeJS.Platform {
27
45
  switch (str) {
@@ -36,7 +36,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
36
36
  private jobId = '';
37
37
 
38
38
  public async handle(message: any, topic: string): Promise<void> {
39
- const TOPICS = this.getJobTopic();
39
+ const TOPICS = this.getJobTopics();
40
40
 
41
41
  try {
42
42
  switch (topic) {
@@ -54,7 +54,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
54
54
  }
55
55
  }
56
56
 
57
- getJobTopic() {
57
+ getJobTopics() {
58
58
  const TOPICS = {
59
59
  NOTIFY_NEXT: `$aws/things/${this.clientId}/jobs/notify-next`,
60
60
  START_NEXT: `$aws/things/${this.clientId}/jobs/start-next`,
@@ -67,7 +67,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
67
67
  private async notifyNext(message: any): Promise<void> {
68
68
  // Triggers when a job is completed and we need to notify the next job
69
69
  logger.info('Invoking NOTIFY_NEXT handler');
70
- const TOPICS = this.getJobTopic();
70
+ const TOPICS = this.getJobTopics();
71
71
  this.publisher.publish(TOPICS.START_NEXT, JSON.stringify({}));
72
72
  }
73
73
 
@@ -121,7 +121,7 @@ export class JobHandler extends BaseHandler implements MessageHandler {
121
121
  }
122
122
 
123
123
  private updateJobStatus(status: string, message?: string): void {
124
- const { UPDATE } = this.getJobTopic();
124
+ const { UPDATE } = this.getJobTopics();
125
125
  const payload = {
126
126
  status,
127
127
  statusDetails: {
@@ -80,6 +80,7 @@ export const setAnalyticsCfgCliLeaf = CliLeaf({
80
80
  appConfig: JSON.stringify(appCfg) // Pack app config as string as dictated by schema
81
81
  }
82
82
  };
83
+ await deviceAgent.waitForConnection();
83
84
  deviceAgent.publisher.publish(
84
85
  getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
85
86
  JSON.stringify(
@@ -92,9 +93,7 @@ export const setAnalyticsCfgCliLeaf = CliLeaf({
92
93
  // Sleep for extra time to ensure time for shadow response
93
94
  await sleep(10000);
94
95
 
95
- while (deviceAgent.isCmdInProgress(project)) {
96
- await sleep(1000);
97
- }
96
+ await deviceAgent.waitForCmd(project);
98
97
  await deviceAgent.stop();
99
98
  }
100
99
  });
@@ -66,6 +66,7 @@ export const setEnvCliLeaf = CliLeaf({
66
66
  envVars: JSON.stringify(envVars)
67
67
  }
68
68
  };
69
+ await deviceAgent.waitForConnection();
69
70
  deviceAgent.publisher.publish(
70
71
  getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
71
72
  JSON.stringify(
@@ -78,9 +79,7 @@ export const setEnvCliLeaf = CliLeaf({
78
79
  // Sleep for extra time to ensure time for shadow response
79
80
  await sleep(10000);
80
81
 
81
- while (deviceAgent.isCmdInProgress(projectId)) {
82
- await sleep(1000);
83
- }
82
+ await deviceAgent.waitForCmd(projectId);
84
83
  await deviceAgent.stop();
85
84
  }
86
85
  });
@@ -128,6 +127,7 @@ export const rmEnvCliLeaf = CliLeaf({
128
127
  envVars: JSON.stringify(newEnvs)
129
128
  }
130
129
  };
130
+ await deviceAgent.waitForConnection();
131
131
  deviceAgent.publisher.publish(
132
132
  getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
133
133
  JSON.stringify(
@@ -140,9 +140,7 @@ export const rmEnvCliLeaf = CliLeaf({
140
140
  // Sleep for extra time to ensure time for shadow response
141
141
  await sleep(10000);
142
142
 
143
- while (deviceAgent.isCmdInProgress(projectId)) {
144
- await sleep(1000);
145
- }
143
+ await deviceAgent.waitForCmd(projectId);
146
144
  await deviceAgent.stop();
147
145
  }
148
146
  });
@@ -54,6 +54,7 @@ export const addModelCliLeaf = CliLeaf({
54
54
  appConfig: JSON.stringify(newAppCfg)
55
55
  }
56
56
  };
57
+ await deviceAgent.waitForConnection();
57
58
  deviceAgent.publisher.publish(
58
59
  getShadowTopic(deviceAgent.getClientId(), 'projects', 'update'),
59
60
  JSON.stringify(
@@ -66,9 +67,7 @@ export const addModelCliLeaf = CliLeaf({
66
67
  // Sleep for extra time to ensure time for shadow response
67
68
  await sleep(10000);
68
69
 
69
- while (deviceAgent.isCmdInProgress(projectId)) {
70
- await sleep(1000);
71
- }
70
+ await deviceAgent.waitForCmd(projectId);
72
71
  await deviceAgent.stop();
73
72
  }
74
73
  });
@@ -14,13 +14,12 @@ export const getShadowCliLeaf = CliLeaf({
14
14
  async action(_, opts) {
15
15
  const { project } = opts;
16
16
  const deviceAgent = new DeviceAgentCloudConnection();
17
+ await deviceAgent.waitForConnection();
17
18
  deviceAgent.shadowHandler.getProjectShadowUpdates();
18
19
 
19
20
  // 5 seconds should cover the response wait time
20
21
  await sleep(5000);
21
- while (deviceAgent.isCmdInProgress(project)) {
22
- await sleep(1000);
23
- }
22
+ await deviceAgent.waitForCmd(project);
24
23
  await deviceAgent.stop();
25
24
  }
26
25
  });
@@ -37,13 +36,12 @@ export const updateShadowCliLeaf = CliLeaf({
37
36
  async action(_, opts) {
38
37
  const { project } = opts;
39
38
  const deviceAgent = new DeviceAgentCloudConnection();
39
+ await deviceAgent.waitForConnection();
40
40
  await deviceAgent.shadowHandler.updateProjectShadow(project);
41
41
 
42
42
  // 5 seconds should cover the response wait time
43
43
  await sleep(5000);
44
- while (deviceAgent.isCmdInProgress(project)) {
45
- await sleep(1000);
46
- }
44
+ await deviceAgent.waitForCmd(project);
47
45
  await deviceAgent.stop();
48
46
  }
49
47
  });
@@ -10,6 +10,7 @@ import { DeviceAgentCloudConnection } from '../../cloud-connection/device-agent-
10
10
  import { AgentConfigFile } from '../../infrastructure/agent-config';
11
11
  import sleep from '../../util/sleep';
12
12
  import { logger } from '../../util/logger';
13
+ import { device } from 'alwaysai/lib/components';
13
14
 
14
15
  export const listAppsCliLeaf = CliLeaf({
15
16
  name: 'list',
@@ -81,10 +82,9 @@ export const installAppCliLeaf = CliLeaf({
81
82
  envVars
82
83
  }
83
84
  };
84
- await deviceAgent.handleMessage(topic, message);
85
- while (deviceAgent.isCmdInProgress(project)) {
86
- await sleep(1000);
87
- }
85
+ await deviceAgent.waitForConnection();
86
+ await deviceAgent.sendCliCmd(topic, message);
87
+ await deviceAgent.waitForCmd(project);
88
88
  await deviceAgent.stop();
89
89
  }
90
90
  });
@@ -112,10 +112,9 @@ export const uninstallAppCliLeaf = CliLeaf({
112
112
  projectId: project
113
113
  }
114
114
  };
115
- await deviceAgent.handleMessage(topic, message);
116
- while (deviceAgent.isCmdInProgress(project)) {
117
- await sleep(1000);
118
- }
115
+ await deviceAgent.waitForConnection();
116
+ await deviceAgent.sendCliCmd(topic, message);
117
+ await deviceAgent.waitForCmd(project);
119
118
  await deviceAgent.stop();
120
119
  }
121
120
  });