mirror of
https://github.com/weewx/weewx.git
synced 2026-04-18 16:46:56 -04:00
Merge branch 'master' into development
This commit is contained in:
@@ -3,8 +3,18 @@ WeeWX change history
|
||||
|
||||
### 5.2.1 MM/DD/YYYY
|
||||
|
||||
Remove unnecessary `UNIQUE` index on `PRIMARY KEY` columns in SQLite, achieving
|
||||
size reduction of ~10%. Existing database schemas are not modified. Users
|
||||
desiring size reduction are advised to consider manually migrating.
|
||||
|
||||
Fix problem that prevented `weectl database reconfigure` from working in cases
|
||||
where a schema was specified.
|
||||
|
||||
Fix problem when importing data into a MySQL database. PR
|
||||
#[1025](https://github.com/weewx/weewx/pull/1025). Thanks to user Robert!
|
||||
[#1025](https://github.com/weewx/weewx/pull/1025). Thanks to user Robert!
|
||||
|
||||
Fix problem that prevented `weewxd` from restarting reliably if a MySQL
|
||||
connection was lost. Fixes [Issue #1036](https://github.com/weewx/weewx/pull/1036).
|
||||
|
||||
|
||||
### 5.2.0 10/05/2025
|
||||
@@ -21,14 +31,13 @@ namespace. Addresses [Issue #993](https://github.com/weewx/weewx/issues/993).
|
||||
The WeeWX Almanac is now extensible, allowing other astronomy packages to be
|
||||
used besides `pyephem`. In particular, a WeeWX extension that uses the
|
||||
[Skyfield](https://rhodesmill.org/skyfield/) package is available and can be
|
||||
installed. See [Issue #981](https://github.com/weewx/weewx/issues/981) and [PR
|
||||
#988](https://github.com/weewx/weewx/pull/988). Thanks to user Johanna!
|
||||
installed. See [Issue #981](https://github.com/weewx/weewx/issues/981)
|
||||
and [PR #988](https://github.com/weewx/weewx/pull/988). Thanks to user Johanna!
|
||||
|
||||
Fix LOGNAME bug in the weewx-multi sysV script. Thanks to Glenn McKechnie.
|
||||
|
||||
Added `illuminance` to the `wview_extended` schema. See [Issue
|
||||
#992](https://github.com/weewx/weewx/issues/991) and [PR
|
||||
#992](https://github.com/weewx/weewx/pull/992/files). Thanks to user Jeremy!
|
||||
Added `illuminance` to the `wview_extended` schema. See [Issue #992](https://github.com/weewx/weewx/issues/991)
|
||||
and [PR #992](https://github.com/weewx/weewx/pull/992/files). Thanks to user Jeremy!
|
||||
|
||||
Fix typo that causes phantom values of `soilMoist3` to appear with VantageVue
|
||||
stations.
|
||||
@@ -52,15 +61,13 @@ Ben Cotton!
|
||||
In the Cumulus import code, the prefix `cur_` is used to signify a current value
|
||||
for most observation types. However, there was one exception: `curr_in_temp`.
|
||||
The utility and documentation have been changed to use `cur_in_temp` (one
|
||||
'`r`'), making all types consistent. Fixes [Issue
|
||||
#1006](https://github.com/weewx/weewx/issues/1006).
|
||||
'`r`'), making all types consistent. Fixes [Issue #1006](https://github.com/weewx/weewx/issues/1006).
|
||||
|
||||
Fix a problem caused by an assumption that delta times are always in seconds.
|
||||
Fixes issue [Issue #1009](https://github.com/weewx/weewx/issues/1009).
|
||||
|
||||
Fix bug that prevented arbitrary types from being used with `weectl database
|
||||
add-column`. Fixes issue [Issue
|
||||
#1007](https://github.com/weewx/weewx/issues/1007).
|
||||
add-column`. Fixes issue [Issue #1007](https://github.com/weewx/weewx/issues/1007).
|
||||
|
||||
Fix bug that prevented MySQL and MariaDB versions greater than 10.0 from
|
||||
working. Fixes issue [Issue #1010](https://github.com/weewx/weewx/issues/1010).
|
||||
|
||||
@@ -124,6 +124,8 @@ directly underneath. When you're done, it should look something like this:
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Finally, `weewx.restx.StdWOWBE` should be added into `restful_services`.
|
||||
|
||||
|
||||
### Luminosity and Illuminance
|
||||
|
||||
|
||||
@@ -91,3 +91,15 @@ again assuming user `weewx` with password `weewx`. Adjust as necessary.
|
||||
CREATE USER 'weewx'@'localhost' IDENTIFIED BY 'weewx';
|
||||
GRANT select, update, create, delete, insert, alter, drop ON weewx.* TO weewx@localhost;
|
||||
```
|
||||
|
||||
### 5. Make sure MySQL/MariaDB starts before WeeWX
|
||||
|
||||
Locate your WeeWX service file. Depending on your installation method, it will
|
||||
located at either `/lib/systemd/system/weewx.service` or `/etc/systemd/system/weewx.service`).
|
||||
Under the `[Unit]` section, add the following lines:
|
||||
|
||||
```ini
|
||||
After=mariadb.service mysqld.service
|
||||
Wants=mariadb.service mysqld.service
|
||||
```
|
||||
This will ensure that MySQL/MariaDB starts before WeeWX.
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2009-2024 Tom Keffer <tkeffer@gmail.com>
|
||||
# Copyright (c) 2009-2025 Tom Keffer <tkeffer@gmail.com>
|
||||
#
|
||||
# See the file LICENSE.txt for your full rights.
|
||||
#
|
||||
@@ -8,16 +8,19 @@
|
||||
import decimal
|
||||
|
||||
try:
|
||||
# Typically supplied by the "mysqlclient" package.
|
||||
import MySQLdb
|
||||
except ImportError:
|
||||
# Maybe the user has "pymysql", a pure-Python version?
|
||||
# Typically supplied by the "pymysql" package, a pure-Python version.
|
||||
import pymysql as MySQLdb
|
||||
from pymysql import DatabaseError as MySQLDatabaseError
|
||||
from pymysql import (DatabaseError as MySQLDatabaseError,
|
||||
InterfaceError as MySQLInterfaceError)
|
||||
else:
|
||||
try:
|
||||
from MySQLdb import DatabaseError as MySQLDatabaseError
|
||||
except ImportError:
|
||||
from _mysql_exceptions import DatabaseError as MySQLDatabaseError
|
||||
from _mysql_exceptions import (DatabaseError as MySQLDatabaseError,
|
||||
InterfaceError as MySQLInterfaceError)
|
||||
|
||||
from weeutil.weeutil import to_bool, natural_compare
|
||||
import weedb
|
||||
@@ -60,6 +63,8 @@ def guard(fn):
|
||||
# Default exception is weedb.DatabaseError
|
||||
klass = exception_map.get(errno, weedb.DatabaseError)
|
||||
raise klass(e)
|
||||
except MySQLInterfaceError as e:
|
||||
raise weedb.DisconnectError(e)
|
||||
|
||||
return guarded_fn
|
||||
|
||||
|
||||
@@ -268,7 +268,7 @@ class Cursor(sqlite3.Cursor, weedb.Cursor):
|
||||
if obs_name in column_names:
|
||||
continue
|
||||
no_null_str = " NOT NULL" if no_null else ""
|
||||
pk_str = " UNIQUE PRIMARY KEY" if pk else ""
|
||||
pk_str = " PRIMARY KEY" if pk else ""
|
||||
default_str = " DEFAULT %s" % default if default is not None else ""
|
||||
create_list.append("`%s` %s%s%s%s" % (obs_name, obs_type, no_null_str,
|
||||
pk_str, default_str))
|
||||
|
||||
@@ -150,7 +150,7 @@ class TestMySQL(unittest.TestCase):
|
||||
with Cursor(user='weewx1', password='weewx1') as cursor:
|
||||
cursor.execute("CREATE DATABASE test_weewx1")
|
||||
cursor.execute("CREATE TABLE test_weewx1.test1 "
|
||||
"( dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY, col1 int, col2 int)")
|
||||
"( dateTime INTEGER NOT NULL PRIMARY KEY, col1 int, col2 int)")
|
||||
cursor.execute("INSERT INTO test_weewx1.test1 "
|
||||
"(dateTime, col1, col2) VALUES (1, 10, 20)")
|
||||
with self.assertRaises(IntegrityError) as e:
|
||||
|
||||
@@ -100,7 +100,7 @@ class TestSqlite3(unittest.TestCase):
|
||||
|
||||
def test_duplicate_key(self):
|
||||
with Cursor(sqdb1) as cursor:
|
||||
cursor.execute("CREATE TABLE test1 ( dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY, col1 int, col2 int)")
|
||||
cursor.execute("CREATE TABLE test1 ( dateTime INTEGER NOT NULL PRIMARY KEY, col1 int, col2 int)")
|
||||
cursor.execute("INSERT INTO test1 (dateTime, col1, col2) VALUES (1, 10, 20)")
|
||||
with self.assertRaises(IntegrityError) as e:
|
||||
cursor.execute("INSERT INTO test1 (dateTime, col1, col2) VALUES (1, 30, 40)")
|
||||
|
||||
@@ -180,7 +180,7 @@ class Common(unittest.TestCase):
|
||||
weedb.create(db_dict)
|
||||
connect = weedb.connect(db_dict)
|
||||
cursor = connect.cursor()
|
||||
cursor.execute("CREATE TABLE test1 ( dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY, col1 int, col2 int)")
|
||||
cursor.execute("CREATE TABLE test1 ( dateTime INTEGER NOT NULL PRIMARY KEY, col1 int, col2 int)")
|
||||
cursor.execute("INSERT INTO test1 (dateTime, col1, col2) VALUES (1, 10, 20)")
|
||||
with self.assertRaises(weedb.IntegrityError) as e:
|
||||
cursor.execute("INSERT INTO test1 (dateTime, col1, col2) VALUES (1, 30, 40)")
|
||||
|
||||
@@ -48,10 +48,10 @@ class Common(unittest.TestCase):
|
||||
weedb.create(self.db_dict)
|
||||
with weedb.connect(self.db_dict) as _connect:
|
||||
with weedb.Transaction(_connect) as _cursor:
|
||||
_cursor.execute("CREATE TABLE test1 (dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY,"
|
||||
_cursor.execute("CREATE TABLE test1 (dateTime INTEGER NOT NULL PRIMARY KEY,"
|
||||
" min REAL, mintime INTEGER, max REAL, maxtime INTEGER, sum REAL,"
|
||||
" count INTEGER, descript CHAR(20));")
|
||||
_cursor.execute("CREATE TABLE test2 (dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY,"
|
||||
_cursor.execute("CREATE TABLE test2 (dateTime INTEGER NOT NULL PRIMARY KEY,"
|
||||
" min REAL, mintime INTEGER, max REAL, maxtime INTEGER, sum REAL, "
|
||||
"count INTEGER, descript CHAR(20));")
|
||||
for irec in range(20):
|
||||
@@ -151,7 +151,7 @@ class Common(unittest.TestCase):
|
||||
with weedb.connect(self.db_dict) as _connect:
|
||||
with _connect.cursor() as _cursor:
|
||||
_cursor.execute(
|
||||
"CREATE TABLE test1 (dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY, x REAL )")
|
||||
"CREATE TABLE test1 (dateTime INTEGER NOT NULL PRIMARY KEY, x REAL )")
|
||||
|
||||
# Now start the transaction
|
||||
_connect.begin()
|
||||
@@ -176,7 +176,7 @@ class Common(unittest.TestCase):
|
||||
# create the table outside the transaction. We're not as concerned about a
|
||||
# transaction failing when creating a table, because it only happens the first time
|
||||
# weewx starts up.
|
||||
_connect.execute("CREATE TABLE test1 (dateTime INTEGER NOT NULL UNIQUE PRIMARY KEY, "
|
||||
_connect.execute("CREATE TABLE test1 (dateTime INTEGER NOT NULL PRIMARY KEY, "
|
||||
"x REAL );")
|
||||
|
||||
# We're going to trigger the rollback by raising a bogus exception.
|
||||
|
||||
@@ -65,9 +65,9 @@ import weedb
|
||||
import weeutil.config
|
||||
import weeutil.weeutil
|
||||
import weewx.accum
|
||||
import weewx.units
|
||||
import weewx.xtypes
|
||||
from weeutil.weeutil import timestamp_to_string, to_int, TimeSpan
|
||||
from weewx.units import GenWithConvert
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -708,8 +708,7 @@ def reconfig(old_db_dict, new_db_dict, new_unit_system=None, new_schema=None, dr
|
||||
new_schema = weewx.schemas.wview_extended.schema
|
||||
with Manager.open_with_create(new_db_dict, schema=new_schema) as new_archive:
|
||||
# Wrap the input generator in a unit converter.
|
||||
record_generator = weewx.units.GenWithConvert(old_archive.genBatchRecords(),
|
||||
new_unit_system)
|
||||
record_generator = GenWithConvert(old_archive.genBatchRecords(), new_unit_system)
|
||||
if not dry_run:
|
||||
# This is very fast because it is done in a single transaction context:
|
||||
new_archive.addRecord(record_generator)
|
||||
@@ -1017,7 +1016,7 @@ class DaySummaryManager(Manager):
|
||||
# Schemas used by the daily summaries:
|
||||
day_schemas = {
|
||||
'scalar': [
|
||||
('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('min', 'REAL'),
|
||||
('mintime', 'INTEGER'),
|
||||
('max', 'REAL'),
|
||||
@@ -1028,7 +1027,7 @@ class DaySummaryManager(Manager):
|
||||
('sumtime', 'INTEGER')
|
||||
],
|
||||
'vector': [
|
||||
('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('min', 'REAL'),
|
||||
('mintime', 'INTEGER'),
|
||||
('max', 'REAL'),
|
||||
@@ -1048,7 +1047,7 @@ class DaySummaryManager(Manager):
|
||||
|
||||
# SQL statements used by the metadata in the daily summaries.
|
||||
meta_create_str = "CREATE TABLE %s_day__metadata (name CHAR(20) NOT NULL " \
|
||||
"UNIQUE PRIMARY KEY, value TEXT);"
|
||||
"PRIMARY KEY, value TEXT);"
|
||||
meta_replace_str = "REPLACE INTO %s_day__metadata VALUES(?, ?)"
|
||||
meta_select_str = "SELECT value FROM %s_day__metadata WHERE name=?"
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# with V4, a new style was added, which allows schema for the daily summaries
|
||||
# to be expressed explicitly.
|
||||
# =============================================================================
|
||||
schema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
schema = [('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('usUnits', 'INTEGER NOT NULL'),
|
||||
('interval', 'INTEGER NOT NULL'),
|
||||
('barometer', 'REAL'),
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# =============================================================================
|
||||
# NB: This schema is specified using the WeeWX V4 "new-style" schema.
|
||||
# =============================================================================
|
||||
table = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
table = [('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('usUnits', 'INTEGER NOT NULL'),
|
||||
('interval', 'INTEGER NOT NULL'),
|
||||
('altimeter', 'REAL'),
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# =============================================================================
|
||||
# NB: This schema is specified using the WeeWX V4 "new-style" schema.
|
||||
# =============================================================================
|
||||
table = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
table = [('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('usUnits', 'INTEGER NOT NULL'),
|
||||
('interval', 'INTEGER NOT NULL'),
|
||||
('altimeter', 'REAL'),
|
||||
|
||||
@@ -22,7 +22,7 @@ weeutil.logger.setup('weetest_database')
|
||||
archive_sqlite = {'database_name': '/var/tmp/weewx_test/weedb.sdb', 'driver':'weedb.sqlite'}
|
||||
archive_mysql = {'database_name': 'test_weedb', 'user':'weewx1', 'password':'weewx1', 'driver':'weedb.mysql'}
|
||||
|
||||
archive_schema = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
archive_schema = [('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('usUnits', 'INTEGER NOT NULL'),
|
||||
('interval', 'INTEGER NOT NULL'),
|
||||
('barometer', 'REAL'),
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#
|
||||
# See the file LICENSE.txt for your full rights.
|
||||
#
|
||||
table = [('dateTime', 'INTEGER NOT NULL UNIQUE PRIMARY KEY'),
|
||||
table = [('dateTime', 'INTEGER NOT NULL PRIMARY KEY'),
|
||||
('usUnits', 'INTEGER NOT NULL'),
|
||||
('interval', 'INTEGER NOT NULL'),
|
||||
('altimeter', 'REAL'),
|
||||
|
||||
@@ -71,7 +71,7 @@ unit_system = metricwx
|
||||
lightning_distance = Blitzentfernung
|
||||
lightning_strike_count = Blitzanzahl
|
||||
luminosity = Helligkeit
|
||||
outHumidity = Luftfeuchte
|
||||
outHumidity = Außenluftfeuchte
|
||||
outTemp = Außentemperatur
|
||||
pressure = abs. Luftdruck # QFE
|
||||
pressureRate = Luftdruckänderung
|
||||
@@ -96,7 +96,7 @@ unit_system = metricwx
|
||||
windgustvec = Böen-Vektor
|
||||
windrun = Windverlauf
|
||||
windSpeed = Windgeschwindigkeit
|
||||
windvec = Wind-Vektor
|
||||
windvec = Windvektor
|
||||
|
||||
# used in Seasons skin but not defined
|
||||
feel = gefühlte Temperatur
|
||||
@@ -109,7 +109,7 @@ unit_system = metricwx
|
||||
rainBatteryStatus = Regenmesser
|
||||
referenceVoltage = Referenz
|
||||
rxCheckPercent = Signalqualität
|
||||
supplyVoltage = Versorgung
|
||||
supplyVoltage = Versorgungsspannung
|
||||
txBatteryStatus = Übertrager
|
||||
windBatteryStatus = Anemometer
|
||||
batteryStatus1 = Batterie1
|
||||
|
||||
@@ -155,7 +155,7 @@ unit_system = metricwx
|
||||
[Almanac]
|
||||
|
||||
# The labels to be used for the phases of the moon:
|
||||
moon_phases = Nymåne, Voksende månesigd, Voksende halvmåne, Voksende fullmåne, Fullmåne, Minkende fullmåne, Minkende halvmåne, Minkende månesigd
|
||||
moon_phases = Nymåne, Voksende sigd, Første kvarter, Voksende måne, Fullmåne, Avtakende måne, Siste kvarter, Avtakende sigd
|
||||
|
||||
[Texts]
|
||||
"About this station" = "Om denne stasjonen"
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
interval = Intervall
|
||||
lightning_distance = Blitzentfernung
|
||||
lightning_strike_count = Blitzanzahl
|
||||
outHumidity = Luftfeuchte
|
||||
outHumidity = Außenluftfeuchte
|
||||
outTemp = Außentemperatur
|
||||
pressure = abs. Luftdruck # QFE
|
||||
pressureRate = Luftdruckänderung
|
||||
@@ -65,7 +65,7 @@
|
||||
windgustvec = Böen-Vektor
|
||||
windrun = Windverlauf
|
||||
windSpeed = Windgeschwindigkeit
|
||||
windvec = Wind-Vektor
|
||||
windvec = Windvektor
|
||||
|
||||
# used in Seasons skin but not defined
|
||||
feel = gefühlte Temperatur
|
||||
@@ -78,7 +78,7 @@
|
||||
rainBatteryStatus = Regenmesser
|
||||
referenceVoltage = Referenz
|
||||
rxCheckPercent = Signalqualität
|
||||
supplyVoltage = Versorgung
|
||||
supplyVoltage = Versorgungsspannung
|
||||
txBatteryStatus = Übertrager
|
||||
windBatteryStatus = Anemometer
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ unit_system = metricwx
|
||||
[[Ordinates]]
|
||||
|
||||
# Ordinal directions. The last one should be for no wind direction
|
||||
directions = N, NNE, NØ, ØNØ, Ø, ØSØ, SØ, SSØ, S, SSV, SV, VSV, V, VNV, NV, NNV, N/A
|
||||
directions = N, NNØ, NØ, ØNØ, Ø, ØSØ, SØ, SSØ, S, SSV, SV, VSV, V, VNV, NV, NNV, N/A
|
||||
|
||||
[Labels]
|
||||
|
||||
@@ -111,7 +111,7 @@ unit_system = metricwx
|
||||
[Almanac]
|
||||
|
||||
# The labels to be used for the phases of the moon:
|
||||
moon_phases = Nymåne, Voksende månesigd, Halvmåne første kvarter, Voksende måne (ny), Fullmåne, Minkende måne (ne), Halvmåne siste kvarter, Minkende månesigd
|
||||
moon_phases = Nymåne, Voksende sigd, Første kvarter, Voksende måne, Fullmåne, Avtakende måne, Siste kvarter, Avtakende sigd
|
||||
|
||||
[Texts]
|
||||
"7-day" = "7-dager"
|
||||
|
||||
@@ -8,6 +8,14 @@ After=time-sync.target
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
|
||||
# If you are using MySQL uncomment the following lines:
|
||||
# After=mysqld.service
|
||||
# Wants=mysqld.service
|
||||
|
||||
# If you are using MariaDB uncomment the following lines:
|
||||
# After=mariadb.service
|
||||
# Wants=mariadb.service
|
||||
|
||||
[Service]
|
||||
ExecStart=WEEWX_PYTHON WEEWXD WEEWX_CFGDIR/weewx.conf
|
||||
StandardOutput=null
|
||||
|
||||
Reference in New Issue
Block a user