update to 1.0.2
This commit is contained in:
@@ -1,108 +0,0 @@
|
||||
from datetime import datetime, timedelta
|
||||
from pymodbus.client import ModbusSerialClient
|
||||
from solaxx3.rs485 import SolaxX3
|
||||
import mysql.connector
|
||||
|
||||
s = SolaxX3(port="/dev/ttyUSB0", baudrate=115200)
|
||||
|
||||
database_ip = "172.17.7.77"
|
||||
|
||||
if s.connect():
|
||||
s.read_all_registers()
|
||||
|
||||
# read the stats from the inverter
|
||||
battery_capacity = s.read("battery_capacity")[0]
|
||||
feed_in_today = s.read("feed_in_energy_today")[0]
|
||||
consumtion_today = s.read("consumption_energy_today")[0]
|
||||
battery_charging = s.read("battery_power_charge1")[0]
|
||||
grid_voltage_r = s.read("grid_voltage_r")[0]
|
||||
grid_voltage_s = s.read("grid_voltage_s")[0]
|
||||
grid_voltage_t = s.read("grid_voltage_t")[0]
|
||||
run_mode = s.read("run_mode")[0]
|
||||
time_count_down = s.read("time_count_down")[0]
|
||||
inverter_ac_power = s.read("grid_power")[0]
|
||||
etoday_togrid = s.read("energy_to_grid_today")[0]
|
||||
solar_energy_today = s.read("solar_energy_today")[0]
|
||||
echarge_today = s.read("echarge_today")[0]
|
||||
energy_from_grid = s.read("energy_from_grid_meter")[0]
|
||||
energy_to_grid = s.read("energy_to_grid_meter")[0]
|
||||
power_to_ev = s.read("power_to_ev")[0]
|
||||
feed_in_power = s.read("feed_in_power")[0]
|
||||
output_energy_charge = s.read("output_energy_charge")[0]
|
||||
output_energy_today = s.read("output_energy_charge_today")[0]
|
||||
input_energy_today = s.read("input_energy_charge_today")[0]
|
||||
power_dc1 = s.read("power_dc1")[0]
|
||||
power_dc2 = s.read("power_dc2")[0]
|
||||
total_power = power_dc1 + power_dc2
|
||||
uploadTime = s.read("rtc_datetime")[0]
|
||||
uploadDate = uploadTime.date()
|
||||
|
||||
timezone_difference_from_utc = 2
|
||||
uploadTime = uploadTime - timedelta(hours=timezone_difference_from_utc, minutes=0)
|
||||
|
||||
# store the stats in the database
|
||||
mydb = mysql.connector.connect(
|
||||
host=database_ip, user="root", passwd="rootroot", database="solax"
|
||||
)
|
||||
mycursor = mydb.cursor()
|
||||
|
||||
try:
|
||||
|
||||
# create the sql statement
|
||||
sql = """REPLACE INTO solax_local (
|
||||
uploadTime,
|
||||
inverter_status,
|
||||
dc_solar_power,
|
||||
grid_voltage_r,
|
||||
grid_voltage_s,
|
||||
grid_voltage_t,
|
||||
battery_capacity,
|
||||
battery_power,
|
||||
feed_in_power,
|
||||
time_count_down,
|
||||
inverter_ac_power,
|
||||
consumeenergy,
|
||||
feedinenergy,
|
||||
power_dc1,
|
||||
power_dc2
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
values = (
|
||||
uploadTime,
|
||||
run_mode,
|
||||
total_power,
|
||||
grid_voltage_r,
|
||||
grid_voltage_s,
|
||||
grid_voltage_t,
|
||||
battery_capacity,
|
||||
battery_charging,
|
||||
feed_in_power,
|
||||
time_count_down,
|
||||
inverter_ac_power,
|
||||
energy_from_grid,
|
||||
energy_to_grid,
|
||||
power_dc1,
|
||||
power_dc2,
|
||||
)
|
||||
|
||||
mycursor.execute(sql, values)
|
||||
mydb.commit()
|
||||
|
||||
# update daily values
|
||||
sql = """REPLACE INTO solax_daily (
|
||||
uploadDate,
|
||||
feed_in,
|
||||
total_yield
|
||||
) VALUES (%s, %s, %s)
|
||||
"""
|
||||
values = (uploadDate, feed_in_today, etoday_togrid)
|
||||
mycursor.execute(sql, values)
|
||||
mydb.commit()
|
||||
|
||||
except mysql.connector.Error as error:
|
||||
print("parameterized query failed {}".format(error))
|
||||
|
||||
else:
|
||||
print("Cannot connect to the Modbus Server/Slave")
|
||||
exit()
|
||||
19
source/database/data_source_db.py
Normal file
19
source/database/data_source_db.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Module containing an abstract class."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class DataSourceDb(ABC):
|
||||
"""Abstract class representing a data source."""
|
||||
|
||||
@abstractmethod
|
||||
def save_record(self):
|
||||
"""Transfer some data."""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
@abstractmethod
|
||||
def bulk_save(self):
|
||||
"""Transfer multiple records of data."""
|
||||
|
||||
raise NotImplementedError
|
||||
89
source/database/mysql_data_source.py
Normal file
89
source/database/mysql_data_source.py
Normal file
@@ -0,0 +1,89 @@
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
import mysql.connector
|
||||
|
||||
from .data_source_db import DataSourceDb
|
||||
|
||||
|
||||
class MySQLDataSource(DataSourceDb):
|
||||
def __init__(self, mysql_connection_info: Dict[str, str]) -> None:
|
||||
self.user = mysql_connection_info["user"]
|
||||
self.host = mysql_connection_info["host"]
|
||||
self.password = mysql_connection_info["password"]
|
||||
|
||||
def save_record(
|
||||
self,
|
||||
database: str,
|
||||
tablename: str,
|
||||
data: Dict[str, Any],
|
||||
use_obj_connection: bool = False,
|
||||
close_obj_connection: bool = True,
|
||||
):
|
||||
query, values = self.create_query(tablename, data)
|
||||
|
||||
if use_obj_connection:
|
||||
try:
|
||||
self.cursor.execute(query, values)
|
||||
|
||||
if close_obj_connection:
|
||||
self.db.commit()
|
||||
self.db.close()
|
||||
|
||||
except mysql.connector.Error:
|
||||
self.db.commit()
|
||||
self.db.close()
|
||||
raise
|
||||
|
||||
else:
|
||||
db = mysql.connector.connect(
|
||||
user=self.user,
|
||||
host=self.host,
|
||||
password=self.password,
|
||||
database=database,
|
||||
)
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
cursor.execute(query, values)
|
||||
db.commit()
|
||||
db.close()
|
||||
except mysql.connector.Error:
|
||||
db.close()
|
||||
raise
|
||||
|
||||
def bulk_save(self, export_data: List[Dict[str, Any]]) -> None:
|
||||
for index, unit in enumerate(export_data):
|
||||
database, table_name, data = unit.values()
|
||||
|
||||
if (
|
||||
not hasattr(self, "db")
|
||||
or not hasattr(self, "cursor")
|
||||
or not self.db.is_connected()
|
||||
):
|
||||
self.db = mysql.connector.connect(
|
||||
user=self.user,
|
||||
host=self.host,
|
||||
password=self.password,
|
||||
database=database,
|
||||
)
|
||||
try:
|
||||
self.cursor = self.db.cursor()
|
||||
except:
|
||||
self.db.close()
|
||||
raise
|
||||
|
||||
self.save_record(
|
||||
database, table_name, data, True, index + 1 == len(export_data)
|
||||
)
|
||||
|
||||
def create_query(self, table_name: str, data: dict) -> Tuple[str, list]:
|
||||
columns = list(data.keys())
|
||||
values = list(data.values())
|
||||
|
||||
query = (
|
||||
f"REPLACE INTO {table_name} ("
|
||||
+ ", ".join(columns)
|
||||
+ ") VALUES ("
|
||||
+ ", ".join(["%s"] * len(columns))
|
||||
+ ")"
|
||||
)
|
||||
return (query, values)
|
||||
93
source/database/read_and_save.py
Normal file
93
source/database/read_and_save.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""Example of reading and saving some inverter registers."""
|
||||
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from os import environ
|
||||
|
||||
from solaxx3.solaxx3 import SolaxX3
|
||||
|
||||
from .mysql_data_source import MySQLDataSource
|
||||
|
||||
|
||||
def _get_datetime(inverter_time: datetime) -> datetime:
|
||||
return inverter_time - timedelta(hours=TIMEZONE_OFFSET)
|
||||
|
||||
|
||||
MYSQL_CONNECTION_INFO = {
|
||||
"user": environ["MYSQL_DB_USERNAME"],
|
||||
"host": environ["MYSQL_DB_HOST_IP"],
|
||||
"password": environ["MYSQL_DB_PASSWORD"],
|
||||
}
|
||||
DATABASE = environ["MYSQL_DB_DATABASE"]
|
||||
TIMEZONE_OFFSET = 2
|
||||
|
||||
s = SolaxX3(port="/dev/ttyUSB0", baudrate=115200)
|
||||
if not s.connect():
|
||||
print("Could not connect to inverter")
|
||||
sys.exit(1)
|
||||
|
||||
s.read_all_registers()
|
||||
|
||||
mysql_export_data = [
|
||||
{
|
||||
"database": DATABASE,
|
||||
"table": "solax_local",
|
||||
"data": {
|
||||
"uploadTime": _get_datetime(s.read("rtc_datetime")[0]),
|
||||
"inverter_status": s.read("run_mode")[0],
|
||||
"dc_solar_power": s.read("power_dc1")[0] + s.read("power_dc2")[0],
|
||||
"grid_voltage_r": s.read("grid_voltage_r")[0],
|
||||
"grid_voltage_s": s.read("grid_voltage_s")[0],
|
||||
"grid_voltage_t": s.read("grid_voltage_t")[0],
|
||||
"battery_capacity": s.read("battery_capacity")[0],
|
||||
"battery_power": s.read("battery_power_charge1")[0],
|
||||
"feed_in_power": s.read("feed_in_power")[0],
|
||||
"time_count_down": s.read("time_count_down")[0],
|
||||
"inverter_ac_power": s.read("grid_power")[0],
|
||||
"consumeenergy": s.read("energy_from_grid_meter")[0],
|
||||
"feedinenergy": s.read("energy_to_grid_meter")[0],
|
||||
"power_dc1": s.read("power_dc1")[0],
|
||||
"power_dc2": s.read("power_dc2")[0],
|
||||
"inv_volt_r": s.read("inv_volt_r")[0],
|
||||
"inv_volt_s": s.read("inv_volt_s")[0],
|
||||
"inv_volt_t": s.read("inv_volt_t")[0],
|
||||
"off_grid_power_active_r": s.read("off_grid_power_active_r")[0],
|
||||
"off_grid_power_active_s": s.read("off_grid_power_active_s")[0],
|
||||
"off_grid_power_active_t": s.read("off_grid_power_active_t")[0],
|
||||
"grid_power_r": s.read("grid_power_r")[0],
|
||||
"grid_power_s": s.read("grid_power_s")[0],
|
||||
"grid_power_t": s.read("grid_power_t")[0],
|
||||
},
|
||||
},
|
||||
{
|
||||
"database": DATABASE,
|
||||
"table": "solax_daily",
|
||||
"data": {
|
||||
"uploadDate": _get_datetime(s.read("rtc_datetime")[0]).date(),
|
||||
"feed_in": s.read("feed_in_energy_today")[0],
|
||||
"total_yield": s.read("energy_to_grid_today")[0],
|
||||
},
|
||||
},
|
||||
]
|
||||
mysql_data_source = MySQLDataSource(MYSQL_CONNECTION_INFO)
|
||||
|
||||
|
||||
def bulk_save():
|
||||
"""Save collected data."""
|
||||
|
||||
mysql_data_source.bulk_save(mysql_export_data)
|
||||
|
||||
|
||||
def _transfer(index: int, **extras) -> None:
|
||||
"""Save a record of collected data."""
|
||||
|
||||
data_record = mysql_export_data[index]
|
||||
database, tablename = data_record["database"], data_record["table"]
|
||||
data = data_record["data"]
|
||||
mysql_data_source.save_record(database, tablename, data, **extras)
|
||||
|
||||
|
||||
save = bulk_save
|
||||
|
||||
if __name__ == "__main__":
|
||||
save()
|
||||
@@ -1,25 +1,36 @@
|
||||
CREATE TABLE `solax_daily` (
|
||||
`uploadDate` date NOT NULL,
|
||||
`feed_in` float(6,1) DEFAULT NULL,
|
||||
`total_yield` float(6,1) DEFAULT NULL,
|
||||
PRIMARY KEY (`uploadDate`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
CREATE TABLE solax_daily (
|
||||
uploadDate DATE NOT NULL,
|
||||
feed_in FLOAT NULL,
|
||||
total_yield FLOAT NULL
|
||||
)
|
||||
ENGINE=InnoDB
|
||||
DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE `solax_local` (
|
||||
`uploadTime` datetime NOT NULL,
|
||||
`inverter_status` tinyint(4) DEFAULT NULL,
|
||||
`dc_solar_power` smallint(6) DEFAULT NULL,
|
||||
`grid_voltage_r` smallint(6) DEFAULT NULL,
|
||||
`grid_voltage_s` smallint(6) DEFAULT NULL,
|
||||
`grid_voltage_t` smallint(6) DEFAULT NULL,
|
||||
`battery_capacity` tinyint(4) DEFAULT NULL,
|
||||
`battery_power` smallint(6) DEFAULT NULL,
|
||||
`feed_in_power` smallint(6) DEFAULT NULL,
|
||||
`time_count_down` smallint(6) DEFAULT NULL,
|
||||
`inverter_ac_power` smallint(6) DEFAULT NULL,
|
||||
`consumeenergy` float(7,1) DEFAULT NULL,
|
||||
`feedinenergy` float(7,1) DEFAULT NULL,
|
||||
`power_dc1` smallint(6) DEFAULT NULL,
|
||||
`power_dc2` smallint(6) DEFAULT NULL,
|
||||
PRIMARY KEY (`uploadTime`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
CREATE TABLE solax_local (
|
||||
uploadTime DATETIME NOT NULL,
|
||||
inverter_status TINYINT NULL,
|
||||
dc_solar_power SMALLINT NULL,
|
||||
grid_voltage_r SMALLINT NULL,
|
||||
grid_voltage_s SMALLINT NULL,
|
||||
grid_voltage_t SMALLINT NULL,
|
||||
battery_capacity TINYINT NULL,
|
||||
battery_power SMALLINT NULL,
|
||||
feed_in_power SMALLINT NULL,
|
||||
time_count_down SMALLINT NULL,
|
||||
inverter_ac_power SMALLINT NULL,
|
||||
consumeenergy FLOAT NULL,
|
||||
feedinenergy FLOAT NULL,
|
||||
power_dc1 SMALLINT NULL,
|
||||
power_dc2 SMALLINT NULL,
|
||||
inv_volt_r SMALLINT NULL,
|
||||
inv_volt_s SMALLINT NULL,
|
||||
inv_volt_t SMALLINT NULL,
|
||||
off_grid_power_active_r INTEGER NULL,
|
||||
off_grid_power_active_s INTEGER NULL,
|
||||
off_grid_power_active_t INTEGER NULL,
|
||||
grid_power_r INTEGER NULL,
|
||||
grid_power_s INTEGER NULL,
|
||||
grid_power_t INTEGER NULL
|
||||
)
|
||||
ENGINE=InnoDB
|
||||
DEFAULT CHARSET=latin1;
|
||||
Reference in New Issue
Block a user