Didn't Karen K have something of this sort in her repo? The above will only work with metric db, will it?
Dr Henk Harms schrieb am Montag, 24. März 2025 um 06:56:39 UTC+1: > > 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 <drhen...@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. <ozcz...@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+...@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/6508b98a-abff-425d-8c84-c417cafb13ddn%40googlegroups.com.