diff --git a/.github/workflows/run-templates.yml b/.github/workflows/run-templates.yml deleted file mode 100644 index e750daa..0000000 --- a/.github/workflows/run-templates.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Run Python Mock-up Data Script - -on: - schedule: - # Run every weekday at 7:00 AM UTC - - cron: "0 7 * * 1-5" - # Run the script from GitHub interface - workflow_dispatch: - -jobs: - execute-python-scripts: - runs-on: ubuntu-latest - - steps: - # Checkout the repository - - name: Checkout code - uses: actions/checkout@v3 - - # Set up Python environment - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.x" - - # Install tofupilot package - - name: Install dependencies - run: | - python -m pip install --upgrade pip - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - # Set TOFUPILOT_API_KEY and run all Python files in corresponding folder - - name: Run Battery-Testing Script - env: - TOFUPILOT_API_KEY: ${{ secrets.GET_STARTED_BATTERY_API_KEY }} - run: | - cd welcome_aboard/battery_testing - for i in {1..10}; do - echo "Execution $i" - python main.py - done diff --git a/.github/workflows/test-scripts.yml b/.github/workflows/test-scripts.yml deleted file mode 100644 index d712852..0000000 --- a/.github/workflows/test-scripts.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: Run Python Scripts - -on: - push: - branches: - - main - pull_request: - branches: - - main - # Run the script from GitHub interface - workflow_dispatch: - -jobs: - execute-python-scripts: - # Running on both ubuntu and windows - strategy: - matrix: - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - - env: - TOFUPILOT_API_KEY: ${{ secrets.PRODUCTION_API_KEY}} - # Forcing Python to run in UTF-8 mode for all steps in this job - PYTHONUTF8: "1" - - steps: - # Checking out the repository - - name: Checking out the repository - uses: actions/checkout@v3 - - - name: Changing code page to UTF-8 (Windows only) - if: runner.os == 'Windows' - run: chcp 65001 - - # Setting up Python - - name: Setting up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - # Installing dependencies - - name: Installing dependencies - shell: bash - run: | - if [[ "$RUNNER_OS" == "Windows" ]]; then - python -m pip install --upgrade pip - else - pip install --upgrade pip - fi - - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - # Running all Python scripts - - name: Running all Python scripts - shell: bash - run: | - find . -type f -name 'main.py' \ - -not -path '*/venv/*' \ - -not -path '*/.*/*' \ - -print0 | while IFS= read -r -d '' file; do - - directory="$(dirname "$file")" - - if [ -f "$directory/requirements.txt" ]; then - pip install -r "$directory/requirements.txt" - fi - - echo "Running files in $directory" - - ( - cd "$directory" || exit - python main.py - ) - done diff --git a/api/index.py b/api/index.py deleted file mode 100644 index b5323fd..0000000 --- a/api/index.py +++ /dev/null @@ -1,76 +0,0 @@ -import json -import os -from http.server import BaseHTTPRequestHandler - -import welcome_aboard.openhtf.main as openhtf -import welcome_aboard.vanilla.main as vanilla - - -class Handler(BaseHTTPRequestHandler): - # Setting common CORS headers - def _set_cors_headers(self): - self.send_header("Access-Control-Allow-Origin", "*") - self.send_header("Access-Control-Allow-Methods", "POST, OPTIONS") - self.send_header( - "Access-Control-Allow-Headers", - "Authorization, Content-Type") - - # Sending error response with appropriate CORS headers - def _send_error_response(self, status_code, message): - self.send_response(status_code) - self._set_cors_headers() - self.end_headers() - self.wfile.write(message.encode("utf-8")) - - # Handling preflight requests for CORS - def do_OPTIONS(self): - self.send_response(200) - self._set_cors_headers() - self.end_headers() - - # Handling POST requests - def do_POST(self): - auth_header = self.headers.get("Authorization") - - # Checking if Authorization header is present - if not auth_header: - self._send_error_response(401, "Missing Authorization header") - return - - # Parsing the Authorization header - try: - _, api_key = auth_header.split(" ") - except ValueError: - self._send_error_response( - 400, "Invalid Authorization header format") - return - - # Reading and parsing request body - content_length = int(self.headers.get("Content-Length", 0)) - body = self.rfile.read(content_length).decode("utf-8") - try: - body_data = json.loads(body) if body else {} - except json.JSONDecodeError: - body_data = {} - - url = body_data.get("url", None) - framework = body_data.get("framework", "openhtf") - serial_number = body_data.get("serial_number", None) - - os.environ["TOFUPILOT_URL"] = url - os.environ["TOFUPILOT_API_KEY"] = api_key - - # Calling the appropriate function based on the framework - if framework == "vanilla": - vanilla.main(serial_number) - elif framework == "openhtf": - openhtf.main(serial_number) - - # Sending success response - self.send_response(200) - self.send_header("Content-type", "application/json") - self._set_cors_headers() - self.end_headers() - - response_body = {"message": "Request processed successfully"} - self.wfile.write(json.dumps(response_body).encode("utf-8")) diff --git a/docs_openhtf/attachments/by_path/data/sample_file.txt b/docs_openhtf/attachments/by_path/data/sample_file.txt deleted file mode 100644 index 0089758..0000000 --- a/docs_openhtf/attachments/by_path/data/sample_file.txt +++ /dev/null @@ -1 +0,0 @@ -OpenHTF + TofuPilot = <3 \ No newline at end of file diff --git a/docs_openhtf/attachments/by_path/main.py b/docs_openhtf/attachments/by_path/main.py deleted file mode 100644 index df6d51f..0000000 --- a/docs_openhtf/attachments/by_path/main.py +++ /dev/null @@ -1,20 +0,0 @@ -import openhtf as htf -from tofupilot.openhtf import TofuPilot - - -def phase_file_attachment(test): - test.attach_from_file("data/sample_file.txt") - return htf.PhaseResult.CONTINUE - - -def main(): - test = htf.Test( - phase_file_attachment, - procedure_id="TEST0", - part_number="00389") - with TofuPilot(test): - test.execute(lambda: "PCB0001") - - -if __name__ == "__main__": - main() diff --git a/welcome_aboard/battery_testing/main.py b/docs_tofupilot/api_v1/assembly_test_with_voltage_sampling.py similarity index 88% rename from welcome_aboard/battery_testing/main.py rename to docs_tofupilot/api_v1/assembly_test_with_voltage_sampling.py index 2e848ae..3ba6708 100644 --- a/welcome_aboard/battery_testing/main.py +++ b/docs_tofupilot/api_v1/assembly_test_with_voltage_sampling.py @@ -136,6 +136,43 @@ def voltage_value(): return passed, value_measured, "V", 10.0, 12.0 +def voltage_sampling_test(): + """ + Multi-dimensional voltage sampling test. + Samples 100 voltage measurements over time. + Returns: (passed, measurements, units, limit_low, limit_high) + where measurements is a list of (timestamp, voltage) tuples + """ + passed_prob = 0.98 + num_samples = 100 + limit_low = 10.0 + limit_high = 12.0 + + measurements = [] + all_passed = True + + # Simulate voltage measurements over time + for i in range(num_samples): + timestamp = i / num_samples # Time in seconds (0 to 0.99) + + # Determine if this sample should pass + sample_passed = simulate_test_result(passed_prob) + + if sample_passed: + voltage = round(random.uniform(limit_low, limit_high), 2) + else: + voltage = round(random.uniform(8.0, 9.5), 2) + all_passed = False + + measurements.append((timestamp, voltage)) + + # Return multi-dimensional measurement + # Format: (passed, value_measured, unit, limit_low, limit_high) + # For multi-dimensional, value_measured is the list of tuples + # and unit should be a list of units for each dimension + return all_passed, measurements, ["s", "V"], limit_low, limit_high + + def internal_resistance(): passed = simulate_test_result(0.98) value_measured = ( @@ -349,10 +386,13 @@ def execute_procedures(end): if not passed_cell: continue - # Execute Assembly Tests + # Execute Assembly Tests with voltage sampling tests_assembly = [ (battery_connection, timedelta(seconds=0.1)), - (voltage_value, timedelta(seconds=1)), + ( + voltage_sampling_test, + timedelta(seconds=10), + ), # New multi-dimensional test (internal_resistance, timedelta(seconds=1)), (thermal_runaway_detection, timedelta(seconds=2)), (state_of_health, timedelta(seconds=2)), diff --git a/docs_tofupilot/attachments/client/data/temperature-map.png b/docs_tofupilot/api_v1/attachments/client/data/temperature-map.png similarity index 100% rename from docs_tofupilot/attachments/client/data/temperature-map.png rename to docs_tofupilot/api_v1/attachments/client/data/temperature-map.png diff --git a/docs_tofupilot/attachments/client/main.py b/docs_tofupilot/api_v1/attachments/client/main.py similarity index 85% rename from docs_tofupilot/attachments/client/main.py rename to docs_tofupilot/api_v1/attachments/client/main.py index 49daaae..dc49f63 100644 --- a/docs_tofupilot/attachments/client/main.py +++ b/docs_tofupilot/api_v1/attachments/client/main.py @@ -12,7 +12,7 @@ def main(): attachments = phase_file_attachment() client.create_run( - procedure_id="FVT1", + procedure_id="FVT1", # Create the procedure first in the Application unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, run_passed=True, attachments=attachments, diff --git a/docs_tofupilot/attachments/openhtf/data/temperature-map.png b/docs_tofupilot/api_v1/attachments/openhtf/data/temperature-map.png similarity index 100% rename from docs_tofupilot/attachments/openhtf/data/temperature-map.png rename to docs_tofupilot/api_v1/attachments/openhtf/data/temperature-map.png diff --git a/docs_tofupilot/attachments/openhtf/main.py b/docs_tofupilot/api_v1/attachments/openhtf/main.py similarity index 77% rename from docs_tofupilot/attachments/openhtf/main.py rename to docs_tofupilot/api_v1/attachments/openhtf/main.py index 6053e23..11c425d 100644 --- a/docs_tofupilot/attachments/openhtf/main.py +++ b/docs_tofupilot/api_v1/attachments/openhtf/main.py @@ -11,8 +11,9 @@ def phase_file_attachment(test): def main(): test = htf.Test( phase_file_attachment, - procedure_id="FVT1", - part_number="PCB1") + procedure_id="FVT1", # Create the procedure first in the Application + part_number="PCB1", + ) with TofuPilot(test): test.execute(lambda: "PCB1A001") diff --git a/docs_tofupilot/integrations/client/main.py b/docs_tofupilot/api_v1/integrations/client/main.py similarity index 80% rename from docs_tofupilot/integrations/client/main.py rename to docs_tofupilot/api_v1/integrations/client/main.py index 38e6028..c75b970 100644 --- a/docs_tofupilot/integrations/client/main.py +++ b/docs_tofupilot/api_v1/integrations/client/main.py @@ -5,7 +5,7 @@ def main(): client = TofuPilotClient() client.create_run( - procedure_id="FVT1", # Define the TofuPilot's procedure ID + procedure_id="FVT1", # Create the procedure first in the Application unit_under_test={ "serial_number": "PCB1A001", "part_number": "PCB1", diff --git a/docs_tofupilot/integrations/openhtf/main.py b/docs_tofupilot/api_v1/integrations/openhtf/main.py similarity index 66% rename from docs_tofupilot/integrations/openhtf/main.py rename to docs_tofupilot/api_v1/integrations/openhtf/main.py index a072fc2..7acc686 100644 --- a/docs_tofupilot/integrations/openhtf/main.py +++ b/docs_tofupilot/api_v1/integrations/openhtf/main.py @@ -2,12 +2,14 @@ from tofupilot.openhtf import TofuPilot # Import OpenHTF for TofuPilot -def phase_one(test): +def phase_one(): return htf.PhaseResult.CONTINUE def main(): - test = htf.Test(phase_one) + test = htf.Test( + phase_one, procedure_id="FVT1", part_number="PCB01" + ) # Specify procedure and part_number with TofuPilot(test): # One-line integration test.execute(lambda: "PCB1A001") diff --git a/docs_tofupilot/api_v1/logger/client/main.py b/docs_tofupilot/api_v1/logger/client/main.py new file mode 100644 index 0000000..0c3f33f --- /dev/null +++ b/docs_tofupilot/api_v1/logger/client/main.py @@ -0,0 +1,61 @@ +import logging +import sys +from datetime import datetime + +from tofupilot import TofuPilotClient + + +class TofuPilotLogHandler(logging.Handler): + """Handler that captures logs in a format compatible with TofuPilot API.""" + + def __init__(self): + super().__init__() + self.logs = [] + + def emit(self, record): + # Format log with ISO-8601 timestamp (UTC, ms) for TofuPilot API + log_entry = { + "level": record.levelname, + "timestamp": datetime.utcfromtimestamp(record.created).isoformat( + timespec="milliseconds" + ) + + "Z", + "message": record.getMessage(), + "source_file": record.filename, + "line_number": record.lineno, + } + self.logs.append(log_entry) + + +# Initialize the TofuPilot client to report test results +client = TofuPilotClient() + +# Set up local logger with custom name and prevent propagation to parent +# loggers +local_logger = logging.getLogger("test_logger") +local_logger.setLevel(logging.DEBUG) +local_logger.propagate = False + +# Add handlers: one for TofuPilot API capture and one for console output +capture_handler = TofuPilotLogHandler() +local_logger.addHandler(capture_handler) +local_logger.addHandler(logging.StreamHandler(sys.stdout)) + + +# Log examples at different severity levels +local_logger.debug("Debug message: Detailed information for troubleshooting") +local_logger.info("Info message: Normal operation information") +local_logger.warning("Warning: Something unexpected but not critical") +local_logger.error("Error: A significant problem that needs attention") +local_logger.critical("Critical: System unstable, immediate action required") + +# Create a run and send captured logs to TofuPilot +try: + client.create_run( + procedure_id="FVT1", + unit_under_test={"serial_number": "00007035", "part_number": "LOGS01"}, + run_passed=True, + logs=capture_handler.logs, + ) +finally: + local_logger.removeHandler(capture_handler) diff --git a/docs_tofupilot/api_v1/logger/openhtf/main.py b/docs_tofupilot/api_v1/logger/openhtf/main.py new file mode 100644 index 0000000..42d3eca --- /dev/null +++ b/docs_tofupilot/api_v1/logger/openhtf/main.py @@ -0,0 +1,24 @@ +import openhtf as htf +from tofupilot.openhtf import TofuPilot + + +@htf.measures(htf.Measurement("boolean_measure").equals(True)) +def phase_with_info_logger(test): + test.measurements.boolean_measure = True + # You can log info, warning, error, and critical. By default, debug. + test.logger.info("Logging an information") + + +def main(): + test = htf.Test( + phase_with_info_logger, + procedure_id="FVT1", + part_number="PCB01", + ) + + with TofuPilot(test): + test.execute(lambda: "PCB1A001") + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/boolean/client/main.py b/docs_tofupilot/api_v1/measurements/boolean/client/main.py new file mode 100644 index 0000000..343f7e5 --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/boolean/client/main.py @@ -0,0 +1,44 @@ +import random +from datetime import datetime + +from tofupilot import MeasurementOutcome, PhaseOutcome, TofuPilotClient + +client = TofuPilotClient() + + +def phase_led(): + start_time_millis = datetime.now().timestamp() * 1000 + + phase = [ + { + "name": "phase_led", + "outcome": PhaseOutcome.PASS, + "start_time_millis": start_time_millis, + "end_time_millis": start_time_millis + 1000, + "measurements": [ + { + "name": "is_led_switch_on", + "measured_value": True, + "outcome": MeasurementOutcome.PASS, + } + ], + } + ] + + return phase + + +def main(): + phases = phase_led() + + client.create_run( + procedure_id="FVT1", # Create the procedure first in the Application + unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, + phases=phases, + run_passed=all( + phase["outcome"] == PhaseOutcome.PASS for phase in phases), + ) + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/boolean/openhtf/main.py b/docs_tofupilot/api_v1/measurements/boolean/openhtf/main.py new file mode 100644 index 0000000..0cb8035 --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/boolean/openhtf/main.py @@ -0,0 +1,22 @@ +import openhtf as htf +from tofupilot.openhtf import TofuPilot + + +@htf.measures(htf.Measurement("is_led_switch_on").equals(True)) +def phase_led(test): + test.measurements.is_led_switch_on = True + + +def main(): + test = htf.Test( + phase_led, + procedure_id="FVT1", # Create the procedure first in the Application + part_number="PCB1", + ) + + with TofuPilot(test): + test.execute(lambda: "PCB001") + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/dimensional/client/main.py b/docs_tofupilot/api_v1/measurements/dimensional/client/main.py new file mode 100644 index 0000000..2953753 --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/dimensional/client/main.py @@ -0,0 +1,77 @@ +import random +from datetime import datetime + +import numpy as np +from tofupilot import MeasurementOutcome, PhaseOutcome, TofuPilotClient + +client = TofuPilotClient() + + +def standard(): + """Python lists approach - one point at a time""" + start = datetime.now().timestamp() * 1000 + measurements = [] + + for t in range(100): + timestamp = t / 100 # Time dimension + voltage = round(random.uniform(3.3, 3.5), 2) # Voltage dimension + current = round(random.uniform(0.3, 0.8), 3) # Current dimension + measurements.append((timestamp, voltage, current, voltage / current)) + + return { + "name": "loop_approach", + "outcome": PhaseOutcome.PASS, + "start_time_millis": start, + "end_time_millis": start + 30000, + "measurements": [ + { + "name": "current_voltage_resistance_over_time", + "units": ["s", "V", "A", "Ohm"], + "measured_value": measurements, + "outcome": MeasurementOutcome.PASS, + } + ], + } + + +def numpy_way(): + """NumPy approach - all points at once""" + start = datetime.now().timestamp() * 1000 + + # Generate all dimensions simultaneously + timestamps = np.linspace(0, 0.99, 100) + voltages = np.round(np.random.uniform(3.3, 3.5, 100), 2) + currents = np.round(np.random.uniform(0.3, 0.8, 100), 3) + + measurements = [ + tuple(x) + for x in np.column_stack((timestamps, voltages, currents, voltages / currents)) + ] + + return { + "name": "vector_approach", + "outcome": PhaseOutcome.PASS, + "start_time_millis": start, + "end_time_millis": start + 30000, + "measurements": [ + { + "name": "current_voltage_resistance_over_time", + "units": ["s", "V", "A", "Ohm"], + "measured_value": measurements, + "outcome": MeasurementOutcome.PASS, + } + ], + } + + +def main(): + client.create_run( + procedure_id="FVT1", + unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, + phases=[standard(), numpy_way()], + run_passed=True, + ) + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/dimensional/openhtf/main.py b/docs_tofupilot/api_v1/measurements/dimensional/openhtf/main.py new file mode 100644 index 0000000..9d52d7a --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/dimensional/openhtf/main.py @@ -0,0 +1,38 @@ +import random + +import openhtf as htf +from openhtf.util import units +from tofupilot.openhtf import TofuPilot + + +@htf.measures( + htf.Measurement("current_voltage_resistance_over_time") + .with_dimensions( + units.SECOND, units.VOLT, units.AMPERE + ) # Input axes: time, voltage, current + .with_units(units.OHM) # Output unit: resistance in ohms +) +def power_phase(test): + for t in range(100): + timestamp = t / 100 + voltage = round(random.uniform(3.3, 3.5), 2) + current = round(random.uniform(0.3, 0.8), 3) + resistance = voltage / current + test.measurements.current_voltage_resistance_over_time[ + timestamp, voltage, current + ] = resistance + + +def main(): + test = htf.Test( + power_phase, + procedure_id="FVT1", + part_number="PCB01", + ) + + with TofuPilot(test): + test.execute(lambda: "PCB1A003") + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/multi-measurements/client/main.py b/docs_tofupilot/api_v1/measurements/multi-measurements/client/main.py new file mode 100644 index 0000000..3c02735 --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/multi-measurements/client/main.py @@ -0,0 +1,79 @@ +import random +from datetime import datetime + +from tofupilot import MeasurementOutcome, PhaseOutcome, TofuPilotClient + +client = TofuPilotClient() + + +def phase_multi_measurements(): + start_time_millis = datetime.now().timestamp() * 1000 + + is_connected = True + firmware_version = "1.2.7" + input_voltage = round(random.uniform(3.29, 3.42), 2) + input_current = round(random.uniform(1.0, 1.55), 3) + + phase = [ + { + "name": "phase_multi_measurements", + "outcome": PhaseOutcome.PASS, + "start_time_millis": start_time_millis, + "end_time_millis": start_time_millis + 5000, + "measurements": [ + { + "name": "is_connected", + "measured_value": is_connected, + "outcome": MeasurementOutcome.PASS, + }, + { + "name": "firmware_version", + "measured_value": firmware_version, + "outcome": MeasurementOutcome.PASS, + }, + { + "name": "input_voltage", + "units": "V", + "lower_limit": 3.2, + "upper_limit": 3.4, + "measured_value": input_voltage, + "outcome": ( + MeasurementOutcome.PASS + if 3.2 <= input_voltage <= 3.4 + else MeasurementOutcome.FAIL + ), + }, + { + "name": "input_current", + "units": "A", + "upper_limit": 1.5, + "measured_value": input_current, + "outcome": ( + MeasurementOutcome.PASS + if input_current <= 1.5 + else MeasurementOutcome.FAIL + ), + }, + ], + } + ] + + return phase + + +def main(): + phases = phase_multi_measurements() + + client.create_run( + procedure_id="FVT1", + unit_under_test={ + "serial_number": "PCB1A004", + "part_number": "PCB01", + }, + phases=phases, + run_passed=all(p["outcome"] == PhaseOutcome.PASS for p in phases), + ) + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/multi-measurements/openhtf/main.py b/docs_tofupilot/api_v1/measurements/multi-measurements/openhtf/main.py new file mode 100644 index 0000000..f8f34ba --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/multi-measurements/openhtf/main.py @@ -0,0 +1,35 @@ +import random + +import openhtf as htf +from openhtf.util import units +from tofupilot.openhtf import TofuPilot + + +@htf.measures( + htf.Measurement("is_connected").equals(True), # Boolean measure + htf.Measurement("firmware_version").equals("1.2.7"), # String measure + htf.Measurement("input_voltage").in_range(3.2, 3.4).with_units(units.VOLT), + htf.Measurement("input_current").in_range( + maximum=1.5).with_units(units.AMPERE), +) +def phase_multi_measurements(test): + test.measurements.is_connected = True + test.measurements.firmware_version = "1.2.7" + + test.measurements.input_voltage = round(random.uniform(3.29, 3.42), 2) + test.measurements.input_current = round(random.uniform(1.0, 1.55), 3) + + +def main(): + test = htf.Test( + phase_multi_measurements, + procedure_id="FVT1", + part_number="PCB01", + ) + + with TofuPilot(test): + test.execute(lambda: "PCB1A004") + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/numerical/client/main.py b/docs_tofupilot/api_v1/measurements/numerical/client/main.py new file mode 100644 index 0000000..4d0813a --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/numerical/client/main.py @@ -0,0 +1,46 @@ +from datetime import datetime + +from tofupilot import MeasurementOutcome, PhaseOutcome, TofuPilotClient + +client = TofuPilotClient() + + +def phase_temperature(): + start_time_millis = datetime.now().timestamp() * 1000 + + phase = [ + { + "name": "phase_temperature", + "outcome": PhaseOutcome.PASS, + "start_time_millis": start_time_millis, + "end_time_millis": start_time_millis + 1000, + "measurements": [ + { + "name": "temperature", + "measured_value": 25, + "units": "C", + "outcome": MeasurementOutcome.PASS, + "lower_limit": 0, + "upper_limit": 100, + } + ], + } + ] + + return phase + + +def main(): + phases = phase_temperature() + + client.create_run( + procedure_id="FVT1", # Create the procedure first in the Application + unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, + phases=phases, + run_passed=all( + phase["outcome"] == PhaseOutcome.PASS for phase in phases), + ) + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/numerical/openhtf/main.py b/docs_tofupilot/api_v1/measurements/numerical/openhtf/main.py new file mode 100644 index 0000000..44aa197 --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/numerical/openhtf/main.py @@ -0,0 +1,27 @@ +import openhtf as htf +from openhtf.util import units +from tofupilot.openhtf import TofuPilot + + +@htf.measures( + htf.Measurement("temperature") # Declares the measurement name + .in_range(0, 100) # Defines the lower and upper limits + .with_units(units.DEGREE_CELSIUS) # Specifies the unit +) +def phase_temperature(test): + test.measurements.temperature = 25 # Set the temperature measured value to 25°C + + +def main(): + test = htf.Test( + phase_temperature, + procedure_id="FVT1", # Create the procedure first in the Application + part_number="PCB1", + ) + + with TofuPilot(test): + test.execute(lambda: "PCB001") + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/string/client/main.py b/docs_tofupilot/api_v1/measurements/string/client/main.py new file mode 100644 index 0000000..2d83e8b --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/string/client/main.py @@ -0,0 +1,43 @@ +from datetime import datetime + +from tofupilot import MeasurementOutcome, PhaseOutcome, TofuPilotClient + +client = TofuPilotClient() + + +def phase_firmware(): + start_time_millis = datetime.now().timestamp() * 1000 + + phase = [ + { + "name": "phase_firmware", + "outcome": PhaseOutcome.PASS, + "start_time_millis": start_time_millis, + "end_time_millis": start_time_millis + 1000, + "measurements": [ + { + "name": "temperature", + "measured_value": "1.2.4", + "outcome": MeasurementOutcome.PASS, + } + ], + } + ] + + return phase + + +def main(): + phases = phase_firmware() + + client.create_run( + procedure_id="FVT1", # Create the procedure first in the Application + unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, + phases=phases, + run_passed=all( + phase["outcome"] == PhaseOutcome.PASS for phase in phases), + ) + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/api_v1/measurements/string/openhtf/main.py b/docs_tofupilot/api_v1/measurements/string/openhtf/main.py new file mode 100644 index 0000000..ab5b1bf --- /dev/null +++ b/docs_tofupilot/api_v1/measurements/string/openhtf/main.py @@ -0,0 +1,22 @@ +import openhtf as htf +from tofupilot.openhtf import TofuPilot + + +@htf.measures(htf.Measurement("firmware_version").equals("1.2.4")) +def phase_firmware(test): + test.measurements.firmware_version = "1.2.4" + + +def main(): + test = htf.Test( + phase_firmware, + procedure_id="FVT1", # Create the procedure first in the Application + part_number="PCB1", + ) + + with TofuPilot(test): + test.execute(lambda: "PCB001") + + +if __name__ == "__main__": + main() diff --git a/docs_tofupilot/offline-upload/client/main.py b/docs_tofupilot/api_v1/offline-upload/client/main.py similarity index 84% rename from docs_tofupilot/offline-upload/client/main.py rename to docs_tofupilot/api_v1/offline-upload/client/main.py index 580da85..5674b06 100644 --- a/docs_tofupilot/offline-upload/client/main.py +++ b/docs_tofupilot/api_v1/offline-upload/client/main.py @@ -7,7 +7,7 @@ def main(): client = TofuPilotClient() client.create_run( - procedure_id="FVT1", + procedure_id="FVT1", # Create the procedure first in the Application started_at=datetime.now() - timedelta(days=1), # Run performed the day before unit_under_test={ "serial_number": "PCB1A003", diff --git a/docs_tofupilot/offline-upload/openhtf/data/PCB01A69658.openhtf_test.2025-01-20_15-32-06-058.json b/docs_tofupilot/api_v1/offline-upload/openhtf/data/PCB01A69658.openhtf_test.2025-01-20_15-32-06-058.json similarity index 100% rename from docs_tofupilot/offline-upload/openhtf/data/PCB01A69658.openhtf_test.2025-01-20_15-32-06-058.json rename to docs_tofupilot/api_v1/offline-upload/openhtf/data/PCB01A69658.openhtf_test.2025-01-20_15-32-06-058.json diff --git a/docs_tofupilot/offline-upload/openhtf/main.py b/docs_tofupilot/api_v1/offline-upload/openhtf/main.py similarity index 100% rename from docs_tofupilot/offline-upload/openhtf/main.py rename to docs_tofupilot/api_v1/offline-upload/openhtf/main.py diff --git a/docs_tofupilot/phases/advanced/client/main.py b/docs_tofupilot/api_v1/phases/advanced/client/main.py similarity index 96% rename from docs_tofupilot/phases/advanced/client/main.py rename to docs_tofupilot/api_v1/phases/advanced/client/main.py index 8dd7f29..a5a6c2d 100644 --- a/docs_tofupilot/phases/advanced/client/main.py +++ b/docs_tofupilot/api_v1/phases/advanced/client/main.py @@ -9,7 +9,7 @@ def main(): start_time_millis = datetime.now().timestamp() * 1000 client.create_run( - procedure_id="FVT1", # First create procedure in Application + procedure_id="FVT1", # Create the procedure first in the Application unit_under_test={ "serial_number": "PCB1A002", "part_number": "PCB1", diff --git a/docs_tofupilot/phases/advanced/openhtf/main.py b/docs_tofupilot/api_v1/phases/advanced/openhtf/main.py similarity index 80% rename from docs_tofupilot/phases/advanced/openhtf/main.py rename to docs_tofupilot/api_v1/phases/advanced/openhtf/main.py index 99dcfd5..f8ecced 100644 --- a/docs_tofupilot/phases/advanced/openhtf/main.py +++ b/docs_tofupilot/api_v1/phases/advanced/openhtf/main.py @@ -16,9 +16,11 @@ def phase_firmware_version_check(test): # Phase with multiple measurements @htf.measures( - htf.Measurement("input_voltage").in_range(3.1, 3.5).with_units(units.VOLT), - htf.Measurement("output_voltage").in_range(1.1, 1.3).with_units(units.VOLT), -) + htf.Measurement("input_voltage").in_range( + 3.1, 3.5).with_units( + units.VOLT), htf.Measurement("output_voltage").in_range( + 1.1, 1.3).with_units( + units.VOLT), ) def phase_voltage_measurements(test): test.measurements.input_voltage = 3.3 test.measurements.output_voltage = 1.2 diff --git a/docs_tofupilot/phases/optional/client/main.py b/docs_tofupilot/api_v1/phases/optional/client/main.py similarity index 87% rename from docs_tofupilot/phases/optional/client/main.py rename to docs_tofupilot/api_v1/phases/optional/client/main.py index fa9a47d..ed4bba3 100644 --- a/docs_tofupilot/phases/optional/client/main.py +++ b/docs_tofupilot/api_v1/phases/optional/client/main.py @@ -35,10 +35,8 @@ def main(): phases = [phase_voltage_measure()] client.create_run( - procedure_id="FVT1", - unit_under_test={ - "serial_number": "PCB1A001", - "part_number": "PCB1"}, + procedure_id="FVT1", # Create the procedure first in the Application + unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, phases=phases, run_passed=all( phase["outcome"] == PhaseOutcome.PASS for phase in phases), diff --git a/docs_tofupilot/phases/optional/openhtf/main.py b/docs_tofupilot/api_v1/phases/optional/openhtf/main.py similarity index 100% rename from docs_tofupilot/phases/optional/openhtf/main.py rename to docs_tofupilot/api_v1/phases/optional/openhtf/main.py diff --git a/docs_tofupilot/phases/required/client/main.py b/docs_tofupilot/api_v1/phases/required/client/main.py similarity index 81% rename from docs_tofupilot/phases/required/client/main.py rename to docs_tofupilot/api_v1/phases/required/client/main.py index e43bd91..f467f33 100644 --- a/docs_tofupilot/phases/required/client/main.py +++ b/docs_tofupilot/api_v1/phases/required/client/main.py @@ -21,10 +21,8 @@ def main(): phases = [phase_one()] client.create_run( - procedure_id="FVT1", - unit_under_test={ - "serial_number": "PCB1A001", - "part_number": "PCB1"}, + procedure_id="FVT1", # Create the procedure first in the Application + unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, phases=phases, run_passed=all( phase["outcome"] == PhaseOutcome.PASS for phase in phases), diff --git a/docs_tofupilot/phases/required/openhtf/main.py b/docs_tofupilot/api_v1/phases/required/openhtf/main.py similarity index 100% rename from docs_tofupilot/phases/required/openhtf/main.py rename to docs_tofupilot/api_v1/phases/required/openhtf/main.py diff --git a/docs_tofupilot/procedures/client/main.py b/docs_tofupilot/api_v1/procedures/client/main.py similarity index 81% rename from docs_tofupilot/procedures/client/main.py rename to docs_tofupilot/api_v1/procedures/client/main.py index 01213c0..37ef2a5 100644 --- a/docs_tofupilot/procedures/client/main.py +++ b/docs_tofupilot/api_v1/procedures/client/main.py @@ -1,4 +1,5 @@ from datetime import timedelta + from tofupilot import TofuPilotClient @@ -6,7 +7,7 @@ def main(): client = TofuPilotClient() client.create_run( - procedure_id="FVT1", # First create procedure in Application + procedure_id="FVT1", # Create the procedure first in the Application run_passed=True, unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, duration=timedelta(minutes=1, seconds=45), diff --git a/docs_tofupilot/procedures/openhtf/main.py b/docs_tofupilot/api_v1/procedures/openhtf/main.py similarity index 78% rename from docs_tofupilot/procedures/openhtf/main.py rename to docs_tofupilot/api_v1/procedures/openhtf/main.py index fb373c4..1c2db5e 100644 --- a/docs_tofupilot/procedures/openhtf/main.py +++ b/docs_tofupilot/api_v1/procedures/openhtf/main.py @@ -4,7 +4,7 @@ def main(): test = htf.Test( - procedure_id="FVT1", # Procedure name set by default as "openhtf_test" + procedure_id="FVT1", # Create the procedure first in the Application part_number="PCB1", ) with TofuPilot(test): diff --git a/docs_tofupilot/stations/client/main.py b/docs_tofupilot/api_v1/stations/client/main.py similarity index 78% rename from docs_tofupilot/stations/client/main.py rename to docs_tofupilot/api_v1/stations/client/main.py index c4c6d9f..f22adcb 100644 --- a/docs_tofupilot/stations/client/main.py +++ b/docs_tofupilot/api_v1/stations/client/main.py @@ -1,10 +1,12 @@ # Before running the script, ensure you have created a station in the TofuPilot interface # and linked it to the specified procedure ID ("FVT1" in this example). # You also need to save your API key in an environment variable named "STATION_API_KEY" -# or pass it directly as an argument like this: TofuPilotClient(api_key="STATION_API_KEY") +# or pass it directly as an argument like this: +# TofuPilotClient(api_key="STATION_API_KEY") -from datetime import timedelta, datetime -from tofupilot import TofuPilotClient, PhaseOutcome +from datetime import datetime, timedelta + +from tofupilot import PhaseOutcome, TofuPilotClient def phase_one(): @@ -26,7 +28,8 @@ def main(): client.create_run( procedure_id="FVT1", # Create a station in TofuPilot linked to this procedure ID - run_passed=all(phase["outcome"] == PhaseOutcome.PASS for phase in phases), + run_passed=all( + phase["outcome"] == PhaseOutcome.PASS for phase in phases), unit_under_test={"serial_number": "PCB1A001", "part_number": "PCBA01"}, phases=phases, duration=timedelta(minutes=1, seconds=45), diff --git a/docs_tofupilot/stations/openhtf/main.py b/docs_tofupilot/api_v1/stations/openhtf/main.py similarity index 88% rename from docs_tofupilot/stations/openhtf/main.py rename to docs_tofupilot/api_v1/stations/openhtf/main.py index 530101d..010ebca 100644 --- a/docs_tofupilot/stations/openhtf/main.py +++ b/docs_tofupilot/api_v1/stations/openhtf/main.py @@ -1,7 +1,8 @@ # Before running the script, ensure you have created a station in the TofuPilot interface # and linked it to the specified procedure ID ("FVT1" in this example). # You also need to save your API key in an environment variable named "STATION_API_KEY" -# or pass it directly as an argument like this: TofuPilot(test, api_key="STATION_API_KEY") +# or pass it directly as an argument like this: TofuPilot(test, +# api_key="STATION_API_KEY") import openhtf as htf diff --git a/docs_tofupilot/sub-units/client/main.py b/docs_tofupilot/api_v1/sub-units/client/main.py similarity index 70% rename from docs_tofupilot/sub-units/client/main.py rename to docs_tofupilot/api_v1/sub-units/client/main.py index 117b214..a4ce1d9 100644 --- a/docs_tofupilot/sub-units/client/main.py +++ b/docs_tofupilot/api_v1/sub-units/client/main.py @@ -9,10 +9,11 @@ def main(): client = TofuPilotClient() client.create_run( - procedure_id="FVT2", # First create procedure in Application + procedure_id="FVT2", # Create the procedure first in the Application unit_under_test={"serial_number": "CAM1A001", "part_number": "CAM1"}, run_passed=True, - sub_units=[{"serial_number": "PCB1A001"}, {"serial_number": "LEN1A001"}], + sub_units=[{"serial_number": "PCB1A001"}, + {"serial_number": "LEN1A001"}], ) diff --git a/docs_tofupilot/sub-units/openhtf/main.py b/docs_tofupilot/api_v1/sub-units/openhtf/main.py similarity index 70% rename from docs_tofupilot/sub-units/openhtf/main.py rename to docs_tofupilot/api_v1/sub-units/openhtf/main.py index 6a866f2..ba37a40 100644 --- a/docs_tofupilot/sub-units/openhtf/main.py +++ b/docs_tofupilot/api_v1/sub-units/openhtf/main.py @@ -8,9 +8,10 @@ def main(): test = Test( - procedure_id="FVT2", # First create procedure in Application + procedure_id="FVT2", # Create the procedure first in the Application part_number="CAM1", - sub_units=[{"serial_number": "PCB1A001"}, {"serial_number": "LEN1A001"}], + sub_units=[{"serial_number": "PCB1A001"}, + {"serial_number": "LEN1A001"}], ) with TofuPilot(test): test.execute(lambda: "CAM1A001") diff --git a/docs_tofupilot/unit-under-test/client/main.py b/docs_tofupilot/api_v1/unit-under-test/client/main.py similarity index 84% rename from docs_tofupilot/unit-under-test/client/main.py rename to docs_tofupilot/api_v1/unit-under-test/client/main.py index d4a6ca5..ca05bfd 100644 --- a/docs_tofupilot/unit-under-test/client/main.py +++ b/docs_tofupilot/api_v1/unit-under-test/client/main.py @@ -7,7 +7,7 @@ def main(): phases = [] client.create_run( - procedure_id="FVT1", + procedure_id="FVT1", # Create the procedure first in the Application unit_under_test={ "serial_number": "PCB1A002", "part_number": "PCB1", diff --git a/docs_tofupilot/unit-under-test/openhtf/main.py b/docs_tofupilot/api_v1/unit-under-test/openhtf/main.py similarity index 83% rename from docs_tofupilot/unit-under-test/openhtf/main.py rename to docs_tofupilot/api_v1/unit-under-test/openhtf/main.py index 3659e70..6600dc8 100644 --- a/docs_tofupilot/unit-under-test/openhtf/main.py +++ b/docs_tofupilot/api_v1/unit-under-test/openhtf/main.py @@ -6,7 +6,7 @@ def main(): phases = [] # Your test phases here test = Test( phases, - procedure_id="FVT1", + procedure_id="FVT1", # Create the procedure first in the Application part_number="PCB1", revision="A", # optional batch_number="12-24", # optional diff --git a/qa/client/create_run/basic/main.py b/qa/client/create_run/basic/main.py deleted file mode 100644 index 21c96b7..0000000 --- a/qa/client/create_run/basic/main.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Basic example showing how to create a test run using the TofuPilotClient. - -This script creates a test run for a unit with the specified serial number and part number, -indicating whether the test passed. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -from tofupilot import TofuPilotClient -import random - - -def main(): - # Initialize the TofuPilot client. - client = TofuPilotClient() - # Create a test run for the unit with serial number "00102" and part - # number "PCB01" - random_digits = "".join([str(random.randint(0, 9)) for _ in range(5)]) - serial_number = f"00220D4K{random_digits}" - client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": serial_number, "part_number": "PCB01"}, - run_passed=True, - ) - - -if __name__ == "__main__": - main() diff --git a/qa/client/create_run/fpy/main.py b/qa/client/create_run/fpy/main.py deleted file mode 100644 index 2dd951f..0000000 --- a/qa/client/create_run/fpy/main.py +++ /dev/null @@ -1,25 +0,0 @@ -import random -from datetime import datetime, timedelta - -from tofupilot import TofuPilotClient - -client = TofuPilotClient() - - -def handle_test(): - # Create 2 test for same SN - for testnumber in range(2): - client.create_run( - procedure_id="FVT112", - started_at=datetime.now(), - unit_under_test={ - "part_number": "FPY", - "serial_number": "FPY-0123410", - }, - # First Good, Second KO, to check FPY - run_passed=True if testnumber == 0 else False, - ) - - -if __name__ == "__main__": - handle_test() diff --git a/qa/client/create_run/multiple_sub_units/main.py b/qa/client/create_run/multiple_sub_units/main.py deleted file mode 100644 index 32315d0..0000000 --- a/qa/client/create_run/multiple_sub_units/main.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -Example script demonstrating how to create a test run in TofuPilot with multiple sub-units. - -This script creates a test run for a unit with the specified serial number and part number, -and includes multiple sub-units in the run. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -from tofupilot import TofuPilotClient - -# Initialize the TofuPilot client -client = TofuPilotClient() - -# Create a test run for the unit with serial number "00003" and part number "SI002", -# including sub-units with serial numbers "00002" and "00102" -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00003", "part_number": "SI002"}, - run_passed=True, - sub_units=[{"serial_number": "00002"}, {"serial_number": "00102"}], -) diff --git a/qa/client/create_run/phases_string_outcome/main.py b/qa/client/create_run/phases_string_outcome/main.py deleted file mode 100644 index d900ed7..0000000 --- a/qa/client/create_run/phases_string_outcome/main.py +++ /dev/null @@ -1,56 +0,0 @@ -import random -import time -from tofupilot import TofuPilotClient - -client = TofuPilotClient() - - -def flash_firmware(): - passed = bool(random.randint(0, 1)) - measured_value = "1.2.4" if passed else "1.2.0" - return passed, measured_value, None, None, None - - -def handle_test(): - serial_number = f"SI0364A{random.randint(10000, 99999)}" - - start_time = int(time.time() * 1000) - passed, measured_value, unit, limit_low, limit_high = flash_firmware() - end_time = int(time.time() * 1000) - - outcome = "PASS" if passed else "FAIL" - - phase = { - "name": "flash_firmware", - "outcome": outcome, - "start_time_millis": start_time, - "end_time_millis": end_time, - "measurements": [ - { - "name": "flash_firmware", - "outcome": outcome, - "measured_value": measured_value, - "units": unit, - "lower_limit": limit_low, - "upper_limit": limit_high, - } - ], - } - - client.create_run( - procedure_id="FVT9", - procedure_name="Test_QA", - unit_under_test={ - "part_number": "SI03645A", - "part_name": "test-QA", - "revision": "3.1", - "batch_number": "11-24", - "serial_number": serial_number, - }, - run_passed=passed, - phases=[phase], - ) - - -if __name__ == "__main__": - handle_test() diff --git a/qa/client/create_run/procedure_version/main.py b/qa/client/create_run/procedure_version/main.py deleted file mode 100644 index d4e7bec..0000000 --- a/qa/client/create_run/procedure_version/main.py +++ /dev/null @@ -1,52 +0,0 @@ -import random -import time -from datetime import datetime, timedelta -from tofupilot import TofuPilotClient - - -def main(): - client = TofuPilotClient() - - # Generate SN - serial_number = f"SI0364A{random.randint(10000, 99999)}" - - # 1 Phase test - start_time_millis = int(time.time() * 1000) - voltage = round(random.uniform(3, 4), 1) - limits = {"limit_low": 3.1, "limit_high": 3.5} - passed = limits["limit_low"] <= voltage <= limits["limit_high"] - outcome = {True: "PASS", False: "FAIL"}[passed] - end_time_millis = int(time.time() * 1000) - - client.create_run( - unit_under_test={ - "part_number": "SI0364", - "serial_number": serial_number, - "revision": "A", - }, - procedure_id="FVT1", # First create procedure in Application - procedure_version="1.2.20", # Create procedure version - phases=[ - { - "name": "test_voltage", - "outcome": outcome, - "start_time_millis": start_time_millis, - "end_time_millis": end_time_millis, - "measurements": [ - { - "name": "voltage_input", - "outcome": outcome, - "measured_value": voltage, - "units": "V", - "lower_limit": limits["limit_low"], - "upper_limit": limits["limit_high"], - }, - ], - }, - ], - run_passed=passed, - ) - - -if __name__ == "__main__": - main() diff --git a/qa/client/create_run/single_sub_unit/main.py b/qa/client/create_run/single_sub_unit/main.py deleted file mode 100644 index 5645c7f..0000000 --- a/qa/client/create_run/single_sub_unit/main.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -Example script demonstrating how to create a test run in TofuPilot with a single sub-unit. - -This script creates a test run for a unit with the specified serial number and part number, -and includes a single sub-unit in the run. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -from tofupilot import TofuPilotClient - -# Initialize the TofuPilot client -client = TofuPilotClient() - -# Create a test run for the unit with serial number "00002" and part number "SI001", -# including a sub-unit with serial number "00102" -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00002", "part_number": "SI001"}, - run_passed=True, - sub_units=[{"serial_number": "00102"}], -) diff --git a/qa/client/create_run/started_at/main.py b/qa/client/create_run/started_at/main.py deleted file mode 100644 index 22f5fbf..0000000 --- a/qa/client/create_run/started_at/main.py +++ /dev/null @@ -1,23 +0,0 @@ -from tofupilot import TofuPilotClient -import random -from datetime import datetime, timedelta - - -def main(): - # Initialize the TofuPilot client. - client = TofuPilotClient() - # Create a test run for the unit with serial number "00102" and part - # number "PCB01" - random_digits = "".join([str(random.randint(0, 9)) for _ in range(5)]) - serial_number = f"00220D4K{random_digits}" - client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": serial_number, "part_number": "PCB01"}, - run_passed=True, - started_at=datetime.now() - timedelta(days=1), - duration=timedelta(seconds=23), - ) - - -if __name__ == "__main__": - main() diff --git a/qa/client/create_run/with_all_types_of_phases/main.py b/qa/client/create_run/with_all_types_of_phases/main.py deleted file mode 100644 index 7138be7..0000000 --- a/qa/client/create_run/with_all_types_of_phases/main.py +++ /dev/null @@ -1,89 +0,0 @@ -import random -from datetime import datetime, timedelta -from random import randint - -from tofupilot import TofuPilotClient - -# Reference time to calculate start_time_millis in milliseconds since epoch -epoch = datetime(1970, 1, 1) - - -# Function to calculate milliseconds since epoch -def to_millis(dt): - return int((dt - epoch).total_seconds() * 1000) - - -client = TofuPilotClient() - -client.create_run( - procedure_id="FVT1", - unit_under_test={ - "serial_number": "SN17", - "part_number": "PNrstsrtsr", - "batch_number": "B", - }, - run_passed=True, # Overall run status - phases=[ - { - "name": "phase_connect", # First phase - "outcome": "PASS", - "start_time_millis": to_millis( - datetime.now() - ), # Start time of the step in ms - "end_time_millis": to_millis( - datetime.now() + timedelta(seconds=5, milliseconds=12) - ), # End time in ms - "measurements": [ - { - "name": "numeric_measurement", - "outcome": "PASS", - "measured_value": 12, - "units": "Hertz", - "lower_limit": 1, - "upper_limit": 20, - }, - { - "name": "string_measurement", - "outcome": "PASS", - "measured_value": "Test value", - "units": "Unitless", - "docstring": "This is a string measurement example", - }, - { - "name": "boolean_measurement_true", - "outcome": "PASS", - "measured_value": True, - "units": "BooleanUnit", - "docstring": "This is a boolean measurement example", - }, - { - "name": "boolean_measurement_false", - "outcome": "PASS", - "measured_value": False, - "units": "BooleanUnit", - "docstring": "This is a boolean measurement example", - }, - { - "name": "json_measurement", - "outcome": "PASS", - "measured_value": {"key1": "value1", "key2": 42}, - "units": "JSONUnit", - "docstring": "This is a JSON measurement example", - }, - { - "name": "empty_measurement", - "outcome": "PASS", - "measured_value": None, - "units": "EmptyUnit", - "docstring": "This is a measurement with a null value", - }, - { - "name": "no_value_measurement", - "outcome": "PASS", - "units": "NoValueUnit", - "docstring": "This is a measurement with no value specified", - }, - ], - } - ], -) diff --git a/qa/client/create_run/with_attachments/data/performance-report.pdf b/qa/client/create_run/with_attachments/data/performance-report.pdf deleted file mode 100644 index ce6914b..0000000 Binary files a/qa/client/create_run/with_attachments/data/performance-report.pdf and /dev/null differ diff --git a/qa/client/create_run/with_attachments/data/temperature-map.png b/qa/client/create_run/with_attachments/data/temperature-map.png deleted file mode 100644 index c7eb24b..0000000 Binary files a/qa/client/create_run/with_attachments/data/temperature-map.png and /dev/null differ diff --git a/qa/client/create_run/with_attachments/main.py b/qa/client/create_run/with_attachments/main.py deleted file mode 100644 index 7f9fe21..0000000 --- a/qa/client/create_run/with_attachments/main.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Example script demonstrating how to create a test run in TofuPilot with attachments. - -This script creates a test run for a unit with the specified serial number and part number, -and includes attachments, such as images and reports, that are related to the test. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -from tofupilot import TofuPilotClient - -# Initialize the TofuPilot client -client = TofuPilotClient() - -# Create a test run for the unit with serial number "00102" and part number "PCB01", -# including attachments such as images and PDF reports -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00102", "part_number": "PCB01"}, - run_passed=True, - attachments=[ - "data/temperature-map.png", # Path to your local files - "data/performance-report.pdf", - ], -) diff --git a/qa/client/create_run/with_duration/main.py b/qa/client/create_run/with_duration/main.py deleted file mode 100644 index d96aaac..0000000 --- a/qa/client/create_run/with_duration/main.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Example script demonstrating how to create a test run in TofuPilot with the duration of the test. - -This script measures the duration of a test function, then creates a test run for a unit -with the specified serial number and part number, including the duration as part of the run data. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -import time -from datetime import timedelta - -from tofupilot import TofuPilotClient - -# Initialize the TofuPilot client -client = TofuPilotClient() - - -def test_function(): - """ - Simulates a test execution. - """ - # Simulate test execution with a delay - time.sleep(1) # Placeholder for test execution time - return True - - -# Measure the duration of the test_function -start_time = time.time() -run_passed = test_function() -end_time = time.time() -duration = timedelta(seconds=end_time - start_time) # Calculate duration - -# Create a test run for the unit with serial number "00102" and part number "PCB01", -# including the duration of the test -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00102", "part_number": "PCB01"}, - run_passed=run_passed, - duration=duration, # Optional argument to include the duration -) diff --git a/qa/client/create_run/with_phases_and_steps/main.py b/qa/client/create_run/with_phases_and_steps/main.py deleted file mode 100644 index 9c729d6..0000000 --- a/qa/client/create_run/with_phases_and_steps/main.py +++ /dev/null @@ -1,183 +0,0 @@ -import random -from datetime import datetime, timedelta -from random import randint - -from tofupilot import TofuPilotClient - -# Reference time to calculate start_time_millis in milliseconds since epoch -epoch = datetime(1970, 1, 1) - - -# Function to calculate milliseconds since epoch -def to_millis(dt): - return int((dt - epoch).total_seconds() * 1000) - - -client = TofuPilotClient() - -client.create_run( - procedure_id="FVT1", - unit_under_test={ - "serial_number": "SN17", - "part_number": "PNrstsrtsr", - "batch_number": "B", - }, - run_passed=True, # Overall run status - steps=[ - { - "name": "step_connect", # First step - "step_passed": True, # Status of the step - # Duration of the step - "duration": timedelta(seconds=5, milliseconds=12), - "started_at": datetime.now(), # Start time of the step - }, - { - "name": "step_string2", # First step - "step_passed": True, # Status of the step - # Duration of the step - "duration": timedelta(seconds=5, milliseconds=12), - "started_at": datetime.now(), # Start time of the step - "measurement_value": "This is a string", - }, - { - "name": "step_initial_charge_check", # Second step - "step_passed": True, # Status of the step - "duration": timedelta( - seconds=3, milliseconds=100 - ), # Duration of the step (<1s) - "started_at": datetime.now() - + timedelta(seconds=3), # Start time of the second step - "measurement_value": randint(90, 100), # Measured value - }, - { - "name": "step_initial_temp_check", # Third step - "step_passed": True, # Status of the step - "duration": timedelta( - seconds=1, milliseconds=100 - ), # Duration of the step (<1s) - "started_at": datetime.now() - # Start time of the third step - + timedelta(seconds=2, milliseconds=500), - "measurement_value": randint(-5, 20), # Measured temperature value - "measurement_unit": "°C", # Unit of the measurement (temperature) - "limit_low": 0, # Lower limit of acceptable temperature - }, - { - "name": "step_temp_calibration", # Fourth step - "step_passed": False, # Status of the step - "duration": timedelta( - seconds=3, milliseconds=100 - ), # Duration of the step (<1s) - "started_at": datetime.now() - timedelta(days=1, minutes=20), - "measurement_value": randint( - 69, 81 - ), # Measured temperature value after calibration - "measurement_unit": "°C", # Unit of the measurement (temperature) - "limit_low": 70, # Lower limit of acceptable temperature - "limit_high": 80, # Upper limit of acceptable temperature - }, - ], - phases=[ - { - "name": "phase_connect", # First phase - "outcome": "PASS", - "start_time_millis": to_millis( - datetime.now() - ), # Start time of the step in ms - "end_time_millis": to_millis( - datetime.now() + timedelta(seconds=5, milliseconds=12) - ), # End time in ms - "measurements": [ - { - "name": "connectivity_check", - "outcome": "PASS", # Measurement outcome - "measured_value": None, - "units": None, - "lower_limit": None, - "upper_limit": None, - } - ], - }, - { - "name": "phase_initial_charge_check", # Second phase - "outcome": "PASS", - "start_time_millis": to_millis( - datetime.now() + timedelta(seconds=3) - ), # Start time in ms - "end_time_millis": to_millis( - datetime.now() + timedelta(seconds=6, milliseconds=100) - ), # End time in ms - "measurements": [ - { - "name": "initial_charge", - "outcome": "PASS", # Measurement outcome - "measured_value": randint(90, 100), # Measured value - "units": None, - "lower_limit": None, - "upper_limit": None, - }, - { - "name": "initial_temperature", - "outcome": "PASS", # Measurement outcome - # Measured temperature value - "measured_value": randint(-5, 20), - "units": "°C", # Unit of the measurement - "lower_limit": 0, # Lower limit - "upper_limit": None, - }, - { - "name": "initial_temperature_2", - "outcome": "FAIL", # Measurement outcome - # Measured temperature value - "measured_value": randint(-5, 20), - "units": "°C", # Unit of the measurement - "lower_limit": 0, # Lower limit - "upper_limit": 15, # Upper limit - }, - ], - }, - { - "name": "phase_initial_temp_check", # Third phase - "outcome": "PASS", - "start_time_millis": to_millis( - datetime.now() + timedelta(seconds=2, milliseconds=500) - ), # Start time in ms - "end_time_millis": to_millis( - datetime.now() + timedelta(seconds=3, milliseconds=600) - ), # End time in ms - "measurements": [ - { - "name": "initial_temperature", - "outcome": "PASS", # Measurement outcome - # Measured temperature value - "measured_value": randint(-5, 20), - "units": "°C", # Unit of the measurement - "lower_limit": 0, # Lower limit - "upper_limit": None, - } - ], - }, - { - "name": "phase_temp_calibration", # Fourth phase - "outcome": "FAIL", - "start_time_millis": to_millis( - datetime.now() - timedelta(days=1, minutes=20) - ), # Start time in ms - "end_time_millis": to_millis( - datetime.now() - - timedelta(days=1, minutes=20) - + timedelta(seconds=3, milliseconds=100) - ), # End time in ms - "measurements": [ - { - "name": "temperature_calibration", - "outcome": "FAIL", # Measurement outcome - "measured_value": randint(69, 81), # Measured value - "units": "°C", # Unit of the measurement - "lower_limit": 70, # Lower limit - "upper_limit": 80, - } - ], - }, - ], -) diff --git a/qa/client/create_run_from_openhtf_report/basic/main.py b/qa/client/create_run_from_openhtf_report/basic/main.py deleted file mode 100644 index 536f5e9..0000000 --- a/qa/client/create_run_from_openhtf_report/basic/main.py +++ /dev/null @@ -1,36 +0,0 @@ -from openhtf import PhaseResult, Test -from openhtf.output.callbacks import json_factory -from openhtf.plugs import user_input -from tofupilot import TofuPilotClient - -client = TofuPilotClient() - - -# Define a test phase to simulate the power-on procedure -def power_on_test(test): - print("Power on.") - return PhaseResult.CONTINUE - - -# Function to execute the test and save results to a JSON file -def execute_test(file_path): - test = Test(power_on_test, serial_number="PCB01") - - # Set output callback to save the test results as a JSON file - test.add_output_callbacks(json_factory.OutputToJSON(file_path)) - - # Execute the test with a specific device identifier - test.execute(lambda: "0001") - - -def main(): - # Specify the file path for saving test results - file_path = "./test_result.json" - execute_test(file_path) - - # Upload the test results to TofuPilot, specifying the importer type - client.create_run_from_openhtf_report(file_path) - - -if __name__ == "__main__": - main() diff --git a/qa/client/create_run_from_openhtf_report/with_attachments/data/oscilloscope.jpeg b/qa/client/create_run_from_openhtf_report/with_attachments/data/oscilloscope.jpeg deleted file mode 100644 index d49014b..0000000 Binary files a/qa/client/create_run_from_openhtf_report/with_attachments/data/oscilloscope.jpeg and /dev/null differ diff --git a/qa/client/create_run_from_openhtf_report/with_attachments/data/sample_file.txt b/qa/client/create_run_from_openhtf_report/with_attachments/data/sample_file.txt deleted file mode 100644 index 0089758..0000000 --- a/qa/client/create_run_from_openhtf_report/with_attachments/data/sample_file.txt +++ /dev/null @@ -1 +0,0 @@ -OpenHTF + TofuPilot = <3 \ No newline at end of file diff --git a/qa/client/create_run_from_openhtf_report/with_attachments/main.py b/qa/client/create_run_from_openhtf_report/with_attachments/main.py deleted file mode 100644 index a0189e0..0000000 --- a/qa/client/create_run_from_openhtf_report/with_attachments/main.py +++ /dev/null @@ -1,49 +0,0 @@ -import openhtf as htf -from openhtf import PhaseResult, Test -from openhtf.output.callbacks import json_factory -from openhtf.plugs import user_input -from tofupilot import TofuPilotClient -from tofupilot.openhtf import TofuPilot - -client = TofuPilotClient() - - -# Define a test phase to simulate the power-on procedure -def power_on_test(test): - print("Power on.") - return PhaseResult.CONTINUE - - -# Define a phase that attaches a file -def phase_file_attachment(test): - test.attach_from_file("data/sample_file.txt") - test.attach_from_file("data/oscilloscope.jpeg") - return htf.PhaseResult.CONTINUE - - -# Function to execute the test and save results to a JSON file -def execute_test(file_path): - test = Test( - power_on_test, - phase_file_attachment, - procedure_id="FVT7", - serial_number="PCB01") - - # Set output callback to save the test results as a JSON file - test.add_output_callbacks(json_factory.OutputToJSON(file_path)) - - # Execute the test with a specific device identifier - test.execute(lambda: "0001") - - -def main(): - # Specify the file path for saving test results - file_path = "./test_result.json" - execute_test(file_path) - - # Upload the test results to TofuPilot, specifying the importer type - client.create_run_from_openhtf_report(file_path) - - -if __name__ == "__main__": - main() diff --git a/qa/client/delete_run/basic/main.py b/qa/client/delete_run/basic/main.py deleted file mode 100644 index e62f1eb..0000000 --- a/qa/client/delete_run/basic/main.py +++ /dev/null @@ -1,13 +0,0 @@ -from tofupilot import TofuPilotClient - -client = TofuPilotClient() - -response = client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00102", "part_number": "PCB01"}, - run_passed=True, -) - -run_id = response.get("id") - -client.delete_run(run_id=run_id) diff --git a/qa/client/delete_unit/basic/main.py b/qa/client/delete_unit/basic/main.py deleted file mode 100644 index 11343f0..0000000 --- a/qa/client/delete_unit/basic/main.py +++ /dev/null @@ -1,15 +0,0 @@ -from tofupilot import TofuPilotClient - -client = TofuPilotClient() - -response = client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "NEW_UNIT", "part_number": "PCB01"}, - run_passed=True, -) - -run_id = response.get("id") - -client.delete_run(run_id=run_id) - -client.delete_unit(serial_number="NEW_UNIT") diff --git a/qa/client/get_runs/basic/main.py b/qa/client/get_runs/basic/main.py deleted file mode 100644 index 6480b75..0000000 --- a/qa/client/get_runs/basic/main.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Example script demonstrating how to create and then fetch a test run in TofuPilot. - -This script first creates a test run for a unit with a specified serial number and part number, -then retrieves the run data using the serial number. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -from tofupilot import TofuPilotClient - -# Initialize the TofuPilot client -client = TofuPilotClient() - -# Define the serial number of the unit under test -serial_number = "SN00102" - -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": serial_number, "part_number": "PCB01"}, - run_passed=True, -) - -# Fetch the created run using the serial number -client.get_runs(serial_number=serial_number) diff --git a/qa/client/legacy/steps/advanced/main.py b/qa/client/legacy/steps/advanced/main.py deleted file mode 100644 index 8ae17fe..0000000 --- a/qa/client/legacy/steps/advanced/main.py +++ /dev/null @@ -1,45 +0,0 @@ -from datetime import datetime, timedelta - -from tofupilot import TofuPilotClient - - -def main(): - client = TofuPilotClient() - - client.create_run( - procedure_id="FVT1", - unit_under_test={ - "serial_number": "PCB1A002", - "part_number": "PCB1", - }, - run_passed=True, - steps=[ - { - "name": "step_connect", - "step_passed": True, - "duration": timedelta(seconds=3), - "started_at": datetime.now(), - }, - { - "name": "test_firmware_version_check", - "step_passed": True, - "duration": timedelta(minutes=1, seconds=42), - "started_at": datetime.now() + timedelta(seconds=3), - "measurement_value": "v2.5.1", - }, - { - "name": "step_temp_calibration", - "step_passed": True, - "duration": timedelta(milliseconds=500), - "started_at": datetime.now() + timedelta(seconds=4), - "measurement_value": 75, - "measurement_unit": "°C", - "limit_low": 70, - "limit_high": 80, - }, - ], - ) - - -if __name__ == "__main__": - main() diff --git a/qa/client/legacy/steps/optional/main.py b/qa/client/legacy/steps/optional/main.py deleted file mode 100644 index 04b2cfa..0000000 --- a/qa/client/legacy/steps/optional/main.py +++ /dev/null @@ -1,37 +0,0 @@ -from datetime import datetime, timedelta - -from tofupilot import TofuPilotClient - - -def step_one(): - step = [ - { - "name": "step_one", - "step_passed": True, - "started_at": datetime.now(), - "duration": timedelta(seconds=30), - # Add a measurement with value, units and limits - "measurement_unit": "V", - "measurement_value": 3.3, - "limit_low": 3.1, - "limit_high": 3.5, - } - ] - return step - - -def main(): - steps = step_one() - - client = TofuPilotClient() - - client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, - steps=steps, - run_passed=all(step["step_passed"] for step in steps), - ) - - -if __name__ == "__main__": - main() diff --git a/qa/client/legacy/steps/required/main.py b/qa/client/legacy/steps/required/main.py deleted file mode 100644 index 54524d3..0000000 --- a/qa/client/legacy/steps/required/main.py +++ /dev/null @@ -1,32 +0,0 @@ -from datetime import datetime, timedelta - -from tofupilot import TofuPilotClient - - -def step_one(): - step = [ - { - "name": "step_one", - "step_passed": True, - "duration": timedelta(seconds=30), - "started_at": datetime.now(), - } - ] - return step - - -def main(): - steps = step_one() - - client = TofuPilotClient() - - client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "PCB1A001", "part_number": "PCB1"}, - steps=steps, - run_passed=all(step["step_passed"] for step in steps), - ) - - -if __name__ == "__main__": - main() diff --git a/qa/client/update_unit/basic/main.py b/qa/client/update_unit/basic/main.py deleted file mode 100644 index 9385262..0000000 --- a/qa/client/update_unit/basic/main.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Simple example showing how to add a sub-unit to an existing unit using the TofuPilotClient. - -This script assumes you already have two units with the respective serial numbers "00102" and "00103". -If the units do not exist, you can uncomment the lines to create them first. - -Ensure your API key is stored in the environment variables as per the documentation: -https://tofupilot.com/docs/user-management#api-key -""" - -from tofupilot import TofuPilotClient - -# Initialize the TofuPilot client -client = TofuPilotClient() - -# Creating units -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00102", "part_number": "PCB01"}, - run_passed=True, -) -client.create_run( - procedure_id="FVT1", - unit_under_test={"serial_number": "00103", "part_number": "PSU01"}, - run_passed=True, -) - -# Update unit "00102" by adding unit "00103" as a sub-unit -client.update_unit(serial_number="00102", - sub_units=[{"serial_number": "00103"}]) diff --git a/qa/openhtf/all_the_things/data/oscilloscope.jpeg b/qa/openhtf/all_the_things/data/oscilloscope.jpeg deleted file mode 100644 index d49014b..0000000 Binary files a/qa/openhtf/all_the_things/data/oscilloscope.jpeg and /dev/null differ diff --git a/qa/openhtf/all_the_things/main.py b/qa/openhtf/all_the_things/main.py deleted file mode 100644 index d79b503..0000000 --- a/qa/openhtf/all_the_things/main.py +++ /dev/null @@ -1,182 +0,0 @@ -import os.path -import time - -import openhtf as htf -from openhtf import util -from openhtf.output import callbacks -from openhtf.output.callbacks import console_summary, json_factory -from openhtf.util import units -from tofupilot.openhtf import TofuPilot - - -@htf.measures( - htf.Measurement("widget_type") - .matches_regex(r".*Widget$") - .doc("""This measurement tracks the type of widgets."""), - htf.Measurement("widget_color").doc("Color of the widget"), - htf.Measurement("widget_size").in_range(1, 4).doc("Size of widget"), -) -@htf.measures( - "specified_as_args", - docstring="Helpful docstring", - units=units.HERTZ, - validators=[util.validators.matches_regex("Measurement")], -) -def hello_world(test): - """A hello world test phase.""" - test.logger.info("Hello World!") - test.measurements.widget_type = "MyWidget" - test.measurements.widget_color = "Black" - test.measurements.widget_size = 3 - test.measurements.specified_as_args = "Measurement args specified directly" - - -# Timeout if this phase takes longer than 10 seconds. -@htf.PhaseOptions(timeout_s=10) -@htf.measures(*(htf.Measurement("level_%s" % i) - for i in ["none", "some", "all"])) -def set_measurements(test): - """Test phase that sets a measurement.""" - test.measurements.level_none = 0 - time.sleep(1) - test.measurements.level_some = 8 - time.sleep(1) - test.measurements.level_all = 9 - time.sleep(1) - level_all = test.get_measurement("level_all") - assert level_all.value == 9 - - -@htf.measures( - htf.Measurement("dimensions").with_dimensions(units.HERTZ), - htf.Measurement("lots_of_dims").with_dimensions( - units.HERTZ, - units.SECOND, - htf.Dimension(description="my_angle", unit=units.RADIAN), - ), -) -def dimensions(test): - """Phase with dimensioned measurements.""" - for dim in range(5): - test.measurements.dimensions[dim] = 1 << dim - for x, y, z in zip( - list( - range( - 1, 5)), list( - range( - 21, 25)), list( - range( - 101, 105))): - test.measurements.lots_of_dims[x, y, z] = x + y + z - - -@htf.measures( - htf.Measurement("replaced_min_only").in_range( - "{minimum}", 5, type=int), htf.Measurement("replaced_max_only").in_range( - 0, "{maximum}", type=int), htf.Measurement("replaced_min_max").in_range( - "{minimum}", "{maximum}", type=int), ) -def measures_with_args(test, minimum, maximum): - """Phase with measurement with arguments.""" - del minimum # Unused. - del maximum # Unused. - test.measurements.replaced_min_only = 1 - test.measurements.replaced_max_only = 1 - test.measurements.replaced_min_max = 1 - - -@htf.measures( - htf.Measurement("replaced_marginal_min_only").in_range( - 0, 10, "{marginal_minimum}", 8, type=int - ), - htf.Measurement("replaced_marginal_max_only").in_range( - 0, 10, 2, "{marginal_maximum}", type=int - ), - htf.Measurement("replaced_marginal_min_max").in_range( - 0, 10, "{marginal_minimum}", "{marginal_maximum}", type=int - ), -) -def measures_with_marginal_args(test, marginal_minimum, marginal_maximum): - """Phase with measurement with marginal arguments.""" - del marginal_minimum # Unused. - del marginal_maximum # Unused. - test.measurements.replaced_marginal_min_only = 3 - test.measurements.replaced_marginal_max_only = 3 - test.measurements.replaced_marginal_min_max = 3 - - -def attachments(test): - test.attach( - "test_attachment", - "This is test attachment data.".encode("utf-8")) - test.attach_from_file("data/oscilloscope.jpeg") - - test_attachment = test.get_attachment("test_attachment") - assert test_attachment.data == b"This is test attachment data." - - -@htf.PhaseOptions(run_if=lambda: False) -def skip_phase(): - """Don't run this phase.""" - - -def analysis(test): # pylint: disable=missing-function-docstring - level_all = test.get_measurement("level_all") - assert level_all.value == 9 - test_attachment = test.get_attachment("test_attachment") - assert test_attachment.data == b"This is test attachment data." - lots_of_dims = test.get_measurement("lots_of_dims") - assert lots_of_dims.value.value == [ - (1, 21, 101, 123), - (2, 22, 102, 126), - (3, 23, 103, 129), - (4, 24, 104, 132), - ] - test.logger.info( - "Pandas datafram of lots_of_dims \n:%s", - lots_of_dims.value.to_dataframe()) - - -def teardown(test): - test.logger.info("Running teardown") - - -def make_test(): - return htf.Test( - htf.PhaseGroup.with_teardown(teardown)( - hello_world, - set_measurements, - dimensions, - attachments, - skip_phase, - measures_with_args.with_args(minimum=1, maximum=4), - measures_with_marginal_args.with_args( - marginal_minimum=4, marginal_maximum=6 - ), - analysis, - ), - test_name="MyTest", - test_description="OpenHTF Example Test", - test_version="1.0.0", - part_number="PCB01", - ) - - -def main(): - test = make_test() - test.add_output_callbacks( - callbacks.OutputToFile( - "./{dut_id}.{metadata[test_name]}.{start_time_millis}.pickle" - ) - ) - test.add_output_callbacks( - json_factory.OutputToJSON( - "./{dut_id}.{metadata[test_name]}.{start_time_millis}.json", - indent=4)) - test.add_output_callbacks(console_summary.ConsoleSummary()) - - with TofuPilot(test): - test.execute(lambda: "00220D4K") - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/generic/data/oscilloscope.jpeg b/qa/openhtf/generic/data/oscilloscope.jpeg deleted file mode 100644 index d49014b..0000000 Binary files a/qa/openhtf/generic/data/oscilloscope.jpeg and /dev/null differ diff --git a/qa/openhtf/generic/main.py b/qa/openhtf/generic/main.py deleted file mode 100644 index a71a2de..0000000 --- a/qa/openhtf/generic/main.py +++ /dev/null @@ -1,95 +0,0 @@ -import random -import time -from datetime import datetime, timedelta -import openhtf as htf -from openhtf.util import units -from tofupilot.openhtf import TofuPilot - - -@htf.measures(htf.Measurement("firmware_version").equals("1.4.3")) -def pcba_firmware_version(test): - test.measurements.firmware_version = "1.4.3" if random.random() < 0.99 else "1.4.2" - - -@htf.measures(htf.Measurement("button_status").equals(True)) -def check_button(test): - test.measurements.button_status = random.choice([True, False]) - time.sleep(1) - - -@htf.measures(htf.Measurement("input_voltage").in_range(4.5, 5).with_units(units.VOLT)) -def test_voltage_input(test): - test.measurements.input_voltage = round(random.uniform(3.7, 4.9), 2) - - -@htf.measures( - htf.Measurement("output_voltage").in_range(3.2, 3.4).with_units(units.VOLT) -) -def test_voltage_output(test): - test.measurements.output_voltage = round(random.uniform(2.95, 3.35), 2) - - -@htf.measures( - htf.Measurement("current_protection_triggered") - .in_range(maximum=1.5) - .with_units(units.AMPERE) -) -def test_overcurrent_protection(test): - test.measurements.current_protection_triggered = round(random.uniform(1.0, 1.7), 3) - time.sleep(1) - - -def test_battery_switch(): - if random.random() < 0.9: - return htf.PhaseResult.CONTINUE - else: - return htf.PhaseResult.STOP - - -@htf.measures( - htf.Measurement("efficiency").in_range(85, 98).with_units(units.Unit("%")) -) -def test_converter_efficiency(test): - input_power = 500 - output_power = round(random.uniform(425, 480)) - test.measurements.efficiency = round(((output_power / input_power) * 100), 1) - time.sleep(1) - - -def visual_control_pcb_coating(test): - if random.random() < 0.98: - test.attach_from_file("qa/openhtf/generic/data/oscilloscope.jpeg") - return htf.PhaseResult.CONTINUE - else: - return htf.PhaseResult.STOP - - -def main(): - # Define the test plan with all steps - test = htf.Test( - pcba_firmware_version, - check_button, - test_voltage_input, - test_voltage_output, - test_overcurrent_protection, - test_battery_switch, - test_converter_efficiency, - visual_control_pcb_coating, - procedure_id="FVT1", - part_number="00220", - revision="A", - # batch_number="1024-0001", - # sub_units=[{"serial_number": "00102"}], - ) - - # Generate random Serial Number - random_digits = "".join([str(random.randint(0, 9)) for _ in range(5)]) - serial_number = f"00220B4K{random_digits}" - - # Execute the test - with TofuPilot(test): - test.execute(lambda: serial_number) - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/logger/main.py b/qa/openhtf/logger/main.py deleted file mode 100644 index aacdfd0..0000000 --- a/qa/openhtf/logger/main.py +++ /dev/null @@ -1,51 +0,0 @@ -import openhtf as htf -from tofupilot.openhtf import TofuPilot -from openhtf.output.callbacks import json_factory -import random - - -@htf.measures(htf.Measurement("button_status").equals(True)) -def phase_info_logger(test): - test.measurements.button_status = True - test.logger.info("Logging an info in the logger") - - -def phase_error_logger(test): - test.logger.error("Logging error in the logger") - return htf.PhaseResult.CONTINUE - - -def phase_warning_logger(test): - test.logger.warning("Logging a warning in the logger") - return htf.PhaseResult.CONTINUE - - -def phase_critical_logger(test): - test.logger.critical("Logging a critical in the logger") - return htf.PhaseResult.CONTINUE - - -def main(): - # Define the test plan with all steps - test = htf.Test( - phase_info_logger, - phase_error_logger, - phase_warning_logger, - phase_critical_logger, - procedure_id="FVT9", - part_number="00220D", - ) - - # Generate random Serial Number - random_digits = "".join([str(random.randint(0, 9)) for _ in range(5)]) - serial_number = f"00220D4K{random_digits}" - - test.add_output_callbacks(json_factory.OutputToJSON("test_result.json", indent=2)) - - # Execute the test - with TofuPilot(test): - test.execute(lambda: serial_number) - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/multi_dimensions/main.py b/qa/openhtf/multi_dimensions/main.py deleted file mode 100644 index caff6ce..0000000 --- a/qa/openhtf/multi_dimensions/main.py +++ /dev/null @@ -1,100 +0,0 @@ -import openhtf as htf -from openhtf.util import units -from tofupilot.openhtf import TofuPilot -from openhtf.output.callbacks import json_factory -import random -import time -import numpy as np - - -@htf.measures( - htf.Measurement("voltage").with_dimensions(units.SECOND).with_units(units.VOLT), - htf.Measurement("mean_voltage").with_units(units.VOLT).in_range(3.3, 3.5), - htf.Measurement("sinus").with_dimensions(units.SECOND).with_units(units.AMPERE), - htf.Measurement("neg_x_axis").with_dimensions(units.SECOND).with_units(units.VOLT), - htf.Measurement("neg_y_axis").with_dimensions(units.SECOND).with_units(units.VOLT), - htf.Measurement("parameters"), -) -def multi_dimension_phase(test): - len = 50 - sum_voltage = 0.0 - min_voltage = float("inf") - max_voltage = float("-inf") - for t in range(len): - voltage = round(random.uniform(3.3, 3.5), 2) - test.measurements.voltage[t] = voltage - sum_voltage += voltage - - if voltage < min_voltage: - min_voltage = voltage - if voltage > max_voltage: - max_voltage = voltage - - negative_timestamp = -t - test.measurements.neg_x_axis[negative_timestamp] = voltage - test.measurements.neg_y_axis[t] = -voltage - - test.measurements.mean_voltage = sum_voltage / len - - # metadata array - test.measurements.parameters = { - "mean_voltage": test.measurements.mean_voltage, - "min_voltage": min_voltage, - "max_voltage": max_voltage, - "duration": 345, - } - - # Sinus - x = np.linspace(0, 2 * np.pi, 100) - y = np.sin(x) - for i, amp in enumerate(y): - test.measurements.sinus[i] = amp - - -@htf.measures( - htf.Measurement("current_and_voltage_over_time") - .with_dimensions(units.SECOND, units.VOLT) - .with_units(units.AMPERE), - htf.Measurement("current_voltage_resistence_over_time") - .with_dimensions(units.SECOND, units.VOLT, units.AMPERE) - .with_units(units.OHM), -) -def power_phase(test): - for t in range(100): - timestamp = t / 100 - voltage = round(random.uniform(3.3, 3.5), 2) - current = round(random.uniform(0.3, 0.8), 3) - resistance = voltage / current - test.measurements.current_and_voltage_over_time[timestamp, voltage] = current - test.measurements.current_voltage_resistence_over_time[ - timestamp, voltage, current - ] = resistance - - -def main(): - test = htf.Test( - multi_dimension_phase, - power_phase, - procedure_id="FVT2", - part_number="00220S", - revision="B", - batch_number="1124-0001", - ) - - random_digits = "".join([str(random.randint(0, 9)) for _ in range(5)]) - serial_number = f"00220D4K{random_digits}" - - test.add_output_callbacks(json_factory.OutputToJSON("test_result.json", indent=2)) - - start = time.time() - # Execute the test - with TofuPilot(test): - test.execute(lambda: serial_number) - - end = time.time() - duration = end - start - print(f"Durée : {duration:.2f} secondes") - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/multi_measurements/main.py b/qa/openhtf/multi_measurements/main.py deleted file mode 100644 index 0e9bd41..0000000 --- a/qa/openhtf/multi_measurements/main.py +++ /dev/null @@ -1,104 +0,0 @@ -import openhtf as htf -from openhtf.util import units -from tofupilot.openhtf import TofuPilot -import random - - -@htf.measures( - htf.Measurement("firmware_version").equals("1.4.3"), - htf.Measurement("power_mode_functional").equals("on"), -) -def string_test(test): - test.measurements.firmware_version = "1.4.3" if random.random() < 0.99 else "1.4.2" - test.measurements.power_mode_functional = "on" - - -@htf.measures(htf.Measurement("button_status").equals(True)) -def boolean_test(test): - test.measurements.button_status = True - - -def phaseresult_test(): - return htf.PhaseResult.CONTINUE - - -@htf.measures( - htf.Measurement("two_limits").in_range(4.5, 5).with_units(units.VOLT), - htf.Measurement("one_limit").in_range(maximum=1.5).with_units(units.AMPERE), - htf.Measurement("percentage").in_range(85, 98).with_units(units.Unit("%")), -) -def measure_test_with_limits(test): - test.measurements.two_limits = round(random.uniform(3.8, 4.9), 2) - test.measurements.one_limit = round(random.uniform(1.0, 1.6), 3) - input_power = 500 - output_power = round(random.uniform(425, 480)) - test.measurements.percentage = round(((output_power / input_power) * 100), 1) - - -@htf.measures( - htf.Measurement("is_connected").equals(True), - htf.Measurement("firmware_version").equals("1.2.7"), - htf.Measurement("temperature").in_range(20, 25).with_units(units.DEGREE_CELSIUS), -) -def phase_multi_measurements(test): - test.measurements.is_connected = True - test.measurements.firmware_version = ( - "1.2.7" if test.measurements.is_connected else "N/A" - ) - test.measurements.temperature = round(random.uniform(22.5, 23), 2) - - -@htf.measures( - htf.Measurement("dimensions").with_dimensions(units.HERTZ), - htf.Measurement("lots_of_dims").with_dimensions( - units.HERTZ, - units.SECOND, - htf.Dimension(description="my_angle", unit=units.RADIAN), - ), -) -def dimensions(test): - """Phase with dimensioned measurements.""" - for dim in range(5): - test.measurements.dimensions[dim] = 1 << dim - for x, y, z in zip(list(range(1, 5)), list(range(21, 25)), list(range(101, 105))): - test.measurements.lots_of_dims[x, y, z] = x + y + z - - -@htf.measures( - htf.Measurement("binary_measure").equals(True), - htf.Measurement("string_measure").equals("1.2.7"), - htf.Measurement("numerical_measure") - .in_range(20, 25) - .with_units(units.DEGREE_CELSIUS), -) -def not_working_multi_measurements(test): - test.measurements.binary_measure = 42 - test.measurements.string_measure = 123 - test.measurements.numerical_measure = 35 - - -def main(): - # Define the test plan with all steps - test = htf.Test( - phase_multi_measurements, - dimensions, - string_test, - boolean_test, - phaseresult_test, - measure_test_with_limits, - not_working_multi_measurements, - procedure_id="FVT9", - part_number="00220D", - ) - - # Generate random Serial Number - random_digits = "".join([str(random.randint(0, 9)) for _ in range(5)]) - serial_number = f"00220D4K{random_digits}" - - # Execute the test - with TofuPilot(test): - test.execute(lambda: serial_number) - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/procedure_version/main.py b/qa/openhtf/procedure_version/main.py deleted file mode 100644 index e215db2..0000000 --- a/qa/openhtf/procedure_version/main.py +++ /dev/null @@ -1,29 +0,0 @@ -import random -import openhtf as htf -from tofupilot.openhtf import TofuPilot - - -@htf.measures(htf.Measurement("button_status").equals(True)) -def check_button(test): - test.measurements.button_status = bool(random.randint(0, 1)) - - -def main(): - test = htf.Test( - check_button, - procedure_id="FVT1", # No need to specify the ID - procedure_version="1.2.20", # Create procedure version - part_number="00220", - revision="B", - ) - - # Generate random Serial Number - serial_number = f"00220B4K{random.randint(10000, 99999)}" - - # Execute the test - with TofuPilot(test, stream=False): - test.execute(lambda: serial_number) - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/regex_serial_number/main.py b/qa/openhtf/regex_serial_number/main.py deleted file mode 100644 index 971a9ba..0000000 --- a/qa/openhtf/regex_serial_number/main.py +++ /dev/null @@ -1,24 +0,0 @@ -import random -import openhtf as htf -from tofupilot.openhtf import TofuPilot - - -@htf.measures(htf.Measurement("button_status").equals(True)) -def check_button(test): - test.measurements.button_status = bool(random.randint(0, 1)) - - -def main(): - test = htf.Test( - check_button, - procedure_id="FVT1", - # REGEX is defined in the Settings from Serial Number for: - # part_number="PCB01", - ) - - with TofuPilot(test): - test.execute(lambda: "PCB01A123") - - -if __name__ == "__main__": - main() diff --git a/qa/openhtf/without_streaming/data/oscilloscope.jpeg b/qa/openhtf/without_streaming/data/oscilloscope.jpeg deleted file mode 100644 index d49014b..0000000 Binary files a/qa/openhtf/without_streaming/data/oscilloscope.jpeg and /dev/null differ diff --git a/qa/openhtf/without_streaming/main.py b/qa/openhtf/without_streaming/main.py deleted file mode 100644 index 1ee0488..0000000 --- a/qa/openhtf/without_streaming/main.py +++ /dev/null @@ -1,182 +0,0 @@ -import os.path -import time - -import openhtf as htf -from openhtf import util -from openhtf.output import callbacks -from openhtf.output.callbacks import console_summary, json_factory -from openhtf.util import units -from tofupilot.openhtf import TofuPilot - - -@htf.measures( - htf.Measurement("widget_type") - .matches_regex(r".*Widget$") - .doc("""This measurement tracks the type of widgets."""), - htf.Measurement("widget_color").doc("Color of the widget"), - htf.Measurement("widget_size").in_range(1, 4).doc("Size of widget"), -) -@htf.measures( - "specified_as_args", - docstring="Helpful docstring", - units=units.HERTZ, - validators=[util.validators.matches_regex("Measurement")], -) -def hello_world(test): - """A hello world test phase.""" - test.logger.info("Hello World!") - test.measurements.widget_type = "MyWidget" - test.measurements.widget_color = "Black" - test.measurements.widget_size = 3 - test.measurements.specified_as_args = "Measurement args specified directly" - - -# Timeout if this phase takes longer than 10 seconds. -@htf.PhaseOptions(timeout_s=10) -@htf.measures(*(htf.Measurement("level_%s" % i) - for i in ["none", "some", "all"])) -def set_measurements(test): - """Test phase that sets a measurement.""" - test.measurements.level_none = 0 - time.sleep(1) - test.measurements.level_some = 8 - time.sleep(1) - test.measurements.level_all = 9 - time.sleep(1) - level_all = test.get_measurement("level_all") - assert level_all.value == 9 - - -@htf.measures( - htf.Measurement("dimensions").with_dimensions(units.HERTZ), - htf.Measurement("lots_of_dims").with_dimensions( - units.HERTZ, - units.SECOND, - htf.Dimension(description="my_angle", unit=units.RADIAN), - ), -) -def dimensions(test): - """Phase with dimensioned measurements.""" - for dim in range(5): - test.measurements.dimensions[dim] = 1 << dim - for x, y, z in zip( - list( - range( - 1, 5)), list( - range( - 21, 25)), list( - range( - 101, 105))): - test.measurements.lots_of_dims[x, y, z] = x + y + z - - -@htf.measures( - htf.Measurement("replaced_min_only").in_range( - "{minimum}", 5, type=int), htf.Measurement("replaced_max_only").in_range( - 0, "{maximum}", type=int), htf.Measurement("replaced_min_max").in_range( - "{minimum}", "{maximum}", type=int), ) -def measures_with_args(test, minimum, maximum): - """Phase with measurement with arguments.""" - del minimum # Unused. - del maximum # Unused. - test.measurements.replaced_min_only = 1 - test.measurements.replaced_max_only = 1 - test.measurements.replaced_min_max = 1 - - -@htf.measures( - htf.Measurement("replaced_marginal_min_only").in_range( - 0, 10, "{marginal_minimum}", 8, type=int - ), - htf.Measurement("replaced_marginal_max_only").in_range( - 0, 10, 2, "{marginal_maximum}", type=int - ), - htf.Measurement("replaced_marginal_min_max").in_range( - 0, 10, "{marginal_minimum}", "{marginal_maximum}", type=int - ), -) -def measures_with_marginal_args(test, marginal_minimum, marginal_maximum): - """Phase with measurement with marginal arguments.""" - del marginal_minimum # Unused. - del marginal_maximum # Unused. - test.measurements.replaced_marginal_min_only = 3 - test.measurements.replaced_marginal_max_only = 3 - test.measurements.replaced_marginal_min_max = 3 - - -def attachments(test): - test.attach( - "test_attachment", - "This is test attachment data.".encode("utf-8")) - test.attach_from_file("data/oscilloscope.jpeg") - - test_attachment = test.get_attachment("test_attachment") - assert test_attachment.data == b"This is test attachment data." - - -@htf.PhaseOptions(run_if=lambda: False) -def skip_phase(): - """Don't run this phase.""" - - -def analysis(test): # pylint: disable=missing-function-docstring - level_all = test.get_measurement("level_all") - assert level_all.value == 9 - test_attachment = test.get_attachment("test_attachment") - assert test_attachment.data == b"This is test attachment data." - lots_of_dims = test.get_measurement("lots_of_dims") - assert lots_of_dims.value.value == [ - (1, 21, 101, 123), - (2, 22, 102, 126), - (3, 23, 103, 129), - (4, 24, 104, 132), - ] - test.logger.info( - "Pandas datafram of lots_of_dims \n:%s", - lots_of_dims.value.to_dataframe()) - - -def teardown(test): - test.logger.info("Running teardown") - - -def make_test(): - return htf.Test( - htf.PhaseGroup.with_teardown(teardown)( - hello_world, - set_measurements, - dimensions, - attachments, - skip_phase, - measures_with_args.with_args(minimum=1, maximum=4), - measures_with_marginal_args.with_args( - marginal_minimum=4, marginal_maximum=6 - ), - analysis, - ), - test_name="MyTest", - test_description="OpenHTF Example Test", - test_version="1.0.0", - part_number="PCB01", - ) - - -def main(): - test = make_test() - test.add_output_callbacks( - callbacks.OutputToFile( - "./{dut_id}.{metadata[test_name]}.{start_time_millis}.pickle" - ) - ) - test.add_output_callbacks( - json_factory.OutputToJSON( - "./{dut_id}.{metadata[test_name]}.{start_time_millis}.json", - indent=4)) - test.add_output_callbacks(console_summary.ConsoleSummary()) - - with TofuPilot(test, stream=False): - test.execute(lambda: "00220D4K") - - -if __name__ == "__main__": - main() diff --git a/requirements.txt b/requirements.txt index a3b2c32..50b3d42 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ openhtf six tofupilot -numpy \ No newline at end of file +numpy +paho-mqtt \ No newline at end of file diff --git a/welcome_aboard/battery_testing/data/pcb_coating.jpeg b/welcome_aboard/battery_testing/data/pcb_coating.jpeg deleted file mode 100644 index 5837497..0000000 Binary files a/welcome_aboard/battery_testing/data/pcb_coating.jpeg and /dev/null differ