Skip to content

Peripheral doesn't notify central #180

Open
@weeteniz

Description

@weeteniz

Hi

I'm trying to develop my own window covering BLE peripheral/accessory for HomeKit using Homebridge.

So far I have:

Set up Homebridge on Raspberry Pi 2 with a bluetooth dongle. Homebridge loads fine and finds the BLEPeripheral (in this case RedBear Blend Micro with Nordic nRF8001)
Here's the config.json

{
	  "bridge": {
	    "name": "Raspberry Pi 2”,
	    "username": “00:13:EF:80:00:12”,
	    "port": 51826,
	    "pin": "031-45-154"
	  },
	  "description": "Raspberry Pi 2 Homebridge-Bluetooth",
	

	  "platforms": [
	    {
	      "platform": "Bluetooth",
	      "accessories": [
	        {
	          "name": “Smart Shades“,
	          "name_note": "Name of the accessory as shown in the Home app on iOS.",

	          "address": “D0:5F:2E:E2:11:22”,
	          "address_note": "Bluetooth address of the accessory. Non-matching devices are ignored.",
	
	          "services": [
	            {
	              "name": “Smart Blinds”,
	              "name_note": "Name of the service as shown in the Home app on iOS.",
	
	              "type": “WindowCovering”,
	              "type_note1": "Type of the service - i.e. Lightbulb, Switch, Lock, HumiditySensor, ...",
	              "type_note2": "Must match this list - https://github.com/KhaosT/HAP-NodeJS/blob/master/lib/gen/HomeKitTypes.js",
	              "type_note3": "Service.Lightbulb has a mandatory On characteristic and Brightness, Hue and Saturation are optional.",
	
	              "UUID": "A7B10010-EEEE-5377-FF6C-D104768A1214",
	              "UUID_note": "Bluetooth UUID of the service. Capitalization and dashes doesn't matter.",
	
	              "characteristics": [
	                {
	                  "type": “CurrentPosition”,
	                  "type_note1": "Type of the characteristic - i.e. On, Brightness, CurrentHumidity, CurrentTemperature, ...",
	                  "type_note2": "Must match this list - https://github.com/KhaosT/HAP-NodeJS/blob/master/lib/gen/HomeKitTypes.js",
	                  "type_note3": "Characteristic.On is a BOOL value and expects READ, WRITE and NOTIFY permissions.",

	                  "UUID": "A7B10011-EEEE-5377-FF6C-D104768A1214",
	                  "UUID_note": "Bluetooth UUID of the characteristic. Capitalization and dashes doesn't matter."
	                },
	

	                {
	                  "type": ”TargetPosition”,
	                  "type_note1": "Type of the characteristic - i.e. On, Brightness, CurrentHumidity, CurrentTemperature, ...",
	                  "type_note2": "Must match this list - https://github.com/KhaosT/HAP-NodeJS/blob/master/lib/gen/HomeKitTypes.js",
	                  "type_note3": "Characteristic.Brightness is an INT value and expects READ, WRITE and NOTIFY permissions.",

	                  "UUID": "A7B10012-EEEE-5377-FF6C-D104768A1214",
	                  "UUID_note": "Bluetooth UUID of the characteristic. Capitalization and dashes doesn't matter."
	                }
	              ],
	              "characteristics_note1": "List of Bluetooth characteristics that will be exposed to HomeKit.",
	              "characteristics_note2": "Characteristics with non-matching UUIDs are ignored."
	            }

	          ],
	          "services_note1": "List of Bluetooth services that will be exposed to HomeKit.",
	          "services_note2": "Services with non-matching UUIDs are ignored."
	        }
	      ]
	    }
	  ]
	}

This is what happens when I launch Homebridge and start interacting with my iPhone.

screen shot 2017-09-05 at 22 55 43

I developed the code with two characteristics TargetPosition and CurrentPosition.

#include <SPI.h>
#include <BLEPeripheral.h>


const int pinLED = 13;

BLEPeripheral ble = BLEPeripheral(6,7,4);
BLEService informationService("180A");
BLECharacteristic modelCharacteristic("2A24", BLERead, "101");
BLECharacteristic manufacturerCharacteristic("2A29", BLERead, "Arduino");
BLECharacteristic serialNumberCharacteristic("2A25", BLERead, "2.71828");

BLEService windowCoveringService("A7B10010-EEEE-5377-FF6C-D104768A1214");
BLEUnsignedCharCharacteristic currentPositionCharacteristic("A7B10011-EEEE-5377-FF6C-D104768A1214", BLERead | BLENotify);
BLEUnsignedCharCharacteristic targetPositionCharacteristic("A7B10012-EEEE-5377-FF6C-D104768A1214", BLEWrite | BLERead | BLENotify);
//BLEUnsignedIntCharacteristic positionStateCharacteristic("A7B10013-EEEE-5377-FF6C-D104768A1214", BLERead | BLENotify);

void setup() {
  
  Serial.begin(115200);
  pinMode(pinLED, OUTPUT);
  digitalWrite(pinLED, true);

  ble.setLocalName("Smart Blinds");
  ble.setAdvertisedServiceUuid(windowCoveringService.uuid());
  ble.addAttribute(informationService);
  ble.addAttribute(modelCharacteristic);
  ble.addAttribute(manufacturerCharacteristic);
  ble.addAttribute(serialNumberCharacteristic);

  ble.addAttribute(windowCoveringService);
  ble.addAttribute(currentPositionCharacteristic);
  ble.addAttribute(targetPositionCharacteristic);
  //ble.addAttribute(positionStateCharacteristic);
  
  currentPositionCharacteristic.setValue(100);
  //positionStateCharacteristic.setValueLE(positionState);

  ble.setEventHandler(BLEConnected, centralConnect);
  ble.setEventHandler(BLEDisconnected, centralDisconnect);
  targetPositionCharacteristic.setEventHandler(BLEWritten, characteristicWrite);
  currentPositionCharacteristic.setEventHandler(BLESubscribed, characteristicSubscribe);

  delay(5000);

  ble.begin();
  Serial.println("Bluetooth on");
}

void loop() {
  ble.poll();
}


void centralConnect(BLECentral& central) {
  Serial.print("Central connected | ");
  Serial.println(central.address());
}

void centralDisconnect(BLECentral& central) {
  Serial.print("Central disconnected | ");
  Serial.println(central.address());
}

void characteristicWrite(BLECentral& central, BLECharacteristic& characteristic) {
  Serial.print("Characteristic written | ");
  Serial.println(characteristic.uuid());
  unsigned char targetPosition = (unsigned char) targetPositionCharacteristic.value();
  Serial.print("Target position set: ");
  Serial.println(targetPosition);
  setBlinds(targetPosition);

}

void characteristicSubscribe(BLECentral& central, BLECharacteristic& characteristic) {

	Serial.println("Characteristic event, subscribed");
	
	//Central subscribes just fine

}

void setBlinds(unsigned char targetPosition) {
	
  //This is where the code to drive the motor will go

  currentPositionCharacteristic.setValue(0);
  
  //When the current position value is set, no notification is sent to the central
  
  Serial.print("Current position: ");
  Serial.println(currentPositionCharacteristic.value());
  digitalWrite(pinLED, false);
  
}

When I attempt to open/close the blinds using iOS, the value is written from the central (Homebridge) to the peripheral (RedBear Blend Micro) TargetPosition characteristic as per the first screenshot. Interestingly, TargetPosition characteristic also sends the notification back to the central.

My issue is that whatever I tried, the CurrentPosition characteristic just refuses to send the notification back to the central when its value changes to let the central know that the operation has finished. The central is subscribed to the characteristic because serial prints out some text when the event handler is triggered at the point when the central subscribes.

As the central doesn't get an updated value for the CurrentPosition characteristic, presumably HomeKit has no idea where the blinds are so it simply displays a spinner next to the icon which just doesn't stop spinning (infinite loop).

smart blinds

Where am I going wrong?

Any help at all would be appreciated!

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions