15
15
from datetime import datetime
16
16
17
17
__author__ = "Sebastian Hollas"
18
- __version__ = "2.0 .0"
18
+ __version__ = "2.1 .0"
19
19
20
20
####################################################################################
21
21
# USER INPUT REQUIRED !
22
22
# Path to HomeAssistant config root (e.g. /HomeAssistant/config )
23
23
HA_CONFIG_ROOT = "/HomeAssistant/config"
24
- HA_CONFIG_ROOT = r"C:/users/shollas"
25
24
####################################################################################
26
25
27
- # USER INPUT OPTIONAL ! (if DATABASE server is used instead of database file)
26
+ # USER INPUT OPTIONAL ! (if MySQL server shall be used instead of a SQLite database file)
28
27
DB_SERVER = {
29
28
"DB_HOST" : "" ,
30
29
"DB_USER" : "" ,
49
48
sys .exit (f"File { ENTITY_REGISTRY_PATH } does not exist! (Path to HomeAssistant config valid?)" )
50
49
51
50
52
- # Open Database Server connection if user provided DB_SERVER information
51
+ # Open MySQL server connection if user provided DB_SERVER information
53
52
if all (DB_SERVER .values ()):
54
53
import pymysql
55
54
db = pymysql .connect (
59
58
database = DB_SERVER ["DB_NAME" ]
60
59
)
61
60
62
- # Create connection to database file if no DB_SERVER was provided
61
+ # Create connection to database file if no DB_SERVER information was provided
63
62
else :
64
63
# Check for database file
65
64
DATABASE_PATH = os .path .join (HA_CONFIG_ROOT , "home-assistant_v2.db" )
@@ -108,10 +107,11 @@ def main():
108
107
109
108
with open (ENTITIES_FILE , "w" ) as file :
110
109
# Get Entities that have a round option
110
+ SqlExec ("SELECT statistic_id FROM statistics_meta WHERE has_sum=1" , ())
111
111
for entity_id in getEntitiesPrecision ():
112
112
file .write (f"{ entity_id } \n " )
113
113
114
- print (f"File '{ ENTITIES_FILE } ' created with entities that are most likely Riemann Sum Entities "
114
+ print (f"File '{ ENTITIES_FILE } ' created with entities that have the key 'sum' "
115
115
f"\n Please adjust to your needs and rerun the script with no arguments." )
116
116
117
117
else :
@@ -150,11 +150,11 @@ def fixDatabase(ENTITIES: list):
150
150
################################################################################################################
151
151
# Get amount of decimals for Riemann Sum integral that the user configured
152
152
if entity_id not in EntityPrecision :
153
- print (f" [WARNING]: Entity seems not to be a Riemann Sum Entity! Skipping... " )
154
- continue
155
-
156
- # Get Precision of Entity that user configured
157
- roundDigits = EntityPrecision [entity_id ]
153
+ print (f" [WARNING]: Entity seems not to be a Riemann Sum Entity! UNTESTED. USE WITH CAUTION! " )
154
+ roundDigits = - 1
155
+ else :
156
+ # Get Precision of Entity that user configured
157
+ roundDigits = EntityPrecision [entity_id ]
158
158
159
159
################################################################################################################
160
160
# FIX DATABASE
@@ -171,8 +171,12 @@ def fixDatabase(ENTITIES: list):
171
171
# Fix table "states"
172
172
recalculateStates (metadata_id = metadata_id_states , roundDigits = roundDigits )
173
173
174
- # Fix last valid state in HA to ensure a valid calculation with the next Riemann Sum run
175
- fixLastValidState (entity_id = entity_id , lastValidState = lastValidState )
174
+ # Fix last valid state if entity seems to be a Riemann Sum Entity only
175
+ # OPEN: How to find out if entity is a Riemann Sum Entity?!
176
+ # Currently: If entity is in table statistics and has a "round" attribute, it is assumed to be a Riemann Sum Entity
177
+ if roundDigits != - 1 :
178
+ # Fix last valid state in HA to ensure a valid calculation with the next Riemann Sum calculation
179
+ fixLastValidState (entity_id = entity_id , lastValidState = lastValidState )
176
180
177
181
# Store database on disk
178
182
print (f"\n { db .total_changes } changes made to database!" )
@@ -207,7 +211,11 @@ def recalculateStatistics(metadata_id: int, key: str, roundDigits: int) -> str:
207
211
# Recalculate new value with difference of previous entries
208
212
current_value += (value - pre_value )
209
213
210
- roundedValue = f"{ current_value :.{roundDigits }f} "
214
+ if roundDigits != - 1 :
215
+ roundedValue = f"{ current_value :.{roundDigits }f} "
216
+ else :
217
+ # Just copy because we don't round the value
218
+ roundedValue = current_value
211
219
print (f" Updating { idx = } : { value = } -> { roundedValue = } " )
212
220
SqlExec (f"UPDATE statistics SET { key } =? WHERE id=?" , (roundedValue , idx ))
213
221
@@ -217,7 +225,12 @@ def recalculateStatistics(metadata_id: int, key: str, roundDigits: int) -> str:
217
225
current_value = value
218
226
219
227
# Return last value
220
- return f"{ current_value :.{roundDigits }f} "
228
+ if roundDigits != - 1 :
229
+ # Return rounded value
230
+ return f"{ current_value :.{roundDigits }f} "
231
+ else :
232
+ # Return value as it is
233
+ return current_value
221
234
222
235
223
236
def fixShortTerm (metadata_id : int , lastValidSum : str , lastValidState : str ):
@@ -264,7 +277,11 @@ def recalculateStates(metadata_id: int, roundDigits: int):
264
277
265
278
if state is None or not state .replace ("." , "" , 1 ).isdigit ():
266
279
# State is NULL or not numeric; update to current value
267
- roundedValue = f"{ current_state :.{roundDigits }f} "
280
+ if roundDigits != - 1 :
281
+ roundedValue = f"{ current_state :.{roundDigits }f} "
282
+ else :
283
+ # Just copy because we don't round the value
284
+ roundedValue = current_state
268
285
print (f" Updating { state_id = } : { state = } -> { roundedValue } " )
269
286
SqlExec ("UPDATE states SET state=? WHERE state_id=?" , (roundedValue , state_id ))
270
287
continue
@@ -277,7 +294,11 @@ def recalculateStates(metadata_id: int, roundDigits: int):
277
294
# Recalculate new value with difference of previous entries
278
295
current_state += (state - float (pre_state ))
279
296
280
- roundedValue = f"{ current_state :.{roundDigits }f} "
297
+ if roundDigits != - 1 :
298
+ roundedValue = f"{ current_state :.{roundDigits }f} "
299
+ else :
300
+ # Just copy because we don't round the value
301
+ roundedValue = current_state
281
302
print (f" Updating { state_id = } : { state = } -> { roundedValue } " )
282
303
SqlExec ("UPDATE states SET state=? WHERE state_id=?" , (roundedValue , state_id ))
283
304
continue
@@ -321,7 +342,7 @@ def getEntitiesPrecision() -> dict[str: int]:
321
342
322
343
configIds = dict ()
323
344
324
- # Find entry_ids which have the option/round attribute (these are most likely Riemann Sum Entities
345
+ # Find entry_ids which have the option/round attribute (these are most likely Riemann Sum Entities)
325
346
for configEntry in configEntries ["data" ]["entries" ]:
326
347
number = configEntry ["options" ].get ("round" , - 1 )
327
348
if number == - 1 :
@@ -346,6 +367,7 @@ def getEntitiesPrecision() -> dict[str: int]:
346
367
347
368
def SqlExec (SqlQuery : str , arguments : tuple ):
348
369
if not isinstance (db , sqlite3 .Connection ):
370
+ # Replace placeholder for module PyMySQL
349
371
SqlQuery = SqlQuery .replace ("?" , "%s" )
350
372
351
373
cur .execute (SqlQuery , arguments )
0 commit comments