#!/usr/bin/env python3 import http.server import socketserver import json import os import ssl from urllib.parse import urlparse from datetime import datetime PORT = 6443 class ShellyDeviceHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): parsed_path = urlparse(self.path).path.strip('/') # Handle both .html and no extension if parsed_path.endswith('.html'): device_id = parsed_path.replace('.html', '') else: device_id = parsed_path if device_id.startswith('shellyplusplugs-'): file_path = f"./webserver_shelly_{device_id}.txt" if os.path.exists(file_path): try: data = [] with open(file_path, 'r') as f: for line in f: if line.strip(): data.append(json.loads(line)) if data: html = self.generate_html(data) self.send_response(200) self.send_header('Content-type', 'text/html; charset=utf-8') self.end_headers() self.wfile.write(html.encode()) else: self.send_error(404, "No data found") except Exception as e: self.send_error(500, f"Error: {str(e)}") else: self.send_error(404, f"File not found") else: self.send_error(404, "Invalid device ID") def generate_html(self, data): latest = data[-1] device_id = latest.get('device_id', 'N/A') fw_version = latest.get('fw_version', 'N/A') uptime_s = latest.get('uptime_s', 'N/A') timestamp = latest.get('timestamp', 'N/A') switch_output = latest['measurements']['switch:0'].get('output', 'N/A') timestamps, apower, voltage, current, temp, kwh = [], [], [], [], [], [] for entry in data: timestamps.append(entry['timestamp']) m = entry['measurements']['switch:0'] apower.append(m.get('apower', 0)) voltage.append(m.get('voltage', 0)) current.append(m.get('current', 0)) temp.append(m['temperature'].get('tC', 0)) kwh.append(entry['daily_kwh'].get('switch:0', 0)) labels = [datetime.fromtimestamp(ts).strftime('%H:%M:%S') for ts in timestamps] return f""" Shelly Device

🔌 {device_id}

Device Information

FW: {fw_version}

Uptime: {uptime_s}s

TS: {timestamp}

Switch: {'ON' if switch_output else 'OFF'}

""" if __name__ == '__main__': context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) context.load_cert_chain('cert.pem', 'key.pem') with socketserver.TCPServer(("", PORT), ShellyDeviceHandler) as httpd: httpd.socket = context.wrap_socket(httpd.socket, server_side=True) print(f"HTTPS Server running on port {PORT}") print(f"Access: https://localhost:{PORT}/shellyplusplugs-3ce90e2fba14.html") try: httpd.serve_forever() except KeyboardInterrupt: print("\nServer stopped.")