mirror of https://github.com/labapart/gattlib
gattlib-py/examples/nordic_thingy: Add example for sound support
parent
e5daed3484
commit
4e9b1094d4
|
@ -0,0 +1,183 @@
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from dbus.mainloop.glib import DBusGMainLoop
|
||||||
|
try:
|
||||||
|
from gi.repository import GLib, GObject
|
||||||
|
except ImportError:
|
||||||
|
import gobject as GObject
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
from matplotlib.pylab import *
|
||||||
|
from mpl_toolkits.axes_grid1 import host_subplot
|
||||||
|
import matplotlib.animation as animation
|
||||||
|
|
||||||
|
from gattlib import uuid
|
||||||
|
|
||||||
|
last_measures = {
|
||||||
|
'temperature': { 'value': None, 'min': None, 'max': None },
|
||||||
|
'pressure': { 'value': None, 'min': None, 'max': None },
|
||||||
|
'humidity': { 'value': None, 'min': None, 'max': None },
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def temperature_notification(value, user_data):
|
||||||
|
last_measures['temperature']['value'] = float("%d.%d" % (value[0], value[1]))
|
||||||
|
print("Temperature: %f" % last_measures['temperature']['value'])
|
||||||
|
|
||||||
|
|
||||||
|
def pressure_notification(value, user_data):
|
||||||
|
(pressure_integer, pressure_decimal) = struct.unpack("<IB", value)
|
||||||
|
last_measures['pressure']['value'] = float("%d.%d" % (pressure_integer, pressure_decimal))
|
||||||
|
print("Pressure: %f" % last_measures['pressure']['value'])
|
||||||
|
|
||||||
|
|
||||||
|
def humidity_notification(value, user_data):
|
||||||
|
last_measures['humidity']['value'] = value[0]
|
||||||
|
print("Humidity: %d%%" % last_measures['humidity']['value'])
|
||||||
|
|
||||||
|
|
||||||
|
# Data Placeholders
|
||||||
|
temperature = zeros(0)
|
||||||
|
humidity = zeros(0)
|
||||||
|
t = zeros(0)
|
||||||
|
x = 0.0
|
||||||
|
xmax = 1000.0
|
||||||
|
temp_line = None
|
||||||
|
hum_line = None
|
||||||
|
ax_temp = None
|
||||||
|
ax_hum = None
|
||||||
|
simulation = None
|
||||||
|
|
||||||
|
|
||||||
|
def graph_init():
|
||||||
|
global x
|
||||||
|
global temperature, humidity, t
|
||||||
|
global temp_line, hum_line
|
||||||
|
global ax_temp, ax_hum
|
||||||
|
global simulation
|
||||||
|
|
||||||
|
font = {'size' : 9}
|
||||||
|
matplotlib.rc('font', **font)
|
||||||
|
|
||||||
|
# Setup figure and subplots
|
||||||
|
f0 = figure(num=0, figsize=(12, 8)) # , dpi = 100)
|
||||||
|
f0.suptitle("Nordic Thingy", fontsize=12)
|
||||||
|
ax_temp = host_subplot(111)
|
||||||
|
ax_hum = ax_temp.twinx()
|
||||||
|
|
||||||
|
# Set titles of subplots
|
||||||
|
ax_temp.set_title('Temperature/Humidity vs Time')
|
||||||
|
|
||||||
|
# set y-limits
|
||||||
|
ax_temp.set_ylim(0, 45)
|
||||||
|
ax_hum.set_ylim(0, 100)
|
||||||
|
|
||||||
|
# sex x-limits
|
||||||
|
ax_temp.set_xlim(0, xmax)
|
||||||
|
ax_hum.set_xlim(0, xmax)
|
||||||
|
|
||||||
|
# Turn on grids
|
||||||
|
ax_temp.grid(True)
|
||||||
|
|
||||||
|
# set label names
|
||||||
|
ax_temp.set_xlabel("t")
|
||||||
|
ax_temp.set_ylabel("temperature")
|
||||||
|
ax_hum.set_ylabel("humidity")
|
||||||
|
|
||||||
|
temp_line, = ax_temp.plot(t, temperature, 'b-', label="temperature")
|
||||||
|
hum_line, = ax_hum.plot(t, humidity, 'g-', label="humidity")
|
||||||
|
|
||||||
|
# set lagends
|
||||||
|
ax_temp.legend([temp_line, hum_line], [temp_line.get_label(), hum_line.get_label()])
|
||||||
|
|
||||||
|
# interval: draw new frame every 'interval' ms
|
||||||
|
# Note: We expose simulation to prevent Python garbage collector to rmeove it!
|
||||||
|
simulation = animation.FuncAnimation(f0, graph_update, blit=False, interval=20)
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
def graph_update(self):
|
||||||
|
global x, xmax
|
||||||
|
global temperature, humidity, t
|
||||||
|
global temp_line, hum_line
|
||||||
|
|
||||||
|
if last_measures['temperature']['value']:
|
||||||
|
temperature = append(temperature, last_measures['temperature']['value'])
|
||||||
|
if last_measures['temperature']['min']:
|
||||||
|
last_measures['temperature']['min'] = min(last_measures['temperature']['min'], last_measures['temperature']['value'] - 5)
|
||||||
|
else:
|
||||||
|
last_measures['temperature']['min'] = last_measures['temperature']['value'] - 5
|
||||||
|
if last_measures['temperature']['max']:
|
||||||
|
last_measures['temperature']['max'] = max(last_measures['temperature']['max'], last_measures['temperature']['value'] + 5)
|
||||||
|
else:
|
||||||
|
last_measures['temperature']['max'] = last_measures['temperature']['value'] + 5
|
||||||
|
|
||||||
|
ax_temp.set_ylim(last_measures['temperature']['min'], last_measures['temperature']['max'])
|
||||||
|
|
||||||
|
if last_measures['humidity']['value']:
|
||||||
|
humidity = append(humidity, last_measures['humidity']['value'])
|
||||||
|
if last_measures['humidity']['min']:
|
||||||
|
last_measures['humidity']['min'] = min(last_measures['humidity']['min'], last_measures['humidity']['value'] - 20)
|
||||||
|
else:
|
||||||
|
last_measures['humidity']['min'] = last_measures['humidity']['value'] - 20
|
||||||
|
if last_measures['humidity']['max']:
|
||||||
|
last_measures['humidity']['max'] = max(last_measures['humidity']['max'], last_measures['humidity']['value'] + 20)
|
||||||
|
else:
|
||||||
|
last_measures['humidity']['max'] = last_measures['humidity']['value'] + 20
|
||||||
|
|
||||||
|
ax_hum.set_ylim(last_measures['humidity']['min'], last_measures['humidity']['max'])
|
||||||
|
|
||||||
|
t = append(t, x)
|
||||||
|
|
||||||
|
x += 0.05
|
||||||
|
|
||||||
|
temp_line.set_data(t, temperature)
|
||||||
|
hum_line.set_data(t, humidity)
|
||||||
|
|
||||||
|
if x >= xmax - 1.00:
|
||||||
|
temp_line.axes.set_xlim(x - xmax + 1.0, x + 1.0)
|
||||||
|
hum_line.axes.set_xlim(x - xmax + 1.0, x + 1.0)
|
||||||
|
|
||||||
|
return temp_line, hum_line
|
||||||
|
|
||||||
|
|
||||||
|
def environment_service(args, gatt_device):
|
||||||
|
NORDIC_THINGY_WEATHER_STATION_SERVICE = uuid.gattlib_uuid_str_to_int("EF680200-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_TEMPERATURE_CHAR = uuid.gattlib_uuid_str_to_int("EF680201-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_PRESSURE_CHAR = uuid.gattlib_uuid_str_to_int("EF680202-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_HUMIDITY_CHAR = uuid.gattlib_uuid_str_to_int("EF680203-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_AIR_QUALITY_CHAR = uuid.gattlib_uuid_str_to_int("EF680204-9B35-4933-9B10-52FFA9740042")
|
||||||
|
|
||||||
|
temperature_characteristic = gatt_device.characteristics[NORDIC_THINGY_TEMPERATURE_CHAR]
|
||||||
|
pressure_characteristic = gatt_device.characteristics[NORDIC_THINGY_PRESSURE_CHAR]
|
||||||
|
humidity_characteristic = gatt_device.characteristics[NORDIC_THINGY_HUMIDITY_CHAR]
|
||||||
|
air_quality_characteristic = gatt_device.characteristics[NORDIC_THINGY_AIR_QUALITY_CHAR]
|
||||||
|
|
||||||
|
# Initialize graph
|
||||||
|
threading.Thread(target=graph_init).start()
|
||||||
|
|
||||||
|
try:
|
||||||
|
DBusGMainLoop(set_as_default=True)
|
||||||
|
mainloop = GLib.MainLoop()
|
||||||
|
|
||||||
|
temperature_characteristic.register_notification(temperature_notification)
|
||||||
|
temperature_characteristic.notification_start()
|
||||||
|
|
||||||
|
pressure_characteristic.register_notification(pressure_notification)
|
||||||
|
pressure_characteristic.notification_start()
|
||||||
|
|
||||||
|
humidity_characteristic.register_notification(humidity_notification)
|
||||||
|
humidity_characteristic.notification_start()
|
||||||
|
|
||||||
|
mainloop.run()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
mainloop.quit()
|
||||||
|
finally:
|
||||||
|
humidity_characteristic.notification_stop()
|
||||||
|
pressure_characteristic.notification_stop()
|
||||||
|
temperature_characteristic.notification_stop()
|
||||||
|
gatt_device.disconnect()
|
|
@ -1,194 +1,32 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
import threading
|
|
||||||
|
|
||||||
from dbus.mainloop.glib import DBusGMainLoop
|
from gattlib import device
|
||||||
try:
|
|
||||||
from gi.repository import GLib, GObject
|
|
||||||
except ImportError:
|
|
||||||
import gobject as GObject
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import numpy
|
|
||||||
from matplotlib.pylab import *
|
|
||||||
from mpl_toolkits.axes_grid1 import host_subplot
|
|
||||||
import matplotlib.animation as animation
|
|
||||||
|
|
||||||
from gattlib import device, uuid
|
|
||||||
|
|
||||||
last_measures = {
|
|
||||||
'temperature': { 'value': None, 'min': None, 'max': None },
|
|
||||||
'pressure': { 'value': None, 'min': None, 'max': None },
|
|
||||||
'humidity': { 'value': None, 'min': None, 'max': None },
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def temperature_notification(value, user_data):
|
|
||||||
last_measures['temperature']['value'] = float("%d.%d" % (value[0], value[1]))
|
|
||||||
print("Temperature: %f" % last_measures['temperature']['value'])
|
|
||||||
|
|
||||||
|
|
||||||
def pressure_notification(value, user_data):
|
|
||||||
(pressure_integer, pressure_decimal) = struct.unpack("<IB", value)
|
|
||||||
last_measures['pressure']['value'] = float("%d.%d" % (pressure_integer, pressure_decimal))
|
|
||||||
print("Pressure: %f" % last_measures['pressure']['value'])
|
|
||||||
|
|
||||||
|
|
||||||
def humidity_notification(value, user_data):
|
|
||||||
last_measures['humidity']['value'] = value[0]
|
|
||||||
print("Humidity: %d%%" % last_measures['humidity']['value'])
|
|
||||||
|
|
||||||
|
|
||||||
# Data Placeholders
|
|
||||||
temperature = zeros(0)
|
|
||||||
humidity = zeros(0)
|
|
||||||
t = zeros(0)
|
|
||||||
x = 0.0
|
|
||||||
xmax = 1000.0
|
|
||||||
temp_line = None
|
|
||||||
hum_line = None
|
|
||||||
ax_temp = None
|
|
||||||
ax_hum = None
|
|
||||||
simulation = None
|
|
||||||
|
|
||||||
|
|
||||||
def graph_init():
|
|
||||||
global x
|
|
||||||
global temperature, humidity, t
|
|
||||||
global temp_line, hum_line
|
|
||||||
global ax_temp, ax_hum
|
|
||||||
global simulation
|
|
||||||
|
|
||||||
font = {'size' : 9}
|
|
||||||
matplotlib.rc('font', **font)
|
|
||||||
|
|
||||||
# Setup figure and subplots
|
|
||||||
f0 = figure(num=0, figsize=(12, 8)) # , dpi = 100)
|
|
||||||
f0.suptitle("Nordic Thingy", fontsize=12)
|
|
||||||
ax_temp = host_subplot(111)
|
|
||||||
ax_hum = ax_temp.twinx()
|
|
||||||
|
|
||||||
# Set titles of subplots
|
|
||||||
ax_temp.set_title('Temperature/Humidity vs Time')
|
|
||||||
|
|
||||||
# set y-limits
|
|
||||||
ax_temp.set_ylim(0, 45)
|
|
||||||
ax_hum.set_ylim(0, 100)
|
|
||||||
|
|
||||||
# sex x-limits
|
|
||||||
ax_temp.set_xlim(0, xmax)
|
|
||||||
ax_hum.set_xlim(0, xmax)
|
|
||||||
|
|
||||||
# Turn on grids
|
|
||||||
ax_temp.grid(True)
|
|
||||||
|
|
||||||
# set label names
|
|
||||||
ax_temp.set_xlabel("t")
|
|
||||||
ax_temp.set_ylabel("temperature")
|
|
||||||
ax_hum.set_ylabel("humidity")
|
|
||||||
|
|
||||||
temp_line, = ax_temp.plot(t, temperature, 'b-', label="temperature")
|
|
||||||
hum_line, = ax_hum.plot(t, humidity, 'g-', label="humidity")
|
|
||||||
|
|
||||||
# set lagends
|
|
||||||
ax_temp.legend([temp_line, hum_line], [temp_line.get_label(), hum_line.get_label()])
|
|
||||||
|
|
||||||
# interval: draw new frame every 'interval' ms
|
|
||||||
# Note: We expose simulation to prevent Python garbage collector to rmeove it!
|
|
||||||
simulation = animation.FuncAnimation(f0, graph_update, blit=False, interval=20)
|
|
||||||
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
|
|
||||||
def graph_update(self):
|
|
||||||
global x, xmax
|
|
||||||
global temperature, humidity, t
|
|
||||||
global temp_line, hum_line
|
|
||||||
|
|
||||||
if last_measures['temperature']['value']:
|
|
||||||
temperature = append(temperature, last_measures['temperature']['value'])
|
|
||||||
if last_measures['temperature']['min']:
|
|
||||||
last_measures['temperature']['min'] = min(last_measures['temperature']['min'], last_measures['temperature']['value'] - 5)
|
|
||||||
else:
|
|
||||||
last_measures['temperature']['min'] = last_measures['temperature']['value'] - 5
|
|
||||||
if last_measures['temperature']['max']:
|
|
||||||
last_measures['temperature']['max'] = max(last_measures['temperature']['max'], last_measures['temperature']['value'] + 5)
|
|
||||||
else:
|
|
||||||
last_measures['temperature']['max'] = last_measures['temperature']['value'] + 5
|
|
||||||
|
|
||||||
ax_temp.set_ylim(last_measures['temperature']['min'], last_measures['temperature']['max'])
|
|
||||||
|
|
||||||
if last_measures['humidity']['value']:
|
|
||||||
humidity = append(humidity, last_measures['humidity']['value'])
|
|
||||||
if last_measures['humidity']['min']:
|
|
||||||
last_measures['humidity']['min'] = min(last_measures['humidity']['min'], last_measures['humidity']['value'] - 20)
|
|
||||||
else:
|
|
||||||
last_measures['humidity']['min'] = last_measures['humidity']['value'] - 20
|
|
||||||
if last_measures['humidity']['max']:
|
|
||||||
last_measures['humidity']['max'] = max(last_measures['humidity']['max'], last_measures['humidity']['value'] + 20)
|
|
||||||
else:
|
|
||||||
last_measures['humidity']['max'] = last_measures['humidity']['value'] + 20
|
|
||||||
|
|
||||||
ax_hum.set_ylim(last_measures['humidity']['min'], last_measures['humidity']['max'])
|
|
||||||
|
|
||||||
t = append(t, x)
|
|
||||||
|
|
||||||
x += 0.05
|
|
||||||
|
|
||||||
temp_line.set_data(t, temperature)
|
|
||||||
hum_line.set_data(t, humidity)
|
|
||||||
|
|
||||||
if x >= xmax - 1.00:
|
|
||||||
temp_line.axes.set_xlim(x - xmax + 1.0, x + 1.0)
|
|
||||||
hum_line.axes.set_xlim(x - xmax + 1.0, x + 1.0)
|
|
||||||
|
|
||||||
return temp_line, hum_line
|
|
||||||
|
|
||||||
|
from environment_service import environment_service
|
||||||
|
from sound_service import sound_service
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='Gattlib example for Nordic Thingy')
|
parser = argparse.ArgumentParser(description='Gattlib example for Nordic Thingy')
|
||||||
parser.add_argument('mac', type=str, help='Mac Address of the GATT device to connect')
|
parser.add_argument('mac', type=str, help='Mac Address of the GATT device to connect')
|
||||||
|
subparsers = parser.add_subparsers(help='sub-command help')
|
||||||
|
|
||||||
|
environment_parser = subparsers.add_parser('environment', help='Environment Command')
|
||||||
|
environment_parser.set_defaults(func=environment_service)
|
||||||
|
|
||||||
|
sound_parser = subparsers.add_parser('sound', help='Sound Command')
|
||||||
|
sound_parser.add_argument('--wav', type=str, help='WAV file to play')
|
||||||
|
sound_parser.set_defaults(func=sound_service)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
NORDIC_THINGY_WEATHER_STATION_SERVICE = uuid.gattlib_uuid_str_to_int("EF680200-9B35-4933-9B10-52FFA9740042")
|
if not hasattr(args, 'func'):
|
||||||
NORDIC_THINGY_TEMPERATURE_CHAR = uuid.gattlib_uuid_str_to_int("EF680201-9B35-4933-9B10-52FFA9740042")
|
raise RuntimeError("Please specify the command to launch: 'environment', 'sound'")
|
||||||
NORDIC_THINGY_PRESSURE_CHAR = uuid.gattlib_uuid_str_to_int("EF680202-9B35-4933-9B10-52FFA9740042")
|
|
||||||
NORDIC_THINGY_HUMIDITY_CHAR = uuid.gattlib_uuid_str_to_int("EF680203-9B35-4933-9B10-52FFA9740042")
|
|
||||||
NORDIC_THINGY_AIR_QUALITY_CHAR = uuid.gattlib_uuid_str_to_int("EF680204-9B35-4933-9B10-52FFA9740042")
|
|
||||||
|
|
||||||
gatt_device = device.Device(adapter=None, addr=args.mac)
|
gatt_device = device.Device(adapter=None, addr=args.mac)
|
||||||
gatt_device.connect()
|
gatt_device.connect()
|
||||||
gatt_device.discover()
|
gatt_device.discover()
|
||||||
|
|
||||||
temperature_characteristic = gatt_device.characteristics[NORDIC_THINGY_TEMPERATURE_CHAR]
|
# Launch the sub-command specific function
|
||||||
pressure_characteristic = gatt_device.characteristics[NORDIC_THINGY_PRESSURE_CHAR]
|
args.func(args, gatt_device)
|
||||||
humidity_characteristic = gatt_device.characteristics[NORDIC_THINGY_HUMIDITY_CHAR]
|
|
||||||
air_quality_characteristic = gatt_device.characteristics[NORDIC_THINGY_AIR_QUALITY_CHAR]
|
|
||||||
|
|
||||||
# Initialize graph
|
|
||||||
threading.Thread(target=graph_init).start()
|
|
||||||
|
|
||||||
try:
|
|
||||||
DBusGMainLoop(set_as_default=True)
|
|
||||||
mainloop = GLib.MainLoop()
|
|
||||||
|
|
||||||
temperature_characteristic.register_notification(temperature_notification)
|
|
||||||
temperature_characteristic.notification_start()
|
|
||||||
|
|
||||||
pressure_characteristic.register_notification(pressure_notification)
|
|
||||||
pressure_characteristic.notification_start()
|
|
||||||
|
|
||||||
humidity_characteristic.register_notification(humidity_notification)
|
|
||||||
humidity_characteristic.notification_start()
|
|
||||||
|
|
||||||
mainloop.run()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
mainloop.quit()
|
|
||||||
finally:
|
|
||||||
humidity_characteristic.notification_stop()
|
|
||||||
pressure_characteristic.notification_stop()
|
|
||||||
temperature_characteristic.notification_stop()
|
|
||||||
gatt_device.disconnect()
|
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
import wave
|
||||||
|
|
||||||
|
from gattlib import uuid
|
||||||
|
|
||||||
|
from dbus.mainloop.glib import DBusGMainLoop
|
||||||
|
try:
|
||||||
|
from gi.repository import GLib, GObject
|
||||||
|
except ImportError:
|
||||||
|
import gobject as GObject
|
||||||
|
|
||||||
|
m_thingy_buffer_free = threading.Event()
|
||||||
|
m_mainloop = None
|
||||||
|
|
||||||
|
|
||||||
|
def speaker_status_notification(value, user_data):
|
||||||
|
global m_thingy_buffer_free
|
||||||
|
|
||||||
|
if value == b'\x01':
|
||||||
|
print("Thingy's Buffer warning")
|
||||||
|
m_thingy_buffer_free.clear()
|
||||||
|
elif value == b'\x02':
|
||||||
|
print("Thingy's Buffer ready")
|
||||||
|
m_thingy_buffer_free.set()
|
||||||
|
elif value == b'\x10':
|
||||||
|
print("Thingy's Packet disregarded")
|
||||||
|
elif value == b'\x11':
|
||||||
|
print("Thingy's Invalid command")
|
||||||
|
elif value == b'\x00':
|
||||||
|
print("Thingy's Finished")
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Invalid Speaker notification value: %s" % value)
|
||||||
|
|
||||||
|
|
||||||
|
def play_sample(config_characteristic, speaker_characteristic):
|
||||||
|
# Read the current configuration and only change the speaker configuration (not the microphone configuration)
|
||||||
|
sound_config = config_characteristic.read()
|
||||||
|
sound_config[0] = 0x03
|
||||||
|
config_characteristic.write(sound_config)
|
||||||
|
# Test speaker
|
||||||
|
speaker_characteristic.write(b'\x03')
|
||||||
|
m_mainloop.quit()
|
||||||
|
|
||||||
|
|
||||||
|
def play_wav_file(config_characteristic, speaker_characteristic, wav_filepath):
|
||||||
|
global m_thingy_buffer_free
|
||||||
|
|
||||||
|
wav_file = wave.open(wav_filepath)
|
||||||
|
|
||||||
|
# Python library only support non-compressed WAV file
|
||||||
|
if wav_file.getcomptype() != 'NONE':
|
||||||
|
raise RuntimeError("Please give a non-compressed WAV file")
|
||||||
|
if wav_file.getsampwidth() != 1:
|
||||||
|
raise RuntimeError("Nordic Thingy52 only supports 8-bit WAV file")
|
||||||
|
if wav_file.getframerate() != 8000:
|
||||||
|
raise RuntimeError("Nordic Thingy52 only supports 8kHz WAV file")
|
||||||
|
if wav_file.getnchannels() == 2:
|
||||||
|
print("Warning: Your WAV file is a stereo file")
|
||||||
|
|
||||||
|
frames = wav_file.readframes(wav_file.getnframes())
|
||||||
|
|
||||||
|
# Read the current configuration and only change the speaker configuration (not the microphone configuration)
|
||||||
|
sound_config = config_characteristic.read()
|
||||||
|
sound_config[0] = 0x02
|
||||||
|
config_characteristic.write(sound_config)
|
||||||
|
|
||||||
|
stream = speaker_characteristic.stream_open()
|
||||||
|
|
||||||
|
# We assume the buffer is free when we start
|
||||||
|
m_thingy_buffer_free.set()
|
||||||
|
|
||||||
|
# We send one frame at a time
|
||||||
|
max_frame_size = stream.mtu * 1
|
||||||
|
|
||||||
|
while len(frames) > 0:
|
||||||
|
if not m_thingy_buffer_free.is_set():
|
||||||
|
m_thingy_buffer_free.wait()
|
||||||
|
|
||||||
|
stream.write(frames[0:max_frame_size])
|
||||||
|
frames = frames[max_frame_size:]
|
||||||
|
|
||||||
|
# Arbitraty value
|
||||||
|
time.sleep(0.03)
|
||||||
|
|
||||||
|
stream.close()
|
||||||
|
print("All WAV file has been sent")
|
||||||
|
m_mainloop.quit()
|
||||||
|
|
||||||
|
|
||||||
|
def sound_service(args, gatt_device):
|
||||||
|
global m_mainloop
|
||||||
|
|
||||||
|
NORDIC_THINGY_SOUND_SERVICE = uuid.gattlib_uuid_str_to_int("EF680500-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_CONFIG_CHAR = uuid.gattlib_uuid_str_to_int("EF680501-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_SPEAKER_CHAR = uuid.gattlib_uuid_str_to_int("EF680502-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_SPEAKER_STATUS_CHAR = uuid.gattlib_uuid_str_to_int("EF680503-9B35-4933-9B10-52FFA9740042")
|
||||||
|
NORDIC_THINGY_MICROPHONE_CHAR = uuid.gattlib_uuid_str_to_int("EF680504-9B35-4933-9B10-52FFA9740042")
|
||||||
|
|
||||||
|
config_characteristic = gatt_device.characteristics[NORDIC_THINGY_CONFIG_CHAR]
|
||||||
|
speaker_characteristic = gatt_device.characteristics[NORDIC_THINGY_SPEAKER_CHAR]
|
||||||
|
speaker_status_characteristic = gatt_device.characteristics[NORDIC_THINGY_SPEAKER_STATUS_CHAR]
|
||||||
|
microphone_characteristic = gatt_device.characteristics[NORDIC_THINGY_MICROPHONE_CHAR]
|
||||||
|
|
||||||
|
try:
|
||||||
|
DBusGMainLoop(set_as_default=True)
|
||||||
|
m_mainloop = GLib.MainLoop()
|
||||||
|
|
||||||
|
speaker_status_characteristic.register_notification(speaker_status_notification)
|
||||||
|
speaker_status_characteristic.notification_start()
|
||||||
|
|
||||||
|
if args.wav:
|
||||||
|
threading.Thread(target=play_wav_file, args=(config_characteristic, speaker_characteristic, args.wav)).start()
|
||||||
|
else:
|
||||||
|
threading.Thread(target=play_sample, args=(config_characteristic, speaker_characteristic)).start()
|
||||||
|
|
||||||
|
m_mainloop.run()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
m_mainloop.quit()
|
||||||
|
finally:
|
||||||
|
speaker_status_characteristic.notification_stop()
|
||||||
|
gatt_device.disconnect()
|
Loading…
Reference in New Issue