Skip to content

Commit

Permalink
Update python test script
Browse files Browse the repository at this point in the history
  • Loading branch information
erjiaqing committed Dec 14, 2021
1 parent 1e286fd commit 0471a92
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 67 deletions.
28 changes: 1 addition & 27 deletions src/app/clusters/network-commissioning/network-commissioning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <app/util/attribute-storage.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ThreadOperationalDataset.h>
#include <platform/PlatformManager.h>
#include <platform/internal/DeviceControlServer.h>
#include <platform/internal/DeviceNetworkInfo.h>

Expand All @@ -48,7 +47,6 @@ CHIP_ERROR InstanceBase::Register()
{
ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->RegisterCommandHandler(this));
VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(DeviceLayer::PlatformMgrImpl().AddEventHandler(_OnCommissioningComplete, reinterpret_cast<intptr_t>(this)));
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -127,7 +125,7 @@ CHIP_ERROR InstanceBase::Read(const ConcreteReadAttributePath & aPath, Attribute
case Attributes::LastNetworkingStatus::Id:
return aEncoder.Encode(NetworkCommissioningStatus::kSuccess);
case Attributes::LastNetworkID::Id:
return aEncoder.Encode(ByteSpan());
return aEncoder.Encode(CharSpan());
case Attributes::LastConnectErrorValue::Id:
return aEncoder.Encode(Attributes::LastConnectErrorValue::TypeInfo::Type(0));

Expand Down Expand Up @@ -539,30 +537,6 @@ void InstanceBase::OnScanFinished(CHIP_ERROR err, CharSpan debugText, const Span
commandHandle->AddResponseData(mPath, response);
}

static InstanceBase::_OnCommissioningComplete(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg)
{
InstanceBase * this_ = reinterpret_cast<InstanceBase *>(arg);
VerifyOrReturn(event->Type == DeviceEventType::kCommissioningComplete);
this_->OnCommissioningComplete(event->CommissioningComplete.status);
}

void InstanceBase::OnCommissioningComplete(CHIP_ERROR err)
{
if (err == CHIP_NO_ERROR)
{
ChipLogDetail(Zcl, "Commissioning complete, persist network credentails to platform driver.");
// TODO: Implement this
if (network->mNetworkType == NetworkType::kWiFi)
{
mpWiFiDelegate->StoreNetworks(Span<WiFiNetworkCommissioningDelegate::WiFiNetworkInfo>());
}
else if (network->mNetworkType == NetworkType::kThread)
{
mpThreadDelegate->StoreNetworks(Span<Thread::OperationalDataset>());
}
}
}

} // namespace NetworkCommissioning
} // namespace Clusters
} // namespace app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,19 @@ class InstanceBase : public CommandHandlerInterface,
} mData;
};

/**
* Register will register the network commissioning instance to the attribute and command dispatching route.
*/
CHIP_ERROR Register();

// CommandHandlerInterface
void InvokeCommand(HandlerContext & ctx) override;

// AttributeAccessInterface
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
CHIP_ERROR Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder) override;

// Actual handlers of the commands
void HandleScanNetworks(HandlerContext & ctx, const Commands::ScanNetworks::DecodableType & req);
void HandleAddOrUpdateWiFiNetwork(HandlerContext & ctx, const Commands::AddOrUpdateWiFiNetwork::DecodableType & req);
void HandleAddOrUpdateThreadNetwork(HandlerContext & ctx, const Commands::AddOrUpdateThreadNetwork::DecodableType & req);
Expand Down Expand Up @@ -98,6 +105,8 @@ class InstanceBase : public CommandHandlerInterface,
private:
void OnConnectResult(app::Clusters::NetworkCommissioning::NetworkCommissioningStatus commissioningError, CharSpan errorText,
int32_t networkRelatedAssociationStatus);

// Some handlers for attribute reads.
CHIP_ERROR HandleReadNetworks(AttributeValueEncoder & aEncoder);
CHIP_ERROR HandleReadScanMaxTimeSeconds(AttributeValueEncoder & aEncoder);
CHIP_ERROR HandleReadConnectMaxTimeSeconds(AttributeValueEncoder & aEncoder);
Expand Down
2 changes: 1 addition & 1 deletion src/controller/python/chip/clusters/ClusterObjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def TagDictToLabelDict(self, debugPath: str, tlvData: Dict[int, Any]) -> Dict[st
for tag, value in tlvData.items():
descriptor = self.GetFieldByTag(tag)
if not descriptor:
# We do not have enough infomation for this field.
# We do not have enough information for this field.
ret[tag] = value
continue

Expand Down
29 changes: 0 additions & 29 deletions src/controller/python/test/test_scripts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,35 +150,6 @@ def TestCloseSession(self, nodeid: int):
f"Failed to close sessions with device {nodeid}: {ex}")
return False

def TestNetworkCommissioning(self, nodeid: int, endpoint: int, group: int, dataset: str, network_id: str):
self.logger.info("Commissioning network to device {}".format(nodeid))
try:
(err, resp) = self.devCtrl.ZCLSend("NetworkCommissioning", "AddOrUpdateThreadNetwork", nodeid, endpoint, group, {
"operationalDataset": bytes.fromhex(dataset),
"breadcrumb": 0}, blocking=True)
self.logger.info(f"Received response: {resp}")
if resp.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
self.logger.exception("Failed to add Thread network.")
return False
except Exception as ex:
self.logger.exception(
"Failed to send AddOrUpdateThreadNetwork command")
return False
self.logger.info(
"Send ConnectNetwork command to device {}".format(nodeid))
try:
self.devCtrl.ZCLSend("NetworkCommissioning", "ConnectNetwork", nodeid, endpoint, group, {
"networkID": bytes.fromhex(network_id),
"breadcrumb": 0}, blocking=True)
self.logger.info(f"Received response: {resp}")
if resp.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
self.logger.exception("Failed to enable Thread network.")
return False
except Exception as ex:
self.logger.exception("Failed to send ConnectNetwork command")
return False
return True

def TestOnOffCluster(self, nodeid: int, endpoint: int, group: int):
self.logger.info(
"Sending On/Off commands to device {} endpoint {}".format(nodeid, endpoint))
Expand Down
9 changes: 3 additions & 6 deletions src/controller/python/test/test_scripts/mobile-device-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
import sys
from optparse import OptionParser
from base import TestFail, TestTimeout, BaseTestHelper, FailIfNot, logger
from cluster_objects import ClusterObjectTests
from cluster_objects import NODE_ID, ClusterObjectTests
from network_commissioning import NetworkCommissioningTests
import asyncio

# The thread network dataset tlv for testing, splited into T-L-V.
Expand Down Expand Up @@ -93,11 +94,7 @@ def main():
"Failed to resolve nodeid")

logger.info("Testing network commissioning")
FailIfNot(test.TestNetworkCommissioning(nodeid=1,
endpoint=ENDPOINT_ID,
group=GROUP_ID,
dataset=TEST_THREAD_NETWORK_DATASET_TLV,
network_id=TEST_THREAD_NETWORK_ID),
FailIfNot(asyncio.run(NetworkCommissioningTests(devCtrl=test.devCtrl, nodeid=1).run(testThread=True)),
"Failed to finish network commissioning")

logger.info("Testing on off cluster")
Expand Down
179 changes: 179 additions & 0 deletions src/controller/python/test/test_scripts/network_commissioning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#
# Copyright (c) 2021 Project CHIP Authors
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import chip.clusters as Clusters
import logging
from chip.clusters.Attribute import AttributePath, AttributeReadResult, AttributeStatus, ValueDecodeFailure
import chip.interaction_model
import asyncio

logger = logging.getLogger('NetworkCommissioning')
logger.setLevel(logging.INFO)

NODE_ID = 1
THREAD_ENDPOINT_ID = 0
WIFI_ENDPOINT_ID = 1

TEST_THREAD_NETWORK_DATASET_TLVS = [bytes.fromhex("0e080000000000010000" +
"000300000c" +
"35060004001fffe0" +
"0208fedcba9876543210" +
"0708fd00000000001234" +
"0510ffeeddccbbaa99887766554433221100" +
"030e54657374696e674e6574776f726b" +
"0102d252" +
"041081cb3b2efa781cc778397497ff520fa50c0302a0ff"),
# End of first TLV
]
# Network id, for the thread network, current a const value, will be changed to XPANID of the thread network.
TEST_THREAD_NETWORK_IDS = [
bytes.fromhex("fedcba9876543210"),
]


class NetworkCommissioningTests:
def __init__(self, devCtrl, nodeid):
self._devCtrl = devCtrl
self._nodeid = nodeid

def log_interface_basic_info(self, values):
logger.info(f"The interface supports {values.maxNetworks} networks.")
logger.info(
f"ScanNetworks should take no more than {values.scanMaxTimeSeconds} seconds.")
logger.info(
f"ConnectNetwork should take no more than {values.connectMaxTimeSeconds} seconds.")
logger.info(
f"The feature map of this endpoint is {values.featureMap}.")

async def test_wifi(self):
logger.info(f"Get basic information of the endpoint")
res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[
(WIFI_ENDPOINT_ID,
Clusters.NetworkCommissioning.Attributes.ConnectMaxTimeSeconds),
(WIFI_ENDPOINT_ID,
Clusters.NetworkCommissioning.Attributes.ScanMaxTimeSeconds),
(WIFI_ENDPOINT_ID, Clusters.NetworkCommissioning.Attributes.MaxNetworks),
(WIFI_ENDPOINT_ID, Clusters.NetworkCommissioning.Attributes.FeatureMap)],
returnClusterObject=True)
self.log_interface_basic_info(
res[WIFI_ENDPOINT_ID][Clusters.NetworkCommissioning])
logger.info(f"Finished getting basic information of the endpoint")

# Scan networks
logger.info(f"Scan networks")
req = Clusters.NetworkCommissioning.Commands.ScanNetworks(
ssid=b'', breadcrumb=0)
res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=WIFI_ENDPOINT_ID, payload=req)
logger.info(f"Received response: {res}")
if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
raise AssertionError(f"Unexpected result: {res.networkingStatus}")

# Add first network
logger.info(f"Adding first test network")
req = Clusters.NetworkCommissioning.Commands.AddOrUpdateWiFiNetwork(
ssid=b"TestSSID", credentials=b"TestPass", breadcrumb=0)
res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=WIFI_ENDPOINT_ID, payload=req)
logger.info(f"Received response: {res}")
if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
raise AssertionError(f"Unexpected result: {res.networkingStatus}")

logger.info(f"Check network list")
res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(WIFI_ENDPOINT_ID, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True)
networkList = res[THREAD_ENDPOINT_ID][Clusters.NetworkCommissioning].networks
logger.info(f"Got network list: {networkList}")
if len(networkList) != 2:
raise AssertionError(
f"Unexpected result: expect 1 networks, but {len(networkList)} networks received")
if networkList[0].networkID != b"TestSSID":
raise AssertionError(
f"Unexpected result: first network ID should be 'TestSSID' got {networkList[0].networkID}")

logger.info(f"Connect to a network")
req = Clusters.NetworkCommissioning.Commands.ConnectNetwork(
networkID=b'TestSSID', breadcrumb=0)
res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=WIFI_ENDPOINT_ID, payload=req)
logger.info(f"Got response: {res}")
if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
raise AssertionError(f"Unexpected result: {res.networkingStatus}")
logger.info(f"Device connected to a network.")

async def test_thread(self):
logger.info(f"Get basic information of the endpoint")
res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[
(THREAD_ENDPOINT_ID,
Clusters.NetworkCommissioning.Attributes.ConnectMaxTimeSeconds),
(THREAD_ENDPOINT_ID,
Clusters.NetworkCommissioning.Attributes.ScanMaxTimeSeconds),
(THREAD_ENDPOINT_ID, Clusters.NetworkCommissioning.Attributes.MaxNetworks),
(THREAD_ENDPOINT_ID, Clusters.NetworkCommissioning.Attributes.FeatureMap)],
returnClusterObject=True)
self.log_interface_basic_info(
res[THREAD_ENDPOINT_ID][Clusters.NetworkCommissioning])
logger.info(f"Finished getting basic information of the endpoint")

# Scan networks
logger.info(f"Scan networks")
req = Clusters.NetworkCommissioning.Commands.ScanNetworks(
ssid=b'', breadcrumb=0)
res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=THREAD_ENDPOINT_ID, payload=req)
logger.info(f"Received response: {res}")
if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
raise AssertionError(f"Unexpected result: {res.networkingStatus}")

# Add first network
logger.info(f"Adding first test network")
req = Clusters.NetworkCommissioning.Commands.AddOrUpdateThreadNetwork(
operationalDataset=TEST_THREAD_NETWORK_DATASET_TLVS[0], breadcrumb=0)
res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=THREAD_ENDPOINT_ID, payload=req)
logger.info(f"Received response: {res}")
if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
raise AssertionError(f"Unexpected result: {res.networkingStatus}")

logger.info(f"Check network list")
res = await self._devCtrl.ReadAttribute(nodeid=self._nodeid, attributes=[(THREAD_ENDPOINT_ID, Clusters.NetworkCommissioning.Attributes.Networks)], returnClusterObject=True)
networkList = res[THREAD_ENDPOINT_ID][Clusters.NetworkCommissioning].networks
logger.info(f"Got network list: {networkList}")
if len(networkList) != 1:
raise AssertionError(
f"Unexpected result: expect 1 networks, but {len(networkList.Data.value)} networks received")
if networkList[0].networkID != TEST_THREAD_NETWORK_IDS[0]:
raise AssertionError(
f"Unexpected result: first network ID should be {TEST_THREAD_NETWORK_IDS[0]} got {networkList[0].networkID}")

logger.info(f"Connect to a network")
req = Clusters.NetworkCommissioning.Commands.ConnectNetwork(
networkID=TEST_THREAD_NETWORK_IDS[0], breadcrumb=0)
res = await self._devCtrl.SendCommand(nodeid=self._nodeid, endpoint=THREAD_ENDPOINT_ID, payload=req)
logger.info(f"Got response: {res}")
if res.networkingStatus != Clusters.NetworkCommissioning.Enums.NetworkCommissioningStatus.kSuccess:
raise AssertionError(f"Unexpected result: {res.networkingStatus}")
logger.info(f"Device connected to a network.")

async def run(self, testThread=True, testWiFi=False):
if testThread:
try:
await self.test_thread()
except Exception as ex:
logger.exception(ex)
return False
if testWiFi:
try:
await self.test_wifi()
except Exception as ex:
logger.exception(ex)
return False
return True
18 changes: 14 additions & 4 deletions src/platform/Linux/ConnectivityManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,6 +1123,13 @@ CHIP_ERROR ConnectivityManagerImpl::StartWiFiScan(ByteSpan ssid, WiFiNetworkComm
std::lock_guard<std::mutex> lock(mWpaSupplicantMutex);
VerifyOrReturnError(mWpaSupplicant.iface != nullptr, CHIP_ERROR_INCORRECT_STATE);

if (wpa_fi_w1_wpa_supplicant1_interface_get_scanning(mWpaSupplicant.iface))
{
// If we are already scanning, skip it
mpNetworkCommissioningCallback = callback;
return CHIP_NO_ERROR;
}

CHIP_ERROR ret = CHIP_NO_ERROR;
GError * err = nullptr;
GVariant * args = nullptr;
Expand Down Expand Up @@ -1338,10 +1345,13 @@ void ConnectivityManagerImpl::_OnWpaInterfaceScanDone(GObject * source_object, G
scanResults.push_back(scanResult);
}

mpNetworkCommissioningCallback->OnScanFinished(
CHIP_NO_ERROR, CharSpan(),
Span<app::Clusters::NetworkCommissioning::Structs::WiFiInterfaceScanResult::Type>(scanResults.data(),
scanResults.size()));
if (mpNetworkCommissioningCallback != nullptr)
{
mpNetworkCommissioningCallback->OnScanFinished(
CHIP_NO_ERROR, CharSpan(),
Span<app::Clusters::NetworkCommissioning::Structs::WiFiInterfaceScanResult::Type>(scanResults.data(),
scanResults.size()));
}
});

g_strfreev(oldBsss);
Expand Down

0 comments on commit 0471a92

Please sign in to comment.