3 * Copyright (c) 2021 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <controller/CHIPDeviceController.h>
20 #include <platform/CHIPDeviceLayer.h>
21 #include <platform/KeyValueStoreManager.h>
22 #include <support/logging/CHIPLogging.h>
24 #include "ChipThreadWork.h"
28 class ServerStorageDelegate : public chip::PersistentStorageDelegate
31 void SetStorageDelegate(chip::PersistentStorageResultDelegate * delegate) override { mAsyncDelegate = delegate; }
33 void AsyncSetKeyValue(const char * key, const char * value) override
36 CHIP_ERROR err = SyncSetKeyValue(key, value, strlen(value));
38 if (err != CHIP_NO_ERROR)
40 mAsyncDelegate->OnPersistentStorageStatus(key, chip::PersistentStorageResultDelegate::Operation::kSET, err);
45 SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override
47 return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(key, buffer, size);
50 CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override
52 return chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(key, value, size);
55 void AsyncDeleteKeyValue(const char * key) override { chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(key); }
58 chip::PersistentStorageResultDelegate * mAsyncDelegate = nullptr;
61 // FIXME: implement this class
62 class ScriptDevicePairingDelegate final : public chip::Controller::DevicePairingDelegate
65 using OnNetworkCredentialsRequestedCallback = void (*)();
66 using OnOperationalCredentialsRequestedCallback = void (*)(const char * csr, size_t length);
67 using OnPairingCompleteCallback = void (*)(CHIP_ERROR err);
69 ~ScriptDevicePairingDelegate() = default;
71 void OnNetworkCredentialsRequested(chip::RendezvousDeviceCredentialsDelegate * callback) override
73 mCredentialsDelegate = callback;
74 if (mNetworkCredentialsRequested == nullptr)
76 ChipLogError(Controller, "Callback for network credentials is not defined.");
79 mNetworkCredentialsRequested();
82 void OnOperationalCredentialsRequested(const char * csr, size_t csr_length,
83 chip::RendezvousDeviceCredentialsDelegate * callback) override
85 mCredentialsDelegate = callback;
86 if (mOperationalCredentialsRequested == nullptr)
88 ChipLogError(Controller, "Callback for operational credentials is not defined.");
92 mOperationalCredentialsRequested(csr, csr_length);
95 void OnPairingComplete(CHIP_ERROR error) override
97 if (mPairingComplete == nullptr)
99 ChipLogError(Controller, "Callback for pairing coomplete is not defined.");
102 mPairingComplete(error);
105 void SetNetworkCredentialsRequestedCallback(OnNetworkCredentialsRequestedCallback callback)
107 mNetworkCredentialsRequested = callback;
110 void SetOperatioonalCredentialsRequestedCallback(OnOperationalCredentialsRequestedCallback callback)
112 mOperationalCredentialsRequested = callback;
115 void SetPairingCompleteCallback(OnPairingCompleteCallback callback) { mPairingComplete = callback; }
117 void SetWifiCredentials(const char * ssid, const char * password)
119 if (mCredentialsDelegate == nullptr)
121 ChipLogError(Controller, "Wifi credentials received before delegate available.");
125 mCredentialsDelegate->SendNetworkCredentials(ssid, password);
128 void SetThreadCredentials(const chip::DeviceLayer::Internal::DeviceNetworkInfo & threadData)
130 if (mCredentialsDelegate == nullptr)
132 ChipLogError(Controller, "Thread credentials received before delegate available.");
136 mCredentialsDelegate->SendThreadCredentials(threadData);
140 OnNetworkCredentialsRequestedCallback mNetworkCredentialsRequested = nullptr;
141 OnOperationalCredentialsRequestedCallback mOperationalCredentialsRequested = nullptr;
142 OnPairingCompleteCallback mPairingComplete = nullptr;
144 /// Delegate is set during request callbacks
145 chip::RendezvousDeviceCredentialsDelegate * mCredentialsDelegate = nullptr;
148 ServerStorageDelegate gServerStorage;
149 ScriptDevicePairingDelegate gPairingDelegate;
153 extern "C" void pychip_internal_PairingDelegate_SetWifiCredentials(const char * ssid, const char * password)
155 chip::python::ChipMainThreadScheduleAndWait([&]() { gPairingDelegate.SetWifiCredentials(ssid, password); });
158 extern "C" CHIP_ERROR pychip_internal_PairingDelegate_SetThreadCredentials(const void * data, uint32_t length)
161 // Openthread is OPAQUE by the spec, however current CHIP stack does not have any
162 // validation/support for opaque blobs. As a result, we try to do some
163 // pre-validation here
165 // TODO: there should be uniform 'BLOBL' support within the thread stack
166 if (length != sizeof(chip::DeviceLayer::Internal::DeviceNetworkInfo))
168 ChipLogError(Controller, "Received invalid thread credential blob. Expected size %u and got %u bytes instead",
169 sizeof(chip::DeviceLayer::Internal::DeviceNetworkInfo), length);
170 return CHIP_ERROR_INVALID_ARGUMENT;
173 // unsure about alignment so copy into a properly aligned item
174 chip::DeviceLayer::Internal::DeviceNetworkInfo threadInfo;
175 memcpy(&threadInfo, data, sizeof(threadInfo));
177 // TODO: figure out a proper way to validate this or remove validation once
178 // thread credentials are assumed opaque throughout
179 if ((threadInfo.ThreadChannel != chip::DeviceLayer::Internal::kThreadChannel_NotSpecified) &&
180 ((threadInfo.ThreadChannel < 11) || (threadInfo.ThreadChannel > 26)))
182 ChipLogError(Controller, "Failed to validate thread info: channel %d is not valid", threadInfo.ThreadChannel);
183 return CHIP_ERROR_INVALID_ARGUMENT;
186 chip::python::ChipMainThreadScheduleAndWait([&]() { gPairingDelegate.SetThreadCredentials(threadInfo); });
188 return CHIP_NO_ERROR;
191 extern "C" void pychip_internal_PairingDelegate_SetNetworkCredentialsRequestedCallback(
192 ScriptDevicePairingDelegate::OnNetworkCredentialsRequestedCallback callback)
194 gPairingDelegate.SetNetworkCredentialsRequestedCallback(callback);
197 extern "C" void pychip_internal_PairingDelegate_SetOperationalCredentialsRequestedCallback(
198 ScriptDevicePairingDelegate::OnOperationalCredentialsRequestedCallback callback)
200 gPairingDelegate.SetOperatioonalCredentialsRequestedCallback(callback);
204 pychip_internal_PairingDelegate_SetPairingCompleteCallback(ScriptDevicePairingDelegate::OnPairingCompleteCallback callback)
206 gPairingDelegate.SetPairingCompleteCallback(callback);
209 extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_New(uint64_t localDeviceId)
211 std::unique_ptr<chip::Controller::DeviceCommissioner> result;
214 chip::python::ChipMainThreadScheduleAndWait([&]() {
215 result = std::make_unique<chip::Controller::DeviceCommissioner>();
217 // System and Inet layers explicitly passed to indicate that the CHIP stack is
218 // already assumed initialized
219 err = result->Init(localDeviceId,
220 chip::Controller::ControllerInitParams{
221 .storageDelegate = &gServerStorage,
222 .systemLayer = &chip::DeviceLayer::SystemLayer,
223 .inetLayer = &chip::DeviceLayer::InetLayer,
228 if (err != CHIP_NO_ERROR)
230 ChipLogError(Controller, "Commissioner initialization failed: %s", chip::ErrorStr(err));
234 return result.release();
237 /// Returns CHIP_ERROR corresponding to an UnpairDevice call
238 extern "C" uint32_t pychip_internal_Commissioner_Unpair(chip::Controller::DeviceCommissioner * commissioner,
239 uint64_t remoteDeviceId)
243 chip::python::ChipMainThreadScheduleAndWait([&]() { err = commissioner->UnpairDevice(remoteDeviceId); });
248 extern "C" uint32_t pychip_internal_Commissioner_BleConnectForPairing(chip::Controller::DeviceCommissioner * commissioner,
249 uint64_t remoteNodeId, uint32_t pinCode,
250 uint16_t discriminator)
255 chip::python::ChipMainThreadScheduleAndWait([&]() {
256 chip::RendezvousParameters params;
258 params.SetDiscriminator(discriminator).SetSetupPINCode(pinCode).SetRemoteNodeId(remoteNodeId);
259 #if CONFIG_NETWORK_LAYER_BLE
260 params.SetBleLayer(chip::DeviceLayer::ConnectivityMgr().GetBleLayer()).SetPeerAddress(chip::Transport::PeerAddress::BLE());
263 err = commissioner->PairDevice(remoteNodeId, params);