forked from TillRepo/IrSender
122 lines
2.8 KiB
Python
122 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
import json
|
|
import sys
|
|
import time
|
|
|
|
import pigpio
|
|
|
|
DEFAULT_GPIO = 12
|
|
|
|
|
|
def load_config(path: str) -> dict:
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
|
|
if "signal" not in data or not isinstance(data["signal"], list):
|
|
raise ValueError("JSON braucht ein 'signal'-Array.")
|
|
|
|
return data
|
|
|
|
|
|
def build_wave(pi: pigpio.pi, gpio: int, carrier_hz: int, signal: list[dict]) -> int:
|
|
period_us = max(2, round(1_000_000 / carrier_hz))
|
|
on_us = max(1, period_us // 2)
|
|
off_us = max(1, period_us - on_us)
|
|
|
|
gpio_mask = 1 << gpio
|
|
pulses = []
|
|
|
|
for item in signal:
|
|
kind = str(item.get("type", "")).lower()
|
|
duration = int(item.get("duration", 0))
|
|
|
|
if duration <= 0:
|
|
continue
|
|
|
|
if kind == "space":
|
|
pulses.append(pigpio.pulse(0, 0, duration))
|
|
|
|
elif kind == "mark":
|
|
full_cycles = duration // period_us
|
|
remainder = duration % period_us
|
|
|
|
for _ in range(full_cycles):
|
|
pulses.append(pigpio.pulse(gpio_mask, 0, on_us))
|
|
pulses.append(pigpio.pulse(0, gpio_mask, off_us))
|
|
|
|
if remainder > 0:
|
|
pulses.append(pigpio.pulse(gpio_mask, 0, remainder))
|
|
|
|
else:
|
|
raise ValueError(f"Unbekannter type: {kind} (erlaubt: mark, space)")
|
|
|
|
pi.wave_clear()
|
|
pi.wave_add_generic(pulses)
|
|
wid = pi.wave_create()
|
|
|
|
return wid
|
|
|
|
|
|
def send_wave(pi: pigpio.pi, wid: int, repeat: int) -> None:
|
|
for i in range(repeat):
|
|
pi.wave_send_once(wid)
|
|
while pi.wave_tx_busy():
|
|
time.sleep(0.001)
|
|
|
|
if i != repeat - 1:
|
|
time.sleep(0.03)
|
|
|
|
|
|
def main() -> int:
|
|
if len(sys.argv) != 2:
|
|
print("Usage: python3 ir_send.py signal.json")
|
|
return 1
|
|
|
|
cfg = load_config(sys.argv[1])
|
|
|
|
gpio = int(cfg.get("gpio", DEFAULT_GPIO))
|
|
carrier = int(cfg.get("carrier", 38000))
|
|
repeat = int(cfg.get("repeat", 1))
|
|
|
|
if repeat < 1:
|
|
repeat = 1
|
|
|
|
pi = pigpio.pi()
|
|
if not pi.connected:
|
|
print("Fehler: pigpiod läuft nicht.")
|
|
return 1
|
|
|
|
wid = -1
|
|
try:
|
|
pi.set_mode(gpio, pigpio.OUTPUT)
|
|
pi.write(gpio, 0)
|
|
|
|
wid = build_wave(pi, gpio, carrier, cfg["signal"])
|
|
if wid < 0:
|
|
print("Fehler: wave_create fehlgeschlagen.")
|
|
return 1
|
|
|
|
send_wave(pi, wid, repeat)
|
|
print("IR-Signal gesendet.")
|
|
return 0
|
|
|
|
finally:
|
|
try:
|
|
if wid >= 0:
|
|
pi.wave_tx_stop()
|
|
pi.wave_delete(wid)
|
|
except Exception:
|
|
pass
|
|
|
|
try:
|
|
pi.write(gpio, 0)
|
|
except Exception:
|
|
pass
|
|
|
|
pi.wave_clear()
|
|
pi.stop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|