Browse Source

now made for micropython on rp2040 / pi pico

Thomas Buck 1 year ago
parent
commit
cbd2d34053
4 changed files with 130 additions and 136 deletions
  1. 16
    0
      python-test/copy.sh
  2. 24
    45
      python-test/flow.py
  3. 72
    59
      python-test/poll.py
  4. 18
    32
      python-test/scan.py

+ 16
- 0
python-test/copy.sh View File

1
+#!/bin/bash
2
+
3
+if [ $# -ne 0 ] ; then
4
+cat << EOF | rshell
5
+cp flow.py /pyboard
6
+cp poll.py /pyboard
7
+cp scan.py /pyboard
8
+cp $1 /pyboard/main.py
9
+EOF
10
+else
11
+cat << EOF | rshell
12
+cp flow.py /pyboard
13
+cp poll.py /pyboard
14
+cp scan.py /pyboard
15
+EOF
16
+fi

+ 24
- 45
python-test/flow.py View File

1
 #!/usr/bin/env python
1
 #!/usr/bin/env python
2
 
2
 
3
+import uasyncio as asyncio
3
 import sys
4
 import sys
4
 import time
5
 import time
5
-import os
6
 
6
 
7
 from poll import (
7
 from poll import (
8
     ble_conn,
8
     ble_conn,
12
     get_state, set_state
12
     get_state, set_state
13
 )
13
 )
14
 
14
 
15
-terminal_width = os.get_terminal_size().columns - 15
16
-
17
 def print_bar(value, start, end, unit):
15
 def print_bar(value, start, end, unit):
18
-    width = terminal_width
19
-    s = "\r"
20
-    s += "#" * int((value - start) / (end - start) * width)
21
-    s += "-" * (width - int((value - start) / (end - start) * width))
22
-    s += " {}{}".format(value, unit)
23
-    print(s, end="", flush=True)
16
+    print("{}{} -> {}{} -> {}{}".format(start, unit, value, unit, end, unit))
24
 
17
 
25
 def sleep(t):
18
 def sleep(t):
26
     w = terminal_width
19
     w = terminal_width
32
         print_bar(i + 1, 0, w, "s")
25
         print_bar(i + 1, 0, w, "s")
33
     print()
26
     print()
34
 
27
 
35
-def wait_for_temp(client, temp):
28
+async def wait_for_temp(client, temp):
36
     print("Setting temperature {}".format(temp))
29
     print("Setting temperature {}".format(temp))
37
-    set_target_temp(client, temp)
30
+    await set_target_temp(client, temp)
38
 
31
 
39
     print("Waiting for temperature to rise...")
32
     print("Waiting for temperature to rise...")
40
-    start = get_current_temp(client)
33
+    start = await get_current_temp(client)
41
     curr = start
34
     curr = start
42
     print_bar(curr, start, temp, " degC")
35
     print_bar(curr, start, temp, " degC")
43
     while curr < temp:
36
     while curr < temp:
44
         time.sleep(1.0)
37
         time.sleep(1.0)
45
-        curr = get_current_temp(client)
38
+        curr = await get_current_temp(client)
46
         print_bar(curr, start, temp, " degC")
39
         print_bar(curr, start, temp, " degC")
47
     print()
40
     print()
48
 
41
 
49
     print("Reached temperature {}".format(temp))
42
     print("Reached temperature {}".format(temp))
50
 
43
 
51
-def flow_step(client, temp, t_wait, t_pump):
52
-    wait_for_temp(client, temp)
44
+async def flow_step(client, temp, t_wait, t_pump):
45
+    await wait_for_temp(client, temp)
53
 
46
 
54
     print("Waiting {}s for heat to settle...".format(t_wait))
47
     print("Waiting {}s for heat to settle...".format(t_wait))
55
     sleep(t_wait)
48
     sleep(t_wait)
56
 
49
 
57
     print("Pumping for {}s".format(t_pump))
50
     print("Pumping for {}s".format(t_pump))
58
-    set_state(client, (True, True)) # turn on pump
51
+    await set_state(client, (True, True)) # turn on pump
59
     sleep(t_pump)
52
     sleep(t_pump)
60
-    set_state(client, (True, False)) # turn off pump
53
+    await set_state(client, (True, False)) # turn off pump
61
 
54
 
62
-def flow(client):
55
+async def flow(client):
63
     print("Turning on heater")
56
     print("Turning on heater")
64
-    set_state(client, (True, False))
57
+    await set_state(client, (True, False))
65
 
58
 
66
-    flow_step(client, 190.0, 20.0, 5.0)
67
-    flow_step(client, 205.0, 10.0, 20.0)
68
-    flow_step(client, 220.0, 10.0, 20.0)
59
+    await flow_step(client, 190.0, 20.0, 5.0)
60
+    await flow_step(client, 205.0, 10.0, 20.0)
61
+    await flow_step(client, 220.0, 10.0, 20.0)
69
 
62
 
70
     print("Notification by pumping three times...")
63
     print("Notification by pumping three times...")
71
     for i in range(0, 3):
64
     for i in range(0, 3):
72
         time.sleep(1.0)
65
         time.sleep(1.0)
73
-        set_state(client, (True, True)) # turn on pump
66
+        await set_state(client, (True, True)) # turn on pump
74
         time.sleep(1.0)
67
         time.sleep(1.0)
75
-        set_state(client, (True, False)) # turn off pump
68
+        await set_state(client, (True, False)) # turn off pump
76
 
69
 
77
     print("Turning heater off")
70
     print("Turning heater off")
78
-    set_state(client, (False, False)) # turn off heater and pump
71
+    await set_state(client, (False, False)) # turn off heater and pump
79
 
72
 
80
 if __name__ == "__main__":
73
 if __name__ == "__main__":
81
-    def main(address, adapter):
82
-        client = ble_conn(address, adapter)
74
+    async def main(address):
75
+        client = await ble_conn(address)
83
 
76
 
84
         try:
77
         try:
85
-            if get_unit_is_fahrenheit(client):
78
+            if await get_unit_is_fahrenheit(client):
86
                 raise RuntimeError("Imperial American scum is currently not supported :P")
79
                 raise RuntimeError("Imperial American scum is currently not supported :P")
87
 
80
 
88
             print("Starting Workflow")
81
             print("Starting Workflow")
89
-            flow(client)
82
+            await flow(client)
90
         except:
83
         except:
91
             print("\nTurning heater off")
84
             print("\nTurning heater off")
92
-            set_state(client, (False, False)) # turn off heater and pump
93
-
94
-            print("Disconnecting")
95
-            client.disconnect()
96
-
85
+            await set_state(client, (False, False)) # turn off heater and pump
97
             raise
86
             raise
98
 
87
 
99
-        print("Disconnecting")
100
-        client.disconnect()
101
-
102
-    adapter = None
103
-    mac = None
104
-    if len(sys.argv) > 1:
105
-        adapter = int(sys.argv[1])
106
-    if len(sys.argv) > 2:
107
-        mac = sys.argv[2]
108
-
109
-    main(mac, adapter)
88
+    asyncio.run(main(None))

+ 72
- 59
python-test/poll.py View File

1
 #!/usr/bin/env python
1
 #!/usr/bin/env python
2
 
2
 
3
-import simplepyble
4
-from scan import ble_scan
3
+import uasyncio as asyncio
4
+import bluetooth
5
 import time
5
 import time
6
 
6
 
7
-serviceUuidVolcano3 = "10100000-5354-4f52-5a26-4249434b454c"
8
-serviceUuidVolcano4 = "10110000-5354-4f52-5a26-4249434b454c"
7
+from scan import ble_scan
8
+
9
+serviceUuidVolcano3 = bluetooth.UUID("10100000-5354-4f52-5a26-4249434b454c")
10
+serviceUuidVolcano4 = bluetooth.UUID("10110000-5354-4f52-5a26-4249434b454c")
9
 
11
 
10
-def ble_conn(address, adapter):
11
-    dev = ble_scan(address, adapter)
12
+async def ble_conn(address):
13
+    dev = await ble_scan(address)
12
 
14
 
13
-    if dev != None:
14
-        address = dev.address()
15
+    if dev:
16
+        address = dev.addr_hex()
15
         print("Connecting to '{}'...".format(address))
17
         print("Connecting to '{}'...".format(address))
16
-        dev.connect()
18
+        connection = await dev.connect()
19
+        return connection
17
 
20
 
18
-    return dev
21
+    return None
19
 
22
 
20
-def get_current_temp(device):
21
-    val = device.read(serviceUuidVolcano4, "10110001-5354-4f52-5a26-4249434b454c")
22
-    num = int.from_bytes(val, byteorder="little")
23
+async def get_current_temp(device):
24
+    service = await device.service(serviceUuidVolcano4)
25
+    uuid = bluetooth.UUID("10110001-5354-4f52-5a26-4249434b454c")
26
+    characteristic = await service.characteristic(uuid)
27
+    val = await characteristic.read()
28
+    num = int.from_bytes(val, "little")
23
     return num / 10.0
29
     return num / 10.0
24
 
30
 
25
-def get_target_temp(device):
26
-    val = device.read(serviceUuidVolcano4, "10110003-5354-4f52-5a26-4249434b454c")
27
-    num = int.from_bytes(val, byteorder="little")
31
+async def get_target_temp(device):
32
+    service = await device.service(serviceUuidVolcano4)
33
+    uuid = bluetooth.UUID("10110003-5354-4f52-5a26-4249434b454c")
34
+    characteristic = await service.characteristic(uuid)
35
+    val = await characteristic.read()
36
+    num = int.from_bytes(val, "little")
28
     return num / 10.0
37
     return num / 10.0
29
 
38
 
30
-def set_target_temp(device, temp):
39
+async def set_target_temp(device, temp):
31
     val = int(temp * 10.0)
40
     val = int(temp * 10.0)
32
-    d = val.to_bytes(4, byteorder="little")
33
-    device.write_request(serviceUuidVolcano4, "10110003-5354-4f52-5a26-4249434b454c", d)
34
-
35
-def get_unit_is_fahrenheit(device):
36
-    val = device.read(serviceUuidVolcano3, "1010000d-5354-4f52-5a26-4249434b454c")
37
-    num = int.from_bytes(val, byteorder="little")
41
+    d = val.to_bytes(4, "little")
42
+    service = await device.service(serviceUuidVolcano4)
43
+    uuid = bluetooth.UUID("10110003-5354-4f52-5a26-4249434b454c")
44
+    characteristic = await service.characteristic(uuid)
45
+    await characteristic.write(d)
46
+
47
+async def get_unit_is_fahrenheit(device):
48
+    service = await device.service(serviceUuidVolcano3)
49
+    uuid = bluetooth.UUID("1010000d-5354-4f52-5a26-4249434b454c")
50
+    characteristic = await service.characteristic(uuid)
51
+    val = await characteristic.read()
52
+    num = int.from_bytes(val, "little")
38
     return (num & 0x200) != 0
53
     return (num & 0x200) != 0
39
 
54
 
40
-def get_state(device):
41
-    val = device.read(serviceUuidVolcano3, "1010000c-5354-4f52-5a26-4249434b454c")
42
-    num = int.from_bytes(val, byteorder="little")
55
+async def get_state(device):
56
+    service = await device.service(serviceUuidVolcano3)
57
+    uuid = bluetooth.UUID("1010000c-5354-4f52-5a26-4249434b454c")
58
+    characteristic = await service.characteristic(uuid)
59
+    val = await characteristic.read()
60
+    num = int.from_bytes(val, "little")
43
     heater = (num & 0x0020) != 0
61
     heater = (num & 0x0020) != 0
44
     pump = (num & 0x2000) != 0
62
     pump = (num & 0x2000) != 0
45
     return (heater, pump)
63
     return (heater, pump)
46
 
64
 
47
-def set_state(device, state):
65
+async def set_state(device, state):
48
     heater, pump = state
66
     heater, pump = state
49
     if heater:
67
     if heater:
50
-        device.write_request(serviceUuidVolcano4, "1011000f-5354-4f52-5a26-4249434b454c", 0)
68
+        service = await device.service(serviceUuidVolcano4)
69
+        uuid = bluetooth.UUID("1011000f-5354-4f52-5a26-4249434b454c")
70
+        characteristic = await service.characteristic(uuid)
71
+        await characteristic.write(int(0).to_bytes(1, "little"))
51
     else:
72
     else:
52
-        device.write_request(serviceUuidVolcano4, "10110010-5354-4f52-5a26-4249434b454c", 0)
73
+        service = await device.service(serviceUuidVolcano4)
74
+        uuid = bluetooth.UUID("10110010-5354-4f52-5a26-4249434b454c")
75
+        characteristic = await service.characteristic(uuid)
76
+        await characteristic.write(int(0).to_bytes(1, "little"))
53
     if pump:
77
     if pump:
54
-        device.write_request(serviceUuidVolcano4, "10110013-5354-4f52-5a26-4249434b454c", 0)
78
+        service = await device.service(serviceUuidVolcano4)
79
+        uuid = bluetooth.UUID("10110013-5354-4f52-5a26-4249434b454c")
80
+        characteristic = await service.characteristic(uuid)
81
+        await characteristic.write(int(0).to_bytes(1, "little"))
55
     else:
82
     else:
56
-        device.write_request(serviceUuidVolcano4, "10110014-5354-4f52-5a26-4249434b454c", 0)
83
+        service = await device.service(serviceUuidVolcano4)
84
+        uuid = bluetooth.UUID("10110014-5354-4f52-5a26-4249434b454c")
85
+        characteristic = await service.characteristic(uuid)
86
+        await characteristic.write(int(0).to_bytes(1, "little"))
57
 
87
 
58
 if __name__ == "__main__":
88
 if __name__ == "__main__":
59
-    def test_poll(device):
60
-        temp = get_current_temp(device)
89
+    async def test_poll(device):
90
+        temp = await get_current_temp(device)
61
         print("Current Temperature: {}".format(temp))
91
         print("Current Temperature: {}".format(temp))
62
 
92
 
63
-        target = get_target_temp(device)
93
+        target = await get_target_temp(device)
64
         print("Target Temperature: {}".format(target))
94
         print("Target Temperature: {}".format(target))
65
 
95
 
66
-        fahrenheit = get_unit_is_fahrenheit(device)
96
+        fahrenheit = await get_unit_is_fahrenheit(device)
67
         if fahrenheit:
97
         if fahrenheit:
68
             print("Unit is Fahrenheit")
98
             print("Unit is Fahrenheit")
69
         else:
99
         else:
70
             print("Unit is Celsius")
100
             print("Unit is Celsius")
71
 
101
 
72
-        heater, pump = get_state(device)
102
+        heater, pump = await get_state(device)
73
         if heater:
103
         if heater:
74
             print("Heater is On")
104
             print("Heater is On")
75
         else:
105
         else:
79
         else:
109
         else:
80
             print("Pump is Off")
110
             print("Pump is Off")
81
 
111
 
82
-    def test(address, adapter):
83
-        device = ble_conn(address, adapter)
112
+    async def test(address):
113
+        device = await ble_conn(address)
84
         if device == None:
114
         if device == None:
85
             return
115
             return
86
 
116
 
87
-        try:
117
+        async with device:
88
             print("Writing...")
118
             print("Writing...")
89
-            set_target_temp(device, 190.0)
119
+            await set_target_temp(device, 190.0)
90
 
120
 
91
             print("Reading...")
121
             print("Reading...")
92
             for i in range(0, 5):
122
             for i in range(0, 5):
93
-                test_poll(device)
123
+                await test_poll(device)
94
                 print()
124
                 print()
95
                 time.sleep(2.0)
125
                 time.sleep(2.0)
96
-        except:
97
-            print("Disconnecting")
98
-            client.disconnect()
99
-
100
-            raise
101
-
102
-        print("Disconnecting")
103
-        client.disconnect()
104
-
105
-    import sys
106
-
107
-    adapter = None
108
-    mac = None
109
-    if len(sys.argv) > 1:
110
-        adapter = int(sys.argv[1])
111
-    if len(sys.argv) > 2:
112
-        mac = sys.argv[2]
113
 
126
 
114
-    test(mac, adapter)
127
+    asyncio.run(test(None))

+ 18
- 32
python-test/scan.py View File

1
-import simplepyble
1
+# https://github.com/micropython/micropython-lib/blob/master/micropython/bluetooth/aioble/examples/temp_client.py
2
 
2
 
3
-def ble_scan(addr = None, adapterIndex = 0, timeout = 1):
4
-    adapters = simplepyble.Adapter.get_adapters()
3
+import uasyncio as asyncio
4
+import aioble
5
+import bluetooth
6
+import sys
5
 
7
 
6
-    if len(adapters) == 0:
7
-        print("No adapters found")
8
-        return None
9
-
10
-    adapter = adapters[adapterIndex]
11
-    print("Selected adapter: {} [{}]".format(adapter.identifier(), adapter.address()))
12
-
13
-    # TODO abort scan when found?
8
+async def ble_scan(addr = None, timeout = 0.1):
14
     print("Scanning for '{}' for {}s...".format(addr, timeout))
9
     print("Scanning for '{}' for {}s...".format(addr, timeout))
15
-    adapter.scan_for(timeout * 1000)
16
-
17
-    peripherals = adapter.scan_get_results()
18
-    for peripheral in peripherals:
19
-        if addr != None:
20
-            if addr == peripheral.address():
21
-                return peripheral
22
-        else:
23
-            if peripheral.identifier() == "S&B VOLCANO H":
24
-                return peripheral
10
+    scanner = aioble.scan(int(timeout * 1000.0), interval_us=30000, window_us=30000, active=True)
11
+    async with scanner as s:
12
+        async for d in s:
13
+            print("Scan: '{}' [{}]".format(d.name(), d.device.addr_hex()))
14
+            if addr != None:
15
+                if addr == d.device.addr_hex():
16
+                    return d.device
17
+            else:
18
+                if d.name() == "S&B VOLCANO H":
19
+                    return d.device
25
 
20
 
26
     print("No device found")
21
     print("No device found")
27
     return None
22
     return None
28
 
23
 
29
 if __name__ == "__main__":
24
 if __name__ == "__main__":
30
-    import sys
31
-
32
-    adapter = None
33
-    mac = None
34
-    if len(sys.argv) > 1:
35
-        adapter = int(sys.argv[1])
36
-    if len(sys.argv) > 2:
37
-        mac = sys.argv[2]
38
-
39
-    dev = ble_scan(mac, adapter)
25
+    dev = asyncio.run(ble_scan())
40
     if dev != None:
26
     if dev != None:
41
-        print("{} {}".format(dev.identifier(), dev.address()))
27
+        print("{}".format(dev.addr_hex()))

Loading…
Cancel
Save