espressif / esp-homekit-sdk

541 stars 98 forks source link

Help me understand how homekit works (bridge + thermostat example) #108

Closed MirekVer closed 10 months ago

MirekVer commented 10 months ago

Hello everyone, by studying the examples I was able to pairing with a bridge and add 10 thermostats. I mainly have 3 problems/doubts that I can't solve:

1) I managed to implement the callback that triggers when the thermostat's current temperature, mode (inactive, hot, etc...), target temperature, etc... is changed. However, this callback does not trigger if I change the name to the thermostat from the home app. Surely I am doing something wrong, maybe I am considering the wrong characteristic strcmp(hap_char_get_type_uuid(write->hc), HAP_CHAR_UUID_NAME) or something like that.

2) How can I change the name of a thermostat from code? To read the current name of a thermostat, given the aid (thermo_aid):

hap_acc_t *ha = hap_acc_get_by_aid(thermo_aid);
hap_serv_t *hs = hap_acc_get_serv_by_uuid(ha, HAP_SERV_UUID_ACCESSORY_INFORMATION);
hap_char_t *hc = hap_serv_get_char_by_uuid(hs, HAP_CHAR_UID_NAME);
hap_val_t *val_read = (hap_val_t *)hap_char_get_val(hc);
ESP_LOGI(TAG, "Actual thermo name: %s", val_read->s);

I get the thermostat name correctly, so I modify it as follows:

hap_val_t val_write;
val_write.s = (char *)malloc(14);
memcpy(val_write.s, "new_name_test", 13);
ESP_LOGI(TAG, "New thermo name: %s", (val_write.s));
int ret = hap_char_update_val(hc, &val_write);
free(val_write.s);

(I also tried the same implementation by declaring val_write as a pointer). If I run the code again to read the thermostat name, it returns the new changed name but on the home app I still see the old name and it is not updated. What am I doing wrong?

3)Suppose everything works properly with 1 bridge and 10 thermostats. I need to add two new thermostats (so from 10 thermostats -> 12 thermostats). Can I do this while the hap server is running or should I stop and restart everything? If I have to stop with hap_stop, do I have to redo the whole procedure after that command: hap init, bridge creation, 12 thermostats creation, etc.? If there are examples to do this I would be happy to study them but I can't find anything.

I hope someone can help me.

shahpiyushv commented 10 months ago

@MirekVer , the name characteristic in the Accessory Information Service is a read-only characteristic and is used only for the default name.

Screenshot 2023-08-11 at 4 50 25 PM

iOS does not send any updated values to the accessory but instead, maintains it only in its own database.

The HomeKit specs explicitly say that The values of "Manufacturer", "Model", "Name", "Serial Number" "Product Data" must be persistent through the lifetime of the accessory., So you should not change the value as you have tried in the Q.2.

Any accessory can be added/removed at runtime using hap_add_bridged_accessory() and hap_remove_bridged_accessory(). You need not stop the hap framework for that.

MirekVer commented 10 months ago

@MirekVer , the name characteristic in the Accessory Information Service is a read-only characteristic and is used only for the default name. Screenshot 2023-08-11 at 4 50 25 PM iOS does not send any updated values to the accessory but instead, maintains it only in its own database.

The HomeKit specs explicitly say that The values of "Manufacturer", "Model", "Name", "Serial Number" "Product Data" must be persistent through the lifetime of the accessory., So you should not change the value as you have tried in the Q.2.

Any accessory can be added/removed at runtime using hap_add_bridged_accessory() and hap_remove_bridged_accessory(). You need not stop the hap framework for that.

Ok, thank you for the answer!

MirekVer commented 10 months ago

Hello everyone, I have another question: I'm in the same situation as the example I wrote earlier (a bridge and 10 thermostats), and I'm modifying the temperature or operating mode of the thermostat. Following the examples, in the callback, I have an implementation like this: if (!strcmp(hap_char_get_type_uuid(write->hc), HAP_CHAR_UUID_TARGET_TEMPERATURE)) { ESP_LOGI(TAG_HOMEKIT_ACCESSORY, "Received Write. Thermostat targ_temp: %.1f", write->val.f); hap_char_update_val(write->hc, &(write->val)); *(write->status) = HAP_STATUS_SUCCESS; } and other "else if" that checks on the characteristics to determine which change has occurred. How can I identify the thermostat that received the modification among the 10 I have? In the example it use "hap_req_get_ctrl_id(write_priv)" but if i'm not wrong, it prints the bridge (is it true?) that it's always the same.

MirekVer commented 10 months ago

Can no one help me? :(

shahpiyushv commented 10 months ago

As you can see here in the bridge example, we have assigned the accessory name as the private data. You can assign any data you want here and that data would be available as the serv_priv in the write callback. You can see that we have printed the same accessory name here.

MirekVer commented 10 months ago

As you can see here in the bridge example, we have assigned the accessory name as the private data. You can assign any data you want here and that data would be available as the serv_priv in the write callback. You can see that we have printed the same accessory name here.

Okay, it was much simpler than I thought. Thx!

shahpiyushv commented 10 months ago

Closing this issue as it has been answered.