|
@@ 432-461 (lines=30) @@
|
| 429 |
|
i0 = _safe_float_list(reporting['values'][triplet[0]]) |
| 430 |
|
i1 = _safe_float_list(reporting['values'][triplet[1]]) |
| 431 |
|
i2 = _safe_float_list(reporting['values'][triplet[2]]) |
| 432 |
|
if len(i0) and len(i0) == len(i1) == len(i2) and ts0 == ts1 == ts2: |
| 433 |
|
unbalance_rates = [] |
| 434 |
|
worst = -1.0 |
| 435 |
|
worst_time = None |
| 436 |
|
for i in range(len(i0)): |
| 437 |
|
avg_i = (i0[i] + i1[i] + i2[i]) / 3.0 |
| 438 |
|
if avg_i <= 0: |
| 439 |
|
continue |
| 440 |
|
max_dev = max(abs(i0[i] - avg_i), abs(i1[i] - avg_i), abs(i2[i] - avg_i)) |
| 441 |
|
rate_pct = max_dev / avg_i * 100.0 |
| 442 |
|
unbalance_rates.append(rate_pct) |
| 443 |
|
if rate_pct > worst: |
| 444 |
|
worst = rate_pct |
| 445 |
|
worst_time = ts0[i] |
| 446 |
|
limit_pct = getattr(config, 'current_unbalance_limit_pct', 10.0) |
| 447 |
|
within = sum(1 for r in unbalance_rates if r <= limit_pct) |
| 448 |
|
compliance = (within / len(unbalance_rates) * 100.0) if unbalance_rates else None |
| 449 |
|
stats = _calc_basic_stats(unbalance_rates) if unbalance_rates else None |
| 450 |
|
analysis.append({ |
| 451 |
|
'point_name': 'Three-phase current', |
| 452 |
|
'unit': 'A', |
| 453 |
|
'category': 'current', |
| 454 |
|
'type': 'current_unbalance', |
| 455 |
|
'limit_pct': limit_pct, |
| 456 |
|
'compliance_pct': compliance, |
| 457 |
|
'worst_unbalance_pct': worst, |
| 458 |
|
'worst_time': worst_time, |
| 459 |
|
'metrics': [ |
| 460 |
|
{'name': 'mean_unbalance_pct', 'value': stats['mean'] if stats else None}, |
| 461 |
|
{'name': 'p95_unbalance_pct', 'value': stats['p95'] if stats else None} |
| 462 |
|
] |
| 463 |
|
}) |
| 464 |
|
for idx, name in enumerate(reporting['names']): |
|
@@ 347-376 (lines=30) @@
|
| 344 |
|
v0 = _safe_float_list(reporting['values'][triplet[0]]) |
| 345 |
|
v1 = _safe_float_list(reporting['values'][triplet[1]]) |
| 346 |
|
v2 = _safe_float_list(reporting['values'][triplet[2]]) |
| 347 |
|
if len(v0) and len(v0) == len(v1) == len(v2) and ts0 == ts1 == ts2: |
| 348 |
|
unbalance_rates = [] |
| 349 |
|
worst = -1.0 |
| 350 |
|
worst_time = None |
| 351 |
|
for i in range(len(v0)): |
| 352 |
|
avg_v = (v0[i] + v1[i] + v2[i]) / 3.0 |
| 353 |
|
if avg_v <= 0: |
| 354 |
|
continue |
| 355 |
|
max_dev = max(abs(v0[i] - avg_v), abs(v1[i] - avg_v), abs(v2[i] - avg_v)) |
| 356 |
|
rate_pct = max_dev / avg_v * 100.0 |
| 357 |
|
unbalance_rates.append(rate_pct) |
| 358 |
|
if rate_pct > worst: |
| 359 |
|
worst = rate_pct |
| 360 |
|
worst_time = ts0[i] |
| 361 |
|
limit_pct = getattr(config, 'voltage_unbalance_limit_pct', 2.0) |
| 362 |
|
within = sum(1 for r in unbalance_rates if r <= limit_pct) |
| 363 |
|
compliance = (within / len(unbalance_rates) * 100.0) if unbalance_rates else None |
| 364 |
|
stats = _calc_basic_stats(unbalance_rates) if unbalance_rates else None |
| 365 |
|
analysis.append({ |
| 366 |
|
'point_name': 'Three-phase voltage', |
| 367 |
|
'unit': 'V', |
| 368 |
|
'category': 'voltage', |
| 369 |
|
'type': 'voltage_unbalance', |
| 370 |
|
'limit_pct': limit_pct, |
| 371 |
|
'compliance_pct': compliance, |
| 372 |
|
'worst_unbalance_pct': worst, |
| 373 |
|
'worst_time': worst_time, |
| 374 |
|
'metrics': [ |
| 375 |
|
{'name': 'mean_unbalance_pct', 'value': stats['mean'] if stats else None}, |
| 376 |
|
{'name': 'p95_unbalance_pct', 'value': stats['p95'] if stats else None} |
| 377 |
|
] |
| 378 |
|
}) |
| 379 |
|
|