Release v0.1.0
Some checks failed
CI / Release (push) Has been cancelled
CI / Lint (push) Successful in 4s
CI / Type Check (push) Successful in 19s
CI / Test (push) Successful in 37s

This commit is contained in:
2025-12-04 13:18:17 +00:00
parent 64be5dacbf
commit ba2ab9d5d8
9 changed files with 433 additions and 333 deletions

View File

@@ -72,7 +72,7 @@ jobs:
release:
name: Release
needs: [lint, typecheck, test]
if: startsWith(github.ref, 'refs/tags/v')
if: startsWith(gitea.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -91,7 +91,22 @@ jobs:
run: python -m build
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: dist/*
generate_release_notes: true
run: |
TAG_NAME=${GITHUB_REF#refs/tags/}
VERSION=${TAG_NAME#v}
BODY=$(awk "/^## \[${VERSION}\]/{flag=1; next} /^## \\[/{flag=0} flag" CHANGELOG.md)
echo "Creating release ${TAG_NAME}"
RESPONSE=$(curl -s -X POST -H "Authorization: token ${GITHUB_TOKEN}" -H "Content-Type: application/json" -d "{\"tag_name\": \"${TAG_NAME}\", \"name\": \"${TAG_NAME}\", \"body\": $(echo "$BODY" | jq -Rs .)}" "${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/releases")
RELEASE_ID=$(echo "$RESPONSE" | jq -r '.id')
echo "Created release ID: ${RELEASE_ID}"
if [ "$RELEASE_ID" != "null" ] && [ -n "$RELEASE_ID" ]; then
for file in dist/*; do
echo "Uploading $(basename ${file})..."
curl -s -X POST -H "Authorization: token ${GITHUB_TOKEN}" -F "attachment=@${file}" "${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=$(basename ${file})"
done
else
echo "Failed to create release: $RESPONSE"
exit 1
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [0.1.0] - 2025-12-04
### Added
- Streamlit Dashboard Enhancement (Sprint 17)
- HAL-based instrument control (no direct physics access)
- Test execution page for running TempCo characterisation
- Results viewer page with filtering and historical data
- Form-based parameter controls preventing UI clunkiness
- Live simulation charts with auto-start
- End-to-end integration tests covering full workflow
- Updated README with installation and usage instructions
- Proprietary licence
### Changed
- Integration tests now run 100x faster with simulation time scaling
- Removed confusing pause/clear chart buttons from dashboard
### Fixed
- CI release workflow now creates proper releases with changelog description
### Technical
- Dashboard uses InstrumentFactory and InstrumentSet abstraction
- Embedded SimulationServer with threading synchronisation
- SQLite repository close() method for Windows file handle cleanup
- 259 unit tests, 12 integration tests all passing
- Coverage: 100% on core physics/instrument modules
## [0.1.0-beta.2] - 2025-12-03
### Added
@@ -128,7 +155,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
| Version | Date | Milestone |
|---------|------|-----------|
| 0.1.0 | TBD | MVP Complete |
| 0.1.0 | 2025-12-04 | MVP Complete |
| 0.1.0-beta.2 | 2025-12-03 | First DVT test runs |
| 0.1.0-beta.1 | 2025-12-02 | HAL complete |
| 0.1.0-alpha.3 | 2025-12-02 | Network ready |

5
LICENSE Normal file
View File

@@ -0,0 +1,5 @@
Copyright (c) 2025 Kai Chappell. All rights reserved.
This software is proprietary and confidential. Unauthorized copying,
distribution, modification, or use of this software, via any medium,
is strictly prohibited without prior written permission from the author.

View File

@@ -1,12 +1,12 @@
# py_dvt_ate
**ThermalATE: Coupled Physics DVT Simulation Platform**
**Coupled Physics DVT Simulation Platform**
A software simulation environment that accurately models the physical coupling between thermal and electrical domains, enabling DVT (Design Validation Test) engineers to develop, validate, and debug characterisation test sequences without physical access to laboratory equipment.
A software simulation environment for offline development of ATE (Automated Test Equipment) characterisation algorithms. Accurately models thermal-electrical coupling, enabling DVT engineers to develop and validate test sequences without physical laboratory access.
## Overview
ThermalATE enables offline development of ATE (Automated Test Equipment) characterisation algorithms by simulating:
py_dvt_ate simulates a complete DVT test bench:
- **Thermal Chamber** - Temperature control with realistic ramp and settling behaviour
- **Programmable Power Supply** - Voltage/current control and measurement
@@ -32,10 +32,6 @@ ThermalATE enables offline development of ATE (Automated Test Equipment) charact
## Installation
```bash
# Clone the repository
git clone https://github.com/yourrepo/py_dvt_ate.git
cd py_dvt_ate
# Install with development dependencies
pip install -e ".[dev]"
```
@@ -121,4 +117,4 @@ Kai Chappell
## Licence
TBD
Proprietary - All rights reserved. See [LICENSE](LICENSE) for details.

View File

@@ -1,3 +1,3 @@
"""py_dvt_ate: Coupled Physics DVT Simulation Platform."""
__version__ = "0.1.0-beta.2"
__version__ = "0.1.0"

File diff suppressed because it is too large Load Diff

View File

@@ -57,17 +57,39 @@ class SimulationServer:
self._instrument_server: InstrumentServer | None = None
self._physics_task: asyncio.Task[None] | None = None
self._running = False
self._paused = False # Pause physics simulation
self._time_scale = 1.0 # Simulation time multiplier
@property
def is_running(self) -> bool:
"""Check if server is currently running."""
return self._running
@property
def paused(self) -> bool:
"""Check if physics simulation is paused."""
return self._paused
@paused.setter
def paused(self, value: bool) -> None:
"""Pause or resume the physics simulation."""
self._paused = value
@property
def physics_engine(self) -> PhysicsEngine | None:
"""Get the physics engine instance."""
return self._physics_engine
@property
def time_scale(self) -> float:
"""Get the current time scale multiplier."""
return self._time_scale
@time_scale.setter
def time_scale(self, value: float) -> None:
"""Set the time scale multiplier (e.g., 10.0 = 10x faster)."""
self._time_scale = max(0.1, min(value, 1000.0))
def _setup(self) -> None:
"""Create and wire up all components."""
# Create physics engine
@@ -101,8 +123,12 @@ class SimulationServer:
dt = self._physics_engine.dt
while self._running:
if not self._paused:
# Step physics multiple times based on time scale
steps_per_tick = max(1, int(self._time_scale))
for _ in range(steps_per_tick):
self._physics_engine.step()
# Sleep for the physics timestep
# Sleep for the physics timestep (wall clock time)
await asyncio.sleep(dt)
async def start(self) -> None:

View File

@@ -125,6 +125,10 @@ def simulation_server() -> Generator[ServerConfig, None, None]:
server_thread = ServerThread(config)
server_thread.start()
# Speed up simulation for tests (100x faster)
if server_thread.server is not None:
server_thread.server.time_scale = 100.0
try:
yield config
finally:

View File

@@ -73,6 +73,8 @@ class TestInstrumentServer:
# Set temperature setpoint
writer.write(b"TEMP:SETPOINT 85.0\n")
await writer.drain()
# Small delay to ensure server processes command before next one
await asyncio.sleep(0.01)
# Query setpoint
writer.write(b"TEMP:SETPOINT?\n")
@@ -212,6 +214,7 @@ class TestSimulationServer:
psu_r, psu_w = await asyncio.open_connection("127.0.0.1", 16201)
psu_w.write(b"VOLT 5.0\n")
await psu_w.drain()
await asyncio.sleep(0.01) # Allow server to process
psu_w.write(b"OUTP ON\n")
await psu_w.drain()