diff --git a/components/common/homekit b/components/common/homekit index 0f8dd68b..ab41afb7 160000 --- a/components/common/homekit +++ b/components/common/homekit @@ -1 +1 @@ -Subproject commit 0f8dd68bc1499f38f82771ac58ddaf3c778cd87f +Subproject commit ab41afb7e53d511973354bcb6536af2c3a66b2c8 diff --git a/components/esp8266-open-rtos/cJSON b/components/esp8266-open-rtos/cJSON index 2216b130..2b931710 160000 --- a/components/esp8266-open-rtos/cJSON +++ b/components/esp8266-open-rtos/cJSON @@ -1 +1 @@ -Subproject commit 2216b130ce726071407541680f5c763003e8d740 +Subproject commit 2b9317101a7ffbcf834eaebf7ef92b6d52d10ff4 diff --git a/components/esp8266-open-rtos/led-status b/components/esp8266-open-rtos/led-status index c56094c4..269fe8a2 160000 --- a/components/esp8266-open-rtos/led-status +++ b/components/esp8266-open-rtos/led-status @@ -1 +1 @@ -Subproject commit c56094c4c5bb92e33f7c019d548171bbe0497c36 +Subproject commit 269fe8a23299908ee6dcd5af0a7660246d402cfc diff --git a/examples/contact_sensor/Makefile b/examples/contact_sensor/Makefile new file mode 100644 index 00000000..e5fb129b --- /dev/null +++ b/examples/contact_sensor/Makefile @@ -0,0 +1,19 @@ +PROGRAM = contact_sensor + +EXTRA_COMPONENTS = \ + extras/http-parser \ + extras/dhcpserver \ + $(abspath ../../components/esp-8266/wifi_config) \ + $(abspath ../../components/common/wolfssl) \ + $(abspath ../../components/common/cJSON) \ + $(abspath ../../components/common/homekit) + +FLASH_SIZE ?= 32 +FLASH_MODE ?= dout + +EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS + +include $(SDK_PATH)/common.mk + +monitor: + $(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT) diff --git a/examples/contact_sensor/contact_sensor.c b/examples/contact_sensor/contact_sensor.c new file mode 100644 index 00000000..32f82e0f --- /dev/null +++ b/examples/contact_sensor/contact_sensor.c @@ -0,0 +1,108 @@ +#define DEVICE_MANUFACTURER "Unknown" +#define DEVICE_NAME "Contact-Sensor" +#define DEVICE_MODEL "esp8266" +#define DEVICE_SERIAL "12345678" +#define FW_VERSION "1.0" +#define CONTACT_SENSOR_GPIO 4 +#define LED_GPIO 2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, DEVICE_NAME); +homekit_characteristic_t manufacturer = HOMEKIT_CHARACTERISTIC_(MANUFACTURER, DEVICE_MANUFACTURER); +homekit_characteristic_t serial = HOMEKIT_CHARACTERISTIC_(SERIAL_NUMBER, DEVICE_SERIAL); +homekit_characteristic_t model = HOMEKIT_CHARACTERISTIC_(MODEL, DEVICE_MODEL); +homekit_characteristic_t revision = HOMEKIT_CHARACTERISTIC_(FIRMWARE_REVISION, FW_VERSION); +homekit_characteristic_t sensor_state = HOMEKIT_CHARACTERISTIC_(CONTACT_SENSOR_STATE, 0); + +void led_write(bool on) { + gpio_write(LED_GPIO, on ? 0 : 1); +} + +void identify_task(void *_args) { + // We identify the board by Flashing it's LED. + for (int i=0; i<1; i++) { + for (int j=0; j<2; j++) { + led_write(true); + vTaskDelay(100 / portTICK_PERIOD_MS); + led_write(false); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + vTaskDelay(250 / portTICK_PERIOD_MS); + } + led_write(false); + vTaskDelete(NULL); +} + +void identify() { + printf("identify\n\n"); + xTaskCreate(identify_task, "identify", 128, NULL, 2, NULL); +} + +homekit_accessory_t *accessories[] = { + HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_sensor, .services=(homekit_service_t*[]){ + HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]){ + &name, + &manufacturer, + &serial, + &model, + &revision, + HOMEKIT_CHARACTERISTIC(IDENTIFY, identify), + NULL + }), + HOMEKIT_SERVICE(CONTACT_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]){ + HOMEKIT_CHARACTERISTIC(NAME, "Contact Sensor"), + &sensor_state, + NULL + }), + NULL + }), + NULL +}; + +void contact_sensor_callback(uint8_t gpio) { + if (gpio == CONTACT_SENSOR_GPIO){ + int new = 0; + new = gpio_read(CONTACT_SENSOR_GPIO); + identify(); + sensor_state.value = HOMEKIT_UINT8(new); + homekit_characteristic_notify(&sensor_state, HOMEKIT_UINT8(new)); + } + else { + printf("Interrupt on %d", gpio); + } +} + +void gpio_init() { + gpio_enable(LED_GPIO, GPIO_OUTPUT); + gpio_enable(CONTACT_SENSOR_GPIO, GPIO_INPUT); + gpio_set_pullup(CONTACT_SENSOR_GPIO, true, true); + gpio_set_interrupt(CONTACT_SENSOR_GPIO, GPIO_INTTYPE_EDGE_ANY, contact_sensor_callback); +} +homekit_server_config_t config = { + .accessories = accessories, + .password = "111-11-111" +}; + +void on_wifi_ready() { + homekit_server_init(&config); +} +void user_init(void) { + uart_set_baud(0, 115200); + wifi_config_init("contact-sensor", NULL, on_wifi_ready); + gpio_init(); +} diff --git a/examples/led_strip_animation_wifi/Makefile b/examples/led_strip_animation_wifi/Makefile new file mode 100644 index 00000000..d1ec4904 --- /dev/null +++ b/examples/led_strip_animation_wifi/Makefile @@ -0,0 +1,29 @@ +PROGRAM = led_strip_animation + +EXTRA_COMPONENTS = \ + extras/http-parser \ + extras/i2s_dma \ + extras/ws2812_i2s \ + extras/dhcpserver \ + $(abspath ../../components/esp8266-open-rtos/cJSON) \ + $(abspath ../../components/common/wolfssl) \ + $(abspath ../../components/common/homekit) \ + $(abspath ../../components/common/button) \ + $(abspath ../../components/esp8266-open-rtos/wifi_config) \ + $(abspath ../../components/esp8266-open-rtos/WS2812FX) + +FLASH_SIZE ?= 32 +# FLASH_SIZE ?= 8 +# HOMEKIT_SPI_FLASH_BASE_ADDR ?= 0x7A000 +HOMEKIT_SPI_FLASH_BASE_ADDR=0x7A000 + +EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS + +include $(SDK_PATH)/common.mk +include $(abspath ../../wifi.h) + +LIBS += m + +monitor: + $(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT) + diff --git a/examples/led_strip_animation_wifi/led_strip_animation.c b/examples/led_strip_animation_wifi/led_strip_animation.c new file mode 100644 index 00000000..6ee0ecdd --- /dev/null +++ b/examples/led_strip_animation_wifi/led_strip_animation.c @@ -0,0 +1,362 @@ +/* +* This is an example of an rgb ws2812_i2s led strip animation using a WS2812FX library fork for freertos +* +* NOTE: +* 1) the ws2812_i2s library uses hardware I2S so output pin is GPIO3 and cannot be changed. +* 2) on some ESP8266 such as the Wemos D1 mini, GPIO3 is the same pin used for serial comms (RX pin). +* 3) you can still print stuff to serial but transmiting data to wemos will interfere on the leds output +* +* Debugging printf statements are disabled below because of note (2) - you can uncomment +* them if your hardware supports serial comms that do not conflict with I2S on GPIO3. +* +* Contributed April 2018 by https://github.com/PCSaito +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "wifi_config.h" +#include + +#include "WS2812FX/WS2812FX.h" + +#define LED_RGB_SCALE 255 // this is the scaling factor used for color conversion +#define LED_COUNT 9 // this is the number of WS2812B leds on the strip +#define LED_INBUILT_GPIO 2 // this is the onboard LED used to show on/off only +#define RESET_BUTTON 0 +// Global variables +float led_hue = 0; // hue is scaled 0 to 360 +float led_saturation = 100; // saturation is scaled 0 to 100 +float led_brightness = 33; // brightness is scaled 0 to 100 +bool led_on = false; // on is boolean on or off +bool led_on_value = (bool)0; // this is the value to write to GPIO for led on (0 = GPIO low) + +float fx_hue = 64; // hue is scaled 0 to 360 +float fx_saturation = 50; // saturation is scaled 0 to 100 +float fx_brightness = 50; // brightness is scaled 0 to 100 +bool fx_on = true; + +//http://blog.saikoled.com/post/44677718712/how-to-convert-from-hsi-to-rgb-white +static void hsi2rgb(float h, float s, float i, ws2812_pixel_t* rgb) { + int r, g, b; + + while (h < 0) { h += 360.0F; }; // cycle h around to 0-360 degrees + while (h >= 360) { h -= 360.0F; }; + h = 3.14159F*h / 180.0F; // convert to radians. + s /= 100.0F; // from percentage to ratio + i /= 100.0F; // from percentage to ratio + s = s > 0 ? (s < 1 ? s : 1) : 0; // clamp s and i to interval [0,1] + i = i > 0 ? (i < 1 ? i : 1) : 0; // clamp s and i to interval [0,1] + i = i * sqrt(i); // shape intensity to have finer granularity near 0 + + if (h < 2.09439) { + r = LED_RGB_SCALE * i / 3 * (1 + s * cos(h) / cos(1.047196667 - h)); + g = LED_RGB_SCALE * i / 3 * (1 + s * (1 - cos(h) / cos(1.047196667 - h))); + b = LED_RGB_SCALE * i / 3 * (1 - s); + } + else if (h < 4.188787) { + h = h - 2.09439; + g = LED_RGB_SCALE * i / 3 * (1 + s * cos(h) / cos(1.047196667 - h)); + b = LED_RGB_SCALE * i / 3 * (1 + s * (1 - cos(h) / cos(1.047196667 - h))); + r = LED_RGB_SCALE * i / 3 * (1 - s); + } + else { + h = h - 4.188787; + b = LED_RGB_SCALE * i / 3 * (1 + s * cos(h) / cos(1.047196667 - h)); + r = LED_RGB_SCALE * i / 3 * (1 + s * (1 - cos(h) / cos(1.047196667 - h))); + g = LED_RGB_SCALE * i / 3 * (1 - s); + } + + rgb->red = (uint8_t) r; + rgb->green = (uint8_t) g; + rgb->blue = (uint8_t) b; + rgb->white = (uint8_t) 0; // white channel is not used +} + +void led_identify_task(void *_args) { + // initialise the onboard led as a secondary indicator (handy for testing) + gpio_enable(LED_INBUILT_GPIO, GPIO_OUTPUT); + + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + gpio_write(LED_INBUILT_GPIO, (int)led_on_value); + vTaskDelay(100 / portTICK_PERIOD_MS); + gpio_write(LED_INBUILT_GPIO, 1 - (int)led_on_value); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + vTaskDelay(250 / portTICK_PERIOD_MS); + } + + gpio_write(LED_INBUILT_GPIO, 1 - (int)led_on_value); + + vTaskDelete(NULL); +} + +void led_identify(homekit_value_t _value) { + // printf("LED identify\n"); + xTaskCreate(led_identify_task, "LED identify", 128, NULL, 2, NULL); +} + +homekit_value_t led_on_get() { + return HOMEKIT_BOOL(led_on); +} + +void led_on_set(homekit_value_t value) { + if (value.format != homekit_format_bool) { + // printf("Invalid on-value format: %d\n", value.format); + return; + } + + led_on = value.bool_value; + + if (led_on) { + WS2812FX_setBrightness((uint8_t)floor(led_brightness*2.55)); + + } else { + WS2812FX_setBrightness(0); + } +} + +homekit_value_t led_brightness_get() { + return HOMEKIT_INT(led_brightness); +} + +void led_brightness_set(homekit_value_t value) { + if (value.format != homekit_format_int) { + // printf("Invalid brightness-value format: %d\n", value.format); + return; + } + led_brightness = value.int_value; + + WS2812FX_setBrightness((uint8_t)floor(led_brightness*2.55)); +} + +homekit_value_t led_hue_get() { + return HOMEKIT_FLOAT(led_hue); +} + +void led_hue_set(homekit_value_t value) { + if (value.format != homekit_format_float) { + // printf("Invalid hue-value format: %d\n", value.format); + return; + } + led_hue = value.float_value; + + ws2812_pixel_t rgb = { { 0, 0, 0, 0 } }; + hsi2rgb(led_hue, led_saturation, 100, &rgb); + + WS2812FX_setColor(rgb.red, rgb.green, rgb.blue); +} + +homekit_value_t led_saturation_get() { + return HOMEKIT_FLOAT(led_saturation); +} + +void led_saturation_set(homekit_value_t value) { + if (value.format != homekit_format_float) { + // printf("Invalid sat-value format: %d\n", value.format); + return; + } + led_saturation = value.float_value; + + ws2812_pixel_t rgb = { { 0, 0, 0, 0 } }; + hsi2rgb(led_hue, led_saturation, 100, &rgb); + + WS2812FX_setColor(rgb.red, rgb.green, rgb.blue); +} + +homekit_value_t fx_on_get() { + return HOMEKIT_BOOL(fx_on); +} + +void fx_on_set(homekit_value_t value) { + if (value.format != homekit_format_bool) { + // printf("Invalid on-value format: %d\n", value.format); + return; + } + fx_on = value.bool_value; + + if (fx_on) { + WS2812FX_setMode360(fx_hue); + } else { + WS2812FX_setMode360(0); + } +} + +homekit_value_t fx_brightness_get() { + return HOMEKIT_INT(fx_brightness); +} + +void fx_brightness_set(homekit_value_t value) { + if (value.format != homekit_format_int) { + // printf("Invalid brightness-value format: %d\n", value.format); + return; + } + fx_brightness = value.int_value; + + if (fx_brightness > 50) { + uint8_t fx_speed = fx_brightness - 50; + WS2812FX_setSpeed(fx_speed*5.1); + WS2812FX_setInverted(true); + } else { + uint8_t fx_speed = abs(fx_brightness - 51); + WS2812FX_setSpeed(fx_speed*5.1); + WS2812FX_setInverted(false); + } +} + +homekit_value_t fx_hue_get() { + return HOMEKIT_FLOAT(fx_hue); +} + +void fx_hue_set(homekit_value_t value) { + if (value.format != homekit_format_float) { + // printf("Invalid hue-value format: %d\n", value.format); + return; + } + fx_hue = value.float_value; + + WS2812FX_setMode360(fx_hue); +} + +homekit_value_t fx_saturation_get() { + return HOMEKIT_FLOAT(fx_saturation); +} + +void fx_saturation_set(homekit_value_t value) { + if (value.format != homekit_format_float) { + // printf("Invalid hue-value format: %d\n", value.format); + return; + } + fx_saturation = value.float_value; +} + +homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, "Ledstrip"); + +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*[]) { + &name, + HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Generic"), + HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "137A2BABF19D"), + HOMEKIT_CHARACTERISTIC(MODEL, "LEDStripFX"), + HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"), + HOMEKIT_CHARACTERISTIC(IDENTIFY, led_identify), + NULL + }), + HOMEKIT_SERVICE(LIGHTBULB, .primary = true, .characteristics = (homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "LED"), + HOMEKIT_CHARACTERISTIC( + ON, true, + .getter = led_on_get, + .setter = led_on_set + ), + HOMEKIT_CHARACTERISTIC( + BRIGHTNESS, 100, + .getter = led_brightness_get, + .setter = led_brightness_set + ), + HOMEKIT_CHARACTERISTIC( + HUE, 0, + .getter = led_hue_get, + .setter = led_hue_set + ), + HOMEKIT_CHARACTERISTIC( + SATURATION, 0, + .getter = led_saturation_get, + .setter = led_saturation_set + ), + NULL + }), + HOMEKIT_SERVICE(LIGHTBULB, .primary = true, .characteristics = (homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "LED FX"), + HOMEKIT_CHARACTERISTIC( + ON, true, + .getter = fx_on_get, + .setter = fx_on_set + ), + HOMEKIT_CHARACTERISTIC( + BRIGHTNESS, 100, + .getter = fx_brightness_get, + .setter = fx_brightness_set + ), + HOMEKIT_CHARACTERISTIC( + HUE, 0, + .getter = fx_hue_get, + .setter = fx_hue_set + ), + HOMEKIT_CHARACTERISTIC( + SATURATION, 0, + .getter = fx_saturation_get, + .setter = fx_saturation_set + ), + NULL + }), + NULL + }), + NULL +}; + +void button_reset_callback(button_event_t event, void* context) { + // down button pressed + switch (event) { + case button_event_single_press: + //printf("single press\n"); + break; + case button_event_double_press: + //printf("double press\n"); + break; + case button_event_tripple_press: + //printf("tripple press\n"); + break; + case button_event_long_press: + //printf("long press\n"); + //printf("Resetting Wifi Config\n"); + wifi_config_reset(); + //printf("Resetting HomeKit Config\n"); + homekit_server_reset(); + //printf("Restarting\n"); + sdk_system_restart(); + break; + } +} +homekit_server_config_t config = { + .accessories = accessories, + .password = "111-11-111" +}; + +static bool homekit_initialized = false; + +void on_wifi_config_event(wifi_config_event_t event) { + if (event == WIFI_CONFIG_CONNECTED) { + //printf("WIFI_CONFIG_CONNECTED\n"); + if (!homekit_initialized) { + //printf("Starting Homekit server...\n"); + homekit_server_init(&config); + homekit_initialized = true; + button_config_t buttonconfig = BUTTON_CONFIG( + button_active_low, + .long_press_time = 3000, + .max_repeat_presses = 3, + ); + if (button_create(RESET_BUTTON, buttonconfig, button_reset_callback, NULL)) { + printf("Failed to initialize button resetwn\n"); + } + } + } +} + +void user_init(void) { + // uart_set_baud(0, 115200); + wifi_config_init2("Led_Strip", "myledstrip", on_wifi_config_event); + WS2812FX_init(LED_COUNT); + led_identify(HOMEKIT_INT(led_brightness)); +} \ No newline at end of file diff --git a/examples/motion_sensor/Makefile b/examples/motion_sensor/Makefile new file mode 100644 index 00000000..f3f2d2cf --- /dev/null +++ b/examples/motion_sensor/Makefile @@ -0,0 +1,19 @@ +PROGRAM = motion_sensor + +EXTRA_COMPONENTS = \ + extras/http-parser \ + extras/dhcpserver \ + $(abspath ../../components/esp-8266/wifi_config) \ + $(abspath ../../components/common/wolfssl) \ + $(abspath ../../components/common/cJSON) \ + $(abspath ../../components/common/homekit) + +FLASH_SIZE ?= 32 +FLASH_MODE ?= dout + +EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS + +include $(SDK_PATH)/common.mk + +monitor: + $(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT) diff --git a/examples/motion_sensor/motion_sensor.c b/examples/motion_sensor/motion_sensor.c new file mode 100644 index 00000000..aca984bf --- /dev/null +++ b/examples/motion_sensor/motion_sensor.c @@ -0,0 +1,107 @@ +#define DEVICE_MANUFACTURER "Unknown" +#define DEVICE_NAME "Motion-Sensor" +#define DEVICE_MODEL "esp8266" +#define DEVICE_SERIAL "12345678" +#define FW_VERSION "1.0" +#define MOTION_SENSOR_GPIO 4 +#define LED_GPIO 2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, DEVICE_NAME); +homekit_characteristic_t manufacturer = HOMEKIT_CHARACTERISTIC_(MANUFACTURER, DEVICE_MANUFACTURER); +homekit_characteristic_t serial = HOMEKIT_CHARACTERISTIC_(SERIAL_NUMBER, DEVICE_SERIAL); +homekit_characteristic_t model = HOMEKIT_CHARACTERISTIC_(MODEL, DEVICE_MODEL); +homekit_characteristic_t revision = HOMEKIT_CHARACTERISTIC_(FIRMWARE_REVISION, FW_VERSION); +homekit_characteristic_t motion_detected = HOMEKIT_CHARACTERISTIC_(MOTION_DETECTED, 0); + +void led_write(bool on) { + gpio_write(LED_GPIO, on ? 0 : 1); +} + +void identify_task(void *_args) { + // We identify the board by Flashing it's LED. + for (int i=0; i<3; i++) { + for (int j=0; j<2; j++) { + led_write(true); + vTaskDelay(100 / portTICK_PERIOD_MS); + led_write(false); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + vTaskDelay(250 / portTICK_PERIOD_MS); + } + led_write(false); + vTaskDelete(NULL); +} + +void identify(homekit_value_t _value) { + printf("identify\n\n"); + xTaskCreate(identify_task, "identify", 128, NULL, 2, NULL); +} + +homekit_accessory_t *accessories[] = { + HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_switch, .services=(homekit_service_t*[]){ + HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]){ + &name, + &manufacturer, + &serial, + &model, + &revision, + HOMEKIT_CHARACTERISTIC(IDENTIFY, identify), + NULL + }), + HOMEKIT_SERVICE(MOTION_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]){ + HOMEKIT_CHARACTERISTIC(NAME, "Motion Sensor"), + &motion_detected, + NULL + }), + NULL + }), + NULL +}; + +void motion_sensor_callback(uint8_t gpio) { + if (gpio == MOTION_SENSOR_GPIO){ + int new = 0; + new = gpio_read(MOTION_SENSOR_GPIO); + motion_detected.value = HOMEKIT_BOOL(new); + homekit_characteristic_notify(&motion_detected, HOMEKIT_BOOL(new)); + } + else { + printf("Interrupt on %d", gpio); + } +} + +void gpio_init() { + gpio_enable(LED_GPIO, GPIO_OUTPUT); + gpio_enable(MOTION_SENSOR_GPIO, GPIO_INPUT); + gpio_set_pullup(MOTION_SENSOR_GPIO, false, false); + gpio_set_interrupt(MOTION_SENSOR_GPIO, GPIO_INTTYPE_EDGE_ANY, motion_sensor_callback); +} +homekit_server_config_t config = { + .accessories = accessories, + .password = "111-11-111" +}; + +void on_wifi_ready() { + homekit_server_init(&config); +} +void user_init(void) { + uart_set_baud(0, 115200); + wifi_config_init("motion-sensor", NULL, on_wifi_ready); + gpio_init(); +} diff --git a/examples/multiple_sensors/Makefile b/examples/multiple_sensors/Makefile new file mode 100644 index 00000000..e1fcd151 --- /dev/null +++ b/examples/multiple_sensors/Makefile @@ -0,0 +1,23 @@ +PROGRAM = multiple_sensors + +EXTRA_COMPONENTS = \ + extras/dht \ + extras/http-parser \ + extras/dhcpserver \ + $(abspath ../../components/esp-8266/wifi_config) \ + $(abspath ../../components/common/wolfssl) \ + $(abspath ../../components/common/cJSON) \ + $(abspath ../../components/common/homekit) + +# DHT22 sensor pin D1 in NodeMCU +SENSOR_PIN ?= 5 + +FLASH_SIZE ?= 32 + +EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS -DSENSOR_PIN=$(SENSOR_PIN) + + +include $(SDK_PATH)/common.mk + +monitor: + $(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT) diff --git a/examples/multiple_sensors/multiple_sensors.c b/examples/multiple_sensors/multiple_sensors.c new file mode 100644 index 00000000..e1a90d54 --- /dev/null +++ b/examples/multiple_sensors/multiple_sensors.c @@ -0,0 +1,171 @@ +#define DEVICE_MANUFACTURER "Unknown" +#define DEVICE_NAME "MultiSensor" +#define DEVICE_MODEL "esp8266" +#define DEVICE_SERIAL "12345678" +#define FW_VERSION "1.0" +#define MOTION_SENSOR_GPIO 4 +#define LED_GPIO 2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, DEVICE_NAME); +homekit_characteristic_t manufacturer = HOMEKIT_CHARACTERISTIC_(MANUFACTURER, DEVICE_MANUFACTURER); +homekit_characteristic_t serial = HOMEKIT_CHARACTERISTIC_(SERIAL_NUMBER, DEVICE_SERIAL); +homekit_characteristic_t model = HOMEKIT_CHARACTERISTIC_(MODEL, DEVICE_MODEL); +homekit_characteristic_t revision = HOMEKIT_CHARACTERISTIC_(FIRMWARE_REVISION, FW_VERSION); +homekit_characteristic_t motion_detected = HOMEKIT_CHARACTERISTIC_(MOTION_DETECTED, 0); +homekit_characteristic_t temperature = HOMEKIT_CHARACTERISTIC_(CURRENT_TEMPERATURE, 0); +homekit_characteristic_t humidity = HOMEKIT_CHARACTERISTIC_(CURRENT_RELATIVE_HUMIDITY, 0); + +#ifndef SENSOR_PIN +#error SENSOR_PIN is not specified +#endif + +void led_write(bool on) { + gpio_write(LED_GPIO, on ? 0 : 1); +} + +void identify_task(void *_args) { + // We identify the board by Flashing it's LED. + for (int i=0; i<1; i++) { + for (int j=0; j<2; j++) { + led_write(true); + vTaskDelay(100 / portTICK_PERIOD_MS); + led_write(false); + vTaskDelay(100 / portTICK_PERIOD_MS); + } + + vTaskDelay(300 / portTICK_PERIOD_MS); + } + led_write(false); + vTaskDelete(NULL); +} + +void identify() { + xTaskCreate(identify_task, "identify", 256, NULL, 2, NULL); +} +void temperature_sensor_identify(homekit_value_t _value) { + printf("Temperature sensor identify\n"); +} + +void temperature_sensor_task(void *_args) { + + float humidity_value, temperature_value; + while (1) { + bool success = dht_read_float_data( + DHT_TYPE_DHT22, SENSOR_PIN, + &humidity_value, &temperature_value + ); + if (success) { + temperature.value.float_value = temperature_value; + humidity.value.float_value = humidity_value; + + homekit_characteristic_notify(&temperature, HOMEKIT_FLOAT(temperature_value)); + homekit_characteristic_notify(&humidity, HOMEKIT_FLOAT(humidity_value)); + } else { + printf("Couldnt read data from sensor\n"); + } + + vTaskDelay(3000 / portTICK_PERIOD_MS); + } +} +void temperature_sensor_init() { + xTaskCreate(temperature_sensor_task, "Temperature Sensor", 256, NULL, 2, NULL); +} + +homekit_accessory_t *accessories[] = { + HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_switch, .services=(homekit_service_t*[]){ + HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]){ + &name, + &manufacturer, + &serial, + &model, + &revision, + HOMEKIT_CHARACTERISTIC(IDENTIFY, identify), + NULL + }), + HOMEKIT_SERVICE(MOTION_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]){ + HOMEKIT_CHARACTERISTIC(NAME, "Motion Sensor"), + &motion_detected, + NULL + }), + NULL + }), + HOMEKIT_ACCESSORY(.id=2, .category=homekit_accessory_category_thermostat, .services=(homekit_service_t*[]) { + HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) { + &name, + &manufacturer, + HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0012345"), + &model, + &revision, + HOMEKIT_CHARACTERISTIC(IDENTIFY, temperature_sensor_identify), + NULL + }), + HOMEKIT_SERVICE(TEMPERATURE_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"), + &temperature, + NULL + }), + HOMEKIT_SERVICE(HUMIDITY_SENSOR, .characteristics=(homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "Humidity Sensor"), + &humidity, + NULL + }), + NULL + }), + NULL +}; + +void motion_sensor_callback(uint8_t gpio) { + if (gpio == MOTION_SENSOR_GPIO){ + int new = 0; + new = gpio_read(MOTION_SENSOR_GPIO); + if (new) { + printf("Motion detected\n"); + identify(); + } + motion_detected.value = HOMEKIT_BOOL(new); + homekit_characteristic_notify(&motion_detected, HOMEKIT_BOOL(new)); + } + else { + printf("Interrupt on %d", gpio); + } +} + +void gpio_init() { + gpio_enable(LED_GPIO, GPIO_OUTPUT); + gpio_enable(MOTION_SENSOR_GPIO, GPIO_INPUT); + gpio_enable(SENSOR_PIN, GPIO_INPUT); + //gpio_set_pullup(SENSOR_PIN, false, false); + //gpio_set_pullup(MOTION_SENSOR_GPIO, false, false); + gpio_set_interrupt(MOTION_SENSOR_GPIO, GPIO_INTTYPE_EDGE_ANY, motion_sensor_callback); +} + + +homekit_server_config_t config = { + .accessories = accessories, + .password = "111-11-111" +}; +void on_wifi_ready() { + homekit_server_init(&config); +} +void user_init(void) { + uart_set_baud(0, 115200); + wifi_config_init("motion-sensor", NULL, on_wifi_ready); + gpio_init(); + temperature_sensor_init(); +} diff --git a/examples/temperature_sensor_oled/Makefile b/examples/temperature_sensor_oled/Makefile new file mode 100644 index 00000000..a0704f86 --- /dev/null +++ b/examples/temperature_sensor_oled/Makefile @@ -0,0 +1,30 @@ +PROGRAM = temperature_sensor_oled + +EXTRA_COMPONENTS = \ + extras/dht \ + extras/http-parser \ + extras/ssd1306 \ + extras/i2c \ + extras/fonts \ + $(abspath ../../components/esp8266-open-rtos/cJSON) \ + $(abspath ../../components/common/wolfssl) \ + $(abspath ../../components/common/homekit) + +# Enable fonts provided by extras/fonts package +FONTS_TERMINUS_6X12_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_6X12_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_12X24_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_14X28_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_16X32_ISO8859_1 = 1 + +# DHT11 sensor pin +SENSOR_PIN ?= 0 + +FLASH_SIZE ?= 32 + +EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS -DSENSOR_PIN=$(SENSOR_PIN) + +include $(SDK_PATH)/common.mk + +monitor: + $(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT) diff --git a/examples/temperature_sensor_oled/temperature_sensor_oled.c b/examples/temperature_sensor_oled/temperature_sensor_oled.c new file mode 100644 index 00000000..a687da0e --- /dev/null +++ b/examples/temperature_sensor_oled/temperature_sensor_oled.c @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "wifi.h" + +#include + +// OLED Stuff Start +#include +#include +#include +#define I2C_BUS 0 +#define I2C_SDA_PIN 5 +#define I2C_SCL_PIN 4 +#define DISPLAY_WIDTH 128 +#define DISPLAY_HEIGHT 64 +#define DEFAULT_FONT FONT_FACE_TERMINUS_6X12_ISO8859_1 +//#define DEFAULT_FONT0 FONT_FACE_TERMINUS_BOLD_8X14_ISO8859_1 +//#define DEFAULT_FONT-x FONT_FACE_TERMINUS_BOLD_10X18_ISO8859_1 +//#define DEFAULT_FONT-x FONT_FACE_TERMINUS_BOLD_11X22_ISO8859_1 +#define DEFAULT_FONT1 FONT_FACE_TERMINUS_BOLD_12X24_ISO8859_1 +#define DEFAULT_FONT2 FONT_FACE_TERMINUS_BOLD_14X28_ISO8859_1 +#define DEFAULT_FONT3 FONT_FACE_TERMINUS_BOLD_16X32_ISO8859_1 +// OLED Stuff Stop + +#ifndef SENSOR_PIN +#error SENSOR_PIN is not specified +#endif + +//OLED START +static const ssd1306_t display = { + .protocol = SSD1306_PROTO_I2C, + .screen = SSD1306_SCREEN, + .i2c_dev.bus = I2C_BUS, + .i2c_dev.addr = SSD1306_I2C_ADDR_0, + .width = DISPLAY_WIDTH, + .height = DISPLAY_HEIGHT, +}; + +static uint8_t display_buffer[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8]; + +void display_init() { + printf("Starting display init..."); + i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_400K); + if (ssd1306_init(&display)) { + printf("Failed to initialize OLED display\n"); + return; + } + ssd1306_set_whole_display_lighting(&display, false); + ssd1306_set_scan_direction_fwd(&display, false); + ssd1306_set_segment_remapping_enabled(&display, true); + ssd1306_display_on(&display, true); +} + +void display_temperature(float temperature, float humidity) { + //printf(" TEMP %g, HUM %g\n", temperature, humidity); + + char str[16]; + //float f = 123.456789; + //snprintf(str, sizeof(str), "%.2f", temperature); + snprintf(str, sizeof(str), "%.1f", temperature); + + //ssd1306_display_on(&display, true); + + ssd1306_fill_rectangle(&display, display_buffer, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT3], 0, 0, str, OLED_COLOR_WHITE, OLED_COLOR_BLACK); + + //ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT3], 0, 0, "2130", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT2], 90, 0, "C", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT1], 78, 0, "o", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + + //ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT], 0, 0, "Temperature", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + snprintf(str, sizeof(str), "%.1f", humidity); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT3], 0, 32, str, OLED_COLOR_WHITE, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT2], 90, 34, "%", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + //ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT3], 2, 2, "0", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + + + ssd1306_load_frame_buffer(&display, display_buffer); + + +} +//OLED STOP + +static void wifi_init() { + struct sdk_station_config wifi_config = { + .ssid = WIFI_SSID, + .password = WIFI_PASSWORD, + }; + + sdk_wifi_set_opmode(STATION_MODE); + sdk_wifi_station_set_config(&wifi_config); + sdk_wifi_station_connect(); +} + + +void temperature_sensor_identify(homekit_value_t _value) { + printf("Temperature sensor identify\n"); +} + +homekit_characteristic_t temperature = HOMEKIT_CHARACTERISTIC_(CURRENT_TEMPERATURE, 0); +homekit_characteristic_t humidity = HOMEKIT_CHARACTERISTIC_(CURRENT_RELATIVE_HUMIDITY, 0); + + +void temperature_sensor_task(void *_args) { + gpio_set_pullup(SENSOR_PIN, false, false); + + float humidity_value, temperature_value; + while (1) { + bool success = dht_read_float_data( + DHT_TYPE_DHT22, SENSOR_PIN, + &humidity_value, &temperature_value + ); + if (success) { + temperature.value.float_value = temperature_value; + humidity.value.float_value = humidity_value; + + homekit_characteristic_notify(&temperature, HOMEKIT_FLOAT(temperature_value)); + homekit_characteristic_notify(&humidity, HOMEKIT_FLOAT(humidity_value)); + //OLED START + display_temperature(temperature_value, humidity_value); + //OLED STOP + } else { + printf("Couldnt read data from sensor\n"); + } + + vTaskDelay(10000 / portTICK_PERIOD_MS); + } +} + +void temperature_sensor_init() { + xTaskCreate(temperature_sensor_task, "Temperatore Sensor", 512, NULL, 2, NULL); +} + + +homekit_accessory_t *accessories[] = { + HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_thermostat, .services=(homekit_service_t*[]) { + HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"), + HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"), + HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0012345"), + HOMEKIT_CHARACTERISTIC(MODEL, "MyTemperatureSensor"), + HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"), + HOMEKIT_CHARACTERISTIC(IDENTIFY, temperature_sensor_identify), + NULL + }), + HOMEKIT_SERVICE(TEMPERATURE_SENSOR, .primary=true, .characteristics=(homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "Temperature Sensor"), + &temperature, + NULL + }), + HOMEKIT_SERVICE(HUMIDITY_SENSOR, .characteristics=(homekit_characteristic_t*[]) { + HOMEKIT_CHARACTERISTIC(NAME, "Humidity Sensor"), + &humidity, + NULL + }), + NULL + }), + NULL +}; + +homekit_server_config_t config = { + .accessories = accessories, + .password = "111-11-111" +}; + +void user_init(void) { + uart_set_baud(0, 115200); + display_init(); + wifi_init(); + temperature_sensor_init(); + homekit_server_init(&config); +} + + diff --git a/examples/thermostat/Makefile b/examples/thermostat/Makefile index ef9f1c9e..f4985038 100644 --- a/examples/thermostat/Makefile +++ b/examples/thermostat/Makefile @@ -3,9 +3,22 @@ PROGRAM = thermostat EXTRA_COMPONENTS = \ extras/dht \ extras/http-parser \ + extras/ssd1306 \ + extras/dhcpserver \ + extras/i2c \ + extras/fonts \ $(abspath ../../components/esp8266-open-rtos/cJSON) \ + $(abspath ../../components/esp8266-open-rtos/wifi_config) \ $(abspath ../../components/common/wolfssl) \ - $(abspath ../../components/common/homekit) + $(abspath ../../components/common/homekit) \ + $(abspath ../../components/common/button) + +# include a lot of builtin fonts + +FONTS_TERMINUS_6X12_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_12X24_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_14X28_ISO8859_1 = 1 +FONTS_TERMINUS_BOLD_16X32_ISO8859_1 = 1 FLASH_SIZE ?= 32 diff --git a/examples/thermostat/thermostat.c b/examples/thermostat/thermostat.c index f9a5bc7d..4e24eaf8 100644 --- a/examples/thermostat/thermostat.c +++ b/examples/thermostat/thermostat.c @@ -1,25 +1,16 @@ /* * Thermostat example - * - * Wiring is as follows (requires ESP-12 as it needs 4 GPIOs): - * - * DHT11 (temperature sensor) - * - * ------------- - * |GND VCC| (These go to control pins of relay) - * |15 13| --> Heater - * |2 12| --> Cooler - * |0 14| --> Fan - * |5 16| - * DHT Data <-- |4 CH_PD| - * |RXD ADC| - * |TXD REST| - * ------------- - * | |-| |-| | | - * | __| |_| |_| | - * ------------- - * */ +#define TEMPERATURE_SENSOR_PIN 2 // GPIO2 is D4 on NodeMCU +#define HEATER_PIN 15 // GPIO15 is D8 on NodeMCU +#define TEMPERATURE_POLL_PERIOD 10000 // Temp refresh rate to milliseconds +#define TEMP_DIFF 0.5 // Set this for differential +#define INVERT_RELAY_SWITCH 0 +#define DHT_TYPE DHT_TYPE_DHT22 // If you are using DHT11 change the type to DHT_TYPE_DHT11 +#define BUTTON_UP_PIN 12 // GPIO12 is D6 on NodeMCU +#define BUTTON_DOWN_PIN 13 // GPIO13 is D7 on NodeMCU +#define BUTTON_RESET_PIN 14 // GPIO14 is D5 on NodeMCU + #include #include #include @@ -30,86 +21,14 @@ #include #include #include - +#include #include #include -#include "wifi.h" - +#include "wifi_config.h" +#include #include - - -#define LED_PIN 2 -#define TEMPERATURE_SENSOR_PIN 4 -#define FAN_PIN 14 -#define COOLER_PIN 12 -#define HEATER_PIN 13 -#define TEMPERATURE_POLL_PERIOD 10000 -#define HEATER_FAN_DELAY 30000 -#define COOLER_FAN_DELAY 0 - - -static void wifi_init() { - struct sdk_station_config wifi_config = { - .ssid = WIFI_SSID, - .password = WIFI_PASSWORD, - }; - - sdk_wifi_set_opmode(STATION_MODE); - sdk_wifi_station_set_config(&wifi_config); - sdk_wifi_station_connect(); -} - - -void thermostat_identify(homekit_value_t _value) { - printf("Thermostat identify\n"); -} - - - - -ETSTimer fan_timer; - - -void heaterOn() { - gpio_write(HEATER_PIN, false); -} - - -void heaterOff() { - gpio_write(HEATER_PIN, true); -} - - -void coolerOn() { - gpio_write(COOLER_PIN, false); -} - - -void coolerOff() { - gpio_write(COOLER_PIN, true); -} - - -void fan_alarm(void *arg) { - gpio_write(FAN_PIN, false); -} - -void fanOn(uint16_t delay) { - if (delay > 0) { - sdk_os_timer_arm(&fan_timer, delay, false); - } else { - gpio_write(FAN_PIN, false); - } -} - - -void fanOff() { - sdk_os_timer_disarm(&fan_timer); - gpio_write(FAN_PIN, true); -} - - void update_state(); +static bool heater_power = 1; void on_update(homekit_characteristic_t *ch, homekit_value_t value, void *context) { @@ -124,9 +43,9 @@ homekit_characteristic_t target_temperature = HOMEKIT_CHARACTERISTIC_( TARGET_TEMPERATURE, 22, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(on_update) ); homekit_characteristic_t units = HOMEKIT_CHARACTERISTIC_(TEMPERATURE_DISPLAY_UNITS, 0); -homekit_characteristic_t current_state = HOMEKIT_CHARACTERISTIC_(CURRENT_HEATING_COOLING_STATE, 0); +homekit_characteristic_t current_state = HOMEKIT_CHARACTERISTIC_(CURRENT_HEATING_COOLING_STATE, 1); homekit_characteristic_t target_state = HOMEKIT_CHARACTERISTIC_( - TARGET_HEATING_COOLING_STATE, 0, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(on_update) + TARGET_HEATING_COOLING_STATE, 1, .valid_values = {.count = 2, .values = (uint8_t[]) { 0, 1}}, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(on_update) ); homekit_characteristic_t cooling_threshold = HOMEKIT_CHARACTERISTIC_( COOLING_THRESHOLD_TEMPERATURE, 25, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(on_update) @@ -136,72 +55,152 @@ homekit_characteristic_t heating_threshold = HOMEKIT_CHARACTERISTIC_( ); homekit_characteristic_t current_humidity = HOMEKIT_CHARACTERISTIC_(CURRENT_RELATIVE_HUMIDITY, 0); +// OLED Stuff Start +#include +#include +#include +#define I2C_BUS 0 +#define I2C_SDA_PIN 5 +#define I2C_SCL_PIN 4 +#define DISPLAY_WIDTH 128 +#define DISPLAY_HEIGHT 64 +#define DEFAULT_FONT FONT_FACE_TERMINUS_6X12_ISO8859_1 +#define DEFAULT_FONT1 FONT_FACE_TERMINUS_BOLD_12X24_ISO8859_1 +#define DEFAULT_FONT2 FONT_FACE_TERMINUS_BOLD_14X28_ISO8859_1 +#define DEFAULT_FONT3 FONT_FACE_TERMINUS_BOLD_16X32_ISO8859_1 + +static const ssd1306_t display = { + .protocol = SSD1306_PROTO_I2C, + .screen = SSD1306_SCREEN, + .i2c_dev.bus = I2C_BUS, + .i2c_dev.addr = SSD1306_I2C_ADDR_0, + .width = DISPLAY_WIDTH, + .height = DISPLAY_HEIGHT, +}; + +static uint8_t display_buffer[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8]; + + +void display_temperature_task(void *_args) { + //printf(" TEMP %g, HUM %g, TARGET: %g\n", temperature, humidity, target_temperature.value.float_value); + while (1) { + float temperature = current_temperature.value.float_value; + float humidity = current_humidity.value.float_value; + char str[16]; + //float f = 123.456789; + //snprintf(str, sizeof(str), "%.2f", temperature); + + //ssd1306_display_on(&display, true); + + // Display temp + snprintf(str, sizeof(str), "%.1f", temperature); + ssd1306_fill_rectangle(&display, display_buffer, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT], 0, 0, "TEMP", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT], 64, 0, "Humidity", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT1], 0, 15, str, OLED_COLOR_WHITE, OLED_COLOR_BLACK); + //ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT2], 50, 0, "°", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + + // Display humidity + snprintf(str, sizeof(str), "%.1f %%", humidity); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT1], 64, 15, str, OLED_COLOR_WHITE, OLED_COLOR_BLACK); + + // Display target temp + if (heater_power){ + snprintf(str, sizeof(str), "Target: %.1f", target_temperature.value.float_value); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT], 0, 40, str, OLED_COLOR_WHITE, OLED_COLOR_BLACK); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT], 80, 40, "C", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + //ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT], 78, 40, "°", OLED_COLOR_WHITE, OLED_COLOR_BLACK); + } else { + snprintf(str, sizeof(str), "POWER OFF"); + ssd1306_draw_string(&display, display_buffer, font_builtin_fonts[DEFAULT_FONT1], 0, 40, str, OLED_COLOR_WHITE, OLED_COLOR_BLACK); + } + + if (ssd1306_load_frame_buffer(&display, display_buffer)) { + printf("Failed to load buffer for OLED display\n"); + } + vTaskDelay(500 / portTICK_PERIOD_MS); + } +} +void display_init() { + printf("Starting display init..."); + i2c_init(I2C_BUS, I2C_SCL_PIN, I2C_SDA_PIN, I2C_FREQ_400K); + if (ssd1306_init(&display)) { + printf("Failed to initialize OLED display\n"); + return; + } + ssd1306_set_whole_display_lighting(&display, false); + ssd1306_set_scan_direction_fwd(&display, false); + ssd1306_set_segment_remapping_enabled(&display, true); + ssd1306_display_on(&display, true); + xTaskCreate(display_temperature_task, "Display", 512, NULL, 2, NULL); +} + + +void thermostat_identify(homekit_value_t _value) { + printf("Thermostat identify\n"); +} + +void heaterOn() { + gpio_write(HEATER_PIN, INVERT_RELAY_SWITCH ? false : true); +} + + +void heaterOff() { + gpio_write(HEATER_PIN, INVERT_RELAY_SWITCH ? true : false); + +} void update_state() { uint8_t state = target_state.value.int_value; + heater_power = state; if ((state == 1 && current_temperature.value.float_value < target_temperature.value.float_value) || (state == 3 && current_temperature.value.float_value < heating_threshold.value.float_value)) { if (current_state.value.int_value != 1) { current_state.value = HOMEKIT_UINT8(1); homekit_characteristic_notify(¤t_state, current_state.value); - - heaterOn(); - coolerOff(); - fanOff(); - fanOn(HEATER_FAN_DELAY); + heaterOn(); } } else if ((state == 2 && current_temperature.value.float_value > target_temperature.value.float_value) || (state == 3 && current_temperature.value.float_value > cooling_threshold.value.float_value)) { if (current_state.value.int_value != 2) { current_state.value = HOMEKIT_UINT8(2); homekit_characteristic_notify(¤t_state, current_state.value); - - coolerOn(); heaterOff(); - fanOff(); - fanOn(COOLER_FAN_DELAY); } } else { if (current_state.value.int_value != 0) { current_state.value = HOMEKIT_UINT8(0); homekit_characteristic_notify(¤t_state, current_state.value); - - coolerOff(); heaterOff(); - fanOff(); } } } void temperature_sensor_task(void *_args) { - sdk_os_timer_setfn(&fan_timer, fan_alarm, NULL); - - gpio_set_pullup(TEMPERATURE_SENSOR_PIN, false, false); - - gpio_enable(FAN_PIN, GPIO_OUTPUT); - gpio_enable(HEATER_PIN, GPIO_OUTPUT); - gpio_enable(COOLER_PIN, GPIO_OUTPUT); - - fanOff(); - heaterOff(); - coolerOff(); - float humidity_value, temperature_value; + + float humidity_value, temperature_value, temp_difference; while (1) { bool success = dht_read_float_data( - DHT_TYPE_DHT11, TEMPERATURE_SENSOR_PIN, + DHT_TYPE, TEMPERATURE_SENSOR_PIN, &humidity_value, &temperature_value ); if (success) { - printf("Got readings: temperature %g, humidity %g\n", temperature_value, humidity_value); + //printf("Got readings: temperature %g, humidity %g\n", temperature_value, humidity_value); current_temperature.value = HOMEKIT_FLOAT(temperature_value); current_humidity.value = HOMEKIT_FLOAT(humidity_value); homekit_characteristic_notify(¤t_temperature, current_temperature.value); homekit_characteristic_notify(¤t_humidity, current_humidity.value); - - update_state(); + //display_temperature(temperature_value, humidity_value); + temp_difference = current_temperature.value.float_value - target_temperature.value.float_value; + //printf("temp difference: %.2f\n",fabs(temp_difference)); + if (fabs(temp_difference) > TEMP_DIFF) { + //printf("updating state\n"); + update_state(); + } } else { printf("Couldnt read data from sensor\n"); } @@ -214,14 +213,13 @@ void thermostat_init() { xTaskCreate(temperature_sensor_task, "Thermostat", 256, NULL, 2, NULL); } - homekit_accessory_t *accessories[] = { HOMEKIT_ACCESSORY(.id=1, .category=homekit_accessory_category_thermostat, .services=(homekit_service_t*[]) { HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) { HOMEKIT_CHARACTERISTIC(NAME, "Thermostat"), HOMEKIT_CHARACTERISTIC(MANUFACTURER, "HaPK"), HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "001"), - HOMEKIT_CHARACTERISTIC(MODEL, "MyThermostat"), + HOMEKIT_CHARACTERISTIC(MODEL, "SmartThermostat"), HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "0.1"), HOMEKIT_CHARACTERISTIC(IDENTIFY, thermostat_identify), NULL @@ -247,12 +245,88 @@ homekit_server_config_t config = { .accessories = accessories, .password = "111-11-111" }; +static bool homekit_initialized = false; + +void on_wifi_config_event(wifi_config_event_t event) { + if (event == WIFI_CONFIG_CONNECTED) { + printf("WIFI_CONFIG_CONNECTED\n"); + if (!homekit_initialized) { + printf("Starting Homekit server...\n"); + homekit_server_init(&config); + homekit_initialized = true; + } + } +} +void button_up_callback(button_event_t event, void* context) { + // up button pressed + printf("Button up pressed\n"); + float newTargetTemp = target_temperature.value.float_value + 0.5; + target_temperature.value = HOMEKIT_FLOAT(newTargetTemp); + homekit_characteristic_notify(&target_temperature, target_temperature.value); + //display_temperature(current_temperature.value.float_value, current_humidity.value.float_value); +} + +void button_down_callback(button_event_t event, void* context) { + // down button pressed + printf("Button down pressed\n"); + float newTargetTemp = target_temperature.value.float_value - 0.5; + target_temperature.value = HOMEKIT_FLOAT(newTargetTemp); + homekit_characteristic_notify(&target_temperature, target_temperature.value); + //display_temperature(current_temperature.value.float_value, current_humidity.value.float_value); +} +void button_reset_callback(button_event_t event, void* context) { + // down button pressed + switch (event) { + case button_event_single_press: + printf("single press\n"); + break; + case button_event_double_press: + printf("double press\n"); + break; + case button_event_tripple_press: + printf("tripple press\n"); + break; + case button_event_long_press: + printf("long press\n"); + printf("Resetting Wifi Config\n"); + wifi_config_reset(); + printf("Resetting HomeKit Config\n"); + homekit_server_reset(); + printf("Restarting\n"); + sdk_system_restart(); + break; + } + +} +void gpio_init(){ + //gpio_set_pullup(TEMPERATURE_SENSOR_PIN, false, false); + gpio_enable(HEATER_PIN, GPIO_OUTPUT); + gpio_enable(BUTTON_DOWN_PIN, GPIO_INPUT); + gpio_enable(BUTTON_UP_PIN, GPIO_INPUT); + gpio_set_pullup(BUTTON_DOWN_PIN, true, true); + gpio_set_pullup(BUTTON_UP_PIN, true, true); + heaterOff(); +} void user_init(void) { uart_set_baud(0, 115200); - - wifi_init(); + gpio_init(); + wifi_config_init2("Thermostat", "mythermostat", on_wifi_config_event); thermostat_init(); - homekit_server_init(&config); + display_init(); + button_config_t buttonconfig = BUTTON_CONFIG( + button_active_low, + .long_press_time = 3000, + .max_repeat_presses = 3, + ); + if (button_create(BUTTON_UP_PIN, buttonconfig, button_up_callback, NULL)) { + printf("Failed to initialize button up\n"); + } + if (button_create(BUTTON_DOWN_PIN, buttonconfig, button_down_callback, NULL)) { + printf("Failed to initialize button down\n"); + } + if (button_create(BUTTON_RESET_PIN, buttonconfig, button_reset_callback, NULL)) { + printf("Failed to initialize button resetwn\n"); + } }