Yurik72 / ESPHap

ESP32/ESP8266 Arduino library for native Apple Homekit Accessory Protocol (HAP)
MIT License
265 stars 60 forks source link

Double switch not working as expected on ESP8266 #47

Closed chrwh closed 3 years ago

chrwh commented 3 years ago

Hi,

Thanks for this project, it's GREAT :-)

I have an issue with a double switch i'm trying to make. When both are off in IOS home, and I turn on switch 1, switch 2 will also turn on. If both are off, and I turn on switch 2, only switch 2 will turn on as expected. What can I be doing wrong?

Best regards, Christian

/* ESPHap example EspHapLed for ESP8266

This example for ESPHap shows how to control a LED with Apple Home app. It implements accessory type "light bulb".

This example code is part of the public domain */

include

ifdef ESP32

include

endif

include

include

include "coredecls.h"

const char ssid = "xx"; const char password = "xx";

const int identity_led=3; const int led_gpio = 2; const int led1_gpio = 0;

extern "C"{

include "homeintegration.h"

}

include "homekitintegrationcpp.h"

homekit_service_t hapservice={0}; String pair_file_name="/pair.dat"; //esp8266::MDNSImplementation::MDNSResponder MDNS1;

LOCAL os_timer_t callbacktimer;

void setup() { disable_extra4k_at_link_time(); Serial.begin(115200); delay(10);

// We start by connecting to a WiFi network

ifdef ESP32

 if (!SPIFFS.begin(true)) {
  // Serial.print("SPIFFS Mount failed");
 }

endif

ifdef ESP8266

 if (!SPIFFS.begin()) {
  Serial.print("SPIFFS Mount failed");
 }

endif

Serial.println(ssid);

ifdef ESP8266

WiFi.mode(WIFI_STA); WiFi.begin((char)ssid, (char)password);

else

WiFi.begin(ssid, password);

endif

while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
}
Serial.println("");

// Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP());

pinMode(led_gpio,OUTPUT); pinMode(led1_gpio,OUTPUT); ///setup identity gpio // hap_set_identity_gpio(identity_led); //identity_led=2 will blink on identity

/// now will setup homekit device

//this is for custom storaage usage
// In given example we are using \pair.dat   file in our spiffs system
//see implementation below
Serial.print("Free heap: ");
Serial.println(system_get_free_heap_size());

init_hap_storage();

set_callback_storage_change(storage_changed);

/// We will use for this example only one accessory (possible to use a several on the same esp)
//Our accessory type is light bulb, Apple interface will proper show that

// hap_setbase_accessorytype(homekit_accessory_category_lightbulb); hap_setbase_accessorytype(homekit_accessory_category_switch);

/// init base properties
hap_initbase_accessory_service("","test","0","Fun","1.42"); 

//we will add only one light bulb service and keep pointer for nest using //hapservice= hap_add_lightbulb_service("Led",led_callback,(void)&led_gpio); hapservice= hap_add_switch_service("AUX",led_callback,(void)&led_gpio); hapservice= hap_add_switch_service("CD",led1_callback,(void*)&led1_gpio); //and finally init HAP

hap_init_homekit_server();

}

void loop() {

hap_homekit_loop(); //delay(2); return; }

void init_hap_storage(){ Serial.print("init_hap_storage");

File fsDAT=SPIFFS.open(pair_file_name, "r"); if(!fsDAT){ Serial.println("Failed to read pair.dat"); return; } int size=hap_get_storage_size_ex(); char* buf=new char[size]; memset(buf,0xff,size); int readed=fsDAT.readBytes(buf,size); // Serial.print("Readed bytes ->"); // Serial.println(readed); hap_init_storage_ex(buf,size); fsDAT.close(); delete []buf; }

void storage_changed(char * szstorage,int bufsize){

SPIFFS.remove(pair_file_name); File fsDAT=SPIFFS.open(pair_file_name, "w+"); if(!fsDAT){ Serial.println("Failed to open pair.dat"); return; } fsDAT.write((uint8_t*)szstorage, bufsize);

fsDAT.close(); } //can be used for any logic, it will automatically inform Apple about state changes void set_led(bool val){ Serial.println("set_led"); digitalWrite(led_gpio, val?HIGH:LOW); //we need notify apple about changes

if(hapservice){ Serial.println("notify hap"); //getting on/off characteristic homekit_characteristic_t * ch= homekit_service_characteristic_by_type(hapservice, HOMEKIT_CHARACTERISTIC_ON); if(ch){ Serial.println("found characteristic"); if(ch->value.bool_value!=val){ //wil notify only if different ch->value.bool_value=val; homekit_characteristic_notify(ch,ch->value); } } } }

void set_led1(bool val){ Serial.println("set_led1"); digitalWrite(led1_gpio, val?HIGH:LOW); //we need notify apple about changes

if(hapservice){ Serial.println("notify hap"); //getting on/off characteristic homekit_characteristic_t * ch= homekit_service_characteristic_by_type(hapservice, HOMEKIT_CHARACTERISTIC_ON); if(ch){ Serial.println("found characteristic"); if(ch->value.bool_value!=val){ //wil notify only if different ch->value.bool_value=val; homekit_characteristic_notify(ch,ch->value); } } } }

void led_callback(homekit_characteristic_t ch, homekit_value_t value, void context) { Serial.println("led_callback"); set_led(ch->value.bool_value); }

void led1_callback(homekit_characteristic_t ch, homekit_value_t value, void context) { Serial.println("led1_callback"); set_led1(ch->value.bool_value); }

Yurik72 commented 3 years ago

Hello, firts of all I think you not completelly filling a difference between Sevices And Accessories. In your example I suppose you want to handle 3 accessories on the same ESP board: 1x LED & 2x Switch (or only 2xSwitch) Therefore Led is a firts Accessory and any additional switch shoul be added as : hap_new_switch_service_as_accessory instead of hap_add_switch_service. Or y

But this is not a rootcause of you mistake If you want to handle two switch services you should have separate pointers to them, in your code

hapservice= hap_add_switch_service("AUX",led_callback,(void*)&led_gpio);
hapservice= hap_add_switch_service("CD",led1_callback,(void*)&led1_gpio);

you simple owerrwritten first AUX and lost pointer to them and you hav such behaviour, would be better

hapservice1= hap_add_switch_service("AUX",led_callback,(void*)&led_gpio);
hapservice2= hap_add_switch_service("CD",led1_callback,(void*)&led1_gpio);

and handling of each changing and callback should used those services

You can see example where are two accessories are used https://github.com/Yurik72/ESPHap/tree/master/examples/EspHap_RGB_Motion

chrwh commented 3 years ago

Hi, OK I see, thanks for that. One more thing how do I update the code via webinterface IP/update ? Tried to make bin file in arduino and upload that, (the same as already installed, but with my changes, but it says it too big?

Yurik72 commented 3 years ago

There is not an issue of this library, Please check what Partition Scheme you are selecting (Arduino->Tools-PartitionScheme) To be able for OTA , Partition scheme must be enabled for OTA.
When OTA is enable program available size is reduced twice, to be able to store TWO firmwares

So in given example (I suppose scketch is size around 600Kб, and Fash Size is 4Mb) you can choose (ESP8266) like 1.2 APP /1.5 SPIFFS, means you have 2 blocks (1.2 Mb each) for firmware and 1.5 for SPIFFS