44import asyncio
55import json
66import logging
7- import os
87
98from aiohttp import ClientSession
9+ from custom_components .talent_monitor .pyTalentMonitor .inverter import InverterDataProvider
10+ from custom_components .talent_monitor .pyTalentMonitor .data_provider import DataProvider
11+ from custom_components .talent_monitor .pyTalentMonitor .power_station import PowerStation , PowerStationDataProvider
1012
1113# Configure logging
1214_LOGGER : logging .Logger = logging .getLogger (__name__ )
1315
1416BASE_URL = "https://www.talent-monitoring.com/prod-api"
1517TIMEZONE = "+02:00"
1618
17-
1819class AuthenticationError (Exception ):
1920 """AuthenticationError when connecting to the Talent API."""
20-
2121 pass
2222
23-
2423class TalentSolarMonitor :
2524 """TalentSolarMonitor API client."""
2625
@@ -29,125 +28,27 @@ def __init__(
2928 username : str = None ,
3029 password : str = None ,
3130 session : ClientSession = None ,
32- return_json : bool = False ,
3331 ):
3432 """Construct the TalentSolarMonitor API client."""
35- self .username = username or os .environ .get ("PYTALENT_USERNAME" )
36- self .password = password or os .environ .get ("PYTALENT_PASSWORD" )
37- self .session = session
38- self .return_json = return_json
39- self .token = None
40-
41- def get_credentials (self ):
42- """Check whether the credentials are set."""
43- if not self .username or not self .password :
44- raise ValueError (
45- "Credentials not provided via command line arguments or environment variables."
46- )
33+ self ._data_provider = DataProvider (username , password , session )
34+ self ._inverter_data_provider = InverterDataProvider (self ._data_provider )
35+ self ._power_station_data_provider = PowerStationDataProvider (self ._data_provider )
4736
48- async def login (self ):
49- """Log in using the given credentials."""
50- login_data = {"username" : self .username , "password" : self .password }
51- response = await self .session .post (f"{ BASE_URL } /login" , json = login_data )
52- response_data = await response .json ()
53- if "token" in response_data :
54- self .token = response_data ["token" ]
55- _LOGGER .debug ("Login successful - received token: %s" , self .token )
56- else :
57- _LOGGER .error ("Login failed. Got status code %s" , response .status )
58- raise AuthenticationError ("Authentication failed" )
5937
60- async def refresh_token (self ):
61- """Refresh the token."""
62- _LOGGER .debug ("Token expired. Refreshing token..." )
63- self .login ()
38+ def get_power_stations (self ) -> list [PowerStation ]:
39+ return self ._power_station_data_provider .power_stations
6440
65- async def get_data (self , endpoint ):
66- """Get data from the given endpoint."""
67- if not self .token :
68- self .login ()
69- headers = {"Authorization" : f"Bearer { self .token } " }
70- response = await self .session .get (f"{ BASE_URL } /{ endpoint } " , headers = headers )
71- if response .status == 401 : # Unauthorized, token might be expired
72- self .refresh_token ()
73- headers ["Authorization" ] = f"Bearer { self .token } "
74- response = await self .session .get (f"{ BASE_URL } /{ endpoint } " , headers = headers )
75-
76- if response .status == 200 :
77- return await response .json ()
78- else :
79- _LOGGER .error ("Failed to fetch data. Status Code: %s" , response .status )
80- return None
41+ def fetch_data (self ):
42+ self ._inverter_data_provider .fetch_data ()
43+ self ._power_station_data_provider .fetch_data ()
8144
8245 async def fetch_solar_data (self ):
83- """Fetch the solar data."""
84- self .get_credentials ()
85- await self .login ()
86-
87- data = await self .get_data (endpoint = "system/station/list" )
88- if data and "rows" in data and len (data ["rows" ]) > 0 :
89- first_station = data ["rows" ][0 ]
90- status = first_station ["status" ]
91- stationName = first_station ["stationName" ]
92- powerStationGuid = first_station ["powerStationGuid" ]
93- _LOGGER .debug ("GUID: %s" , powerStationGuid )
94-
95- data = await self .get_data (
96- endpoint = f"system/station/getPowerStationByGuid?powerStationGuid={ powerStationGuid } &timezone={ TIMEZONE } "
97- )
98- _LOGGER .debug ("Data for powerstation GUID %s: %s" , powerStationGuid , json .dumps (data ))
99-
100- if data :
101- power_data = data ["data" ]
102- totalActivePower = power_data ["totalActivePower" ]
103- dayEnergy = power_data ["dayEnergy" ]
104- monthEnergy = power_data ["monthEnergy" ]
105- yearEnergy = power_data ["yearEnergy" ]
46+ await self .fetch_data ()
10647
107- data = await self .get_data (endpoint = "tools/device/selectDeviceInverter" )
108- if data :
109- deviceGuid = data ["rows" ][0 ]["deviceGuid" ]
110-
111- data = await self .get_data (
112- endpoint = f"tools/device/selectDeviceInverterInfo?deviceGuid={ deviceGuid } "
113- )
114-
115- _LOGGER .debug ("Data for inverter GUID %s: %s" , deviceGuid , json .dumps (data ))
116- if data :
117- pv = data ["data" ]["pv" ]
118- pv1Voltage = pv [0 ]["voltage" ]
119- pv1Current = pv [0 ]["current" ]
120- pv1Power = pv [0 ]["power" ]
121- pv2Voltage = pv [1 ]["voltage" ]
122- pv2Current = pv [1 ]["current" ]
123- pv2Power = pv [1 ]["power" ]
124-
125- result = {
126- "Status" : status ,
127- "StationName" : stationName ,
128- "TotalActivePower(W)" : totalActivePower ,
129- "DailyEnergy(Wh)" : dayEnergy ,
130- "MonthlyEnergy(Wh)" : monthEnergy ,
131- "YearlyEnergy(Wh)" : yearEnergy ,
132- "Panel1Voltage(V)" : pv1Voltage ,
133- "Panel1Current(A)" : pv1Current ,
134- "Panel1Power(W)" : pv1Power ,
135- "Panel2Voltage(V)" : pv2Voltage ,
136- "Panel2Current(A)" : pv2Current ,
137- "Panel2Power(W)" : pv2Power ,
138- }
139-
140- if self .return_json :
141- return json .dumps (result , indent = 4 )
142- else :
143- for key , value in result .items ():
144- _LOGGER .debug ("%s: %s" ,key , value )
145-
146-
147- async def main (username : str , password : str , return_json : bool ):
48+ async def main (username : str , password : str ):
14849 """Connect to the TalentSolarMonitor API and fetch the solar data."""
14950 async with ClientSession () as session :
150- talent_monitor = TalentSolarMonitor (username , password , session , return_json )
51+ talent_monitor = TalentSolarMonitor (username , password , session )
15152 result = await talent_monitor .fetch_solar_data ()
15253 if result :
15354 _LOGGER .info ("Solar data received: %s" , result )
@@ -159,9 +60,6 @@ async def main(username: str, password: str, return_json: bool):
15960 )
16061 parser .add_argument ("-u" , "--username" , required = False , help = "Username to log in" )
16162 parser .add_argument ("-p" , "--password" , required = False , help = "Password to log in" )
162- parser .add_argument (
163- "--json" , action = "store_true" , help = "Return output as JSON object"
164- )
16563 args = parser .parse_args ()
16664
167- asyncio .run (main (args .username , args .password , args . json ))
65+ asyncio .run (main (args .username , args .password ))
0 commit comments