Search code examples
pythonraspberry-pibluetoothbluetooth-lowenergy

Send information to an iOS app from a Raspberry Pi Zero W via Bluetooth


I am trying to send data to my iPhone from my Raspberry Pi. I set up bluetooth on the Pi and I am able to connect to it on the iPhone. In a bluetooth inspector app that I downloaded, I am clearly able to see the UUID of the service that the Pi is advertising, but it says "Service was advertised but not yet discovered"

Here is my code

from pybleno import *
import array
import sys
from builtins import str
from builtins import range
import threading
import time
import random

class EchoCharacteristic(Characteristic):

  def __init__(self):
    Characteristic.__init__(
      self, {
        'uuid': 'a64e8b82-4b3c-444a-b379-0a066c910740',
        'properties': ['read', 'write', 'notify'],
        'value': None
      })

    self._value = array.array('B', [0] * 0)
    self._updateValueCallback = None

  def onReadRequest(self, offset, callback):
    print('EchoCharacteristic - onReadRequest: value = ' + str(self._value))
    callback(Characteristic.RESULT_SUCCESS, self._value[offset:])

  def onWriteRequest(self, data, offset, withoutResponse, callback):
    self._value = data
    print('EchoCharacteristic - onWriteRequest: value = ' + str(self._value))

    if self._updateValueCallback:
      print('EchoCharacteristic - onWriteRequest:     notifying')
      self._updateValueCallback(self._value)
    callback(Characteristic.RESULT_SUCCESS)

  def onSubscribe(self, maxValueSize, updateValueCallback):
    print('EchoCharacteristic - onSubscribe')
    self._updateValueCallback = updateValueCallback

  def onUnsubscribe(self):
    print('EchoCharacteristic - onUnsubscribe')
    self._updateValueCallback = None
  def update(self, newValue):
    self._value = array.array('B', newValue)
    if self._updateValueCallback:
      self._updateValueCallback(self._value)

def getData():
  return [random.randint(0, 100)]

def main():
  bleno = Bleno()
  echoCharacteristic = EchoCharacteristic()
  def updateCharacteristic():     # background thread function
    while True:
      newValue = getData()
      echoCharacteristic.update(newValue)
      time.sleep(1)
  thread = threading.Thread(target=updateCharacteristic)
  thread.start()
  
  def onStateChange(state):
    print('on -> stateChange: ' + state)
    if state == 'poweredOn':
      bleno.startAdvertising('Echo', ['a64e8b82-4b3c-444a-b379-0a066c910741'])
    elif state == 'poweredOff':
      bleno.stopAdvertising()

  bleno.on('stateChange', onStateChange)

  def onAdvertisingStart(error):
    print('on -> advertisingStart: ' +
          ('error ' + str(error) if error else 'success'))
    if not error:
      bleno.setServices([
        BlenoPrimaryService({
          'uuid': 'a64e8b82-4b3c-444a-b379-0a066c910741',
          'characteristics': [echoCharacteristic]
        })
      ])

  bleno.on('advertisingStart', onAdvertisingStart)

  def onDisconnect(clientAddress):
    bleno.stopAdvertising()

  bleno.on('disconnect', onDisconnect)

  bleno.start()

  print('Hit <ENTER> to disconnect')
  input()
  bleno.stopAdvertising()
  bleno.disconnect()


if __name__ == "__main__":
  main()

It should just be sending a random number that updates once per second. The UUIDs are random. Any advise is appropriated.


Solution

  • This probably isn’t the solution that anyone wants, but I solved this problem by starting over with NodeJS instead of python, and it worked. I pretty much made an exact port of the code and that fixed it. I had to use node 8.9.0 and install python 2.7 (for one of the dependencies) so Bleno is definitely a bit out dated, but it solved the issue. If you’re still trying to run it with python, perhaps try installing python 2?