So been "messing with it" To create a table. CREATE TABLE archive_bom_minmax ( dateTime INTEGER NOT NULL PRIMARY KEY, usUnits INTEGER NOT NULL, `interval` INTEGER NOT NULL, min_temp DOUBLE, min_temp_time INTEGER, max_temp DOUBLE, max_temp_time INTEGER );
Then add this to /usr/share/weewx/user #!/usr/bin/env python # -*- coding: utf-8 -*- """ bom_minmax.py - WeeWX service to record BoM-compliant min/max temperatures This service records minimum and maximum temperatures between 6pm the previous day and 9am the current day, storing them at 9am in a dedicated table. """ import datetime import time import weedb import weewx from weewx.engine import StdService # Try to use new-style WeeWX V5 logging try: import logging log = logging.getLogger(__name__) def logdbg(msg): log.debug(msg) def loginf(msg): log.info(msg) def logerr(msg): log.error(msg) except (ImportError, AttributeError): # Use old-style WeeWX V4 logging via syslog import syslog def logmsg(level, msg): syslog.syslog(level, 'bom_minmax: %s' % msg) def logdbg(msg): logmsg(syslog.LOG_DEBUG, msg) def loginf(msg): logmsg(syslog.LOG_INFO, msg) def logerr(msg): logmsg(syslog.LOG_ERR, msg) # BoM observation time configuration BOM_MORNING_HOUR = 9 # 9am BOM_EVENING_HOUR = 18 # 6pm class BomMinMaxService(StdService): """Service to record min/max temperatures in BoM format.""" def __init__(self, engine, config_dict): super(BomMinMaxService, self).__init__(engine, config_dict) loginf("Starting BoM Min/Max Temperature Service") # Get the database configuration self.db_dict = config_dict.get('BomMinMax', {}) # Archive database binding - where to get temperature data from self.archive_binding = self.db_dict.get('archive_binding', 'wx_binding') # Output database binding - where to store BoM min/max data self.output_binding = self.db_dict.get('output_binding', 'wx_binding') # Table name for BoM min/max data self.table_name = self.db_dict.get('table_name', 'archive_bom_minmax') # Temperature field to use self.temp_field = self.db_dict.get('temp_field', 'outTemp') # Initialize the table if it doesn't exist # Commented out for stability #self.init_table() # Bind to archive events self.bind(weewx.NEW_ARCHIVE_RECORD, self.new_archive_record) loginf("BoM Min/Max Temperature Service initialized") def init_table(self): """Initialize the table if it doesn't exist.""" try: with self.engine.db_binder.get_manager(self.output_binding) as dbm: # Check if table exists if self.table_name not in dbm.connection.tables(): loginf(f"Creating table {self.table_name}") # Create the table dbm.connection.execute( f"CREATE TABLE {self.table_name} (" f"dateTime INTEGER NOT NULL PRIMARY KEY, " f"usUnits INTEGER NOT NULL, " f"`interval` INTEGER NOT NULL, " f"min_temp DOUBLE, " f"min_temp_time INTEGER, " f"max_temp DOUBLE, " f"max_temp_time INTEGER)" ) except Exception as e: logerr(f"Error initializing table: {e}") def new_archive_record(self, event): """Called when a new archive record is available. Check if it's just after 9am and if so, record the min/max data for the 6pm-9am period. """ timestamp = event.record['dateTime'] dt = datetime.datetime.fromtimestamp(timestamp) # Only process records at or just after 9am if dt.hour == BOM_MORNING_HOUR and dt.minute < 10: self.process_bom_minmax(timestamp) def process_bom_minmax(self, current_ts): """Process and record BoM min/max temperatures. Args: current_ts: Current timestamp (around 9am) """ # Convert timestamp to datetime current_dt = datetime.datetime.fromtimestamp(current_ts) # Calculate the timestamp for 6pm yesterday yesterday = current_dt - datetime.timedelta(days=1) yesterday_6pm = datetime.datetime(yesterday.year, yesterday.month, yesterday.day, BOM_EVENING_HOUR, 0, 0) start_ts = int(yesterday_6pm.timestamp()) # Calculate the timestamp for 9am today today_9am = datetime.datetime(current_dt.year, current_dt.month, current_dt.day, BOM_MORNING_HOUR, 0, 0) end_ts = int(today_9am.timestamp()) loginf(f"Processing BoM min/max data for {yesterday_6pm.strftime( '%Y-%m-%d %H:%M')} to {today_9am.strftime('%Y-%m-%d %H:%M')}") try: # Get the temperature data from the archive with self.engine.db_binder.get_manager(self.archive_binding) as dbm_archive: # Get min temperature min_temp_data = dbm_archive.getSql( f"SELECT MIN({self.temp_field}), dateTime, usUnits FROM archive " f"WHERE dateTime >= {start_ts} AND dateTime <= {end_ts} " f"AND {self.temp_field} IS NOT NULL") # Get max temperature max_temp_data = dbm_archive.getSql( f"SELECT MAX({self.temp_field}), dateTime, usUnits FROM archive " f"WHERE dateTime >= {start_ts} AND dateTime <= {end_ts} " f"AND {self.temp_field} IS NOT NULL") # Skip if no data available if not min_temp_data or not max_temp_data: loginf("Insufficient temperature data for period, skipping") return # Create the record record = { 'dateTime': end_ts, 'usUnits': min_temp_data[2], # Use the same unit system from archive 'interval': 1440, # 24 hours in minutes 'min_temp': min_temp_data[0], 'min_temp_time': min_temp_data[1], 'max_temp': max_temp_data[0], 'max_temp_time': max_temp_data[1] } # Store in the output database with self.engine.db_binder.get_manager(self.output_binding) as dbm_output: dbm_output.addRecord(record) # Log the min/max data min_temp_time = datetime.datetime.fromtimestamp( min_temp_data[1]) max_temp_time = datetime.datetime.fromtimestamp( max_temp_data[1]) loginf(f"Recorded BoM min/max: Min {min_temp_data[0]:.1f}°C at {min_temp_time.strftime('%H:%M')}, " f"Max {max_temp_data[0]:.1f}°C at {max_temp_time. strftime('%H:%M')}") except Exception as e: logerr(f"Error processing BoM min/max: {e}") # To use this service, add to weewx.conf: # # [BomMinMax] # # Database binding to read temperature data from # archive_binding = wx_binding # # Database binding to store BoM min/max data (can be same as archive_binding) # output_binding = wx_binding # # Table name for BoM min/max data # table_name = archive_bom_minmax # # Temperature field to monitor (default: outTemp) # temp_field = outTemp # # [Engine] # [[Services]] # data_services = ..., user.bom_minmax.BomMinMaxService, ... That should work, I disable the table checking as that caused me to error. I also installed weewx as a package not via pip. Guess we know tomorrow here in AU if it works :-). Let me know how you go. H. (https://dayboro.au) On Mon, 24 Mar 2025 at 13:38, Dr Henk Harms <drhenkha...@gmail.com> wrote: > I ran that query or similar on my mariadb... took forever. > Would it not be simpler to have an table called archive_day_bom_minmax and > have a weewx service write to that table at 9am each day? > > > On Thu, 20 Mar 2025 at 18:31, Mike B. <ozcze...@gmail.com> wrote: > >> Hi All, >> >> I am trying to capture a new observation: "Highest Nighttime Min >> Temperature". I am using this logic "The running min, a value the Bureau Of >> Meteorology uses to highlight the lowest temperature between 6pm and 9am" >> >> I have a query against archive table (MariaDb) >> >> SELECT (x.night + INTERVAL 1 DAY) AS night, >> UNIX_TIMESTAMP(x.night), >> x.lowestNightTemp >> FROM ( >> SELECT CAST(FROM_UNIXTIME(dateTime) AS DATE) - INTERVAL >> 9 HOUR AS night, >> MAX((a.outTemp-32)*(5/9)) AS highestNightTemp, >> MIN((a.outTemp-32)*(5/9)) AS lowestNightTemp, >> DATE_ADD(DATE_SUB(CAST(FROM_UNIXTIME(dateTime) AS >> DATE), INTERVAL 1 DAY), INTERVAL 18 HOUR) AS DayBefore, >> DATE_ADD(CAST(FROM_UNIXTIME(dateTime) AS DATE), >> INTERVAL 9 HOUR) AS Day >> FROM archive AS a >> WHERE a.dateTime BETWEEN >> UNIX_TIMESTAMP(DATE_ADD(DATE_SUB(CAST >> (FROM_UNIXTIME(dateTime) AS DATE), INTERVAL 1 DAY), INTERVAL 18 HOUR)) >> AND >> UNIX_TIMESTAMP(DATE_ADD(CAST(FROM_UNIXTIME( >> dateTime) AS DATE), INTERVAL 9 HOUR)) >> GROUP BY night >> ) AS x >> ORDER BY x.lowestNightTemp DESC LIMIT 1 >> >> The above query seems to work, as it returns the Highest lowest >> Temperature between 6pm and 9am. >> >> I am trying to work out how to integrate this into the weewx process. I >> want to: >> * Run a service or something once a day (say midnight) and then for each >> "day" (defined as 6pm to 9am) store the summary >> * If I run rebuild daily summaries (weectl database) ideally this >> process should also run >> * Add result to records to have something like: >> "Highest Minimum overnight Temperature 29.111 C 23 Mar 2025" >> >> I created a service "class NighttimeTempTracker(StdService)" and added it >> to "data_services"...but it runs for each ARCHIVE PERIOD >> (weewx.NEW_ARCHIVE_RECORD) >> and cannot span multiple days. >> >> I am out of ideas in which ways I can achieve the above via weewx >> process. Any help, pointers, sample code or projects would be highly >> appreciated. >> >> Thanks >> >> Mike >> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "weewx-user" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to weewx-user+unsubscr...@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/weewx-user/31513f26-63d1-4e47-a903-9c584ba64a7cn%40googlegroups.com >> <https://groups.google.com/d/msgid/weewx-user/31513f26-63d1-4e47-a903-9c584ba64a7cn%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "weewx-user" group. To unsubscribe from this group and stop receiving emails from it, send an email to weewx-user+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/weewx-user/CANcmcPUCc5%2Bmoe2gZMTU1EH7yamNifLbX-M_Lxrh1wQHOAgG2A%40mail.gmail.com.