esp-homekit-demo
esp-homekit-demo copied to clipboard
getter + setter with variable
Hi
first of all thanks for that git and the option to programm an esp with homekit support and I appriciate any help as I am stuck here right now.
I try to have multiple relays controller by PCF8574 via I2C from ESP-01
- additional an voltage input with as well PCF8574 an different I2C adress. I got quite far and everything is working with the led getter and led setter example for one relay.
Now I want to have that for multiple relays which would need to have a variable passed to the getter and setter function. => Copying the setter and getter code multiple times seems with different function names is not really "professional" and very frustation if I need to update something ;-)
How do I have to modify the code that it can pass an variable to getter and setter?
Initial Setter/Getter Example Code:
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, "Sample LED"),
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "037A2BABF19D"),
HOMEKIT_CHARACTERISTIC(MODEL, "MyLED"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, led_identify),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Sample LED"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter=led_on_get,
.setter=led_on_set
),
NULL
}),
NULL
}),
NULL
};
I tried to merge the dynamic and led sample code but the get seems not to work as homekit showes only the latest set status and does not get the update:
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, "Sample LED"),
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "037A2BABF19D"),
HOMEKIT_CHARACTERISTIC(MODEL, "MyLED"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, led_identify),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Status LED"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter=led_on_get,
.setter=led_on_set
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 1"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[0]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[0]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 2"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[1]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[1]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 3"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[2]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[2]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 4"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[3]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[3]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 5"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[4]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[4]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 6"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[5]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[5]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 7"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[6]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[6]),
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 8"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_get, .context=(void*)&relay_gpios[7]),
.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(relay_callback_set, .context=(void*)&relay_gpios[7]),
),
NULL
}),
NULL
}),
NULL
};
Thanks
Philipp
What you need to do is:
- use .getter_ex and .setter_ex instead of .getter and .setter. The .*_ex variants are the same getters and setters, except for they take a pointer to characteristic as first argument.
- use .context field in homekit_characteristic_t to store your extra data. Then you can access it through characteristic pointer in getter and setter (and callback, although callbacks were designed prior to realizing that getters and setters will need context too, so they had a separate means to attach context which is now superseeded by characteristic context).
homekit_value_t light_on_get(homekit_charactersitic_t *ch) {
uint8_t gpio = *((uint8_t*) ch->conext);
return HOMEKIT_BOOL(gpio_read(gpio));
}
void light_on_set(homekit_characteristic_t *ch, homekit_value_t value) {
uint8_t gpio = *((uint8_t*) ch->conext);
gpio_write(gpio, value.bool_value);
}
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 7"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=light_on_get,
.setter_ex=light_on_set,
.context=(void*)&relay_gpios[6],
),
NULL
}),
I will try that, right now I added 8 times led_on_set0, led_on_set1... were in the function it passes the relay_gpios[ * ] to the „working“ functions. => Works ;-) Removing that led_on_set*/get* will cut the code and makes it more readable i hope, thanks
Right now I have the „.primary=true“ on all 8 relays/lightbulbs, is that ok or whats the function of „.primary=true“?
Just one additional question, when should I make a new task and when it is ok to have it direct in the „homekit“ function calls?
is that ok or whats the function of „.primary=true“?
No, this is not OK. Accessory should have only one primary service.
when should I make a new task and when it is ok to have it direct in the „homekit“ function calls?
Well, the rule of thumb is to have all getters/setters/callbacks being fast: no waiting, sleeping, expensive computations.
And whats the difference between primary and non primary?
I think primary attribute determines which accessory tile will be displayed in Home app. E.g. if you have a thermostat and an outlet services together in one accessory, whichever is marked primary will be displayed on accessory tile in Home app.
Thanks for support and the great git!
Tried it out and get a warning which I dont understand, any ideas whats the problem? Thanks
make -C schaltkasten all
make: Verzeichnis „/home/pi/projects/schaltkasten“ wird betreten
CC /home/pi/projects/schaltkasten/schaltkasten.c
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_lightbulb, .services=(homekit_service_t*[]){
^
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: initialization from incompatible pointer type [enabled by default]
/home/pi/projects/schaltkasten/schaltkasten.c:118:5: warning: (near initialization for '(anonymous).getter_ex') [enabled by default]
Code:
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, "Sample LED"),
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "037A2BABF19D"),
HOMEKIT_CHARACTERISTIC(MODEL, "MyLED"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, led_identify),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Status LED"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter=led_on_get,
.setter=led_on_set
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 1"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[0]
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 2"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[1]
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 3"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[2]
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 4"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[3],
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 5"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[4]
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 6"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[5]
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 7"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[6]
),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=false, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Relay 8"),
HOMEKIT_CHARACTERISTIC(
ON, false,
.getter_ex=get_relay,
.setter_ex=set_relay,
.context=(void*)&relay[7]
),
NULL
}),
NULL
}),
NULL
};
warning: initialization from incompatible pointer type
I guess you're using wrong function signature for getters and setters.