@@ -101,8 +101,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
const ZOOM_MARGIN = 10;
- import WebGLImpl from "../common/AMCImplementation_WebGL.js"
- import LayerViewImpl from "../common/AMCImplementation_LayerView.js"
+ import WebGLImpl from "@core/common/AMCImplementation_WebGL.js"
+ import LayerViewImpl from "@core/common/AMCImplementation_LayerView.js"
export default {
props: ["Application", "module"],
@@ -157,8 +157,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
this.LayerViewerInstance.setColorMode ("laseron");
}
else if (this.LayerViewerInstance.layerPointsMode == "laseron") {
+ this.LayerViewerInstance.setColorMode ("powerramp");
+ }
+ else if (this.LayerViewerInstance.layerPointsMode == "powerramp") {
this.LayerViewerInstance.setColorMode ("uniform");
- } else {
+ }
+ else {
this.LayerViewerInstance.setColorMode ("time");
}
},
@@ -240,6 +244,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
return "Color: LaserOn";
}
+ if (this.LayerViewerInstance.layerPointsMode == "powerramp") {
+ return "Color: Power";
+ }
+
return "Color: Uniform";
},
@@ -308,7 +316,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
this.LayerViewerInstance.clearPoints ();
- return this.Application.axiosGetArrayBufferRequest("/ui/pointcloud/" + scatterplotuuid)
+ return this.Application.axiosGetArrayBufferRequest("/pointcloud/" + scatterplotuuid)
.then(responseData => {
let pointcoordinates = new Float32Array(responseData.data);
@@ -332,7 +340,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
this.LayerViewerInstance.clearPointsChannelData (pointsChannelName);
- return this.Application.axiosGetArrayBufferRequest("/ui/pointchanneldata/" + scatterplotuuid + "/" + pointsChannelName)
+ return this.Application.axiosGetArrayBufferRequest("/pointchanneldata/" + scatterplotuuid + "/" + pointsChannelName)
.then(responseData => {
const contentType = responseData.headers['content-type'];
@@ -357,6 +365,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
} else {
console.log(`${key}: ${floatArray.length}`);
}
+ } else if (key.toLowerCase() === 'power') {
+ if (this.LayerViewerInstance) {
+ this.LayerViewerInstance.loadPointsChannelData ("laser", key.toLowerCase(), floatArray);
+ } else {
+ console.log(`${key}: ${floatArray.length}`);
+ }
}
} else {
console.warn(`Key "${key}" is not an array and will be ignored.`);
@@ -588,6 +602,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
let pointVelocity = this.LayerViewerInstance.getPointVelocity (pointIndex);
let pointAcceleration = this.LayerViewerInstance.getPointAcceleration (pointIndex);
let pointJerk = this.LayerViewerInstance.getPointJerk (pointIndex);
+ let pointPower = this.LayerViewerInstance.getPointPower (pointIndex);
let infoCaption = `Point ID = ${pointIndex.toFixed(0)}\n`;
if (pointPosition) {
@@ -605,7 +620,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
let jerkinmeterspersecondsquared = pointJerk.j / 1000000.0;
infoCaption += `Jerk: ${jerkinmeterspersecondsquared.toFixed(4)} km/s³\n`;
}
-
+ if (pointPower) {
+ let powerinwatts = pointPower; // * 1000.0;
+ infoCaption += `Power: ${powerinwatts.toFixed(4)} W\n`;
+ }
this.lastMouseX = mouseX;
this.lastMouseY = mouseY;
@@ -666,24 +684,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
},
- created () {
- this.module.onDataHasChanged = null;
- if (this.module.platform) {
- this.module.platform.displayed_layer = 0;
- this.module.platform.displayed_build = 0;
- }
-
- this.glInstance = this.Application.retrieveWebGLInstance (module.uuid);
+ created () {
+ this.module.onDataHasChanged = null;
+ if (this.module.platform) {
+ this.module.platform.displayed_layer = 0;
+ this.module.platform.displayed_build = 0;
+ }
+
+ this.glInstance = this.Application.retrieveWebGLInstance (this.module.uuid);
- if (!this.glInstance) {
- this.glInstance = new WebGLImpl ();
+ if (!this.glInstance) {
+ this.glInstance = new WebGLImpl ();
+ this.Application.storeWebGLInstance (this.module.uuid, this.glInstance);
+ }
- this.Application.storeWebGLInstance (this.glInstance);
- this.LayerViewerInstance = new LayerViewImpl (this.glInstance);
- this.LayerViewerInstance.RenderScene (true);
-
- }
- },
+ // Always create a fresh LayerViewerInstance wrapping the (possibly cached) glInstance.
+ this.LayerViewerInstance = new LayerViewImpl (this.glInstance);
+ this.LayerViewerInstance.RenderScene (true);
+ },
unmounted ()
{
diff --git a/Client/vue2/src/modules/AMCModule_Logs.vue b/Client/vue2/src/modules/AMCModule_Logs.vue
new file mode 100644
index 000000000..61c0e9f32
--- /dev/null
+++ b/Client/vue2/src/modules/AMCModule_Logs.vue
@@ -0,0 +1,457 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mdi-arrow-collapse-down
+
+
+ Scroll to bottom
+
+
+
+
+
+
+
+
+ mdi-format-list-numbered
+
+
+ Limit shown entries ({{ effectiveLimit }})
+
+
+
+
+ {{ opt.label }}
+
+
+
+
+
+
+
+
+
+
+
+ mdi-filter-variant
+
+
+
+ {{ subsystemFilter ? 'Filter: ' + subsystemFilter : 'Filter by subsystem' }}
+
+
+
+
+
+ mdi-filter-off-outline
+
+ Clear filter
+
+
+
+ {{ sys }}
+
+
+ No entries
+
+
+
+
+
+
+
+
+
+
+ mdi-download
+
+
+ Download log
+
+
+
+
+ mdi-code-json
+ Current view – JSON
+
+
+ mdi-code-json
+ All historic – JSON
+
+
+
+ mdi-file-delimited-outline
+ Current view – CSV
+
+
+ mdi-file-delimited-outline
+ All historic – CSV
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Client/vue2/src/modules/AMCModule_Paragraph.vue b/Client/vue2/src/modules/AMCModule_Paragraph.vue
new file mode 100644
index 000000000..f84b9ce8a
--- /dev/null
+++ b/Client/vue2/src/modules/AMCModule_Paragraph.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ {{ module.text }}
+
+
+
+
+
+
+
+
diff --git a/Client/vue2/src/modules/AMCModule_ParameterList.vue b/Client/vue2/src/modules/AMCModule_ParameterList.vue
new file mode 100644
index 000000000..7eb253177
--- /dev/null
+++ b/Client/vue2/src/modules/AMCModule_ParameterList.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+ No entries available
+
+
+
+
+
+
+
+
+
diff --git a/Client/src/modules/AMCModule_ContentItem_Chart.vue b/Client/vue2/src/modules/AMCModule_Separator.vue
similarity index 50%
rename from Client/src/modules/AMCModule_ContentItem_Chart.vue
rename to Client/vue2/src/modules/AMCModule_Separator.vue
index d238cd117..a98c78dc3 100644
--- a/Client/src/modules/AMCModule_ContentItem_Chart.vue
+++ b/Client/vue2/src/modules/AMCModule_Separator.vue
@@ -1,6 +1,6 @@
+
+
+
+
+
+ {{ iconName }}
+
+ {{ module.title }}
+ — {{ module.description }}
+
+
+
+
+
+
+
+
diff --git a/Client/vue2/src/modules/AMCModule_TableBase.vue b/Client/vue2/src/modules/AMCModule_TableBase.vue
new file mode 100644
index 000000000..1d08df3ee
--- /dev/null
+++ b/Client/vue2/src/modules/AMCModule_TableBase.vue
@@ -0,0 +1,264 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Client/src/modules/AMCModule_Tabs.vue b/Client/vue2/src/modules/AMCModule_Tabs.vue
similarity index 52%
rename from Client/src/modules/AMCModule_Tabs.vue
rename to Client/vue2/src/modules/AMCModule_Tabs.vue
index 02bb83e8c..b3a6c5d7f 100644
--- a/Client/src/modules/AMCModule_Tabs.vue
+++ b/Client/vue2/src/modules/AMCModule_Tabs.vue
@@ -30,62 +30,75 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
-
+
+
+
+
-
{{ moduleTab.caption }}
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
-
-
+
-
+
+
+
diff --git a/Client/vue2/src/modules/AMCModule_Upload.vue b/Client/vue2/src/modules/AMCModule_Upload.vue
new file mode 100644
index 000000000..881710381
--- /dev/null
+++ b/Client/vue2/src/modules/AMCModule_Upload.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Client/src/modules/AMCModule_Logs.vue b/Client/vue2/src/modules/AMCModule_VideoStream.vue
similarity index 67%
rename from Client/src/modules/AMCModule_Logs.vue
rename to Client/vue2/src/modules/AMCModule_VideoStream.vue
index 77e167383..0bfb0294b 100644
--- a/Client/src/modules/AMCModule_Logs.vue
+++ b/Client/vue2/src/modules/AMCModule_VideoStream.vue
@@ -30,44 +30,38 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
-
-
-
+
+
![Video Stream]()
+
- export default {
- props: ["Application", "module"],
-
- components: {
- },
-
- data: () => ({
- Headers: [
- { text: 'Time', value: 'logTime', width: "50pt", fixed: true },
- { text: 'Subsystem', value: 'logSubsystem', width: "50pt", fixed: true },
- { text: 'Text', value: 'logText' },
- ],
-
- logsAvailable: false,
- tab: null
- })
-
- };
-
-
\ No newline at end of file
+
diff --git a/Client/src/vuetify.js b/Client/vue2/src/vuetify.js
similarity index 85%
rename from Client/src/vuetify.js
rename to Client/vue2/src/vuetify.js
index 834fe0a4d..fe1bbf441 100644
--- a/Client/src/vuetify.js
+++ b/Client/vue2/src/vuetify.js
@@ -36,13 +36,19 @@ Vue.use(Vuetify);
export default new Vuetify({
theme: {
+ dark: false,
themes: {
light: {
- primary: '#808080',
- secondary: '#1e1e1e',
- accent: '#666666',
- error: '#DD2222',
+ primary: '#C8102E',
+ secondary: '#3C3C3C',
+ accent: '#C8102E',
+ error: '#C8102E',
+ info: '#2979FF',
+ success: '#43A047',
+ warning: '#F9A825',
+ background: '#E0E3E7',
+ surface: '#FFFFFF',
},
},
- },
+ },
});
diff --git a/Client/vue.config.js b/Client/vue2/vue.config.js
similarity index 90%
rename from Client/vue.config.js
rename to Client/vue2/vue.config.js
index 43e322eca..723a51ef8 100644
--- a/Client/vue.config.js
+++ b/Client/vue2/vue.config.js
@@ -28,8 +28,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+const path = require('path');
+
module.exports = {
"transpileDependencies": [
"vuetify"
- ]
+ ],
+ configureWebpack: {
+ resolve: {
+ alias: {
+ '@core': path.resolve(__dirname, '../core')
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/DevTools/CMakeLists_Distrib.txt b/DevTools/CMakeLists_Distrib.txt
index b7174787a..07fbc660e 100644
--- a/DevTools/CMakeLists_Distrib.txt
+++ b/DevTools/CMakeLists_Distrib.txt
@@ -26,7 +26,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "")
diff --git a/DevTools/build_clean_distrib_linux64.sh b/DevTools/build_clean_distrib_linux64.sh
index 87dcf0ed5..4ee0f0cd3 100644
--- a/DevTools/build_clean_distrib_linux64.sh
+++ b/DevTools/build_clean_distrib_linux64.sh
@@ -1,9 +1,6 @@
#!/bin/bash
set -e
-# disable go modules
-export GO111MODULE="off"
-
scriptpath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
echo "script path: $scriptpath"
cd "$scriptpath"
@@ -40,4 +37,3 @@ cmake ..
cmake --build . --config Release
cd Output
-
diff --git a/DevTools/build_clean_distrib_rpi.sh b/DevTools/build_clean_distrib_rpi.sh
index d22dabf15..0faaa1e2b 100644
--- a/DevTools/build_clean_distrib_rpi.sh
+++ b/DevTools/build_clean_distrib_rpi.sh
@@ -1,9 +1,6 @@
#!/bin/bash
set -e
-# disable go modules
-export GO111MODULE="off"
-
scriptpath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
echo "script path: $scriptpath"
cd "$scriptpath"
@@ -40,4 +37,3 @@ cmake ..
cmake --build . --config Release
cd Output
-
diff --git a/DevTools/build_clean_distrib_win64.bat b/DevTools/build_clean_distrib_win64.bat
index 948759d1d..4c1bb8fae 100644
--- a/DevTools/build_clean_distrib_win64.bat
+++ b/DevTools/build_clean_distrib_win64.bat
@@ -6,7 +6,7 @@ SET /p DEVPACKAGE=
/dev/null 2>&1; then
+ echo "lcov not found. Please install lcov/genhtml before running coverage."
+ exit 1
+fi
+
+mkdir -p "$BUILD_DIR"
+if [[ ! -f "$BUILD_DIR/githash.txt" ]]; then
+ GITHASH=""
+ if command -v git >/dev/null 2>&1; then
+ GITHASH="$(git -C "$ROOT_DIR" rev-parse --short=8 HEAD 2>/dev/null || true)"
+ fi
+ if [[ -z "$GITHASH" && -f "$ROOT_DIR/build_linux64/githash.txt" ]]; then
+ GITHASH="$(cat "$ROOT_DIR/build_linux64/githash.txt" 2>/dev/null || true)"
+ fi
+ if [[ -z "$GITHASH" && -f "$ROOT_DIR/githash.txt" ]]; then
+ GITHASH="$(cat "$ROOT_DIR/githash.txt" 2>/dev/null || true)"
+ fi
+ if [[ -z "$GITHASH" ]]; then
+ echo "githash.txt not found and git hash unavailable. Run build_clean_linux64.sh or ensure githash.txt exists."
+ exit 1
+ fi
+ printf "%s\n" "$GITHASH" > "$BUILD_DIR/githash.txt"
+fi
+
+if [[ ! -f "$BUILD_DIR/clientdirhash.txt" ]]; then
+ CLIENTHASH=""
+ if [[ -f "$ROOT_DIR/build_linux64/clientdirhash.txt" ]]; then
+ CLIENTHASH="$(cat "$ROOT_DIR/build_linux64/clientdirhash.txt" 2>/dev/null || true)"
+ fi
+ if [[ -z "$CLIENTHASH" && -f "$ROOT_DIR/clientdirhash.txt" ]]; then
+ CLIENTHASH="$(cat "$ROOT_DIR/clientdirhash.txt" 2>/dev/null || true)"
+ fi
+ if [[ -z "$CLIENTHASH" ]]; then
+ echo "clientdirhash.txt not found. Run build_clean_linux64.sh or ensure clientdirhash.txt exists."
+ exit 1
+ fi
+ printf "%s\n" "$CLIENTHASH" > "$BUILD_DIR/clientdirhash.txt"
+fi
+
+cmake -S "$ROOT_DIR" -B "$BUILD_DIR" -DINCLUDE_TESTS=ON -DENABLE_COVERAGE=ON
+
+TARGETS=()
+if [[ $RUN_UNITTEST -eq 1 ]]; then
+ TARGETS+=("amc_unittest")
+fi
+if [[ ${#TESTDEFS[@]} -gt 0 ]]; then
+ TARGETS+=("amc_test")
+fi
+if [[ ${#EXTRA_TARGETS[@]} -gt 0 ]]; then
+ TARGETS+=("${EXTRA_TARGETS[@]}")
+fi
+
+if [[ ${#TARGETS[@]} -gt 0 ]]; then
+ cmake --build "$BUILD_DIR" --target "${TARGETS[@]}"
+fi
+
+pushd "$BUILD_DIR" >/dev/null
+lcov --directory . --zerocounters
+
+if [[ $RUN_UNITTEST -eq 1 ]]; then
+ ./Output/amc_unittest
+fi
+
+if [[ ${#TESTDEFS[@]} -gt 0 ]]; then
+ CMD=(./Output/amc_test)
+ for def in "${TESTDEFS[@]}"; do
+ CMD+=(--testdefinition "$def")
+ done
+ "${CMD[@]}"
+fi
+
+lcov --capture --directory . --base-directory "$ROOT_DIR" --output-file coverage.info
+lcov --ignore-errors unused --remove coverage.info \
+ '/usr/*' \
+ "$ROOT_DIR/3RD_PARTY/*" \
+ "$ROOT_DIR/Framework/*" \
+ "$ROOT_DIR/Libraries/*" \
+ "$ROOT_DIR/SDK/*" \
+ "$ROOT_DIR/submodules/*" \
+ --output-file coverage.info
+genhtml coverage.info --output-directory coverage_html
+echo "Coverage report: $BUILD_DIR/coverage_html/index.html"
+popd >/dev/null
diff --git a/DevTools/packageManager.arm b/DevTools/packageManager.arm
deleted file mode 100644
index 59097910c..000000000
Binary files a/DevTools/packageManager.arm and /dev/null differ
diff --git a/DevTools/packageManager.exe b/DevTools/packageManager.exe
deleted file mode 100644
index 1cbad1916..000000000
Binary files a/DevTools/packageManager.exe and /dev/null differ
diff --git a/DevTools/packageManager.linux64 b/DevTools/packageManager.linux64
deleted file mode 100644
index bdc43c28c..000000000
Binary files a/DevTools/packageManager.linux64 and /dev/null differ
diff --git a/DevTools/package_manager.exe b/DevTools/package_manager.exe
new file mode 100644
index 000000000..92de7cef9
Binary files /dev/null and b/DevTools/package_manager.exe differ
diff --git a/Documentation/API/source/Drivers/ADS/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/ADS/CMakeLists_dynamic.txt
index 0db43f085..a1743c9f2 100644
--- a/Documentation/API/source/Drivers/ADS/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/ADS/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_ADSExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/ADS/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/ADS/CMakeLists_implicit.txt
index 6490dde36..000bb58ad 100644
--- a/Documentation/API/source/Drivers/ADS/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/ADS/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_ADSExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/BuR/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/BuR/CMakeLists_dynamic.txt
index e4da181de..d2881321d 100644
--- a/Documentation/API/source/Drivers/BuR/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/BuR/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_BuRExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/BuR/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/BuR/CMakeLists_implicit.txt
index 3c1454418..664627fa1 100644
--- a/Documentation/API/source/Drivers/BuR/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/BuR/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_BuRExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/Duet/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/Duet/CMakeLists_dynamic.txt
index f35238fde..006601512 100644
--- a/Documentation/API/source/Drivers/Duet/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/Duet/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_DuetExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/Duet/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/Duet/CMakeLists_implicit.txt
index 51ebc7b33..17c74b17f 100644
--- a/Documentation/API/source/Drivers/Duet/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/Duet/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_DuetExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/LibOAPC/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/LibOAPC/CMakeLists_dynamic.txt
index 510677fb0..a6611a13f 100644
--- a/Documentation/API/source/Drivers/LibOAPC/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/LibOAPC/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_LibOAPCExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/LibOAPC/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/LibOAPC/CMakeLists_implicit.txt
index aa7275c13..3a92a1435 100644
--- a/Documentation/API/source/Drivers/LibOAPC/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/LibOAPC/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_LibOAPCExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/Marlin/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/Marlin/CMakeLists_dynamic.txt
index c70dc39ff..a21669240 100644
--- a/Documentation/API/source/Drivers/Marlin/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/Marlin/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_MarlinExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/Marlin/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/Marlin/CMakeLists_implicit.txt
index a6cc70ba9..b15416624 100644
--- a/Documentation/API/source/Drivers/Marlin/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/Marlin/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_MarlinExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/OPCUA/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/OPCUA/CMakeLists_dynamic.txt
index ccbbf381c..56e439aaa 100644
--- a/Documentation/API/source/Drivers/OPCUA/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/OPCUA/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_OPCUAExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/OPCUA/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/OPCUA/CMakeLists_implicit.txt
index 8e6507ad3..8030823af 100644
--- a/Documentation/API/source/Drivers/OPCUA/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/OPCUA/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_OPCUAExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/Rasterizer/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/Rasterizer/CMakeLists_dynamic.txt
index b35346cda..a276d8019 100644
--- a/Documentation/API/source/Drivers/Rasterizer/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/Rasterizer/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_RasterizerExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/Rasterizer/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/Rasterizer/CMakeLists_implicit.txt
index 8cfb2dad8..45c7a2b53 100644
--- a/Documentation/API/source/Drivers/Rasterizer/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/Rasterizer/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_RasterizerExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/RayLase/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/RayLase/CMakeLists_dynamic.txt
index f1fc2147b..046606dc4 100644
--- a/Documentation/API/source/Drivers/RayLase/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/RayLase/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_RaylaseExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/RayLase/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/RayLase/CMakeLists_implicit.txt
index 6d37daa3f..b2a07405d 100644
--- a/Documentation/API/source/Drivers/RayLase/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/RayLase/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_RaylaseExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/S7Net/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/S7Net/CMakeLists_dynamic.txt
index f582ad0b6..84749f666 100644
--- a/Documentation/API/source/Drivers/S7Net/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/S7Net/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_S7NetExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/S7Net/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/S7Net/CMakeLists_implicit.txt
index 2d4528f5e..c697757f5 100644
--- a/Documentation/API/source/Drivers/S7Net/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/S7Net/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_S7NetExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/ScanLab/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/ScanLab/CMakeLists_dynamic.txt
index 60ff4437f..0781715b3 100644
--- a/Documentation/API/source/Drivers/ScanLab/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/ScanLab/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_ScanLabExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/ScanLab/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/ScanLab/CMakeLists_implicit.txt
index 25ae10db0..ee372e522 100644
--- a/Documentation/API/source/Drivers/ScanLab/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/ScanLab/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_ScanLabExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_dynamic.txt
index ca30fc31d..71bb38178 100644
--- a/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_ScanLabOIEExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_implicit.txt
index 93cfa41f2..490514bdb 100644
--- a/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/ScanLabOIE/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_ScanLabOIEExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/TCPIP/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/TCPIP/CMakeLists_dynamic.txt
index a77546564..e557e47a2 100644
--- a/Documentation/API/source/Drivers/TCPIP/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/TCPIP/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_TCPIPExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/TCPIP/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/TCPIP/CMakeLists_implicit.txt
index 7f0ce2fbc..408dc4b09 100644
--- a/Documentation/API/source/Drivers/TCPIP/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/TCPIP/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_TCPIPExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/UART/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/UART/CMakeLists_dynamic.txt
index a961bc540..caa2b8344 100644
--- a/Documentation/API/source/Drivers/UART/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/UART/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_UARTExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/UART/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/UART/CMakeLists_implicit.txt
index a8fc0cf5b..202bad2ab 100644
--- a/Documentation/API/source/Drivers/UART/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/UART/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_UARTExample_CPPImplicit)
diff --git a/Documentation/API/source/Drivers/Ximc/CMakeLists_dynamic.txt b/Documentation/API/source/Drivers/Ximc/CMakeLists_dynamic.txt
index 2d0a2a237..355d937ec 100644
--- a/Documentation/API/source/Drivers/Ximc/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Drivers/Ximc/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_XimcExample_CPPDynamic)
diff --git a/Documentation/API/source/Drivers/Ximc/CMakeLists_implicit.txt b/Documentation/API/source/Drivers/Ximc/CMakeLists_implicit.txt
index aacf4dd4f..3d350ec74 100644
--- a/Documentation/API/source/Drivers/Ximc/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Drivers/Ximc/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCDriver_XimcExample_CPPImplicit)
diff --git a/Documentation/API/source/Environment/CMakeLists_dynamic.txt b/Documentation/API/source/Environment/CMakeLists_dynamic.txt
index 79892ca36..d747a7da7 100644
--- a/Documentation/API/source/Environment/CMakeLists_dynamic.txt
+++ b/Documentation/API/source/Environment/CMakeLists_dynamic.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCEnvExample_CPPDynamic)
diff --git a/Documentation/API/source/Environment/CMakeLists_implicit.txt b/Documentation/API/source/Environment/CMakeLists_implicit.txt
index f343bdea1..955374a84 100644
--- a/Documentation/API/source/Environment/CMakeLists_implicit.txt
+++ b/Documentation/API/source/Environment/CMakeLists_implicit.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.10)
set(CMAKE_CURRENT_BINDING_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.)
project(LibMCEnvExample_CPPImplicit)
diff --git a/Documentation/Introduction/AutodeskMachineControlFramework.md b/Documentation/Introduction/AutodeskMachineControlFramework.md
index be5a4b950..1d84e03cc 100644
--- a/Documentation/Introduction/AutodeskMachineControlFramework.md
+++ b/Documentation/Introduction/AutodeskMachineControlFramework.md
@@ -284,14 +284,140 @@ As those are many configurations, in order to balance complexity with the need o
### 1.3. Modular Architecture and the need for a Client-Server system
-There are a lot of ways and opinions how one could define a modular architecture.
+There are many interpretations of "modular architecture", but in AMCF the meaning is practical: each part of the system should be replaceable or extensible without rewriting the entire stack. A machine builder should be able to swap a driver, add a new build strategy, or customize the operator workflow while keeping safety logic, scheduling, and API contracts intact. Modularity only exists if separation of concerns is enforced by clear boundaries, stable interfaces, and explicit data ownership. This reduces integration risk, accelerates vendor onboarding, and prevents long-term drift between UI and machine behavior.
+
+At the highest level, AMCF is organized into three layers: a deterministic core server that owns state, scheduling, and safety-relevant decisions; a client layer that renders the UI and communicates over a stable API; and a plugin/driver layer that integrates hardware and process logic. Each layer is independently replaceable as long as its interface contract is respected. The server is the single source of truth, the client is a consumer and operator interface, and the plugin layer is the only place that should know about proprietary device details.
+
+This structure naturally leads to a client-server architecture. In industrial control systems, the UI is only one of several consumers of machine state and services. Other consumers include automated test harnesses, remote service tools, analytics pipelines, and manufacturing execution systems (MES). A client-server design formalizes that all machine functionality is exposed as a service usable by any authorized client. This is critical for integration with factory ecosystems, for multi-client access, and for consistent behavior across different deployment contexts.
+
+The server is designed to run headless with identical behavior whether a UI is attached or not. It can run on an industrial PC, a rack-mounted server, or a virtualized environment for simulation and testing. Clients can be local (HMI), remote (service), or distributed. Because the server owns state and arbitrates actions, multiple clients can connect simultaneously without introducing inconsistent behavior. The server validates all actions under the same safety and scheduling constraints, ensuring that client diversity does not compromise correctness.
+
+The client-server split also prevents tight coupling between UI logic and machine logic. In tightly coupled systems, UI features become de facto control logic and are hard to test or reuse. AMCF enforces that control actions are implemented in the server and exposed via API endpoints. The UI does not "own" functionality; it only presents it. This keeps control logic testable with automated clients and makes UI redesigns low risk with respect to core machine behavior.
+
+Determinism and safety are major reasons to keep the server authoritative. Machine control requires predictable timing, state transitions, and interlocks. The server enforces these constraints without being affected by UI latency or network variability. By isolating timing-sensitive logic in the server, AMCF ensures safety-critical transitions execute under controlled conditions.
+
+The plugin and driver layer is the mechanism that localizes hardware differences. Machines vary in sensors, actuators, motion controllers, scanners, cameras, and safety devices. AMCF isolates hardware integration into drivers and plugin interfaces so machine builders can tailor their hardware stack without modifying the core. Vendor-specific SDKs or protocols belong here, not in the server or client. This keeps the server stable and makes new hardware onboarding a localized change rather than a system-wide refactor.
+
+Because drivers and plugins are modular, they can be tested in isolation. Simulation drivers can provide deterministic responses for unit and integration tests, and process logic can be exercised without real hardware. The same API surface used in production is used in tests, which reduces the need for custom harnesses and makes test results representative. A simulated server can also support UI development and regression testing without constant access to a physical machine.
+
+From a deployment and operations perspective, the client-server model separates update cycles. UI features often evolve faster than core machine logic, so a workflow or dashboard can ship without touching the server. Conversely, a server security or safety patch can be deployed without rebuilding the UI, reducing downtime and validation effort.
+
+Scalability, security, and resilience also improve. As machines become more connected, a server with a single authoritative state can serve multiple clients with controlled permissions. Authentication and authorization are enforced in one place, and client commands are validated as untrusted input. If a UI disconnects or a network link fails, the server continues operating safely and clients can recover state through the API.
+
+In practice, the architecture supports common deployment patterns without special cases:
+
+- Local HMI with server on the same machine for low-latency control.
+- Remote UI clients over a network for monitoring and service.
+- Headless server operation with automated clients or scripts for testing and integration.
+
+All of these use the same API contract, which makes them predictable and easier to maintain.
+
+Finally, modularity is essential for long-term evolution. Machines often live for decades, while UI technologies and hardware components evolve quickly. A stable server with versioned interfaces allows new clients, plugins, and drivers to evolve independently. This is a strategy for managing change across the lifetime of a machine, not just a technical preference.
+
+In summary, AMCF’s modular architecture provides strong boundaries between control logic, hardware integration, and user interaction. The client-server split enables determinism, safety, multi-client support, independent updates, robust testing, and long-term maintainability. It allows AMCF to function as a platform rather than a single-purpose application, supporting diverse machines and workflows while keeping the core stable and reliable.
### 1.4. Plugin mechanism and choice of programming language
+Every machine is a specialized system. The framework therefore exposes extension points for:
+
+- Drivers (hardware connectivity)
+- Process logic (build strategies, motion sequences)
+- UI modules (custom operator workflows)
+
+AMCF standardizes these extension points with a strict interface contract rather than ad hoc C++ headers. The contract is defined in XML and consumed by the Autodesk Component Toolkit (ACT), which generates the bindings, ABI headers, and wrapper code used across the framework. This is a deliberate design choice: interface definitions are treated as declarative specifications, while generated artifacts are treated as build outputs. Developers change the XML, regenerate, and then implement or consume the resulting interfaces. This avoids hand-crafted glue code, enforces consistency, and makes interface evolution explicit and auditable.
+
+ACT XML files live alongside the framework and drivers. Examples include `ACT/LibMCEnv.xml` for core environment interfaces, `SDK/ACT/LibAMCF.xml` for the public SDK, and `Drivers/*/ACT/LibMCDriver_*.xml` for hardware drivers. These XML files describe the library namespace, versioning, error codes, data types, and the classes and methods exposed by the component. XML is used because it is concise, diff-friendly, and easy to validate. It also scales well across different interface scopes: a core server API, a single driver, or a UI plugin can all be expressed with the same schema.
+
+The XML definition is the single source of truth for interface shape. It captures:
+
+- Library identity and version metadata (library name, namespace, base name).
+- Error codes and error descriptions to keep API behavior consistent.
+- Types, enums, and data structures shared across components.
+- Class and method signatures, including parameters and return values.
+- Import relationships between components, where one interface depends on another.
+
+From that XML, ACT generates the bindings and ABI layers that allow components to interact safely. In this repository, the generated output includes C and C++ headers, dynamic loader wrappers, ABI definitions, and language-specific bindings for the SDK. You can see these outputs in folders such as `Framework/HeadersCore`, `Framework/InterfacesCore`, `SDK/Headers`, and in each driver’s `Headers` and `Interfaces` directories. Generated source and header files are clearly marked as ACT output; they should not be edited directly. The workflow is always: edit the XML, run ACT to regenerate, and then update implementation code as needed.
+
+This approach also explains the choice of programming language. Plugins and drivers are implemented in C++ because machine control and hardware access require deterministic performance, tight memory control, and straightforward integration with existing SDKs. C++ also maps well onto the ABI layer that ACT generates. However, by using ACT-generated bindings, AMCF can expose those same interfaces to additional languages where appropriate, especially for higher-level integration and client tooling. The SDK includes bindings in multiple languages (for example C, C++, Python, and NodeJS), which makes it possible to integrate with external systems or build tooling without re-implementing the core logic. The interface surface remains the same because it is defined once in XML and re-generated for each target language.
+
+ACT is also what makes versioning and backward compatibility tractable. Because interfaces are declarative, changes can be reviewed in a single file and then propagated to all bindings in a controlled manner. This reduces the risk of ABI mismatches between the server, plugins, and clients. It also means that changes to error codes, types, or method signatures are visible and can be enforced during code review, which supports long-term maintainability and supports multiple platform builds without custom glue.
+
+For driver development, the XML approach is particularly valuable. A driver can import core components (for example `LibMCEnv`) to reuse shared types and services while defining only the driver-specific API. The generated headers provide a consistent interface to the server, while the implementation stays focused on vendor SDK integration and device-specific logic. This keeps driver code smaller and more predictable, and it avoids diverging conventions from one driver to the next. The same mechanism is used for UI plugins and process logic modules, which makes the overall plugin ecosystem easier to extend and document.
+
+In short, AMCF’s plugin mechanism depends on ACT as the interface definition and code generation layer. XML definitions make contracts explicit, reduce ambiguity, and allow consistent bindings across languages. C++ remains the primary implementation language for performance and control, while ACT-generated bindings open the ecosystem to other languages for integration, tooling, and client development. This combination gives AMCF both the low-level control required for machine operation and the flexibility needed for long-term platform growth.
+
### 1.5. The Hourglass pattern and Stable ABIs
+The hourglass model in AMCF is realized through ACT’s ABI strategy. At the top, you can have a rich, high-level class architecture: interfaces, inheritance, and structured types that make sense to an SDK user or driver author. At the bottom, you can have many different consumers and host environments that each want a simple, stable way to call into that architecture. The narrow middle is a plain C ABI that acts as the stable contract between them.
+
+ACT takes the declarative interface definition and generates a flat C DLL surface. Each class instance becomes a handle, and each method becomes a function that takes that handle plus serialized parameters. The C ABI uses standard error codes for all calls, which ensures a consistent failure model regardless of language or runtime. This layer is intentionally minimal: no C++ name mangling, no exceptions, no STL types, and no compiler-specific ABI details. The result is a binary interface that remains stable across compiler versions and across languages.
+
+On the consumer side, ACT-generated bindings reconstruct the richer class model. The C ABI functions are wrapped into language-native classes or interfaces, exposing idiomatic method calls, typed parameters, and resource lifetimes. From the point of view of a client, it feels like using a normal SDK. Under the hood, each call is routed through the C ABI, with error codes translated into language-native exceptions or return types. This "expand again" step is what preserves developer ergonomics while keeping the ABI compatible and predictable.
+
+The benefit of this pattern is that the complex class hierarchy is not the ABI; the ABI is the thin C layer. That means new languages can be supported by generating new wrappers without changing the core, and drivers or plugins compiled with older toolchains can keep working against newer servers as long as the C layer remains compatible. It also means that runtime loading becomes simple and uniform: every plugin is just a DLL with a defined set of exported C functions, and every consumer speaks the same function-level contract.
+
+This model also makes it straightforward to integrate proprietary third-party code. A plugin or driver can link against vendor SDKs, hardware libraries, or closed-source toolkits internally while exposing only the stable C ABI to the outside. The proprietary dependency stays encapsulated behind the handle-based interface, so the rest of the system does not have to understand or adapt to vendor-specific binaries, compilers, or error models. As long as the plugin respects the ABI contract, the core remains unaffected and stability is preserved.
+
+The hourglass approach helps manage change at different speeds. Vendor SDKs may update frequently, operating systems may add new requirements, and clients may demand new UX capabilities. Those changes can be absorbed at the edges without forcing a ripple through the system, because the middle remains narrow and stable. ACT’s generated C ABI becomes the governance point for compatibility, allowing the framework to enforce versioning, detect mismatches early, and keep older components operational during a transition.
+
+In practice, this means API boundaries are strict. Input and output types are explicit, error codes are formalized, and versioning is part of the design, not an afterthought. The narrow middle becomes a safe place to stand: a known set of behaviors that clients and drivers can trust. The wide edges remain free to innovate, but they do so by speaking the same stable language. Over time, this approach protects the system from fragmentation, keeps long-lived deployments supportable, and allows AMCF to grow in capability without sacrificing reliability.
+
### 1.6. API First Design guidelines and best practices
+API-first means the server API is the primary product surface, and everything else
+(UI, scripts, automation, and integrations) is a client of that API. If a feature
+is important for operators or external systems, it must be reachable through a
+documented endpoint. This keeps the behavior consistent across clients, reduces
+hidden state, and makes integration predictable. It also forces the team to think
+about stability and supportability before a feature ships.
+
+API-first has a few core implications for the framework. The server owns the
+domain model and state transitions; the UI only visualizes and orchestrates.
+Business rules live in the server API layer so that a button click and a remote
+integration call have the same effect. Features must be implemented as API
+capabilities first, then consumed by UI or plugins. This prevents UI-only logic,
+ensures testability, and avoids subtle discrepancies between local and remote
+operation.
+
+To keep the API reliable and evolvable, design endpoints as explicit contracts.
+Every request should return structured data and explicit error codes, never rely
+on ad-hoc text or ambiguous HTTP status mapping. Favor clear, typed payloads over
+deeply nested or under-specified blobs. When a request changes server state,
+make the operation explicit and document the required preconditions (e.g.,
+machine state, permissions, or resource locks). Where possible, design actions
+to be idempotent so clients can retry safely. Use pagination for lists, stable
+identifiers for resources, and consistent naming across endpoints.
+
+Versioning is non-negotiable. Any breaking change must be introduced as a new
+API version, with existing versions kept operational for a defined period. Add
+new fields in a backward-compatible way and avoid changing semantics of existing
+fields. Deprecate with a clear migration path, and document the planned removal
+window. This approach protects older UI packages and external integrations while
+allowing forward progress. In practice, API versioning should be reflected in
+endpoint paths and in the generated client bindings where applicable.
+
+Security and permissions must be enforced at the API boundary. Do not depend on
+UI behavior for access control. Every endpoint should validate permissions based
+on roles and session context, and return clear errors when access is denied. If
+an action has safety implications, the API should require explicit confirmation
+or a stronger permission scope, and that requirement should be documented.
+
+Observability is part of the contract. API calls should generate structured
+logs, meaningful error codes, and correlate with build/job identifiers when
+relevant. This makes it possible to trace behavior in the field and tie a
+failure to a specific build, configuration, or machine state. For long-running
+operations, provide status or progress endpoints and consistent polling or event
+mechanisms. Avoid hidden background tasks that cannot be queried or cancelled.
+
+Finally, design the API so it is pleasant to consume. Documentation should
+describe the purpose of each endpoint, the request and response models, and
+example payloads. Keep names consistent, provide clear field descriptions, and
+call out invariants. A simple rule is to treat the API docs as a first-class
+deliverable that changes in lockstep with the code. Tests should validate both
+success and failure cases, and new features should add API-level tests alongside
+implementation changes. When in doubt, ask: could a third-party integration
+reliably use this endpoint without reading the server code? If the answer is
+no, the API is not yet first-class.
### 1.7. Serialization principles, XML, JSON and binary storage
### 1.8. Resource handling and file access
@@ -304,6 +430,14 @@ There are a lot of ways and opinions how one could define a modular architecture
### 2.2. Using of git hashes in the core code
+The framework embeds git hashes into build artifacts to track provenance. This allows the machine operator and developer to identify the exact source revision of a running system, which is critical for:
+
+- Debugging field issues
+- Reproducing test results
+- Verifying compatibility of plugins and packages
+
+Build scripts store hashes in `build_/githash.txt` and package metadata, and the server exposes this information in its output folder and logs.
+
### 2.3. Stable APIs, Backwards compatibility and Data migration
### 2.4. Separation of Data and Logic and forward compatibilty.
@@ -312,6 +446,8 @@ There are a lot of ways and opinions how one could define a modular architecture
### 2.6. Testing Framework
+Testing is integrated into the CMake build and includes both unit tests and system tests. The unit test framework in `Implementation/UnitTest` is built into the `amc_unittest` binary, while driver tests live under `Tests/Test`. Tests are expected to run against deterministic inputs and use simulation drivers where possible.
+
## 3. General Backend Architecture
### 3.1. Client Server Implementation
@@ -485,4 +621,3 @@ There are a lot of ways and opinions how one could define a modular architecture
# VII Tutorials
# VIII AMCF REST API Documentation
-
diff --git a/Documentation/Website/index.html b/Documentation/Website/index.html
index dada04b79..2298e0c49 100644
--- a/Documentation/Website/index.html
+++ b/Documentation/Website/index.html
@@ -371,7 +371,7 @@ Schaeffler
Evobeam
With a background in electron beam welding and vacuum
- machines, Evobeam's SLAvam 300 system ventures into Powder Bed Fusion, and offers high temperature
+ machines, Evobeam's SLaVAM 300 system ventures into Powder Bed Fusion, and offers high temperature
processes up to 1000° degree C in a vacuum atmosphere.
- Your Windows development environment should host Visual Studio, CMake, Go and git.
+ Your Windows development environment should host Visual Studio, CMake and git.
@@ -911,4 +911,4 @@ Communit