@alwaysai/device-agent 1.5.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/application-control/config.d.ts.map +1 -1
- package/lib/application-control/config.js +8 -3
- package/lib/application-control/config.js.map +1 -1
- package/lib/application-control/environment-variables.d.ts +5 -5
- package/lib/application-control/environment-variables.d.ts.map +1 -1
- package/lib/application-control/environment-variables.js +25 -38
- package/lib/application-control/environment-variables.js.map +1 -1
- package/lib/application-control/environment-variables.test.js +27 -7
- package/lib/application-control/environment-variables.test.js.map +1 -1
- package/lib/application-control/index.d.ts +4 -4
- package/lib/application-control/index.d.ts.map +1 -1
- package/lib/application-control/index.js +1 -4
- package/lib/application-control/index.js.map +1 -1
- package/lib/application-control/install.d.ts +4 -1
- package/lib/application-control/install.d.ts.map +1 -1
- package/lib/application-control/install.js +24 -8
- package/lib/application-control/install.js.map +1 -1
- package/lib/application-control/models.d.ts +0 -11
- package/lib/application-control/models.d.ts.map +1 -1
- package/lib/application-control/models.js +5 -54
- package/lib/application-control/models.js.map +1 -1
- package/lib/application-control/utils.d.ts +0 -4
- package/lib/application-control/utils.d.ts.map +1 -1
- package/lib/application-control/utils.js +12 -22
- package/lib/application-control/utils.js.map +1 -1
- package/lib/cloud-connection/base-message-handler.d.ts +27 -0
- package/lib/cloud-connection/base-message-handler.d.ts.map +1 -0
- package/lib/cloud-connection/base-message-handler.js +72 -0
- package/lib/cloud-connection/base-message-handler.js.map +1 -0
- package/lib/cloud-connection/bootstrap-provision.js +3 -2
- package/lib/cloud-connection/bootstrap-provision.js.map +1 -1
- package/lib/cloud-connection/connection-manager.d.ts +21 -0
- package/lib/cloud-connection/connection-manager.d.ts.map +1 -0
- package/lib/cloud-connection/connection-manager.js +158 -0
- package/lib/cloud-connection/connection-manager.js.map +1 -0
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts +9 -30
- package/lib/cloud-connection/device-agent-cloud-connection.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent-cloud-connection.js +69 -508
- package/lib/cloud-connection/device-agent-cloud-connection.js.map +1 -1
- package/lib/cloud-connection/device-agent-message-handler.d.ts +22 -0
- package/lib/cloud-connection/device-agent-message-handler.d.ts.map +1 -0
- package/lib/cloud-connection/device-agent-message-handler.js +357 -0
- package/lib/cloud-connection/device-agent-message-handler.js.map +1 -0
- package/lib/cloud-connection/device-agent.d.ts.map +1 -1
- package/lib/cloud-connection/device-agent.js +11 -9
- package/lib/cloud-connection/device-agent.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.d.ts +19 -28
- package/lib/cloud-connection/live-updates-handler.d.ts.map +1 -1
- package/lib/cloud-connection/live-updates-handler.js +60 -172
- package/lib/cloud-connection/live-updates-handler.js.map +1 -1
- package/lib/cloud-connection/live-updates-handler.test.js +71 -165
- package/lib/cloud-connection/live-updates-handler.test.js.map +1 -1
- package/lib/cloud-connection/message-dispatcher.d.ts +10 -0
- package/lib/cloud-connection/message-dispatcher.d.ts.map +1 -0
- package/lib/cloud-connection/message-dispatcher.js +27 -0
- package/lib/cloud-connection/message-dispatcher.js.map +1 -0
- package/lib/cloud-connection/passthrough-handler.d.ts +4 -1
- package/lib/cloud-connection/passthrough-handler.d.ts.map +1 -1
- package/lib/cloud-connection/passthrough-handler.js +30 -11
- package/lib/cloud-connection/passthrough-handler.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.d.ts +11 -3
- package/lib/cloud-connection/shadow-handler.d.ts.map +1 -1
- package/lib/cloud-connection/shadow-handler.js +133 -28
- package/lib/cloud-connection/shadow-handler.js.map +1 -1
- package/lib/cloud-connection/shadow-handler.test.js +45 -57
- package/lib/cloud-connection/shadow-handler.test.js.map +1 -1
- package/lib/cloud-connection/shadow.d.ts.map +1 -1
- package/lib/cloud-connection/shadow.js +2 -1
- package/lib/cloud-connection/shadow.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.d.ts +12 -3
- package/lib/cloud-connection/transaction-manager.d.ts.map +1 -1
- package/lib/cloud-connection/transaction-manager.js +29 -28
- package/lib/cloud-connection/transaction-manager.js.map +1 -1
- package/lib/cloud-connection/transaction-manager.test.js +46 -5
- package/lib/cloud-connection/transaction-manager.test.js.map +1 -1
- package/lib/device-control/device-control.d.ts +8 -8
- package/lib/device-control/device-control.d.ts.map +1 -1
- package/lib/device-control/device-control.js +95 -71
- package/lib/device-control/device-control.js.map +1 -1
- package/lib/docker/docker-compose.d.ts.map +1 -1
- package/lib/docker/docker-compose.js +2 -1
- package/lib/docker/docker-compose.js.map +1 -1
- package/lib/infrastructure/agent-config.d.ts +2 -1
- package/lib/infrastructure/agent-config.d.ts.map +1 -1
- package/lib/infrastructure/agent-config.js +7 -7
- package/lib/infrastructure/agent-config.js.map +1 -1
- package/lib/infrastructure/agent-config.test.js +3 -1
- package/lib/infrastructure/agent-config.test.js.map +1 -1
- package/lib/infrastructure/config-check-utility.d.ts +6 -0
- package/lib/infrastructure/config-check-utility.d.ts.map +1 -0
- package/lib/infrastructure/config-check-utility.js +67 -0
- package/lib/infrastructure/config-check-utility.js.map +1 -0
- package/lib/infrastructure/config-check-utility.test.d.ts +2 -0
- package/lib/infrastructure/config-check-utility.test.d.ts.map +1 -0
- package/lib/infrastructure/config-check-utility.test.js +109 -0
- package/lib/infrastructure/config-check-utility.test.js.map +1 -0
- package/lib/infrastructure/device-certificate.d.ts +10 -0
- package/lib/infrastructure/device-certificate.d.ts.map +1 -0
- package/lib/infrastructure/device-certificate.js +47 -0
- package/lib/infrastructure/device-certificate.js.map +1 -0
- package/lib/infrastructure/device-certificate.test.d.ts +2 -0
- package/lib/infrastructure/device-certificate.test.d.ts.map +1 -0
- package/lib/infrastructure/device-certificate.test.js +24 -0
- package/lib/infrastructure/device-certificate.test.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts +2 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.js +61 -0
- package/lib/infrastructure/legacy-migration/legacy-file.test.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-files.d.ts +75 -0
- package/lib/infrastructure/legacy-migration/legacy-files.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-files.js +75 -0
- package/lib/infrastructure/legacy-migration/legacy-files.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.d.ts +6 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.js +149 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.js.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts +2 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.d.ts.map +1 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.js +226 -0
- package/lib/infrastructure/legacy-migration/legacy-migration.test.js.map +1 -0
- package/lib/infrastructure/require-files-present-ready.test.d.ts +2 -0
- package/lib/infrastructure/require-files-present-ready.test.d.ts.map +1 -0
- package/lib/infrastructure/require-files-present-ready.test.js +44 -0
- package/lib/infrastructure/require-files-present-ready.test.js.map +1 -0
- package/lib/infrastructure/required-config-checks.d.ts +2 -0
- package/lib/infrastructure/required-config-checks.d.ts.map +1 -0
- package/lib/infrastructure/required-config-checks.js +30 -0
- package/lib/infrastructure/required-config-checks.js.map +1 -0
- package/lib/infrastructure/tokens-and-device-cfg.d.ts.map +1 -1
- package/lib/infrastructure/tokens-and-device-cfg.js +11 -8
- package/lib/infrastructure/tokens-and-device-cfg.js.map +1 -1
- package/lib/jobs/job-handler.d.ts +23 -0
- package/lib/jobs/job-handler.d.ts.map +1 -0
- package/lib/jobs/job-handler.js +131 -0
- package/lib/jobs/job-handler.js.map +1 -0
- package/lib/local-connection/rabbitmq-connection.d.ts.map +1 -1
- package/lib/local-connection/rabbitmq-connection.js +14 -14
- package/lib/local-connection/rabbitmq-connection.js.map +1 -1
- package/lib/secure-tunneling/secure-tunnel-message-handler.d.ts +8 -0
- package/lib/secure-tunneling/secure-tunnel-message-handler.d.ts.map +1 -0
- package/lib/secure-tunneling/secure-tunnel-message-handler.js +42 -0
- package/lib/secure-tunneling/secure-tunnel-message-handler.js.map +1 -0
- package/lib/secure-tunneling/secure-tunneling.d.ts +9 -9
- package/lib/secure-tunneling/secure-tunneling.d.ts.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.js +21 -16
- package/lib/secure-tunneling/secure-tunneling.js.map +1 -1
- package/lib/secure-tunneling/secure-tunneling.test.js +11 -13
- package/lib/secure-tunneling/secure-tunneling.test.js.map +1 -1
- package/lib/subcommands/app/analytics.d.ts.map +1 -1
- package/lib/subcommands/app/analytics.js +1 -2
- package/lib/subcommands/app/analytics.js.map +1 -1
- package/lib/subcommands/app/env-vars.d.ts +4 -0
- package/lib/subcommands/app/env-vars.d.ts.map +1 -1
- package/lib/subcommands/app/env-vars.js +52 -6
- package/lib/subcommands/app/env-vars.js.map +1 -1
- package/lib/subcommands/app/index.d.ts.map +1 -1
- package/lib/subcommands/app/index.js +1 -3
- package/lib/subcommands/app/index.js.map +1 -1
- package/lib/subcommands/app/models.d.ts +0 -11
- package/lib/subcommands/app/models.d.ts.map +1 -1
- package/lib/subcommands/app/models.js +2 -58
- package/lib/subcommands/app/models.js.map +1 -1
- package/lib/subcommands/app/shadow.d.ts.map +1 -1
- package/lib/subcommands/app/shadow.js +6 -5
- package/lib/subcommands/app/shadow.js.map +1 -1
- package/lib/subcommands/app/version.d.ts +2 -0
- package/lib/subcommands/app/version.d.ts.map +1 -1
- package/lib/subcommands/app/version.js +16 -6
- package/lib/subcommands/app/version.js.map +1 -1
- package/lib/subcommands/config.d.ts +2 -0
- package/lib/subcommands/config.d.ts.map +1 -0
- package/lib/subcommands/config.js +39 -0
- package/lib/subcommands/config.js.map +1 -0
- package/lib/subcommands/device/clean.d.ts +1 -1
- package/lib/subcommands/device/clean.d.ts.map +1 -1
- package/lib/subcommands/device/clean.js +23 -13
- package/lib/subcommands/device/clean.js.map +1 -1
- package/lib/subcommands/device/index.d.ts.map +1 -1
- package/lib/subcommands/device/index.js +3 -1
- package/lib/subcommands/device/index.js.map +1 -1
- package/lib/subcommands/device/init.js +8 -8
- package/lib/subcommands/device/init.js.map +1 -1
- package/lib/subcommands/device/migrate.d.ts +2 -0
- package/lib/subcommands/device/migrate.d.ts.map +1 -0
- package/lib/subcommands/device/migrate.js +24 -0
- package/lib/subcommands/device/migrate.js.map +1 -0
- package/lib/subcommands/device/refresh.d.ts.map +1 -1
- package/lib/subcommands/device/refresh.js +1 -0
- package/lib/subcommands/device/refresh.js.map +1 -1
- package/lib/subcommands/index.d.ts +1 -1
- package/lib/subcommands/index.d.ts.map +1 -1
- package/lib/subcommands/index.js +3 -1
- package/lib/subcommands/index.js.map +1 -1
- package/lib/subcommands/rabbitmq-connection.d.ts +1 -1
- package/lib/subcommands/rabbitmq-connection.d.ts.map +1 -1
- package/lib/util/aai-error.d.ts +12 -0
- package/lib/util/aai-error.d.ts.map +1 -0
- package/lib/util/aai-error.js +11 -0
- package/lib/util/aai-error.js.map +1 -0
- package/lib/util/aws-regions.d.ts +2 -0
- package/lib/util/aws-regions.d.ts.map +1 -0
- package/lib/util/{cloud-mode-ready.js → aws-regions.js} +2 -20
- package/lib/util/aws-regions.js.map +1 -0
- package/lib/util/check-for-updates.d.ts.map +1 -1
- package/lib/util/check-for-updates.js +5 -28
- package/lib/util/check-for-updates.js.map +1 -1
- package/lib/util/clean-certs.d.ts.map +1 -1
- package/lib/util/clean-certs.js +5 -4
- package/lib/util/clean-certs.js.map +1 -1
- package/lib/util/directories.d.ts +4 -18
- package/lib/util/directories.d.ts.map +1 -1
- package/lib/util/directories.js +18 -32
- package/lib/util/directories.js.map +1 -1
- package/lib/util/file.d.ts +4 -0
- package/lib/util/file.d.ts.map +1 -1
- package/lib/util/file.js +65 -4
- package/lib/util/file.js.map +1 -1
- package/lib/util/get-device-id.d.ts.map +1 -1
- package/lib/util/get-device-id.js +7 -1
- package/lib/util/get-device-id.js.map +1 -1
- package/lib/util/http-client.js +3 -3
- package/lib/util/http-client.js.map +1 -1
- package/package.json +19 -17
- package/readme.md +12 -32
- package/src/application-control/config.ts +9 -12
- package/src/application-control/environment-variables.test.ts +28 -7
- package/src/application-control/environment-variables.ts +42 -59
- package/src/application-control/index.ts +3 -16
- package/src/application-control/install.ts +39 -13
- package/src/application-control/models.ts +6 -87
- package/src/application-control/utils.ts +10 -25
- package/src/cloud-connection/base-message-handler.ts +118 -0
- package/src/cloud-connection/bootstrap-provision.ts +7 -7
- package/src/cloud-connection/connection-manager.ts +187 -0
- package/src/cloud-connection/device-agent-cloud-connection.ts +130 -723
- package/src/cloud-connection/device-agent-message-handler.ts +642 -0
- package/src/cloud-connection/device-agent.ts +16 -7
- package/src/cloud-connection/live-updates-handler.test.ts +121 -189
- package/src/cloud-connection/live-updates-handler.ts +105 -232
- package/src/cloud-connection/message-dispatcher.ts +33 -0
- package/src/cloud-connection/passthrough-handler.ts +55 -18
- package/src/cloud-connection/shadow-handler.test.ts +45 -57
- package/src/cloud-connection/shadow-handler.ts +224 -54
- package/src/cloud-connection/shadow.ts +4 -1
- package/src/cloud-connection/transaction-manager.test.ts +68 -6
- package/src/cloud-connection/transaction-manager.ts +69 -41
- package/src/device-control/device-control.ts +102 -70
- package/src/docker/docker-compose.ts +3 -2
- package/src/infrastructure/agent-config.test.ts +6 -2
- package/src/infrastructure/agent-config.ts +8 -7
- package/src/infrastructure/config-check-utility.test.ts +154 -0
- package/src/infrastructure/config-check-utility.ts +77 -0
- package/src/infrastructure/device-certificate.test.ts +40 -0
- package/src/infrastructure/device-certificate.ts +58 -0
- package/src/infrastructure/legacy-migration/legacy-file.test.ts +88 -0
- package/src/infrastructure/legacy-migration/legacy-files.ts +101 -0
- package/src/infrastructure/legacy-migration/legacy-migration.test.ts +396 -0
- package/src/infrastructure/legacy-migration/legacy-migration.ts +229 -0
- package/src/infrastructure/require-files-present-ready.test.ts +53 -0
- package/src/infrastructure/required-config-checks.ts +33 -0
- package/src/infrastructure/tokens-and-device-cfg.ts +12 -10
- package/src/jobs/job-handler.ts +146 -0
- package/src/local-connection/rabbitmq-connection.ts +22 -17
- package/src/secure-tunneling/secure-tunnel-message-handler.ts +56 -0
- package/src/secure-tunneling/secure-tunneling.test.ts +20 -22
- package/src/secure-tunneling/secure-tunneling.ts +41 -29
- package/src/subcommands/app/analytics.ts +2 -4
- package/src/subcommands/app/env-vars.ts +72 -9
- package/src/subcommands/app/index.ts +3 -11
- package/src/subcommands/app/models.ts +5 -81
- package/src/subcommands/app/shadow.ts +6 -5
- package/src/subcommands/app/version.ts +23 -6
- package/src/subcommands/config.ts +42 -0
- package/src/subcommands/device/clean.ts +31 -17
- package/src/subcommands/device/index.ts +3 -1
- package/src/subcommands/device/init.ts +11 -11
- package/src/subcommands/device/migrate.ts +20 -0
- package/src/subcommands/device/refresh.ts +1 -0
- package/src/subcommands/index.ts +3 -1
- package/src/util/aai-error.ts +20 -0
- package/src/util/{cloud-mode-ready.ts → aws-regions.ts} +0 -24
- package/src/util/check-for-updates.ts +14 -30
- package/src/util/clean-certs.ts +8 -4
- package/src/util/directories.ts +23 -67
- package/src/util/file.ts +83 -3
- package/src/util/get-device-id.ts +7 -7
- package/src/util/http-client.ts +2 -2
- package/lib/util/cloud-mode-ready.d.ts +0 -3
- package/lib/util/cloud-mode-ready.d.ts.map +0 -1
- package/lib/util/cloud-mode-ready.js.map +0 -1
- package/lib/util/download-file.d.ts +0 -6
- package/lib/util/download-file.d.ts.map +0 -1
- package/lib/util/download-file.js +0 -25
- package/lib/util/download-file.js.map +0 -1
- package/lib/util/fetch-with-timeout.d.ts +0 -4
- package/lib/util/fetch-with-timeout.d.ts.map +0 -1
- package/lib/util/fetch-with-timeout.js +0 -30
- package/lib/util/fetch-with-timeout.js.map +0 -1
- package/lib/util/parsing.d.ts +0 -2
- package/lib/util/parsing.d.ts.map +0 -1
- package/lib/util/parsing.js +0 -17
- package/lib/util/parsing.js.map +0 -1
- package/src/util/download-file.ts +0 -25
- package/src/util/fetch-with-timeout.ts +0 -35
- package/src/util/parsing.ts +0 -11
|
@@ -1,47 +1,17 @@
|
|
|
1
|
-
// eslint-disable-next-line
|
|
2
|
-
const awsIot = require('aws-iot-device-sdk');
|
|
3
1
|
import {
|
|
4
|
-
AppInstallResponsePayload,
|
|
5
|
-
AppStateControlPayload,
|
|
6
|
-
AppVersionControlInstallPayload,
|
|
7
|
-
AppVersionControlUninstallPayload,
|
|
8
|
-
DeviceActionPayload,
|
|
9
|
-
ModelsInstallResponsePayload,
|
|
10
|
-
SignedUrlsRequestPayload,
|
|
11
|
-
ToCloudMessage,
|
|
12
|
-
ToDeviceAgentMessage,
|
|
13
|
-
getToDeviceTopic,
|
|
14
|
-
buildSignedUrlsRequestMessage,
|
|
15
2
|
buildToClientStatusResponseMessage,
|
|
16
|
-
|
|
17
|
-
keyMirrors
|
|
18
|
-
validateToDeviceAgentMessage,
|
|
19
|
-
validateSecureTunnelShadowUpdate
|
|
3
|
+
getToDeviceTopic,
|
|
4
|
+
keyMirrors
|
|
20
5
|
} from '@alwaysai/device-agent-schemas';
|
|
21
6
|
import { existsSync } from 'fs';
|
|
22
|
-
import {
|
|
23
|
-
installApp,
|
|
24
|
-
restartApp,
|
|
25
|
-
startApp,
|
|
26
|
-
stopApp,
|
|
27
|
-
uninstallApp,
|
|
28
|
-
updateAppCfg,
|
|
29
|
-
updateModelsWithPresignedUrls
|
|
30
|
-
} from '../application-control';
|
|
31
|
-
import { createAppBackup, rollbackApp } from '../application-control/backup';
|
|
32
|
-
import { reboot } from '../device-control/device-control';
|
|
33
7
|
import { ALWAYSAI_ANALYTICS_PASSTHROUGH } from '../environment';
|
|
34
|
-
import {
|
|
8
|
+
import { getBootstrapPrivateKeyFilePath } from '../infrastructure/device-certificate';
|
|
9
|
+
import { migrateFromLegacyCertsAndTokens } from '../infrastructure/legacy-migration/legacy-migration';
|
|
10
|
+
import { requiredConfigFilesPresentAndValid } from '../infrastructure/required-config-checks';
|
|
35
11
|
import { getIoTCoreEndpointUrl } from '../infrastructure/urls';
|
|
36
12
|
import { SecureTunnelHandlerSingleton } from '../secure-tunneling/secure-tunneling';
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
AWS_ROOT_CERTIFICATE_FILE_PATH,
|
|
40
|
-
BOOTSTRAP_CERTIFICATES_DIR_PATH,
|
|
41
|
-
BOOTSTRAP_PRIVATE_KEY_FILE_PATH,
|
|
42
|
-
DEVICE_CERTIFICATE_FILE_PATH,
|
|
43
|
-
DEVICE_PRIVATE_KEY_FILE_PATH
|
|
44
|
-
} from '../util/directories';
|
|
13
|
+
import { SecureTunnelMessageHandler } from '../secure-tunneling/secure-tunnel-message-handler';
|
|
14
|
+
import { getDeviceAgentVersion } from '../util/check-for-updates';
|
|
45
15
|
import { getDeviceUuid } from '../util/get-device-id';
|
|
46
16
|
import { logger } from '../util/logger';
|
|
47
17
|
import sleep from '../util/sleep';
|
|
@@ -49,716 +19,142 @@ import { bootstrapProvision } from './bootstrap-provision';
|
|
|
49
19
|
import { LiveUpdatesHandler } from './live-updates-handler';
|
|
50
20
|
import { PassthroughHandler } from './passthrough-handler';
|
|
51
21
|
import { Publisher } from './publisher';
|
|
52
|
-
import { ShadowHandler,
|
|
22
|
+
import { ShadowHandler, ProjectShadowMessageHandler } from './shadow-handler';
|
|
23
|
+
import { JobHandler } from '../jobs/job-handler';
|
|
53
24
|
import { TransactionManager } from './transaction-manager';
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
import { getDeviceAgentVersion } from '../util/check-for-updates';
|
|
58
|
-
|
|
59
|
-
const exec_promise = promisify(exec);
|
|
25
|
+
import { ConnectionManager } from './connection-manager';
|
|
26
|
+
import { DeviceAgentMessageHandler } from './device-agent-message-handler';
|
|
27
|
+
import { HandlerContext } from './base-message-handler';
|
|
60
28
|
|
|
61
29
|
export class DeviceAgentCloudConnection {
|
|
62
|
-
private
|
|
63
|
-
|
|
30
|
+
private connectionManager: ConnectionManager;
|
|
31
|
+
private transactionManager: TransactionManager;
|
|
64
32
|
private liveUpdatesHandler: LiveUpdatesHandler;
|
|
65
|
-
|
|
66
|
-
|
|
33
|
+
public shadowHandler: ShadowHandler;
|
|
34
|
+
public publisher: Publisher;
|
|
67
35
|
|
|
68
|
-
private clientId = getDeviceUuid();
|
|
69
|
-
private host = getIoTCoreEndpointUrl();
|
|
70
|
-
private port = 8883;
|
|
36
|
+
private readonly clientId = getDeviceUuid();
|
|
37
|
+
private readonly host = getIoTCoreEndpointUrl();
|
|
38
|
+
private readonly port = 8883;
|
|
71
39
|
private readonly toDeviceTopic = getToDeviceTopic(this.clientId);
|
|
72
|
-
private readonly secureTunnelNotifyTopic = `$aws/things/${this.clientId}/tunnels/notify`;
|
|
73
40
|
private readonly secureTunnelHandler =
|
|
74
41
|
SecureTunnelHandlerSingleton.getInstance();
|
|
75
42
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
): Promise<boolean> => {
|
|
79
|
-
const { baseCommand, projectId } = payload;
|
|
80
|
-
switch (baseCommand) {
|
|
81
|
-
case keyMirrors.appStateControl.start:
|
|
82
|
-
await startApp({ projectId });
|
|
83
|
-
break;
|
|
84
|
-
case keyMirrors.appStateControl.stop:
|
|
85
|
-
await stopApp({ projectId });
|
|
86
|
-
break;
|
|
87
|
-
case keyMirrors.appStateControl.restart:
|
|
88
|
-
await restartApp({ projectId });
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
return true;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
private handleAppVersionControl = async (
|
|
95
|
-
payload:
|
|
96
|
-
| AppVersionControlInstallPayload
|
|
97
|
-
| AppVersionControlUninstallPayload,
|
|
98
|
-
txId: string
|
|
99
|
-
): Promise<boolean> => {
|
|
100
|
-
switch (payload.baseCommand) {
|
|
101
|
-
case keyMirrors.appVersionControl.install: {
|
|
102
|
-
const { projectId, appReleaseHash } = payload;
|
|
103
|
-
|
|
104
|
-
const signedUrlsRequestPayload: SignedUrlsRequestPayload = {
|
|
105
|
-
signedUrlsRequest: {
|
|
106
|
-
projectId,
|
|
107
|
-
appReleaseHash
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
const message = buildSignedUrlsRequestMessage(
|
|
111
|
-
this.clientId,
|
|
112
|
-
signedUrlsRequestPayload,
|
|
113
|
-
txId
|
|
114
|
-
);
|
|
115
|
-
await this.publishCloudRequest(message);
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
case keyMirrors.appVersionControl.uninstall: {
|
|
119
|
-
const { projectId } = payload;
|
|
120
|
-
await this.atomicApplicationUninstall(projectId);
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
default:
|
|
124
|
-
logger.warn(
|
|
125
|
-
`Ignore App Version Control packet: ${JSON.stringify(
|
|
126
|
-
payload,
|
|
127
|
-
null,
|
|
128
|
-
2
|
|
129
|
-
)}`
|
|
130
|
-
);
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
private handleAppInstallCloudResponsePayload = async (
|
|
136
|
-
payload: AppInstallResponsePayload
|
|
137
|
-
): Promise<boolean> => {
|
|
138
|
-
const {
|
|
139
|
-
projectId,
|
|
140
|
-
appReleaseHash,
|
|
141
|
-
appInstallPayload,
|
|
142
|
-
modelsInstallPayload
|
|
143
|
-
} = payload.appInstallResponse;
|
|
144
|
-
const signedUrlsPayload = {
|
|
145
|
-
appInstallPayload,
|
|
146
|
-
modelsInstallPayload
|
|
147
|
-
};
|
|
148
|
-
await this.atomicApplicationUpdate(async () => {
|
|
149
|
-
this.shadowHandler.clearProjectShadow(projectId);
|
|
150
|
-
await installApp({ projectId, appReleaseHash, signedUrlsPayload });
|
|
151
|
-
}, projectId);
|
|
152
|
-
return true;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
private handleModelsInstallCloudResponsePayload = async (
|
|
156
|
-
payload: ModelsInstallResponsePayload,
|
|
157
|
-
txId: string
|
|
158
|
-
): Promise<boolean> => {
|
|
159
|
-
const projectId = payload.modelsInstallResponse.projectId;
|
|
160
|
-
|
|
161
|
-
const update = this.txnMgr.getAppCfgUpdateFromTxID(txId);
|
|
162
|
-
if (update === undefined) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
'Unknown error while updating models via application config! No config present for model update.'
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
const { appCfgUpdate, envVarUpdate } = update;
|
|
168
|
-
if (appCfgUpdate) {
|
|
169
|
-
await this.atomicApplicationUpdate(
|
|
170
|
-
async () =>
|
|
171
|
-
await updateModelsWithPresignedUrls({
|
|
172
|
-
projectId,
|
|
173
|
-
modelInstallPayloads: payload.modelsInstallResponse.newModels,
|
|
174
|
-
newAppCfg: appCfgUpdate.newAppCfg
|
|
175
|
-
}),
|
|
176
|
-
projectId
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
if (envVarUpdate) {
|
|
181
|
-
await this.atomicApplicationUpdate(
|
|
182
|
-
async () =>
|
|
183
|
-
await this.shadowHandler.updateProjectEnvVars({
|
|
184
|
-
projectId,
|
|
185
|
-
envVars: envVarUpdate.envVars
|
|
186
|
-
}),
|
|
187
|
-
projectId,
|
|
188
|
-
true
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return true;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
private async handleDeviceAction(payload: DeviceActionPayload) {
|
|
196
|
-
const { system_restart } = keyMirrors.deviceAction;
|
|
197
|
-
switch (payload.action) {
|
|
198
|
-
case system_restart: {
|
|
199
|
-
await reboot();
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
default: {
|
|
203
|
-
logger.info(
|
|
204
|
-
`Unrecognized device action requested: '${payload.action}'.`
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
private async publishCloudRequest(message: ToCloudMessage) {
|
|
211
|
-
this.publisher.publishToCloud(message);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
private subscribe(topic: string) {
|
|
215
|
-
logger.info(`Subscribing to ${topic}`);
|
|
216
|
-
this.device.subscribe(topic);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
private async atomicApplicationUninstall(projectId: string) {
|
|
220
|
-
try {
|
|
221
|
-
await uninstallApp({ projectId });
|
|
222
|
-
this.shadowHandler.clearProjectShadow(projectId);
|
|
223
|
-
} catch (e) {
|
|
224
|
-
logger.error(`Failed to uninstall ${projectId}: ${e.message}`);
|
|
225
|
-
throw e;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// eslint-disable-next-line
|
|
230
|
-
private async atomicApplicationUpdate <F extends () => any>(
|
|
231
|
-
func: F,
|
|
232
|
-
projectId: string,
|
|
233
|
-
skipUpdateShadow?: boolean
|
|
234
|
-
): Promise<ReturnType<F>> {
|
|
235
|
-
// First try to create a backup, so that there is one available if something goes wrong in the next try:catch.
|
|
236
|
-
if (await AgentConfigFile().isAppPresent({ projectId })) {
|
|
237
|
-
try {
|
|
238
|
-
await createAppBackup({ projectId });
|
|
239
|
-
} catch (e) {
|
|
240
|
-
logger.error(
|
|
241
|
-
`Could not create a backup for the project: ${projectId}:\n${e.message}\n${e.stack}`
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
try {
|
|
247
|
-
const out: ReturnType<F> = await func();
|
|
248
|
-
if (!skipUpdateShadow)
|
|
249
|
-
await this.shadowHandler.updateProjectShadow(projectId);
|
|
250
|
-
return out;
|
|
251
|
-
} catch (errorAppUpdate) {
|
|
252
|
-
logger.error(
|
|
253
|
-
`Failed to update ${projectId}:\n${JSON.stringify(errorAppUpdate)}}`
|
|
254
|
-
);
|
|
255
|
-
// If something goes wrong, first try to rollback
|
|
256
|
-
try {
|
|
257
|
-
await rollbackApp({ projectId });
|
|
258
|
-
logger.error(
|
|
259
|
-
`Application update failed, rolled back to previous version: ${errorAppUpdate}`
|
|
260
|
-
);
|
|
261
|
-
} catch (errorRollbackApp) {
|
|
262
|
-
// and if that fails, uninstall the app as a last resort.
|
|
263
|
-
try {
|
|
264
|
-
await this.atomicApplicationUninstall(projectId);
|
|
265
|
-
} catch {
|
|
266
|
-
// atomicApplicationUninstall handles failing, so there's nothing to handle here.
|
|
267
|
-
}
|
|
268
|
-
logger.error(
|
|
269
|
-
`Application update failed, rolled back to previous version: ${errorAppUpdate}`
|
|
270
|
-
);
|
|
271
|
-
throw new Error(
|
|
272
|
-
`Application update and rollback failed, uninstalled the application: ${errorAppUpdate}`
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
throw new Error(
|
|
276
|
-
`Application update failed, rolled the application back: ${errorAppUpdate}`
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
private handleProjectShadowConfigUpdate = async (
|
|
282
|
-
update: ShadowUpdate,
|
|
283
|
-
txId: string
|
|
284
|
-
): Promise<boolean> => {
|
|
285
|
-
const { projectId, appCfgUpdate, envVarUpdate } = update;
|
|
286
|
-
|
|
287
|
-
if (
|
|
288
|
-
appCfgUpdate?.updatedModels &&
|
|
289
|
-
Object.keys(appCfgUpdate.updatedModels).length
|
|
290
|
-
) {
|
|
291
|
-
// When there are model updates request signed URLs and wait to apply config changes
|
|
292
|
-
const { updatedModels } = appCfgUpdate;
|
|
293
|
-
|
|
294
|
-
logger.debug(
|
|
295
|
-
`Requesting presigned urls from cloud for model versions: ${JSON.stringify(
|
|
296
|
-
updatedModels
|
|
297
|
-
)}`
|
|
298
|
-
);
|
|
299
|
-
const modelsOnlyUrlsRequestPayload: SignedUrlsRequestPayload = {
|
|
300
|
-
modelsOnlyUrlsRequest: {
|
|
301
|
-
projectId,
|
|
302
|
-
models: updatedModels
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
const message = buildSignedUrlsRequestMessage(
|
|
306
|
-
this.clientId,
|
|
307
|
-
modelsOnlyUrlsRequestPayload,
|
|
308
|
-
txId
|
|
309
|
-
);
|
|
310
|
-
this.publisher.publishToCloud(message);
|
|
311
|
-
|
|
312
|
-
this.txnMgr.setAppCfgUpdateToTx(txId, update);
|
|
313
|
-
|
|
314
|
-
return false;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (appCfgUpdate) {
|
|
318
|
-
await this.atomicApplicationUpdate(async () => {
|
|
319
|
-
await pruneModels({
|
|
320
|
-
projectId,
|
|
321
|
-
appCfg: appCfgUpdate.newAppCfg
|
|
322
|
-
});
|
|
323
|
-
await updateAppCfg({
|
|
324
|
-
projectId,
|
|
325
|
-
newAppCfg: appCfgUpdate.newAppCfg
|
|
326
|
-
});
|
|
327
|
-
}, projectId);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (envVarUpdate) {
|
|
331
|
-
await this.atomicApplicationUpdate(
|
|
332
|
-
async () =>
|
|
333
|
-
await this.shadowHandler.updateProjectEnvVars({
|
|
334
|
-
projectId,
|
|
335
|
-
envVars: envVarUpdate.envVars
|
|
336
|
-
}),
|
|
337
|
-
projectId,
|
|
338
|
-
true
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
return true;
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
private async handleProjectShadowMessage(topic: string, message: any) {
|
|
345
|
-
const shadowUpdates = await this.shadowHandler.handleProjectShadow({
|
|
346
|
-
topic,
|
|
347
|
-
payload: message,
|
|
348
|
-
clientToken: message.clientToken
|
|
349
|
-
});
|
|
350
|
-
if (shadowUpdates.length) {
|
|
351
|
-
const shadowUpdatePromises: Promise<void>[] = [];
|
|
352
|
-
for (const shadowUpdate of shadowUpdates) {
|
|
353
|
-
const projectId = shadowUpdate.projectId;
|
|
354
|
-
const txId = shadowUpdate.txId;
|
|
355
|
-
shadowUpdatePromises.push(
|
|
356
|
-
this.txnMgr
|
|
357
|
-
.runTransactionStep({
|
|
358
|
-
func: () =>
|
|
359
|
-
this.handleProjectShadowConfigUpdate(shadowUpdate, txId),
|
|
360
|
-
projectId,
|
|
361
|
-
txId,
|
|
362
|
-
start: true,
|
|
363
|
-
stepName: topic
|
|
364
|
-
})
|
|
365
|
-
.catch((e: Error) => {
|
|
366
|
-
logger.error(
|
|
367
|
-
`There was an issue updating project shadow config: ${JSON.stringify(
|
|
368
|
-
e
|
|
369
|
-
)}`
|
|
370
|
-
);
|
|
371
|
-
})
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
await Promise.all(shadowUpdatePromises);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
public async handleSecureTunnelMessage(payload: any): Promise<void> {
|
|
380
|
-
logger.info(`Received secure tunnel update: ${JSON.stringify(payload)}`);
|
|
381
|
-
const state = payload.state;
|
|
382
|
-
if (!state) {
|
|
383
|
-
logger.debug(`No state found in message: ${JSON.stringify(payload)}`);
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
386
|
-
const valid = validateSecureTunnelShadowUpdate(state);
|
|
387
|
-
if (!valid) {
|
|
388
|
-
logger.error(
|
|
389
|
-
`Error validating message: ${JSON.stringify(
|
|
390
|
-
{ payload, errors: validateSecureTunnelShadowUpdate.errors },
|
|
391
|
-
null,
|
|
392
|
-
2
|
|
393
|
-
)}`
|
|
394
|
-
);
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
const secureTunnelUpdate =
|
|
398
|
-
await this.secureTunnelHandler.syncShadowToDeviceState(payload);
|
|
399
|
-
await this.shadowHandler.updateSecureTunnelShadow(secureTunnelUpdate);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
43
|
+
constructor() {
|
|
44
|
+
this.liveUpdatesHandler = new LiveUpdatesHandler();
|
|
402
45
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
46
|
+
// Initialize & setup the connection
|
|
47
|
+
this.connectionManager = new ConnectionManager(
|
|
48
|
+
this.clientId,
|
|
49
|
+
this.host,
|
|
50
|
+
this.port
|
|
51
|
+
);
|
|
52
|
+
this.connectionManager.setupConnection();
|
|
406
53
|
|
|
407
|
-
|
|
408
|
-
this.
|
|
409
|
-
|
|
410
|
-
certPath: DEVICE_CERTIFICATE_FILE_PATH,
|
|
411
|
-
caPath: AWS_ROOT_CERTIFICATE_FILE_PATH,
|
|
412
|
-
clientId: this.clientId,
|
|
413
|
-
host: this.host,
|
|
414
|
-
port: this.port,
|
|
415
|
-
keepalive: 1 // time before re-connect attempt on dropped connection, default is 400 seconds
|
|
416
|
-
});
|
|
417
|
-
this.publisher = new Publisher(this.device, this.clientId);
|
|
418
|
-
this.shadowHandler = new ShadowHandler(this.clientId, this.publisher);
|
|
419
|
-
this.liveUpdatesHandler = new LiveUpdatesHandler(
|
|
420
|
-
this.publisher,
|
|
54
|
+
// Initialize the Publisher, ShadowHandler & Transaction Manager
|
|
55
|
+
this.publisher = new Publisher(
|
|
56
|
+
this.connectionManager.getIoTDevice(),
|
|
421
57
|
this.clientId
|
|
422
58
|
);
|
|
423
|
-
this.
|
|
59
|
+
this.shadowHandler = new ShadowHandler(this.clientId, this.publisher);
|
|
60
|
+
|
|
61
|
+
this.transactionManager = new TransactionManager(
|
|
424
62
|
this.publisher,
|
|
425
63
|
this.liveUpdatesHandler
|
|
426
64
|
);
|
|
427
65
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
this.
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
public getClientId(): string {
|
|
438
|
-
return this.clientId;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
public getToDeviceTopic() {
|
|
442
|
-
return this.toDeviceTopic;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
public isCmdInProgress(projectId: string): boolean {
|
|
446
|
-
return this.txnMgr.isOngoingTransactionForProjectID(projectId);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
public async updateProjectShadow(projectId: string) {
|
|
450
|
-
await this.shadowHandler.updateProjectShadow(projectId);
|
|
451
|
-
}
|
|
66
|
+
// Construct a HandlerContext used by all the message handlers
|
|
67
|
+
const handlerContext: HandlerContext = {
|
|
68
|
+
clientId: this.clientId,
|
|
69
|
+
txnMgr: this.transactionManager,
|
|
70
|
+
publisher: this.publisher,
|
|
71
|
+
shadowHandler: this.shadowHandler,
|
|
72
|
+
liveUpdatesHandler: this.liveUpdatesHandler,
|
|
73
|
+
secureTunnelHandler: this.secureTunnelHandler
|
|
74
|
+
};
|
|
452
75
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
topic
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if (!valid) {
|
|
462
|
-
logger.error(
|
|
463
|
-
`Error validating message: ${JSON.stringify(
|
|
464
|
-
{ topic, message, errors: validateToDeviceAgentMessage.errors },
|
|
465
|
-
null,
|
|
466
|
-
2
|
|
467
|
-
)}`
|
|
76
|
+
// Instantiate & register message handlers for Project Shadow topics
|
|
77
|
+
const projectShadowMessageHandler = new ProjectShadowMessageHandler(
|
|
78
|
+
handlerContext
|
|
79
|
+
);
|
|
80
|
+
this.shadowHandler.projectShadowTopics.forEach((topic) => {
|
|
81
|
+
this.connectionManager.registerHandler(
|
|
82
|
+
topic,
|
|
83
|
+
projectShadowMessageHandler
|
|
468
84
|
);
|
|
469
|
-
|
|
470
|
-
return;
|
|
471
|
-
}
|
|
472
|
-
const txId = message.txId;
|
|
473
|
-
const {
|
|
474
|
-
app_state_control,
|
|
475
|
-
app_version_control,
|
|
476
|
-
live_state_updates,
|
|
477
|
-
app_install_response,
|
|
478
|
-
models_install_response,
|
|
479
|
-
status_response,
|
|
480
|
-
device_action
|
|
481
|
-
} = keyMirrors.toDeviceAgentMessageType;
|
|
482
|
-
switch (message.messageType) {
|
|
483
|
-
case app_state_control: {
|
|
484
|
-
// txId sent from cloud, just need to continue it
|
|
485
|
-
const payload = message.payload;
|
|
486
|
-
const projectId = payload.projectId;
|
|
487
|
-
|
|
488
|
-
try {
|
|
489
|
-
await this.txnMgr.runTransactionStep({
|
|
490
|
-
func: () => this.handleAppStateControl(message.payload),
|
|
491
|
-
projectId,
|
|
492
|
-
txId,
|
|
493
|
-
start: true,
|
|
494
|
-
stepName: payload.baseCommand
|
|
495
|
-
});
|
|
496
|
-
} catch (e) {
|
|
497
|
-
logger.error(
|
|
498
|
-
`Error processing application state control request: ${e}!`
|
|
499
|
-
);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
break;
|
|
503
|
-
}
|
|
504
|
-
case app_version_control: {
|
|
505
|
-
// txId sent from cloud, just need to continue it
|
|
506
|
-
const payload = message.payload;
|
|
507
|
-
const projectId = payload.projectId;
|
|
508
|
-
try {
|
|
509
|
-
await this.txnMgr.runTransactionStep({
|
|
510
|
-
func: () => this.handleAppVersionControl(payload, txId),
|
|
511
|
-
projectId,
|
|
512
|
-
txId,
|
|
513
|
-
start: true,
|
|
514
|
-
stepName: payload.baseCommand
|
|
515
|
-
});
|
|
516
|
-
} catch (e) {
|
|
517
|
-
logger.error(`Error processing application install request: ${e}!`);
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
break;
|
|
521
|
-
}
|
|
522
|
-
case live_state_updates: {
|
|
523
|
-
const payload = message.payload;
|
|
524
|
-
// TODO: Send response?
|
|
525
|
-
void this.liveUpdatesHandler.handleToggles(payload, txId);
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
case app_install_response: {
|
|
529
|
-
const payload = message.payload;
|
|
530
|
-
const { projectId } = payload.appInstallResponse;
|
|
531
|
-
if (txId !== this.txnMgr.getTransactionFromProject(projectId)) {
|
|
532
|
-
throw new Error(
|
|
533
|
-
`App install response received a message for a transaction ID ${txId} that is not currently underway (${this.txnMgr.getTransactionFromProject(
|
|
534
|
-
projectId
|
|
535
|
-
)})!`
|
|
536
|
-
);
|
|
537
|
-
}
|
|
538
|
-
await this.txnMgr.runTransactionStep({
|
|
539
|
-
func: () => this.handleAppInstallCloudResponsePayload(payload),
|
|
540
|
-
projectId,
|
|
541
|
-
txId,
|
|
542
|
-
start: false,
|
|
543
|
-
stepName: message.messageType
|
|
544
|
-
});
|
|
545
|
-
break;
|
|
546
|
-
}
|
|
547
|
-
case models_install_response: {
|
|
548
|
-
// This message doesn't have appReleaseHash in it's payload, but
|
|
549
|
-
// atomicCmd should be able to read it from the installed app
|
|
550
|
-
const payload = message.payload;
|
|
551
|
-
const { projectId } = payload.modelsInstallResponse;
|
|
552
|
-
if (txId !== this.txnMgr.getTransactionFromProject(projectId)) {
|
|
553
|
-
throw new Error(
|
|
554
|
-
`Model install response received a message for a transaction ID ${txId} that is not currently underway (${this.txnMgr.getTransactionFromProject(
|
|
555
|
-
projectId
|
|
556
|
-
)})!`
|
|
557
|
-
);
|
|
558
|
-
}
|
|
559
|
-
await this.txnMgr.runTransactionStep({
|
|
560
|
-
func: () =>
|
|
561
|
-
this.handleModelsInstallCloudResponsePayload(payload, txId),
|
|
562
|
-
projectId,
|
|
563
|
-
txId,
|
|
564
|
-
start: false,
|
|
565
|
-
stepName: message.messageType
|
|
566
|
-
});
|
|
567
|
-
break;
|
|
568
|
-
}
|
|
569
|
-
case status_response: {
|
|
570
|
-
const { failure } = keyMirrors.statusResponse;
|
|
571
|
-
if (message.payload.status === failure) {
|
|
572
|
-
this.txnMgr.completeTransaction(txId);
|
|
85
|
+
});
|
|
573
86
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
case device_action: {
|
|
590
|
-
try {
|
|
591
|
-
const statusResponsePayload: StatusResponsePayload = {
|
|
592
|
-
status: keyMirrors.statusResponse.in_progress
|
|
593
|
-
};
|
|
594
|
-
const statusResponseMessage = buildToClientStatusResponseMessage(
|
|
595
|
-
this.clientId,
|
|
596
|
-
statusResponsePayload,
|
|
87
|
+
// Instantiate & register message handlers for to-device and secureTunnel topics
|
|
88
|
+
this.connectionManager.registerHandler(
|
|
89
|
+
this.toDeviceTopic,
|
|
90
|
+
new DeviceAgentMessageHandler(
|
|
91
|
+
handlerContext,
|
|
92
|
+
(txId: string, errorMsg: string) => {
|
|
93
|
+
const msg = buildToClientStatusResponseMessage(
|
|
94
|
+
this.publisher.getClientId(),
|
|
95
|
+
{
|
|
96
|
+
status: keyMirrors.statusResponse.failure,
|
|
97
|
+
message: errorMsg
|
|
98
|
+
},
|
|
597
99
|
txId
|
|
598
100
|
);
|
|
599
|
-
this.publisher.publishToClient(
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
status: keyMirrors.statusResponse.success
|
|
605
|
-
|
|
606
|
-
const successStatusResponseMessage =
|
|
607
|
-
buildToClientStatusResponseMessage(
|
|
608
|
-
this.clientId,
|
|
609
|
-
successStatusResponsePayload,
|
|
610
|
-
txId
|
|
611
|
-
);
|
|
612
|
-
this.publisher.publishToClient(successStatusResponseMessage);
|
|
613
|
-
} catch (e) {
|
|
614
|
-
logger.error(
|
|
615
|
-
`There was a problem performing device action '${message.payload.action}': ${e.message}`
|
|
101
|
+
this.publisher.publishToClient(msg);
|
|
102
|
+
},
|
|
103
|
+
(txId: string) => {
|
|
104
|
+
const msg = buildToClientStatusResponseMessage(
|
|
105
|
+
this.publisher.getClientId(),
|
|
106
|
+
{ status: keyMirrors.statusResponse.success },
|
|
107
|
+
txId
|
|
616
108
|
);
|
|
617
|
-
|
|
618
|
-
status: keyMirrors.statusResponse.failure,
|
|
619
|
-
message: e.message
|
|
620
|
-
};
|
|
621
|
-
const failureStatusResponseMessage =
|
|
622
|
-
buildToClientStatusResponseMessage(
|
|
623
|
-
this.clientId,
|
|
624
|
-
failureStatusResponsePayload,
|
|
625
|
-
txId
|
|
626
|
-
);
|
|
627
|
-
this.publisher.publishToClient(failureStatusResponseMessage);
|
|
109
|
+
this.publisher.publishToClient(msg);
|
|
628
110
|
}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
default:
|
|
632
|
-
logger.error(
|
|
633
|
-
`Invalid client message: '${JSON.stringify(
|
|
634
|
-
{ topic, message, txId },
|
|
635
|
-
null,
|
|
636
|
-
2
|
|
637
|
-
)}'`
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
111
|
+
)
|
|
112
|
+
);
|
|
641
113
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
114
|
+
const secureTunnelMessageHandler = new SecureTunnelMessageHandler(
|
|
115
|
+
handlerContext
|
|
116
|
+
);
|
|
117
|
+
this.connectionManager.registerHandler(
|
|
118
|
+
secureTunnelMessageHandler.getNotifyTopic(),
|
|
119
|
+
secureTunnelMessageHandler
|
|
645
120
|
);
|
|
646
|
-
// ProjectShadow messages
|
|
647
|
-
if (this.shadowHandler.projectShadowTopics.includes(topic)) {
|
|
648
|
-
await this.handleProjectShadowMessage(topic, message);
|
|
649
|
-
} else if (topic === this.toDeviceTopic) {
|
|
650
|
-
await this.handleDeviceAgentMessage({
|
|
651
|
-
topic,
|
|
652
|
-
message
|
|
653
|
-
});
|
|
654
|
-
// SecureTunnelNotify messages
|
|
655
|
-
} else if (topic === this.secureTunnelNotifyTopic) {
|
|
656
|
-
await this.secureTunnelHandler.secureTunnelNotifyHandler(message);
|
|
657
|
-
// SecureTunnel messages
|
|
658
|
-
} else if (
|
|
659
|
-
topic === this.shadowHandler.shadowTopics.secureTunnel.updateDelta
|
|
660
|
-
) {
|
|
661
|
-
await this.handleSecureTunnelMessage(message);
|
|
662
|
-
} else if (
|
|
663
|
-
topic === this.shadowHandler.shadowTopics.secureTunnel.deleteAccepted
|
|
664
|
-
) {
|
|
665
|
-
logger.info(`Received secure tunnel deleteAccepted: ${message}`);
|
|
666
|
-
await this.secureTunnelHandler.destroy();
|
|
667
|
-
} else {
|
|
668
|
-
logger.error(`Unexpected topic, ignoring! ${topic}`);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
121
|
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
122
|
+
this.connectionManager.registerHandler(
|
|
123
|
+
this.shadowHandler.shadowTopics.secureTunnel.updateDelta,
|
|
124
|
+
secureTunnelMessageHandler
|
|
125
|
+
);
|
|
126
|
+
this.connectionManager.registerHandler(
|
|
127
|
+
this.shadowHandler.shadowTopics.secureTunnel.deleteAccepted,
|
|
128
|
+
secureTunnelMessageHandler
|
|
129
|
+
);
|
|
680
130
|
|
|
681
|
-
|
|
682
|
-
logger.warn('Device Agent has been disconnected from the cloud');
|
|
683
|
-
});
|
|
131
|
+
const jobHandler = new JobHandler(handlerContext);
|
|
684
132
|
|
|
685
|
-
|
|
686
|
-
logger.info(
|
|
687
|
-
`Device Agent attempting to re-connect ${new Date().toLocaleString()}`
|
|
688
|
-
);
|
|
689
|
-
});
|
|
133
|
+
const JOB_HANDLER_TOPICS = jobHandler.getJobTopic();
|
|
690
134
|
|
|
691
|
-
this.
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
135
|
+
this.connectionManager.registerHandler(
|
|
136
|
+
JOB_HANDLER_TOPICS.NOTIFY_NEXT,
|
|
137
|
+
jobHandler
|
|
138
|
+
);
|
|
695
139
|
|
|
696
|
-
this.
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
} catch (e) {
|
|
701
|
-
logger.error(`Error parsing message: ${e.message}`);
|
|
702
|
-
}
|
|
703
|
-
});
|
|
140
|
+
this.connectionManager.registerHandler(
|
|
141
|
+
JOB_HANDLER_TOPICS.START_NEXT_ACCEPTED,
|
|
142
|
+
jobHandler
|
|
143
|
+
);
|
|
704
144
|
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
void this.logConnectionInfo();
|
|
708
|
-
});
|
|
145
|
+
// Initialize job
|
|
146
|
+
this.publisher.publish(JOB_HANDLER_TOPICS.START_NEXT, JSON.stringify({}));
|
|
709
147
|
}
|
|
710
148
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
* nc -zv -w 1 a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com 8883
|
|
721
|
-
*
|
|
722
|
-
* Sample output when port is not blocked and host is reachable:
|
|
723
|
-
* $ nc -zv -w 1 a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com 443
|
|
724
|
-
* Connection to a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com 443 port [tcp/https] succeeded!
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
* Sample output when port is blocked (will repeatedly try until ctrl-C out):
|
|
728
|
-
* $ nc -zv -w 1 a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com 8883
|
|
729
|
-
* nc: connect to a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com port 8883 (tcp) timed out: Operation now in progress
|
|
730
|
-
* nc: connect to a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com port 8883 (tcp) timed out: Operation now in progress
|
|
731
|
-
* nc: connect to a3tzi5g7sq5zsj-ats.iot.us-west-2.amazonaws.com port 8883 (tcp) timed out: Operation now in progress
|
|
732
|
-
* ^C
|
|
733
|
-
*
|
|
734
|
-
*
|
|
735
|
-
* Sample command/output when the port isn't enable on that host:
|
|
736
|
-
* $ nc -zv -w 1 localhost 8883
|
|
737
|
-
* nc: connect to localhost port 8883 (tcp) failed: Connection refused
|
|
738
|
-
*/
|
|
739
|
-
await exec_promise(`nc -zv -w 1 ${this.host} ${this.port}`, {
|
|
740
|
-
timeout: 2000
|
|
741
|
-
});
|
|
742
|
-
} catch (err) {
|
|
743
|
-
const output = JSON.stringify(err['stderr']);
|
|
744
|
-
if (output.indexOf('not known') !== -1) {
|
|
745
|
-
logger.warn(
|
|
746
|
-
'Iot Core endpoint appears to be unreachable, internet connection may be unstable or the host may be down.'
|
|
747
|
-
);
|
|
748
|
-
} else if (output.indexOf('timed out') !== -1) {
|
|
749
|
-
logger.warn(
|
|
750
|
-
`Internet connection appears fine, however the endpoint was not reachable on the current connection port: ${this.port}\nPlease check if a firewall is in place.`
|
|
751
|
-
);
|
|
752
|
-
} else if (output.indexOf('refused') !== -1) {
|
|
753
|
-
logger.warn(
|
|
754
|
-
`The connection was refused, likely ${this.host} is not running a service on ${this.port}.`
|
|
755
|
-
);
|
|
756
|
-
} else {
|
|
757
|
-
logger.warn(
|
|
758
|
-
`Output from checking connection to ${this.host} on ${this.port}: ${output}`
|
|
759
|
-
);
|
|
760
|
-
}
|
|
761
|
-
}
|
|
149
|
+
/*=================================================================
|
|
150
|
+
Public interface
|
|
151
|
+
=================================================================*/
|
|
152
|
+
public getClientId(): string {
|
|
153
|
+
return this.clientId;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public isCmdInProgress(projectId: string): boolean {
|
|
157
|
+
return this.transactionManager.isOngoingTransactionForProjectID(projectId);
|
|
762
158
|
}
|
|
763
159
|
|
|
764
160
|
public async stop() {
|
|
@@ -766,7 +162,10 @@ export class DeviceAgentCloudConnection {
|
|
|
766
162
|
// lost since we aren't waiting for responses so sleep for a short time to
|
|
767
163
|
// receive them
|
|
768
164
|
await sleep(1000);
|
|
769
|
-
this.
|
|
165
|
+
this.connectionManager.disconnect();
|
|
166
|
+
}
|
|
167
|
+
public async handleMessage(topic: string, message: any) {
|
|
168
|
+
this.connectionManager.dispatch(topic, message);
|
|
770
169
|
}
|
|
771
170
|
}
|
|
772
171
|
|
|
@@ -774,20 +173,28 @@ export async function runDeviceAgentCloudInterface() {
|
|
|
774
173
|
logger.info(
|
|
775
174
|
`Starting alwaysAI Device Agent v${await getDeviceAgentVersion()}`
|
|
776
175
|
);
|
|
777
|
-
if (
|
|
176
|
+
if (existsSync(getBootstrapPrivateKeyFilePath())) {
|
|
177
|
+
await bootstrapProvision();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const filesAlreadyMigrated = await requiredConfigFilesPresentAndValid();
|
|
182
|
+
if (!filesAlreadyMigrated) {
|
|
183
|
+
logger.debug('Attempting configuration file migration.');
|
|
184
|
+
await migrateFromLegacyCertsAndTokens();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (await requiredConfigFilesPresentAndValid()) {
|
|
778
188
|
const deviceAgent = new DeviceAgentCloudConnection();
|
|
779
|
-
await deviceAgent.setupHandlers();
|
|
780
189
|
if (ALWAYSAI_ANALYTICS_PASSTHROUGH === true) {
|
|
190
|
+
const shadowHandler = deviceAgent.shadowHandler;
|
|
781
191
|
const publisher = deviceAgent.publisher;
|
|
782
|
-
const passthroughHandler = new PassthroughHandler(
|
|
192
|
+
const passthroughHandler = new PassthroughHandler(
|
|
193
|
+
publisher,
|
|
194
|
+
shadowHandler
|
|
195
|
+
);
|
|
783
196
|
await passthroughHandler.setup();
|
|
784
197
|
}
|
|
785
|
-
} else if (existsSync(BOOTSTRAP_PRIVATE_KEY_FILE_PATH())) {
|
|
786
|
-
await bootstrapProvision();
|
|
787
|
-
} else if (existsSync(BOOTSTRAP_CERTIFICATES_DIR_PATH())) {
|
|
788
|
-
throw new Error(
|
|
789
|
-
"Device has not been created using 'aai-agent device init' or there has been an issue with device initialization"
|
|
790
|
-
);
|
|
791
198
|
} else {
|
|
792
199
|
throw new Error(
|
|
793
200
|
"Set device agent to local mode and retry the 'aai-agent device init' command"
|