#:########################################################################################:# # TITLE: LOUNGE ENVIRONMENT SENSOR #:########################################################################################:# # REPO: # https://home.fox.co.nz/gitea/zorruno/zorruno-homeassistant/src/branch/master/esphome/esp-loungeenvironment.yaml #:########################################################################################:# # VERSIONS: # V1.5 2026-03-22 Updated yaml to zorruno layout V1.1; fixed units to °C; added # device_class/state_class; retained MQTT publishing and all existing logic # V1.4 2026-03-22 Updated yaml to zorruno layout V1.1; added MQTT publishing for # temperature, humidity and pressure; retained all existing sensor logic # V1.3 2026-03-22 Added MQTT publishing for temperature, humidity and pressure readings # V1.2 2026-02-16 Pressure tendency now 5-state over 3 hours + rate/hour, 1h removed # V1.1 2026-02-16 Added derived min/max sensors and pressure trend text sensors # V1.0 2026-02-16 Initial Version #:########################################################################################:# # HARDWARE: # - ESP32-C3 SuperMini # - BME280 (I2C) # - SDA = GPIO1 # - SCL = GPIO3 # - I2C address = 0x76 #:########################################################################################:# # OPERATION NOTES: # - Reads temperature, humidity and pressure from the BME280 every 20 seconds # - Publishes each fresh reading to local MQTT status topics: # - ${mqtt_local_status_topic}/temperature # - ${mqtt_local_status_topic}/humidity # - ${mqtt_local_status_topic}/pressure # - Tracks: # - Lowest Temp Overnight # - Highest Temp Today (Daytime) # - Highest/Lowest Temp This Month # - Highest/Lowest Temp Last Month # - Highest/Lowest Temp Last 24 Hours # - Lowest Humidity Overnight # - Highest Humidity Today (Daytime) # - Highest/Lowest Humidity This Month # - Highest/Lowest Humidity Last Month # - Highest/Lowest Humidity Last 24 Hours # - Pressure direction uses a 3-hour tendency: # - rising rapidly # - rising # - steady # - falling # - falling rapidly # - Pressure rate per hour is calculated from the 3-hour pressure delta #:########################################################################################:# # OFFLINE NOTES: # a) HA offline (network + MQTT online) # - Device continues reading sensors and publishing local MQTT status topics. # b) MQTT offline (or HA/MQTT offline) # - Device continues reading sensors and updating local derived values internally. # c) Entire WiFi/Network offline # - Accurate time is needed for daily/monthly min/max periods and pressure trend timing. # - If SNTP is unavailable, the fallback clock can drift and can be reset by power # cycling at 12pm (midday). #:########################################################################################:# substitutions: # Device Naming device_name: "esp-loungeenvironment" friendly_name: "Lounge Environment" description_comment: "Lounge Environment :: ESP32-C3 SuperMini + BME280 (Layout V1.1)" device_area: "Lounge" # Project Naming project_name: "ESP32-C3 SuperMini.BME280" project_version: "v1.5" # Passwords api_key: !secret esp-api_key ota_pass: !secret esp-ota_pass static_ip_address: !secret esp-loungeenvironment_ip # Layout V1.1 Required current_ip_address: ${static_ip_address} # MQTT Local Status mqtt_local_status_main_topic: !secret mqtt_status_main_topic mqtt_device_name: "lounge-environment" mqtt_local_status_topic: "${mqtt_local_status_main_topic}/${mqtt_device_name}" # General Settings log_level: "WARN" update_interval: "60s" # I2C Settings i2c_sda_pin: "GPIO1" i2c_scl_pin: "GPIO3" i2c_frequency: "100kHz" bmp_address: "0x76" # Pressure tendency thresholds (hPa over 3 hours) # - falling rapidly: <= -6.0 hPa / 3h # - falling: <= -1.0 hPa / 3h # - steady: between -1.0 and +1.0 hPa / 3h # - rising: >= +1.0 hPa / 3h # - rising rapidly: >= +6.0 hPa / 3h pressure_3h_steady_band: "1.0" pressure_3h_rapid_threshold: "6.0" ########################################################################################## # PACKAGES ########################################################################################## packages: common_wifi: !include file: common/network_common.yaml vars: local_device_name: "${device_name}" local_static_ip_address: "${static_ip_address}" local_current_ip_address: "${current_ip_address}" local_ota_pass: "${ota_pass}" common_api: !include file: common/api_common.yaml vars: local_api_key: "${api_key}" common_mqtt: !include file: common/mqtt_common.yaml vars: local_device_name: "${device_name}" # Provides: # - time id: sntp_time # - global: current_mins (minutes since midnight, fallback supported) # - text sensors: time_text, time_sync, device_last_restart common_sntp: !include common/sntp_common.yaml diag_basic: !include common/include_basic_diag_sensors.yaml diag_more: !include common/include_more_diag_sensors.yaml ########################################################################################## # ESPHOME ########################################################################################## esphome: name: "${device_name}" friendly_name: "${friendly_name}" comment: "${description_comment}" area: "${device_area}" name_add_mac_suffix: false min_version: 2026.1.0 project: name: "${project_name}" version: "${project_version}" ########################################################################################## # PLATFORM ########################################################################################## esp32: board: esp32-c3-devkitm-1 variant: ESP32C3 framework: type: esp-idf cpu_frequency: 80MHz preferences: flash_write_interval: 5min mdns: disabled: false ########################################################################################## # LOGGING ########################################################################################## logger: level: "${log_level}" baud_rate: 0 ########################################################################################## # I2C ########################################################################################## i2c: sda: ${i2c_sda_pin} scl: ${i2c_scl_pin} scan: true frequency: ${i2c_frequency} ########################################################################################## # GLOBALS (tracking min/max across time windows) ########################################################################################## globals: # Last completed overnight window (23:00 -> 07:00) min temperature - id: g_min_temp_today_overnight type: float restore_value: yes initial_value: "NAN" # Working overnight min temperature for the current 23:00 -> 07:00 window - id: g_work_min_temp_overnight type: float restore_value: no initial_value: "NAN" # Last completed daytime window (07:00 -> 23:00) max temperature - id: g_max_temp_today_daytime type: float restore_value: yes initial_value: "NAN" # Working daytime max temperature for the current 07:00 -> 23:00 window - id: g_work_max_temp_daytime type: float restore_value: no initial_value: "NAN" # Last completed overnight window (23:00 -> 07:00) min humidity - id: g_min_humidity_today_overnight type: float restore_value: yes initial_value: "NAN" # Working overnight min humidity for the current 23:00 -> 07:00 window - id: g_work_min_humidity_overnight type: float restore_value: no initial_value: "NAN" # Last completed daytime window (07:00 -> 23:00) max humidity - id: g_max_humidity_today_daytime type: float restore_value: yes initial_value: "NAN" # Working daytime max humidity for the current 07:00 -> 23:00 window - id: g_work_max_humidity_daytime type: float restore_value: no initial_value: "NAN" # Current month max temperature - id: g_max_temp_this_month type: float restore_value: yes initial_value: "NAN" # Last month max temperature - id: g_max_temp_last_month type: float restore_value: yes initial_value: "NAN" # Current month min temperature - id: g_min_temp_this_month type: float restore_value: yes initial_value: "NAN" # Last month min temperature - id: g_min_temp_last_month type: float restore_value: yes initial_value: "NAN" # Current month max humidity - id: g_max_humidity_this_month type: float restore_value: yes initial_value: "NAN" # Last month max humidity - id: g_max_humidity_last_month type: float restore_value: yes initial_value: "NAN" # Current month min humidity - id: g_min_humidity_this_month type: float restore_value: yes initial_value: "NAN" # Last month min humidity - id: g_min_humidity_last_month type: float restore_value: yes initial_value: "NAN" # Track current calendar month/year so we can roll over month stats - id: g_current_month type: int restore_value: yes initial_value: "0" - id: g_current_year type: int restore_value: yes initial_value: "0" # Hour-bucket rolling 24h min/max temperature - id: g_temp_hour_min type: std::array restore_value: no initial_value: "{NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN}" - id: g_temp_hour_max type: std::array restore_value: no initial_value: "{NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN}" - id: g_temp_hour_ts type: std::array restore_value: no initial_value: "{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}" # Hour-bucket rolling 24h min/max humidity - id: g_hum_hour_min type: std::array restore_value: no initial_value: "{NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN}" - id: g_hum_hour_max type: std::array restore_value: no initial_value: "{NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN}" - id: g_hum_hour_ts type: std::array restore_value: no initial_value: "{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}" # Pressure sampling (every 5 minutes) for trend calculation - id: g_pressure_samples type: std::array restore_value: no initial_value: "{NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN}" - id: g_pressure_ts type: std::array restore_value: no initial_value: "{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}" - id: g_pressure_idx type: int restore_value: no initial_value: "0" ########################################################################################## # SENSORS ########################################################################################## sensor: - platform: bme280_i2c address: ${bmp_address} update_interval: 20s temperature: name: "${friendly_name} Temperature" id: lounge_temperature unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 filters: - offset: -2.9 on_value: then: # Publish current temperature to local MQTT status topic - mqtt.publish: topic: "${mqtt_local_status_topic}/temperature" payload: !lambda |- char buffer[32]; snprintf(buffer, sizeof(buffer), "%.2f", x); return std::string(buffer); - lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return; const int hour = now.hour; const uint32_t now_ts = now.timestamp; { int idx = hour; if (idx < 0) idx = 0; if (idx > 23) idx = 23; id(g_temp_hour_ts)[idx] = now_ts; float v = x; if (isnan(id(g_temp_hour_min)[idx]) || v < id(g_temp_hour_min)[idx]) id(g_temp_hour_min)[idx] = v; if (isnan(id(g_temp_hour_max)[idx]) || v > id(g_temp_hour_max)[idx]) id(g_temp_hour_max)[idx] = v; } const int mins = id(current_mins); const bool in_overnight = (mins >= 1380) || (mins < 420); if (in_overnight) { if (isnan(id(g_work_min_temp_overnight)) || x < id(g_work_min_temp_overnight)) { id(g_work_min_temp_overnight) = x; } } else { if (isnan(id(g_work_max_temp_daytime)) || x > id(g_work_max_temp_daytime)) { id(g_work_max_temp_daytime) = x; } } if (isnan(id(g_min_temp_this_month)) || x < id(g_min_temp_this_month)) id(g_min_temp_this_month) = x; if (isnan(id(g_max_temp_this_month)) || x > id(g_max_temp_this_month)) id(g_max_temp_this_month) = x; pressure: name: "${friendly_name} Pressure" id: lounge_pressure unit_of_measurement: "hPa" device_class: pressure state_class: measurement accuracy_decimals: 2 on_value: then: # Publish current pressure to local MQTT status topic - mqtt.publish: topic: "${mqtt_local_status_topic}/pressure" payload: !lambda |- char buffer[32]; snprintf(buffer, sizeof(buffer), "%.2f", x); return std::string(buffer); humidity: name: "${friendly_name} Humidity" id: lounge_humidity unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 on_value: then: # Publish current humidity to local MQTT status topic - mqtt.publish: topic: "${mqtt_local_status_topic}/humidity" payload: !lambda |- char buffer[32]; snprintf(buffer, sizeof(buffer), "%.1f", x); return std::string(buffer); - lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return; const int hour = now.hour; const uint32_t now_ts = now.timestamp; { int idx = hour; if (idx < 0) idx = 0; if (idx > 23) idx = 23; id(g_hum_hour_ts)[idx] = now_ts; float v = x; if (isnan(id(g_hum_hour_min)[idx]) || v < id(g_hum_hour_min)[idx]) id(g_hum_hour_min)[idx] = v; if (isnan(id(g_hum_hour_max)[idx]) || v > id(g_hum_hour_max)[idx]) id(g_hum_hour_max)[idx] = v; } const int mins = id(current_mins); const bool in_overnight = (mins >= 1380) || (mins < 420); if (in_overnight) { if (isnan(id(g_work_min_humidity_overnight)) || x < id(g_work_min_humidity_overnight)) { id(g_work_min_humidity_overnight) = x; } } else { if (isnan(id(g_work_max_humidity_daytime)) || x > id(g_work_max_humidity_daytime)) { id(g_work_max_humidity_daytime) = x; } } if (isnan(id(g_min_humidity_this_month)) || x < id(g_min_humidity_this_month)) id(g_min_humidity_this_month) = x; if (isnan(id(g_max_humidity_this_month)) || x > id(g_max_humidity_this_month)) id(g_max_humidity_this_month) = x; # min_temp_today_overnight (this is the min temp, from 11pm to 7am for the last daily period) - platform: template name: "Lowest Temp Overnight" id: min_temp_today_overnight unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_min_temp_today_overnight); # max_temp_today_daytime (this is the max temp, from 7am to 11pm for the last daily period) - platform: template name: "Highest Temp Today (Daytime)" id: max_temp_today_daytime unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_max_temp_today_daytime); # max_temp_this_month (max for this current calendar month) - platform: template name: "Highest Temp This Month" id: max_temp_this_month unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_max_temp_this_month); # max_temp_last_month (max for this last calendar month) - platform: template name: "Highest Temp Last Month" id: max_temp_last_month unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_max_temp_last_month); # min_temp_this_month (min for this current calendar month) - platform: template name: "Lowest Temp This Month" id: min_temp_this_month unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_min_temp_this_month); # min_temp_last_month (min for this last calendar month) - platform: template name: "Lowest Temp Last Month" id: min_temp_last_month unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- return id(g_min_temp_last_month); # min_temp_today (min temp for last rolling 24 hours) - platform: template name: "Lowest Temp Last 24 Hours" id: min_temp_today unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return NAN; const uint32_t now_ts = now.timestamp; float m = NAN; for (int i = 0; i < 24; i++) { if (id(g_temp_hour_ts)[i] == 0) continue; if ((now_ts - id(g_temp_hour_ts)[i]) > 86400) continue; float v = id(g_temp_hour_min)[i]; if (isnan(v)) continue; if (isnan(m) || v < m) m = v; } return m; # max_temp_today (max temp for last rolling 24 hours) - platform: template name: "Highest Temp Last 24 Hours" id: max_temp_today unit_of_measurement: "°C" device_class: temperature state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return NAN; const uint32_t now_ts = now.timestamp; float m = NAN; for (int i = 0; i < 24; i++) { if (id(g_temp_hour_ts)[i] == 0) continue; if ((now_ts - id(g_temp_hour_ts)[i]) > 86400) continue; float v = id(g_temp_hour_max)[i]; if (isnan(v)) continue; if (isnan(m) || v > m) m = v; } return m; # min_humidity_today_overnight (this is the min humidity, from 11pm to 7am for the last daily period) - platform: template name: "Lowest Humidity Overnight" id: min_humidity_today_overnight unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_min_humidity_today_overnight); # max_humidity_today_daytime (this is the max humidity, from 7am to 11pm for the last daily period) - platform: template name: "Highest Humidity Today (Daytime)" id: max_humidity_today_daytime unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_max_humidity_today_daytime); # max_humidity_this_month (max for this current calendar month) - platform: template name: "Highest Humidity This Month" id: max_humidity_this_month unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_max_humidity_this_month); # max_humidity_last_month (max for this last calendar month) - platform: template name: "Highest Humidity Last Month" id: max_humidity_last_month unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_max_humidity_last_month); # min_humidity_this_month (min for this current calendar month) - platform: template name: "Lowest Humidity This Month" id: min_humidity_this_month unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_min_humidity_this_month); # min_humidity_last_month (min for this last calendar month) - platform: template name: "Lowest Humidity Last Month" id: min_humidity_last_month unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- return id(g_min_humidity_last_month); # min_humidity_today (min humidity for last rolling 24 hours) - platform: template name: "Lowest Humidity Last 24 Hours" id: min_humidity_today unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return NAN; const uint32_t now_ts = now.timestamp; float m = NAN; for (int i = 0; i < 24; i++) { if (id(g_hum_hour_ts)[i] == 0) continue; if ((now_ts - id(g_hum_hour_ts)[i]) > 86400) continue; float v = id(g_hum_hour_min)[i]; if (isnan(v)) continue; if (isnan(m) || v < m) m = v; } return m; # max_humidity_today (max humidity for last rolling 24 hours) - platform: template name: "Highest Humidity Last 24 Hours" id: max_humidity_today unit_of_measurement: "%" device_class: humidity state_class: measurement accuracy_decimals: 1 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return NAN; const uint32_t now_ts = now.timestamp; float m = NAN; for (int i = 0; i < 24; i++) { if (id(g_hum_hour_ts)[i] == 0) continue; if ((now_ts - id(g_hum_hour_ts)[i]) > 86400) continue; float v = id(g_hum_hour_max)[i]; if (isnan(v)) continue; if (isnan(m) || v > m) m = v; } return m; # Pressure Rate Per Hour (3h) (hPa/hour based on delta over the last ~3 hours) - platform: template name: "Pressure Rate Per Hour (3h)" id: pressure_rate_per_hour_3h unit_of_measurement: "hPa/h" state_class: measurement accuracy_decimals: 2 update_interval: 60s lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return NAN; const uint32_t now_ts = now.timestamp; const uint32_t target_ts = now_ts - 10800; float past = NAN; uint32_t best_dt = 0xFFFFFFFF; for (int i = 0; i < 40; i++) { uint32_t ts = id(g_pressure_ts)[i]; if (ts == 0) continue; uint32_t dt = (ts > target_ts) ? (ts - target_ts) : (target_ts - ts); if (dt < best_dt) { best_dt = dt; past = id(g_pressure_samples)[i]; } } float cur = id(lounge_pressure).state; if (isnan(cur) || isnan(past)) return NAN; float delta_3h = cur - past; return delta_3h / 3.0f; ########################################################################################## # TEXT SENSORS (pressure tendency) ########################################################################################## text_sensor: # Pressure Direction, Last 3 Hours (5-state tendency over the last ~3 hours) - platform: template name: "Pressure Direction, Last 3 Hours" id: pressure_rising_or_falling_3_hours update_interval: 60s lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return std::string("unknown"); const uint32_t now_ts = now.timestamp; const uint32_t target_ts = now_ts - 10800; float past = NAN; uint32_t best_dt = 0xFFFFFFFF; for (int i = 0; i < 40; i++) { uint32_t ts = id(g_pressure_ts)[i]; if (ts == 0) continue; uint32_t dt = (ts > target_ts) ? (ts - target_ts) : (target_ts - ts); if (dt < best_dt) { best_dt = dt; past = id(g_pressure_samples)[i]; } } float cur = id(lounge_pressure).state; if (isnan(cur) || isnan(past)) return std::string("unknown"); float delta_3h = cur - past; float steady_band = atof("${pressure_3h_steady_band}"); float rapid_thr = atof("${pressure_3h_rapid_threshold}"); if (delta_3h >= rapid_thr) return std::string("rising rapidly"); if (delta_3h >= steady_band) return std::string("rising"); if (delta_3h <= -rapid_thr) return std::string("falling rapidly"); if (delta_3h <= -steady_band) return std::string("falling"); return std::string("steady"); ########################################################################################## # INTERVALS (rollover overnight/daytime periods, month rollover, and pressure sampling) ########################################################################################## interval: # Sample pressure every 5 minutes for trend calculations - interval: 5min then: - lambda: |- auto now = id(sntp_time).now(); if (!now.is_valid()) return; float p = id(lounge_pressure).state; if (isnan(p)) return; const uint32_t ts = now.timestamp; int idx = id(g_pressure_idx); if (idx < 0) idx = 0; if (idx > 39) idx = 0; id(g_pressure_samples)[idx] = p; id(g_pressure_ts)[idx] = ts; idx++; if (idx >= 40) idx = 0; id(g_pressure_idx) = idx; # Check period boundaries once a minute (uses current_mins, works during fallback) - interval: 60s then: - lambda: |- const int mins = id(current_mins); const bool at_0700 = (mins == 420); const bool at_2300 = (mins == 1380); if (at_0700) { id(g_min_temp_today_overnight) = id(g_work_min_temp_overnight); id(g_work_min_temp_overnight) = NAN; id(g_min_humidity_today_overnight) = id(g_work_min_humidity_overnight); id(g_work_min_humidity_overnight) = NAN; } if (at_2300) { id(g_max_temp_today_daytime) = id(g_work_max_temp_daytime); id(g_work_max_temp_daytime) = NAN; id(g_max_humidity_today_daytime) = id(g_work_max_humidity_daytime); id(g_work_max_humidity_daytime) = NAN; } auto now = id(sntp_time).now(); if (!now.is_valid()) return; const int mon = now.month; const int yr = now.year; if (id(g_current_month) == 0 || id(g_current_year) == 0) { id(g_current_month) = mon; id(g_current_year) = yr; } if (mon != id(g_current_month) || yr != id(g_current_year)) { id(g_max_temp_last_month) = id(g_max_temp_this_month); id(g_min_temp_last_month) = id(g_min_temp_this_month); id(g_max_humidity_last_month) = id(g_max_humidity_this_month); id(g_min_humidity_last_month) = id(g_min_humidity_this_month); id(g_max_temp_this_month) = NAN; id(g_min_temp_this_month) = NAN; id(g_max_humidity_this_month) = NAN; id(g_min_humidity_this_month) = NAN; id(g_current_month) = mon; id(g_current_year) = yr; }