Browse Source

initial commit

Thomas Buck 8 months ago
commit
fcba15e8fd
5 changed files with 218 additions and 0 deletions
  1. 2
    0
      .gitignore
  2. 75
    0
      python-test/flow.py
  3. 111
    0
      python-test/poll.py
  4. 16
    0
      python-test/scan.py
  5. 14
    0
      web-app/fetch.sh

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
1
+web-app/*.js
2
+__pycache__

+ 75
- 0
python-test/flow.py View File

@@ -0,0 +1,75 @@
1
+#!/usr/bin/env python
2
+
3
+import sys
4
+import asyncio
5
+from poll import (
6
+    ble_conn,
7
+    get_current_temp,
8
+    get_target_temp, set_target_temp,
9
+    get_unit_is_fahrenheit,
10
+    get_state, set_state
11
+)
12
+
13
+async def wait_for_temp(client, temp):
14
+    print("Setting temperature {}".format(temp))
15
+    await set_target_temp(client, temp)
16
+
17
+    print("Waiting for temperature to rise...")
18
+    curr = await get_current_temp(client)
19
+    while curr < temp:
20
+        print("Currently at {}".format(curr))
21
+        await asyncio.sleep(2.0)
22
+        curr = await get_current_temp(client)
23
+
24
+    print("Reached temperature {}".format(temp))
25
+
26
+async def flow_step(client, temp, t_wait, t_pump):
27
+    await wait_for_temp(client, temp)
28
+
29
+    print("Waiting {}s for heat to settle...".format(t_wait))
30
+    await asyncio.sleep(t_wait)
31
+
32
+    print("Pumping for {}s".format(t_pump))
33
+    await set_state(client, (True, True)) # turn on pump
34
+    await asyncio.sleep(t_pump)
35
+    await set_state(client, (True, False)) # turn off pump
36
+
37
+async def flow(client):
38
+    print("Turning on heater")
39
+    await set_state(client, (True, False))
40
+
41
+    await flow_step(client, 190.0, 25.0, 5.0)
42
+    await flow_step(client, 205.0, 10.0, 20.0)
43
+    await flow_step(client, 220.0, 10.0, 20.0)
44
+
45
+    print("Notification by pumping four times...")
46
+    for i in range(0, 4):
47
+        await asyncio.sleep(1.0)
48
+        await set_state(client, (True, True)) # turn on pump
49
+        await asyncio.sleep(1.0)
50
+        await set_state(client, (True, False)) # turn off pump
51
+
52
+    print("Turning heater off")
53
+    await set_state(client, (False, False)) # turn off heater and pump
54
+
55
+async def main(address):
56
+    device = await ble_conn(address)
57
+
58
+    print("Connecting...")
59
+    async with device as client:
60
+        try:
61
+            print("Starting Workflow")
62
+            await flow(client)
63
+        except asyncio.exceptions.CancelledError:
64
+            print("Turning heater off")
65
+            await set_state(client, (False, False)) # turn off heater and pump
66
+        except KeyboardInterrupt:
67
+            print("Turning heater off")
68
+            await set_state(client, (False, False)) # turn off heater and pump
69
+
70
+if __name__ == "__main__":
71
+    if len(sys.argv) <= 1:
72
+        print("Please pass MAC address of device")
73
+        sys.exit(1)
74
+
75
+    asyncio.run(main(sys.argv[1]))

+ 111
- 0
python-test/poll.py View File

@@ -0,0 +1,111 @@
1
+#!/usr/bin/env python
2
+
3
+import sys
4
+import asyncio
5
+from bleak import BleakClient, BleakScanner
6
+from bleak.exc import BleakDBusError
7
+
8
+async def ble_conn(address):
9
+    attempts = 10
10
+    print("Opening device..", end = "", flush=True)
11
+    while attempts > 0:
12
+        try:
13
+            if (attempts % 10) == 0:
14
+                print(".", end = "", flush=True)
15
+
16
+            device = await BleakScanner.find_device_by_address(address)
17
+            client = BleakClient(device)
18
+            print("", flush=True)
19
+            return client
20
+        except BleakDBusError as e:
21
+            attempts -= 1
22
+            if attempts == 0:
23
+                print("", flush=True)
24
+                print(e)
25
+            else:
26
+                await asyncio.sleep(0.1)
27
+
28
+    print("Could not connect to device")
29
+    return None
30
+
31
+async def get_current_temp(client):
32
+    val = await client.read_gatt_char("10110001-5354-4f52-5a26-4249434b454c")
33
+    num = int.from_bytes(val, byteorder="little")
34
+    return num / 10.0
35
+
36
+async def get_target_temp(client):
37
+    val = await client.read_gatt_char("10110003-5354-4f52-5a26-4249434b454c")
38
+    num = int.from_bytes(val, byteorder="little")
39
+    return num / 10.0
40
+
41
+async def set_target_temp(client, temp):
42
+    val = int(temp * 10.0)
43
+    d = val.to_bytes(4, byteorder="little")
44
+    await client.write_gatt_char("10110003-5354-4f52-5a26-4249434b454c", d)
45
+
46
+async def get_unit_is_fahrenheit(client):
47
+    val = await client.read_gatt_char("1010000d-5354-4f52-5a26-4249434b454c")
48
+    num = int.from_bytes(val, byteorder="little")
49
+    return (num & 0x200) != 0
50
+
51
+async def get_state(client):
52
+    val = await client.read_gatt_char("1010000c-5354-4f52-5a26-4249434b454c")
53
+    num = int.from_bytes(val, byteorder="little")
54
+    heater = (num & 0x0020) != 0
55
+    pump = (num & 0x2000) != 0
56
+    return (heater, pump)
57
+
58
+async def set_state(client, state):
59
+    heater, pump = state
60
+    if heater:
61
+        await client.write_gatt_char("1011000f-5354-4f52-5a26-4249434b454c", 0)
62
+    else:
63
+        await client.write_gatt_char("10110010-5354-4f52-5a26-4249434b454c", 0)
64
+    if pump:
65
+        await client.write_gatt_char("10110013-5354-4f52-5a26-4249434b454c", 0)
66
+    else:
67
+        await client.write_gatt_char("10110014-5354-4f52-5a26-4249434b454c", 0)
68
+
69
+async def test_poll(client):
70
+    temp = await get_current_temp(client)
71
+    print("Current Temperature: {}".format(temp))
72
+
73
+    target = await get_target_temp(client)
74
+    print("Target Temperature: {}".format(target))
75
+
76
+    fahrenheit = await get_unit_is_fahrenheit(client)
77
+    if fahrenheit:
78
+        print("Unit is Fahrenheit")
79
+    else:
80
+        print("Unit is Celsius")
81
+
82
+    heater, pump = await get_state(client)
83
+    if heater:
84
+        print("Heater is On")
85
+    else:
86
+        print("Heater is Off")
87
+    if pump:
88
+        print("Pump is On")
89
+    else:
90
+        print("Pump is Off")
91
+
92
+async def test(address):
93
+    device = await ble_conn(address)
94
+
95
+    print("Connecting...")
96
+    async with device as client:
97
+        print("Writing...")
98
+        await set_target_temp(client, 190.0)
99
+
100
+        print("Reading...")
101
+        for i in range(0, 5):
102
+            await test_poll(client)
103
+            print()
104
+            await asyncio.sleep(2.0)
105
+
106
+if __name__ == "__main__":
107
+    if len(sys.argv) <= 1:
108
+        print("Please pass MAC address of device")
109
+        sys.exit(1)
110
+
111
+    asyncio.run(test(sys.argv[1]))

+ 16
- 0
python-test/scan.py View File

@@ -0,0 +1,16 @@
1
+#!/usr/bin/env python
2
+
3
+import asyncio
4
+from bleak import BleakScanner
5
+
6
+async def scan():
7
+    print("scanning for 5 seconds, please wait...")
8
+    devices = await BleakScanner.discover(return_adv=True)
9
+    for d, a in devices.values():
10
+        print()
11
+        print(d)
12
+        print("-" * len(str(d)))
13
+        print(a)
14
+
15
+if __name__ == "__main__":
16
+    asyncio.run(scan())

+ 14
- 0
web-app/fetch.sh View File

@@ -0,0 +1,14 @@
1
+#!/bin/bash
2
+
3
+# https://github.com/beautify-web/js-beautify
4
+
5
+ROOT="https://app.storz-bickel.com"
6
+FILES=`curl -s $ROOT | grep "text/javascript" | grep -v "jquery" | grep -v "bootstrap" | sed 's/.*src="//g' | sed 's*"></script>**g'`
7
+
8
+for F in $FILES
9
+do
10
+    N=`echo $F | sed 's*/*_*g'`
11
+    O=`echo $N | sed 's/.js/.min.js/g'`
12
+    curl -o $O $ROOT/$F
13
+    js-beautify $O > $N
14
+done

Loading…
Cancel
Save