Skip to content

Commit

Permalink
ESP32: Support Thread and Wi-Fi network revert configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
DejinChen committed Jun 12, 2024
1 parent 923854b commit 4569dc9
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 34 deletions.
2 changes: 0 additions & 2 deletions src/platform/ESP32/KeyValueStoreManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
size_t offset_bytes)
{
VerifyOrReturnError(value, CHIP_ERROR_INVALID_ARGUMENT);

// Offset and partial reads are not supported in nvs, for now just return NOT_IMPLEMENTED. Support can be added in the
// future if this is needed.
VerifyOrReturnError(offset_bytes == 0, CHIP_ERROR_NOT_IMPLEMENTED);
Expand Down
104 changes: 73 additions & 31 deletions src/platform/ESP32/NetworkCommissioningDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,39 +95,31 @@ CHIP_ERROR GetConfiguredNetwork(Network & network)

CHIP_ERROR ESPWiFiDriver::Init(NetworkStatusChangeCallback * networkStatusChangeCallback)
{
CHIP_ERROR err;
size_t ssidLen = 0;
size_t credentialsLen = 0;

err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, mSavedNetwork.credentials,
sizeof(mSavedNetwork.credentials), &credentialsLen);
if (err == CHIP_ERROR_NOT_FOUND)
wifi_config_t stationConfig;
if (esp_wifi_get_config(WIFI_IF_STA, &stationConfig) == ERR_OK && stationConfig.sta.ssid[0] != 0)
{
return CHIP_NO_ERROR;
}
uint8_t ssidLen = static_cast<uint8_t>(
strnlen(reinterpret_cast<const char *>(stationConfig.sta.ssid), DeviceLayer::Internal::kMaxWiFiSSIDLength));
memcpy(mStagingNetwork.ssid, stationConfig.sta.ssid, ssidLen);
mStagingNetwork.ssidLen = ssidLen;

err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid), &ssidLen);
if (err == CHIP_ERROR_NOT_FOUND)
{
return CHIP_NO_ERROR;
}
if (!CanCastTo<uint8_t>(credentialsLen))
{
return CHIP_ERROR_INCORRECT_STATE;
}
mSavedNetwork.credentialsLen = static_cast<uint8_t>(credentialsLen);
uint8_t credentialsLen = static_cast<uint8_t>(
strnlen(reinterpret_cast<const char *>(stationConfig.sta.password), DeviceLayer::Internal::kMaxWiFiKeyLength));

if (!CanCastTo<uint8_t>(ssidLen))
{
return CHIP_ERROR_INCORRECT_STATE;
memcpy(mStagingNetwork.credentials, stationConfig.sta.password, credentialsLen);
mStagingNetwork.credentialsLen = credentialsLen;
}
mSavedNetwork.ssidLen = static_cast<uint8_t>(ssidLen);

mStagingNetwork = mSavedNetwork;
mpScanCallback = nullptr;
mpConnectCallback = nullptr;
mpStatusChangeCallback = networkStatusChangeCallback;
return err;

// If the network configuration backup exists, it means that the device has been rebooted with
// the fail-safe armed. Since ESP-WiFi persists all wifi credentials changes, the backup must
// be restored on the boot. If there's no backup, the below function is a no-op.
RevertConfiguration();

return CHIP_NO_ERROR;
}

void ESPWiFiDriver::Shutdown()
Expand All @@ -137,17 +129,51 @@ void ESPWiFiDriver::Shutdown()

CHIP_ERROR ESPWiFiDriver::CommitConfiguration()
{
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen));
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials,
mStagingNetwork.credentialsLen));
mSavedNetwork = mStagingNetwork;
PersistedStorage::KeyValueStoreMgr().Delete(kWiFiSSIDKeyName);
PersistedStorage::KeyValueStoreMgr().Delete(kWiFiCredentialsKeyName);

return CHIP_NO_ERROR;
}

CHIP_ERROR ESPWiFiDriver::RevertConfiguration()
{
mStagingNetwork = mSavedNetwork;
return CHIP_NO_ERROR;
WiFiNetwork network;
Network configuredNetwork;
size_t ssidLen = 0;
size_t credentialsLen = 0;

CHIP_ERROR error = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, network.ssid, sizeof(network.ssid), &ssidLen);
ReturnErrorCodeIf(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR);
VerifyOrExit(CanCastTo<uint8_t>(ssidLen), error = CHIP_ERROR_INTERNAL);
VerifyOrExit(PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, network.credentials, sizeof(network.credentials),
&credentialsLen) == CHIP_NO_ERROR,
error = CHIP_ERROR_INTERNAL);
VerifyOrExit(CanCastTo<uint8_t>(credentialsLen), error = CHIP_ERROR_INTERNAL);

network.ssidLen = static_cast<uint8_t>(ssidLen);
network.credentialsLen = static_cast<uint8_t>(credentialsLen);
mStagingNetwork = network;

if (GetConfiguredNetwork(configuredNetwork) == CHIP_NO_ERROR)
{
VerifyOrExit(!NetworkMatch(mStagingNetwork, ByteSpan(configuredNetwork.networkID, configuredNetwork.networkIDLen)),
error = CHIP_NO_ERROR);
}

if (error == CHIP_NO_ERROR)
{
// ConnectWiFiNetwork can work with empty mStagingNetwork (ssidLen = 0).
error = ConnectWiFiNetwork(reinterpret_cast<const char *>(mStagingNetwork.ssid), mStagingNetwork.ssidLen,
reinterpret_cast<const char *>(mStagingNetwork.credentials), mStagingNetwork.credentialsLen);
}

exit:

// Remove the backup.
PersistedStorage::KeyValueStoreMgr().Delete(kWiFiSSIDKeyName);
PersistedStorage::KeyValueStoreMgr().Delete(kWiFiCredentialsKeyName);

return error;
}

bool ESPWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId)
Expand All @@ -163,6 +189,7 @@ Status ESPWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, Mu
VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded);
VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange);
VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange);
VerifyOrReturnError(BackupConfiguration() == CHIP_NO_ERROR, Status::kUnknownError);

memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size());
mStagingNetwork.credentialsLen = static_cast<decltype(mStagingNetwork.credentialsLen)>(credentials.size());
Expand All @@ -178,6 +205,7 @@ Status ESPWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDeb
outDebugText.reduce_size(0);
outNetworkIndex = 0;
VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound);
VerifyOrReturnError(BackupConfiguration() == CHIP_NO_ERROR, Status::kUnknownError);

// Use empty ssid for representing invalid network
mStagingNetwork.ssidLen = 0;
Expand Down Expand Up @@ -273,6 +301,7 @@ void ESPWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callbac
const uint32_t secToMiliSec = 1000;

VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound);
VerifyOrExit(BackupConfiguration() == CHIP_NO_ERROR, networkingStatus = Status::kUnknownError);
VerifyOrExit(mpConnectCallback == nullptr, networkingStatus = Status::kUnknownError);
ChipLogProgress(NetworkProvisioning, "ESP NetworkCommissioningDelegate: SSID: %.*s", static_cast<int>(networkId.size()),
networkId.data());
Expand Down Expand Up @@ -484,6 +513,19 @@ bool ESPWiFiDriver::WiFiNetworkIterator::Next(Network & item)
return true;
}

CHIP_ERROR ESPWiFiDriver::BackupConfiguration()
{
CHIP_ERROR err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, nullptr, 0);
if (err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL)
{
return CHIP_NO_ERROR;
}
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials,
mStagingNetwork.credentialsLen));
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen));
return CHIP_NO_ERROR;
}

} // namespace NetworkCommissioning
} // namespace DeviceLayer
} // namespace chip
2 changes: 1 addition & 1 deletion src/platform/ESP32/NetworkCommissioningDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ class ESPWiFiDriver final : public WiFiDriver
private:
bool NetworkMatch(const WiFiNetwork & network, ByteSpan networkId);
CHIP_ERROR StartScanWiFiNetworks(ByteSpan ssid);
CHIP_ERROR BackupConfiguration();

WiFiNetwork mSavedNetwork;
WiFiNetwork mStagingNetwork;
ScanCallback * mpScanCallback;
ConnectCallback * mpConnectCallback;
Expand Down

0 comments on commit 4569dc9

Please sign in to comment.