Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,8 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# VSCode
.vscode

# Testcase for personal use
test/
2 changes: 1 addition & 1 deletion demo.py → demo_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ async def _():
await dglab_instance.close()


asyncio.run(_())
asyncio.run(_())
35 changes: 35 additions & 0 deletions demo_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Description: This is a demo script to show how to use the pydglab library to interact with the DGLab device.

import asyncio
import logging

import pydglab
from pydglab import model_v3

logging.basicConfig(
format="%(module)s [%(levelname)s]: %(message)s", level=logging.DEBUG
)


async def _():
await pydglab.scan()
dglab_instance = pydglab.dglab_v3()
try:
await dglab_instance.create()
except TimeoutError:
logging.error("Timeout, retrying...")
await dglab_instance.create()
await dglab_instance.set_coefficient(100, 100, 100, model_v3.ChannelA)
await dglab_instance.set_coefficient(100, 100, 100, model_v3.ChannelB)
await dglab_instance.get_strength()
await dglab_instance.set_strength_sync(1, 1)
await dglab_instance.set_wave_sync(0, 0, 0, 0, 0, 0)
await dglab_instance.set_wave_set(
model_v3.Wave_set["Going_Faster"], model_v3.ChannelA
)
await dglab_instance.get_strength()
await asyncio.sleep(2)
await dglab_instance.close()


asyncio.run(_())
4 changes: 3 additions & 1 deletion pydglab/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
handler.setFormatter(logging.Formatter(fmt=LOGFORMAT))
_logger.addHandler(handler)

from .service import dglab
from .service import dglab, dglab_v3
from .model import *
from .bthandler import scan
from .model_v3 import *
from .bthandler_v3 import scan
87 changes: 87 additions & 0 deletions pydglab/bthandler_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import logging
from bleak import BleakClient, BleakScanner
from typing import Tuple, List
from bitstring import BitArray

from pydglab.model_v3 import *
from pydglab.uuid import *

logger = logging.getLogger(__name__)


async def scan():
"""
Scan for DGLAB v3.0 devices and return a list of tuples with the address and the RSSI of the devices found.

Returns:
List[Tuple[str, int]]: (address, RSSI)
"""
devices = await BleakScanner().discover(return_adv=True)
dglab_v3: List[Tuple[str, int]] = []
for i, j in devices.values():
if j.local_name == CoyoteV3.name and i.address is not None:
logger.info(f"Found DGLAB v3.0 {i.address}")
dglab_v3.append((i.address, j.rssi))
if not dglab_v3:
logger.error("No DGLAB v3.0 found")
return dglab_v3


async def scan_():
dglab_v3 = await scan()
if not dglab_v3:
raise Exception("No DGLAB v3.0 found")
if len(dglab_v3) > 1:
logger.warning("Multiple DGLAB v3.0 found, chosing the closest one")
elif len(dglab_v3) == 0:
raise Exception("No DGLAB v3.0 found")
return sorted(dglab_v3, key=lambda device: device[1])[0][0]


async def notify_(client: BleakClient, characteristics: CoyoteV3, callback: callable):
await client.start_notify(characteristics.characteristicNotify, callback)


async def write_strenth_(client: BleakClient, value: Coyote_v3, characteristics: CoyoteV3):
struct = (
0xB0,
0b00010000 + 0b00001111,
value.ChannelA.strength,
value.ChannelB.strength,
value.ChannelA.wave,
value.ChannelA.waveStrenth,
value.ChannelB.wave,
value.ChannelB.waveStrenth,
)
bytes_ = bytes(
tuple(
item if isinstance(item, int) else subitem
for item in struct
for subitem in (tuple(item) if isinstance(item, list) else (item,))
)
)
logger.debug(f"Sending bytes: {bytes_.hex()} , which is {bytes_}")
await client.write_gatt_char(characteristics.characteristicWrite, bytes_)


async def write_coefficient_(
client: BleakClient, value: Coyote_v3, characteristics: CoyoteV3
):
struct = (
0xBF,
value.ChannelA.limit,
value.ChannelB.limit,
value.ChannelA.coefficientFrequency,
value.ChannelB.coefficientFrequency,
value.ChannelA.coefficientStrenth,
value.ChannelB.coefficientStrenth,
)
bytes_ = bytes(
tuple(
item if isinstance(item, int) else subitem
for item in struct
for subitem in (item if isinstance(item, tuple) else (item,))
)
)
logger.debug(f"Sending bytes: {bytes_.hex()} , which is {bytes_}")
await client.write_gatt_char(characteristics.characteristicWrite, bytes_)
2 changes: 1 addition & 1 deletion pydglab/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ def __init__(self):
(1, 14, 20),
(1, 9, 20),
],
}
}
48 changes: 48 additions & 0 deletions pydglab/model_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from typing import Optional


class ChannelA(object):
def __init__(self):
self.strength: Optional[int] = None
self.wave: Optional[list[int]] = [0, 0, 0, 0]
self.waveStrenth: Optional[list[int]] = [0, 0, 0, 0]
self.coefficientStrenth: Optional[int] = None
self.coefficientFrequency: Optional[int] = None
self.limit: Optional[int] = None


class ChannelB(object):
def __init__(self):
self.strength: Optional[int] = None
self.wave: Optional[list[int]] = [0, 0, 0, 0]
self.waveStrenth: Optional[list[int]] = [0, 0, 0, 0]
self.coefficientStrenth: Optional[int] = None
self.coefficientFrequency: Optional[int] = None
self.limit: Optional[int] = None


class Coyote_v3(object):
def __init__(self):
self.ChannelA: Optional[ChannelA] = ChannelA()
self.ChannelB: Optional[ChannelB] = ChannelB()


Wave_set = {
"Going_Faster": [
(5, 135, 20),
(5, 125, 20),
(5, 115, 20),
(5, 105, 20),
(5, 95, 20),
(4, 86, 20),
(4, 76, 20),
(4, 66, 20),
(3, 57, 20),
(3, 47, 20),
(3, 37, 20),
(2, 28, 20),
(2, 18, 20),
(1, 14, 20),
(1, 9, 20),
],
}
Loading