gea-program 0.22.0__tar.gz → 0.24.0__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.
- {gea_program-0.22.0 → gea_program-0.24.0}/PKG-INFO +35 -2
- {gea_program-0.22.0 → gea_program-0.24.0}/README.md +34 -1
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/__init__.py +1 -1
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/__main__.py +204 -5
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/acceptance_tests.py +373 -0
- gea_program-0.24.0/gea/dlis.py +624 -0
- gea_program-0.24.0/gea/dnp3.py +614 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/files.py +18 -2
- gea_program-0.24.0/gea/hartip.py +513 -0
- gea_program-0.24.0/gea/help/dlis.md +11 -0
- gea_program-0.24.0/gea/help/field-ports.md +11 -0
- gea_program-0.24.0/gea/help/historian.md +11 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/helplib.py +3 -0
- gea_program-0.24.0/gea/modbus_rtu.py +439 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/patches.py +96 -3
- gea_program-0.24.0/gea/piwebapi.py +366 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/ports.py +4 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/service.py +6 -2
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/survey_cmd.py +13 -3
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/web/app.html +1 -1
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/workspace.py +1 -1
- {gea_program-0.22.0 → gea_program-0.24.0}/gea_program.egg-info/PKG-INFO +35 -2
- {gea_program-0.22.0 → gea_program-0.24.0}/gea_program.egg-info/SOURCES.txt +8 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/pyproject.toml +1 -1
- {gea_program-0.22.0 → gea_program-0.24.0}/LICENSE +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/backup.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/bench.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/blind_harness.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/certificates.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/cli.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/client_reports.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/config_versioning.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/conformance.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/correlation.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/dashboard.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/deviation.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/doctor.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/earth_model.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/elevation.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/etp.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/etp12_schemas.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/example_register_map.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/fat_sat.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/follower.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/forward_model.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/gamma.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/geodesy.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/alarms.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/backup.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/conformance.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/data-in.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/doctor.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/drift.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/etp.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/files.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/instruments.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/interval.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/month-end.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/notifications.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/osdu.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/patches.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/quality.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/seedlink.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/seismic.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/site.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/sites.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/soak.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/sra.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/start.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/structure.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/transients.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/vibration.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/housekeeping.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/interval.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/jobs.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/live_ports.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/loadtest.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/modbus.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/model_card.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/month_end.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/notify.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/opcua_port.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/operator_app.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/osdu.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/permits.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/ppdm.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/project.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/quakeml.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reconciler.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/sample_record.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/sbom.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seedlink.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/segy.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_array.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_film.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_response.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_track.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/service_life.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/shapefile.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/shell.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/shut_in.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/sla_report.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/soak.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/sra.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/store_forward.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/strata_join.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/structure.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/supervisor.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/survey_view.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/telemetry.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/tool_library.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/transient.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/vibration.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/well_assembler.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/wits0.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea/witsml.py +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/setup.cfg +0 -0
- {gea_program-0.22.0 → gea_program-0.24.0}/tests/test_acceptance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gea-program
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.24.0
|
|
4
4
|
Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
|
|
5
5
|
Author: Daniel T. Murphy
|
|
6
6
|
License: MPL-2.0
|
|
@@ -125,7 +125,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
125
125
|
gea client-report --report accuracy --out client_report
|
|
126
126
|
gea model-cards --out model_cards
|
|
127
127
|
gea sbom --out sbom
|
|
128
|
-
gea accept # the product gate (
|
|
128
|
+
gea accept # the product gate (359 checks)
|
|
129
129
|
gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
|
|
130
130
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
131
131
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -648,6 +648,39 @@ against it; `gea seedlink --config ... --hello` prints what a server says of
|
|
|
648
648
|
itself; `gea help seedlink`. A TexNet station is served by EarthScope at
|
|
649
649
|
`rtserve.iris.washington.edu:18000`, network `TX`.
|
|
650
650
|
|
|
651
|
+
### The log as delivered, and the historian
|
|
652
|
+
|
|
653
|
+
A well log arrives as DLIS (API RP66 V1); `gea/dlis.py` reads the container
|
|
654
|
+
as the standard lays it out, with no dependency - the storage unit label,
|
|
655
|
+
visible records, logical record segments and trailers, the sets of objects
|
|
656
|
+
with every representation code, the frames and channels, the frame data -
|
|
657
|
+
and hands the strata survey the same stream the LAS port does: `gea dlis
|
|
658
|
+
--file log.dlis --info` describes it, `--to-las` exports a frame, `gea survey
|
|
659
|
+
--file log.dlis` reads it directly, and the Files page detects it by its
|
|
660
|
+
label. Encrypted records are skipped and named, never decrypted or guessed.
|
|
661
|
+
Proven on a real Schlumberger station log (104 channels, two frames, 3,252
|
|
662
|
+
records in a tenth of a second). The operator's gauge history in a PI System
|
|
663
|
+
comes out through PI Web API (`gea piwebapi`, protocol `piwebapi` on the
|
|
664
|
+
Patch panel): GET only, the archive between two times with its paging
|
|
665
|
+
followed, every value with the archive's timestamp and flags, credentials
|
|
666
|
+
from environment variables the map names. `gea help dlis`, `gea help
|
|
667
|
+
historian`.
|
|
668
|
+
|
|
669
|
+
### The field ports
|
|
670
|
+
|
|
671
|
+
The three links a gauge panel on a pad actually offers, each read-only in
|
|
672
|
+
the code (no write, control, time set or device-changing command exists),
|
|
673
|
+
each refusing to run without the site's map and its source, each with a
|
|
674
|
+
stand-in on the loopback to rehearse against, each one more protocol on the
|
|
675
|
+
Patch panel: **Modbus RTU** (`gea modbus-rtu`; the RS-485 drop through
|
|
676
|
+
pyserial, the `serial` extra, or RTU over TCP through a serial-to-Ethernet
|
|
677
|
+
converter; CRC-16 framed and checked by this program; functions 03 and 04),
|
|
678
|
+
**DNP3** (`gea dnp3`; IEEE 1815 data link, transport and application layers;
|
|
679
|
+
integrity and event polls; analog, binary and counter objects with their
|
|
680
|
+
flags and 48-bit event times; confirms and unsolicited responses handled),
|
|
681
|
+
**HART-IP** (`gea hartip`; the session, command 0, 3 and 9; HART unit codes
|
|
682
|
+
converted; device and variable status to quality). `gea help field-ports`.
|
|
683
|
+
|
|
651
684
|
### The interval against the mapped tops
|
|
652
685
|
|
|
653
686
|
Where does the injection sit in the geology? The operator declares the
|
|
@@ -86,7 +86,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
86
86
|
gea client-report --report accuracy --out client_report
|
|
87
87
|
gea model-cards --out model_cards
|
|
88
88
|
gea sbom --out sbom
|
|
89
|
-
gea accept # the product gate (
|
|
89
|
+
gea accept # the product gate (359 checks)
|
|
90
90
|
gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
|
|
91
91
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
92
92
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -609,6 +609,39 @@ against it; `gea seedlink --config ... --hello` prints what a server says of
|
|
|
609
609
|
itself; `gea help seedlink`. A TexNet station is served by EarthScope at
|
|
610
610
|
`rtserve.iris.washington.edu:18000`, network `TX`.
|
|
611
611
|
|
|
612
|
+
### The log as delivered, and the historian
|
|
613
|
+
|
|
614
|
+
A well log arrives as DLIS (API RP66 V1); `gea/dlis.py` reads the container
|
|
615
|
+
as the standard lays it out, with no dependency - the storage unit label,
|
|
616
|
+
visible records, logical record segments and trailers, the sets of objects
|
|
617
|
+
with every representation code, the frames and channels, the frame data -
|
|
618
|
+
and hands the strata survey the same stream the LAS port does: `gea dlis
|
|
619
|
+
--file log.dlis --info` describes it, `--to-las` exports a frame, `gea survey
|
|
620
|
+
--file log.dlis` reads it directly, and the Files page detects it by its
|
|
621
|
+
label. Encrypted records are skipped and named, never decrypted or guessed.
|
|
622
|
+
Proven on a real Schlumberger station log (104 channels, two frames, 3,252
|
|
623
|
+
records in a tenth of a second). The operator's gauge history in a PI System
|
|
624
|
+
comes out through PI Web API (`gea piwebapi`, protocol `piwebapi` on the
|
|
625
|
+
Patch panel): GET only, the archive between two times with its paging
|
|
626
|
+
followed, every value with the archive's timestamp and flags, credentials
|
|
627
|
+
from environment variables the map names. `gea help dlis`, `gea help
|
|
628
|
+
historian`.
|
|
629
|
+
|
|
630
|
+
### The field ports
|
|
631
|
+
|
|
632
|
+
The three links a gauge panel on a pad actually offers, each read-only in
|
|
633
|
+
the code (no write, control, time set or device-changing command exists),
|
|
634
|
+
each refusing to run without the site's map and its source, each with a
|
|
635
|
+
stand-in on the loopback to rehearse against, each one more protocol on the
|
|
636
|
+
Patch panel: **Modbus RTU** (`gea modbus-rtu`; the RS-485 drop through
|
|
637
|
+
pyserial, the `serial` extra, or RTU over TCP through a serial-to-Ethernet
|
|
638
|
+
converter; CRC-16 framed and checked by this program; functions 03 and 04),
|
|
639
|
+
**DNP3** (`gea dnp3`; IEEE 1815 data link, transport and application layers;
|
|
640
|
+
integrity and event polls; analog, binary and counter objects with their
|
|
641
|
+
flags and 48-bit event times; confirms and unsolicited responses handled),
|
|
642
|
+
**HART-IP** (`gea hartip`; the session, command 0, 3 and 9; HART unit codes
|
|
643
|
+
converted; device and variable status to quality). `gea help field-ports`.
|
|
644
|
+
|
|
612
645
|
### The interval against the mapped tops
|
|
613
646
|
|
|
614
647
|
Where does the injection sit in the geology? The operator declares the
|
|
@@ -278,6 +278,35 @@ def main(argv=None) -> int:
|
|
|
278
278
|
p_lp.add_argument("--stream-csv", type=str, default=None, help="also write a historian-style CSV the other commands ingest")
|
|
279
279
|
p_lp.add_argument("--selftest", action="store_true", help="etp: the codec round-trip and a session against the simulated store on the loopback")
|
|
280
280
|
|
|
281
|
+
p_dl = sub.add_parser("dlis", help="a DLIS (RP66 V1) well log: --info describes it (origin, channels, frames, what was skipped); --frame --out writes the frame as a historian-style CSV; --to-las writes LAS 2.0")
|
|
282
|
+
p_dl.add_argument("--file", type=str, required=True)
|
|
283
|
+
p_dl.add_argument("--info", action="store_true")
|
|
284
|
+
p_dl.add_argument("--frame", type=str, default=None, help="the frame to read when the file holds several")
|
|
285
|
+
p_dl.add_argument("--out", type=str, default=None, help="write the frame's channels as CSV (index first)")
|
|
286
|
+
p_dl.add_argument("--to-las", type=str, default=None, help="write the frame as a LAS 2.0 file")
|
|
287
|
+
p_dl.add_argument("--json", action="store_true")
|
|
288
|
+
p_pi = sub.add_parser("piwebapi", help="the PI Web API historian pull, read-only: --config (base_url, auth by environment variable names, tags with paths); --selftest against the stand-in")
|
|
289
|
+
p_pi.add_argument("--config", type=str, default=None)
|
|
290
|
+
p_pi.add_argument("--write-example-config", type=str, default=None)
|
|
291
|
+
p_pi.add_argument("--out", type=str, default=None, help="write the records CSV here")
|
|
292
|
+
p_pi.add_argument("--stream-csv", type=str, default=None)
|
|
293
|
+
p_pi.add_argument("--seconds", type=float, default=None, help="ignored: a pull is one request per tag (kept so the live tap's call shape is the same)")
|
|
294
|
+
p_pi.add_argument("--record", type=str, default=None, help="write the pull's summary as one JSON line here")
|
|
295
|
+
p_pi.add_argument("--selftest", action="store_true")
|
|
296
|
+
for name, helptxt in (("modbus-rtu", "Modbus RTU port, read-only: the serial line (pyserial) or RTU over TCP; functions 03/04 only; the stand-in slave with --selftest"),
|
|
297
|
+
("dnp3", "DNP3 (IEEE 1815) master, read-only: integrity and event polls over TCP; analog inputs, binaries, counters with flags and event times; the stand-in outstation with --selftest"),
|
|
298
|
+
("hartip", "HART-IP client, read-only: session, command 0, 3 and 9; the variables with their unit codes and status; the stand-in device with --selftest")):
|
|
299
|
+
p_fp = sub.add_parser(name, help=helptxt)
|
|
300
|
+
p_fp.add_argument("--config", type=str, default=None, help="site map JSON (client-owned): the transport, the mapping and its source")
|
|
301
|
+
p_fp.add_argument("--write-example-config", type=str, default=None, help="write the example map (the stand-in) here and exit")
|
|
302
|
+
p_fp.add_argument("--seconds", type=float, default=None, help="run for this long (polls = seconds / interval_s); default the map's polls")
|
|
303
|
+
p_fp.add_argument("--polls", type=int, default=None, help="poll this many times instead")
|
|
304
|
+
p_fp.add_argument("--record", type=str, default=None, help="write one JSON line per poll (the values and faults) here")
|
|
305
|
+
p_fp.add_argument("--replay", type=str, default=None, help="not offered by these ports (a poll is a request; there is nothing to replay)")
|
|
306
|
+
p_fp.add_argument("--out", type=str, default=None, help="write the records CSV here")
|
|
307
|
+
p_fp.add_argument("--stream-csv", type=str, default=None, help="also write a historian-style CSV the other commands ingest")
|
|
308
|
+
p_fp.add_argument("--selftest", action="store_true", help="the codec vectors and a session against the stand-in on the loopback")
|
|
309
|
+
|
|
281
310
|
p_ws = sub.add_parser("workspace", help="the client site folder: init, add wells (file | catalogue | live), list, migrate a --out folder, refresh the dashboard, audit log")
|
|
282
311
|
p_ws.add_argument("--path", type=str, required=True, help="the workspace folder")
|
|
283
312
|
p_ws.add_argument("--action", type=str, default="list",
|
|
@@ -378,7 +407,7 @@ def main(argv=None) -> int:
|
|
|
378
407
|
p_ws.add_argument("--entry", type=str, default=None, help="add-catalog: catalogue entry")
|
|
379
408
|
p_ws.add_argument("--well", type=str, default=None, help="add-catalog: well tag inside the entry; remove: well id")
|
|
380
409
|
p_ws.add_argument("--station-md", type=float, default=None, help="station MD in ft (catalogue wells need it)")
|
|
381
|
-
p_ws.add_argument("--port", type=str, default=None, choices=["opcua", "mqtt", "modbus_g6"], help="add-live: the port")
|
|
410
|
+
p_ws.add_argument("--port", type=str, default=None, choices=["opcua", "mqtt", "modbus_g6", "wits0", "witsml", "etp", "modbus_rtu", "dnp3", "hartip"], help="add-live: the port")
|
|
382
411
|
p_ws.add_argument("--from", dest="from_dir", type=str, default=None, help="migrate: a folder written by `gea dashboard --out`")
|
|
383
412
|
p_ws.add_argument("--actor", type=str, default="cli", help="who is acting (recorded in the audit log)")
|
|
384
413
|
p_ws.add_argument("--month", type=str, default=None, help="refresh: also measure the SLA for YYYY-MM")
|
|
@@ -657,8 +686,9 @@ def main(argv=None) -> int:
|
|
|
657
686
|
p_fl.add_argument("--station-md", type=float, default=None)
|
|
658
687
|
p_fl.add_argument("--actor", type=str, default="cli")
|
|
659
688
|
|
|
660
|
-
p_sy = sub.add_parser("survey", help="a LAS file in, one strata report out (--demo: the bundled public KTB excerpt); --out writes report.txt + survey.json")
|
|
661
|
-
p_sy.add_argument("--file", type=str, default=None, help="LAS 2.0 file")
|
|
689
|
+
p_sy = sub.add_parser("survey", help="a LAS or DLIS file in, one strata report out (--demo: the bundled public KTB excerpt); --out writes report.txt + survey.json")
|
|
690
|
+
p_sy.add_argument("--file", type=str, default=None, help="LAS 2.0 or DLIS (RP66 V1) file")
|
|
691
|
+
p_sy.add_argument("--frame", type=str, default=None, help="DLIS: the frame to read when the file holds several (gea dlis --file X --info lists them)")
|
|
662
692
|
p_sy.add_argument("--demo", action="store_true")
|
|
663
693
|
p_sy.add_argument("--family", type=str, default="continental_crystalline", help="prior family for the estimator")
|
|
664
694
|
p_sy.add_argument("--lat", type=float, default=None)
|
|
@@ -794,8 +824,8 @@ def main(argv=None) -> int:
|
|
|
794
824
|
import json as _json
|
|
795
825
|
from .survey_cmd import run_survey
|
|
796
826
|
if not (a.file or a.demo):
|
|
797
|
-
raise SystemExit("survey needs --file <LAS> or --demo")
|
|
798
|
-
txt, machine = run_survey(path=a.file, demo=a.demo, family=a.family, lat=a.lat, elev=a.elev)
|
|
827
|
+
raise SystemExit("survey needs --file <LAS or DLIS> or --demo")
|
|
828
|
+
txt, machine = run_survey(path=a.file, demo=a.demo, family=a.family, lat=a.lat, elev=a.elev, frame=a.frame)
|
|
799
829
|
print(txt)
|
|
800
830
|
if a.out:
|
|
801
831
|
os.makedirs(a.out, exist_ok=True)
|
|
@@ -2268,6 +2298,175 @@ def main(argv=None) -> int:
|
|
|
2268
2298
|
stop.set()
|
|
2269
2299
|
print("etp-sim: stopped")
|
|
2270
2300
|
return 0
|
|
2301
|
+
elif a.cmd == "dlis":
|
|
2302
|
+
import json as _json
|
|
2303
|
+
from .dlis import DlisError, DlisFile, read as _read_dlis
|
|
2304
|
+
try:
|
|
2305
|
+
if a.info or not (a.out or a.to_las):
|
|
2306
|
+
with open(a.file, "rb") as f:
|
|
2307
|
+
info = DlisFile(f.read(), os.path.basename(a.file)).describe()
|
|
2308
|
+
if a.json:
|
|
2309
|
+
print(_json.dumps(info, indent=1, default=str)); return 0
|
|
2310
|
+
o = info["origin"]
|
|
2311
|
+
print(f"dlis: {a.file}")
|
|
2312
|
+
print(f" storage set: {info['storage_unit']['storage_set_id']}; file {info['file_header'].get('ID', '').strip()} seq {info['file_header'].get('SEQUENCE-NUMBER', '').strip()}")
|
|
2313
|
+
print(f" well: {o.get('WELL-NAME', '').strip() or '?'} field: {o.get('FIELD-NAME', '').strip() or '?'} company: {o.get('COMPANY', '').strip() or '?'} producer: {o.get('PRODUCER-NAME', '').strip() or '?'} created: {o.get('CREATION-TIME', '?')}")
|
|
2314
|
+
print(f" {info['n_records']} logical records; sets: " + ", ".join(f"{t}{'(' + n + ')' if n else ''} x{k}" for t, n, k in info["eflr_sets"]))
|
|
2315
|
+
if info.get("encrypted_records"):
|
|
2316
|
+
print(" encrypted records skipped: " + ", ".join(f"{k} x{n}" for k, n in info["encrypted_records"].items()))
|
|
2317
|
+
for u in info["unparsed"]:
|
|
2318
|
+
print(" not parsed: " + u)
|
|
2319
|
+
print(f" {len(info['channels'])} channels:")
|
|
2320
|
+
for c in info["channels"]:
|
|
2321
|
+
print(f" {c['name']:<12s} {c['units']:<10s} {c['code']:<7s} dim {c['dimension']} {c['long_name']}")
|
|
2322
|
+
for fr in info["frames"]:
|
|
2323
|
+
print(f" frame {fr['name']}: index {fr['index_type']} {fr['direction']}, spacing {fr['spacing']} {fr['spacing_units']}, {fr['index_min']}..{fr['index_max']}; {len(fr['channels'])} channels: {', '.join(fr['channels'][:12])}{' ...' if len(fr['channels']) > 12 else ''}")
|
|
2324
|
+
return 0
|
|
2325
|
+
st = _read_dlis(a.file, frame=a.frame)
|
|
2326
|
+
except (DlisError, OSError) as e:
|
|
2327
|
+
raise SystemExit(f"dlis: {e}")
|
|
2328
|
+
print(f"dlis: frame {st.meta['frame']}: {len(st.index)} rows, index {st.meta['index_channel']} ({st.meta['index_units']}) {float(st.index[0]):g}..{float(st.index[-1]):g}, {len(st.channels)} channels"
|
|
2329
|
+
+ (f"; {st.meta['notes']}" if st.meta.get("notes") else ""))
|
|
2330
|
+
if a.out:
|
|
2331
|
+
import csv as _csv
|
|
2332
|
+
with open(a.out, "w", newline="", encoding="utf-8") as f:
|
|
2333
|
+
w = _csv.writer(f)
|
|
2334
|
+
w.writerow([st.meta["index_channel"]] + list(st.channels))
|
|
2335
|
+
w.writerow([st.meta["index_units"]] + [st.channels[c].unit for c in st.channels])
|
|
2336
|
+
for i in range(len(st.index)):
|
|
2337
|
+
w.writerow([float(st.index[i])] + ["" if st.channels[c].values[i] != st.channels[c].values[i] else float(st.channels[c].values[i]) for c in st.channels])
|
|
2338
|
+
print(" csv:", a.out)
|
|
2339
|
+
if a.to_las:
|
|
2340
|
+
with open(a.to_las, "w", encoding="utf-8") as f:
|
|
2341
|
+
f.write("~VERSION INFORMATION\n VERS. 2.0 : CWLS LOG ASCII STANDARD - VERSION 2.0\n WRAP. NO : ONE LINE PER DEPTH STEP\n")
|
|
2342
|
+
f.write("~WELL INFORMATION\n")
|
|
2343
|
+
f.write(f" STRT.{st.meta['index_units']:<6s} {float(st.index[0]):.4f} : START\n STOP.{st.meta['index_units']:<6s} {float(st.index[-1]):.4f} : STOP\n")
|
|
2344
|
+
f.write(f" STEP.{st.meta['index_units']:<6s} {(float(st.index[1]) - float(st.index[0])) if len(st.index) > 1 else 0.0:.4f} : STEP\n NULL. -999.25 : NULL VALUE\n")
|
|
2345
|
+
f.write(f" WELL. {st.meta.get('WELL-NAME', '').strip()} : WELL\n FLD . {st.meta.get('FIELD-NAME', '').strip()} : FIELD\n COMP. {st.meta.get('COMPANY', '').strip()} : COMPANY\n SRVC. {st.meta.get('PRODUCER-NAME', '').strip()} : SERVICE COMPANY\n")
|
|
2346
|
+
f.write(f" SRC . DLIS {os.path.basename(a.file)} frame {st.meta['frame']} : SOURCE (gea dlis --to-las)\n")
|
|
2347
|
+
f.write("~CURVE INFORMATION\n")
|
|
2348
|
+
f.write(f" {st.meta['index_channel']:<8s}.{st.meta['index_units']:<8s} : INDEX\n")
|
|
2349
|
+
for c in st.channels:
|
|
2350
|
+
f.write(f" {c:<8s}.{st.channels[c].unit:<8s} : {c}\n")
|
|
2351
|
+
f.write("~A\n")
|
|
2352
|
+
for i in range(len(st.index)):
|
|
2353
|
+
f.write(f"{float(st.index[i]):.4f}" + "".join(f" {(-999.25 if st.channels[c].values[i] != st.channels[c].values[i] else float(st.channels[c].values[i])):.4f}" for c in st.channels) + "\n")
|
|
2354
|
+
print(" las:", a.to_las)
|
|
2355
|
+
return 0
|
|
2356
|
+
elif a.cmd == "piwebapi":
|
|
2357
|
+
import json as _json
|
|
2358
|
+
from .live_ports import records_to_stream, summarize, write_records_csv
|
|
2359
|
+
from . import piwebapi as _PI
|
|
2360
|
+
if a.selftest:
|
|
2361
|
+
r = _PI.selftest()
|
|
2362
|
+
print(f"piwebapi selftest: {'OK' if r['ok'] else 'FAILED'}")
|
|
2363
|
+
for k, v in r.items():
|
|
2364
|
+
if k != "ok":
|
|
2365
|
+
print(f" {'ok ' if v else 'BAD'} {k}")
|
|
2366
|
+
return 0 if r["ok"] else 1
|
|
2367
|
+
if a.write_example_config:
|
|
2368
|
+
with open(a.write_example_config, "w", encoding="utf-8") as f:
|
|
2369
|
+
_json.dump(_PI.EXAMPLE_CONFIG, f, indent=1)
|
|
2370
|
+
print("config:", a.write_example_config); return 0
|
|
2371
|
+
if not a.config:
|
|
2372
|
+
raise SystemExit("piwebapi needs --config (or --write-example-config to start one)")
|
|
2373
|
+
cfg = _PI.load_config(a.config)
|
|
2374
|
+
sim_h = None
|
|
2375
|
+
try:
|
|
2376
|
+
if cfg.get("base_url") == "sim":
|
|
2377
|
+
sim = _PI.SimServer(); sim_h, port_ = sim.serve(); cfg = {**cfg, "base_url": f"http://127.0.0.1:{port_}/piwebapi", "auth": "none"}
|
|
2378
|
+
try:
|
|
2379
|
+
port = _PI.PiPort(cfg)
|
|
2380
|
+
r = port.pull()
|
|
2381
|
+
except (_PI.PiError, ValueError) as e:
|
|
2382
|
+
raise SystemExit(f"piwebapi: {e}")
|
|
2383
|
+
finally:
|
|
2384
|
+
if sim_h is not None:
|
|
2385
|
+
sim_h.close()
|
|
2386
|
+
recs = port.records
|
|
2387
|
+
print(f"piwebapi: {_json.dumps(port.summary(), default=str)}")
|
|
2388
|
+
print(_json.dumps(summarize(recs), indent=1))
|
|
2389
|
+
if a.record:
|
|
2390
|
+
with open(a.record, "w", encoding="utf-8") as f:
|
|
2391
|
+
f.write(_json.dumps({"pull": r, "summary": port.summary()}, default=str) + "\n")
|
|
2392
|
+
if a.out:
|
|
2393
|
+
print(" records:", write_records_csv(recs, a.out))
|
|
2394
|
+
if a.stream_csv and recs:
|
|
2395
|
+
st = records_to_stream(recs, name="piwebapi")
|
|
2396
|
+
import csv as _csv
|
|
2397
|
+
from datetime import datetime as _dt, timedelta as _td
|
|
2398
|
+
t0 = _dt.fromisoformat(st.meta["start_time"])
|
|
2399
|
+
with open(a.stream_csv, "w", newline="", encoding="utf-8") as f:
|
|
2400
|
+
w = _csv.writer(f)
|
|
2401
|
+
w.writerow(["timestamp"] + list(st.channels))
|
|
2402
|
+
for i, t in enumerate(st.index):
|
|
2403
|
+
w.writerow([(t0 + _td(seconds=float(t))).isoformat()] + ["" if st.channels[c].values[i] != st.channels[c].values[i] else round(float(st.channels[c].values[i]), 4) for c in st.channels])
|
|
2404
|
+
print(" stream:", a.stream_csv)
|
|
2405
|
+
return 0 if not port.faults else 1
|
|
2406
|
+
elif a.cmd in ("modbus-rtu", "dnp3", "hartip"):
|
|
2407
|
+
import json as _json
|
|
2408
|
+
from .live_ports import records_to_stream, summarize, write_records_csv
|
|
2409
|
+
mod = __import__({"modbus-rtu": "gea.modbus_rtu", "dnp3": "gea.dnp3", "hartip": "gea.hartip"}[a.cmd], fromlist=["x"])
|
|
2410
|
+
if a.selftest:
|
|
2411
|
+
r = mod.selftest()
|
|
2412
|
+
print(f"{a.cmd} selftest: {'OK' if r['ok'] else 'FAILED'}")
|
|
2413
|
+
for k, v in r.items():
|
|
2414
|
+
if k != "ok":
|
|
2415
|
+
print(f" {'ok ' if v else 'BAD'} {k}")
|
|
2416
|
+
return 0 if r["ok"] else 1
|
|
2417
|
+
if a.write_example_config:
|
|
2418
|
+
with open(a.write_example_config, "w", encoding="utf-8") as f:
|
|
2419
|
+
_json.dump(mod.EXAMPLE_CONFIG, f, indent=1)
|
|
2420
|
+
print("config:", a.write_example_config); return 0
|
|
2421
|
+
if a.replay:
|
|
2422
|
+
raise SystemExit(f"{a.cmd}: a poll is a request to the device; there is no recording to replay - run against the device or the stand-in")
|
|
2423
|
+
if not a.config:
|
|
2424
|
+
raise SystemExit(f"{a.cmd} needs --config (or --write-example-config to start one)")
|
|
2425
|
+
cfg = mod.load_config(a.config)
|
|
2426
|
+
polls = a.polls
|
|
2427
|
+
if polls is None and a.seconds is not None:
|
|
2428
|
+
polls = max(1, int(round(a.seconds / max(float(cfg.get("interval_s", 1.0)), 0.05))))
|
|
2429
|
+
from .patches import close_field_port, open_field_port
|
|
2430
|
+
proto = {"modbus-rtu": "modbus_rtu", "dnp3": "dnp3", "hartip": "hartip"}[a.cmd]
|
|
2431
|
+
try:
|
|
2432
|
+
tap = open_field_port(proto, mod, cfg)
|
|
2433
|
+
except (NotImplementedError, ConnectionError, ValueError, OSError) as e:
|
|
2434
|
+
raise SystemExit(f"{a.cmd}: {e}")
|
|
2435
|
+
rec_f = open(a.record, "w", encoding="utf-8") if a.record else None
|
|
2436
|
+
n = int(cfg.get("polls", 3) if polls is None else polls)
|
|
2437
|
+
dt = float(cfg.get("interval_s", 1.0))
|
|
2438
|
+
try:
|
|
2439
|
+
for k in range(n):
|
|
2440
|
+
before = len(tap.records)
|
|
2441
|
+
r = tap.poll_once(integrity=(k == 0)) if a.cmd == "dnp3" else tap.poll_once()
|
|
2442
|
+
if rec_f:
|
|
2443
|
+
rec_f.write(_json.dumps({"poll": k + 1, "utc": tap.records[-1].ingest_timestamp_utc if tap.records else None,
|
|
2444
|
+
"values": {x.tag_id: x.value for x in tap.records[before:]}, "quality": {x.tag_id: x.quality_flag for x in tap.records[before:]},
|
|
2445
|
+
"detail": (r if isinstance(r, dict) and a.cmd != "modbus-rtu" else None)}, default=str) + "\n")
|
|
2446
|
+
if dt > 0 and k < n - 1:
|
|
2447
|
+
import time as _time
|
|
2448
|
+
_time.sleep(dt)
|
|
2449
|
+
finally:
|
|
2450
|
+
close_field_port(proto, tap)
|
|
2451
|
+
if rec_f:
|
|
2452
|
+
rec_f.close()
|
|
2453
|
+
recs = tap.records
|
|
2454
|
+
print(f"{a.cmd}: {_json.dumps(tap.summary(), default=str)}")
|
|
2455
|
+
print(_json.dumps(summarize(recs), indent=1))
|
|
2456
|
+
if a.out:
|
|
2457
|
+
print(" records:", write_records_csv(recs, a.out))
|
|
2458
|
+
if a.stream_csv and recs:
|
|
2459
|
+
st = records_to_stream(recs, name=proto)
|
|
2460
|
+
import csv as _csv
|
|
2461
|
+
from datetime import datetime as _dt, timedelta as _td
|
|
2462
|
+
t0 = _dt.fromisoformat(st.meta["start_time"])
|
|
2463
|
+
with open(a.stream_csv, "w", newline="", encoding="utf-8") as f:
|
|
2464
|
+
w = _csv.writer(f)
|
|
2465
|
+
w.writerow(["timestamp"] + list(st.channels))
|
|
2466
|
+
for i, t in enumerate(st.index):
|
|
2467
|
+
w.writerow([(t0 + _td(seconds=float(t))).isoformat()] + ["" if st.channels[c].values[i] != st.channels[c].values[i] else round(float(st.channels[c].values[i]), 4) for c in st.channels])
|
|
2468
|
+
print(" stream:", a.stream_csv)
|
|
2469
|
+
return 0
|
|
2271
2470
|
elif a.cmd in ("opcua", "mqtt", "wits0", "witsml", "etp"):
|
|
2272
2471
|
import json as _json
|
|
2273
2472
|
from .live_ports import records_to_stream, summarize, write_records_csv
|