Index: denali.qrc
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- denali.qrc (.../denali.qrc) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ denali.qrc (.../denali.qrc) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -22,6 +22,7 @@
sources/gui/qml/pages/settings/SettingsServicePassword.qml
sources/gui/qml/pages/settings/SettingsManufacturingSetup.qml
sources/gui/qml/pages/settings/SettingsFactoryReset.qml
+ sources/gui/qml/pages/settings/SettingsDecommission.qml
sources/gui/qml/dialogs/PowerOff.qml
Index: scripts/decommission.sh
===================================================================
diff -u
--- scripts/decommission.sh (revision 0)
+++ scripts/decommission.sh (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -0,0 +1,53 @@
+#!/bin/sh
+###########################################################################
+#
+# Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved.
+#
+# THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN
+# WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER.
+#
+# @file decommission.sh
+#
+# @author (last) Vy Duong
+# @date (last) 26-May-2023
+# @author (original) Vy Duong
+# @date (original) 26-May-2023
+#
+############################################################################
+
+# @details
+# This file is called by UI Software to remove and reset the device to a decommissioned state
+
+LOC_PARTITION="/dev/mmcblk0p7"
+LOC_SETTINGS_CONF="/home/root/scripts/settings.conf" #TODO update to reflect real location
+LOC_DEFAULT_SETTINGS_CONF="/home/root/scripts/default_settings.conf" #TODO update to reflect real location
+LOC_WIFI_CONF="/etc/wpa_supplicant/wpa_supplicant-wlan0.conf"
+LOC_BLUETOOTH_CONF="/etc/bluetooth/main.conf"
+
+# ------------------------------ Remove Wifi Conf
+if [ -f $LOC_WIFI_CONF ]; then
+ rm "$LOC_WIFI_CONF"
+ echo "Deleted Wifi Conf"
+fi
+
+# ------------------------------ Remove Bluetooth Conf
+if [ -f $LOC_BLUETOOTH_CONF ]; then
+ rm "$LOC_BLUETOOTH_CONF"
+ echo "Deleted Bluetooth Conf"
+fi
+
+# ------------------------------ Reset Settings Conf
+cp $LOC_DEFAULT_SETTINGS_CONF $LOC_SETTINGS_CONF
+
+# ------------------------------ Remove Logs
+rm -rf /media/sd-card/*/*
+
+# ------------------------------ Format Former Encrypted Partition
+
+# Assuming the partition is decrypted in advance
+#mkfs.ext4 $LOC_PARTITION ## NEED TO Re-eval. since it might ask yes/no...and expect answer..can do force, but dangerous
+
+# ------------------------------ Remove CloudSync Token
+# TODO remove the cloudsync token ? Need additional info on how
+
+exit 0
Index: sources/device/DeviceController.cpp
===================================================================
diff -u -r2038a8a2dcec5a461868b0150ad6fbfc2bfd8707 -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 2038a8a2dcec5a461868b0150ad6fbfc2bfd8707)
+++ sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -777,3 +777,56 @@
didAttributeResponse(model.data());
LOG_APPED_UI(model.data().mMessage);
}
+
+///////////////////////////////////////////// DeviceDecommission
+/*!
+ * \brief DeviceController::onAttributeRequest
+ * \details Calls the decommission script with the model data DeviceDecommissionRequestData
+ * \param vData - the model data
+ */
+void DeviceController::onAttributeRequest(const DeviceDecommissionRequestData &vData)
+{
+ _deviceDecommissionRequest._data = vData;
+
+ // ----- check that script exists.
+ QString script;
+ if ( checkError( DeviceError::checkScript(script, Device_Decommission), _deviceDecommissionResponse, script) )
+ return;
+
+ // ----- check if the process is not running
+ if ( _processDecommission.state() != QProcess::NotRunning ) {
+ checkError(DeviceError::eDevice_Scripts_Error_IsRunning, _deviceDecommissionResponse);
+ return;
+ }
+
+
+ // ----- run the process
+ int timeout_ms = 10000;
+ TimedProcess *timedProcess = new TimedProcess(&_processDecommission, script, timeout_ms);
+ timedProcess->start();
+
+ MDeviceDecommissionResponse model;
+ model._data.mAccepted = false; // will indirectly set the property decommissionEnabled
+ model._data.mMessage = tr("Decommissioning started.");
+ didAttributeResponse(model.data());
+}
+
+/*!
+ * \brief DeviceController::onProcessDecommissionExitCode
+ * \param vExitCode
+ * \param vStatus
+ */
+void DeviceController::onProcessDecommissionExitCode(int vExitCode, QProcess::ExitStatus vStatus)
+{
+ // The Exit code in this script is not used.
+ // any other checking is done by UI Software at the moment this script is called.
+ // The only thing matters is the paired device info in text and it will be empty string if error happens.
+ MDeviceDecommissionResponse model;
+ QByteArray deviceInfo = _processDecommission.readAll();
+ if ( vStatus ) vExitCode = Device::DeviceError::eDevice_Scripts_Error_Status;
+ else deviceInfo = _processDecommission.readAll();
+ model.fromByteArray( deviceInfo, &vExitCode );
+ // DEBUG: qDebug() << model._data.mMessage << deviceInfo;
+ didAttributeResponse(model.data());
+ LOG_APPED_UI(model.data().mMessage);
+}
Index: sources/device/DeviceError.h
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceError.h (.../DeviceError.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/device/DeviceError.h (.../DeviceError.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -64,6 +64,7 @@
eDevice_CryptSetup_Error ,
eDevice_FactoryReset_Error ,
+ eDevice_Decommission_Error ,
eDevice_Error_End
Index: sources/device/DeviceGlobals.h
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceGlobals.h (.../DeviceGlobals.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/device/DeviceGlobals.h (.../DeviceGlobals.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -176,35 +176,41 @@
DEVICE_DEV_PARENT ( BluetoothPairedQuery ) \
DEVICE_DEV_PARENT ( CryptSetup ) \
DEVICE_DEV_PARENT ( FactoryReset ) \
+ DEVICE_DEV_PARENT ( Decommission ) \
#define DEVICE_DEV_INIT_CONNECTIONS_LIST \
DEVICE_DEV_INIT_CONNECTIONS ( Brightness ) \
DEVICE_DEV_INIT_CONNECTIONS ( BluetoothPairedReset ) \
DEVICE_DEV_INIT_CONNECTIONS ( BluetoothPairedQuery ) \
DEVICE_DEV_INIT_CONNECTIONS ( CryptSetup ) \
DEVICE_DEV_INIT_CONNECTIONS ( FactoryReset ) \
+ DEVICE_DEV_INIT_CONNECTIONS ( Decommission ) \
#define DEVICE_DEV_DEFINITION_LIST \
DEVICE_DEV_DEFINITION ( Brightness ) \
DEVICE_DEV_DEFINITION ( BluetoothPairedReset ) \
DEVICE_DEV_DEFINITION ( BluetoothPairedQuery ) \
DEVICE_DEV_DEFINITION ( CryptSetup ) \
DEVICE_DEV_DEFINITION ( FactoryReset ) \
+ DEVICE_DEV_DEFINITION ( Decommission ) \
+
/* ---------------------------- APP */
#define DEVICE_APP_INIT_CONNECTIONS_LIST \
DEVICE_APP_INIT_CONNECTIONS ( Brightness ) \
DEVICE_APP_INIT_CONNECTIONS ( BluetoothPairedReset ) \
DEVICE_APP_INIT_CONNECTIONS ( BluetoothPairedQuery ) \
DEVICE_APP_INIT_CONNECTIONS ( CryptSetup ) \
DEVICE_APP_INIT_CONNECTIONS ( FactoryReset ) \
+ DEVICE_APP_INIT_CONNECTIONS ( Decommission ) \
#define DEVICE_APP_BRIDGE_DEFINITION_LIST \
DEVICE_APP_BRIDGE_DEFINITION( Brightness ) \
DEVICE_APP_BRIDGE_DEFINITION( BluetoothPairedReset ) \
DEVICE_APP_BRIDGE_DEFINITION( BluetoothPairedQuery ) \
DEVICE_APP_BRIDGE_DEFINITION( CryptSetup ) \
DEVICE_APP_BRIDGE_DEFINITION( FactoryReset ) \
+ DEVICE_APP_BRIDGE_DEFINITION( Decommission ) \
/* ---------------------------- GUI */
#define DEVICE_GUI_BRIDGE_DEFINITION_LIST \
@@ -213,13 +219,15 @@
DEVICE_GUI_BRIDGE_DEFINITION( BluetoothPairedQuery ) \
DEVICE_GUI_BRIDGE_DEFINITION( CryptSetup ) \
DEVICE_GUI_BRIDGE_DEFINITION( FactoryReset ) \
+ DEVICE_GUI_BRIDGE_DEFINITION( Decommission ) \
#define DEVICE_GUI_INIT_CONNECTIONS_LIST \
DEVICE_GUI_INIT_CONNECTIONS ( Brightness ) \
DEVICE_GUI_INIT_CONNECTIONS ( BluetoothPairedReset ) \
DEVICE_GUI_INIT_CONNECTIONS ( BluetoothPairedQuery ) \
DEVICE_GUI_INIT_CONNECTIONS ( CryptSetup ) \
DEVICE_GUI_INIT_CONNECTIONS ( FactoryReset ) \
+ DEVICE_GUI_INIT_CONNECTIONS ( Decommission ) \
/* ---------------------------- VIEW */
#define DEVICE_VIEW_INIT_CONNECTIONS_LIST \
@@ -228,4 +236,5 @@
DEVICE_VIEW_INIT_CONNECTIONS( BluetoothPairedQuery ) \
DEVICE_VIEW_INIT_CONNECTIONS( CryptSetup ) \
DEVICE_VIEW_INIT_CONNECTIONS( FactoryReset ) \
+ DEVICE_VIEW_INIT_CONNECTIONS( Decommission ) \
Index: sources/device/DeviceModels.cpp
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceModels.cpp (.../DeviceModels.cpp) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/device/DeviceModels.cpp (.../DeviceModels.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -221,3 +221,34 @@
lOut:
return _data.mAccepted;
}
+
+
+/*!
+ * \brief MDeviceDecommissionResponse::fromByteArray
+ * \details Checks the response and sets up the mode data.
+ * \param vExitCode - Passed script exit code
+ * \return true if passed.
+ */
+bool MDeviceDecommissionResponse::fromByteArray(const QByteArray &vByteArray, int *vExitCode)
+{
+ // initialize data
+ int error = 0;
+ _data.mAccepted = false;
+
+ // check if the vExitCode passed and it has a value other than zero
+ if ( vExitCode && *vExitCode ){ _data.mReason = Device::DeviceError::eDevice_FactoryReset_Error; error = *vExitCode; }
+ else _data.mReason = Device::DeviceError::eDevice_OK;
+
+ // if vExitCode is not zero go to error since the data is no longer valid
+ if ( _data.mReason ) goto lError; // non-zero Exit code
+
+ // Now everything is good to extract the data
+ _data.mAccepted = true;
+ _data.mMessage = QObject::tr("The Decommissioning Command Complete."); goto lOut ; // normal return
+
+lError:
+ _data.mMessage = Device::DeviceError::deviceErrorText(static_cast(_data.mReason), error) + "\n" + vByteArray;
+
+lOut:
+ return _data.mAccepted;
+}
Index: sources/device/DeviceModels.h
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceModels.h (.../DeviceModels.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/device/DeviceModels.h (.../DeviceModels.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -254,7 +254,6 @@
class MDeviceFactoryResetRequest : public MDeviceRequestBase {
public:
struct Data {
- QString mCommand = "";
} _data;
QString toString() {
@@ -264,7 +263,7 @@
/*!
* \brief The MDeviceFactoryResetResponse class
- * \details The model for the CryptSetup script call returned value / response.
+ * \details The model for the factory reset script call returned value / response.
*/
class MDeviceFactoryResetResponse : public MDeviceResponseBase {
public:
@@ -275,11 +274,39 @@
Data data ( ) const { return _data; }
bool fromByteArray(const QByteArray &vByteArray, int *vExitCode = nullptr) override;
};
-}
+// ---------- MDeviceDecommission ---------- //
+/*!
+ * \brief The MDeviceDecommissionRequest class
+ * \details The model for the decommission script call.
+ */
+class MDeviceDecommissionRequest : public MDeviceRequestBase {
+public:
+ struct Data {
+ } _data;
+ QString toString() {
+ return MDeviceRequestBase::toString("DeviceDecommission", { });
+ }
+};
+/*!
+ * \brief The MDeviceDecommissionResponse class
+ * \details The model for the decommission script call returned value / response.
+ */
+class MDeviceDecommissionResponse : public MDeviceResponseBase {
+public:
+ struct Data : MDeviceResponseBase::Data {
+ } _data;
+ QVariantList parameters ( ) const override { return { }; }
+ QString infoText ( ) const override { return QString("DeviceDecommission"); }
+ Data data ( ) const { return _data; }
+ bool fromByteArray(const QByteArray &vByteArray, int *vExitCode = nullptr) override;
+};
+}
+
+
typedef Model::MDeviceResponseBase ::Data DeviceResponseBaseData ;
typedef Model::MDeviceBrightnessRequest ::Data DeviceBrightnessRequestData ;
typedef Model::MDeviceBrightnessResponse::Data DeviceBrightnessResponseData ;
@@ -295,3 +322,6 @@
typedef Model::MDeviceFactoryResetRequest ::Data DeviceFactoryResetRequestData ;
typedef Model::MDeviceFactoryResetResponse::Data DeviceFactoryResetResponseData;
+
+typedef Model::MDeviceDecommissionRequest ::Data DeviceDecommissionRequestData ;
+typedef Model::MDeviceDecommissionResponse::Data DeviceDecommissionResponseData;
Index: sources/device/DeviceView.cpp
===================================================================
diff -u -rc849da4382b19f1e0cf36c39e7975b337bf6bec0 -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceView.cpp (.../DeviceView.cpp) (revision c849da4382b19f1e0cf36c39e7975b337bf6bec0)
+++ sources/device/DeviceView.cpp (.../DeviceView.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -169,3 +169,31 @@
DeviceFactoryResetRequestData data;
emit didAttributeRequest(data);
}
+
+// ================================================= Decommission
+void VDevice::doInitDecommission() {
+ // Nothing for now.
+}
+
+void VDevice::onAttributeResponse(const DeviceDecommissionResponseData &vData) {
+ qDebug() << "HERE Response " << Q_FUNC_INFO << " accepted: "<< vData.mAccepted << vData.mReason;
+ // this has to be called to let Gui to set to old value that device controller provided.
+ status(vData.mMessage);
+
+ // Either the script exited successfully or the script failed and the reason is provided
+ decommissionEnabled(vData.mAccepted || (!vData.mAccepted && vData.mReason!=0));
+
+ accepted(vData.mAccepted);
+ reason (vData.mReason );
+
+ // has to be the last one
+ response(true);
+}
+
+void VDevice::decommissionRequest(const QString &vCommand) {
+ Q_UNUSED(vCommand)
+ // DEBUG : qDebug() << "HERE Request" << vCommand;
+ DeviceDecommissionRequestData data;
+ emit didAttributeRequest(data);
+}
+
Index: sources/device/DeviceView.h
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/device/DeviceView.h (.../DeviceView.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/device/DeviceView.h (.../DeviceView.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -53,6 +53,9 @@
ATTRIBUTE ( QString , factoryReset , "", FactoryReset )
PROPERTY ( bool , factoryResetEnabled , true )
+ ATTRIBUTE ( QString , decommission , "", Decommission )
+ PROPERTY ( bool , decommissionEnabled , true )
+
VIEW_DEC_CLASS(VDevice)
};
}
Index: sources/gui/qml/pages/settings/SettingsDecommission.qml
===================================================================
diff -u
--- sources/gui/qml/pages/settings/SettingsDecommission.qml (revision 0)
+++ sources/gui/qml/pages/settings/SettingsDecommission.qml (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -0,0 +1,47 @@
+/*!
+ *
+ * Copyright (c) 2021-2023 Diality Inc. - All Rights Reserved.
+ * \copyright
+ * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN
+ * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER.
+ *
+ * \file SettingsDecommission.qml
+ * \author (last) Vy Duong
+ * \date (last) 09-Jun-2023
+ * \author (original) Vy Duong
+ * \date (original) 09-Jun-2023
+ *
+ */
+
+// Qt
+import QtQuick 2.12
+
+// Qml imports
+import "qrc:/globals"
+import "qrc:/pages"
+import "qrc:/components"
+
+/*!
+ * \brief SettingsDecommission is the screen
+ * which asks for confirmation of performing a factory reset and doing it if confirmed
+ */
+UserConfirmation{ id: _root
+ title : qsTr("Device Decommissioning")
+ message : vDevice.factoryResetEnabled ? qsTr("Do you want to perform a decommissioning of this device?")
+ : qsTr("Decommissioning...")
+ itemIndex : SettingsStack.Decommission
+ notificationText : vDevice.status
+
+ confirmVisible : true
+ confirmEnabled : vDevice.decommissionEnabled
+ onConfirmClicked : {
+ vDevice.decommission = "start"
+
+ // restore the binding; notificationText will now be bind to vDevice.status and correctly update
+ _root.notificationText = Qt.binding(function(){return vDevice.status})
+ }
+
+ backVisible : true
+ backEnabled : vDevice.decommissionEnabled
+ onBackClicked : _root.notificationText = "" // Note: breaks binding of notificationText property
+}
Index: sources/gui/qml/pages/settings/SettingsStack.qml
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/gui/qml/pages/settings/SettingsStack.qml (.../SettingsStack.qml) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/gui/qml/pages/settings/SettingsStack.qml (.../SettingsStack.qml) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -54,7 +54,8 @@
DeviceConfiguration ,
DeviceRegistration ,
SWUpdate ,
- FactoryReset
+ FactoryReset ,
+ Decommission
}
property var itemsText : [
qsTr("Information" ), // Information
@@ -72,6 +73,7 @@
qsTr("Device Registration" ), // DeviceRegistration
qsTr("Software Update" ), // SWUpdate
qsTr("Factory Reset" ), // FactoryReset
+ qsTr("Decommission" ), // Decommission
]
property var itemsEnabled : [
true , // Information
@@ -89,6 +91,7 @@
true , // DeviceRegistration
false , // SWUpdate
serviceMode , // FactoryReset
+ serviceMode , // Decommission
]
property var itemsVisible : [
true , // Information
@@ -106,6 +109,7 @@
_GuiView.manufactMode && serviceMode , // DeviceRegistration // && serviceMode added to make sure the service mode is confirmed by HD
false /* serviceMode phase 1 */ , // SWUpdate
_GuiView.manufactMode && serviceMode , // FactoryReset
+ _GuiView.manufactMode && serviceMode , // Decommission
]
SettingsHome { id : _settingsHome
@@ -173,6 +177,10 @@
push( _serviceFactoryReset )
break
+ case SettingsStack.Decommission:
+ push( _serviceDecommission )
+ break
+
default:
console.debug("Unknown Index", vIndex)
break
@@ -192,6 +200,7 @@
SettingsDeviceRegistration { id: _settingsDeviceRegistration }
SettingsServicePassword { id: _servicePassword }
SettingsFactoryReset { id: _serviceFactoryReset }
+ SettingsDecommission { id: _serviceDecommission }
function gotoServiceMode( vservice ) {
if ( ! _servicePassword.isPassword_Accepted ) return
Index: sources/model/MModel.h
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/model/MModel.h (.../MModel.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/model/MModel.h (.../MModel.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -288,6 +288,8 @@
REGISTER_METATYPE( DeviceCryptSetupResponseData ) \
REGISTER_METATYPE( DeviceFactoryResetRequestData) \
REGISTER_METATYPE( DeviceFactoryResetResponseData) \
+ REGISTER_METATYPE( DeviceDecommissionRequestData) \
+ REGISTER_METATYPE( DeviceDecommissionResponseData) \
/* Settings */ \
REGISTER_METATYPE( SettingsData ) \
REGISTER_METATYPE( WifiNetworkData ) \
Index: sources/storage/StorageGlobals.cpp
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/storage/StorageGlobals.cpp (.../StorageGlobals.cpp) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/storage/StorageGlobals.cpp (.../StorageGlobals.cpp) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -166,4 +166,7 @@
// Factory Reset
const char *Factory_Reset = "factory_reset.sh";
+ // Device Decommissioning
+ const char *Device_Decommission = "decommission.sh";
+
}
Index: sources/storage/StorageGlobals.h
===================================================================
diff -u -rf0ffeb8c9ec7a838f039b904ce253b001561b5db -r49b21798fb65ce44a04ae4e771ef7c3c1c119fa6
--- sources/storage/StorageGlobals.h (.../StorageGlobals.h) (revision f0ffeb8c9ec7a838f039b904ce253b001561b5db)
+++ sources/storage/StorageGlobals.h (.../StorageGlobals.h) (revision 49b21798fb65ce44a04ae4e771ef7c3c1c119fa6)
@@ -119,4 +119,8 @@
// Factory Reset
extern const char *Factory_Reset;
+
+ // Device Decommissioning
+ extern const char *Device_Decommission;
+
}