Adding and logging to csv files to the subscription service

This commit is contained in:
Lucas Oskorep
2019-11-07 22:16:43 -06:00
parent 1850be4cff
commit 48866f6af2
6 changed files with 207 additions and 128 deletions
-1
View File
@@ -1 +0,0 @@
etwy
-37
View File
@@ -1,37 +0,0 @@
import gatt
manager = gatt.DeviceManager(adapter_name='hci0')
class KanoWand(gatt.Device):
def services_resolved(self):
super().services_resolved()
print("Grabbing services")
print(self.is_connected())
print(self.services)
for service in self.services:
print("FOUND SERVICE")
# print(service)
# print(service.device)
print(service.uuid)
print(service.characteristics)
for char in service.characteristics:
print("FOUND CHARACTERISTIC")
print(char.uuid)
print(char.read_value())
# device_information_service = next(s for s in self.services if s.uuid == '0000180a-0000-1000-8000-00805f9b34fb')
#
# firmware_version_characteristic = next(
# c for c in device_information_service.characteristics
# if c.uuid == '00002a26-0000-1000 -8000-00805f9b34fb')
#
# firmware_version_characteristic.read_value()
def characteristic_value_updated(self, characteristic, value):
print("Firmware version:", value.decode("utf-8"))
device = KanoWand(mac_address='e3:ae:cd:af:28:e2', manager=manager)
device.connect()
manager.run()
manager.stop()
View File
+56
View File
@@ -0,0 +1,56 @@
import asyncio
from bleak import discover
from pprint import pprint
async def run():
devices = await discover()
for d in devices:
print(d)
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
import asyncio
from bleak import BleakClient
address = "D8:9B:12:D1:08:80"
MODEL_NBR_UUID = "64a7000f-f691-4b93-a6f4-0968f5b648f8"
async def run(address, loop):
async with BleakClient(address, loop=loop) as client:
# await client.connect()
print(await client.is_connected())
print(await client.get_services())
services = await client.get_services()
pprint(services.descriptors)
pprint(services.characteristics)
pprint(services.services)
# print(services.descriptors)
# for key, val in services.descriptors.items():
# print(f"{key} + {val}")
#
# print(services.characteristics)
# for key, val in services.characteristics.items():
# print(f"{key} + {val}")
print(services)
for x in services:
print(x)
for characteristic in x.characteristics:
print("")
print(characteristic)
print(characteristic.properties)
for descriptor in characteristic.descriptors:
print(descriptor)
print(x.description)
# for i in range(10):
# x = await client.read_gatt_descriptor(i)
# print(x)
# model_number = await client.read_gatt_char()
# print(model_number)
# print("Model Number: {0}".format("".join(map(chr, model_number))))
loop = asyncio.get_event_loop()
loop.run_until_complete(run(address, loop))
+151 -32
View File
@@ -1,62 +1,152 @@
"""
Notifications
-------------
Example showing how to add notifications to a characteristic and handle the responses.
Updated on 2019-07-03 by hbldh <henrik.blidh@gmail.com>
"""
import logging import logging
import asyncio import asyncio
import platform import platform
import struct import struct
import time
import pandas as pd
from bleak import BleakClient from bleak import BleakClient
from bleak import _logger as logger from bleak import _logger as logger
from converters import BinToInt from converters import BinToInt, BinToFloat
"""
This is used for reading and decoding values from t he Kano Harry Potter Coding Wand
- Wand sends 25 updates to gyro and accel every second
- Wand sends 3 Dimensional data as 48 bit reverse marshalled integers
- Wand seems to send smaller single dimensional data in 16bit unsigned integers
"""
BUTTON = 1 BUTTON = 1
GYROSCOPE = 2 NINE_AXIS = 2
ACCELEROMETER = 3 ACCELEROMETER = 3
BATTERY = 4 BATTERY = 4
TEMPERATURE = 5 TEMPERATURE = 5
MAGNETOMETER = 6
INT_DECODER = BinToInt(48) INT_DECODER = BinToInt(48)
FLOAT_DECODER = BinToFloat(16, 31)
BUTTON_STATUS = None
CHARACTERISTIC_UUIDS = { CHARACTERISTIC_UUIDS = {
# ("64a7000d-f691-4b93-a6f4-0968f5b648f8"):BUTTON,#Button ("64a7000d-f691-4b93-a6f4-0968f5b648f8"): BUTTON, # Button
# ("64a7000a-f691-4b93-a6f4-0968f5b648f8"):GYROSCOPE,#9 axis ("64a7000a-f691-4b93-a6f4-0968f5b648f8"): NINE_AXIS, # 9 axis
("64a7000c-f691-4b93-a6f4-0968f5b648f8"): ACCELEROMETER, # Accel ("64a7000c-f691-4b93-a6f4-0968f5b648f8"): ACCELEROMETER, # Accel
# ("64a70007-f691-4b93-a6f4-0968f5b648f8"):BATTERY, # ("64a70007-f691-4b93-a6f4-0968f5b648f8"):BATTERY,
# ("64a70014-f691-4b93-a6f4-0968f5b648f8"):TEMPERATURE # ("64a70014-f691-4b93-a6f4-0968f5b648f8"):TEMPERATURE,
# ("64a70014-f691-4b93-a6f4-0968f5b648f8"):MAGNETOMETER
} # <--- Change to the characteristic you want to enable notifications from. } # <--- Change to the characteristic you want to enable notifications from.
# TODO: RUMBLE # TODO: RUMBLE
# TODO: RGB # TODO: RGB
# TODO: MAGNETOMETER??
#
# device_address = "e3:ae:cd:af:28:e2"
device_address = "D8:9B:12:D1:08:80" device_address = "D8:9B:12:D1:08:80"
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 Sensors(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):
# print("Printing the gyro and accel", self.gyro, self.accel)
# print(self.dataframe)
# print(self.gyro_updates, self.accel_updates)
if self.gyro_updates == self.accel_updates:
# print({
# "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,
# })
# try:
#
# except Exception as e:
# print("ERROR HAS OCCURRED")
# print(e)
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
def chunker(seq, size): def chunker(seq, size):
return (seq[pos:pos + size] for pos in range(0, len(seq), size)) return (seq[pos:pos + size] for pos in range(0, len(seq), size))
def decode_button(data):
print(data)
print(int.from_bytes(data, byteorder='big'))
def decode_gyroscope(data): count = 0
decode_accelerometer(data)
def decode_button(data):
global sensors, count
if int.from_bytes(data, byteorder='big'):
print("Button Pressed")
sensors = Sensors()
count += 1
else:
print("Button Released")
sensors.save_df_to_file(f"dataset{count}.csv")
def decode_nine_axis(data):
converted = [INT_DECODER.process(x, True) / 10 ** 14 for x in chunker(data, 6)]
# print(converted, sum(converted))
return converted
def decode_accelerometer(data): def decode_accelerometer(data):
converted = [INT_DECODER.process(x, True)/10**14 for x in chunker(data, 6)] converted = [INT_DECODER.process(x, True) / 10 ** 14 for x in chunker(data, 6)]
print(converted,sum(converted)) # print(converted, sum(converted))
return converted
def decode_battery(data): def decode_battery(data):
print(len(data)) global BUTTON_STATUS
print(data) BUTTON_STATUS = int.from_bytes(data, byteorder='big')
print(int.from_bytes(data, byteorder='big'))
def decode_temp(data): def decode_temp(data):
print(len(data)) print(len(data))
@@ -64,30 +154,56 @@ def decode_temp(data):
print(struct.unpack("h", data)) print(struct.unpack("h", data))
def decode_magnet(data):
print(data)
print(len(data))
count = 0
sensors = Sensors()
def notification_handler(sender, data): def notification_handler(sender, data):
global count, sensors
"""Simple notification handler which prints the data received.""" """Simple notification handler which prints the data received."""
#TODO: Convert to a dictionary and a single decode command # TODO: Convert to a dictionary and a single decode command
sender = CHARACTERISTIC_UUIDS[sender] sender = CHARACTERISTIC_UUIDS[sender]
if sender == BUTTON: if sender == BUTTON:
decode_button(data) decode_button(data)
elif sender == GYROSCOPE: elif sender == NINE_AXIS:
decode_gyroscope(data) gyro = Gyro()
# print("getting gyro values")
gyro.x, gyro.y, gyro.z = decode_nine_axis(data)
# print("got gyro values")
# print(gyro)
sensors.set_gyro(gyro)
sensors.append_to_dataframe()
elif sender == ACCELEROMETER: elif sender == ACCELEROMETER:
decode_accelerometer(data) accel = Accel()
accel.x, accel.y, accel.z = decode_nine_axis(data)
sensors.set_accel(accel)
sensors.append_to_dataframe()
# decode_accelerometer(data)
elif sender == BATTERY: elif sender == BATTERY:
decode_battery(data) decode_battery(data)
elif sender == TEMPERATURE: elif sender == TEMPERATURE:
decode_temp(data) decode_temp(data)
elif sender == MAGNETOMETER:
decode_magnet(data)
async def start_notify(client): async def start_notify(client):
for char in CHARACTERISTIC_UUIDS.keys(): for char in CHARACTERISTIC_UUIDS.keys():
await client.start_notify(char, notification_handler) await client.start_notify(char, notification_handler)
async def stop_notify(client): async def stop_notify(client):
for char in CHARACTERISTIC_UUIDS.keys(): for char in CHARACTERISTIC_UUIDS.keys():
await client.stop_notify(char) await client.stop_notify(char)
async def run(address, loop, debug=False): async def run(address, loop, debug=False):
if debug: if debug:
import sys import sys
@@ -105,13 +221,16 @@ async def run(address, loop, debug=False):
logger.info("Connected: {0}".format(x)) logger.info("Connected: {0}".format(x))
await start_notify(client) await start_notify(client)
await asyncio.sleep(60.0, loop=loop) # await asyncio.sleep(60.0, loop=loop)
while True:
time.sleep(1)
await stop_notify(client) await stop_notify(client)
if __name__ == "__main__": if __name__ == "__main__":
import os import os
os.environ["PYTHONASYNCIODEBUG"] = str(1) os.environ["PYTHONASYNCIODEBUG"] = str(1)
address = ( address = (
device_address # <--- Change to your device's address here if you are using Windows or Linux device_address # <--- Change to your device's address here if you are using Windows or Linux
@@ -119,4 +238,4 @@ if __name__ == "__main__":
else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" # <--- Change to your device's address here if you are using macOS else "243E23AE-4A99-406C-B317-18F1BD7B4CBE" # <--- Change to your device's address here if you are using macOS
) )
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
loop.run_until_complete(run(address, loop, True)) loop.run_until_complete(run(address, loop, True))
-58
View File
@@ -1,58 +0,0 @@
import asyncio
from bleak import discover
from pprint import pprint
async def run():
devices = await discover()
for d in devices:
print(d)
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
# import asyncio
# from bleak import BleakClient
#
# address = "e3:ae:cd:af:28:e2"
# MODEL_NBR_UUID = "64a7000f-f691-4b93-a6f4-0968f5b648f8"
#
# async def run(address, loop):
# async with BleakClient(address, loop=loop) as client:
# # await client.connect()
# print(await client.is_connected())
# print(await client.get_services())
# services = await client.get_services()
# pprint(services.descriptors)
# pprint(services.characteristics)
# pprint(services.services)
# # print(services.descriptors)
# # for key, val in services.descriptors.items():
# # print(f"{key} + {val}")
# #
# # print(services.characteristics)
# # for key, val in services.characteristics.items():
# # print(f"{key} + {val}")
#
# print(services)
# for x in services:
# print(x)
# for characteristic in x.characteristics:
# print("")
# print(characteristic)
# print(characteristic.properties)
# for descriptor in characteristic.descriptors:
# print(descriptor)
# print(x.description)
# # for i in range(10):
# # x = await client.read_gatt_descriptor(i)
# # print(x)
#
# # model_number = await client.read_gatt_char()
# # print(model_number)
# # print("Model Number: {0}".format("".join(map(chr, model_number))))
#
#
# loop = asyncio.get_event_loop()
# loop.run_until_complete(run(address, loop))