esp-morpheus 0.9.0__tar.gz

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 (78) hide show
  1. esp_morpheus-0.9.0/LICENSE +202 -0
  2. esp_morpheus-0.9.0/PKG-INFO +434 -0
  3. esp_morpheus-0.9.0/README.md +390 -0
  4. esp_morpheus-0.9.0/pyproject.toml +74 -0
  5. esp_morpheus-0.9.0/setup.cfg +4 -0
  6. esp_morpheus-0.9.0/src/esp_morpheus/__init__.py +7 -0
  7. esp_morpheus-0.9.0/src/esp_morpheus/cli/__init__.py +3 -0
  8. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/__init__.py +173 -0
  9. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/botuser.py +212 -0
  10. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/gendevice.py +61 -0
  11. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/integrations.py +211 -0
  12. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/messaging.py +156 -0
  13. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/nodes.py +71 -0
  14. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/platforms.py +118 -0
  15. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/runtime.py +74 -0
  16. esp_morpheus-0.9.0/src/esp_morpheus/cli/admin/testdata.py +375 -0
  17. esp_morpheus-0.9.0/src/esp_morpheus/cli/context.py +399 -0
  18. esp_morpheus-0.9.0/src/esp_morpheus/cli/device.py +126 -0
  19. esp_morpheus-0.9.0/src/esp_morpheus/cli/groups.py +251 -0
  20. esp_morpheus-0.9.0/src/esp_morpheus/cli/guide.py +155 -0
  21. esp_morpheus-0.9.0/src/esp_morpheus/cli/main.py +176 -0
  22. esp_morpheus-0.9.0/src/esp_morpheus/cli/matter.py +139 -0
  23. esp_morpheus-0.9.0/src/esp_morpheus/cli/nodes.py +106 -0
  24. esp_morpheus-0.9.0/src/esp_morpheus/cli/output.py +360 -0
  25. esp_morpheus-0.9.0/src/esp_morpheus/cli/sharing.py +93 -0
  26. esp_morpheus-0.9.0/src/esp_morpheus/cli/shell.py +229 -0
  27. esp_morpheus-0.9.0/src/esp_morpheus/cli/sims.py +263 -0
  28. esp_morpheus-0.9.0/src/esp_morpheus/cli/user.py +191 -0
  29. esp_morpheus-0.9.0/src/esp_morpheus/data/examples/alexa_skills_config.example.json +5 -0
  30. esp_morpheus-0.9.0/src/esp_morpheus/data/examples/bot-iam-user-credentials.example.json +5 -0
  31. esp_morpheus-0.9.0/src/esp_morpheus/data/examples/gva_config.example.json +13 -0
  32. esp_morpheus-0.9.0/src/esp_morpheus/data/node_config_va_light.json +25 -0
  33. esp_morpheus-0.9.0/src/esp_morpheus/data/node_config_va_multi.json +264 -0
  34. esp_morpheus-0.9.0/src/esp_morpheus/data/node_config_va_switch.json +19 -0
  35. esp_morpheus-0.9.0/src/esp_morpheus/data/node_tags.json +11 -0
  36. esp_morpheus-0.9.0/src/esp_morpheus/data/test_config.default.json +48 -0
  37. esp_morpheus-0.9.0/src/esp_morpheus/outputs.py +292 -0
  38. esp_morpheus-0.9.0/src/esp_morpheus/paths.py +135 -0
  39. esp_morpheus-0.9.0/src/esp_morpheus/sdk/__init__.py +3 -0
  40. esp_morpheus-0.9.0/src/esp_morpheus/sdk/alexa_setup.py +645 -0
  41. esp_morpheus-0.9.0/src/esp_morpheus/sdk/device.py +1640 -0
  42. esp_morpheus-0.9.0/src/esp_morpheus/sdk/errors.py +92 -0
  43. esp_morpheus-0.9.0/src/esp_morpheus/sdk/group.py +269 -0
  44. esp_morpheus-0.9.0/src/esp_morpheus/sdk/gva_setup.py +233 -0
  45. esp_morpheus-0.9.0/src/esp_morpheus/sdk/kvs_viewer.py +2029 -0
  46. esp_morpheus-0.9.0/src/esp_morpheus/sdk/mailosaur.py +235 -0
  47. esp_morpheus-0.9.0/src/esp_morpheus/sdk/matter.py +249 -0
  48. esp_morpheus-0.9.0/src/esp_morpheus/sdk/ses.py +110 -0
  49. esp_morpheus-0.9.0/src/esp_morpheus/sdk/smartthings.py +122 -0
  50. esp_morpheus-0.9.0/src/esp_morpheus/sdk/user.py +3724 -0
  51. esp_morpheus-0.9.0/src/esp_morpheus/sdk/util.py +129 -0
  52. esp_morpheus-0.9.0/src/esp_morpheus/sims/__init__.py +3 -0
  53. esp_morpheus-0.9.0/src/esp_morpheus/sims/app.py +1473 -0
  54. esp_morpheus-0.9.0/src/esp_morpheus/sims/chal_resp_proto/__init__.py +0 -0
  55. esp_morpheus-0.9.0/src/esp_morpheus/sims/chal_resp_proto/esp_rmaker_chal_resp.proto +61 -0
  56. esp_morpheus-0.9.0/src/esp_morpheus/sims/chal_resp_proto/esp_rmaker_chal_resp_pb2.py +52 -0
  57. esp_morpheus-0.9.0/src/esp_morpheus/sims/chal_resp_proto/esp_rmaker_claim.proto +45 -0
  58. esp_morpheus-0.9.0/src/esp_morpheus/sims/chal_resp_proto/esp_rmaker_claim_pb2.py +44 -0
  59. esp_morpheus-0.9.0/src/esp_morpheus/sims/device.py +666 -0
  60. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/proto/constants.proto +18 -0
  61. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/proto/sec0.proto +32 -0
  62. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/proto/sec1.proto +49 -0
  63. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/proto/sec2.proto +52 -0
  64. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/proto/session.proto +29 -0
  65. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/python/constants_pb2.py +36 -0
  66. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/python/sec0_pb2.py +43 -0
  67. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/python/sec1_pb2.py +47 -0
  68. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/python/sec2_pb2.py +47 -0
  69. esp_morpheus-0.9.0/src/esp_morpheus/sims/idf_protocomm/components/protocomm/python/session_pb2.py +41 -0
  70. esp_morpheus-0.9.0/src/esp_morpheus/sims/prov_ble.py +336 -0
  71. esp_morpheus-0.9.0/src/esp_morpheus/sims/sparse_dep.py +190 -0
  72. esp_morpheus-0.9.0/src/esp_morpheus.egg-info/PKG-INFO +434 -0
  73. esp_morpheus-0.9.0/src/esp_morpheus.egg-info/SOURCES.txt +76 -0
  74. esp_morpheus-0.9.0/src/esp_morpheus.egg-info/dependency_links.txt +1 -0
  75. esp_morpheus-0.9.0/src/esp_morpheus.egg-info/entry_points.txt +2 -0
  76. esp_morpheus-0.9.0/src/esp_morpheus.egg-info/requires.txt +23 -0
  77. esp_morpheus-0.9.0/src/esp_morpheus.egg-info/top_level.txt +1 -0
  78. esp_morpheus-0.9.0/tests/test_cli.py +1626 -0
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,434 @@
1
+ Metadata-Version: 2.4
2
+ Name: esp-morpheus
3
+ Version: 0.9.0
4
+ Summary: Console client for an ESP RainMaker Neo deployment
5
+ Author: Espressif Systems (Shanghai) CO LTD
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/espressif/esp-rainmaker-neo
8
+ Project-URL: Source, https://github.com/espressif/esp-rainmaker-neo
9
+ Project-URL: Changelog, https://github.com/espressif/esp-rainmaker-neo/blob/main/cli/CHANGELOG.md
10
+ Keywords: espressif,rainmaker,iot,matter,cli
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Software Development :: Testing
19
+ Requires-Python: >=3.12
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: boto3>=1.43
23
+ Requires-Dist: botocore>=1.43
24
+ Requires-Dist: requests>=2.32
25
+ Requires-Dist: cryptography>=44
26
+ Requires-Dist: PyJWT>=2.9
27
+ Requires-Dist: awscrt>=0.36
28
+ Requires-Dist: awsiotsdk>=1.31
29
+ Requires-Dist: prompt_toolkit>=3.0.50
30
+ Requires-Dist: click>=8.1
31
+ Requires-Dist: rich>=13.7
32
+ Requires-Dist: bleak>=3.0
33
+ Requires-Dist: protobuf<7,>=6.30
34
+ Requires-Dist: ask-smapi-sdk>=1.0
35
+ Requires-Dist: ask-smapi-model>=1.36
36
+ Requires-Dist: ask-sdk-model-runtime>=1.0
37
+ Provides-Extra: camera
38
+ Requires-Dist: aiortc>=1.15; extra == "camera"
39
+ Requires-Dist: websockets>=11.0; extra == "camera"
40
+ Requires-Dist: opencv-python>=4.8; extra == "camera"
41
+ Provides-Extra: test
42
+ Requires-Dist: pytest>=8.0; extra == "test"
43
+ Dynamic: license-file
44
+
45
+ # `esp-morpheus` — the ESP RainMaker Neo console client
46
+
47
+ `esp-morpheus` configures and exercises an ESP RainMaker Neo deployment end to end. It authenticates
48
+ users, registers and destroys IoT nodes, drives the user-facing REST API, connects to MQTT as a user
49
+ or as a simulated device, and manages groups, sharing, mobile push platforms and Matter
50
+ commissioning. It validates any deployment feature with no device and no phone app.
51
+
52
+ It installs as a command and runs from any directory, against any deployment, with no checkout of
53
+ this repository.
54
+
55
+ To reach a deployment, `esp-morpheus` needs its **outputs**: every deployment publishes its common
56
+ outputs to one file, which phone apps, the dashboard and this client all read. `esp-morpheus` reads
57
+ `rmng-outputs.json`, or the source given by `--client-outputs`.
58
+
59
+ Most of `esp-morpheus` needs nothing else. Driving a deployment as a user or a node goes through the
60
+ deployment's own API and its MQTT broker — an end user signs in against the API and is handed
61
+ credentials by it — so `esp-morpheus --client-outputs <url> user someone@example.com` works with no AWS
62
+ account, no profile, and no checkout.
63
+
64
+ **AWS credentials** are needed only under `esp-morpheus admin`, which holds the whole privileged
65
+ surface: every command that reaches AWS directly or calls the admin API. The ones that reach AWS
66
+ create, delete or sweep real resources, so they check that the credentials name the account in the
67
+ outputs and refuse to run against another one. The region is not enforced: every AWS client is
68
+ built with the region from the outputs, so a differing ambient region is reported and ignored.
69
+
70
+ ---
71
+
72
+ ## 1. Install
73
+
74
+ ```bash
75
+ pip install esp-morpheus
76
+ ```
77
+
78
+ `user <id> node camera-stream` needs the WebRTC stack (aiortc, OpenCV), which is heavy and ships as
79
+ an extra:
80
+
81
+ ```bash
82
+ pip install 'esp-morpheus[camera]'
83
+ ```
84
+
85
+ From a checkout, install it in place:
86
+
87
+ ```bash
88
+ pip install -e ./cli
89
+ ```
90
+
91
+ Needs Python 3.12 or later.
92
+
93
+ ## 2. Point it at a deployment
94
+
95
+ The outputs are a JSON file keyed by stack name (`espuser-base`, `espuser-core`, `rmng-base`,
96
+ `rmng-core`, ...). Give `esp-morpheus` a path or a URL.
97
+
98
+ **A local file (default).** With no flag, `esp-morpheus` reads `rmng-outputs.json`. Run from
99
+ anywhere inside a checkout, a relative path resolves against the repo root (`MORPHEUS_REPO_ROOT`
100
+ overrides the detected root); run from outside one, it resolves against the working directory.
101
+
102
+ ```bash
103
+ esp-morpheus user someone@example.com
104
+ ```
105
+
106
+ **A URL.** Point `--client-outputs` at a published outputs file, such as the per-region
107
+ client-outputs in S3. It is fetched at startup, so nothing is downloaded by hand. The bucket is
108
+ always in `us-east-1`; the path names the deployment's region.
109
+
110
+ ```bash
111
+ esp-morpheus --client-outputs https://rmng-public-assets-123456789012.s3.us-east-1.amazonaws.com/ap-south-1/rmng-client-outputs.json \
112
+ user someone@example.com
113
+ ```
114
+
115
+ `MORPHEUS_OUTPUTS` sets the same value, so a shell session can pick a deployment once.
116
+
117
+ ## 3. Pick an identity
118
+
119
+ Everything `esp-morpheus` does, it does as somebody.
120
+
121
+ ### An account that already exists
122
+
123
+ Pass any account provisioned in the deployment.
124
+
125
+ ```bash
126
+ esp-morpheus user someone@example.com # prompts for the password
127
+ ```
128
+
129
+ This tree is the end-user API and nothing else: it signs in against the end-user pool, and an admin
130
+ account belongs to `esp-morpheus admin`. `--password` belongs to `user`, so it comes before the
131
+ identity; everything after it is the subcommand.
132
+
133
+ The password is read from `--password`, then `RMNG_PASSWORD`, then a prompt. Prefer the prompt or
134
+ the environment variable: a password in `--password` is visible to other processes and lands in
135
+ shell history.
136
+
137
+ `esp-morpheus` signs in before running anything, so a wrong password is reported at the prompt rather
138
+ than by whichever command you run first. A typed one can be retyped, up to three tries; one from
139
+ `--password` or `RMNG_PASSWORD` fails straight away with exit code 3, since a script cannot answer
140
+ a prompt. `auth` is the exception — it provisions an account that may not exist yet, so it runs
141
+ even when sign-in fails, and the interactive prompt opens on a warning for the same reason.
142
+
143
+ ### Or seed test users and devices
144
+
145
+ For quick validation against a scratch deployment, `admin test-data setup` creates a known set of
146
+ users and nodes from `test_config.json`. It registers every user and node, creates a default `Home`
147
+ group per user, and associates nodes flagged with `associate_to`.
148
+
149
+ ```bash
150
+ esp-morpheus admin test-data setup
151
+ ```
152
+
153
+ On a fresh install this also writes `test_config.json` from the packaged defaults, generating
154
+ passwords and device certificates. It holds secrets: never commit or share it. The seeded admin is
155
+ marked `"admin": true`, which is how `esp-morpheus admin` finds it without naming one. `node_multi`
156
+ and `node_switch` are associated with `test-user1@example.com`.
157
+
158
+ It needs AWS credentials for the deployment's account (Cognito for the admin, IoT for node
159
+ certificates), from any source boto3 reads. The region comes from the outputs.
160
+
161
+ ```bash
162
+ export AWS_PROFILE=<profile> # or AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY
163
+ ```
164
+
165
+ "AWS account mismatch" means the credentials are for another account than the outputs name. A
166
+ re-run reuses existing users, groups and certificates; "Node ... was not registered" means the node
167
+ already exists.
168
+
169
+ The file is `cli/test_config.json` inside a checkout and `~/.config/morpheus/test_config.json`
170
+ elsewhere. Run from the other place, `setup` writes a new one with fresh passwords and certificates;
171
+ `MORPHEUS_CONFIG` pins one path.
172
+
173
+ ```bash
174
+ esp-morpheus user someone@example.com
175
+ esp-morpheus device node_rsa
176
+ ```
177
+
178
+ `admin test-data destroy` removes them again: the seeded devices, their groups, and any leftover
179
+ `test-*` certificates. It deletes only test-created things and leaves the rest of the deployment
180
+ alone; `--dry-run` lists what it would delete.
181
+
182
+ ### Or create the CI bot user
183
+
184
+ `admin bot-user create` creates an IAM user with AdministratorAccess for CI, and writes its access
185
+ keys to `bot-iam-user-credentials.json` next to `test_config.json`. The name defaults to `bot`. Pass
186
+ another one, and `esp-morpheus` saves it as `ci_bot_user` in `test_config.json`, so `delete` and `show`
187
+ find it again.
188
+
189
+ ```bash
190
+ esp-morpheus admin bot-user create # or: esp-morpheus admin bot-user create rmng-ci
191
+ esp-morpheus admin bot-user show
192
+ esp-morpheus admin bot-user delete
193
+ ```
194
+
195
+ One bot at a time. There is a single credentials file, so a second user under another name would
196
+ overwrite the keys of the first and leave it in IAM with a live admin key nothing tracks. `create`
197
+ refuses a new name until `delete` removes the current bot. A name IAM no longer has is stale, and
198
+ does not block a create.
199
+
200
+ A second `create` under the same name fails rather than invalidate the key CI is using. Use
201
+ `create --rotate` to replace the keys of an existing user, which is the way back when the
202
+ credentials file is lost.
203
+
204
+ ## 4. One command, or a prompt
205
+
206
+ Every command runs two ways. Name it on the command line and `esp-morpheus` runs it and exits:
207
+
208
+ ```bash
209
+ esp-morpheus user someone@example.com group list
210
+ ```
211
+
212
+ Name no subcommand and `esp-morpheus` opens a prompt bound to that identity, where the
213
+ `esp-morpheus user someone@example.com` prefix is implicit:
214
+
215
+ ```
216
+ $ esp-morpheus user someone@example.com
217
+ User context: someone@example.com
218
+ Type help for commands, q to leave.
219
+ someone@example.com > group create My Home
220
+ someone@example.com > api get v1/user/nodes
221
+ someone@example.com > q
222
+ ```
223
+
224
+ Tab completes the command tree. `help` lists the commands and `help <command>` prints its full help,
225
+ both generated from the same tree the dispatcher uses, so neither can drift. A bad command, a failed
226
+ call and `Ctrl-C` all return you to the prompt; `q`, `quit` and `Ctrl-D` leave.
227
+
228
+ ## 5. The command tree
229
+
230
+ ```
231
+ esp-morpheus [--client-outputs SRC] [--json] [--raw] [-v]
232
+ user [--password PW] <identity> [SUBCOMMAND...] # no subcommand -> prompt
233
+ auth connect subscribe publish read-shadow upload-file
234
+ api get | post | put | patch | delete
235
+ group create | list | rename | add-capabilities | share
236
+ group subgroup create | rename | add-node | remove-node | share
237
+ node assoc | remove | claim
238
+ matter initiate | verify | confirm | get-noc
239
+ sharing list | accept | reject
240
+ push register-ios | register-android | register
241
+ device <node> [SUBCOMMAND...] # no subcommand -> prompt
242
+ connect shadow-connect subscribe publish to-cloud group-info
243
+ set-node-config direct-notify
244
+ admin [IDENTITY] [--password PW] [SUBCOMMAND...] # no subcommand -> prompt
245
+ integrations alexa | gva | smartthings
246
+ platforms register-ios | register-android | list
247
+ update-ios | update-android | delete
248
+ nodes register | bulk-register | bulk-status
249
+ iot-event-mode get | set
250
+ claiming enable
251
+ ses setup-sender | request-production
252
+ sns request-production
253
+ test-data setup | destroy
254
+ gen-device <name> <rsa|ec> [--stdout] [--force]
255
+ bot-user create [NAME] [--rotate] | delete [NAME] | show
256
+ guide alexa | gva | smartthings | ios | android
257
+ app-sim [--password PW] <identity>
258
+ list select stats update update-group update-subgroup prov
259
+ schedule set | get | delete
260
+ automation create | add-trigger | add-action | complete
261
+ list | get | delete
262
+ device-sim <node>
263
+ update-params update-tags
264
+ ```
265
+
266
+ There are **two layers**. `user` and `device` are the raw operations: one user-side or device-side
267
+ call at a time. `app-sim` and `device-sim` sit on top and run the sequence of raw operations a real
268
+ phone app or a real node performs.
269
+
270
+ `admin` is the third tree, and the only privileged one: everything that needs AWS credentials or the
271
+ admin API is under it, so what the rest of `esp-morpheus` reaches is what an ordinary account reaches.
272
+ `guide` and `test-data gen-device` are the exceptions in the other direction — they need neither,
273
+ and sit there because each one's other half is an admin command: `guide` prints the console side of
274
+ a setup, and the node `gen-device` writes is inert until `test-data setup` registers it.
275
+
276
+ ### `user` — the user API and a user's MQTT session
277
+
278
+ ```
279
+ auth # authenticate and register the user
280
+ group list # groups, with their nodes and subgroup ids
281
+ group create My Home # create a group
282
+ group create --matter My Home # create it as a Matter fabric
283
+ node assoc node_rsa <group_id> # associate a device into a group
284
+ node camera-stream <node_id> --stats-only # view a camera's live video over KVS WebRTC
285
+ api get v1/user/nodes # raw GET against the user API
286
+ connect # assume role, then connect to MQTT
287
+ subscribe node_rsa params local # subscribe to a node's named shadows
288
+ push register-ios com.app.id <token> # register a push endpoint
289
+ sharing list # pending shares
290
+ ```
291
+
292
+ ### `admin` — deployment-wide operations
293
+
294
+ One tree for everything privileged, so what the rest of `esp-morpheus` can reach is what an ordinary
295
+ account can reach.
296
+
297
+ Its commands split in two. `integrations`, `platforms`, `nodes`, `iot-event-mode` and `claiming`
298
+ call the admin API, which returns 403 for a regular user, so they need an admin identity: name one
299
+ before the command, and without it `esp-morpheus` uses the admin `test_config.json` flags. `ses`, `sns`,
300
+ `test-data` and `bot-user` call AWS directly and need no identity at all — only credentials for the
301
+ account the outputs name.
302
+
303
+ ```bash
304
+ esp-morpheus admin platforms list
305
+ esp-morpheus admin admin@example.com platforms list
306
+ esp-morpheus admin # a prompt over the same tree
307
+ ```
308
+
309
+ ```
310
+ platforms register-ios key.p8 <key_id> <team_id> <bundle_id> --sandbox
311
+ platforms register-android service-account.json
312
+ integrations alexa setup-auto
313
+ integrations smartthings setup st-config.json
314
+ nodes bulk-register nodes.csv --tags created_by:ci
315
+ iot-event-mode set sqs
316
+ claiming enable
317
+ ses setup-sender otp@company.com # SES mails a link; the owner opens it
318
+ ses setup-sender --mailosaur # mint a test address and open the link for you
319
+ test-data setup
320
+ bot-user create
321
+ ```
322
+
323
+ ### `device` — a physical node
324
+
325
+ Acts as a node using the certificate and key from `nodes[]`, over MQTT/TLS.
326
+
327
+ ```
328
+ connect # connect and subscribe to from_cloud
329
+ group-info # the node's group and subgroup ids
330
+ publish params {"Light":{"power":true}} # update a named shadow
331
+ to-cloud {"temp":25} # publish to the node-to-cloud topic
332
+ direct-notify --file notification.json
333
+ set-node-config node_config.json
334
+ ```
335
+
336
+ ### `device-sim <thing_name>` — the device simulator
337
+
338
+ A node that reports params and tags. Unlike `app-sim`, this one does need a `test_config.json`
339
+ entry: a node authenticates with a certificate and key, which cannot be typed at a prompt. The
340
+ entry also needs `node_cfg` and `node_tags`; only `node_multi` and `node_switch` qualify in the
341
+ default config.
342
+
343
+ ```
344
+ update-params {"Colour Light":{"Power":true}}
345
+ update-tags {"location":"hall"}
346
+ ```
347
+
348
+ It connects with the node's certificate and needs no AWS credentials. To control it from the phone
349
+ app, sign in as the node's `associate_to` user (`test-user1@example.com` for `node_multi`); the
350
+ password is in `test_config.json`. The simulator has no BLE, so there is no QR to scan: `test-data
351
+ setup` already associated it. To use your own account, share the group and accept in the app:
352
+
353
+ ```bash
354
+ esp-morpheus user test-user1@example.com group list
355
+ esp-morpheus user test-user1@example.com group share <group_id> primary --username <your-email>
356
+ ```
357
+
358
+ App changes print in the device-sim terminal; `update-params` sends changes back.
359
+
360
+ ### `app-sim <identity>` — the app simulator
361
+
362
+ The mobile app for a user: groups, automations, schedules and BLE provisioning. It resolves and
363
+ checks IDENTITY exactly as `esp-morpheus user` does, prompting for a password, so it drives any account
364
+ in the deployment rather than only the ones in `test_config.json`.
365
+
366
+ ```
367
+ list # the user's groups
368
+ select <group_id> # choose the active home
369
+ update <node_id> {"Light":{"power":true}}
370
+ automation create Evening lights
371
+ schedule get <node_id>
372
+ prov # BLE provisioning
373
+ ```
374
+
375
+ ## 6. Output
376
+
377
+ By default a command prints a curated view of its result. Two flags change that:
378
+
379
+ | Flag | Effect |
380
+ | --------- | ------------------------------------------------------------------------ |
381
+ | `--raw` | Print each payload as JSON, to see what the API returned rather than the fields the command chose to show. |
382
+ | `--json` | The same JSON, plus stdout reserved for it — every message goes to stderr. |
383
+ | `-v` | Add the API request trace, printed verbatim. |
384
+
385
+ The request trace is off unless you ask for it, and prints bodies verbatim so a token can be
386
+ decoded and its claims checked. That means it shows real credentials — `POST /v1/user/credentials`
387
+ answers with a live secret key and session token — so redirect it rather than pasting it around.
388
+
389
+ ## 7. Scripting
390
+
391
+ `--json` puts the payload on stdout and every other word on stderr, so a command pipes straight into
392
+ `jq`:
393
+
394
+ ```bash
395
+ esp-morpheus --json user someone@example.com api get v1/user/nodes | jq -e '.nodes'
396
+ ```
397
+
398
+ Exit codes say what happened, so a script can branch without parsing text:
399
+
400
+ | Code | Meaning |
401
+ | ---- | ------------------------------------------------ |
402
+ | 0 | Success |
403
+ | 1 | The command ran and failed |
404
+ | 2 | Usage error: an unknown command or a bad argument |
405
+ | 3 | Authentication or authorisation failed |
406
+
407
+ ## 8. Where state lives
408
+
409
+ Inside a checkout, `esp-morpheus` keeps using the paths that are already there: `cli/test_config.json`,
410
+ `cli/.*.command_history` and `.sim/`. Installed, it uses XDG directories and writes nothing to the
411
+ working directory.
412
+
413
+ | What | In a checkout | Installed |
414
+ | ------------------- | -------------------------- | --------------------------------- |
415
+ | `test_config.json` | `cli/` | `~/.config/morpheus/` |
416
+ | Command history | `cli/.<context>.command_history` | `~/.cache/morpheus/` |
417
+ | Simulator caches | `.sim/<name>/` | `~/.cache/morpheus/sim/<name>/` |
418
+ | Vendored `esp_prov` | `.vendor/` | `~/.cache/morpheus/vendor/` |
419
+
420
+ `MORPHEUS_CONFIG` overrides the config file, `MORPHEUS_CONFIG_DIR` and `MORPHEUS_CACHE_DIR` the
421
+ directories.
422
+
423
+ ## 9. The Python SDK
424
+
425
+ The same distribution ships the SDK the CLI is built on, so a test or a script can drive a
426
+ deployment directly:
427
+
428
+ ```python
429
+ from esp_morpheus.sdk.user import User
430
+ from esp_morpheus.outputs import RmngSettings
431
+ ```
432
+
433
+ From a clone of this repo, `py_sdk.test_user` and the other pre-rename paths keep working and
434
+ name the same modules; they need no install, because `py_sdk/__init__.py` finds `cli/src` itself.