maximkulkin / esp-homekit

Apple HomeKit accessory server library for ESP-OPEN-RTOS
MIT License
1.12k stars 170 forks source link

IOS 13.0 issues with some "multi-accessories" #107

Closed beckmx closed 5 years ago

beckmx commented 5 years ago

Hello, I just got an iphone 11 pro, previously i was using an iphone 6s with ios 12, I realized that with these new iphone some accesories are not working correctly, specifically the ones that seem not to work:

The section of code defining accesories is this:

homekit_accessory_t *accessories[] = {
    HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_lightbulb, .services=(homekit_service_t*[]){
        HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Light with temperature"),
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"),
            HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "xxxxx"),
            HOMEKIT_CHARACTERISTIC(MODEL, "my light"),
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
            HOMEKIT_CHARACTERISTIC(IDENTIFY, led_identify),
            NULL
        }),
        HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Light"),
            HOMEKIT_CHARACTERISTIC(
                ON, false,
                .getter=led_on_get,
                .setter=led_on_set
            ),
            NULL
        }),
        HOMEKIT_SERVICE(TEMPERATURE_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"),
            &temperature,
            HOMEKIT_CHARACTERISTIC(CURRENT_TEMPERATURE, 18, .getter=temp_get),
            NULL
        }),
        NULL
    }),
    NULL
};

I still don't know if the problem is that the "multi accessory" was indeed prohibited since the beggining and the home understood it anyway and now on ios13 it won't tolerate them or what, those accessories not working on ios13 do work on previous version :/

maximkulkin commented 5 years ago

Try removing ".primary=true" (as you should have done from the beginning) from one of your services, so that only one primary service is there.

PS I should say all my accessories I have at home work OK with iOS13.

beckmx commented 5 years ago

So I removed the "primary=true" but that didn't work, I did an erase of the chip just in case and removed it from "Home app", what did work however was to fully comment out the sensor definition, that's strange... in your devices you use devices + sensors in the same accessory definition?

maximkulkin commented 5 years ago

in your devices you use devices + sensors in the same accessory definition?

No, I do not.

Can you try removing LIGHTBULB service and confirm that TEMPERATURE_SENSOR alone works too.

maximkulkin commented 5 years ago

Ok, I've checked support for mixed accessories and it works fine. I've checked your accessory definition and found out that you apparently have two "temperature" characteristics defined in TEMPERATURE_SENSOR service which is obviously an error. Since you have not provided definition for temperature variable, I assume it's the same CURRENT_TEMPERATURE characteristic as the one immediately following it. I've removed one and it paired perfectly and shows temperature sensor:

IMG_0418

beckmx commented 5 years ago

Let me try tonight, but yes, you are right, I did use 2 :s again my bad... always learning from u

peros550 commented 5 years ago

I have a similar issue with a multi-accessory (A/C, Light, Temperature, Humidity, Motion sensor). Main issue for me after ios 13 is that Temperature and Humidity are now grouped under the same icon in home app and you need to press it in order to reveal the values.

Here is the definition:

homekit_accessory_t *accessories[] = {
    HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_thermostat, .services=(homekit_service_t*[]) {
        HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
            &name,
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "YP"),
            HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0012345"),
            HOMEKIT_CHARACTERISTIC(MODEL, "MultipleSensors"),
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
            HOMEKIT_CHARACTERISTIC(IDENTIFY, temperature_sensor_identify),
            NULL
        }),
        HOMEKIT_SERVICE(TEMPERATURE_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"),
            &temperature,
            NULL
        }),
        HOMEKIT_SERVICE(HUMIDITY_SENSOR, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "Humidity Sensor"),
            &humidity,
            NULL
        }),
        NULL
    }),
HOMEKIT_ACCESSORY(.id=2, .category=homekit_accessory_category_switch, .services=(homekit_service_t*[]){
        HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Motion Sensor"),
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "YP"),
            HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0012346"),
            HOMEKIT_CHARACTERISTIC(MODEL, "MotionSensor"),
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
            HOMEKIT_CHARACTERISTIC(IDENTIFY, identify),
            NULL
        }),
        HOMEKIT_SERVICE(MOTION_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Motion Sensor"),
            &motion_detected,
            NULL
        }),
        NULL
    }),
    HOMEKIT_ACCESSORY(.id=3, .category=homekit_accessory_category_sensor, .services=(homekit_service_t*[]){
        HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Light Sensor"),
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "YP"),
            HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0012347"),
            HOMEKIT_CHARACTERISTIC(MODEL, "LightSensor"),
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
            HOMEKIT_CHARACTERISTIC(IDENTIFY, light_sensor_identify),
            NULL
        }),
        HOMEKIT_SERVICE(LIGHT_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Light Sensor"),
            &currentAmbientLightLevel,
            NULL
        }),
        NULL
    }),
     HOMEKIT_ACCESSORY(.id=4, .category=homekit_accessory_category_air_conditioner , .services=(homekit_service_t*[]) {
        HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "AIR CONDITIONER"),
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"),
            HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "001"),
            HOMEKIT_CHARACTERISTIC(MODEL, "MyThermostat"),
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
            HOMEKIT_CHARACTERISTIC(IDENTIFY, identify),
            NULL
        }),
        HOMEKIT_SERVICE(HEATER_COOLER, .primary=true, .characteristics=(homekit_characteristic_t*[]) {
            HOMEKIT_CHARACTERISTIC(NAME, "AirConditioner"),
            &active,
            &current_temperature,
            //&target_temperature,
            &current_heater_cooler_state,
            &target_heater_cooler_state,
           &cooling_threshold,
            &heating_threshold,
//            &units,
//            &rotation_speed,
            NULL
        }),
        NULL
    }),
    NULL
};

I tried to remove ".primary=true" in a few of the above services , then erased flash and re-flash but then the Accessory would never pair with Home app.

maximkulkin commented 5 years ago

Well, I think that sensors and not meant to be looked on too often anyways (I feel is that sensors are meant to be part of automations), but looking at your accessories definition, why not split your temperature and humidity sensors into two different accessories. You're already doing multiple accessories, should not be a big of a deal.

peros550 commented 5 years ago

Believe it or not , this was my thinking after I posted the above message. Separating the two sensors. Do you think that move would consume more memory though ? I’m already experiencing some strange issues during pairing ... i also want to try dynamic creation of accessories in case that would help making pairing easier.

maximkulkin commented 5 years ago

It certainly will take more memory, but not dramatically: I estimated each characteristic taking ~100 bytes, each service - ~26 bytes, accessory - ~20 bytes. Given new accessory should have an ACCESSORY_INFO service, which normally has 6 characteristics, that would give you ~650 more bytes total. In terms of runtime it should all be the same.

HomeACcessoryKid commented 5 years ago

@peros550,

I have a 7 accessory device but reuse the INFO part.

Please realize that this is one device and using different serial numbers is not relevant. Also, using INFO names is not too much relevant, since you can override with SERVICE names

Please see below example of something that works and has no issue… it REUSES a lot of items that are read-only

Hope this helps, HacK

#define timerNdefine(N,ID) \
    HOMEKIT_ACCESSORY( \
        .id=ID, \
        .category=homekit_accessory_category_sensor, \
        .services=(homekit_service_t*[]){ \
            HOMEKIT_SERVICE(ACCESSORY_INFORMATION, \
                .characteristics=(homekit_characteristic_t*[]){ \
                    HOMEKIT_CHARACTERISTIC(NAME, "NX-8-Sensor" #N), \
                    &manufacturer, \
                    &serial, \
                    &model, \
                    &revision, \
                    HOMEKIT_CHARACTERISTIC(IDENTIFY, identify), \
                    NULL \
                }), \
            HOMEKIT_SERVICE(MOTION_SENSOR, .primary=true, \
                .characteristics=(homekit_characteristic_t*[]){ \
                    HOMEKIT_CHARACTERISTIC(NAME, "Sensor" #N), \
                    &motion ## N, \
                    &retention ## N, \
                    NULL \
                }), \
            NULL \
        }),

homekit_accessory_t *accessories[] = {
    HOMEKIT_ACCESSORY(
        .id=1,
        .category=homekit_accessory_category_security_system,
        .services=(homekit_service_t*[]){
            HOMEKIT_SERVICE(ACCESSORY_INFORMATION,
                .characteristics=(homekit_characteristic_t*[]){
                    HOMEKIT_CHARACTERISTIC(NAME, "NX-8-alarm"),
                    &manufacturer,
                    &serial,
                    &model,
                    &revision,
                    HOMEKIT_CHARACTERISTIC(IDENTIFY, identify),
                    NULL
                }),
            HOMEKIT_SERVICE(SECURITY_SYSTEM, .primary=true,
                .characteristics=(homekit_characteristic_t*[]){
                    HOMEKIT_CHARACTERISTIC(NAME, "Alarm"),
                    &target,
                    &current,
                    &alarmtype,
                    &pin1,
                    &pin2,
                    &pin3,
                    &pin4,
                    &ota_trigger,
                    NULL
                }),
            NULL
        }),
    timerNdefine(1,2)
    timerNdefine(2,3)
    timerNdefine(3,4)
    timerNdefine(4,5)
    timerNdefine(5,6)
    timerNdefine(6,7)
    NULL
};

PS. this is a repetition of the previous comment to see if markdown works or not.
it does if you create the comment on github, but not by mail. The previous (mail) comment has now been deleted.

peros550 commented 5 years ago

many thanks @HomeACcessoryKid ! In regards to OP request, it looks Apple gave the solution in 13.2 (https://www.reddit.com/r/HomeKit/comments/dceaqd/it_worked_apple_finally_listened_to_us_and/)