xref: /aosp_15_r20/external/openthread/tests/toranj/ncp/test-100-mcu-power-state.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1#!/usr/bin/env python3
2#
3#  Copyright (c) 2018, The OpenThread Authors.
4#  All rights reserved.
5#
6#  Redistribution and use in source and binary forms, with or without
7#  modification, are permitted provided that the following conditions are met:
8#  1. Redistributions of source code must retain the above copyright
9#     notice, this list of conditions and the following disclaimer.
10#  2. Redistributions in binary form must reproduce the above copyright
11#     notice, this list of conditions and the following disclaimer in the
12#     documentation and/or other materials provided with the distribution.
13#  3. Neither the name of the copyright holder nor the
14#     names of its contributors may be used to endorse or promote products
15#     derived from this software without specific prior written permission.
16#
17#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27#  POSSIBILITY OF SUCH DAMAGE.
28
29import time
30import wpan
31from wpan import verify
32
33# -----------------------------------------------------------------------------------------------------------------------
34# Test description: Testing controlling of NCP's MCU power state
35
36test_name = __file__[:-3] if __file__.endswith('.py') else __file__
37print('-' * 120)
38print('Starting \'{}\''.format(test_name))
39
40# -----------------------------------------------------------------------------------------------------------------------
41# Creating `wpan.Nodes` instances
42
43node = wpan.Node()
44
45# -----------------------------------------------------------------------------------------------------------------------
46# Init all nodes
47
48wpan.Node.init_all_nodes()
49
50# -----------------------------------------------------------------------------------------------------------------------
51# Test implementation
52
53# Verify that state is ON after a reset
54verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
55
56# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57# Check power state wpantund property get and set
58
59WAIT_TIME = 5
60
61
62def check_wpan_is_in_offline_state():
63    verify(node.get(wpan.WPAN_STATE) == wpan.STATE_OFFLINE)
64
65
66def check_wpan_is_in_deep_sleep_state():
67    verify(node.get(wpan.WPAN_STATE) == wpan.STATE_DEEP_SLEEP)
68
69
70def check_wpan_is_in_commissioned_state():
71    verify(node.get(wpan.WPAN_STATE) == wpan.STATE_COMMISSIONED)
72
73
74def check_wpan_is_in_associated_state():
75    verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
76
77
78def check_wpan_is_in_associating_state():
79    verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATING)
80
81
82node.form("mcu-power-state")
83verify(node.is_associated())
84
85node.set(wpan.WPAN_NCP_MCU_POWER_STATE, 'low-power')
86verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
87verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
88
89node.set(wpan.WPAN_NCP_MCU_POWER_STATE, 'on')
90verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
91
92node.set(wpan.WPAN_NCP_MCU_POWER_STATE, 'lp')  # special short-form string for low-power
93verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
94
95node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_ON)
96verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
97
98node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_LOW_POWER)
99verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
100verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
101
102# Verify that `wpantund` will restore the user-set value after NCP reset
103
104node.reset()
105time.sleep(1)
106verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
107node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_ON)
108
109# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
110# Check the `wpantund` state changes between "deep-sleep" and "offline"
111
112node.leave()
113verify(not node.is_associated())
114
115verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
116verify(node.get(wpan.WPAN_STATE) == wpan.STATE_OFFLINE)
117
118# Setting the power state to `low-power` should change wpantund state to
119# `DEEP_SLEEP`
120
121node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_LOW_POWER)
122wpan.verify_within(check_wpan_is_in_deep_sleep_state, WAIT_TIME)
123
124# Verify that reading/getting a property does not impact the wpantund state.
125
126node.get(wpan.WPAN_THREAD_RLOC16)
127verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
128verify(node.get(wpan.WPAN_STATE) == wpan.STATE_DEEP_SLEEP)
129
130# Setting the power state to `on` should change wpantund state to `OFFLINE`
131
132node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_ON)
133wpan.verify_within(check_wpan_is_in_offline_state, WAIT_TIME)
134
135# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
136# Verify the behavior of `begin-low-power` wpanctl command
137
138node.wpanctl('begin-low-power')
139wpan.verify_within(check_wpan_is_in_deep_sleep_state, WAIT_TIME)
140verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
141
142node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_ON)
143wpan.verify_within(check_wpan_is_in_offline_state, WAIT_TIME)
144
145# Check the `wpantund` state changes between "offline:commissioned" and
146# "deep-sleep"
147
148node.form("test-network")
149node.set('Daemon:AutoAssociateAfterReset', '0')
150
151# Verify that issuing a `begin-low-power` when in "associated" state
152# does not change the state.
153node.wpanctl('begin-low-power')
154verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
155verify(node.get(wpan.WPAN_STATE) == wpan.STATE_ASSOCIATED)
156
157# After reset, power state should remain `LOW_POWER` (wpantund would restore the value
158# on NCP) and since "AutoAssociateAfterReset" is disabled, wpantund state should
159# be `DEEP_SLEEP`.
160
161node.reset()
162wpan.verify_within(check_wpan_is_in_deep_sleep_state, WAIT_TIME)
163
164node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_ON)
165wpan.verify_within(check_wpan_is_in_commissioned_state, WAIT_TIME)
166
167node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_LOW_POWER)
168wpan.verify_within(check_wpan_is_in_deep_sleep_state, WAIT_TIME)
169
170node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_ON)
171node.leave()
172
173# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174# Verify sleep behavior after disabling `wpantund` ("Daemon:Enabled"
175# property) when state is "offline"
176
177verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
178verify(node.get(wpan.WPAN_STATE) == wpan.STATE_OFFLINE)
179verify(node.get('Daemon:Enabled') == 'true')
180
181# Disabling `wpantund` should put the NCP to deep sleep
182node.set('Daemon:Enabled', 'false')
183verify(node.get('Daemon:Enabled') == 'false')
184wpan.verify_within(check_wpan_is_in_deep_sleep_state, WAIT_TIME)
185verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
186
187# Enabling `wpantund` should update the `MCU_POWER_STATE` back to `ON`.
188node.set('Daemon:Enabled', 'true')
189wpan.verify_within(check_wpan_is_in_offline_state, WAIT_TIME)
190verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
191
192# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
193# Verify sleep behavior after disabling `wpantund` ("Daemon:Enabled"
194# property) when state is "associated"
195
196node.form("disable-test")
197verify(node.is_associated())
198verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
199
200node.set('Daemon:Enabled', 'false')
201verify(node.get('Daemon:Enabled') == 'false')
202wpan.verify_within(check_wpan_is_in_deep_sleep_state, WAIT_TIME)
203verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
204
205node.set('Daemon:Enabled', 'true')
206wpan.verify_within(check_wpan_is_in_commissioned_state, WAIT_TIME)
207verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_ON)
208
209node.leave()
210
211# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
212# Verify `AutoAssociateAfterReset` behavior after reset from "deep-sleep"
213# (but commissioned).
214
215node.set('Daemon:AutoAssociateAfterReset', '1')
216
217node.set(wpan.WPAN_NCP_MCU_POWER_STATE, wpan.MCU_POWER_STATE_LOW_POWER)
218verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
219
220node.form("resume-test")
221verify(node.is_associated())
222verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
223
224node.reset()
225
226# After reset, power state should remain `LOW_POWER` (wpantund would restore the value
227# on NCP) and  wpantund state should start as "deep-sleep" but since AutoAssociateAfterReset
228# is enabled, network should be recovered.
229
230wpan.verify_within(check_wpan_is_in_associating_state, WAIT_TIME)
231verify(node.get(wpan.WPAN_NCP_MCU_POWER_STATE) == wpan.MCU_POWER_STATE_LOW_POWER)
232
233# -----------------------------------------------------------------------------------------------------------------------
234# Test finished
235
236wpan.Node.finalize_all_nodes()
237
238print('\'{}\' passed.'.format(test_name))
239