esp-rainmaker-cli 1.11.1__tar.gz → 1.12.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 (123) hide show
  1. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/PKG-INFO +13 -1
  2. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/esp_rainmaker_cli.egg-info/PKG-INFO +13 -1
  3. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/esp_rainmaker_cli.egg-info/SOURCES.txt +3 -0
  4. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rainmaker/rainmaker.py +58 -7
  5. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rainmaker/version.py +1 -1
  6. esp_rainmaker_cli-1.12.0/rmaker_cmd/cache.py +160 -0
  7. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/node.py +355 -67
  8. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/user.py +5 -1
  9. esp_rainmaker_cli-1.12.0/rmaker_lib/node_cache.py +327 -0
  10. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/profile_manager.py +40 -3
  11. esp_rainmaker_cli-1.12.0/rmaker_lib/session_store.py +138 -0
  12. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/security/security1.py +76 -8
  13. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/transport/transport_http.py +38 -4
  14. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/esp_rainmaker_ctrl.py +50 -10
  15. esp_rainmaker_cli-1.12.0/rmaker_tools/rmaker_local_ctrl/integration.py +430 -0
  16. esp_rainmaker_cli-1.11.1/rmaker_tools/rmaker_local_ctrl/integration.py +0 -86
  17. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/LICENSE +0 -0
  18. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/README.md +0 -0
  19. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/esp_rainmaker_cli.egg-info/dependency_links.txt +0 -0
  20. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/esp_rainmaker_cli.egg-info/entry_points.txt +0 -0
  21. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/esp_rainmaker_cli.egg-info/requires.txt +0 -0
  22. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/esp_rainmaker_cli.egg-info/top_level.txt +0 -0
  23. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rainmaker/__init__.py +0 -0
  24. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/__init__.py +0 -0
  25. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/browserlogin.py +0 -0
  26. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/cmd_response.py +0 -0
  27. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/group.py +0 -0
  28. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/html/welcome.html +0 -0
  29. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/provision.py +0 -0
  30. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_cmd/test.py +0 -0
  31. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/__init__.py +0 -0
  32. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/cmd_response.py +0 -0
  33. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/configmanager.py +0 -0
  34. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/constants.py +0 -0
  35. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/device.py +0 -0
  36. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/envval.py +0 -0
  37. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/exceptions.py +0 -0
  38. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/local_control.py +0 -0
  39. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/logger.py +0 -0
  40. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/node.py +0 -0
  41. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/profile_utils.py +0 -0
  42. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/schedule_utils.py +0 -0
  43. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/serverconfig.py +0 -0
  44. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/service.py +0 -0
  45. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/session.py +0 -0
  46. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/simple_local_control.py +0 -0
  47. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_lib/user.py +0 -0
  48. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/__init__.py +0 -0
  49. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/__init__.py +0 -0
  50. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/discovery/__init__.py +0 -0
  51. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/discovery/mdns_discovery.py +0 -0
  52. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/prov/__init__.py +0 -0
  53. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/prov/wifi_ctrl.py +0 -0
  54. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/prov/wifi_prov.py +0 -0
  55. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/prov/wifi_scan.py +0 -0
  56. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/security/__init__.py +0 -0
  57. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/security/security.py +0 -0
  58. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/security/security0.py +0 -0
  59. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/security/security2.py +0 -0
  60. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/security/srp6a.py +0 -0
  61. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/transport/__init__.py +0 -0
  62. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/transport/ble_cli.py +0 -0
  63. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/transport/transport.py +0 -0
  64. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/transport/transport_ble.py +0 -0
  65. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/transport/transport_console.py +0 -0
  66. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/utils/__init__.py +0 -0
  67. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/common/utils/convenience.py +0 -0
  68. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_claim/__init__.py +0 -0
  69. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_claim/claim.py +0 -0
  70. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_claim/claim_config.py +0 -0
  71. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/__init__.py +0 -0
  72. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/constants_pb2.py +0 -0
  73. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/esp_local_ctrl.py +0 -0
  74. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/esp_local_ctrl_pb2.py +0 -0
  75. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/esp_prov.py +0 -0
  76. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/esp_rmaker_prov_local_ctrl_pb2.py +0 -0
  77. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/proto/__init__.py +0 -0
  78. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/proto/proto_lc.py +0 -0
  79. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/prov/__init__.py +0 -0
  80. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/prov/custom_prov.py +0 -0
  81. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/prov/wifi_ctrl.py +0 -0
  82. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/raw_config.py +0 -0
  83. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/raw_params.py +0 -0
  84. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/sec0_pb2.py +0 -0
  85. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/sec1_pb2.py +0 -0
  86. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/sec2_pb2.py +0 -0
  87. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/security/__init__.py +0 -0
  88. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/session_pb2.py +0 -0
  89. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/transport/__init__.py +0 -0
  90. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_local_ctrl/utils/__init__.py +0 -0
  91. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/__init__.py +0 -0
  92. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/challenge_response.py +0 -0
  93. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/config/__init__.py +0 -0
  94. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/config/custom_cloud_config_pb2.py +0 -0
  95. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/config/esp_rmaker_chal_resp_pb2.py +0 -0
  96. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/config/esp_rmaker_claim_pb2.py +0 -0
  97. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/config/esp_rmaker_user_mapping_pb2.py +0 -0
  98. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/esp_rainmaker_prov.py +0 -0
  99. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/on_network_chal_resp.py +0 -0
  100. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/proto/__init__.py +0 -0
  101. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/__init__.py +0 -0
  102. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/python/__init__.py +0 -0
  103. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/python/constants_pb2.py +0 -0
  104. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/python/sec0_pb2.py +0 -0
  105. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/python/sec1_pb2.py +0 -0
  106. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/python/sec2_pb2.py +0 -0
  107. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/protocomm/python/session_pb2.py +0 -0
  108. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/prov/__init__.py +0 -0
  109. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/prov/prov_util.py +0 -0
  110. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/prov/user_mapping.py +0 -0
  111. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/security/__init__.py +0 -0
  112. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/transport/__init__.py +0 -0
  113. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/utils/__init__.py +0 -0
  114. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/wifi_provisioning/__init__.py +0 -0
  115. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/wifi_provisioning/python/__init__.py +0 -0
  116. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/wifi_provisioning/python/wifi_config_pb2.py +0 -0
  117. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/wifi_provisioning/python/wifi_constants_pb2.py +0 -0
  118. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/wifi_provisioning/python/wifi_ctrl_pb2.py +0 -0
  119. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/rmaker_tools/rmaker_prov/wifi_provisioning/python/wifi_scan_pb2.py +0 -0
  120. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/server_cert/__init__.py +0 -0
  121. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/server_cert/server_cert.pem +0 -0
  122. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/setup.cfg +0 -0
  123. {esp_rainmaker_cli-1.11.1 → esp_rainmaker_cli-1.12.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esp-rainmaker-cli
3
- Version: 1.11.1
3
+ Version: 1.12.0
4
4
  Summary: A python utility to perform host based claiming
5
5
  Home-page: https://github.com/espressif/esp-rainmaker-cli
6
6
  Author: Espressif Systems
@@ -115,6 +115,18 @@ Changelog
115
115
 
116
116
  All major changes to ESP RainMaker CLI will be documented in this file.
117
117
 
118
+ ## [1.12.0] - 19-Feb-2026
119
+ ### Added
120
+ - Local node cache layer for faster `--local` control operations:
121
+ - Caches node details, config, POP, and local control capability per profile/user
122
+ - Disk-based session reuse to skip X25519 handshake on repeated commands
123
+ - Auto-POP resolution from cache, eliminating need for prior cloud `getparams` call
124
+ - Empirical capability discovery (probes sec0 first, then sec1, caches result)
125
+ - Cache disabled by default; enable via `cache enable` or `profile add --cache`
126
+ - New `cache` CLI command group: `enable`, `disable`, `show`, `clear`
127
+ - `--no-cache` flag on `getparams`, `setparams`, `getnodeconfig` for one-shot cache bypass
128
+ - `RM_NODE_CACHE` and `RM_NODE_CACHE_DIR` environment variables for automation control
129
+
118
130
  ## [1.11.1] - 10-Feb-2026
119
131
  - Add support for ecdsa in claiming and make it as default, with an option to fall back to the earlier rsa scheme.
120
132
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: esp-rainmaker-cli
3
- Version: 1.11.1
3
+ Version: 1.12.0
4
4
  Summary: A python utility to perform host based claiming
5
5
  Home-page: https://github.com/espressif/esp-rainmaker-cli
6
6
  Author: Espressif Systems
@@ -115,6 +115,18 @@ Changelog
115
115
 
116
116
  All major changes to ESP RainMaker CLI will be documented in this file.
117
117
 
118
+ ## [1.12.0] - 19-Feb-2026
119
+ ### Added
120
+ - Local node cache layer for faster `--local` control operations:
121
+ - Caches node details, config, POP, and local control capability per profile/user
122
+ - Disk-based session reuse to skip X25519 handshake on repeated commands
123
+ - Auto-POP resolution from cache, eliminating need for prior cloud `getparams` call
124
+ - Empirical capability discovery (probes sec0 first, then sec1, caches result)
125
+ - Cache disabled by default; enable via `cache enable` or `profile add --cache`
126
+ - New `cache` CLI command group: `enable`, `disable`, `show`, `clear`
127
+ - `--no-cache` flag on `getparams`, `setparams`, `getnodeconfig` for one-shot cache bypass
128
+ - `RM_NODE_CACHE` and `RM_NODE_CACHE_DIR` environment variables for automation control
129
+
118
130
  ## [1.11.1] - 10-Feb-2026
119
131
  - Add support for ecdsa in claiming and make it as default, with an option to fall back to the earlier rsa scheme.
120
132
 
@@ -12,6 +12,7 @@ rainmaker/rainmaker.py
12
12
  rainmaker/version.py
13
13
  rmaker_cmd/__init__.py
14
14
  rmaker_cmd/browserlogin.py
15
+ rmaker_cmd/cache.py
15
16
  rmaker_cmd/cmd_response.py
16
17
  rmaker_cmd/group.py
17
18
  rmaker_cmd/node.py
@@ -29,12 +30,14 @@ rmaker_lib/exceptions.py
29
30
  rmaker_lib/local_control.py
30
31
  rmaker_lib/logger.py
31
32
  rmaker_lib/node.py
33
+ rmaker_lib/node_cache.py
32
34
  rmaker_lib/profile_manager.py
33
35
  rmaker_lib/profile_utils.py
34
36
  rmaker_lib/schedule_utils.py
35
37
  rmaker_lib/serverconfig.py
36
38
  rmaker_lib/service.py
37
39
  rmaker_lib/session.py
40
+ rmaker_lib/session_store.py
38
41
  rmaker_lib/simple_local_control.py
39
42
  rmaker_lib/user.py
40
43
  rmaker_tools/__init__.py
@@ -16,6 +16,7 @@ from rmaker_cmd.provision import provision
16
16
  from rmaker_cmd.test import test
17
17
  from rmaker_lib.logger import log
18
18
  from rmaker_cmd.group import group_add, group_remove, group_edit, group_list, group_show, group_add_nodes, group_remove_nodes, group_list_nodes
19
+ from rmaker_cmd.cache import cache_manage
19
20
 
20
21
  # Import the version
21
22
  from rainmaker.version import VERSION
@@ -102,6 +103,9 @@ def main():
102
103
  type=str,
103
104
  metavar='<description>',
104
105
  help='Description for the custom profile (optional)')
106
+ profile_add_parser.add_argument('--cache',
107
+ action='store_true',
108
+ help='Enable node cache for this profile')
105
109
  profile_add_parser.set_defaults(func=profile_add)
106
110
 
107
111
  # profile remove
@@ -112,6 +116,33 @@ def main():
112
116
  help='Name of the profile to remove')
113
117
  profile_remove_parser.set_defaults(func=profile_remove)
114
118
 
119
+ # Cache management commands
120
+ cache_parser = subparsers.add_parser("cache",
121
+ help="Manage local node cache")
122
+ cache_subparsers = cache_parser.add_subparsers(dest='cache_command', help='Cache operations')
123
+
124
+ cache_enable_parser = cache_subparsers.add_parser('enable', help='Enable node cache for current profile')
125
+ cache_enable_parser.set_defaults(func=cache_manage)
126
+
127
+ cache_disable_parser = cache_subparsers.add_parser('disable', help='Disable node cache for current profile')
128
+ cache_disable_parser.set_defaults(func=cache_manage)
129
+
130
+ cache_show_parser = cache_subparsers.add_parser('show', help='Show cached data')
131
+ cache_show_parser.add_argument('--node',
132
+ type=str,
133
+ metavar='<nodeid>',
134
+ help='Node ID to show cache for (omit for all)')
135
+ add_profile_argument(cache_show_parser)
136
+ cache_show_parser.set_defaults(func=cache_manage)
137
+
138
+ cache_clear_parser = cache_subparsers.add_parser('clear', help='Clear cached data')
139
+ cache_clear_parser.add_argument('--node',
140
+ type=str,
141
+ metavar='<nodeid>',
142
+ help='Node ID to clear cache for (omit for all)')
143
+ add_profile_argument(cache_clear_parser)
144
+ cache_clear_parser.set_defaults(func=cache_manage)
145
+
115
146
  signup_parser = subparsers.add_parser("signup",
116
147
  help="Sign up for ESP RainMaker")
117
148
  signup_parser.add_argument('user_name',
@@ -245,8 +276,8 @@ def main():
245
276
  getnodeconfig_parser.add_argument('--sec_ver',
246
277
  type=int,
247
278
  choices=[0, 1, 2],
248
- default=1,
249
- help='Security version for local control')
279
+ default=None,
280
+ help='Security version for local control (default: 1)')
250
281
  getnodeconfig_parser.add_argument('--local-raw',
251
282
  action='store_true',
252
283
  help='Use local control via raw endpoints (get_config with fragmentation) instead of esp_local_ctrl')
@@ -259,6 +290,13 @@ def main():
259
290
  getnodeconfig_parser.add_argument('--proxy-report',
260
291
  action='store_true',
261
292
  help='Automatically use current timestamp and POST signed response to proxy API endpoint')
293
+ getnodeconfig_parser.add_argument('--auto',
294
+ action='store_true',
295
+ help='Try local control first, fall back to cloud if local fails')
296
+ getnodeconfig_parser.add_argument('--no-cache',
297
+ action='store_true',
298
+ dest='no_cache',
299
+ help='Skip local cache for this invocation')
262
300
  add_profile_argument(getnodeconfig_parser)
263
301
  getnodeconfig_parser.set_defaults(func=get_node_config)
264
302
 
@@ -308,8 +346,8 @@ def main():
308
346
  setparams_parser.add_argument('--sec_ver',
309
347
  type=int,
310
348
  choices=[0, 1, 2],
311
- default=1,
312
- help='Security version for local control')
349
+ default=None,
350
+ help='Security version for local control (default: 1)')
313
351
  setparams_parser.add_argument('--local-raw',
314
352
  action='store_true',
315
353
  help='Use local control via raw endpoints (get_params/set_params) instead of esp_local_ctrl')
@@ -317,7 +355,13 @@ def main():
317
355
  type=str,
318
356
  help='Device name for BLE transport (e.g., PROV_aaf824). Required when using --transport ble')
319
357
 
320
- # Note: setparams_data_group is mutually exclusive group, so we add profile to the parent
358
+ setparams_parser.add_argument('--auto',
359
+ action='store_true',
360
+ help='Try local control first, fall back to cloud if local fails')
361
+ setparams_parser.add_argument('--no-cache',
362
+ action='store_true',
363
+ dest='no_cache',
364
+ help='Skip local cache for this invocation')
321
365
  add_profile_argument(setparams_parser)
322
366
  setparams_parser.set_defaults(func=set_params)
323
367
 
@@ -345,8 +389,8 @@ def main():
345
389
  getparams_parser.add_argument('--sec_ver',
346
390
  type=int,
347
391
  choices=[0, 1, 2],
348
- default=1,
349
- help='Security version for local control')
392
+ default=None,
393
+ help='Security version for local control (default: 1)')
350
394
  getparams_parser.add_argument('--local-raw',
351
395
  action='store_true',
352
396
  help='Use local control via raw endpoints (get_params/set_params) instead of esp_local_ctrl')
@@ -362,6 +406,13 @@ def main():
362
406
  getparams_parser.add_argument('--init',
363
407
  action='store_true',
364
408
  help='Use initparams API endpoint instead of params (only with --proxy-report)')
409
+ getparams_parser.add_argument('--auto',
410
+ action='store_true',
411
+ help='Try local control first, fall back to cloud if local fails')
412
+ getparams_parser.add_argument('--no-cache',
413
+ action='store_true',
414
+ dest='no_cache',
415
+ help='Skip local cache for this invocation')
365
416
  add_profile_argument(getparams_parser)
366
417
  getparams_parser.set_defaults(func=get_params)
367
418
 
@@ -5,4 +5,4 @@
5
5
  # SPDX-License-Identifier: Apache-2.0
6
6
 
7
7
  # This file contains the version information for the ESP RainMaker CLI
8
- VERSION = "1.11.1"
8
+ VERSION = "1.12.0"
@@ -0,0 +1,160 @@
1
+ # SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import json
6
+ import os
7
+ import time
8
+ import datetime
9
+ from rmaker_lib.logger import log
10
+
11
+
12
+ def cache_manage(vars=None):
13
+ """
14
+ Manage local node cache: enable, disable, show, clear.
15
+ """
16
+ if vars is None:
17
+ print("No cache command specified. Use: cache {enable|disable|show|clear}")
18
+ return
19
+
20
+ command = vars.get('cache_command')
21
+ if not command:
22
+ print("No cache command specified. Use: cache {enable|disable|show|clear}")
23
+ return
24
+
25
+ if command == 'enable':
26
+ _cache_enable_disable(True)
27
+ elif command == 'disable':
28
+ _cache_enable_disable(False)
29
+ elif command == 'show':
30
+ _cache_show(vars)
31
+ elif command == 'clear':
32
+ _cache_clear(vars)
33
+
34
+
35
+ def _cache_enable_disable(enable):
36
+ """Enable or disable cache for the current profile."""
37
+ try:
38
+ from rmaker_lib.configmanager import Config
39
+ config = Config()
40
+ profile_name = config.get_current_profile_name()
41
+ config.profile_manager.set_cache_enabled(profile_name, enable)
42
+ state = 'enabled' if enable else 'disabled'
43
+ print(f"Node cache {state} for profile '{profile_name}'.")
44
+ except Exception as e:
45
+ print(f"Failed to update cache setting: {e}")
46
+
47
+
48
+ def _cache_show(vars):
49
+ """Show cached data for current user/profile."""
50
+ try:
51
+ from rmaker_lib.configmanager import Config
52
+ from rmaker_lib.node_cache import NodeCache, is_cache_enabled, _get_cache_base_dir
53
+
54
+ config = Config(profile_override=vars.get('profile'))
55
+ profile_name = config.get_current_profile_name()
56
+ profile_config = config.get_profile_config_for_current()
57
+
58
+ if not is_cache_enabled(profile_config):
59
+ print(f"Node cache is disabled for profile '{profile_name}'.")
60
+ print("Use 'esp-rainmaker-cli cache enable' to enable it.")
61
+ return
62
+
63
+ try:
64
+ user_id = config.get_user_id()
65
+ except Exception:
66
+ user_id = 'unknown'
67
+
68
+ nc = NodeCache(profile_name, user_id, enabled=True)
69
+ node_filter = vars.get('node')
70
+
71
+ if node_filter:
72
+ nodes = [node_filter]
73
+ else:
74
+ nodes = nc.list_cached_nodes()
75
+
76
+ if not nodes:
77
+ print("No cached data found.")
78
+ return
79
+
80
+ print(f"Cache location: {nc.cache_dir}")
81
+ print(f"Profile: {profile_name}, User: {user_id}")
82
+ print()
83
+
84
+ for nodeid in nodes:
85
+ summary = nc.get_cache_summary(nodeid)
86
+ if summary is None:
87
+ print(f" {nodeid}: No cached data")
88
+ continue
89
+
90
+ print(f" Node: {nodeid}")
91
+ for filename, info in summary.get('files', {}).items():
92
+ ts = info.get('timestamp')
93
+ stale = info.get('stale', True)
94
+ ts_str = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S') if ts else 'unknown'
95
+ status = 'stale' if stale else 'fresh'
96
+ print(f" {filename}: {ts_str} ({status})")
97
+
98
+ lc_info = nc.get_local_control_info(nodeid)
99
+ if lc_info:
100
+ print(f" Local Control: POP={'yes' if lc_info.get('pop') else 'no'}, "
101
+ f"sec_ver={lc_info.get('sec_ver', '?')}")
102
+
103
+ cap = nc.get_local_control_capability(nodeid)
104
+ if cap:
105
+ if cap.get('supported'):
106
+ print(f" Capability: supported, sec_ver={cap.get('sec_ver', '?')}, "
107
+ f"pop_required={cap.get('pop_required', '?')}")
108
+ else:
109
+ print(f" Capability: not supported")
110
+
111
+ from rmaker_lib.session_store import SessionStore
112
+ ss = SessionStore(nc.cache_dir, enabled=True)
113
+ if ss.is_session_valid(nodeid):
114
+ sess = ss.load_session(nodeid)
115
+ if sess:
116
+ last_used = sess.get('last_used_at', 0)
117
+ age = time.time() - last_used
118
+ print(f" Session: active ({age:.0f}s ago)")
119
+ print()
120
+
121
+ except Exception as e:
122
+ print(f"Failed to show cache: {e}")
123
+ log.debug(f"Cache show error: {e}")
124
+
125
+
126
+ def _cache_clear(vars):
127
+ """Clear cached data."""
128
+ try:
129
+ from rmaker_lib.configmanager import Config
130
+ from rmaker_lib.node_cache import NodeCache, is_cache_enabled
131
+ from rmaker_lib.session_store import SessionStore
132
+
133
+ config = Config(profile_override=vars.get('profile'))
134
+ profile_name = config.get_current_profile_name()
135
+ profile_config = config.get_profile_config_for_current()
136
+
137
+ if not is_cache_enabled(profile_config):
138
+ print(f"Node cache is disabled for profile '{profile_name}'.")
139
+ return
140
+
141
+ try:
142
+ user_id = config.get_user_id()
143
+ except Exception:
144
+ user_id = 'unknown'
145
+
146
+ nc = NodeCache(profile_name, user_id, enabled=True)
147
+ ss = SessionStore(nc.cache_dir, enabled=True)
148
+ node_filter = vars.get('node')
149
+
150
+ nc.invalidate(nodeid=node_filter)
151
+ ss.invalidate_session(nodeid=node_filter)
152
+
153
+ if node_filter:
154
+ print(f"Cleared cache for node '{node_filter}'.")
155
+ else:
156
+ print("Cleared all cached data.")
157
+
158
+ except Exception as e:
159
+ print(f"Failed to clear cache: {e}")
160
+ log.debug(f"Cache clear error: {e}")