sonnenbatterie 0.7.dev7__tar.gz → 0.7.dev8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. {sonnenbatterie-0.7.dev7/sonnenbatterie.egg-info → sonnenbatterie-0.7.dev8}/PKG-INFO +1 -1
  2. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/setup.cfg +1 -1
  3. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie/sonnenbatterie.py +13 -13
  4. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8/sonnenbatterie.egg-info}/PKG-INFO +1 -1
  5. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie.egg-info/SOURCES.txt +1 -0
  6. sonnenbatterie-0.7.dev8/test/test_login_new.py +48 -0
  7. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/LICENSE +0 -0
  8. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/README.md +0 -0
  9. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/pyproject.toml +0 -0
  10. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/setup.py +0 -0
  11. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie/__init__.py +0 -0
  12. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie/const.py +0 -0
  13. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie.egg-info/dependency_links.txt +0 -0
  14. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie.egg-info/requires.txt +0 -0
  15. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie.egg-info/top_level.txt +0 -0
  16. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie2/__init__.py +0 -0
  17. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie2/const.py +0 -0
  18. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/sonnenbatterie2/sonnenbatterie2.py +0 -0
  19. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_api_v1.py +0 -0
  20. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_api_v2.py +0 -0
  21. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_battery_reserve.py +0 -0
  22. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_battery_reserve_async.py +0 -0
  23. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_operating_mode.py +0 -0
  24. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_operating_mode_api_v2.py +0 -0
  25. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_operating_mode_async.py +0 -0
  26. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_operating_mode_async_api_v2.py +0 -0
  27. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_retrieval_loop.py +0 -0
  28. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_set_flow.py +0 -0
  29. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_set_flow_async.py +0 -0
  30. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_set_flow_v2.py +0 -0
  31. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_set_flow_v2_async.py +0 -0
  32. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_timeofuse.py +0 -0
  33. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_timeofuse_async.py +0 -0
  34. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_timeofuse_lib.py +0 -0
  35. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_timeofuse_v2.py +0 -0
  36. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/test/test_timeofuse_v2_async.py +0 -0
  37. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/timeofuse/__init__.py +0 -0
  38. {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev8}/timeofuse/timeofuse.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonnenbatterie
3
- Version: 0.7.dev7
3
+ Version: 0.7.dev8
4
4
  Summary: "Access Sonnenbatterie REST API"
5
5
  Home-page: https://github.com/weltmeyer/python_sonnenbatterie
6
6
  Author: Jan Weltmeyer
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = sonnenbatterie
3
- version = 0.7.dev7
3
+ version = 0.7.dev8
4
4
  author = Jan Weltmeyer
5
5
  description = "Access Sonnenbatterie REST API"
6
6
  long_description = file: README.md
@@ -290,8 +290,6 @@ class AsyncSonnenBatterie:
290
290
  saltResponseCode = salt.status
291
291
 
292
292
 
293
-
294
-
295
293
  if saltResponseCode!=200: #use old variant where no salt is availlable
296
294
  #Old path (no salt): PBKDF2 over sha512(password) + challenge → hex
297
295
  response=hashlib.pbkdf2_hmac('sha512',pw_sha512.encode('utf-8'),challenge.encode('utf-8'),7500,64).hex()
@@ -314,6 +312,16 @@ class AsyncSonnenBatterie:
314
312
  self.sb2 = AsyncSonnenBatterieV2(ip_address=self.ipaddress, api_token=self.token)
315
313
 
316
314
 
315
+
316
+ def create_response_from_values(self, username, password, challenge, salt):
317
+ pw_sha512_hex = hashlib.sha512(password.encode("utf-8")).hexdigest()
318
+ pw_bytes = pw_sha512_hex.encode("utf-8")
319
+ dk = hashlib.pbkdf2_hmac("sha512", pw_bytes, salt.encode("utf-8"), 7500, dklen=64)
320
+ derived_hex = dk.hex()
321
+ key = derived_hex.encode("utf-8")
322
+ response = hmac.new(key, challenge.encode("utf-8"), hashlib.sha256).hexdigest()
323
+ return response
324
+
317
325
  async def create_session_token_new(self):
318
326
  # Step 1: challenge
319
327
  async with self._session.get(f"{self.baseurl}challenge") as r:
@@ -330,16 +338,10 @@ class AsyncSonnenBatterie:
330
338
  r.raise_for_status()
331
339
  salt = (await r.json())["salt"]
332
340
 
333
- # Step 3: derive key
334
- pw_sha512_hex = hashlib.sha512(self.password.encode("utf-8")).hexdigest()
335
- pw_bytes = pw_sha512_hex.encode("utf-8")
336
- dk = hashlib.pbkdf2_hmac("sha512", pw_bytes, salt.encode("utf-8"), 7500, dklen=64)
337
- derived_hex = dk.hex()
338
-
341
+
339
342
  # Step 4: loop: POST /session, maybe retry with new_challenge
340
343
  for _ in range(2):
341
- key = derived_hex.encode("utf-8")
342
- response = hmac.new(key, challenge.encode("utf-8"), hashlib.sha256).hexdigest()
344
+ response = self.create_response_from_values(self.username,self.password,challenge,salt)
343
345
  payload = {"user": self.username, "challenge": challenge, "response": response}
344
346
 
345
347
  async with self._session.post(f"{self.baseurl}session", json=payload) as r:
@@ -351,9 +353,7 @@ class AsyncSonnenBatterie:
351
353
  f"Payload: {json.dumps(payload)}\n"
352
354
  f"challenge: {challenge}\n"
353
355
  f"salt: {salt}\n"
354
- f"pw_sha_hex: {pw_sha512_hex}\n"
355
- f"derived_hex: {derived_hex}\n"
356
- f"response_hex: {response}\n"
356
+ f"response: {response}\n"
357
357
  f"Server reply: {txt}"
358
358
  )
359
359
  r.raise_for_status()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonnenbatterie
3
- Version: 0.7.dev7
3
+ Version: 0.7.dev8
4
4
  Summary: "Access Sonnenbatterie REST API"
5
5
  Home-page: https://github.com/weltmeyer/python_sonnenbatterie
6
6
  Author: Jan Weltmeyer
@@ -26,6 +26,7 @@ test/test_api_v1.py
26
26
  test/test_api_v2.py
27
27
  test/test_battery_reserve.py
28
28
  test/test_battery_reserve_async.py
29
+ test/test_login_new.py
29
30
  test/test_operating_mode.py
30
31
  test/test_operating_mode_api_v2.py
31
32
  test/test_operating_mode_async.py
@@ -0,0 +1,48 @@
1
+
2
+ #!/usr/bin/env python3
3
+ # I suspect that I haven't got to grips with the way phthon does things, but soppusely this will setup the path to allod for the sonnen batteri moduel to be in a separate location
4
+ # To me having to do this for testing seems a horrendous hack
5
+ import asyncio
6
+ import os
7
+ import sys
8
+ import time
9
+ import json
10
+ import sys
11
+ import base64, binascii, hashlib, hmac, string
12
+ script_path = os.path.realpath(os.path.dirname(__name__))
13
+ os.chdir(script_path)
14
+ sys.path.append("..")
15
+ from pprint import pprint
16
+ import hashlib
17
+
18
+ # this is based on the test code by rust dust
19
+
20
+ def main():
21
+ challenge="39bdd8a304b84c76"
22
+ username="User"
23
+ password="sonnenUser3552!"
24
+ salt="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb_02bbe1e15021947b232050cc88b07772"
25
+ testResponse=create_response_from_values(username,password,challenge,salt)
26
+ wantedResponse="39b5cb8cc21772b482cdbbcbd135f4a05af4974f3e1b9e4c8aa846d6e64bcc1a"
27
+
28
+
29
+ if testResponse==wantedResponse:
30
+ print("It works!")
31
+ else:
32
+ print("doesnt work :(")
33
+
34
+ print("Response: "+testResponse)
35
+
36
+
37
+ def create_response_from_values(username, password, challenge, salt):
38
+ pw_sha512_hex = hashlib.sha512(password.encode("utf-8")).hexdigest()
39
+ pw_bytes = pw_sha512_hex.encode("utf-8")
40
+ dk = hashlib.pbkdf2_hmac("sha512", pw_bytes, salt.encode("utf-8"), 7500, dklen=64)
41
+ derived_hex = dk.hex()
42
+ key = derived_hex.encode("utf-8")
43
+ response = hmac.new(key, challenge.encode("utf-8"), hashlib.sha256).hexdigest()
44
+ return response
45
+
46
+
47
+ if __name__ == '__main__':
48
+ main()