labpulse 0.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- labpulse-0.3.6/.dockerignore +4 -0
- labpulse-0.3.6/.gitattributes +3 -0
- labpulse-0.3.6/.github/workflows/release.yml +170 -0
- labpulse-0.3.6/.github/workflows/test.yml +32 -0
- labpulse-0.3.6/.gitignore +18 -0
- labpulse-0.3.6/.vscode/launch.json +7 -0
- labpulse-0.3.6/.vscode/settings.json +4 -0
- labpulse-0.3.6/.vscode/tasks.json +29 -0
- labpulse-0.3.6/CHANGELOG.md +100 -0
- labpulse-0.3.6/CITATION.cff +11 -0
- labpulse-0.3.6/CONTRIBUTING.md +108 -0
- labpulse-0.3.6/Dockerfile +23 -0
- labpulse-0.3.6/LICENSE +21 -0
- labpulse-0.3.6/PKG-INFO +228 -0
- labpulse-0.3.6/README.md +188 -0
- labpulse-0.3.6/ROADMAP.md +433 -0
- labpulse-0.3.6/SECURITY.md +40 -0
- labpulse-0.3.6/config.d/triton-01-measurements.yaml +14 -0
- labpulse-0.3.6/config.d/triton-02-measurements.yaml +14 -0
- labpulse-0.3.6/config.yaml +354 -0
- labpulse-0.3.6/deployment/README.md +49 -0
- labpulse-0.3.6/deployment/edit_config.sh +277 -0
- labpulse-0.3.6/deployment/generate_compose.sh +75 -0
- labpulse-0.3.6/deployment/generate_homeassistant_config.sh +106 -0
- labpulse-0.3.6/deployment/setup_container_fs.sh +345 -0
- labpulse-0.3.6/docs/ARCHITECTURE.md +607 -0
- labpulse-0.3.6/docs/CONFIGURATION.md +979 -0
- labpulse-0.3.6/docs/DEVELOPMENT.md +417 -0
- labpulse-0.3.6/docs/HARDWARE.md +75 -0
- labpulse-0.3.6/docs/INSTALLATION.md +772 -0
- labpulse-0.3.6/docs/Internship purchased items.xlsx +0 -0
- labpulse-0.3.6/docs/LabPulse Sensors.xlsx +0 -0
- labpulse-0.3.6/docs/Mini Shopping List.xlsx +0 -0
- labpulse-0.3.6/docs/OPERATIONS.md +64 -0
- labpulse-0.3.6/docs/README.md +72 -0
- labpulse-0.3.6/docs/TRITON_PUBLISHER.md +1187 -0
- labpulse-0.3.6/docs/TROUBLESHOOTING.md +95 -0
- labpulse-0.3.6/docs/USER_GUIDE.md +574 -0
- labpulse-0.3.6/docs/examples/calculated-measurement.yaml +43 -0
- labpulse-0.3.6/docs/examples/driver_template.py +79 -0
- labpulse-0.3.6/docs/examples/minimal-serial.yaml +20 -0
- labpulse-0.3.6/docs/examples/mqtt-input.yaml +27 -0
- labpulse-0.3.6/docs/images/labpulse-overview.png +0 -0
- labpulse-0.3.6/docs/~$Internship purchased items.xlsx +0 -0
- labpulse-0.3.6/firmware/README.md +345 -0
- labpulse-0.3.6/firmware/examples/pressure_monitor/pressure_monitor.cpp +40 -0
- labpulse-0.3.6/firmware/examples/pressure_monitor/pressure_monitor.h +58 -0
- labpulse-0.3.6/firmware/examples/pressure_monitor/pressure_monitor.ino +9 -0
- labpulse-0.3.6/firmware/examples/pump_room/pump_room.cpp +100 -0
- labpulse-0.3.6/firmware/examples/pump_room/pump_room.h +80 -0
- labpulse-0.3.6/firmware/examples/pump_room/pump_room.ino +9 -0
- labpulse-0.3.6/firmware/examples/turbo_pump/turbo_pump.cpp +82 -0
- labpulse-0.3.6/firmware/examples/turbo_pump/turbo_pump.h +50 -0
- labpulse-0.3.6/firmware/examples/turbo_pump/turbo_pump.ino +9 -0
- labpulse-0.3.6/firmware/library.properties +10 -0
- labpulse-0.3.6/firmware/run_triton_publisher.example.ps1 +28 -0
- labpulse-0.3.6/firmware/src/Dht11Sensor.cpp +36 -0
- labpulse-0.3.6/firmware/src/Dht11Sensor.h +39 -0
- labpulse-0.3.6/firmware/src/LinearPressureSensor.cpp +44 -0
- labpulse-0.3.6/firmware/src/LinearPressureSensor.h +38 -0
- labpulse-0.3.6/firmware/src/PinMeasurement.h +17 -0
- labpulse-0.3.6/firmware/src/PipeSampleWriter.cpp +56 -0
- labpulse-0.3.6/firmware/src/PipeSampleWriter.h +31 -0
- labpulse-0.3.6/firmware/src/PulseFlowSensor.cpp +57 -0
- labpulse-0.3.6/firmware/src/PulseFlowSensor.h +43 -0
- labpulse-0.3.6/firmware/src/Reading.h +13 -0
- labpulse-0.3.6/firmware/src/Sht40Sensor.cpp +56 -0
- labpulse-0.3.6/firmware/src/Sht40Sensor.h +38 -0
- labpulse-0.3.6/firmware/src/ThermistorSensor.cpp +45 -0
- labpulse-0.3.6/firmware/src/ThermistorSensor.h +37 -0
- labpulse-0.3.6/firmware/triton_logfile_publisher_production.py +381 -0
- labpulse-0.3.6/firmware/triton_logfile_publisher_setup.py +208 -0
- labpulse-0.3.6/hardware/3d_parts/README.txt +12 -0
- labpulse-0.3.6/hardware/3d_parts/RPi 4 cover holes.stl +0 -0
- labpulse-0.3.6/hardware/3d_parts/Tall boi With hole!.stl +1 -0
- labpulse-0.3.6/hardware/PCB_files/Gerber_PCB_Arduino-Hat_Final_prototype.zip +0 -0
- labpulse-0.3.6/hardware/PCB_files/Gerber_PCB_Arduino-Hat_prototype1.zip +0 -0
- labpulse-0.3.6/hardware/PCB_files/Gerber_PCB_Arduino-Hat_prototype2_2025-11-14.zip +0 -0
- labpulse-0.3.6/hardware/PCB_files/Gerber_PCB_Arduino-Hat_prototype3.zip +0 -0
- labpulse-0.3.6/hardware/PCB_files/PCBv6.zip +0 -0
- labpulse-0.3.6/legacy/Arduino/Compressed Air sensor/Arduino instructions for CA sensor.cpp +51 -0
- labpulse-0.3.6/legacy/Arduino/Compressed Air sensor/Calibration code for CA sensor.cpp +25 -0
- labpulse-0.3.6/legacy/Arduino/Compressed Air sensor/pressurepub.py +50 -0
- labpulse-0.3.6/legacy/Arduino/DHT sensor code/Arduino Instructions for TH sensor.cpp +32 -0
- labpulse-0.3.6/legacy/Arduino/DHT sensor code/TH_sensor_code.cpp +140 -0
- labpulse-0.3.6/legacy/Arduino/DHT sensor code/TH_sensor_code.h +48 -0
- labpulse-0.3.6/legacy/Arduino/Pressure_Arduino.cpp +20 -0
- labpulse-0.3.6/legacy/Arduino/Pump_Room_Arduino.cpp +125 -0
- labpulse-0.3.6/legacy/Arduino/Water Temp sensor code/Arduino Instructions for WT sensor.cpp +51 -0
- labpulse-0.3.6/legacy/Arduino/Water flow meter code/Arduino Instructions.cpp +118 -0
- labpulse-0.3.6/legacy/Arduino/Water flow meter code/Temporary flow reader.cpp +41 -0
- labpulse-0.3.6/legacy/Arduino/Water flow meter code/WT_and_WF_sensor_code_for_P_sensor.cpp +53 -0
- labpulse-0.3.6/legacy/Arduino/Water flow meter code/flowpub.py +55 -0
- labpulse-0.3.6/legacy/Arduino/full_water_sensor_code.cpp +155 -0
- labpulse-0.3.6/legacy/Arduino/pressure_monitor/README.md +6 -0
- labpulse-0.3.6/legacy/Arduino/pressure_monitor/pressure_monitor.cpp +30 -0
- labpulse-0.3.6/legacy/Arduino/pressure_monitor/pressure_monitor.h +40 -0
- labpulse-0.3.6/legacy/Arduino/pressure_monitor/pressure_monitor.ino +9 -0
- labpulse-0.3.6/legacy/Arduino code Water Temperature Sensor calibration.py +90 -0
- labpulse-0.3.6/legacy/Documentation/Internship purchased items.xlsx +0 -0
- labpulse-0.3.6/legacy/Documentation/LabPulse cartoon-03.png +0 -0
- labpulse-0.3.6/legacy/Documentation/PROJECT_REVIEW.md +99 -0
- labpulse-0.3.6/legacy/Documentation/Setup of a lab monitor on a raspberry pi.docx +0 -0
- labpulse-0.3.6/legacy/Future_work/README_FW.md +40 -0
- labpulse-0.3.6/legacy/Future_work/drivers/serial_driver.py +72 -0
- labpulse-0.3.6/legacy/Future_work/generalised_architecture.md +51 -0
- labpulse-0.3.6/legacy/Future_work/main.py +114 -0
- labpulse-0.3.6/legacy/Future_work/sensor_base.py +43 -0
- labpulse-0.3.6/legacy/Future_work/sensor_factory.py +50 -0
- labpulse-0.3.6/legacy/Future_work/update_config.py +88 -0
- labpulse-0.3.6/legacy/Future_work/update_config.yaml +61 -0
- labpulse-0.3.6/legacy/Installation/COMPATIBILITY.md +15 -0
- labpulse-0.3.6/legacy/Installation/QUICKSTART.md +25 -0
- labpulse-0.3.6/legacy/Installation/bootstap_pi.sh +29 -0
- labpulse-0.3.6/legacy/Installation/setup.sh +113 -0
- labpulse-0.3.6/legacy/LEGACY README.md +60 -0
- labpulse-0.3.6/legacy/Set_up_flowchart.pdf +0 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Config files and scripts/Discoverycleaner.py +64 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Config files and scripts/modem-watchdog.sh +28 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Config files and scripts/phone_number_config.json +9 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Config files and scripts/phone_number_edit.py +75 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Config files and scripts/threshold_config_file.json +49 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/General error detection code/Multiple_sensor changes.py +21 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/General error detection code/Single_sensor_long_term_changes.py +35 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/General error detection code/Upper_lower_limits.py +13 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/General error detection code/WT and flow sensor error detection.py +20 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Python publishing scripts/DHT_publishing_code.py +100 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Python publishing scripts/UPS_Monitoring_code.py +360 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Python publishing scripts/pressure_pub.py +266 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Python publishing scripts/water_sensor.py +302 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Service Scripts/dhtpub.service +15 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Service Scripts/power_monitor.service +14 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Service Scripts/pressure_monitor.service +14 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Service Scripts/pump_room_monitor.service +14 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/Service Scripts/turbo_pump_monitor.service +14 -0
- labpulse-0.3.6/legacy/archive_v1_pi_code/setup_homeassistant_313.sh +65 -0
- labpulse-0.3.6/legacy/pi_scripts/config.yaml +49 -0
- labpulse-0.3.6/legacy/pi_scripts/dhtpub.py +104 -0
- labpulse-0.3.6/legacy/pi_scripts/labpulse_common/__init__.py +0 -0
- labpulse-0.3.6/legacy/pi_scripts/labpulse_common/config.py +101 -0
- labpulse-0.3.6/legacy/pi_scripts/labpulse_common/mqtt_health.py +39 -0
- labpulse-0.3.6/legacy/pi_scripts/labpulse_common/sms.py +96 -0
- labpulse-0.3.6/legacy/pi_scripts/labpulse_common/utils.py +6 -0
- labpulse-0.3.6/legacy/pi_scripts/powerpub.py +173 -0
- labpulse-0.3.6/legacy/pi_scripts/pressurepub.py +182 -0
- labpulse-0.3.6/legacy/pi_scripts/pumproompub.py +192 -0
- labpulse-0.3.6/legacy/pi_scripts/pyproject.toml +57 -0
- labpulse-0.3.6/legacy/pi_scripts/requirements.txt +22 -0
- labpulse-0.3.6/legacy/pi_scripts/setup.sh +137 -0
- labpulse-0.3.6/legacy/pi_scripts/smstest.py +76 -0
- labpulse-0.3.6/legacy/pi_scripts/thresholds.json +52 -0
- labpulse-0.3.6/legacy/pi_scripts/turbo_pump_monitor.py +188 -0
- labpulse-0.3.6/pyproject.toml +109 -0
- labpulse-0.3.6/requirements-host.txt +6 -0
- labpulse-0.3.6/setup.cfg +4 -0
- labpulse-0.3.6/setup_usb_devices.py +315 -0
- labpulse-0.3.6/simulate_serial.py +744 -0
- labpulse-0.3.6/src/labpulse/README.md +35 -0
- labpulse-0.3.6/src/labpulse/__init__.py +9 -0
- labpulse-0.3.6/src/labpulse/backup.py +524 -0
- labpulse-0.3.6/src/labpulse/common/README.md +32 -0
- labpulse-0.3.6/src/labpulse/common/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/common/config.py +620 -0
- labpulse-0.3.6/src/labpulse/common/fake_config.py +11 -0
- labpulse-0.3.6/src/labpulse/common/generated_files.py +27 -0
- labpulse-0.3.6/src/labpulse/common/identity.py +32 -0
- labpulse-0.3.6/src/labpulse/common/logging_config.py +58 -0
- labpulse-0.3.6/src/labpulse/common/measurement_config.py +330 -0
- labpulse-0.3.6/src/labpulse/common/mqtt_contracts.py +89 -0
- labpulse-0.3.6/src/labpulse/common/output_config.py +52 -0
- labpulse-0.3.6/src/labpulse/common/service_config.py +199 -0
- labpulse-0.3.6/src/labpulse/common/sms_templates.py +76 -0
- labpulse-0.3.6/src/labpulse/common/sms_templates.yaml +73 -0
- labpulse-0.3.6/src/labpulse/control.py +1007 -0
- labpulse-0.3.6/src/labpulse/deployment/README.md +24 -0
- labpulse-0.3.6/src/labpulse/deployment/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/deployment/__main__.py +7 -0
- labpulse-0.3.6/src/labpulse/deployment/compose.py +197 -0
- labpulse-0.3.6/src/labpulse/deployment/generate.py +225 -0
- labpulse-0.3.6/src/labpulse/deployment/mosquitto.py +60 -0
- labpulse-0.3.6/src/labpulse/doctor.py +635 -0
- labpulse-0.3.6/src/labpulse/hardware/README.md +31 -0
- labpulse-0.3.6/src/labpulse/hardware/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/hardware/__main__.py +93 -0
- labpulse-0.3.6/src/labpulse/hardware/_simulation.py +140 -0
- labpulse-0.3.6/src/labpulse/hardware/driver.py +166 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/README.md +38 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/_gpio.py +44 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/dht11.py +118 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/gpio_input.py +118 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/gpio_output.py +163 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/mqtt_json.py +404 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/serial_pipe.py +145 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/sht40.py +170 -0
- labpulse-0.3.6/src/labpulse/hardware/drivers/x1200.py +180 -0
- labpulse-0.3.6/src/labpulse/hardware/homeassistant_publisher.py +224 -0
- labpulse-0.3.6/src/labpulse/hardware/registry.py +40 -0
- labpulse-0.3.6/src/labpulse/hardware/runner.py +338 -0
- labpulse-0.3.6/src/labpulse/homeassistant/README.md +30 -0
- labpulse-0.3.6/src/labpulse/homeassistant/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/homeassistant/__main__.py +7 -0
- labpulse-0.3.6/src/labpulse/homeassistant/alarm.py +653 -0
- labpulse-0.3.6/src/labpulse/homeassistant/generator.py +143 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/README.md +32 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/alarm_package.yaml.j2 +15 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/installation.yaml.j2 +31 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/measurement.yaml.j2 +4 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/measurement_missing_reading.yaml.j2 +148 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/measurement_state.yaml.j2 +167 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/power.yaml.j2 +6 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/power_state.yaml.j2 +142 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/automations/service_health.yaml.j2 +134 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/derived_entities.yaml.j2 +191 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/helpers.yaml.j2 +236 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/alarm/scripts.yaml.j2 +263 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/configuration.yaml.j2 +54 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/alarm_setup/bulk_editor.yaml.j2 +204 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/alarm_setup/notification_controls.yaml.j2 +30 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/alarm_setup/targets.yaml.j2 +102 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/alarm_setup.yaml.j2 +11 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/custom_dashboards.yaml.j2 +18 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/monitor.yaml.j2 +83 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/monitor_status.yaml.j2 +135 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/power_subviews.yaml.j2 +40 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/setup_measurements.yaml.j2 +38 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/setup_subviews/measurement_cards.yaml.j2 +329 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/setup_subviews/setup_header.yaml.j2 +73 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/setup_subviews.yaml.j2 +14 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard/system_status.yaml.j2 +151 -0
- labpulse-0.3.6/src/labpulse/homeassistant/templates/dashboard.yaml.j2 +12 -0
- labpulse-0.3.6/src/labpulse/installer.py +71 -0
- labpulse-0.3.6/src/labpulse/output/README.md +24 -0
- labpulse-0.3.6/src/labpulse/output/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/output/__main__.py +80 -0
- labpulse-0.3.6/src/labpulse/output/service.py +323 -0
- labpulse-0.3.6/src/labpulse/sms/README.md +28 -0
- labpulse-0.3.6/src/labpulse/sms/__init__.py +1 -0
- labpulse-0.3.6/src/labpulse/sms/__main__.py +76 -0
- labpulse-0.3.6/src/labpulse/sms/sender.py +545 -0
- labpulse-0.3.6/src/labpulse/sms/subscriber.py +295 -0
- labpulse-0.3.6/src/labpulse.egg-info/PKG-INFO +228 -0
- labpulse-0.3.6/src/labpulse.egg-info/SOURCES.txt +292 -0
- labpulse-0.3.6/src/labpulse.egg-info/dependency_links.txt +1 -0
- labpulse-0.3.6/src/labpulse.egg-info/entry_points.txt +10 -0
- labpulse-0.3.6/src/labpulse.egg-info/requires.txt +22 -0
- labpulse-0.3.6/src/labpulse.egg-info/scm_file_list.json +288 -0
- labpulse-0.3.6/src/labpulse.egg-info/scm_version.json +8 -0
- labpulse-0.3.6/src/labpulse.egg-info/top_level.txt +1 -0
- labpulse-0.3.6/testing/README.md +33 -0
- labpulse-0.3.6/testing/conftest.py +29 -0
- labpulse-0.3.6/testing/real_hardware/README.md +17 -0
- labpulse-0.3.6/testing/real_hardware/hardware_fault_common.sh +121 -0
- labpulse-0.3.6/testing/real_hardware/test_dht11_fault.sh +143 -0
- labpulse-0.3.6/testing/real_hardware/test_x1200_faults.sh +161 -0
- labpulse-0.3.6/testing/test_backup_restore.py +377 -0
- labpulse-0.3.6/testing/test_common_contracts.py +280 -0
- labpulse-0.3.6/testing/test_config_editor_bundle.py +250 -0
- labpulse-0.3.6/testing/test_config_pipeline.py +216 -0
- labpulse-0.3.6/testing/test_container_release.py +64 -0
- labpulse-0.3.6/testing/test_control_cli.py +857 -0
- labpulse-0.3.6/testing/test_custom_measurements.py +216 -0
- labpulse-0.3.6/testing/test_deployment_generation.py +602 -0
- labpulse-0.3.6/testing/test_dht11_driver.py +192 -0
- labpulse-0.3.6/testing/test_doctor.py +309 -0
- labpulse-0.3.6/testing/test_documentation.py +140 -0
- labpulse-0.3.6/testing/test_fake_hardware.py +69 -0
- labpulse-0.3.6/testing/test_firmware_layout.py +139 -0
- labpulse-0.3.6/testing/test_gpio_input_driver.py +131 -0
- labpulse-0.3.6/testing/test_gpio_output_driver.py +200 -0
- labpulse-0.3.6/testing/test_hardware_factory.py +274 -0
- labpulse-0.3.6/testing/test_hardware_runner.py +419 -0
- labpulse-0.3.6/testing/test_homeassistant_entities.py +83 -0
- labpulse-0.3.6/testing/test_homeassistant_generator.py +521 -0
- labpulse-0.3.6/testing/test_homeassistant_publisher.py +449 -0
- labpulse-0.3.6/testing/test_logging_config.py +61 -0
- labpulse-0.3.6/testing/test_measurement_files.py +320 -0
- labpulse-0.3.6/testing/test_mqtt_json_driver.py +546 -0
- labpulse-0.3.6/testing/test_notification_context.py +266 -0
- labpulse-0.3.6/testing/test_output_mqtt_service.py +509 -0
- labpulse-0.3.6/testing/test_packaging.py +108 -0
- labpulse-0.3.6/testing/test_power_monitor.py +300 -0
- labpulse-0.3.6/testing/test_serial_driver.py +161 -0
- labpulse-0.3.6/testing/test_serial_parser.py +68 -0
- labpulse-0.3.6/testing/test_setup_grouping.py +285 -0
- labpulse-0.3.6/testing/test_sht40_driver.py +253 -0
- labpulse-0.3.6/testing/test_simulate_serial.py +227 -0
- labpulse-0.3.6/testing/test_sms_container.py +776 -0
- labpulse-0.3.6/testing/test_triton_logfile_decoder.py +330 -0
- labpulse-0.3.6/testing/test_unified_generation.py +125 -0
- labpulse-0.3.6/testing/test_usb_setup.py +236 -0
- labpulse-0.3.6/testing/test_x1200_ups_driver.py +199 -0
- labpulse-0.3.6/testing/test_yaml_dashboard.py +639 -0
- labpulse-0.3.6/testing/ups_test_pi_config.yaml +43 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
name: Release LabPulse
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
validate:
|
|
9
|
+
name: Validate release artifacts
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
outputs:
|
|
12
|
+
version: ${{ steps.version.outputs.version }}
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check out source
|
|
15
|
+
uses: actions/checkout@v6
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
ref: ${{ github.event.release.tag_name }}
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
cache: pip
|
|
25
|
+
|
|
26
|
+
- name: Install build tools
|
|
27
|
+
run: python -m pip install --upgrade pip build twine setuptools-scm
|
|
28
|
+
|
|
29
|
+
- name: Resolve release version from tag
|
|
30
|
+
id: version
|
|
31
|
+
env:
|
|
32
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
33
|
+
run: |
|
|
34
|
+
version="${RELEASE_TAG#v}"
|
|
35
|
+
scm_version="$(python -m setuptools_scm)"
|
|
36
|
+
if [ "$scm_version" != "$version" ]; then
|
|
37
|
+
echo "Release tag $RELEASE_TAG produced package version $scm_version, expected $version" >&2
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
echo "Release tag determines package version $scm_version"
|
|
41
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
42
|
+
|
|
43
|
+
- name: Install LabPulse
|
|
44
|
+
run: python -m pip install --editable ".[dev]"
|
|
45
|
+
|
|
46
|
+
- name: Run hardware-free tests
|
|
47
|
+
run: python -m pytest
|
|
48
|
+
|
|
49
|
+
- name: Build and check distributions
|
|
50
|
+
run: |
|
|
51
|
+
python -m build
|
|
52
|
+
python -m twine check dist/*
|
|
53
|
+
|
|
54
|
+
- name: Smoke-test installed wheel and source distribution
|
|
55
|
+
run: |
|
|
56
|
+
python -m venv "$RUNNER_TEMP/wheel-smoke"
|
|
57
|
+
"$RUNNER_TEMP/wheel-smoke/bin/python" -m pip install dist/*.whl
|
|
58
|
+
"$RUNNER_TEMP/wheel-smoke/bin/labpulse" help
|
|
59
|
+
"$RUNNER_TEMP/wheel-smoke/bin/python" -c "from labpulse.installer import find_install_assets; print(find_install_assets())"
|
|
60
|
+
"$RUNNER_TEMP/wheel-smoke/bin/labpulse" \
|
|
61
|
+
--live-dir "$RUNNER_TEMP/labpulse-live" setup --fake-hardware
|
|
62
|
+
"$RUNNER_TEMP/wheel-smoke/bin/python" -c "import sys, yaml; data = yaml.safe_load(open(sys.argv[1])); images = {service.get('image') for name, service in data['services'].items() if name.startswith('labpulse-')}; expected = {'ghcr.io/lairdgrouplancaster/labpulse:${{ steps.version.outputs.version }}'}; assert images == expected, (images, expected)" "$RUNNER_TEMP/labpulse-live/compose.yaml"
|
|
63
|
+
test ! -d "$RUNNER_TEMP/labpulse-live/labpulse-python"
|
|
64
|
+
python -m venv "$RUNNER_TEMP/sdist-smoke"
|
|
65
|
+
"$RUNNER_TEMP/sdist-smoke/bin/python" -m pip install dist/*.tar.gz
|
|
66
|
+
"$RUNNER_TEMP/sdist-smoke/bin/labpulse" help
|
|
67
|
+
|
|
68
|
+
- name: Smoke-test container
|
|
69
|
+
run: |
|
|
70
|
+
docker build \
|
|
71
|
+
--build-arg "LABPULSE_VERSION=${{ steps.version.outputs.version }}" \
|
|
72
|
+
--tag labpulse-release-smoke \
|
|
73
|
+
.
|
|
74
|
+
docker run --rm labpulse-release-smoke \
|
|
75
|
+
python -c "from importlib.metadata import version; assert version('labpulse') == '${{ steps.version.outputs.version }}'"
|
|
76
|
+
docker run --rm labpulse-release-smoke python -m labpulse.hardware --help
|
|
77
|
+
docker run --rm labpulse-release-smoke python -m labpulse.sms --help
|
|
78
|
+
|
|
79
|
+
- name: Upload distributions
|
|
80
|
+
uses: actions/upload-artifact@v7
|
|
81
|
+
with:
|
|
82
|
+
name: python-distributions
|
|
83
|
+
path: dist/
|
|
84
|
+
if-no-files-found: error
|
|
85
|
+
retention-days: 7
|
|
86
|
+
|
|
87
|
+
publish-python:
|
|
88
|
+
name: Publish Python distributions to PyPI
|
|
89
|
+
needs: validate
|
|
90
|
+
runs-on: ubuntu-latest
|
|
91
|
+
environment:
|
|
92
|
+
name: pypi
|
|
93
|
+
url: https://pypi.org/project/labpulse/${{ needs.validate.outputs.version }}/
|
|
94
|
+
permissions:
|
|
95
|
+
id-token: write
|
|
96
|
+
steps:
|
|
97
|
+
- name: Download distributions
|
|
98
|
+
uses: actions/download-artifact@v8
|
|
99
|
+
with:
|
|
100
|
+
name: python-distributions
|
|
101
|
+
path: dist/
|
|
102
|
+
|
|
103
|
+
- name: Publish to PyPI
|
|
104
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
105
|
+
|
|
106
|
+
publish-container:
|
|
107
|
+
name: Publish multi-platform container
|
|
108
|
+
needs: validate
|
|
109
|
+
runs-on: ubuntu-latest
|
|
110
|
+
permissions:
|
|
111
|
+
contents: read
|
|
112
|
+
packages: write
|
|
113
|
+
attestations: write
|
|
114
|
+
id-token: write
|
|
115
|
+
steps:
|
|
116
|
+
- name: Check out source
|
|
117
|
+
uses: actions/checkout@v6
|
|
118
|
+
|
|
119
|
+
- name: Download distributions
|
|
120
|
+
uses: actions/download-artifact@v8
|
|
121
|
+
with:
|
|
122
|
+
name: python-distributions
|
|
123
|
+
path: dist/
|
|
124
|
+
|
|
125
|
+
- name: Set up QEMU
|
|
126
|
+
uses: docker/setup-qemu-action@v3
|
|
127
|
+
|
|
128
|
+
- name: Set up Docker Buildx
|
|
129
|
+
uses: docker/setup-buildx-action@v3
|
|
130
|
+
|
|
131
|
+
- name: Log in to GHCR
|
|
132
|
+
uses: docker/login-action@v3
|
|
133
|
+
with:
|
|
134
|
+
registry: ghcr.io
|
|
135
|
+
username: ${{ github.actor }}
|
|
136
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
137
|
+
|
|
138
|
+
- name: Generate image metadata
|
|
139
|
+
id: metadata
|
|
140
|
+
uses: docker/metadata-action@v5
|
|
141
|
+
with:
|
|
142
|
+
images: ghcr.io/lairdgrouplancaster/labpulse
|
|
143
|
+
tags: |
|
|
144
|
+
type=semver,pattern={{version}},value=${{ github.event.release.tag_name }}
|
|
145
|
+
type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }}
|
|
146
|
+
labels: |
|
|
147
|
+
org.opencontainers.image.title=LabPulse
|
|
148
|
+
org.opencontainers.image.description=Raspberry Pi laboratory infrastructure monitoring
|
|
149
|
+
|
|
150
|
+
- name: Build and push image
|
|
151
|
+
id: image
|
|
152
|
+
uses: docker/build-push-action@v6
|
|
153
|
+
with:
|
|
154
|
+
context: .
|
|
155
|
+
file: ./Dockerfile
|
|
156
|
+
platforms: linux/amd64,linux/arm64
|
|
157
|
+
push: true
|
|
158
|
+
build-args: |
|
|
159
|
+
LABPULSE_VERSION=${{ needs.validate.outputs.version }}
|
|
160
|
+
tags: ${{ steps.metadata.outputs.tags }}
|
|
161
|
+
labels: ${{ steps.metadata.outputs.labels }}
|
|
162
|
+
provenance: mode=max
|
|
163
|
+
sbom: true
|
|
164
|
+
|
|
165
|
+
- name: Attest image provenance
|
|
166
|
+
uses: actions/attest@v4
|
|
167
|
+
with:
|
|
168
|
+
subject-name: ghcr.io/lairdgrouplancaster/labpulse
|
|
169
|
+
subject-digest: ${{ steps.image.outputs.digest }}
|
|
170
|
+
push-to-registry: true
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Test LabPulse
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
pytest:
|
|
9
|
+
name: Python ${{ matrix.python-version }}
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Check out source
|
|
18
|
+
uses: actions/checkout@v6
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v6
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
cache: pip
|
|
27
|
+
|
|
28
|
+
- name: Install LabPulse and test dependencies
|
|
29
|
+
run: python -m pip install --editable ".[dev]"
|
|
30
|
+
|
|
31
|
+
- name: Run hardware-free tests
|
|
32
|
+
run: python -m pytest
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
waterenv/
|
|
2
|
+
.venv/
|
|
3
|
+
build/
|
|
4
|
+
dist/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
__pycache__/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
/logs/
|
|
9
|
+
**/__pycache__/
|
|
10
|
+
|
|
11
|
+
# Generated Home Assistant smoke-test outputs
|
|
12
|
+
tmp_ha_*/
|
|
13
|
+
tmp_ha_*-check.py
|
|
14
|
+
/testing/tmp/
|
|
15
|
+
|
|
16
|
+
# Codex local workspace/artifact files
|
|
17
|
+
.codex/
|
|
18
|
+
.agents/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tasks": [
|
|
3
|
+
{
|
|
4
|
+
"type": "cppbuild",
|
|
5
|
+
"label": "C/C++: clang build active file",
|
|
6
|
+
"command": "/usr/bin/clang",
|
|
7
|
+
"args": [
|
|
8
|
+
"-fcolor-diagnostics",
|
|
9
|
+
"-fansi-escape-codes",
|
|
10
|
+
"-g",
|
|
11
|
+
"${file}",
|
|
12
|
+
"-o",
|
|
13
|
+
"${fileDirname}/${fileBasenameNoExtension}"
|
|
14
|
+
],
|
|
15
|
+
"options": {
|
|
16
|
+
"cwd": "${fileDirname}"
|
|
17
|
+
},
|
|
18
|
+
"problemMatcher": [
|
|
19
|
+
"$gcc"
|
|
20
|
+
],
|
|
21
|
+
"group": {
|
|
22
|
+
"kind": "build",
|
|
23
|
+
"isDefault": true
|
|
24
|
+
},
|
|
25
|
+
"detail": "Task generated by Debugger."
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"version": "2.0.0"
|
|
29
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable user-visible changes will be recorded here. The earlier prototype
|
|
4
|
+
history was not maintained as formal releases.
|
|
5
|
+
|
|
6
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
7
|
+
Versioning follows [Semantic Versioning](https://semver.org/).
|
|
8
|
+
|
|
9
|
+
## Unreleased
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Independent Triton control-PC publisher heartbeats and availability, with
|
|
14
|
+
fridge service alerts driven by script health instead of logfile activity.
|
|
15
|
+
- A per-service `notify_on_service_failure` setting, enabled by default, to
|
|
16
|
+
silence known unreliable or intentionally disconnected hubs without hiding
|
|
17
|
+
their status.
|
|
18
|
+
|
|
19
|
+
- Repository-wide MIT licensing for software, firmware, documentation, and
|
|
20
|
+
hardware design files.
|
|
21
|
+
- A reference Raspberry Pi deployment matrix and explicit pre-1.0 support,
|
|
22
|
+
compatibility, safety, and experimental-feature boundaries.
|
|
23
|
+
- An explicit product boundary defining LabPulse as monitoring and best-effort
|
|
24
|
+
alerting rather than safety-critical equipment control.
|
|
25
|
+
- A pipx-installable `labpulse` package and unified operator command.
|
|
26
|
+
- Setup, lifecycle, logs, configuration, browser, firmware-help, and diagnostic
|
|
27
|
+
commands.
|
|
28
|
+
- Version reporting through `labpulse version` and runtime-image matching in
|
|
29
|
+
`labpulse doctor`.
|
|
30
|
+
- Tag-derived package, runtime, and container versions through `setuptools-scm`.
|
|
31
|
+
- One-container-per-service hardware execution with a central lifecycle runner.
|
|
32
|
+
- Self-contained serial, DHT11, and X1200 drivers with declarative resources.
|
|
33
|
+
- A self-contained Sensirion SHT40 I2C temperature/humidity driver with
|
|
34
|
+
CRC-validated measurements and least-privilege device access.
|
|
35
|
+
- Compressed-air Arduino firmware that publishes pressure plus SHT40
|
|
36
|
+
temperature/humidity through the standard serial pipe, with the superseded
|
|
37
|
+
pressure-only sketch retained under `legacy/Arduino/pressure_monitor/`.
|
|
38
|
+
- Complete fake-hardware deployments which preserve the configured dashboard
|
|
39
|
+
and container layout while simulating every sensor and output in memory.
|
|
40
|
+
- Generated Home Assistant MQTT entities, alarm package, and native YAML
|
|
41
|
+
dashboard.
|
|
42
|
+
- Dry-run, test-mode, and modem-backed SMS delivery with subscription controls.
|
|
43
|
+
- Checksummed, consistent state archives and guarded blank-host reconstruction
|
|
44
|
+
through `labpulse backup` and `labpulse restore`.
|
|
45
|
+
- A release workflow that validates wheel, source distribution, and container
|
|
46
|
+
artifacts, publishes through PyPI Trusted Publishing, and publishes
|
|
47
|
+
attested AMD64/ARM64 images to GHCR.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- Home Assistant now receives the validated IANA timezone selected in
|
|
52
|
+
`config.yaml` instead of a hard-coded `Europe/London` timezone.
|
|
53
|
+
- Service measurement configuration now supports typed shared defaults,
|
|
54
|
+
infers labels from stable IDs when omitted, and keeps MQTT JSON source names
|
|
55
|
+
beside their measurements instead of duplicating IDs under driver options.
|
|
56
|
+
- Optional hardware dependencies are grouped by the `serial`, `i2c`, and
|
|
57
|
+
`gpio` connection types instead of individual driver names.
|
|
58
|
+
- The installed deployment directory is `~/labpulse-live`.
|
|
59
|
+
- The guarded configuration command is `labpulse config`.
|
|
60
|
+
- Deployment shell scripts are maintained under `deployment/`.
|
|
61
|
+
- Measurement units are published exactly as configured while icons are
|
|
62
|
+
derived independently.
|
|
63
|
+
- Real-Pi reliability acceptance now records two weeks of continuous operation,
|
|
64
|
+
real and injected hardware faults, UPS and abrupt-power recovery, restart
|
|
65
|
+
alarm reconciliation, SMS delivery, and the built-in watchdog decision.
|
|
66
|
+
- `labpulse config` now preserves an active fake-hardware deployment and validates
|
|
67
|
+
and regenerates its derived runtime configuration transactionally.
|
|
68
|
+
- Hardware lifecycle logs now include stable service/driver/target context,
|
|
69
|
+
status transitions, and the age of the last valid reading.
|
|
70
|
+
- `labpulse doctor` now reports the active runtime mode and gives corrective
|
|
71
|
+
commands or checks for common deployment, container, hardware, MQTT, and
|
|
72
|
+
Home Assistant failures.
|
|
73
|
+
- `labpulse down` and `labpulse restart` accept individual Compose service
|
|
74
|
+
names.
|
|
75
|
+
- Generated deployments use the GHCR image matching the installed package
|
|
76
|
+
version instead of copying source and rebuilding containers on each Pi.
|
|
77
|
+
- Guarded configuration now uses the same configurable Docker command as every
|
|
78
|
+
other lifecycle operation.
|
|
79
|
+
- Doctor now checks Docker daemon access and versions, host timezone/NTP state,
|
|
80
|
+
and systemd hardware-watchdog activation.
|
|
81
|
+
- Installation now includes ordered Home Assistant/MQTT onboarding, a
|
|
82
|
+
first-install acceptance checklist, host-time validation, and a non-editable
|
|
83
|
+
production update command.
|
|
84
|
+
- Power-loss and restoration notifications are explicitly separate: loss is
|
|
85
|
+
reported promptly, while recovery closes the lifecycle with outage duration.
|
|
86
|
+
- Persistent Python worker logs now rotate daily and retain seven previous
|
|
87
|
+
daily files instead of growing without a bound.
|
|
88
|
+
- The deployed USB assignment helper now reliably switches from the system
|
|
89
|
+
Python to LabPulse's managed environment before importing the package.
|
|
90
|
+
- Measurement configuration now uses the optional strict boolean `required`
|
|
91
|
+
field, defaulting to `true`, with plainly named missing/recovery timers.
|
|
92
|
+
- The generated Diagnostics view is now a human-readable System Status view
|
|
93
|
+
with Working, Needs attention, and Offline service states.
|
|
94
|
+
|
|
95
|
+
### Removed
|
|
96
|
+
|
|
97
|
+
- Prototype package layouts and earlier Pi implementations from the active
|
|
98
|
+
runtime. They remain under `legacy/` for reference only.
|
|
99
|
+
- The redundant per-reading availability sensor and the old
|
|
100
|
+
`availability: required|optional` measurement configuration.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: >-
|
|
3
|
+
If you use LabPulse in published research, please cite the software and
|
|
4
|
+
record the exact release and local configuration used.
|
|
5
|
+
title: LabPulse
|
|
6
|
+
type: software
|
|
7
|
+
authors:
|
|
8
|
+
- name: LabPulse contributors
|
|
9
|
+
repository-code: https://github.com/lairdgrouplancaster/LabPulse
|
|
10
|
+
url: https://github.com/lairdgrouplancaster/LabPulse
|
|
11
|
+
license: MIT
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Contributing to LabPulse
|
|
2
|
+
|
|
3
|
+
Thank you for helping improve LabPulse. Changes to public commands,
|
|
4
|
+
configuration or extension interfaces need migration notes and normal semantic
|
|
5
|
+
versioning so existing installations are not surprised.
|
|
6
|
+
|
|
7
|
+
## Before starting
|
|
8
|
+
|
|
9
|
+
For a small correction, open a focused pull request. For a new feature,
|
|
10
|
+
configuration change, public interface, or hardware driver, open an issue first
|
|
11
|
+
so the intended behavior and test boundary can be agreed.
|
|
12
|
+
|
|
13
|
+
Read:
|
|
14
|
+
|
|
15
|
+
1. [User guide and safety boundary](docs/USER_GUIDE.md)
|
|
16
|
+
2. [Architecture](docs/ARCHITECTURE.md)
|
|
17
|
+
3. [Development](docs/DEVELOPMENT.md)
|
|
18
|
+
4. [Hardware driver package guide](src/labpulse/hardware/drivers/README.md)
|
|
19
|
+
when adding direct hardware support
|
|
20
|
+
5. [Firmware guide](firmware/README.md) when changing Arduino firmware or
|
|
21
|
+
serial output
|
|
22
|
+
|
|
23
|
+
## Development principles
|
|
24
|
+
|
|
25
|
+
- Preserve `~/labpulse-live/config.yaml` as the installed source of truth.
|
|
26
|
+
- Keep sensor acquisition in Python and alarm decisions in Home Assistant.
|
|
27
|
+
- Keep equipment control and safety functions outside the measurement driver
|
|
28
|
+
contract; discuss any actuation proposal before implementation.
|
|
29
|
+
- Prefer the standard serial protocol when firmware can normalize a device.
|
|
30
|
+
- Keep optional hardware libraries lazy so unrelated drivers and host-side
|
|
31
|
+
generation do not require them.
|
|
32
|
+
- Make important behavior testable without Raspberry Pi hardware.
|
|
33
|
+
- Add compatibility or migration logic only for a concrete published-release
|
|
34
|
+
requirement.
|
|
35
|
+
- Do not commit phone numbers, credentials, Home Assistant state, logs, or
|
|
36
|
+
locally generated deployment files.
|
|
37
|
+
|
|
38
|
+
## Making a change
|
|
39
|
+
|
|
40
|
+
1. Create a branch from the current main branch.
|
|
41
|
+
2. Install the project in editable mode as described in
|
|
42
|
+
[Development](docs/DEVELOPMENT.md).
|
|
43
|
+
3. Make the smallest coherent change.
|
|
44
|
+
4. Add or update automated tests.
|
|
45
|
+
5. Update the authoritative documentation for changed behavior.
|
|
46
|
+
6. Run the complete hardware-free suite with `python -m pytest`.
|
|
47
|
+
7. Describe any real-Pi checks that are still required.
|
|
48
|
+
|
|
49
|
+
By submitting a contribution, you agree that it may be distributed under the
|
|
50
|
+
[MIT License](LICENSE) used by this project.
|
|
51
|
+
|
|
52
|
+
Do not hand-edit generated `compose.yaml`,
|
|
53
|
+
`homeassistant/config/packages/labpulse_generated.yaml`, or
|
|
54
|
+
`homeassistant/config/labpulse-dashboard.yaml` as source changes. Update their
|
|
55
|
+
generators, models, templates, or source configuration.
|
|
56
|
+
|
|
57
|
+
## Pull requests
|
|
58
|
+
|
|
59
|
+
A pull request should explain:
|
|
60
|
+
|
|
61
|
+
- the problem and intended behavior;
|
|
62
|
+
- the components changed;
|
|
63
|
+
- automated tests run;
|
|
64
|
+
- real hardware tested, if any;
|
|
65
|
+
- configuration or generated-output changes;
|
|
66
|
+
- documentation updated;
|
|
67
|
+
- remaining risks or follow-up work.
|
|
68
|
+
|
|
69
|
+
Keep unrelated formatting and refactors out of functional changes. Preserve
|
|
70
|
+
user changes already present in the branch.
|
|
71
|
+
|
|
72
|
+
## Hardware contributions
|
|
73
|
+
|
|
74
|
+
First decide whether the device can emit the unit-free pipe-delimited serial
|
|
75
|
+
protocol. If it can, add firmware, configuration, simulator coverage, and
|
|
76
|
+
documentation without creating a Python driver.
|
|
77
|
+
|
|
78
|
+
A direct-hardware driver must include:
|
|
79
|
+
|
|
80
|
+
- a stable driver ID and strict options model;
|
|
81
|
+
- `connect`, `read`, and idempotent `close` behavior;
|
|
82
|
+
- normalized numeric readings and classified failures;
|
|
83
|
+
- declarative container resources;
|
|
84
|
+
- lazy optional dependency imports;
|
|
85
|
+
- hardware-free tests for configuration, reading, failure, and cleanup;
|
|
86
|
+
- fake or injectable hardware where practical;
|
|
87
|
+
- example configuration and documentation;
|
|
88
|
+
- a recorded real-device smoke test before release.
|
|
89
|
+
|
|
90
|
+
See the [hardware driver package guide](src/labpulse/hardware/drivers/README.md).
|
|
91
|
+
|
|
92
|
+
## Documentation style
|
|
93
|
+
|
|
94
|
+
Write current facts rather than implementation history. Put operator tasks in
|
|
95
|
+
operator guides, cross-component contracts in architecture references, and
|
|
96
|
+
code-local details in docstrings. Avoid creating one-off implementation-plan
|
|
97
|
+
documents for completed features.
|
|
98
|
+
|
|
99
|
+
Use relative links inside the repository. Examples must distinguish the
|
|
100
|
+
repository starter `config.yaml` from the installed
|
|
101
|
+
`~/labpulse-live/config.yaml`.
|
|
102
|
+
|
|
103
|
+
## Participation
|
|
104
|
+
|
|
105
|
+
Be respectful, constructive, and professional when opening issues, reviewing
|
|
106
|
+
changes, or discussing the project. Do not publish credentials, phone numbers,
|
|
107
|
+
private network details, or other sensitive information in issues or pull
|
|
108
|
+
requests.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
ARG LABPULSE_VERSION
|
|
4
|
+
|
|
5
|
+
LABEL org.opencontainers.image.source="https://github.com/lairdgrouplancaster/LabPulse"
|
|
6
|
+
LABEL org.opencontainers.image.licenses="MIT"
|
|
7
|
+
LABEL org.opencontainers.image.version="${LABPULSE_VERSION}"
|
|
8
|
+
|
|
9
|
+
WORKDIR /app
|
|
10
|
+
|
|
11
|
+
RUN apt-get update \
|
|
12
|
+
&& apt-get install -y --no-install-recommends \
|
|
13
|
+
gpiod \
|
|
14
|
+
modemmanager \
|
|
15
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
16
|
+
|
|
17
|
+
COPY dist/labpulse-${LABPULSE_VERSION}-py3-none-any.whl /tmp/
|
|
18
|
+
|
|
19
|
+
RUN python -m pip install --no-cache-dir \
|
|
20
|
+
"labpulse[serial,i2c,gpio] @ file:///tmp/labpulse-${LABPULSE_VERSION}-py3-none-any.whl" \
|
|
21
|
+
&& rm "/tmp/labpulse-${LABPULSE_VERSION}-py3-none-any.whl"
|
|
22
|
+
|
|
23
|
+
CMD ["python", "-m", "labpulse.hardware", "--help"]
|
labpulse-0.3.6/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LabPulse contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|