live.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """Reaalajas AS7341 värvinäitaja.
  2. Loeb ClickHouse'ist viimase mõõtmise ja kuvab terminalis värvinäidise (24-bitine
  3. ANSI) + kanalite spektri. Mõeldud katseteks (eri värvi pindade mõõtmine).
  4. Käivitamine (projekti .venv):
  5. CH_URL=http://100.87.1.24:8125 CH_USER=zigbee CH_PASS=<parool> \
  6. .venv/bin/python varvusensor/collector/live.py [--interval 2] [--once]
  7. """
  8. from __future__ import annotations
  9. import argparse
  10. import json
  11. import os
  12. import time
  13. import requests
  14. import color
  15. from settings import CH_URL, CH_DB, CH_TABLE, CH_USER, CH_PASS
  16. BANDS = color.CHANNEL_WAVELENGTHS # {f1: 415, ...}
  17. RESET = "\x1b[0m"
  18. def fetch_latest() -> dict | None:
  19. cols = ", ".join(BANDS)
  20. sql = (
  21. f"SELECT ts, {cols}, rgb_hex, x_chrom, y_chrom, r, g, b "
  22. f"FROM {CH_DB}.{CH_TABLE} ORDER BY ts DESC LIMIT 1 FORMAT JSONEachRow"
  23. )
  24. resp = requests.post(
  25. f"{CH_URL}/",
  26. params={"database": CH_DB, "query": sql},
  27. auth=(CH_USER, CH_PASS),
  28. timeout=10,
  29. )
  30. resp.raise_for_status()
  31. lines = [line for line in resp.text.strip().splitlines() if line]
  32. return json.loads(lines[0]) if lines else None
  33. def swatch(r: int, g: int, b: int, width: int = 28, height: int = 3) -> str:
  34. block = f"\x1b[48;2;{r};{g};{b}m" + " " * width + RESET
  35. return "\n".join([block] * height)
  36. def spectrum_bar(channels: dict[str, float]) -> str:
  37. vmax = max((channels.get(band) or 0.0) for band in BANDS) or 1.0
  38. lines = []
  39. for band, wavelength in BANDS.items():
  40. value = channels.get(band) or 0.0
  41. bars = int(round(40 * value / vmax))
  42. lines.append(f" {band} {wavelength:3d}nm |{'█' * bars:<40}| {value:8.1f}")
  43. return "\n".join(lines)
  44. def render(row: dict) -> str:
  45. r, g, b = int(row["r"]), int(row["g"]), int(row["b"])
  46. channels = {band: row.get(band) for band in BANDS}
  47. return "\n".join(
  48. [
  49. f" Aeg: {row['ts']}",
  50. f" Värvus: {row['rgb_hex']} x={row['x_chrom']:.3f} y={row['y_chrom']:.3f}",
  51. "",
  52. swatch(r, g, b),
  53. "",
  54. " Spekter (kanalid):",
  55. spectrum_bar(channels),
  56. ]
  57. )
  58. def main() -> int:
  59. parser = argparse.ArgumentParser(description="AS7341 reaalajas värvinäitaja")
  60. parser.add_argument("--interval", type=float, default=2.0, help="värskendus sekundites")
  61. parser.add_argument("--once", action="store_true", help="kuva üks kord ja välju")
  62. args = parser.parse_args()
  63. try:
  64. while True:
  65. row = fetch_latest()
  66. os.system("clear")
  67. print("AS7341 värvinäitaja (Ctrl+C väljumiseks)")
  68. print("=" * 54)
  69. print(render(row) if row else " Andmeid pole.")
  70. if args.once:
  71. break
  72. time.sleep(args.interval)
  73. except KeyboardInterrupt:
  74. pass
  75. return 0
  76. if __name__ == "__main__":
  77. raise SystemExit(main())