Forum Archive

Hexiwear BLE access

robStacks

Need some help with access to BLE services & characteristics with the Hexiwear dev platformpje !?

from __future__ import print_function
import cb
import sound
import time
import struct
import console

console.set_color(0, 0, 1)
print("""
  _  _             _____ _
 | || |___ _  _ * | __  | |_ _ ___
 | -- | -_| \/  | | __ -| | | | -_|
 |_||_|___|_/\__|_ _____|_|___|___|

""")
console.set_color()


class HeartRateManager (object):
    def __init__(self):
        self.peripheral = None

    def did_discover_peripheral(self, p):
        if p.name and 'HEXIWEAR' in p.name and not self.peripheral:
            self.peripheral = p
            print('Connecting to Hexiwear...')
            cb.connect_peripheral(p)

    def did_connect_peripheral(self, p):
        print('Connected:', p.name)
        print('Discovering services...')
        p.discover_services()

    def did_discover_services(self, p, error):
        print('did_discover_services({})'.format(p.name))
        cb.get_state()
        print("Name:", p.name)
        print("UUID:", p.uuid)
        try:
            state = 'Disconnected Connecting Connected'.split()[p.state]
        except IndexError:
            state = 'Invalid state ({})'.format(p.state)
        print("STAT: ", state)
        time.sleep(0.4)
        print("AUTH:", cb.CH_PROP_AUTHENTICATED_SIGNED_WRITES)
        time.sleep(0.4)
        print("Properties:", cb.CH_PROP_EXTENDED_PROPERTIES)
        time.sleep(0.4)
        print("Indicate:", cb.CH_PROP_INDICATE)
        time.sleep(0.4)
        print("Encryption:", cb.CH_PROP_NOTIFY_ENCRYPTION_REQUIRED)
        time.sleep(0.4)
        print("{} Services:".format(len(p.services)))
        for s in p.services:
            print("-" + str(s.uuid))
        p.discover_characteristics(s)

    def did_discover_characteristics(self, s, error):
        print("Characteristics:")
        for c in s.characteristics:
            print("-" + str(c.uuid))
            # s.set_notify_value(c, True)
            s.read_characteristic_value(c)
            data = s.read_characteristic_value(c)
            print(c.value, data)

    def did_write_value(self, c, error):
        print(self.peripheral.properties)
        time.sleep(0.5)

    def did_update_value(self, c, error):
        time.sleep(0.5)

    def did_fail_to_connect_peripheral(self, p, error):
        print('Failed to connect: %s' % (error,))

    def did_disconnect_peripheral(self, p, error):
        print('Disconnected, error: %s' % (error,))
        self.peripheral = None


mngr = HeartRateManager()
cb.set_central_delegate(mngr)
print('Scanning for Hexiwear...')
cb.scan_for_peripherals()

try:
    while True: pass
except KeyboardInterrupt:
    cb.reset()

Can’t get access to all characteristics need some pointers!?

Thx in advance

JonB

@robStacks what seems to be the problem?

robStacks

https://github.com/MikroElektronika/HEXIWEAR/blob/master/documentation/HEXIWEAR%20Bluetooth%20Specifications.pdf

I just can’t get access to the other services

Thx for the help guys...

JonB

Looks like maybe you are missing an indent - you wAnt to call discover_characteristics for each service. Your code would only be the last.

Should be:

for s in p.services:
   print("-" + str(s.uuid))
   p.discover_characteristics(s)
robStacks

Great thx that’s it thx allot!

robStacks

Well almost now I am getting just the first characteristic of each service but getting closer.

Thx a bunch!

JonB

is there a service.read_characteristic_value? or is it under peripheral? also, the read command does not return a value, you must implement did_update_value.

Peripheral.read_characteristic_value(characteristic)
Retrieve the value of the given Characteristic. When the value has been read, your central delegate will receive a did_update_value callback, at which point you can access the value with the characteristics’s value attribute. Not all characteristics are guaranteed to have a readable value.

If you need synchronous access like this, perhaps, implement a semaphore system -- update_value sets a semaphore that the did_discover_characteristics blocks on ( you do maybe need to make sure did_discover_characteristics uses @in_background)

robStacks

Ok thx for your help I get the full readout now
Listing all services and characteristics
Now I want to get the raw values of all the sensors and print them.
You talked about setting up a semafore system?
I am totally new to this can you explain more in-depth please?

The code till now:
```

import cb
import time

class HexiwearManager (object):
def init(self):
self.peripheral = None

def did_discover_peripheral(self, p):
    if p.name and 'HEXIWEAR' in p.name and not self.peripheral:
        self.peripheral = p
        print('Connecting to Hexiwear...')
        cb.connect_peripheral(p)

def did_connect_peripheral(self, p):
    print('Connected:', p.name)
    print('Discovering services...')
    p.discover_services()

def did_discover_services(self, p, error):
    print('did_discover_services({})'.format(p.name))
    cb.get_state()
    print("Name:", p.name)
    print("UUID:", p.uuid)
    try:
        state = 'Disconnected Connecting Connected'.split()[p.state]
    except IndexError:
        state = 'Invalid state ({})'.format(p.state)
    print("STAT: ", state)
    time.sleep(0.4)
    print("AUTH:", cb.CH_PROP_AUTHENTICATED_SIGNED_WRITES)
    time.sleep(0.4)
    print("Properties:", cb.CH_PROP_EXTENDED_PROPERTIES)
    time.sleep(0.4)
    print("Indicate:", cb.CH_PROP_INDICATE)
    time.sleep(0.4)
    print("Encryption:", cb.CH_PROP_NOTIFY_ENCRYPTION_REQUIRED)
    time.sleep(0.4)
    print("{} Services:".format(len(p.services)))
    for s in p.services:
        print("-" + str(s.uuid))
        p.discover_characteristics(s)

def did_discover_characteristics(self, s, error):

    print("{} Characteristics:".format(len(s.characteristics)))
    for c in s.characteristics:
        print("-" + str(c.uuid))


def did_fail_to_connect_peripheral(self, p, error):
    print('Failed to connect: %s' % (error,))

def did_disconnect_peripheral(self, p, error):
    print('Disconnected, error: %s' % (error,))
    self.peripheral = None

mngr = HexiwearManager()
cb.set_central_delegate(mngr)
print('Scanning for Hexiwear...')
cb.scan_for_peripherals()

try:
while True: pass
except KeyboardInterrupt:
cb.reset() ```

JonB

something like this, for simple reading.
notice that you call read, but the actual access to c.value is in update_value -- so your code just needs to be asynchronous, responding to value updates there.

if you need synchronous access, it becomes harder, since your main code needs to wait until the value has been updated. which can be tricky because i dont think there is a guarantee that when you request a read, that a read actually happens by the device, etc.

CHPROPS={cb.CH_PROP_BROADCAST:'Broadcast',
         cb.CH_PROP_READ:'Read',
         cb.CH_PROP_WRITE_WITHOUT_RESPONSE:'WriteWithoutResponse',
         cb.CH_PROP_WRITE:'Write',
         cb.CH_PROP_NOTIFY:'Notify',
         cb.CH_PROP_INDICATE:'Indicate',
         cb.CH_PROP_AUTHENTICATED_SIGNED_WRITES:'AuthSignedWrites',
         cb.CH_PROP_EXTENDED_PROPERTIES:'ExtendedProps', 
         cb.CH_PROP_NOTIFY_ENCRYPTION_REQUIRED:'NotifyEncrypReq',
         cb.CH_PROP_INDICATE_ENCRYPTION_REQUIRED:'IndicateEncrReq'}


#...inside your manager...

   def did_discover_characteristics(self, s, error):
      # You can now read or write the characteristic's value
      props=[]
      for propbit,name in CHPROPS.items():
         if c.properties & propbit:
            props.append(name)
      print(f'-UUID:{c.uuid} PROPS:{",".join(props)}')
      if cb.CH_PROP_READ & c.properties:
         self.peripheral.read_characteristic_value(c)

   def did_update_value(self, c):
      '''called when characteristic is read'''
      print(f'-UUID:{c.uuid} + VALUE:{c.value}')
robStacks

Where do I put in the CHPROPS?
Should I put it in sitepackages and import it in the beginning of the code?
Keep getting “CHPROPS” is not defined no matter where in the code I put it in.

Thx again for the help!

JonB

just in the same file, before you declare the class.

or, i suppose, it would be cleaner to define inside __init__, as self.CHPROPS , then refer to it as such in inside did_discover_characteristics.

The purpose of that is to give a more meaningful display of characateristic properties -- but you could always just print c.properties, and figure out the bitmask yourself.