maximkulkin / esp-homekit-demo

Demo of Apple HomeKit accessory server library
MIT License
808 stars 233 forks source link

help with "make flash monitor" #365

Closed renandw closed 4 years ago

renandw commented 4 years ago

Hello. I am working on a code that allows me to control 4 relays controlled by an individual toggle, and a button to reset configuration. But for some reason, the logs, when I use "make flash monitor", stops. But I can configure wifi, pair it to HomeKit and everything. But some bugs show up and I can't see why.

#include <stdio.h>
#include <stdlib.h>
#include <espressif/esp_wifi.h>
#include <espressif/esp_sta.h>
#include <espressif/esp_common.h>
#include <esp/uart.h>
#include <esp8266.h>
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <string.h>

#include <homekit/homekit.h>
#include <homekit/characteristics.h>
#include <wifi_config.h>

#include <button.h>
#include <toggle.h>
#include "led_status.h"
#include "config.h"

// The GPIO pin that is connected to RELAY#1 on the board.
const int relay_gpio_1 = 1;
// The GPIO pin that is connected to RELAY#2 on the board.
const int relay_gpio_2 = 3;
// The GPIO pin that is connected to RELAY#3 on the board.
const int relay_gpio_3 = 13;
// The GPIO pin that is connected to RELAY#4 on the board.
const int relay_gpio_4 = 16;

// The GPIO pin that is connected to the LED on the ESP12F.
const int led_gpio = LED_GPIO;

// The GPIO pin that is connected to the button on the Board.
#define BUTTON_PIN 0
#ifndef BUTTON_PIN
#error BUTTON_PIN is not specified
#endif

// The GPIO pin that is connected to the header on the board(external switch).
#define TOGGLE_PIN_1 5
#ifndef TOGGLE_PIN_1
#error TOGGLE_PIN_1 is not specified
#endif

#define TOGGLE_PIN_2 4
#ifndef TOGGLE_PIN_2
#error TOGGLE_PIN_2 is not specified
#endif

#define TOGGLE_PIN_3 14
#ifndef TOGGLE_PIN_3
#error TTOGGLE_PIN_3 is not specified
#endif

#define TOGGLE_PIN_4 12
#ifndef TOGGLE_PIN_4
#error TOGGLE_PIN_4 is not specified
#endif

// NOVO
// one short blink every 3 seconds
led_status_pattern_t mode_normal = LED_STATUS_PATTERN({100, -2900});
// two short blinks every 3 seconds
led_status_pattern_t mode_connecting_to_wifi = LED_STATUS_PATTERN({100, -100, 100, -2700});
// long blink, long wait
led_status_pattern_t mode_no_wifi_config = LED_STATUS_PATTERN({2000, -2000});
// short blink, long blink, long wait
led_status_pattern_t mode_unpaired = LED_STATUS_PATTERN({100, -100, 800, -1000});

// three short blinks
led_status_pattern_t mode_reset = LED_STATUS_PATTERN({100, -100, 100, -100, 100, -4500});
// three series of two short blinks
led_status_pattern_t mode_identify = LED_STATUS_PATTERN({ 100, -100, 100, -350, 100, -100, 100, -350, 100, -100, 100, -2500});

static led_status_t status;

void lightbulb_on_1_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context);
void lightbulb_on_2_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context);
void lightbulb_on_3_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context);
void lightbulb_on_4_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context);

void relay_write_1(bool on) {
    gpio_write(relay_gpio_1, on ? 0 : 1);
}

void relay_write_2(bool on) {
    gpio_write(relay_gpio_2, on ? 0 : 1);
}

void relay_write_3(bool on) {
    gpio_write(relay_gpio_3, on ? 0 : 1);
}

void relay_write_4(bool on) {
    gpio_write(relay_gpio_4, on ? 0 : 1);
}

//NOVO
void reset_configuration_task() {
    // Flash the LED first before we start the reset
    led_status_signal(status, &mode_reset);
    vTaskDelay(500 / portTICK_PERIOD_MS);

    printf("Resetting Wifi Config\n");
    wifi_config_reset();

    vTaskDelay(1000 / portTICK_PERIOD_MS);

    printf("Resetting HomeKit Config\n");
    homekit_server_reset();

    vTaskDelay(1000 / portTICK_PERIOD_MS);

    printf("Restarting\n");
    sdk_system_restart();

    vTaskDelete(NULL);
}

void reset_configuration() {
    printf("Resetting configuration\n");
    xTaskCreate(reset_configuration_task, "Reset configuration", 256, NULL, 2, NULL);
}

homekit_characteristic_t lightbulb_on_1 = HOMEKIT_CHARACTERISTIC_(
    ON, false, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(lightbulb_on_1_callback)
);

homekit_characteristic_t lightbulb_on_2 = HOMEKIT_CHARACTERISTIC_(
    ON, false, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(lightbulb_on_2_callback)
);

homekit_characteristic_t lightbulb_on_3 = HOMEKIT_CHARACTERISTIC_(
    ON, false, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(lightbulb_on_3_callback)
);

homekit_characteristic_t lightbulb_on_4 = HOMEKIT_CHARACTERISTIC_(
    ON, false, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(lightbulb_on_4_callback)
);

void gpio_init() {

  gpio_enable(relay_gpio_1, GPIO_OUTPUT);
    relay_write_1(lightbulb_on_1.value.bool_value);

    gpio_enable(relay_gpio_2, GPIO_OUTPUT);
    relay_write_2(lightbulb_on_2.value.bool_value);

    gpio_enable(relay_gpio_3, GPIO_OUTPUT);
    relay_write_3(lightbulb_on_3.value.bool_value);

    gpio_enable(relay_gpio_4, GPIO_OUTPUT);
    relay_write_4(lightbulb_on_4.value.bool_value);

    gpio_enable(BUTTON_PIN,  GPIO_INPUT);
    gpio_enable(TOGGLE_PIN_1, GPIO_INPUT);
    gpio_enable(TOGGLE_PIN_2, GPIO_INPUT);
    gpio_enable(TOGGLE_PIN_3, GPIO_INPUT);
    gpio_enable(TOGGLE_PIN_4, GPIO_INPUT);
}

void lightbulb_on_1_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) {
    relay_write_1(lightbulb_on_1.value.bool_value);
}

void lightbulb_on_2_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) {
    relay_write_2(lightbulb_on_2.value.bool_value);
}

void lightbulb_on_3_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) {
    relay_write_3(lightbulb_on_3.value.bool_value);
}

void lightbulb_on_4_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) {
    relay_write_4(lightbulb_on_4.value.bool_value);
}

void button_callback(button_event_t event, void* context) {
    switch (event) {
        case button_event_long_press:
            reset_configuration();
            break;
        default:
            printf("Unknown button event: %d\n", event);
    }
}

void toggle_callback_1(bool high, void *context) {
    printf("Toggling relay 1");
    lightbulb_on_1.value.bool_value = !lightbulb_on_1.value.bool_value;
    relay_write_1(lightbulb_on_1.value.bool_value);
    homekit_characteristic_notify(&lightbulb_on_1, lightbulb_on_1.value);
}

void toggle_callback_2(bool high, void *context) {
    printf("Toggling relay 2");
    lightbulb_on_2.value.bool_value = !lightbulb_on_2.value.bool_value;
    relay_write_2(lightbulb_on_2.value.bool_value);
    homekit_characteristic_notify(&lightbulb_on_2, lightbulb_on_2.value);
}

void toggle_callback_3(bool high, void *context) {
    printf("Toggling relay 3");
    lightbulb_on_3.value.bool_value = !lightbulb_on_3.value.bool_value;
    relay_write_3(lightbulb_on_3.value.bool_value);
    homekit_characteristic_notify(&lightbulb_on_3, lightbulb_on_3.value);
}

void toggle_callback_4(bool high, void *context) {
    printf("Toggling relay 4");
    lightbulb_on_4.value.bool_value = !lightbulb_on_4.value.bool_value;
    relay_write_4(lightbulb_on_4.value.bool_value);
    homekit_characteristic_notify(&lightbulb_on_4, lightbulb_on_4.value);
}

void light_identify(homekit_value_t _value) {
    printf("Light identify\n");
    led_status_signal(status, &mode_identify);
}

homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, "4 Lâmpadas");
homekit_characteristic_t serial = HOMEKIT_CHARACTERISTIC_(SERIAL_NUMBER, 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*[]){
            HOMEKIT_CHARACTERISTIC(IDENTIFY, light_identify),
            HOMEKIT_CHARACTERISTIC(MANUFACTURER, "renandw"),
            HOMEKIT_CHARACTERISTIC(MODEL, "4chrelay"),
            &name,
            &serial,
            HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "3.0"),
            HOMEKIT_CHARACTERISTIC(HARDWARE_REVISION, "2.0"),
            NULL
        },
        ),

        HOMEKIT_SERVICE(LIGHTBULB, .primary=true, .characteristics=(homekit_characteristic_t*[]){
        HOMEKIT_CHARACTERISTIC(NAME, "Lâmpada 1"),
        &lightbulb_on_1,
            NULL
        }),

        HOMEKIT_SERVICE(LIGHTBULB, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Lâmpada 2"),
            &lightbulb_on_2,
            NULL
        }),

        HOMEKIT_SERVICE(LIGHTBULB, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Lâmpada 3"),
            &lightbulb_on_3,
            NULL
        }),

        HOMEKIT_SERVICE(LIGHTBULB, .characteristics=(homekit_characteristic_t*[]){
            HOMEKIT_CHARACTERISTIC(NAME, "Lâmpada 4"),
            &lightbulb_on_4,
            NULL
        }),
        NULL
    }),
    NULL
};

//homekit_server_config_t config = {
//    .accessories = accessories,
//    .password = "736-24-212",
//    .setupId="7EN2",
//};

void on_homekit_event(homekit_event_t event) {
    if (event == HOMEKIT_EVENT_PAIRING_ADDED) {
        led_status_set(status, &mode_normal);
    } else if (event == HOMEKIT_EVENT_PAIRING_REMOVED) {
        if (!homekit_is_paired()) {
            led_status_set(status, &mode_unpaired);
        }
    }
}

static bool initialized = false;
homekit_server_config_t config = {
    .accessories = accessories,
    .password = ACCESSORY_SETUP_CODE,
    .setupId="1QJ8",
    .on_event = on_homekit_event,
};

void on_wifi_config_event(wifi_config_event_t event) {
    if (event == WIFI_CONFIG_CONNECTED && !initialized) {
        if (!initialized) {
            homekit_server_init(&config);

            initialized = true;

            led_status_set(status, homekit_is_paired() ? &mode_normal : &mode_unpaired);
        }
    }
}

void create_accessory_name() {
    uint8_t macaddr[6];
    sdk_wifi_get_macaddr(STATION_IF, macaddr);

    int name_len = snprintf(NULL, 0, "4Lâmpadas-%02X%02X%02X",
                            macaddr[3], macaddr[4], macaddr[5]);
    char *name_value = malloc(name_len+1);
    snprintf(name_value, name_len+1, "4Lâmpadas-%02X%02X%02X",
             macaddr[3], macaddr[4], macaddr[5]);

    name.value = HOMEKIT_STRING(name_value);

    char *serial_value = malloc(13);
    snprintf(serial_value, 13, "%02X%02X%02X%02X%02X%02X", macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
    serial.value = HOMEKIT_STRING(serial_value);
}

bool wifi_is_configured() {
    char *ssid = NULL;
    wifi_config_get(&ssid, NULL);
    if (!ssid)
        return false;

    free(ssid);
    return true;
}

void user_init(void) {
    uart_set_baud(0, 115200);
    create_accessory_name();
    gpio_init();
    status = led_status_init(led_gpio, LED_ACTIVE_LEVEL);

    button_config_t config = BUTTON_CONFIG(
        button_active_low,
        .long_press_time = 3000,
        .max_repeat_presses = 3,
    );

    if (button_create(BUTTON_PIN, config, button_callback, NULL)) {
        printf("Failed to initialize button\n");
    }

    if (toggle_create(TOGGLE_PIN_1, toggle_callback_1, NULL)) {
        printf("Failed to initialize toggle 1 \n");
    }

    if (toggle_create(TOGGLE_PIN_2, toggle_callback_2, NULL)) {
        printf("Failed to initialize toggle 2 \n");
    }

    if (toggle_create(TOGGLE_PIN_3, toggle_callback_3, NULL)) {
        printf("Failed to initialize toggle 3 \n");
    }

    if (toggle_create(TOGGLE_PIN_4, toggle_callback_4, NULL)) {
        printf("Failed to initialize toggle 4 \n");
    }

    led_status_set(status, wifi_is_configured() ? &mode_connecting_to_wifi : &mode_no_wifi_config);
    wifi_config_init2(WIFI_AP_NAME, WIFI_AP_PASSWORD, on_wifi_config_event);
}
pi@raspberrypi:~/projects/esp-homekit-demo/examples/4lampadas $ make erase_flash flash monitor
esptool.py -p /dev/ttyUSB0 --baud 115200 erase_flash
esptool.py v1.2
Connecting...
Running Cesanta flasher stub...
Erasing flash (this may take a while)...
Erase took 11.1 seconds
esptool.py -p /dev/ttyUSB0 --baud 115200 write_flash -fs 8m -fm dout -ff 40m \
    0x0 /home/pi/projects/esp-open-rtos/bootloader/firmware_prebuilt/rboot.bin 0x1000 /home/pi/projects/esp-open-rtos/bootloader/firmware_prebuilt/blank_config.bin 0x2000 ./firmware/4lampadas.bin
esptool.py v1.2
Connecting...
Running Cesanta flasher stub...
Flash params set to 0x0320
Writing 4096 @ 0x0... 4096 (100 %)
Wrote 4096 bytes at 0x0 in 0.4 seconds (89.2 kbit/s)...
Writing 4096 @ 0x1000... 4096 (100 %)
Wrote 4096 bytes at 0x1000 in 0.4 seconds (89.0 kbit/s)...
Writing 454656 @ 0x2000... 454656 (100 %)
Wrote 454656 bytes at 0x2000 in 39.4 seconds (92.2 kbit/s)...
Leaving...
/home/pi/projects/esp-open-rtos//utils/filteroutput.py --port /dev/ttyUSB0 --baud 115200 --elf ./build/4lampadas.out
Opening /dev/ttyUSB0 at 115200bps...

the Makefile is here

PROGRAM = 4lampadas

EXTRA_COMPONENTS = \
        extras/http-parser \
        extras/dhcpserver \
  $(abspath ../../components/common/button) \
        $(abspath ../../components/esp8266-open-rtos/wifi_config) \
        $(abspath ../../components/esp8266-open-rtos/cJSON) \
        $(abspath ../../components/common/wolfssl) \
        $(abspath ../../components/common/homekit)

FLASH_SIZE ?= 8
FLASH_MODE ?= dout
FLASH_SPEED ?= 40
HOMEKIT_SPI_FLASH_BASE_ADDR ?= 0x7A000

EXTRA_CFLAGS += -I../.. -DHOMEKIT_SHORT_APPLE_UUIDS

include $(SDK_PATH)/common.mk

monitor:
        $(FILTEROUTPUT) --port $(ESPPORT) --baud 115200 --elf $(PROGRAM_OUT)

is something that I am forgetting? thanks

maximkulkin commented 4 years ago

You're using GPIO 1 and 3 to control your relays, but they are part of UART0 interface which is used to communicate with the board over USB. The moment you do gpio_enable() on those your serial interface stops working. IMO it's OK to use GPIO3 since people rarely transmit something to MCU, but GPIO1 should not be used.

This is a pretty tight setup but doable. I've done 4-button-4-relays firmwares in the past and here is my GPIO config: buttons = [0, 2, 4, 5], relays = [12, 13, 14, 16]. I haven't done a reset button though, but you can do the following: use GPIO 0 as reset/control button and use GPIO 3 as one of button inputs.

Generally, there is a good article on what pins can be used where, which you can easily google with "esp8266 what pins to use".

renandw commented 4 years ago

Thanks a lot @maximkulkin. I made those changes and not only the logs are fine, but the bugs are also gone. Thanks for the help