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