Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getter + setter with variable #410

Open
MGPhil opened this issue Dec 28, 2020 · 8 comments
Open

getter + setter with variable #410

MGPhil opened this issue Dec 28, 2020 · 8 comments

Comments

@MGPhil
Copy link

MGPhil commented Dec 28, 2020

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

@maximkulkin
Copy link
Owner

What you need to do is:

  1. 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.
  2. 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
}),

@MGPhil
Copy link
Author

MGPhil commented Dec 29, 2020

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?

@maximkulkin
Copy link
Owner

maximkulkin commented Dec 29, 2020

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.

@MGPhil
Copy link
Author

MGPhil commented Dec 29, 2020

And whats the difference between primary and non primary?

@maximkulkin
Copy link
Owner

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.

@MGPhil
Copy link
Author

MGPhil commented Jan 2, 2021

Thanks for support and the great git!

@MGPhil MGPhil closed this as completed Jan 2, 2021
@MGPhil MGPhil reopened this Jan 6, 2021
@MGPhil
Copy link
Author

MGPhil commented Jan 6, 2021

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
};

@rottenhowler
Copy link

warning: initialization from incompatible pointer type

I guess you're using wrong function signature for getters and setters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants