maximkulkin / esp-homekit

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

Dynamic Television Input Source Creation #148

Closed mriksman closed 4 years ago

mriksman commented 4 years ago

Hey,

I've had a little success with using the dynamic creation of a Television accessory. I set the number of Input Services (which are named 'Animations' in the code below). This works OK. But I need to set the .linked parameter - my code below hasn't worked.

void init_accessory() {
    uint8_t macaddr[6];
    esp_read_mac(macaddr, ESP_MAC_WIFI_STA);
    int name_len = snprintf( NULL, 0, "esp_%02x%02x%02x", macaddr[3], macaddr[4], macaddr[5] );
    char *name_value = malloc(name_len + 1);
    snprintf( name_value, name_len + 1, "esp_%02x%02x%02x", macaddr[3], macaddr[4], macaddr[5] ); 

    // ACCESSORY_INFORMATION, TELEVISION, the ANIMATIONS, and NULL
    homekit_service_t* services[3 + NUM_ANIMATIONS]; 
    homekit_service_t** s = services;

    *(s++) = NEW_HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
        NEW_HOMEKIT_CHARACTERISTIC(NAME, name_value),
        NEW_HOMEKIT_CHARACTERISTIC(MANUFACTURER, "MikeKit"),
        NEW_HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "037A3BBBF29D"),
        NEW_HOMEKIT_CHARACTERISTIC(MODEL, "AnimLights"),
        NEW_HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
        NEW_HOMEKIT_CHARACTERISTIC(IDENTIFY, status_led_identify),
        NULL
    });

    homekit_service_t* tv_anim_services[NUM_ANIMATIONS];
    homekit_service_t** s_tv = tv_anim_services;

    for (int i=0; i < NUM_ANIMATIONS; i++) {
        int anim_name_len = snprintf(NULL, 0, "Anim %d", i + 1);
        char *anim_name_val = malloc(anim_name_len + 1);
        snprintf(anim_name_val, anim_name_len + 1, "Anim %d", i + 1);

        int conf_name_len = snprintf(NULL, 0, "Animation %d", i + 1);
        char *conf_name_val = malloc(conf_name_len + 1);
        snprintf(conf_name_val, conf_name_len + 1, "Animation %d", i + 1);

        *(s_tv++) = NEW_HOMEKIT_SERVICE(INPUT_SOURCE, .characteristics=(homekit_characteristic_t*[]){
            NEW_HOMEKIT_CHARACTERISTIC(NAME, anim_name_val),
            NEW_HOMEKIT_CHARACTERISTIC(IDENTIFIER, i + 1),
            NEW_HOMEKIT_CHARACTERISTIC(CONFIGURED_NAME, conf_name_val),
            NEW_HOMEKIT_CHARACTERISTIC(INPUT_SOURCE_TYPE, HOMEKIT_INPUT_SOURCE_TYPE_HDMI),
            NEW_HOMEKIT_CHARACTERISTIC(IS_CONFIGURED, true),
            NEW_HOMEKIT_CHARACTERISTIC(CURRENT_VISIBILITY_STATE, HOMEKIT_CURRENT_VISIBILITY_STATE_SHOWN),
            NULL
        });
    }

    *(s++) = NEW_HOMEKIT_SERVICE(TELEVISION, .characteristics=(homekit_characteristic_t*[]) {
        NEW_HOMEKIT_CHARACTERISTIC(ACTIVE, false),
        NEW_HOMEKIT_CHARACTERISTIC(ACTIVE_IDENTIFIER, 1),
        NEW_HOMEKIT_CHARACTERISTIC(CONFIGURED_NAME, "TelevisionName"),
        NEW_HOMEKIT_CHARACTERISTIC(SLEEP_DISCOVERY_MODE, HOMEKIT_SLEEP_DISCOVERY_MODE_ALWAYS_DISCOVERABLE),
        NULL
    }, .linked=(homekit_service_t*[]) {
        tv_anim_services,
        NULL
    });

    for (int i=0; i < NUM_ANIMATIONS; i++) {
        *(s++) = tv_anim_services[i];
    }
    *(s++) = NULL;

    accessories[0] = NEW_HOMEKIT_ACCESSORY(.category=homekit_accessory_category_lightbulb, .services=services);
    accessories[1] = NULL;
}

How would I code the .linked part?

mriksman commented 4 years ago

Adding NULL to the end of s_tv, and then changing the .linked to

    }, .linked = tv_anim_services 

Appears to have worked. But I am worried that they might not be pointing to the same address location?

@maximkulkin, could you have a quick look and let me know if this is the correct way?

Thanks.

mriksman commented 4 years ago

Code is working fantastic. https://github.com/mriksman/esp32_homekit_animations