3131class Fronius_Solarweb :
3232 def __init__ (
3333 self ,
34- access_key_id : str ,
35- access_key_value : str ,
34+ access_key_id : str = None ,
35+ access_key_value : str = None ,
36+ login_name : str = None ,
37+ login_password : str = None ,
3638 pv_system_id : str = None ,
3739 httpx_client : AsyncClient = None ,
3840 ):
3941 """
40- Create an Fronius Solarweb API client.
42+ Create an Fronius Solarweb API client from either key/id or login/password .
4143
4244 :param access_key_id: unique ID for the API key, e.g.
4345 "FKIAFEF58CFEFA94486F9C804CF6077A01AB". Access keys are 36
4446 characters long and start with the "FKIA" prefix.
4547 :param access_key_value: A secret value (GUID),
4648 e.g. "47c076bc-23e5-4949-37a6-4bcfcf8d21d6", which
4749 you need to know for authorization of API calls.
50+ :param login_name: Solar.web email / login name.
51+ :param login_password: Solar.web password.
4852 :param pv_system_id (optional): Unique PV system ID,
4953 this can be provided or determined from a call to
5054 get_pvsystems_meta_data()
5155 :param httpx_client (optional)
5256 """
5357 self .access_key_id = access_key_id
5458 self .access_key_value = access_key_value
59+ self .login_name = login_name
60+ self .login_password = login_password
5561 self .pv_system_id = pv_system_id
5662 self .httpx_client = httpx_client or AsyncClient ()
57-
58- @property
59- def _common_headers (self ):
60- return {
61- "Accept" : "application/json" ,
63+ self .jwt_data : dict = None
64+ self ._jwt_base_header = {
65+ "Content-Type" : "application/json-patch+json" ,
6266 "AccessKeyId" : self .access_key_id ,
6367 "AccessKeyValue" : self .access_key_value ,
68+ "Accept" : "application/json" ,
69+ # "Accept-Language": "de-de",
70+ "User-Agent" : "Solar.web/921 CFNetwork/1410.0.3 Darwin/22.6.0" ,
6471 }
6572
73+ @property
74+ def _common_headers (self ):
75+ if self ._jwt_headers .get ("Authorization" ):
76+ return self ._jwt_headers
77+ else :
78+ return {
79+ "Accept" : "application/json" ,
80+ "AccessKeyId" : self .access_key_id ,
81+ "AccessKeyValue" : self .access_key_value ,
82+ }
83+
84+ @property
85+ def _jwt_headers (self ):
86+ return self ._jwt_base_header
87+
88+ @_jwt_headers .setter
89+ def _jwt_headers (self , new : dict ):
90+ return self ._jwt_base_header .update (new )
91+
92+ def _jwt_del_header (self , key : str ):
93+ self ._jwt_base_header .pop (key , None )
94+
6695 async def _check_api_response (self , response ):
6796 if response .status_code == 401 :
68- _LOGGER .debug ("Access unauthorised check solar.web access key values" )
97+ _LOGGER .warning (
98+ "Access unauthorised check solar.web access key values or login password"
99+ )
69100 raise NotAuthorizedException ()
70101 if response .status_code == 404 :
71- _LOGGER .debug ("Item not found check your PV system ID" )
102+ _LOGGER .warning ("Item not found check your PV system ID" )
72103 raise NotFoundException ()
73104
74105 response .raise_for_status ()
75106 # returns dict type not string
76107 return response .json ()
77108
109+ async def login (self ):
110+ self ._jwt_del_header ("Authorization" )
111+ _LOGGER .debug ("Obtaining JSON web token" )
112+ r = await self .httpx_client .post (
113+ f"{ SW_BASE_URL } /iam/jwt" ,
114+ headers = self ._jwt_headers ,
115+ json = {
116+ "userId" : self .login_name ,
117+ "password" : self .login_password ,
118+ },
119+ )
120+ self .jwt_data = await self ._check_api_response (r )
121+ _LOGGER .debug (f"JWT data returned: { self .jwt_data } " )
122+ self ._jwt_headers = {"Authorization" : "Bearer " + self .jwt_data .get ("jwtToken" )}
123+
124+ async def refresh_token (self , token : str = None ):
125+ refresh = self .jwt_data .get ("refreshToken" , token )
126+ self ._jwt_del_header ("Authorization" )
127+ _LOGGER .debug (f"Obtaining JSON web token using refresh token: { refresh } " )
128+ r = await self .httpx_client .patch (
129+ f"{ SW_BASE_URL } /iam/jwt/{ refresh } " , headers = {"accept" : "application/json" }
130+ )
131+ self .jwt_data = await self ._check_api_response (r )
132+ _LOGGER .debug (f"JWT data returned: { self .jwt_data } " )
133+ self ._jwt_headers = {"Authorization" : "Bearer " + self .jwt_data .get ("jwtToken" )}
134+
78135 @retry (
79136 wait = wait_random_exponential (multiplier = 2 , max = 60 ),
80137 retry = retry_if_not_exception_type (
@@ -93,7 +150,7 @@ async def get_api_release_info(self) -> ReleaseInfo:
93150 model_data = ReleaseInfo .model_validate (json_data )
94151 except ValidationError as e :
95152 _LOGGER .error (
96- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
153+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
97154 )
98155 _LOGGER .error (e )
99156 return model_data
@@ -116,7 +173,7 @@ async def get_pvsystems_meta_data(self) -> list[PvSystemMetaData]:
116173 model_data = PvSystemsMetaData .model_validate (json_data ).pvSystems
117174 except ValidationError as e :
118175 _LOGGER .error (
119- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
176+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
120177 )
121178 _LOGGER .error (e )
122179 return model_data
@@ -139,7 +196,7 @@ async def get_pvsystem_meta_data(self) -> PvSystemMetaData:
139196 model_data = PvSystemMetaData .model_validate (json_data )
140197 except ValidationError as e :
141198 _LOGGER .error (
142- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
199+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
143200 )
144201 _LOGGER .error (e )
145202 return model_data
@@ -162,7 +219,7 @@ async def get_devices_meta_data(self) -> list[DeviceMetaData]:
162219 model_data = DevicesMetaData .model_validate (json_data ).devices
163220 except ValidationError as e :
164221 _LOGGER .error (
165- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
222+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
166223 )
167224 _LOGGER .error (e )
168225 return model_data
@@ -185,7 +242,7 @@ async def get_system_flow_data(self, tz: str = "zulu") -> PvSystemFlowData:
185242 model_data = PvSystemFlowData .model_validate (json_data )
186243 except ValidationError as e :
187244 _LOGGER .error (
188- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
245+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
189246 )
190247 _LOGGER .error (e )
191248 return model_data
@@ -213,7 +270,7 @@ async def get_system_aggr_data_v2(
213270 model_data = PvSystemAggrDataV2 .model_validate (json_data )
214271 except ValidationError as e :
215272 _LOGGER .error (
216- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
273+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
217274 )
218275 _LOGGER .error (e )
219276 return model_data
@@ -241,7 +298,7 @@ async def get_hist_data(
241298 model_data = HistoricalValues .model_validate (json_data )
242299 except ValidationError as e :
243300 _LOGGER .error (
244- f"Unable to validate data receieved from SolarWeb api: ' { json_data } ' "
301+ f"Unable to validate data receieved from SolarWeb api: { json_data } "
245302 )
246303 _LOGGER .error (e )
247304 return model_data
0 commit comments