@alwaysai/device-agent 0.0.19 → 0.1.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"passthrough-handler.d.ts","sourceRoot":"","sources":["../../src/cloud-connection/passthrough-handler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,qBAAa,kBAAkB;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,MAAC;IACX,OAAO,MAAC;IACR,WAAW,MAAC;gBAEP,SAAS,EAAE,SAAS;IAInB,KAAK;CAsBnB;AAqBD,wBAAsB,UAAU,CAAC,kBAAkB,EAAE,kBAAkB,iBAetE"}
1
+ {"version":3,"file":"passthrough-handler.d.ts","sourceRoot":"","sources":["../../src/cloud-connection/passthrough-handler.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,qBAAa,kBAAkB;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,MAAC;IACX,OAAO,MAAC;IACR,WAAW,MAAC;gBAEP,SAAS,EAAE,SAAS;IAInB,KAAK;CA6BnB;AAqBD,wBAAsB,UAAU,CAAC,kBAAkB,EAAE,kBAAkB,iBAetE"}
@@ -15,22 +15,29 @@ class PassthroughHandler {
15
15
  async setup() {
16
16
  await (0, rabbitmq_connection_1.setupRabbitMQContainer)();
17
17
  let connectAttempts = 0;
18
- while (connectAttempts < 5 && this.connection === undefined) {
18
+ let connected = false;
19
+ while (connectAttempts <= 10 && this.connection === undefined) {
19
20
  try {
20
21
  this.connection = await amqp.connect('amqp://localhost');
21
22
  this.channel = await this.connection.createChannel();
23
+ connected = true;
22
24
  }
23
25
  catch (e) {
24
- logger_1.logger.debug(`Attempting to connection to Local Connection ${connectAttempts}`);
26
+ logger_1.logger.debug(`Attempting to connect to alwaysAI Local Connection ${connectAttempts}`);
25
27
  await (0, sleep_1.default)(1000 + 1000 * connectAttempts);
26
28
  connectAttempts += 1;
27
29
  }
28
30
  }
29
- this.channel.prefetch(1); // This ensures we only get one packet at a time! This appears to have prevented throttling
30
- this.packetQueue = 'edgeiq-analytics-publish';
31
- await this.channel.assertQueue(this.packetQueue, {
32
- durable: true
33
- });
31
+ if (connected === true) {
32
+ this.channel.prefetch(1); // This ensures we only get one packet at a time! This appears to have prevented throttling
33
+ this.packetQueue = 'edgeiq-analytics-publish';
34
+ await this.channel.assertQueue(this.packetQueue, {
35
+ durable: true
36
+ });
37
+ }
38
+ else {
39
+ throw new Error('Unable to establish connection to alwaysAI Local Connection, please try restarting Device Agent.');
40
+ }
34
41
  }
35
42
  }
36
43
  exports.PassthroughHandler = PassthroughHandler;
@@ -1 +1 @@
1
- {"version":3,"file":"passthrough-handler.js","sourceRoot":"","sources":["../../src/cloud-connection/passthrough-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"passthrough-handler.js","sourceRoot":"","sources":["../../src/cloud-connection/passthrough-handler.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export declare const rabbitMQServiceName = "alwaysAIRabbitMQ";
2
2
  export declare const rabbitMQContainerName = "alwaysAIRabbitMQContainer";
3
3
  export declare function checkRabbitMQContainerRunning(): Promise<boolean | undefined>;
4
+ export declare function writeRabbitMQDockerComposeFile(): Promise<void>;
4
5
  export declare function setupRabbitMQContainer(): Promise<void>;
5
6
  export declare function stopRabbitMQContainer(): Promise<void>;
6
7
  //# sourceMappingURL=rabbitmq-connection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rabbitmq-connection.d.ts","sourceRoot":"","sources":["../../src/local-connection/rabbitmq-connection.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AACtD,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE,wBAAsB,6BAA6B,iCAelD;AAED,wBAAsB,sBAAsB,kBAqB3C;AAED,wBAAsB,qBAAqB,kBAc1C"}
1
+ {"version":3,"file":"rabbitmq-connection.d.ts","sourceRoot":"","sources":["../../src/local-connection/rabbitmq-connection.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AACtD,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE,wBAAsB,6BAA6B,iCAelD;AAED,wBAAsB,8BAA8B,kBAuBnD;AAED,wBAAsB,sBAAsB,kBA2B3C;AAED,wBAAsB,qBAAqB,kBAa1C"}
@@ -1,15 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stopRabbitMQContainer = exports.setupRabbitMQContainer = exports.checkRabbitMQContainerRunning = exports.rabbitMQContainerName = exports.rabbitMQServiceName = void 0;
3
+ exports.stopRabbitMQContainer = exports.setupRabbitMQContainer = exports.writeRabbitMQDockerComposeFile = exports.checkRabbitMQContainerRunning = exports.rabbitMQContainerName = exports.rabbitMQServiceName = void 0;
4
4
  const logger_1 = require("../util/logger");
5
5
  const sleep_1 = require("../util/sleep");
6
6
  const docker_compose_1 = require("docker-compose");
7
+ const YAML = require("yaml");
7
8
  const directories_1 = require("../util/directories");
9
+ const util_1 = require("alwaysai/lib/util");
8
10
  exports.rabbitMQServiceName = 'alwaysAIRabbitMQ';
9
11
  exports.rabbitMQContainerName = 'alwaysAIRabbitMQContainer';
10
12
  async function checkRabbitMQContainerRunning() {
11
13
  logger_1.logger.debug('Checking alwaysAI Local Connection Container status');
12
- const containerData = await docker_compose_1.default.ps({ cwd: directories_1.ASSETS_PATH });
14
+ const containerData = await docker_compose_1.default.ps({ cwd: directories_1.DEVICE_AGENT_CFG_PATH });
13
15
  if (!(containerData === undefined)) {
14
16
  const rabbitmqService = containerData.data.services[0];
15
17
  if (rabbitmqService.name === exports.rabbitMQContainerName &&
@@ -22,11 +24,37 @@ async function checkRabbitMQContainerRunning() {
22
24
  }
23
25
  }
24
26
  exports.checkRabbitMQContainerRunning = checkRabbitMQContainerRunning;
27
+ async function writeRabbitMQDockerComposeFile() {
28
+ const spawner = (0, util_1.JsSpawner)();
29
+ if (!(await spawner.exists(directories_1.DEVICE_AGENT_CFG_PATH))) {
30
+ await (0, util_1.JsSpawner)().mkdirp(directories_1.DEVICE_AGENT_CFG_PATH);
31
+ }
32
+ const rabbitmqDockerComposeCmd = {
33
+ services: {
34
+ [exports.rabbitMQServiceName]: {
35
+ container_name: exports.rabbitMQContainerName,
36
+ image: 'rabbitmq:3.11',
37
+ ports: ['5672:5672'],
38
+ hostname: 'my-rabbit',
39
+ restart: 'on-failure'
40
+ }
41
+ }
42
+ };
43
+ const RabbitMQDockerComposeYaml = YAML.stringify(rabbitmqDockerComposeCmd);
44
+ await spawner.writeFile(directories_1.DEVICE_AGENT_DOCKER_COMPOSE_PATH, RabbitMQDockerComposeYaml);
45
+ }
46
+ exports.writeRabbitMQDockerComposeFile = writeRabbitMQDockerComposeFile;
25
47
  async function setupRabbitMQContainer() {
26
48
  logger_1.logger.debug('Attempting to start the alwaysAI Local Connection Container');
49
+ try {
50
+ await writeRabbitMQDockerComposeFile();
51
+ }
52
+ catch (e) {
53
+ logger_1.logger.error(`An error occurred setting up docker-compose.yaml for Device Agent pass through:\n{e.message}`);
54
+ }
27
55
  try {
28
56
  const upOut = await docker_compose_1.default.upAll({
29
- cwd: directories_1.ASSETS_PATH
57
+ cwd: directories_1.DEVICE_AGENT_CFG_PATH
30
58
  });
31
59
  logger_1.logger.debug(`Docker compose up for alwaysAI Local Connection:\n${JSON.stringify(upOut)}`);
32
60
  // check if the container is up
@@ -35,17 +63,17 @@ async function setupRabbitMQContainer() {
35
63
  }
36
64
  }
37
65
  catch (e) {
38
- logger_1.logger.debug('Unable to start alwaysAI Device Agent Local Connection Container', e.message);
66
+ logger_1.logger.error(`Unable to start alwaysAI Device Agent Local Connection Container:\n${e.messaage}`);
39
67
  }
40
68
  }
41
69
  exports.setupRabbitMQContainer = setupRabbitMQContainer;
42
70
  async function stopRabbitMQContainer() {
43
71
  try {
44
- const downOut = await docker_compose_1.default.down({ cwd: directories_1.ASSETS_PATH });
72
+ const downOut = await docker_compose_1.default.down({ cwd: directories_1.DEVICE_AGENT_CFG_PATH });
45
73
  logger_1.logger.debug(`Docker compose down for alwaysAI Local Connection:\n${JSON.stringify(downOut)}`);
46
74
  }
47
75
  catch (e) {
48
- logger_1.logger.debug('Unable to stop alwaysAI Device Agent Local Connection Container', e.message);
76
+ logger_1.logger.error(`Unable to stop alwaysAI Device Agent Local Connection Container:\n${e.message}`);
49
77
  }
50
78
  }
51
79
  exports.stopRabbitMQContainer = stopRabbitMQContainer;
@@ -1 +1 @@
1
- {"version":3,"file":"rabbitmq-connection.js","sourceRoot":"","sources":["../../src/local-connection/rabbitmq-connection.ts"],"names":[],"mappings":";;;AAEA,2CAAwC;AACxC,yCAAkC;AAClC,mDAAqC;AAErC,qDAAkD;AAErC,QAAA,mBAAmB,GAAG,kBAAkB,CAAC;AACzC,QAAA,qBAAqB,GAAG,2BAA2B,CAAC;AAE1D,KAAK,UAAU,6BAA6B;IACjD,eAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACpE,MAAM,aAAa,GAAG,MAAM,wBAAO,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,yBAAW,EAAE,CAAC,CAAC;IAC7D,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS,CAAC,EAAE;QAClC,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACvD,IACE,eAAe,CAAC,IAAI,KAAK,6BAAqB;YAC9C,eAAe,CAAC,KAAK,KAAK,IAAI,EAC9B;YACA,eAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YACrD,OAAO,IAAI,CAAC;SACb;QACD,eAAM,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC;KACd;AACH,CAAC;AAfD,sEAeC;AAEM,KAAK,UAAU,sBAAsB;IAC1C,eAAM,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC5E,IAAI;QACF,MAAM,KAAK,GAAG,MAAM,wBAAO,CAAC,KAAK,CAAC;YAChC,GAAG,EAAE,yBAAW;SACjB,CAAC,CAAC;QACH,eAAM,CAAC,KAAK,CACV,qDAAqD,IAAI,CAAC,SAAS,CACjE,KAAK,CACN,EAAE,CACJ,CAAC;QACF,+BAA+B;QAC/B,OAAO,CAAC,CAAC,MAAM,6BAA6B,EAAE,CAAC,EAAE;YAC/C,MAAM,IAAA,eAAK,EAAC,EAAE,CAAC,CAAC;SACjB;KACF;IAAC,OAAO,CAAC,EAAE;QACV,eAAM,CAAC,KAAK,CACV,kEAAkE,EAClE,CAAC,CAAC,OAAO,CACV,CAAC;KACH;AACH,CAAC;AArBD,wDAqBC;AAEM,KAAK,UAAU,qBAAqB;IACzC,IAAI;QACF,MAAM,OAAO,GAAG,MAAM,wBAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,yBAAW,EAAE,CAAC,CAAC;QACzD,eAAM,CAAC,KAAK,CACV,uDAAuD,IAAI,CAAC,SAAS,CACnE,OAAO,CACR,EAAE,CACJ,CAAC;KACH;IAAC,OAAO,CAAC,EAAE;QACV,eAAM,CAAC,KAAK,CACV,iEAAiE,EACjE,CAAC,CAAC,OAAO,CACV,CAAC;KACH;AACH,CAAC;AAdD,sDAcC"}
1
+ {"version":3,"file":"rabbitmq-connection.js","sourceRoot":"","sources":["../../src/local-connection/rabbitmq-connection.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export declare const APP_ROOT: string;
2
- export declare const ASSETS_PATH: string;
2
+ export declare const DEVICE_AGENT_CFG_DIR = "device-agent";
3
+ export declare const DEVICE_AGENT_CFG_PATH: string;
3
4
  export declare const DEVICE_AGENT_DOCKER_COMPOSE_PATH: string;
4
5
  export declare const CREDENTIALS_FILE_PATH: string;
5
6
  export declare const AWS_ROOT_CERTIFICATE_FILE_NAME = "AmazonRootCA1.pem";
@@ -1 +1 @@
1
- {"version":3,"file":"directories.d.ts","sourceRoot":"","sources":["../../src/util/directories.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,QAAQ,QAAqC,CAAC;AAE3D,eAAO,MAAM,WAAW,QAAsB,CAAC;AAE/C,eAAO,MAAM,gCAAgC,QAG5C,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAGjC,CAAC;AAEF,eAAO,MAAM,8BAA8B,sBAAsB,CAAC;AAClE,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF,eAAO,MAAM,eAAe,yCAU3B,CAAC;AAMF,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAC3D,eAAO,MAAM,+BAA+B,cACU,CAAC;AACvD,eAAO,MAAM,+BAA+B,cACG,CAAC;AAChD,eAAO,MAAM,sBAAsB,cACW,CAAC;AAC/C,eAAO,MAAM,qCAAqC,oCACf,CAAC;AAEpC,eAAO,MAAM,+BAA+B,cACM,CAAC;AAEnD,eAAO,MAAM,+BAA+B,cAKzC,CAAC;AAEJ,eAAO,MAAM,+BAA+B,cAKzC,CAAC;AAEJ,eAAO,MAAM,sBAAsB,cACyC,CAAC;AAM7E,eAAO,MAAM,4BAA4B,mCAAmC,CAAC;AAC7E,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AACtE,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAE5D,eAAO,MAAM,4BAA4B,QAGxC,CAAC;AAEF,eAAO,MAAM,4BAA4B,QAGxC,CAAC"}
1
+ {"version":3,"file":"directories.d.ts","sourceRoot":"","sources":["../../src/util/directories.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,QAAQ,QAAgC,CAAC;AAEtD,eAAO,MAAM,oBAAoB,iBAAiB,CAAC;AACnD,eAAO,MAAM,qBAAqB,QAGjC,CAAC;AACF,eAAO,MAAM,gCAAgC,QAG5C,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAGjC,CAAC;AAEF,eAAO,MAAM,8BAA8B,sBAAsB,CAAC;AAClE,eAAO,MAAM,8BAA8B,QAG1C,CAAC;AAEF,eAAO,MAAM,eAAe,yCAU3B,CAAC;AAMF,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAC3D,eAAO,MAAM,+BAA+B,cACU,CAAC;AACvD,eAAO,MAAM,+BAA+B,cACG,CAAC;AAChD,eAAO,MAAM,sBAAsB,cACW,CAAC;AAC/C,eAAO,MAAM,qCAAqC,oCACf,CAAC;AAEpC,eAAO,MAAM,+BAA+B,cACM,CAAC;AAEnD,eAAO,MAAM,+BAA+B,cAKzC,CAAC;AAEJ,eAAO,MAAM,+BAA+B,cAKzC,CAAC;AAEJ,eAAO,MAAM,sBAAsB,cACyC,CAAC;AAM7E,eAAO,MAAM,4BAA4B,mCAAmC,CAAC;AAC7E,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AACtE,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAE5D,eAAO,MAAM,4BAA4B,QAGxC,CAAC;AAEF,eAAO,MAAM,4BAA4B,QAGxC,CAAC"}
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEVICE_CERTIFICATE_FILE_PATH = exports.DEVICE_PRIVATE_KEY_FILE_PATH = exports.DEVICE_ID_FILE_NAME = exports.DEVICE_CERTIFICATE_FILE_NAME = exports.DEVICE_PRIVATE_KEY_FILE_NAME = exports.BOOTSTRAP_ID_FILE_PATH = exports.BOOTSTRAP_CERTIFICATE_FILE_PATH = exports.BOOTSTRAP_PRIVATE_KEY_FILE_PATH = exports.BOOTSTRAP_CERTIFICATES_DIR_PATH = exports.CERTIFICATE_OWNERSHIP_TOKEN_FILE_NAME = exports.BOOTSTRAP_ID_FILE_NAME = exports.BOOTSTRAP_CERTIFICATE_FILE_NAME = exports.BOOTSTRAP_PRIVATE_KEY_FILE_NAME = exports.BOOTSTRAP_DIR_NAME = exports.shortenSystemId = exports.AWS_ROOT_CERTIFICATE_FILE_PATH = exports.AWS_ROOT_CERTIFICATE_FILE_NAME = exports.CREDENTIALS_FILE_PATH = exports.DEVICE_AGENT_DOCKER_COMPOSE_PATH = exports.ASSETS_PATH = exports.APP_ROOT = void 0;
3
+ exports.DEVICE_CERTIFICATE_FILE_PATH = exports.DEVICE_PRIVATE_KEY_FILE_PATH = exports.DEVICE_ID_FILE_NAME = exports.DEVICE_CERTIFICATE_FILE_NAME = exports.DEVICE_PRIVATE_KEY_FILE_NAME = exports.BOOTSTRAP_ID_FILE_PATH = exports.BOOTSTRAP_CERTIFICATE_FILE_PATH = exports.BOOTSTRAP_PRIVATE_KEY_FILE_PATH = exports.BOOTSTRAP_CERTIFICATES_DIR_PATH = exports.CERTIFICATE_OWNERSHIP_TOKEN_FILE_NAME = exports.BOOTSTRAP_ID_FILE_NAME = exports.BOOTSTRAP_CERTIFICATE_FILE_NAME = exports.BOOTSTRAP_PRIVATE_KEY_FILE_NAME = exports.BOOTSTRAP_DIR_NAME = exports.shortenSystemId = exports.AWS_ROOT_CERTIFICATE_FILE_PATH = exports.AWS_ROOT_CERTIFICATE_FILE_NAME = exports.CREDENTIALS_FILE_PATH = exports.DEVICE_AGENT_DOCKER_COMPOSE_PATH = exports.DEVICE_AGENT_CFG_PATH = exports.DEVICE_AGENT_CFG_DIR = exports.APP_ROOT = void 0;
4
4
  const constants_1 = require("alwaysai/lib/constants");
5
5
  const path_1 = require("path");
6
6
  const system_id_1 = require("../infrastructure/system-id");
7
- const path = require("path");
8
- exports.APP_ROOT = path.join(constants_1.AAI_DIR, 'applications');
9
- exports.ASSETS_PATH = path.join('assets');
10
- exports.DEVICE_AGENT_DOCKER_COMPOSE_PATH = path.join(exports.ASSETS_PATH, constants_1.DOCKER_COMPOSE_FILE);
7
+ exports.APP_ROOT = (0, path_1.join)(constants_1.AAI_DIR, 'applications');
8
+ exports.DEVICE_AGENT_CFG_DIR = 'device-agent';
9
+ exports.DEVICE_AGENT_CFG_PATH = (0, path_1.join)(constants_1.LOCAL_AAI_CFG_DIR, exports.DEVICE_AGENT_CFG_DIR);
10
+ exports.DEVICE_AGENT_DOCKER_COMPOSE_PATH = (0, path_1.join)(exports.DEVICE_AGENT_CFG_PATH, constants_1.DOCKER_COMPOSE_FILE);
11
11
  exports.CREDENTIALS_FILE_PATH = (0, path_1.join)(constants_1.LOCAL_AAI_CFG_DIR, constants_1.DEVICE_TOKEN_FILE_NAME);
12
12
  exports.AWS_ROOT_CERTIFICATE_FILE_NAME = 'AmazonRootCA1.pem';
13
13
  exports.AWS_ROOT_CERTIFICATE_FILE_PATH = (0, path_1.join)(constants_1.LOCAL_CERT_AND_KEY_DIR, exports.AWS_ROOT_CERTIFICATE_FILE_NAME);
@@ -1 +1 @@
1
- {"version":3,"file":"directories.js","sourceRoot":"","sources":["../../src/util/directories.ts"],"names":[],"mappings":";;;AAAA,sDAMgC;AAChC,+BAA4B;AAC5B,2DAA0D;AAC1D,6BAA6B;AAEhB,QAAA,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAO,EAAE,cAAc,CAAC,CAAC;AAE9C,QAAA,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAElC,QAAA,gCAAgC,GAAG,IAAI,CAAC,IAAI,CACvD,mBAAW,EACX,+BAAmB,CACpB,CAAC;AAEW,QAAA,qBAAqB,GAAG,IAAA,WAAI,EACvC,6BAAiB,EACjB,kCAAsB,CACvB,CAAC;AAEW,QAAA,8BAA8B,GAAG,mBAAmB,CAAC;AACrD,QAAA,8BAA8B,GAAG,IAAA,WAAI,EAChD,kCAAsB,EACtB,sCAA8B,CAC/B,CAAC;AAEK,MAAM,eAAe,GAAG,GAAG,EAAE;IAClC,MAAM,EAAE,GAAG,IAAA,uBAAW,GAAE,CAAC;IACzB,QAAQ,EAAE,EAAE;QACV,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC;QACf,KAAK,IAAI;YACP,OAAO,IAAI,CAAC;QACd,KAAK,YAAY;YACf,OAAO,MAAM,CAAC;KACjB;AACH,CAAC,CAAC;AAVW,QAAA,eAAe,mBAU1B;AAEF;;qEAEqE;AAExD,QAAA,kBAAkB,GAAG,wBAAwB,CAAC;AACpD,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,yBAAyB,IAAA,uBAAe,GAAE,UAAU,CAAC;AAD1C,QAAA,+BAA+B,mCACW;AAChD,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,kBAAkB,IAAA,uBAAe,GAAE,UAAU,CAAC;AADnC,QAAA,+BAA+B,mCACI;AACzC,MAAM,sBAAsB,GAAG,GAAG,EAAE,CACzC,qBAAqB,IAAA,uBAAe,GAAE,MAAM,CAAC;AADlC,QAAA,sBAAsB,0BACY;AAClC,QAAA,qCAAqC,GAChD,iCAAiC,CAAC;AAE7B,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,IAAA,WAAI,EAAC,kCAAsB,EAAE,0BAAkB,CAAC,CAAC;AADtC,QAAA,+BAA+B,mCACO;AAE5C,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,IAAA,WAAI,EACF,kCAAsB,EACtB,0BAAkB,EAClB,IAAA,uCAA+B,GAAE,CAClC,CAAC;AALS,QAAA,+BAA+B,mCAKxC;AAEG,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,IAAA,WAAI,EACF,kCAAsB,EACtB,0BAAkB,EAClB,IAAA,uCAA+B,GAAE,CAClC,CAAC;AALS,QAAA,+BAA+B,mCAKxC;AAEG,MAAM,sBAAsB,GAAG,GAAG,EAAE,CACzC,IAAA,WAAI,EAAC,kCAAsB,EAAE,0BAAkB,EAAE,IAAA,8BAAsB,GAAE,CAAC,CAAC;AADhE,QAAA,sBAAsB,0BAC0C;AAE7E;;qEAEqE;AAExD,QAAA,4BAA4B,GAAG,gCAAgC,CAAC;AAChE,QAAA,4BAA4B,GAAG,yBAAyB,CAAC;AACzD,QAAA,mBAAmB,GAAG,wBAAwB,CAAC;AAE/C,QAAA,4BAA4B,GAAG,IAAA,WAAI,EAC9C,kCAAsB,EACtB,oCAA4B,CAC7B,CAAC;AAEW,QAAA,4BAA4B,GAAG,IAAA,WAAI,EAC9C,kCAAsB,EACtB,oCAA4B,CAC7B,CAAC"}
1
+ {"version":3,"file":"directories.js","sourceRoot":"","sources":["../../src/util/directories.ts"],"names":[],"mappings":";;;AAAA,sDAMgC;AAChC,+BAA4B;AAC5B,2DAA0D;AAE7C,QAAA,QAAQ,GAAG,IAAA,WAAI,EAAC,mBAAO,EAAE,cAAc,CAAC,CAAC;AAEzC,QAAA,oBAAoB,GAAG,cAAc,CAAC;AACtC,QAAA,qBAAqB,GAAG,IAAA,WAAI,EACvC,6BAAiB,EACjB,4BAAoB,CACrB,CAAC;AACW,QAAA,gCAAgC,GAAG,IAAA,WAAI,EAClD,6BAAqB,EACrB,+BAAmB,CACpB,CAAC;AAEW,QAAA,qBAAqB,GAAG,IAAA,WAAI,EACvC,6BAAiB,EACjB,kCAAsB,CACvB,CAAC;AAEW,QAAA,8BAA8B,GAAG,mBAAmB,CAAC;AACrD,QAAA,8BAA8B,GAAG,IAAA,WAAI,EAChD,kCAAsB,EACtB,sCAA8B,CAC/B,CAAC;AAEK,MAAM,eAAe,GAAG,GAAG,EAAE;IAClC,MAAM,EAAE,GAAG,IAAA,uBAAW,GAAE,CAAC;IACzB,QAAQ,EAAE,EAAE;QACV,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC;QACf,KAAK,IAAI;YACP,OAAO,IAAI,CAAC;QACd,KAAK,YAAY;YACf,OAAO,MAAM,CAAC;KACjB;AACH,CAAC,CAAC;AAVW,QAAA,eAAe,mBAU1B;AAEF;;qEAEqE;AAExD,QAAA,kBAAkB,GAAG,wBAAwB,CAAC;AACpD,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,yBAAyB,IAAA,uBAAe,GAAE,UAAU,CAAC;AAD1C,QAAA,+BAA+B,mCACW;AAChD,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,kBAAkB,IAAA,uBAAe,GAAE,UAAU,CAAC;AADnC,QAAA,+BAA+B,mCACI;AACzC,MAAM,sBAAsB,GAAG,GAAG,EAAE,CACzC,qBAAqB,IAAA,uBAAe,GAAE,MAAM,CAAC;AADlC,QAAA,sBAAsB,0BACY;AAClC,QAAA,qCAAqC,GAChD,iCAAiC,CAAC;AAE7B,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,IAAA,WAAI,EAAC,kCAAsB,EAAE,0BAAkB,CAAC,CAAC;AADtC,QAAA,+BAA+B,mCACO;AAE5C,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,IAAA,WAAI,EACF,kCAAsB,EACtB,0BAAkB,EAClB,IAAA,uCAA+B,GAAE,CAClC,CAAC;AALS,QAAA,+BAA+B,mCAKxC;AAEG,MAAM,+BAA+B,GAAG,GAAG,EAAE,CAClD,IAAA,WAAI,EACF,kCAAsB,EACtB,0BAAkB,EAClB,IAAA,uCAA+B,GAAE,CAClC,CAAC;AALS,QAAA,+BAA+B,mCAKxC;AAEG,MAAM,sBAAsB,GAAG,GAAG,EAAE,CACzC,IAAA,WAAI,EAAC,kCAAsB,EAAE,0BAAkB,EAAE,IAAA,8BAAsB,GAAE,CAAC,CAAC;AADhE,QAAA,sBAAsB,0BAC0C;AAE7E;;qEAEqE;AAExD,QAAA,4BAA4B,GAAG,gCAAgC,CAAC;AAChE,QAAA,4BAA4B,GAAG,yBAAyB,CAAC;AACzD,QAAA,mBAAmB,GAAG,wBAAwB,CAAC;AAE/C,QAAA,4BAA4B,GAAG,IAAA,WAAI,EAC9C,kCAAsB,EACtB,oCAA4B,CAC7B,CAAC;AAEW,QAAA,4BAA4B,GAAG,IAAA,WAAI,EAC9C,kCAAsB,EACtB,oCAA4B,CAC7B,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@alwaysai/device-agent",
3
3
  "description": "The alwaysAI Device Agent",
4
- "version": "0.0.19",
4
+ "version": "0.1.0",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "publishConfig": {
package/readme.md CHANGED
@@ -9,7 +9,7 @@ Note that the Device Agent is still in an experimental phase and these commands
9
9
  are likely to change. This guide will be updated with the latest usage as things
10
10
  change.
11
11
 
12
- ## System Requirements
12
+ ## System Requirements & Prerequisites
13
13
 
14
14
  * Supported OS:
15
15
  * Debian Bullseye, Buster
@@ -21,6 +21,14 @@ change.
21
21
  * armv7hf
22
22
  * `docker` version >= 19.03
23
23
  * `curl` installed (required to download provisioning scripts)
24
+ * Passwordless `sudo` for `npm` if using `pm2`
25
+
26
+ To enable passwordless `sudo` for `npm` for the current user, run `sudo visudo`
27
+ and add the following line to the end of the file:
28
+
29
+ ```bash
30
+ <username> <hostname> = (root) NOPASSWD: /usr/bin/npm
31
+ ```
24
32
 
25
33
  ## Provision Device
26
34
 
@@ -28,7 +36,7 @@ change.
28
36
 
29
37
  On the target device, run:
30
38
 
31
- ```
39
+ ```bash
32
40
  $ curl -fsSL https://artifacts.alwaysai.co/device-agent/install-device-agent.sh | sudo -E bash -
33
41
  ```
34
42
 
@@ -44,7 +52,7 @@ Provisioning the device performs the following:
44
52
 
45
53
  Run the following command on the target device to provision it:
46
54
 
47
- ```
55
+ ```bash
48
56
  $ curl -fsSL https://artifacts.alwaysai.co/device-agent/provision.sh | bash -s -- --email <email> --password <password> [--device-name <device_name>]
49
57
  ```
50
58
 
@@ -55,11 +63,36 @@ Where:
55
63
  devices page of the alwaysAI Dashboard. If a device name is not provided, one
56
64
  will be generated for you and logged to the console for reference.
57
65
 
66
+ Confirm the Device Agent is running with the following command:
67
+
68
+ ```bash
69
+ $ pm2 list
70
+ ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
71
+ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │
72
+ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
73
+ │ 0 │ aai-agent │ fork │ 15 │ online │ 0% │ 2.8mb │
74
+ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
75
+ ```
76
+
77
+ To restart and update the Device Agent run the following command:
78
+
79
+ ```bash
80
+ $ pm2 restart aai-agent
81
+ Use --update-env to update environment variables
82
+ [PM2] Applying action restartProcessId on app [aai-agent](ids: [ 0 ])
83
+ [PM2] [aai-agent](0) ✓
84
+ ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
85
+ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │
86
+ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤
87
+ │ 0 │ aai-agent │ fork │ 16 │ online │ 0% │ 2.6mb │
88
+ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘
89
+ ```
90
+
58
91
  If you'd like to only provision the device, but not start the Device Agent in
59
92
  the background (skip step 3), run with the `--provision-only` flag:
60
93
 
61
- ```
62
- $ curl -fsSL https://artifacts.alwaysai.co/device-agent/provision-agent.sh | bash -s -- --email <email> --password <password> [--device-name <device_name>] --provision-only
94
+ ```bash
95
+ $ curl -fsSL https://artifacts.alwaysai.co/device-agent/provision.sh | bash -s -- --email <email> --password <password> [--device-name <device_name>] --provision-only
63
96
  ```
64
97
 
65
98
  When the script completes, the device will be provisioned but the Device Agent will not be running in the background.
@@ -83,11 +116,129 @@ project page of the alwaysAI Dashboard as well!
83
116
 
84
117
  Now you can deploy to your device from the alwaysAI Dashboard.
85
118
 
119
+ ## Enable Analytics through the alwaysAI Device Agent
120
+
121
+ ### Configure the Device Agent
122
+ You can send information from your device to the alwaysAI cloud securely using
123
+ the Device Agent. These instructions assume you have provisioned your device
124
+ using the default script parameters and have the Device agent running (i.e. the
125
+ provisioning script was not run with the `--provision-only` flag set).
126
+
127
+ First, the Device Agent must be configured to enable Analytics Pass-through support. Confirm that the `ALWAYSAI_ANALYTICS_PASSTHROUGH` environment variable is set:
128
+
129
+ ```bash
130
+ $ pm2 env 0 | grep ALWAYSAI
131
+ ALWAYSAI_ANALYTICS_PASSTHROUGH: 1
132
+ ALWAYSAI_LOG_TO_CONSOLE:
133
+ ALWAYSAI_LOG_LEVEL: debug
134
+ ALWAYSAI_DEVICE_AGENT_MODE: cloud
135
+ ```
136
+
137
+ Then confirm the RabbitMQ container is up and running:
138
+
139
+ ```bash
140
+ $ docker ps
141
+ CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
142
+ 596157124a4b rabbitmq:3.11 "docker-entrypoint.s…" 32 minutes ago Up 21 minutes 4369/tcp, 5671/tcp, 15691-15692/tcp, 25672/tcp, 0.0.0.0:5672->5672/tcp alwaysAIRabbitMQContainer
143
+ ```
144
+
145
+ ### Configure the Application
146
+
147
+ From the application side, the `ALWAYSAI_CONNECT_TO_DEVICE_AGENT` environment
148
+ variable must be set. There are a few options:
149
+
150
+ #### In the app source
151
+
152
+ In your `app.py` file, make sure the top of your import statements looks like
153
+ this:
154
+
155
+ ```python
156
+ import os
157
+ os.environ['ALWAYSAI_CONNECT_TO_DEVICE_AGENT']='1'
158
+ import edgeiq
159
+ ```
160
+ You can import any other modules after `edgeiq`, but the other orders must be
161
+ maintained.
162
+
163
+ #### In the Dockerfile
164
+
165
+ ```bash
166
+ ENV ALWAYSAI_CONNECT_TO_DEVICE_AGENT=1
167
+ ```
168
+
169
+ #### In a docker-compose.yaml
170
+
171
+ Add the following section to the service for your app:
172
+
173
+ ```bash
174
+ environment:
175
+ - ALWAYSAI_CONNECT_TO_DEVICE_AGENT=1
176
+ ```
177
+
178
+ ### Enable Publishing to Cloud
179
+
180
+ To enable cloud publishing for your application you can either run
181
+ `aai app enable-cloud-publish`, or update your `alwaysai.app.json` by adding the
182
+ following component in addition to any `models` or `scripts` components:
183
+
184
+ ```json
185
+ "analytics: {
186
+ "enable_cloud_publish": true
187
+ }
188
+ ```
189
+
190
+ So, a valid `alwaysai.app.json` for publishing analytics might look like this:
191
+
192
+ ```json
193
+ {
194
+ "scripts": {
195
+ "start": "python app.py"
196
+ },
197
+ "models": {
198
+ "alwaysai/mobilenet_ssd": 4
199
+ },
200
+ "analytics": {
201
+ "enable_cloud_publish": true
202
+ }
203
+ }
204
+ ```
205
+
206
+ Finally, add a command to publish analytics to your `app.py`. Whenever this
207
+ command is used, it will publish the contents of the analytics message to the
208
+ cloud -- you can choose to call this every frame, or once every event
209
+ occurrence, however your app is designed. Each core computer vision service has
210
+ it's own `publish_analytics` method, which is called on the instance of the
211
+ class. Or, you can published a JSON-serializable message with
212
+ `edgeiq.publish_analytics()`. For instance, to publish object detection results
213
+ you can use:
214
+
215
+ ```python
216
+ results = obj_detect.detect_objects(frame, confidence_level=.5)
217
+ try:
218
+ obj_detect.publish_analytics(results, tag=frame_count)
219
+ except edgeiq.PublishError as e:
220
+ print(e)
221
+ ```
222
+
223
+ Finally, make sure to save all of your changes, and publish your application with
224
+
225
+ ```bash
226
+ $ aai app publish
227
+ ```
228
+
229
+ You can test that analytics are being viewed with `wscat`, using your application's project ID and a secure API key:
230
+
231
+ ```bash
232
+ $ wscat -c "wss://analytics.alwaysai.co?projectId=[PROJECT_ID]&apiKey=[API_KEY]"
233
+ ```
234
+
235
+ Please contact the alwaysAI team if you need a secure API key.
236
+
86
237
  ## The alwaysAI Device Agent Command Line interface
87
238
 
88
239
  The Device Agent can also be used directly on the device with it's command line interface.
89
240
 
90
- ```
241
+ ```bash
91
242
  $ aai-agent --help
92
243
  Usage: aai-agent <subcommand> ...
93
244
 
@@ -119,8 +270,8 @@ Subcommands:
119
270
 
120
271
  To see the output logs, run the following command:
121
272
 
122
- ```
123
- export ALWAYSAI_LOG_TO_CONSOLE=1
273
+ ```bash
274
+ $ export ALWAYSAI_LOG_TO_CONSOLE=1
124
275
  ```
125
276
 
126
277
  ### Install the application on the device
@@ -128,7 +279,7 @@ export ALWAYSAI_LOG_TO_CONSOLE=1
128
279
  Now you can install the application on the device using the device agent. Run
129
280
  the following on the device where the Device Agent is installed:
130
281
 
131
- ```
282
+ ```bash
132
283
  $ aai-agent app install --project <project_id> --release <release_hash>
133
284
  ```
134
285
 
@@ -137,27 +288,27 @@ $ aai-agent app install --project <project_id> --release <release_hash>
137
288
  Run the following commands on the device where the Device Agent is installed:
138
289
 
139
290
  Get application status:
140
- ```
291
+ ```bash
141
292
  $ aai-agent app status --project <project_id>
142
293
  ```
143
294
 
144
295
  Start the application:
145
- ```
296
+ ```bash
146
297
  $ aai-agent app start --project <project_id>
147
298
  ```
148
299
 
149
300
  Show the application logs:
150
- ```
301
+ ```bash
151
302
  $ aai-agent app logs --project <project_id>
152
303
  ```
153
304
 
154
305
  Stop the application:
155
- ```
306
+ ```bash
156
307
  $ aai-agent app stop --project <project_id>
157
308
  ```
158
309
 
159
310
  Uninstall the application:
160
- ```
311
+ ```bash
161
312
  $ aai-agent app uninstall --project <project_id>
162
313
  ```
163
314
 
@@ -171,7 +322,7 @@ If a new version of a model is published for an existing model ID, and an
171
322
  application is already configured to be using that model ID, updating to the
172
323
  new model can simply be done with:
173
324
 
174
- ```
325
+ ```bash
175
326
  $ aai-agent app stop --project <project_id>
176
327
  $ aai-agent app update-models --project <project_id>
177
328
  $ aai-agent app start --project <project_id>
@@ -182,7 +333,7 @@ $ aai-agent app start --project <project_id>
182
333
  If you'd like to install an entirely new model to an application, replacing the
183
334
  model the app was originally configured with, run the following command:
184
335
 
185
- ```
336
+ ```bash
186
337
  $ aai-agent app stop --project <project_id>
187
338
  $ aai-agent app replace-models --project <project_id> --models <model_id_1> [<model_id_2> ...]
188
339
  $ aai-agent app start --project <project_id>
@@ -192,7 +343,7 @@ If you plan on using this method, you can make your application source model ID
192
343
  agnostic by providing the model ID to edgeIQ in the following way:
193
344
 
194
345
  Select the first model in the config list:
195
- ```
346
+ ```python
196
347
  obj_detect = edgeiq.ObjectDetection(edgeiq._globals.MODEL_ID_LIST[0])
197
348
  ```
198
349
 
@@ -200,13 +351,13 @@ obj_detect = edgeiq.ObjectDetection(edgeiq._globals.MODEL_ID_LIST[0])
200
351
 
201
352
  To download a model package from the alwaysAI cloud and unpack to a specific directory, run:
202
353
 
203
- ```
354
+ ```bash
204
355
  $ aai-agent get-model-package <model ID> [--path <destination path>]
205
356
  ```
206
357
 
207
358
  For example, to download `alwaysai/yolo_v3` to `~/alwaysai` run:
208
359
 
209
- ```
360
+ ```bash
210
361
  $ aai-agent get-model-package alwaysai/yolo_v3 --path ~/alwaysai
211
362
  ```
212
363
 
@@ -218,13 +369,13 @@ Once the command completes, you'll see the model package in the
218
369
  The Device Agent enables you to set and update environment variables for all
219
370
  services or a single service of you application.
220
371
 
221
- ```
372
+ ```bash
222
373
  $ aai-agent app set-env <key=val> --project <project_id> [--service <service>]
223
374
  ```
224
375
 
225
376
  For example, to set the following environment variable for the `alwaysai`
226
377
  service run the following command on the device:
227
378
 
228
- ```
379
+ ```bash
229
380
  $ aai-agent app set-env TEST_ENV=1 --project <project_id> --service alwaysai
230
381
  ```
@@ -21,24 +21,31 @@ export class PassthroughHandler {
21
21
  public async setup() {
22
22
  await setupRabbitMQContainer();
23
23
  let connectAttempts = 0;
24
- while (connectAttempts < 5 && this.connection === undefined) {
24
+ let connected = false;
25
+ while (connectAttempts <= 10 && this.connection === undefined) {
25
26
  try {
26
27
  this.connection = await amqp.connect('amqp://localhost');
27
28
  this.channel = await this.connection.createChannel();
29
+ connected = true;
28
30
  } catch (e) {
29
31
  logger.debug(
30
- `Attempting to connection to Local Connection ${connectAttempts}`
32
+ `Attempting to connect to alwaysAI Local Connection ${connectAttempts}`
31
33
  );
32
34
  await sleep(1000 + 1000 * connectAttempts);
33
35
  connectAttempts += 1;
34
36
  }
35
37
  }
36
-
37
- this.channel.prefetch(1); // This ensures we only get one packet at a time! This appears to have prevented throttling
38
- this.packetQueue = 'edgeiq-analytics-publish';
39
- await this.channel.assertQueue(this.packetQueue, {
40
- durable: true
41
- });
38
+ if (connected === true) {
39
+ this.channel.prefetch(1); // This ensures we only get one packet at a time! This appears to have prevented throttling
40
+ this.packetQueue = 'edgeiq-analytics-publish';
41
+ await this.channel.assertQueue(this.packetQueue, {
42
+ durable: true
43
+ });
44
+ } else {
45
+ throw new Error(
46
+ 'Unable to establish connection to alwaysAI Local Connection, please try restarting Device Agent.'
47
+ );
48
+ }
42
49
  }
43
50
  }
44
51
 
@@ -1,17 +1,20 @@
1
- import { stringify } from 'yaml';
2
- import { JsSpawner } from 'alwaysai/lib/util';
3
1
  import { logger } from '../util/logger';
4
2
  import sleep from '../util/sleep';
5
3
  import compose from 'docker-compose';
4
+ import * as YAML from 'yaml';
6
5
 
7
- import { ASSETS_PATH } from '../util/directories';
6
+ import {
7
+ DEVICE_AGENT_CFG_PATH,
8
+ DEVICE_AGENT_DOCKER_COMPOSE_PATH
9
+ } from '../util/directories';
10
+ import { JsSpawner } from 'alwaysai/lib/util';
8
11
 
9
12
  export const rabbitMQServiceName = 'alwaysAIRabbitMQ';
10
13
  export const rabbitMQContainerName = 'alwaysAIRabbitMQContainer';
11
14
 
12
15
  export async function checkRabbitMQContainerRunning() {
13
16
  logger.debug('Checking alwaysAI Local Connection Container status');
14
- const containerData = await compose.ps({ cwd: ASSETS_PATH });
17
+ const containerData = await compose.ps({ cwd: DEVICE_AGENT_CFG_PATH });
15
18
  if (!(containerData === undefined)) {
16
19
  const rabbitmqService = containerData.data.services[0];
17
20
  if (
@@ -26,11 +29,43 @@ export async function checkRabbitMQContainerRunning() {
26
29
  }
27
30
  }
28
31
 
32
+ export async function writeRabbitMQDockerComposeFile() {
33
+ const spawner = JsSpawner();
34
+ if (!(await spawner.exists(DEVICE_AGENT_CFG_PATH))) {
35
+ await JsSpawner().mkdirp(DEVICE_AGENT_CFG_PATH);
36
+ }
37
+
38
+ const rabbitmqDockerComposeCmd = {
39
+ services: {
40
+ [rabbitMQServiceName]: {
41
+ container_name: rabbitMQContainerName,
42
+ image: 'rabbitmq:3.11',
43
+ ports: ['5672:5672'],
44
+ hostname: 'my-rabbit',
45
+ restart: 'on-failure'
46
+ }
47
+ }
48
+ };
49
+
50
+ const RabbitMQDockerComposeYaml = YAML.stringify(rabbitmqDockerComposeCmd);
51
+ await spawner.writeFile(
52
+ DEVICE_AGENT_DOCKER_COMPOSE_PATH,
53
+ RabbitMQDockerComposeYaml
54
+ );
55
+ }
56
+
29
57
  export async function setupRabbitMQContainer() {
30
58
  logger.debug('Attempting to start the alwaysAI Local Connection Container');
59
+ try {
60
+ await writeRabbitMQDockerComposeFile();
61
+ } catch (e) {
62
+ logger.error(
63
+ `An error occurred setting up docker-compose.yaml for Device Agent pass through:\n{e.message}`
64
+ );
65
+ }
31
66
  try {
32
67
  const upOut = await compose.upAll({
33
- cwd: ASSETS_PATH
68
+ cwd: DEVICE_AGENT_CFG_PATH
34
69
  });
35
70
  logger.debug(
36
71
  `Docker compose up for alwaysAI Local Connection:\n${JSON.stringify(
@@ -42,25 +77,23 @@ export async function setupRabbitMQContainer() {
42
77
  await sleep(10);
43
78
  }
44
79
  } catch (e) {
45
- logger.debug(
46
- 'Unable to start alwaysAI Device Agent Local Connection Container',
47
- e.message
80
+ logger.error(
81
+ `Unable to start alwaysAI Device Agent Local Connection Container:\n${e.messaage}`
48
82
  );
49
83
  }
50
84
  }
51
85
 
52
86
  export async function stopRabbitMQContainer() {
53
87
  try {
54
- const downOut = await compose.down({ cwd: ASSETS_PATH });
88
+ const downOut = await compose.down({ cwd: DEVICE_AGENT_CFG_PATH });
55
89
  logger.debug(
56
90
  `Docker compose down for alwaysAI Local Connection:\n${JSON.stringify(
57
91
  downOut
58
92
  )}`
59
93
  );
60
94
  } catch (e) {
61
- logger.debug(
62
- 'Unable to stop alwaysAI Device Agent Local Connection Container',
63
- e.message
95
+ logger.error(
96
+ `Unable to stop alwaysAI Device Agent Local Connection Container:\n${e.message}`
64
97
  );
65
98
  }
66
99
  }
@@ -7,14 +7,16 @@ import {
7
7
  } from 'alwaysai/lib/constants';
8
8
  import { join } from 'path';
9
9
  import { getSystemId } from '../infrastructure/system-id';
10
- import * as path from 'path';
11
10
 
12
- export const APP_ROOT = path.join(AAI_DIR, 'applications');
11
+ export const APP_ROOT = join(AAI_DIR, 'applications');
13
12
 
14
- export const ASSETS_PATH = path.join('assets');
15
-
16
- export const DEVICE_AGENT_DOCKER_COMPOSE_PATH = path.join(
17
- ASSETS_PATH,
13
+ export const DEVICE_AGENT_CFG_DIR = 'device-agent';
14
+ export const DEVICE_AGENT_CFG_PATH = join(
15
+ LOCAL_AAI_CFG_DIR,
16
+ DEVICE_AGENT_CFG_DIR
17
+ );
18
+ export const DEVICE_AGENT_DOCKER_COMPOSE_PATH = join(
19
+ DEVICE_AGENT_CFG_PATH,
18
20
  DOCKER_COMPOSE_FILE
19
21
  );
20
22
 
@@ -1,8 +0,0 @@
1
- services:
2
- alwaysAIRabbitMQ:
3
- container_name: alwaysAIRabbitMQContainer
4
- image: rabbitmq:3.11
5
- ports:
6
- - 5672:5672
7
- hostname: my-rabbit
8
- restart: on-failure