Using MQTT with esp-homekit
sam632 opened this issue ยท 5 comments
Hi, I am trying to combine MQTT with HomeKit to make a pair of friendship lamps, each with 2 LEDs, one controlled by HomeKit (and a button) and the other controlled by the other persons lamp. The MQTT code works on its own but for some reason when I combine with HomeKit it won't work. The phone will not connect to the device and after it tries for a while, the MQTT connection drops. I tried adding a vTaskSuspend to the on_password function but this doesn't seem to get called. Any help would be much appreciated. (I used maqiatto's free MQTT Broker).
#include <stdio.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 <string.h>
#include <paho_mqtt_c/MQTTESP8266.h>
#include <paho_mqtt_c/MQTTClient.h>
#include <semphr.h>
#include <homekit/homekit.h>
#include <homekit/characteristics.h>
#include "wifi.h"
#include "button.h"
#define MQTT_HOST ("maqiatto.com")
#define MQTT_PORT 1883
#define MQTT_USER ("myemail")
#define MQTT_PASS ("mypassword")
SemaphoreHandle_t wifi_alive;
QueueHandle_t publish_queue;
#define PUB_MSG_LEN 2
int led2_state = 0;
// The GPIO pin that is connected to the local LED
const int led1_gpio = 5; //D1
//The GPIO pin that is connected to the externally controlled LED
const int led2_gpio = 4; //D2
//The GPIO pin that is connected to the LED on the button
const int led3_gpio = 14; //D5
// The GPIO pin that is connected to the button on the WEMOS
const int button_gpio = 0; //D3 with internal pullup resistor
// Define callback functions
void switch_on_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context);
void button_callback(button_event_t event, void* context);
TaskHandle_t MQTTTask;
// Define LED functions
void led1_write(bool on) {
gpio_write(led1_gpio, on ? 1 : 0);
}
void led2_write(bool on) {
gpio_write(led2_gpio, on ? 1 : 0);
}
void led3_write(bool on) {
gpio_write(led3_gpio, on ? 1 : 0);
}
static void wifi_task(void *pvParameters) {
uint8_t status = 0;
uint8_t retries = 30;
struct sdk_station_config config = {
.ssid = WIFI_SSID,
.password = WIFI_PASSWORD,
};
printf("WiFi: connecting to WiFi\n\r");
sdk_wifi_set_opmode(STATION_MODE);
sdk_wifi_station_set_config(&config);
while(1)
{
while ((status != STATION_GOT_IP) && (retries)){
status = sdk_wifi_station_get_connect_status();
printf("%s: status = %d\n\r", __func__, status );
if( status == STATION_WRONG_PASSWORD ){
printf("WiFi: wrong password\n\r");
break;
} else if( status == STATION_NO_AP_FOUND ) {
printf("WiFi: AP not found\n\r");
break;
} else if( status == STATION_CONNECT_FAIL ) {
printf("WiFi: connection failed\r\n");
break;
}
vTaskDelay( 1000 / portTICK_PERIOD_MS );
--retries;
}
if (status == STATION_GOT_IP) {
printf("WiFi: Connected\n\r");
xSemaphoreGive( wifi_alive );
taskYIELD();
}
while ((status = sdk_wifi_station_get_connect_status()) == STATION_GOT_IP) {
xSemaphoreGive( wifi_alive );
taskYIELD();
}
printf("WiFi: disconnected\n\r");
sdk_wifi_station_disconnect();
vTaskDelay( 1000 / portTICK_PERIOD_MS );
}
}
void wifi_init() {
printf("Starting WiFi task\n");
xTaskCreate(&wifi_task, "wifi_task", 256, NULL, 2, NULL);
}
// For resetting the wifi
void reset_configuration_task() {
//Flash the LED first before we start the reset
for (int i=0; i<3; i++) {
led3_write(true);
vTaskDelay(100 / portTICK_PERIOD_MS);
led3_write(false);
vTaskDelay(100 / 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);
}
// Identifying the lamp with homekit by flashing the small LED
void lamp_identify_task(void *_args) {
// We identify the lamp by flashing an LED.
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
led3_write(true);
vTaskDelay(200 / portTICK_PERIOD_MS);
led3_write(false);
vTaskDelay(200 / portTICK_PERIOD_MS);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
led3_write(true);
vTaskDelete(NULL);
}
void lamp_identify(homekit_value_t _value) {
printf("Lamp identify\n");
xTaskCreate(lamp_identify_task, "Lamp identify", 128, NULL, 2, NULL);
}
// Homekit characteristic
homekit_characteristic_t switch_on = HOMEKIT_CHARACTERISTIC_(
ON, false, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(switch_on_callback)
);
// Initialise the GPIO pins for the LEDs
void gpio_init() {
gpio_enable(led1_gpio, GPIO_OUTPUT);
led1_write(switch_on.value.bool_value);
gpio_enable(led2_gpio, GPIO_OUTPUT);
led2_write(false);
gpio_enable(led3_gpio, GPIO_OUTPUT);
led3_write(true);
}
//Controls LED 2 using the MQTT message
static void led2_control(mqtt_message_data_t *md) {
int i;
mqtt_message_t *message = md->message;
int length = message->payloadlen;
char * payload = message->payload;
payload[length] = '\0';
printf("Received: ");
for( i = 0; i < md->topic->lenstring.len; ++i)
printf("%c", md->topic->lenstring.data[ i ]);
printf("\r\n");
// printf("The payload length is %i\n", length);
printf("Payload: %s\n", (char *)payload);
if(strcmp((char *)payload, "1") == 0) {
// Turn the LED on
led2_write(true);
printf("Turn LED 2 on due to MQTT message being 1\n");
}
// Check if message is False
if(strcmp((char *)payload, "0") == 0) {
// Turn the LED off
led2_write(false);
printf("Turn LED 2 off due to MQTT message being 0\n");
}
}
//To give the ESP a unique client id for MQTT
static const char * get_my_id(void) {
// Use MAC address for Station as unique ID
static char my_id[13];
static bool my_id_done = false;
int8_t i;
uint8_t x;
if (my_id_done)
return my_id;
if (!sdk_wifi_get_macaddr(STATION_IF, (uint8_t *)my_id))
return NULL;
for (i = 5; i >= 0; --i)
{
x = my_id[i] & 0x0F;
if (x > 9) x += 7;
my_id[i * 2 + 1] = x + '0';
x = my_id[i] >> 4;
if (x > 9) x += 7;
my_id[i * 2] = x + '0';
}
my_id[12] = '\0';
my_id_done = true;
return my_id;
}
//Connects to MQTT and publishes message
static void mqtt_task(void *pvParameters) {
int ret = 0;
struct mqtt_network network;
mqtt_client_t client = mqtt_client_default;
char mqtt_client_id[20];
uint8_t mqtt_buf[100];
uint8_t mqtt_readbuf[100];
mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer;
mqtt_network_new( &network );
memset(mqtt_client_id, 0, sizeof(mqtt_client_id));
strcpy(mqtt_client_id, "ESP-");
strcat(mqtt_client_id, get_my_id());
while(1) {
xSemaphoreTake(wifi_alive, portMAX_DELAY);
printf("%s: started\n\r", __func__);
printf("%s: (Re)connecting to MQTT server %s ... ",__func__,
MQTT_HOST);
ret = mqtt_network_connect(&network, MQTT_HOST, MQTT_PORT);
if( ret ){
printf("error: %d\n\r", ret);
taskYIELD();
continue;
}
printf("done\n\r");
mqtt_client_new(&client, &network, 5000, mqtt_buf, 100,
mqtt_readbuf, 100);
data.willFlag = 0;
data.MQTTVersion = 3;
data.clientID.cstring = mqtt_client_id;
data.username.cstring = MQTT_USER;
data.password.cstring = MQTT_PASS;
data.keepAliveInterval = 10;
data.cleansession = 0;
printf("Send MQTT connect ... ");
ret = mqtt_connect(&client, &data);
if(ret){
printf("error: %d\n\r", ret);
mqtt_network_disconnect(&network);
taskYIELD();
continue;
}
printf("done\r\n");
mqtt_subscribe(&client, "myemail/lamp21", MQTT_QOS1, led2_control);
xQueueReset(publish_queue);
while(1){
char msg[PUB_MSG_LEN - 1] = "\0";
while(xQueueReceive(publish_queue, (void *)msg, 0) ==
pdTRUE){
printf("Published to topic lamp1: %s\r\n", msg);
mqtt_message_t message;
message.payload = msg;
message.payloadlen = PUB_MSG_LEN;
message.dup = 0;
message.qos = MQTT_QOS1;
message.retained = 0;
ret = mqtt_publish(&client, "myemail/lamp1", &message);
if (ret != MQTT_SUCCESS ){
printf("error while publishing message: %d\n", ret );
break;
}
}
ret = mqtt_yield(&client, 1000);
if (ret == MQTT_DISCONNECTED)
break;
}
printf("Connection dropped, request restart\n\r");
mqtt_network_disconnect(&network);
taskYIELD();
}
}
void mqtt_init() {
printf("Starting MQTT task\n");
xTaskCreate(&mqtt_task, "mqtt_task", 1024, NULL, 4, &MQTTTask);
}
// Homekits control over LED
void switch_on_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) {
led1_write(switch_on.value.bool_value);
}
// Buttons control over LED and sending MQTT message
void button_callback(button_event_t event, void* context) {
char msg[PUB_MSG_LEN];
switch (event) {
case button_event_single_press:
printf("Toggling LED 1 due to button press\n");
switch_on.value.bool_value = !switch_on.value.bool_value;
led1_write(switch_on.value.bool_value);
homekit_characteristic_notify(&switch_on, switch_on.value);
printf("LED 1 state is %i\n", switch_on.value.bool_value); //led1_state is 1 or 0
snprintf(msg, PUB_MSG_LEN, "%i", switch_on.value.bool_value);
if (xQueueSend(publish_queue, (void *)msg, 0) == pdFALSE) {
printf("Publish queue overflow.\r\n");
}
break;
case button_event_double_press:
// read state of led2
printf("Toggling LED 2 due to button press\n");
led2_state = gpio_read(led2_gpio);
printf("LED 2 current state is %i.\n", led2_state); //LED 2 state is 1 or 0
led2_state = !led2_state;
printf("Changing LED 2 to state %i.\n", led2_state);
led2_write(led2_state);
break;
case button_event_long_press:
reset_configuration();
break;
default:
printf("Unknown button event\n");
}
}
void button_init() {
button_config_t button_config = BUTTON_CONFIG(
button_active_low, // This sets gpio_pullup on button pin
.long_press_time = 5000,
.max_repeat_presses = 2,
);
int r;
r = button_create(button_gpio, button_config, button_callback, NULL);
if (r) {
printf("Failed to initialize button\n");
}
}
// Homekit setup
homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, "Friendship Lamp");
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,
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Sam"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "SLMPSFL1"),
HOMEKIT_CHARACTERISTIC(MODEL, "Friendship Lamp"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "1.0.0"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, lamp_identify),
NULL
}),
HOMEKIT_SERVICE(SWITCH, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Friendship Lamp"),
&switch_on,
NULL
}),
NULL
}),
NULL
};
void on_password(const char *password) {
printf("Suspending MQTT Task\n");
vTaskSuspend(MQTTTask);
}
void on_homekit_event(homekit_event_t event) {
printf("Resuming MQTT Task\n");
vTaskResume(MQTTTask);
}
homekit_server_config_t config = {
.accessories = accessories,
.password = "137-22-976",
.setupId="2SA8",
.password_callback = on_password,
.on_event = on_homekit_event,
};
// Create different accessory name each time so no clashes
void create_accessory_name() {
uint8_t macaddr[6];
sdk_wifi_get_macaddr(STATION_IF, macaddr);
int name_len = snprintf(NULL, 0, "Friendship Lamp-%02X%02X%02X",
macaddr[3], macaddr[4], macaddr[5]);
char *name_value = malloc(name_len+1);
snprintf(name_value, name_len+1, "Friendship Lamp-%02X%02X%02X",
macaddr[3], macaddr[4], macaddr[5]);
name.value = HOMEKIT_STRING(name_value);
}
void user_init(void) {
uart_set_baud(0, 115200);
create_accessory_name();
vSemaphoreCreateBinary(wifi_alive);
publish_queue = xQueueCreate(3, PUB_MSG_LEN);
wifi_init();
mqtt_init();
gpio_init();
button_init();
homekit_server_init(&config);
}
I did not read your code, but I do use mqtt with my devices, so you can find some examples of using mqtt here https://github.com/lrusnac/esp-homekit-devices
hope it is useful
Thank you very much, I will look at this now :)
@lrusnac you are the first (to my knowledge) that you have brought together mqtt and esp-homekit.
How is stability and performance? Are you getting any sort of "no response" status in your devices?
@peros550 I doubt I'm the first, but I have a couple of devices running for 10 months now (based on my examples commits) and it works well so far, haven't noticed any issues.
I even have one esp that is a bridge between mqtt and homekit without any sensors or actuators attached, instead of running homebridge. Pretty stable, and fast.
Although keep in mind I'm sample size of 1 so if you end up using mqtt with esp-homekit, let us know what your experience is!
Worked a treat, here is my updated code for anyone interested.
#include <stdio.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 <string.h>
#include <paho_mqtt_c/MQTTESP8266.h>
#include <paho_mqtt_c/MQTTClient.h>
#include <semphr.h>
#include <homekit/homekit.h>
#include <homekit/characteristics.h>
#include <wifi_config.h>
#include "button.h"
#define MQTT_HOST ("maqiatto.com")
#define MQTT_PORT 1883
#define MQTT_USER ("username")
#define MQTT_PASS ("password")
#define MQTT_CMND_TOPIC "username/topic" //Controls LED 2
#define MQTT_SEND_TOPIC "username/topic" //Sends MQTT to control other lamp
QueueHandle_t publish_queue;
#define PUB_MSG_LEN 2
int led2_state = 0;
// The GPIO pin that is connected to the local LED
const int led1_gpio = 5; //D1
//The GPIO pin that is connected to the externally controlled LED
const int led2_gpio = 4; //D2
//The GPIO pin that is connected to the LED on the button
const int led3_gpio = 14; //D5
// The GPIO pin that is connected to the button on the WEMOS
const int button_gpio = 0; //D3 with internal pullup resistor
// Define callback functions
void switch_on_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context);
void button_callback(button_event_t event, void* context);
// Define LED functions
void led1_write(bool on) {
gpio_write(led1_gpio, on ? 1 : 0);
}
void led2_write(bool on) {
gpio_write(led2_gpio, on ? 1 : 0);
}
void led3_write(bool on) {
gpio_write(led3_gpio, on ? 1 : 0);
}
// For resetting the wifi
void reset_configuration_task() {
//Flash the LED first before we start the reset
for (int i=0; i<3; i++) {
led3_write(true);
vTaskDelay(100 / portTICK_PERIOD_MS);
led3_write(false);
vTaskDelay(100 / 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);
}
// Identifying the lamp with homekit by flashing the small LED
void lamp_identify_task(void *_args) {
// We identify the lamp by flashing an LED.
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
led3_write(true);
vTaskDelay(200 / portTICK_PERIOD_MS);
led3_write(false);
vTaskDelay(200 / portTICK_PERIOD_MS);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
led3_write(false);
vTaskDelete(NULL);
}
void lamp_identify(homekit_value_t _value) {
printf("Lamp identify\n");
xTaskCreate(lamp_identify_task, "Lamp identify", 128, NULL, 2, NULL);
}
// Homekit characteristic
homekit_characteristic_t switch_on = HOMEKIT_CHARACTERISTIC_(
ON, false, .callback=HOMEKIT_CHARACTERISTIC_CALLBACK(switch_on_callback)
);
// Initialise the GPIO pins for the LEDs
void gpio_init() {
gpio_enable(led1_gpio, GPIO_OUTPUT);
led1_write(switch_on.value.bool_value);
gpio_enable(led2_gpio, GPIO_OUTPUT);
led2_write(false);
gpio_enable(led3_gpio, GPIO_OUTPUT);
led3_write(false);
}
//Controls LED 2 using the MQTT message
static void led2_control(mqtt_message_data_t *md) {
int i;
mqtt_message_t *message = md->message;
int length = message->payloadlen;
char * payload = message->payload;
payload[length] = '\0';
printf("Received: ");
for( i = 0; i < md->topic->lenstring.len; ++i)
printf("%c", md->topic->lenstring.data[ i ]);
printf("\r\n");
// printf("The payload length is %i\n", length);
printf("Payload: %s\n", (char *)payload);
if(strncmp((char *)payload, "1", 1) == 0) {
// Turn the LED on
led2_write(true);
printf("Turn LED 2 on due to MQTT message being 1\n");
}
// Check if message is False
if(strncmp((char *)payload, "0", 1) == 0) {
// Turn the LED off
led2_write(false);
printf("Turn LED 2 off due to MQTT message being 0\n");
}
}
//To give the ESP a unique client id for MQTT
static const char * get_my_id(void) {
// Use MAC address for Station as unique ID
static char my_id[13];
static bool my_id_done = false;
int8_t i;
uint8_t x;
if (my_id_done)
return my_id;
if (!sdk_wifi_get_macaddr(STATION_IF, (uint8_t *)my_id))
return NULL;
for (i = 5; i >= 0; --i)
{
x = my_id[i] & 0x0F;
if (x > 9) x += 7;
my_id[i * 2 + 1] = x + '0';
x = my_id[i] >> 4;
if (x > 9) x += 7;
my_id[i * 2] = x + '0';
}
my_id[12] = '\0';
my_id_done = true;
return my_id;
}
//Connects to MQTT and publishes message
static void mqtt_task(void *pvParameters) {
int ret = 0;
struct mqtt_network network;
mqtt_client_t client = mqtt_client_default;
char mqtt_client_id[20];
uint8_t mqtt_buf[100];
uint8_t mqtt_readbuf[100];
mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer;
mqtt_network_new( &network );
memset(mqtt_client_id, 0, sizeof(mqtt_client_id));
strcpy(mqtt_client_id, "ESP-");
strcat(mqtt_client_id, get_my_id());
printf("MQTT client ID: %s\r\n", mqtt_client_id);
data.willFlag = 0;
data.MQTTVersion = 4;
data.clientID.cstring = mqtt_client_id;
data.username.cstring = MQTT_USER;
data.password.cstring = MQTT_PASS;
data.keepAliveInterval = 10;
data.cleansession = 0;
while(1) {
printf("%s: Started\n\r", __func__);
printf("%s: Connecting to MQTT server %s ... ",__func__, MQTT_HOST);
ret = mqtt_network_connect(&network, MQTT_HOST, MQTT_PORT);
if( ret ){
printf("Error: %d\n\r", ret);
taskYIELD();
vTaskDelay(100 / portTICK_PERIOD_MS);
continue;
}
printf("Done\n\r");
mqtt_client_new(&client, &network, 5000, mqtt_buf, 100, mqtt_readbuf, 100);
printf("Send MQTT connect ... ");
ret = mqtt_connect(&client, &data);
if(ret){
printf("Error: %d\n\r", ret);
mqtt_network_disconnect(&network);
taskYIELD();
continue;
}
printf("Done\r\n");
led3_write(true);
mqtt_subscribe(&client, MQTT_CMND_TOPIC, MQTT_QOS1, led2_control);
xQueueReset(publish_queue);
while(1){
char msg[PUB_MSG_LEN - 1] = "\0";
while(xQueueReceive(publish_queue, (void *)msg, 0) == pdTRUE) {
printf("Published to topic Blue: %s\r\n", msg);
led3_write(true); \\to check if MQTT is still connected
mqtt_message_t message;
message.payload = msg;
message.payloadlen = PUB_MSG_LEN;
message.dup = 0;
message.qos = MQTT_QOS1;
message.retained = 0;
ret = mqtt_publish(&client, MQTT_SEND_TOPIC, &message);
if (ret != MQTT_SUCCESS ){
printf("Error while publishing message: %d\n", ret );
break;
}
}
ret = mqtt_yield(&client, 1000);
if (ret == MQTT_DISCONNECTED)
break;
}
printf("Connection dropped, request restart\n\r");
led3_write(false); //Tells you MQTT has disconnected
mqtt_network_disconnect(&network);
taskYIELD();
}
}
// Homekits control over LED
void switch_on_callback(homekit_characteristic_t *_ch, homekit_value_t on, void *context) {
led1_write(switch_on.value.bool_value);
printf("LED 1 state is %i\n", switch_on.value.bool_value);
char msg[PUB_MSG_LEN];
snprintf(msg, PUB_MSG_LEN, "%i", switch_on.value.bool_value);
if (xQueueSend(publish_queue, (void *)msg, 0) == pdFALSE) {
printf("Publish queue overflow.\r\n");
}
}
// Buttons control over LED and sending MQTT message
void button_callback(button_event_t event, void* context) {
switch (event) {
case button_event_single_press:
printf("Toggling LED 1 due to button press\n");
switch_on.value.bool_value = !switch_on.value.bool_value;
led1_write(switch_on.value.bool_value);
homekit_characteristic_notify(&switch_on, switch_on.value); //This will update homekit and the MQTT topic
break;
case button_event_double_press:
// read state of led2
printf("Toggling LED 2 due to button press\n");
led2_state = gpio_read(led2_gpio);
printf("LED 2 current state is %i.\n", led2_state); //LED 2 state is 1 or 0
led2_state = !led2_state;
printf("Changing LED 2 to state %i.\n", led2_state);
led2_write(led2_state);
break;
case button_event_long_press:
reset_configuration();
break;
default:
printf("Unknown button event\n");
}
}
void button_init() {
button_config_t button_config = BUTTON_CONFIG(
button_active_low, // This sets gpio_pullup on button pin
.long_press_time = 5000,
.max_repeat_presses = 2,
);
int r;
r = button_create(button_gpio, button_config, button_callback, NULL);
if (r) {
printf("Failed to initialize button\n");
}
}
// Homekit setup
homekit_characteristic_t name = HOMEKIT_CHARACTERISTIC_(NAME, "Friendship Lamp");
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,
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Sam"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "SLMPSFL1"),
HOMEKIT_CHARACTERISTIC(MODEL, "Friendship Lamp"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "1.0.0"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, lamp_identify),
NULL
}),
HOMEKIT_SERVICE(SWITCH, .primary=true, .characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Friendship Lamp"),
&switch_on,
NULL
}),
NULL
}),
NULL
};
homekit_server_config_t config = {
.accessories = accessories,
.password = "111-11-111",
.setupId="2SA8",
};
void on_wifi_ready() {
homekit_server_init(&config);
xTaskCreate(&mqtt_task, "mqtt_task", 1024, NULL, 4, NULL);
}
// Create different accessory name each time so no clashes
void create_accessory_name() {
uint8_t macaddr[6];
sdk_wifi_get_macaddr(STATION_IF, macaddr);
int name_len = snprintf(NULL, 0, "Friendship Lamp-%02X%02X%02X",
macaddr[3], macaddr[4], macaddr[5]);
char *name_value = malloc(name_len+1);
snprintf(name_value, name_len+1, "Friendship Lamp-%02X%02X%02X",
macaddr[3], macaddr[4], macaddr[5]);
name.value = HOMEKIT_STRING(name_value);
}
void user_init(void) {
uart_set_baud(0, 115200);
create_accessory_name();
publish_queue = xQueueCreate(3, PUB_MSG_LEN);
wifi_config_init("Friendship Lamps -", NULL, on_wifi_ready);
gpio_init();
button_init();
}