Skip to content

Instantly share code, notes, and snippets.

@jhmartin
Created June 22, 2025 15:55
Show Gist options
  • Save jhmartin/cee1fdbe9a54c2bba885665239ec673e to your computer and use it in GitHub Desktop.
Save jhmartin/cee1fdbe9a54c2bba885665239ec673e to your computer and use it in GitHub Desktop.
Read status from an Airscape Gen2 Controls whole-home-fan and emit into openhab
#!/usr/bin/env python3
import requests
import json
import re
import time
import signal
import sys
import logging
import http.client as http_client
# Enable HTTP debug logging
http_client.HTTPConnection.debuglevel = 0
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s [%(levelname)s] %(message)s",
handlers=[logging.StreamHandler(sys.stdout)]
)
# Reduce noise from overly verbose modules
logging.getLogger("urllib3").setLevel(logging.DEBUG)
logging.getLogger("requests").setLevel(logging.DEBUG)
FANURL = "http://192.168.1.11"
OPENHAB_BASE = "http://localhost:8080/rest/items"
headers = {
"Content-Type": "text/plain",
"Accept": "application/json"
}
running = True
def clean_json_string(text):
cleaned = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]', '', text)
return cleaned
def fetch_clean_json(url):
try:
response = requests.get(url, timeout=2)
response.encoding = 'utf-8'
raw_text = response.text
filtered_lines = [
line for line in raw_text.splitlines() if "server_response" not in line]
cleaned_text = "\n".join(filtered_lines)
sanitized = clean_json_string(cleaned_text)
return json.loads(sanitized)
except Exception as e:
logging.warning(f"Error parsing JSON: {e}")
return {}
def post_temperature(item, value):
try:
url = f"{OPENHAB_BASE}/{item}"
requests.post(url, headers=headers, data=str(value), timeout=2)
except Exception as e:
logging.error(f"Failed to post {item}: {e}")
def signal_handler(sig, frame):
global running
print("\n[INFO] Interrupt received. Stopping gracefully...")
running = False
def main_loop():
signal.signal(signal.SIGINT, signal_handler)
print("[INFO] Temperature sync started. Press Ctrl+C to stop.")
while running:
data = fetch_clean_json(f"{FANURL}/status.json.cgi")
inside = data.get("inside", "0")
attic = data.get("attic", "0")
outside = data.get("oa", "0")
post_temperature("Laundry_Temperature", inside)
post_temperature("Attic_Temperature", attic)
post_temperature("Outside_Temperature", outside)
time.sleep(1)
print("[INFO] Shutdown complete.")
if __name__ == "__main__":
main_loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment