Good morning everyone. This project has taken a deep plunge into AI "help" and now I am at a point where even StackOverflow will not allow my questions to be posted as they are too complex.
CoPilot has given me this complex "soup". I have fought things from 404 server codes to CoPilot totally removing vital lines of code then not being able to replace them.
What is NOT happening is the webpage loads with no errors, it reports the JSON script sees the python code...then it all dies. The arduino is sending data every 30 seconds (verified multiple times). The Pi is still looking and finding no data most of that 30 seconds and I have not found a solution to simply make the Pi stop and simply wait for data to come from the Arduino then do what it's supposed to do and push new data to the website and database (when prompted)
Without delay...here is my soup
This is AI work that began with my own research. I'm over my head and am tired of spending hours with Copilot "trying this or that".
HTML code:ARDUINO Code: (confirmed to work solidly - adding it here for questions)
This is a screenshot of the command line as Flask begins and the page is loaded. It stops here...no updates every 30 seconds as supposedly told to do
![Image]()
This is a screenshot example of my system.log file showing good data as well as the Pi not waiting for new data to trigger a new response
![Image]()
After this, if unsolved, I will toss the project out and reuse components for other projects down the line. Too much time spent...thanks as always
CoPilot has given me this complex "soup". I have fought things from 404 server codes to CoPilot totally removing vital lines of code then not being able to replace them.
What is NOT happening is the webpage loads with no errors, it reports the JSON script sees the python code...then it all dies. The arduino is sending data every 30 seconds (verified multiple times). The Pi is still looking and finding no data most of that 30 seconds and I have not found a solution to simply make the Pi stop and simply wait for data to come from the Arduino then do what it's supposed to do and push new data to the website and database (when prompted)
Without delay...here is my soup
Code:
#!/usr/bin/env python3# -*- coding: utf-8 -*-# Unified / route to handle HTML and JSON, avoiding 404 on /updateimport serialimport mariadbimport timeimport threadingfrom flask import Flask, render_template, jsonify, requestimport tracebackimport osimport datetime# Declare globalsFIELDS = ['temp', 'humid', 'bar', 'rain', 'uva', 'uvb', 'uvi', 'power', 'intensity', 'wind', 'anny']latest_values = ["0"] * len(FIELDS) # Initialize with zerosdbmin = ""# ConfigurationSERIAL_PORT = '/dev/ttyACM0'BAUD_RATE = 9600DB_CONFIG = { "user": "username", "password": "password", "host": "127.0.0.1", "port": 3306, "database": "Temps"}LOG_FILE = "/home/me/server/system.log"app = Flask(__name__)# Loggingdef log(message): global timestamp timestamp = time.strftime('%Y-%m-%d %H:%M:%S') try: with open(LOG_FILE, "a") as f: f.write(f"{timestamp} {message}\n") except Exception as e: print(f"Failed to write to log: {e}") print(f"Log message: {timestamp} {message}")# Serial Readerdef read_serial(): global values, latest_values log("Serial thread initiated...") try: if not os.path.exists(SERIAL_PORT): log(f"Serial port {SERIAL_PORT} does not exist") return ser = serial.Serial(SERIAL_PORT, BAUD_RATE, timeout=2) log("Serial port opened successfully") time.sleep(2) ser.flush() while True: raw = ser.readline().decode('utf-8', errors='ignore').strip() if not raw: log("Empty serial data received") continue time.sleep(15) values = [v.strip() for v in raw.split(',')] log(f"Raw serial data: {raw}") if len(values) == 12 and values[-1].lower() == "end": latest_values = values[:11] valid = all(v == "--" or v.replace('.', '', 1).replace('-', '', 1).isdigit() for v in values[:11]) if valid: latest_values = values[:11] log(f"Data received: {latest_values}") #insert_to_db(latest_values) else: log(f"Non-numeric value(s): {values}") #latest_values = ["0"] * len(FIELDS) # Report zeros if invalid else: log(f"Invalid packet: {repr(raw)}") #latest_values = ["0"] * len(FIELDS) # Report zeros if invalid except serial.SerialException as e: log(f"Serial error: {e}\n{traceback.format_exc()}") latest_values = ["0"] * len(FIELDS) # Report zeros on error except Exception as ex: log(f"Unexpected error in serial thread: {ex}\n{traceback.format_exc()}") latest_values = ["0"] * len(FIELDS) # Report zeros on error# Database Handlerdef insert_to_db(values): try: conn = mariadb.connect(**DB_CONFIG) cur = conn.cursor() cur.execute( f"""INSERT INTO weather ({', '.join(FIELDS)}) VALUES ({', '.join(['?'] * len(FIELDS))})""", values ) conn.commit() cur.close() conn.close() log("Database insert successful") except Exception as e: log(f"Database insert failed: {e}\n{traceback.format_exc()}") def periodic_logger(): #ct = datetime.datetime.now() #dbmin = ct.minute # the above is a possible solution to check the minute and if it equals 00, 10, 20, etc, then it'll send data to the database... connect_to_db(latest_values)# Web Server@app.route('/up')#I think the problem(s) lie within the code below...not suredef up(): log("Reached index route") try: templateData = {field: 'n/a' for field in FIELDS} #templateData['lightning_detected'] = False (will add a lightning sensor soon - commented out for now) if len(latest_values) == len(FIELDS): templateData.update({field: latest_values[i] for i, field in enumerate(FIELDS)}) if request.headers.get('Accept') == 'application/json': log(f"Sending JSON: {templateData}") return jsonify(templateData) else: log("Rendering HTML with templateData") return render_template('index.html', **templateData) except Exception as e: log(f"Error in route: {e}\n{traceback.format_exc()}") return jsonify({'error': 'Server Failure'}), 500if __name__ == '__main__': try: log("Launching server...") threading.Thread(target=read_serial, daemon=True).start() threading.Thread(target=periodic_logger, daemon=True).start() app.run(debug=True, host='127.0.0.1', port=5000, threaded=True) except Exception as e: log(f"Server error: {e}\n{traceback.format_exc()}")HTML code:
Code:
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><title>Weather Co-op</title><link rel="shortcut icon" type="image/jpg" href="/static/reverse engineered logo.png"><link rel="stylesheet" type="text/css" href="/static/stylesheet.css"><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script></head><body id="bodystyle"><!--<script>document.addEventListener("DOMContentLoaded", function() {const now = new Date();const hours = now.getHours();if (hours >= 6 && hours < 18) {document.getElementById('bodystyle').style.background = 'linear-gradient(to bottom, #00d8e4, #499b4a)';document.getElementById('bodystyle').style.color = '#000';} else {document.getElementById('bodystyle').style.background = 'linear-gradient(to bottom, #000, #231b0e, #231b0e, #9b7f51)';document.getElementById('bodystyle').style.color = '#fff';}});</script> temporarily commented out to see if this was causing problems--><nav><div class="logo"><img src="/static/reverse engineered logo.png" alt="Weather Co-Op logo"><div class="heading"><h2>Welcome to Weather Co-op's website</h2><h2 style="color: gold;">Current conditions</h2></div></div></nav><div class="grid-container"><div class="grid-item"><p>Temperature</p><img src="/static/temperature.png" alt="temperature icon"><p id="temp">{{ temp }} --</p> #CoPilot says that if JSON is returned, it should replace the dashes with values. I have both HTML and JSON included until this all works as expected, then will delete the portions that do not need to be included</div><div class="grid-item"><p>Humidity</p><img src="/static/humidity.png" alt="humidity icon"><p id="humid">{{ humid }} --</p></div><div class="grid-item"><p>Wind direction</p><img src="/static/wind_direction.png" alt="anemometer icon"><p id="anny">{{ anny }} --</p></div><div class="grid-item"><p>Wind speed</p><img src="/static/wind_speed.png" alt="wind speed icon"><p id="wind">{{ wind }} --</p></div><div class="grid-item"><p>Barometer</p><img src="/static/press.png" alt="barometer icon"><p id="bar">{{ bar }} --</p></div><div class="grid-item"><p>Rainfall</p><img src="/static/rain.png" alt="rain cloud icon"><p id="rain">{{ rain }} --</p></div><div class="grid-item"><p>UVA</p><img src="/static/uva.png" alt="uva icon"><p id="uva">{{ uva }} --</p></div><div class="grid-item"><p>UVB</p><img src="/static/summer.png" alt="sun tan lotion icon"><p id="uvb">{{ uvb }} --</p></div><div class="grid-item"><p>UVI</p><img src="/static/uv-index.png" alt="uv index icon"><p id="uvi">{{ uvi }} --</p></div><div class="grid-item"><p>Solar Power</p><img src="/static/solar-energy.png" alt="solar energy icon"><p id="power">{{ power }} --</p></div><div class="grid-item"><p>Intensity</p><img src="/static/sun.png" alt="radiant sun icon"><p id="intensity">{{ instensity }} --</p></div><div class="grid-item"><p>Lightning</p><img src="/static/storm.gif" alt="storm logo with animated lightning bolt"><p id="lightning">Lightning nearby: {{lightning_detected}} --</p></div></div><footer><hr><h5>© 2016-2025 Weather Co-Op - All Rights Reserved </h5><hr></footer><script>console.log("starting JSON script");$(document).ready(function() {function updateWeather() {$.ajax({url: '../up',console.log("url navigated");dataType: 'json',console.log("data type JSON established");success: function(data) {const units = {temp: '°F', humid: '%', bar: 'inHg', rain: 'in', wind: 'mph', anny: '°',uva: '', uvb: '', uvi: '', power: 'kW/m³', intensity: '%'};console.log("units given");for (let key in units) {let val = parseFloat(data[key]);console.log("val = parseFloat");let display = (isNaN(val) || data[key] === "0") ? "--" : val.toFixed(1) + units[key];console.log("display");document.getElementById(key).textContent = display;console.log("document get element by ID executed");}},error: function(xhr, status, error) {console.error("AJAX failed:", error);}});}updateWeather();console.log("updateWeather function called");setInterval(updateWeather, 30000);<!-- 30 second delay -->console.log("30 sec delay");});</body></html>Code:
/*This is a custom weather station, many parts engineered of my own design while others were provided from www.thingiverse.com and modified for my purpose*/#include <DS3231.h>#include <ArduinoJson.h>#include <DFRobot_VEML6075.h>#include <Adafruit_BMP085.h>#include <Wire.h>#include <Adafruit_Sensor.h>#include <DHT.h>#include <OneWire.h>#include <DallasTemperature.h>#include <Arduino.h>#include <time.h>#include <string.h>#define DHTTYPE DHT22Adafruit_BMP085 bmp;#define VEML6075_ADDR 0x10#define DEBOUNCE_TIME 80#define ENCODER_A 2#define encoderPin_1 3#define encoderPin_2 4DFRobot_VEML6075_IIC VEML6075(&Wire, VEML6075_ADDR);DS3231 myRTC;const int t_pin = 22;const int h_pin = 24;const int l_pin = A1;const int rain_pin = 19;const unsigned long debounceDelay = 300; // msString LAST_LABEL = "end";OneWire oneWire(t_pin);DallasTemperature sensors(&oneWire);DHT dht(h_pin, DHTTYPE);volatile long encoderTicks = 0;volatile long encoderPosition = 0;volatile long eP = 0;volatile int pulseCount = 0;volatile int lastAState = 0;volatile int tipCount = 0;unsigned long lastTime = 0;unsigned long lastDebounceTime = 0;long lastTicks = 0;bool currentState = false;bool lastState = false;float rain = -0.1473;void setup() {//Serial.println("setup initialized");Serial.begin(9600);pinMode(rain_pin, INPUT_PULLUP);pinMode(t_pin, INPUT);pinMode(ENCODER_A, INPUT_PULLUP);pinMode(encoderPin_1, INPUT_PULLUP);pinMode(encoderPin_2, INPUT_PULLUP);attachInterrupt(digitalPinToInterrupt(ENCODER_A), updateEncoder, CHANGE);attachInterrupt(digitalPinToInterrupt(encoderPin_1), readEncoder, CHANGE);attachInterrupt(digitalPinToInterrupt(rain_pin), tipDetected, RISING);sensors.begin();dht.begin();if (!bmp.begin()) { Serial.println("Could not find the BMP180 sensor..."); while (1) {}}while (!Serial);while (!VEML6075.begin()) { Serial.println("UV sensor failed to start"); delay(8000);} //Serial.println("All sensors initialized.");Wire.begin();}void loop() { /*int cMin = myRTC.getMinute(); //Serial.println(cMin); if(cMin == 00) { connect(); } else if(cMin == 10) { connect(); } else if(cMin == 20) { connect(); } else if(cMin == 30) { connect(); } else if(cMin == 40) { connect(); } else if(cMin == 50) { connect(); delay(29020); }*/ delay(29015);//30 second delay connect();}void connect() { float temp = getTemperature(); Serial.print(temp, 4); Serial.print(","); delay(50); float humid = getHumidity(); Serial.print(humid, 0); Serial.print(","); delay(50); float bar = getBarometer(); Serial.print(bar, 2); Serial.print(","); delay(50); float rain = getRain(); Serial.print(rain, 4); Serial.print(","); delay(50); float uva, uvb, uvi, power; getUV(uva, uvb, uvi, power); Serial.print(uva, 1); Serial.print(","); Serial.print(uvb, 1); Serial.print(","); Serial.print(uvi, 1); Serial.print(","); Serial.print(power, 2); Serial.print(","); delay(50); float intensity = getLight(); Serial.print(intensity, 0); Serial.print(","); delay(50); float wind = getWind(); Serial.print(wind, 2); Serial.print(","); delay(50); float anny = readEncoder(); Serial.print(anny, 0); Serial.print(","); delay(50); Serial.println(LAST_LABEL); //delay(60000); //delay 1 min to prevent errant readings being logged into the database}float getTemperature() { sensors.requestTemperatures(); float temp = sensors.getTempFByIndex(0); return temp;}float getHumidity() { float humid = dht.readHumidity(); return isnan(humid) ? 0.00 : humid;}float getBarometer() { float p = bmp.readPressure(); float bar = (p / 3.244) / 1000; //change the decimal to match your current conditions - smaller this divsor, the larger your pressure reading will become return bar;}float getLight() { int intensity = analogRead(l_pin); return intensity;}float getRain() { return tipCount * 0.1473;}void getUV(float &uva, float &uvb, float &uvi, float &power) { uva = VEML6075.getUva(); uvb = VEML6075.getUvb(); uvi = VEML6075.getUvi(uva, uvb); power = (104 * uvi - 18.365) / 1000;}float getWind() { unsigned long currentTime = millis(); if(currentTime - lastTime >= 100) { long currentTicks = encoderTicks; long ticksSinceLast = currentTicks - lastTicks; float rpm = (float)ticksSinceLast / (currentTime - lastTime) * 1000 / 600.0; float wind = 1.95 * rpm; // converts rotational velocity to linear velocity - circle speed to straight speed - rpms to mph :) lastTime = currentTime; lastTicks = currentTicks; return wind; } return 0.0;}void updateEncoder() { int a = digitalRead(ENCODER_A); encoderTicks++; return encoderTicks;}int readEncoder() { int aState = digitalRead(encoderPin_1); int bState = digitalRead(encoderPin_2); if (aState != lastAState) { if (bState != aState) { pulseCount++; } else { pulseCount--; } } int anny = (pulseCount / 600.0000) * 360; //converts pulses to degrees if (anny <= -0.1) { // keeps the reading between 0 and 359 degrees anny = anny + 360; } if (anny >= 360) { // keeps the reading between 0 and 359 degrees anny = anny - 360; } lastAState = aState; return anny;}void tipDetected() { tipCount++;}This is a screenshot example of my system.log file showing good data as well as the Pi not waiting for new data to trigger a new response
After this, if unsolved, I will toss the project out and reuse components for other projects down the line. Too much time spent...thanks as always
Statistics: Posted by Osprey72 — Thu Jul 24, 2025 1:48 pm