sonnenbatterie 0.7.dev7__tar.gz → 0.7.dev9__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.
- {sonnenbatterie-0.7.dev7/sonnenbatterie.egg-info → sonnenbatterie-0.7.dev9}/PKG-INFO +1 -1
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/setup.cfg +1 -1
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie/sonnenbatterie.py +21 -15
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9/sonnenbatterie.egg-info}/PKG-INFO +1 -1
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie.egg-info/SOURCES.txt +1 -0
- sonnenbatterie-0.7.dev9/test/test_login_new.py +49 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/LICENSE +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/README.md +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/pyproject.toml +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/setup.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie/__init__.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie/const.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie.egg-info/dependency_links.txt +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie.egg-info/requires.txt +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie.egg-info/top_level.txt +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie2/__init__.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie2/const.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie2/sonnenbatterie2.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_api_v1.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_api_v2.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_battery_reserve.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_battery_reserve_async.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_operating_mode.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_operating_mode_api_v2.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_operating_mode_async.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_operating_mode_async_api_v2.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_retrieval_loop.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_set_flow.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_set_flow_async.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_set_flow_v2.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_set_flow_v2_async.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_timeofuse.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_timeofuse_async.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_timeofuse_lib.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_timeofuse_v2.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_timeofuse_v2_async.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/timeofuse/__init__.py +0 -0
- {sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/timeofuse/timeofuse.py +0 -0
|
@@ -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,19 +338,18 @@ class AsyncSonnenBatterie:
|
|
|
330
338
|
r.raise_for_status()
|
|
331
339
|
salt = (await r.json())["salt"]
|
|
332
340
|
|
|
333
|
-
|
|
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
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
+
response = self.create_response_from_values(self.username,self.password,challenge,salt)
|
|
345
|
+
body = urlencode(payload).encode("utf-8")
|
|
346
|
+
async with self._session.post(
|
|
347
|
+
|
|
348
|
+
url = self.baseurl+'session',
|
|
349
|
+
data = {"user":self.username,"challenge":challenge,"response":response},
|
|
350
|
+
timeout=self._timeout,
|
|
344
351
|
|
|
345
|
-
|
|
352
|
+
) as r:
|
|
346
353
|
txt = await r.text()
|
|
347
354
|
if r.status >= 400:
|
|
348
355
|
raise RuntimeError(
|
|
@@ -351,9 +358,7 @@ class AsyncSonnenBatterie:
|
|
|
351
358
|
f"Payload: {json.dumps(payload)}\n"
|
|
352
359
|
f"challenge: {challenge}\n"
|
|
353
360
|
f"salt: {salt}\n"
|
|
354
|
-
f"
|
|
355
|
-
f"derived_hex: {derived_hex}\n"
|
|
356
|
-
f"response_hex: {response}\n"
|
|
361
|
+
f"response: {response}\n"
|
|
357
362
|
f"Server reply: {txt}"
|
|
358
363
|
)
|
|
359
364
|
r.raise_for_status()
|
|
@@ -365,6 +370,7 @@ class AsyncSonnenBatterie:
|
|
|
365
370
|
|
|
366
371
|
if "authentication_token" in data and data["authentication_token"]:
|
|
367
372
|
self.token = data["authentication_token"]
|
|
373
|
+
return
|
|
368
374
|
|
|
369
375
|
raise RuntimeError(f"Unexpected /session response: {json.dumps(data)}")
|
|
370
376
|
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
challenge="d43aeb06a6394daa"
|
|
23
|
+
username="User"
|
|
24
|
+
password="sonnenUser3552!"
|
|
25
|
+
salt="04f8996da763b7a969b1028ee3007569eaf3a635486ddab211d512c85b9df8fb_02bbe1e15021947b232050cc88b07772"
|
|
26
|
+
testResponse=create_response_from_values(username,password,challenge,salt)
|
|
27
|
+
wantedResponse="39b5cb8cc21772b482cdbbcbd135f4a05af4974f3e1b9e4c8aa846d6e64bcc1a"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if testResponse==wantedResponse:
|
|
31
|
+
print("It works!")
|
|
32
|
+
else:
|
|
33
|
+
print("doesnt work :(")
|
|
34
|
+
|
|
35
|
+
print("Response: "+testResponse)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def create_response_from_values(username, password, challenge, salt):
|
|
39
|
+
pw_sha512_hex = hashlib.sha512(password.encode("utf-8")).hexdigest()
|
|
40
|
+
pw_bytes = pw_sha512_hex.encode("utf-8")
|
|
41
|
+
dk = hashlib.pbkdf2_hmac("sha512", pw_bytes, salt.encode("utf-8"), 7500, dklen=64)
|
|
42
|
+
derived_hex = dk.hex()
|
|
43
|
+
key = derived_hex.encode("utf-8")
|
|
44
|
+
response = hmac.new(key, challenge.encode("utf-8"), hashlib.sha256).hexdigest()
|
|
45
|
+
return response
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == '__main__':
|
|
49
|
+
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/sonnenbatterie.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sonnenbatterie-0.7.dev7 → sonnenbatterie-0.7.dev9}/test/test_operating_mode_async_api_v2.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|