Adding refactored classes for ble sensing with working data collection again
This commit is contained in:
+9
-2
@@ -2,6 +2,7 @@
|
||||
import asyncio
|
||||
import json
|
||||
import platform
|
||||
from kano_wand.ble_client import KanoBLEClient
|
||||
|
||||
"""
|
||||
This is used for reading and decoding values from t he Kano Harry Potter Coding Wand
|
||||
@@ -10,7 +11,7 @@ This is used for reading and decoding values from t he Kano Harry Potter Coding
|
||||
- Wand seems to send smaller single dimensional data in 16bit unsigned integers
|
||||
"""
|
||||
|
||||
SPELLS = json.load("spells.json")
|
||||
# SPELLS = json.load("spells.json")
|
||||
CURR_SPELL = 0
|
||||
|
||||
# TODO: RUMBLE
|
||||
@@ -29,5 +30,11 @@ if __name__ == "__main__":
|
||||
if platform.system() != "Darwin"
|
||||
else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" # <--- Change to your device's address here if you are using macOS
|
||||
)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(run(address, loop, True))
|
||||
|
||||
kble = KanoBLEClient(address, loop)
|
||||
|
||||
loop.run_until_complete(kble.connect_and_read(True))
|
||||
|
||||
|
||||
|
||||
+20
-25
@@ -1,21 +1,24 @@
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from converters import BinToInt, BinToFloat
|
||||
from .sensor_tracker import *
|
||||
from .wand_sensors import *
|
||||
from bleak import BleakClient
|
||||
from bleak import _logger as logger
|
||||
from .utils import *
|
||||
from .wand_utils import *
|
||||
from .sensor_decoders import wand_decoder
|
||||
|
||||
|
||||
class KanoBLEClient(object):
|
||||
def __init__(self, wand_address, spells=None):
|
||||
def __init__(self, wand_address, loop, spells=None):
|
||||
self.wand_address = wand_address
|
||||
self.int_decoder = BinToInt(48)
|
||||
self.float_decoder = BinToFloat(16, 31)
|
||||
self.client = None
|
||||
self.decoder = wand_decoder()
|
||||
self.wand_sensors = WandSensors(self.sensor_update_handler)
|
||||
self.loop = loop
|
||||
|
||||
|
||||
async def connect(self, loop, debug=False):
|
||||
async def connect_and_read(self, debug=False):
|
||||
if debug:
|
||||
import sys
|
||||
l = logging.getLogger("asyncio")
|
||||
@@ -25,40 +28,32 @@ class KanoBLEClient(object):
|
||||
l.addHandler(h)
|
||||
logger.addHandler(h)
|
||||
|
||||
async with BleakClient(self.wand_address, loop=loop) as client:
|
||||
async with BleakClient(self.wand_address, loop=self.loop) as client:
|
||||
self.client = client
|
||||
x = await client.is_connected()
|
||||
logger.info("Connected: {0}".format(x))
|
||||
|
||||
async def start_recieving_data(self):
|
||||
await start_notify(self.client)
|
||||
await start_notify(self.client, self.sensor_handling)
|
||||
|
||||
|
||||
async def stop_recieving_data(self):
|
||||
await stop_notify(self.client)
|
||||
|
||||
|
||||
def sensor_update_handler(self, sensors):
|
||||
print(sensors)
|
||||
|
||||
def sensor_handling(self, sender, data):
|
||||
"""Simple notification handler which prints the data received."""
|
||||
# TODO: Convert to a dictionary and a single decode command
|
||||
sender = CHARACTERISTIC_UUIDS[sender]
|
||||
if sender == BUTTON:
|
||||
self.decode_button(data)
|
||||
self.wand_sensors.set_button(self.decoder.decode_button(data))
|
||||
elif sender == NINE_AXIS:
|
||||
#TODO: refactor the gyro to be local to the sensors file only
|
||||
gyro = Gyro()
|
||||
gyro.x, gyro.y, gyro.z = self.decode_nine_axis(data)
|
||||
sensors.set_gyro(gyro)
|
||||
sensors.append_to_dataframe()
|
||||
self.wand_sensors.set_gyro(*self.decoder.decode_nine_axis(data))
|
||||
elif sender == ACCELEROMETER:
|
||||
accel = Accel()
|
||||
accel.x, accel.y, accel.z = self.decode_nine_axis(data)
|
||||
sensors.set_accel(accel)
|
||||
sensors.append_to_dataframe()
|
||||
self.wand_sensors.set_accel(*self.decoder.decode_nine_axis(data))
|
||||
elif sender == BATTERY:
|
||||
self.decode_battery(data)
|
||||
self.decoder.decode_battery(data)
|
||||
elif sender == TEMPERATURE:
|
||||
self.decode_temp(data)
|
||||
self.wand_sensors.set_temp(self.decoder.decode_temp(data))
|
||||
elif sender == MAGNETOMETER:
|
||||
self.decode_magnet(data)
|
||||
|
||||
self.wand_sensors.set_magneto(self.decoder.decode_magnet(data))
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import struct
|
||||
from .wand_utils import chunker
|
||||
from converters import BinToInt, BinToFloat
|
||||
|
||||
class decoder(object):
|
||||
class wand_decoder(object):
|
||||
def __init__(self, int_decoder=BinToInt(48), float_decoder= BinToFloat(16, 31)):
|
||||
self.int_decoder = int_decoder
|
||||
self.float_decoder = float_decoder
|
||||
|
||||
def decode_button(self, data):
|
||||
if int.from_bytes(data, byteorder='big'):
|
||||
print("Button Pressed")
|
||||
else:
|
||||
print("Button Released")
|
||||
return int.from_bytes(data, byteorder='big')
|
||||
|
||||
def decode_nine_axis(self, data):
|
||||
converted = [self.int_decoder.process(x, True) / 10 ** 14 for x in chunker(data, 6)]
|
||||
@@ -21,13 +19,12 @@ class decoder(object):
|
||||
return converted
|
||||
|
||||
def decode_battery(self, data):
|
||||
int.from_bytes(data, byteorder='big')
|
||||
return int.from_bytes(data, byteorder='big')
|
||||
|
||||
def decode_temp(self, data):
|
||||
print(len(data))
|
||||
print(data)
|
||||
print(struct.unpack("h", data))
|
||||
return struct.unpack("h", data)
|
||||
|
||||
def decode_magnet(self, data):
|
||||
print(data)
|
||||
print(len(data))
|
||||
return 0
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
import pandas as pd
|
||||
|
||||
class Gyro(object):
|
||||
def __init__(self):
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.z = 0
|
||||
|
||||
def __str__(self):
|
||||
print(self.x, self.y, self.z)
|
||||
|
||||
|
||||
class Accel(object):
|
||||
def __init__(self):
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.z = 0
|
||||
|
||||
def __str__(self):
|
||||
print(self.x, self.y, self.z)
|
||||
|
||||
|
||||
class SensorTracker(object):
|
||||
def __init__(self):
|
||||
self.gyro = None
|
||||
self.gyro_updates = 0
|
||||
|
||||
self.accel = None
|
||||
self.accel_updates = 0
|
||||
self.dataframe = pd.DataFrame(columns=["gyro_x", "gyro_y", "gyro_z", "accel_x", "accel_y", "accel_z"])
|
||||
|
||||
def append_to_dataframe(self):
|
||||
if self.gyro_updates == self.accel_updates:
|
||||
self.dataframe = self.dataframe.append(
|
||||
pd.DataFrame({
|
||||
"gyro_x": self.gyro.x,
|
||||
"gyro_y": self.gyro.y,
|
||||
"gyro_z": self.gyro.z,
|
||||
"accel_x": self.accel.x,
|
||||
"accel_y": self.accel.y,
|
||||
"accel_z": self.accel.z,
|
||||
}, index=[0])
|
||||
)
|
||||
|
||||
def save_df_to_file(self, filename):
|
||||
self.dataframe.to_csv(filename, index=False)
|
||||
|
||||
def set_gyro(self, gyro):
|
||||
self.gyro = gyro
|
||||
self.gyro_updates += 1
|
||||
|
||||
def set_accel(self, accel):
|
||||
self.accel = accel
|
||||
self.accel_updates += 1
|
||||
@@ -0,0 +1,72 @@
|
||||
import pandas as pd
|
||||
|
||||
|
||||
class ThreeAxisSensor(object):
|
||||
def __init__(self, x, y, z):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
|
||||
def __str__(self):
|
||||
print(self.x, self.y, self.z)
|
||||
|
||||
|
||||
class WandSensors(object):
|
||||
def __init__(self, wand_update_callback):
|
||||
self.gyro = None
|
||||
self.gyro_updates = 0
|
||||
|
||||
self.accel = None
|
||||
self.accel_updates = 0
|
||||
|
||||
self.magneto = 0
|
||||
self.button = 0
|
||||
self.temperature = 0
|
||||
|
||||
self.dataframe = pd.DataFrame(columns=["gyro_x", "gyro_y", "gyro_z", "accel_x", "accel_y", "accel_z"])
|
||||
|
||||
self.wand_update_callback = wand_update_callback
|
||||
|
||||
def __str__(self):
|
||||
return super().__str__()
|
||||
|
||||
def append_to_dataframe(self):
|
||||
if self.gyro_updates == self.accel_updates:
|
||||
self.dataframe = self.dataframe.append(
|
||||
pd.DataFrame({
|
||||
"gyro_x": self.gyro.x,
|
||||
"gyro_y": self.gyro.y,
|
||||
"gyro_z": self.gyro.z,
|
||||
"accel_x": self.accel.x,
|
||||
"accel_y": self.accel.y,
|
||||
"accel_z": self.accel.z,
|
||||
"magneto": self.magneto,
|
||||
"button": self.button
|
||||
}, index=[0])
|
||||
)
|
||||
self.wand_update_callback(self.dataframe)
|
||||
|
||||
def save_df_to_file(self, filename):
|
||||
self.dataframe.to_csv(filename, index=False)
|
||||
|
||||
def set_gyro(self, x, y, z):
|
||||
self.gyro = ThreeAxisSensor(x, y, z)
|
||||
self.gyro_updates += 1
|
||||
self.append_to_dataframe()
|
||||
|
||||
def set_accel(self, x, y, z):
|
||||
self.accel = ThreeAxisSensor(x, y, z)
|
||||
self.accel_updates += 1
|
||||
self.append_to_dataframe()
|
||||
|
||||
def set_temp(self, temp):
|
||||
self.temp = temp
|
||||
|
||||
def set_button(self, button):
|
||||
self.button = button
|
||||
|
||||
def set_magneto(self, magneto):
|
||||
self.magneto = magneto
|
||||
|
||||
def get_dataframe(self):
|
||||
return self.dataframe
|
||||
+4
-1
@@ -2,5 +2,8 @@
|
||||
"0": "unknown",
|
||||
"1": "lumos",
|
||||
"2": "nox",
|
||||
"3": "accio"
|
||||
"3": "accio",
|
||||
"4": "expelliarmus",
|
||||
"5": "engorgio",
|
||||
"6": "reducio"
|
||||
}
|
||||
Reference in New Issue
Block a user