15 KiB
15 KiB
InterferenceETL project context
2026-07-31: Initial hourly interference pipeline
- This repository is developed as the
InterferenceETLsubmodule under Metrix and is intended to run later in Metrix Script Management on an hourly schedule. main.pyreads the configured Metrix SFTP storage through Metrix API Token authentication or a local directory for tests. It selects the newest hour containing all seven known interference source types and falls back from a newer incomplete hour.- Each selected ZIP must contain exactly one XLSX. The script strictly validates the known
Sheet0header, writes one full UTF-8-BOM CSV per source type, and writes one merged CSV containing onlyhour_start,hour_end,cgi,cell_name, andinterference_dbm. - NR CGI uses
{gNBplmn}-{gNBId}-{cellId}. All 4G sources use460-00-{node}-{cell}, mapped to the actual node and cell column names in each workbook schema. - Runs are idempotent at the output-window directory level. Generation happens in a scoped temporary directory, then replaces only the same window below the configured output root. Source storage is never modified.
manifest.jsonrecords input paths, sizes, SHA-256 hashes, row counts, warnings, generated files, and the database write result for ingestion auditing.- The Metrix script container needs
openpyxl==3.1.5, bridge networking, andpython main.py. Runtime-specific source and output settings may be injected through project environment settings. - Read-only validation against the current Metrix storage selected window
2026073110001100, processed all seven source ZIP files, and produced 1,831 summary rows. Per-source row counts were7 / 804 / 45 / 86 / 700 / 164 / 25inEXPECTED_TYPESorder; sampled CGI, cell name, and interference values matched the source workbooks. interference-etl-runtime:1.1is now a local build helper only. Script projects use the standardpython:3.13.11-slimimage and uploaddist/InterferenceETL-offline-1.1.zip, which vendorsopenpyxlandet_xmlfileat the workspace root.- Six Mock tests pass on Windows Python and inside the runtime image. They cover complete-hour fallback, strict schema rejection, summary extraction, cross-midnight window parsing, transactional database replacement, and rollback protection.
2026-07-31: Latest-hour MySQL retention
- Scheduled runs write to MySQL by default. File-only development runs must explicitly pass
--no-database; the MySQL host, port, account, password, database, and table are constants at the top ofmain.py. - The fixed script-owned database is
interference_etland the fixed table isinterference_hourly_summary. Its only time column ismetric_time DATETIME, populated from the source KPI开始时间, so users can identify the hour represented by every row. - One transaction deletes the selected hour for idempotent refresh, inserts its complete batch, then deletes every other database hour. Any failure rolls back the data changes, and an older selected hour cannot replace a newer hour already stored.
- Database retention never deletes or modifies Metrix Storage/SFTP source ZIP or XLSX files. Generated CSV retention remains a separate pending decision.
2026-07-31: Self-contained Script Management package
scripts/build_offline_package.pycopies the three runtime distributions from the verified dependency image, adds the application files and__main__.py, and creates a ZIP that Metrix can extract without preserving executable bits or symlinks. The archive can also run directly aspython InterferenceETL-offline-1.1.zipwhen a Script Management server stores the upload without extracting it.- The builder runs an import check inside
python:3.13.11-slim; the package therefore needs neither a custom server image nor online package installation. - The builder excludes bytecode caches, and the ignored
dist/directory is the only location for this generated package.
2026-07-31: Fixed CGI and database configuration
- Replaced the NR
masterOperatorIdpassthrough withgNBplmn-gNBId-cellId. The remaining five 4G sources use the fixed460-00prefix plus their schema-specific base-station and cell ID columns. - Removed CGI PLMN and MySQL connection command-line/environment options. Database configuration now lives as a small constant block at the top of
main.py; the verified bridge-network address is172.17.0.1:3306becauseShareMySQLDNS is unavailable from the default script network. - Read-only online validation selected complete window
2026073115001600and checked all 2,275 generated CGI values against the seven converted source CSV files. Per-source row counts were6 / 1,198 / 48 / 91 / 731 / 179 / 22inEXPECTED_TYPESorder. - Before the dedicated-database correction, a connection-only check returned the platform database
metrix; that check did not create a table or modify data. Production use now targets onlyinterference_etl.
2026-08-03: Dedicated database initialization
- InterferenceETL no longer writes into the Metrix platform database. Its fixed database is
interference_etl, while the table remainsinterference_hourly_summary. - The default MySQL path first connects without selecting a database, runs
CREATE DATABASE IF NOT EXISTS interference_etlwithutf8mb4, then reconnects to that database and creates the table if needed. The configured account therefore needs database creation permission on first run. - Offline dependencies are stored below the workspace
vendor/directory instead of separate package directories at the project root.main.pyprepends this directory tosys.path, so the run command remainspython main.py. - Summary CSV rows and database rows do not expose
source_typeorsource_path. The database primary key is(metric_time, cgi); the current online hour was checked for CGI uniqueness before migrating from the former source-aware key.
2026-08-03: CellData coordinate enrichment
- Each run selects the latest filename-dated XLSX from five fixed CellData directories for 5G, 700M, reverse-activated 5G, TDD LTE, and FDD LTE. The filename date must end in
YYYYMMDD.xlsx; source files remain read-only. - CellData workbooks use sheet
小区信息表and required columnseNB/gNB,CI,经度, and纬度. CellData CGI is always460-00-{eNB/gNB}-{CI}and conflicting coordinates for the same CGI stop the run instead of silently overwriting data. - The summary CSV now ends with
longitude,latitude. The script-ownedinterference_hourly_summarytable has nullableDECIMAL(10,6)columns with the same names; existing tables are migrated automatically and unmatched CGI values are stored asNULL. - Read-only validation of the five
20260728workbooks produced 66,250 unique CGI coordinates with no conflicts. Against the sampled latest-hour summary, 1,529 of 1,539 rows matched (99.35%); the remaining 10 rows correctly stay empty.
2026-08-03: Metrix API database output
- Storage reads and database writes now share one API Token authenticated
MetrixApiClient. Direct PyMySQL access, MySQL host/account/password constants, and thePyMySQLoffline dependency were removed. ApiSummaryStorecreates the dedicatedinterference_etldatabase andinterference_hourly_summarytable through the Database API. It checks the latest stored hour, then uses/run-scriptwithsingle_session=trueand an explicit transaction to refresh one complete hour and delete all others.- API address, Token, and ShareMySQL
conn_idare constants loaded from ignoredruntime_config.py; the trackedruntime_config.example.pydocuments the required names. The current API address ishttp://188.5.127.115:18271. - Deployment remains SSH based. The Metrix Script Management API is not used for uploads, execution, or log inspection.
- Eleven containerized unit tests cover the pipeline, CellData enrichment, API database transaction, newer-hour protection, decimal validation, and API failure propagation.
- SSH deployment and a real Metrix runner execution succeeded with run
eead5c315fb04836a6327be201f561e6. Window2026080310001100produced 1,991 rows, matched 1,977 coordinates, left 14 unmatched, and deleted 1,789 rows from the prior hour. - Final API verification found exactly one stored hour (
2026-08-03 10:00:00) and exactly six columns:metric_time,cgi,cell_name,interference_dbm,longitude, andlatitude. The obsolete online source backup and environment-level API URL/Token entries were removed after the successful run.
2026-08-03: CellData azimuth enrichment
- All five latest CellData workbooks expose direction angle through column
方向角. CellData metadata now maps each460-00-{eNB/gNB}-{CI}to longitude, latitude, and azimuth. - Summary CSV and
interference_hourly_summaryaddazimuth. The database type isDECIMAL(6,2) NOT NULL DEFAULT 0; existing tables add the column automatically. Empty CellData direction angles and unmatched CGI values both become0, while unmatched coordinates remain empty/NULL. - Real CellData validation loaded 66,524 CGI metadata rows: 54,129 non-zero azimuth values and 12,395 zero/default values. Full window
2026080313001400produced 1,863 summary rows, including 1,677 non-zero azimuth values and 186 zero values. - SSH deployment run
e5462179fa8c4f9f9c2dfb2e4541e048succeeded. Database API verification found exactly one hour (2026-08-03 13:00:00), 1,863 rows, and columnsmetric_time,cgi,cell_name,interference_dbm,longitude,latitude,azimuth. - Twelve containerized unit tests pass, including empty azimuth defaulting and CellData metadata conflict detection.
2026-08-05: Network type and high-interference filtering
- Summary CSV and
interference_hourly_summaryaddnetwork_type: the two5G...source types map to2.6G, the two700M...source types map to700M, and SDR FDD/TDD plus reverse-activated RD map to4G. - Only high-interference rows enter the summary and database.
2.6Gkeeps values greater than or equal to-107 dBm;700Mand4Gkeep values greater than or equal to-110 dBm. Values strictly below those thresholds are discarded; equal values remain. - The seven converted source CSV files remain unfiltered source conversions.
manifest.jsonand stdout recordthreshold_filtered_rowsfor the summary filter. - Real read-only validation of window
2026080514001500reduced 1,868 source rows to 1,109 summary rows:2.6G=137,700M=108,4G=864, with 759 lower-interference rows removed. Thirteen containerized unit tests pass. - SSH deployment run
98a44e88b3684bd1b9ad7edcb866fb17succeeded for the same window. The database contains exactly one hour (2026-08-05 14:00:00) and 1,109 rows; grouped API verification found zero threshold violations and confirmed minimums2.6G=-106.970,700M=-110.000, and4G=-109.996.
2026-08-06: Nearby high-interference cell count
- Summary CSV and
interference_hourly_summaryaddnearby_count, the number of other retained high-interference cells within 1 km during the same selected hour. Counts include all network types, exclude the row itself, include the exact 1 km boundary, and default to0when coordinates are unavailable. - Candidate lookup uses a dependency-free 1 km Earth-centered three-dimensional grid index. Only the current and 26 adjacent buckets are checked, then Haversine distance confirms the exact radius; this avoids a full all-pairs scan while preserving distance accuracy.
- Unit tests pass in both the project virtual environment and
interference-etl-runtime:1.1image. A read-only real run for window2026080613001400produced 1,116 rows, including 1,110 with coordinates, 925 with non-zero nearby counts, and a maximum count of 39. All 1,116 indexed results matched a separate brute-force comparison, which found 3,973 qualifying pairs. - SSH deployment and Metrix runner execution
8f2fd51d7de14c93b4b0eb9bee8fafa0succeeded for the same window. Database API verification found only2026-08-06 13:00:00, with 1,116 rows, 925 non-zero counts, a maximum of 39, and 3,973 nearby pairs. All six rows without coordinates have count0.
2026-08-06: Adaptive source waiting and history export
- Source recognition now fixes only the seven known prefixes and final
_YYYYMMDDHHMMHHMM.zip; middle text may change with provider granularity. The first 12 digits are rounded down to natural 15-minute boundaries, while the final four end-time digits do not participate in grouping. - Each run follows only the group containing the globally newest source start time. It does not fall back or backfill older groups. Missing sources or no matching files produce
status=waitingand a successful exit; storage API failures remain task failures. Multiple files from one source in a group select the latest source start time. - All workbook row start times must round into the target group. Result CSV and database rows use one normalized
metric_timeand the database result columns only;hour_startandhour_endwere removed from summary CSV output. - Database time is checked before source ZIP and CellData downloads. A newer or equal database time skips source processing. Successful database output is archived through the Storage API under
干扰历史数据/YYYY-MM-DD/干扰数据处理结果_YYYYMMDDHHMMSS.csv; an equal database time with a missing/empty history file is exported from the database and repaired. - Nineteen tests pass on Windows and in the offline runtime image. Live read-only selection saw incomplete newest group
2026-08-06 15:00:00, correctly waited for missing5G下FDD干扰监控, and did not produce output. Explicit read-only validation of complete group2026-08-06 14:00:00produced 1,092 rows with one normalizedmetric_timeand the expected nine-column result schema. - SSH deployment run
7a7c0bba3a0c41f5a5a9e83ad25ff2fdprocessed the completed2026-08-06 15:00:00group successfully. It retained 1,082 high-interference rows, removed 853 lower-interference rows, matched coordinates for 1,074 rows, left 8 unmatched, and replaced 1,116 rows from the previous database time. - Database verification found only
2026-08-06 15:00:00and 1,082 rows. Of those, 887 have non-zeronearby_count, the maximum is 40, and all 8 rows without coordinates remain valid. The history CSV was uploaded with the expected nine columns and 1,082 rows to干扰历史数据/2026-08-06/干扰数据处理结果_20260806150000.csv. - A second run
e1c81ada63234b3c85a377e1b46a1370returned success withstatus=skipped, confirming that an existing database time plus a non-empty history file avoids duplicate work. MetrixApiClientuses a proxy-free opener because the API is an intranet service and the Windows system proxy previously converted direct requests into502responses. The verified Metrix API remainshttp://188.5.127.115:18271; external port9082currently serves CapacityReport and must not be used by this script.