Hi,
When I use the below code to create a device with separate accessories, both will intermittently go 'No Response'. Perhaps something to do with using the same ACCESSORY_INFORMATION Service (and NAME)?
Does each Accessory need a different name set in the ACCESSORY_INFORMATION Service? It appears homekit_setup_mdns only uses the name from accessories[0]?
Do I need to specifically set .id for each Accessory, or is this handled by the homekit_accessories_init function?
void init_accessory() {
light_service_t *light = lights;
// not really needed. only used to identify a light service by name
uint8_t hk_light_idx = 1;
// create an array of homekit_service_t pointers.
// remember, this on the stack and will be discarded when the function ends (but is copied to heap in NEW_HOMEKIT_ACCESSORY)
homekit_service_t* services[5];
// get pointer to first array location
homekit_service_t** s = services;
// accessories[] is a global array of homekit_accessory_t pointers
homekit_accessory_t** a = accessories;
homekit_service_t* accessory_service = NULL;
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] );
while (light) {
// if not a remote and not hidden (homekit enable)
if (!light->is_remote && !light->is_hidden) {
// first pass through, create the accessory service to be common for all accessories (if separate accessories)
if (!accessory_service) {
esp_app_desc_t app_desc;
const esp_partition_t *running = esp_ota_get_running_partition();
esp_ota_get_partition_description(running, &app_desc);
// NEW_HOMEKIT_SERVICE uses calloc to save the data on the heap, then returns the address which is saved in a local pointer
// The NEW_HOMEKIT_ACCESSORY copies this pointer to a memory location on the heap
accessory_service = NEW_HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
NEW_HOMEKIT_CHARACTERISTIC(NAME, name_value),
NEW_HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Riksman"),
NEW_HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, name_value),
NEW_HOMEKIT_CHARACTERISTIC(MODEL, "ESP-C3-12F"),
NEW_HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, app_desc.version),
NEW_HOMEKIT_CHARACTERISTIC(IDENTIFY, status_led_identify),
NULL
});
// only occurs on the first accessory created. and if all lights are part of the one accessory (separate=false),
// then we need to add the above to the list of services just once
*(s++) = accessory_service;
}
int light_name_len = snprintf(NULL, 0, "Light %d", hk_light_idx);
char *light_name_value = malloc(light_name_len + 1);
snprintf(light_name_value, light_name_len + 1, "Light %d", hk_light_idx);
homekit_characteristic_t* characteristics[light->is_dimmer ? 3 : 2]; // NAME, ON and if a dimmer BRIGHTNESS
homekit_characteristic_t** c = characteristics;
*(c++) = NEW_HOMEKIT_CHARACTERISTIC(NAME, light_name_value);
// *(c++) = NEW_HOMEKIT_CHARACTERISTIC(NAME, "Light");
*(c++) = NEW_HOMEKIT_CHARACTERISTIC(
ON, false,
// .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(
// lightbulb_on_callback, .context=(void*)light
// ),
.setter_ex=light_on_set,
.getter_ex=light_on_get,
.context=(void*)light
);
if (light->is_dimmer) {
*(c++) = NEW_HOMEKIT_CHARACTERISTIC(
BRIGHTNESS, 100,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(
lightbulb_brightness_callback, .context=(void*)light
),
);
}
*(c++) = NULL;
// if dimmer, use LIGHTBULB Service to use BRIGHTNESS Characteristic
// if not a dimmer, use SWITCH Service, so we can choose the icon to be a Fan or Light.
if (light->is_dimmer) {
*s = NEW_HOMEKIT_SERVICE(LIGHTBULB, .characteristics=characteristics);
}
else {
*s = NEW_HOMEKIT_SERVICE(SWITCH, .characteristics=characteristics);
}
// save the address returned by calloc into light->service as well
light->service = *s;
s++;
// if each light/service is to be a separate accessory
if (separate_accessories) {
// end this services array
*(s++) = NULL;
// create the accessory (copies the local array of homekit_service_t pointers to the heap)
// and save the calloc address to the global accessories[] array
*(a++) = NEW_HOMEKIT_ACCESSORY(.category=homekit_accessory_category_lightbulb, .services=services);
// reuse the services array and start again with a new accessory
s = services;
// each new accessory needs the accessory_service
*(s++) = accessory_service;
}
// only used for naming lights. not really required
hk_light_idx++;
}
// linked list, next light
light = light->next;
}
// out of all the lights (light_service_t linked list), were there any that were homekit enabled?
// if accessory_service exists, then the answer is 'yes'
if (accessory_service) {
// if it isn't separate accessories, then end the accessory definition
if (!separate_accessories) {
*(s++) = NULL;
*(a++) = NEW_HOMEKIT_ACCESSORY(.category=homekit_accessory_category_lightbulb, .services=services);
}
// must end the array of pointers with a NULL
*(a++) = NULL;
// start the homekit server
homekit_server_init(&config);
}
// if homekit doesn't initialise, we still need to start the mdns service
else {
mdns_init();
mdns_hostname_set(name_value);
mdns_instance_name_set(name_value);
}
}
Hi,
When I use the below code to create a device with separate accessories, both will intermittently go 'No Response'. Perhaps something to do with using the same
ACCESSORY_INFORMATIONService (andNAME)?Does each Accessory need a different name set in the
ACCESSORY_INFORMATIONService? It appearshomekit_setup_mdnsonly uses the name fromaccessories[0]?Do I need to specifically set
.idfor each Accessory, or is this handled by thehomekit_accessories_initfunction?