maximkulkin / esp-homekit

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

How to check if the server is paired #54

Closed ruudk closed 5 years ago

ruudk commented 6 years ago

First of all, I want to say thank you all for this amazing library. The moment I got it working on my ESP32 I was super excited 👏

Is there an existing way to check wether the server is paired yet? I want to include a status led that blinks when the accessory is not yet paired.

I know that the homekit_server_t struct contains a bool paired but there is no way to access this server struct from my code since homekit_server_init returns void.

What would be the best way to implement this? I want to create a PR but fail to see how.

peros550 commented 5 years ago

Hey, did you find any way to solve this issue? I kind of came across the same. :)

ruudk commented 5 years ago

Nope

peros550 commented 5 years ago

I made a few changes to the server.c file and now there is a function which returns the status of pair. Please note that my experience with C and homekit is minimum so I'm not sure if the following changes are acceptable in principal or not. If anyone has any suggestion on the proposed changes, please make it. It will be very welcome.

Here is what I did in the server.c:

//declare a local variable that will hold pair status. 
static bool _ispaired = false;

then, within "homekit_server_task" function find the following code and add the marked line:

    if (pairing) {
        INFO("Found admin pairing with %s, disabling pair setup", pairing->device_id);
        _ispaired = true;    // <-- Add this line
        pairing_free(pairing);
        server->paired = true;
   } else {                          //<-- Add this line
          _ispaired = false;         //<-- Add this line
    }

Then add the following function and you should be good to go.

bool homekit_is_paired()
{
    return _ispaired;
}

You can call "homekit_is_paired()" from anywhere in your code and it will return the status of pair. I don't know how to make a PR. If the above changes are acceptable, then give it a try.

peros550 commented 5 years ago

Here is a more concrete implementation of the changes required to get pairing status;

All the below changes should be applied to server.c

1) Definition of a local variable holding the pairing status

//declare a local variable that will hold pair status. 
static bool _ispaired = false;

2) Make changes in code so that local variable _ispaired is in sync with pairing status:

void homekit_server_on_pair_setup(client_context_t *context, const byte *data, size_t size) {
//....other code....

            tlv_values_t *response = tlv_new();
            tlv_add_integer_value(response, TLVType_State, 1, 6);
            tlv_add_value(response, TLVType_EncryptedData,
                          encrypted_response_data, encrypted_response_data_size);

            free(encrypted_response_data);

            send_tlv_response(context, response);

            pairing_context_free(context->server->pairing_context);
            context->server->pairing_context = NULL;

            context->server->paired = 1;
            homekit_setup_mdns(context->server);
        _ispaired = true;                             //--------> Add this line
            CLIENT_INFO(context, "Successfully paired");

            break;
        }
        default: {
            CLIENT_ERROR(context, "Unknown state: %d",
                  tlv_get_integer_value(message, TLVType_State, -1));
        }
}

also here:

void homekit_server_on_pair_verify(client_context_t *context, const byte *data, size_t size) {
//....other code....
 if (!pairing) {
                CLIENT_ERROR(context, "No pairing for %s found", device_id);
        _ispaired = false;                    //--------> Add this line
                free(device_id);
                tlv_free(decrypted_message);
                pair_verify_context_free(context->verify_context);
                context->verify_context = NULL;

                send_tlv_error_response(context, 4, TLVError_Authentication);
                break;
            }
             _ispaired = true;                                //--------> Add this line
            CLIENT_INFO(context, "Found pairing with %s", device_id);
            free(device_id);
//....other code....
}

also here:

void homekit_server_on_pairings(client_context_t *context, const byte *data, size_t size) {

 homekit_storage_pairing_iterator_free(pairing_it);

                    if (!pairing) {
                        // No admins left, enable pairing again
            _ispaired = false;     //--------> Add this line
                        INFO("Last admin pairing was removed, resetting accessory");
                        homekit_server_on_reset(context);
                        /*
                        INFO("Last admin pairing was removed, enabling pair setup");
                        context->server->paired = false;
                        homekit_setup_mdns(context->server);
                        */
                    } else {
                        pairing_free(pairing);
                    }

}

here:

void homekit_server_task(void *args) {

    if (pairing) {
    _ispaired = true;   //--------> Add this line
        INFO("Found admin pairing with %s, disabling pair setup", pairing->device_id);
        pairing_free(pairing);
        server->paired = true;
    }else{      //--------> Add this line
    _ispaired = false; //--------> Add this line
    }
}

3) Finally, implement function homekit_is_paired() which will return status of pairing :

bool homekit_is_paired()
{
    return _ispaired;
}

@maximkulkin Do you think the above code changes are possible to be implemented from your side?

Many Thanks,

maximkulkin commented 5 years ago

I will look into implementing this

peros550 commented 5 years ago

Thank you! Looking forward to read your code and see your approach :)

Roman1us commented 5 years ago

For now you can implement this in your own init code, just use startup code from homekit_server_init to access server structure

maximkulkin commented 5 years ago

I have added support for tracking some homekit internal state through events. Check out led_status example.