Skip to content

Commit

Permalink
Home Accessory Architect v0.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
RavenSystem committed Oct 5, 2019
1 parent 6be50b7 commit 1eb2223
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 43 deletions.
181 changes: 139 additions & 42 deletions devices/HAA/main.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Home Accessory Architect
*
* v0.1.2
* v0.1.3
*
* Copyright 2019 José Antonio Jiménez Campos (@RavenSystem)
*
Expand Down Expand Up @@ -43,15 +43,20 @@
#include <cJSON.h>

// Version
#define FIRMWARE_VERSION "0.1.2"
#define FIRMWARE_VERSION_OCTAL 000102 // Matches as example: firmware_revision 2.3.8 = 02.03.10 (octal) = config_number 020310
#define FIRMWARE_VERSION "0.1.3"
#define FIRMWARE_VERSION_OCTAL 000103 // Matches as example: firmware_revision 2.3.8 = 02.03.10 (octal) = config_number 020310

// Characteristic types (ch_type)
#define CH_TYPE_BOOL 0
#define CH_TYPE_INT8 1
#define CH_TYPE_INT32 2
#define CH_TYPE_FLOAT 3

// Auto-off types (type)
#define TYPE_ON 0
#define TYPE_LOCK 1
#define TYPE_SENSOR 2

// Initial states
#define INIT_STATE_LAST 5
#define INIT_STATE_INV_LAST 6
Expand All @@ -66,6 +71,8 @@
#define ENABLE_HOMEKIT_SERVER "h"
#define ACCESSORIES "a"
#define BUTTONS_ARRAY "b"
#define FIXED_BUTTONS_ARRAY_0 "f0"
#define FIXED_BUTTONS_ARRAY_1 "f1"
#define BUTTON_PRESS_TYPE "t"
#define PULLUP_RESISTOR "p"
#define VALUE "v"
Expand All @@ -81,6 +88,7 @@
#define ACC_TYPE_OUTLET 2
#define ACC_TYPE_BUTTON 3
#define ACC_TYPE_LOCK 4
#define ACC_TYPE_CONTACT_SENSOR 5

#ifndef HAA_MAX_ACCESSORIES
#define HAA_MAX_ACCESSORIES 4 // Max number of accessories before use a bridge
Expand All @@ -96,6 +104,7 @@ typedef struct _autoswitch_params {

typedef struct _autooff_setter_params {
homekit_characteristic_t *ch;
uint8_t type;
double time;
} autooff_setter_params_t;

Expand Down Expand Up @@ -289,19 +298,15 @@ homekit_value_t hkc_getter(const homekit_characteristic_t *ch) {
return ch->value;
}

// --- ON
void hkc_on_setter(homekit_characteristic_t *ch, const homekit_value_t value);
void hkc_on_autooff_setter_task(void *pvParameters) {
autooff_setter_params_t *autooff_setter_params = pvParameters;

vTaskDelay(autooff_setter_params->time * 1000 / portTICK_PERIOD_MS);

hkc_on_setter(autooff_setter_params->ch, HOMEKIT_BOOL(false));

free(autooff_setter_params);
vTaskDelete(NULL);
void hkc_autooff_setter_task(void *pvParameters);

// --- KILL SWITCH ON
void hkc_kill_switch_on_setter(homekit_characteristic_t *ch, const homekit_value_t value) {
setup_mode_toggle_upcount();
save_states_callback();
}

// --- ON
void hkc_on_setter(homekit_characteristic_t *ch, const homekit_value_t value) {
ch_group_t *ch_group = ch_group_find(ch);
if (ch_group->ch_sec && !ch_group->ch_sec->value.bool_value) {
Expand All @@ -323,8 +328,9 @@ void hkc_on_setter(homekit_characteristic_t *ch, const homekit_value_t value) {
if (autoswitch_time > 0) {
autooff_setter_params_t *autooff_setter_params = malloc(sizeof(autooff_setter_params_t));
autooff_setter_params->ch = ch;
autooff_setter_params->type = TYPE_ON;
autooff_setter_params->time = autoswitch_time;
xTaskCreate(hkc_on_autooff_setter_task, "hkc_on_autooff_setter_task", configMINIMAL_STACK_SIZE, autooff_setter_params, 1, NULL);
xTaskCreate(hkc_autooff_setter_task, "hkc_autooff_setter_task", configMINIMAL_STACK_SIZE, autooff_setter_params, 1, NULL);
}
}

Expand All @@ -345,18 +351,6 @@ void button_on(const uint8_t gpio, void *args) {
}

// --- LOCK MECHANISM
void hkc_lock_setter(homekit_characteristic_t *ch, const homekit_value_t value);
void hkc_lock_autooff_setter_task(void *pvParameters) {
autooff_setter_params_t *autooff_setter_params = pvParameters;

vTaskDelay(autooff_setter_params->time * 1000 / portTICK_PERIOD_MS);

hkc_lock_setter(autooff_setter_params->ch, HOMEKIT_UINT8(1));

free(autooff_setter_params);
vTaskDelete(NULL);
}

void hkc_lock_setter(homekit_characteristic_t *ch, const homekit_value_t value) {
ch_group_t *ch_group = ch_group_find(ch);
if (ch_group->ch_sec && !ch_group->ch_sec->value.bool_value) {
Expand All @@ -380,8 +374,9 @@ void hkc_lock_setter(homekit_characteristic_t *ch, const homekit_value_t value)
if (autoswitch_time > 0) {
autooff_setter_params_t *autooff_setter_params = malloc(sizeof(autooff_setter_params_t));
autooff_setter_params->ch = ch;
autooff_setter_params->type = TYPE_LOCK;
autooff_setter_params->time = autoswitch_time;
xTaskCreate(hkc_lock_autooff_setter_task, "hkc_lock_autooff_setter_task", configMINIMAL_STACK_SIZE, autooff_setter_params, 1, NULL);
xTaskCreate(hkc_autooff_setter_task, "hkc_autooff_setter_task", configMINIMAL_STACK_SIZE, autooff_setter_params, 1, NULL);
}
}

Expand Down Expand Up @@ -442,6 +437,70 @@ void button_event3(const uint8_t gpio, void *args) {
}
}

// --- SENSOR
void sensor_on(const uint8_t gpio, void *args) {
homekit_characteristic_t *ch = args;

led_blink(1);
printf("HAA > Sensor activated\n");

ch->value = HOMEKIT_UINT8(1);
homekit_characteristic_notify(ch, ch->value);

cJSON *json_context = ch->context;

do_actions(json_context, (uint8_t) ch->value.int_value);

if (ch->value.bool_value && cJSON_GetObjectItem(json_context, AUTOSWITCH_TIME) != NULL) {
const double autoswitch_time = cJSON_GetObjectItem(json_context, AUTOSWITCH_TIME)->valuedouble;
if (autoswitch_time > 0) {
autooff_setter_params_t *autooff_setter_params = malloc(sizeof(autooff_setter_params_t));
autooff_setter_params->ch = ch;
autooff_setter_params->type = TYPE_SENSOR;
autooff_setter_params->time = autoswitch_time;
xTaskCreate(hkc_autooff_setter_task, "hkc_autooff_setter_task", configMINIMAL_STACK_SIZE, autooff_setter_params, 1, NULL);
}
}
}

void sensor_off(const uint8_t gpio, void *args) {
homekit_characteristic_t *ch = args;

led_blink(1);
printf("HAA > Sensor deactivated\n");

ch->value = HOMEKIT_UINT8(0);
homekit_characteristic_notify(ch, ch->value);

cJSON *json_context = ch->context;

do_actions(json_context, (uint8_t) ch->value.int_value);
}

// --- AUTO-OFF
void hkc_autooff_setter_task(void *pvParameters) {
autooff_setter_params_t *autooff_setter_params = pvParameters;

vTaskDelay(autooff_setter_params->time * 1000 / portTICK_PERIOD_MS);

switch (autooff_setter_params->type) {
case 1:
hkc_lock_setter(autooff_setter_params->ch, HOMEKIT_UINT8(1));
break;

case 2:
sensor_off(0, autooff_setter_params->ch);
break;

default: // case 0:
hkc_on_setter(autooff_setter_params->ch, HOMEKIT_BOOL(false));
break;
}

free(autooff_setter_params);
vTaskDelete(NULL);
}

// --- IDENTIFY
void identify(homekit_value_t _value) {
led_blink(6);
Expand Down Expand Up @@ -469,7 +528,7 @@ void run_homekit_server() {
}

// Buttons GPIO Setup
void buttons_setup(cJSON *json_buttons, void *callback, void *hk_ch) {
void buttons_setup(cJSON *json_buttons, void *callback, void *hk_ch, const bool run_at_launch) {
for(uint8_t j=0; j<cJSON_GetArraySize(json_buttons); j++) {
const uint8_t gpio = (uint8_t) cJSON_GetObjectItem(cJSON_GetArrayItem(json_buttons, j), PIN_GPIO)->valuedouble;
bool pullup_resistor = true;
Expand All @@ -494,7 +553,16 @@ void buttons_setup(cJSON *json_buttons, void *callback, void *hk_ch) {
used_gpio[gpio] = true;
}
adv_button_register_callback_fn(gpio, callback, button_type, hk_ch);

printf("HAA > Enable button GPIO %i, type=%i, inverted=%i\n", gpio, button_type, inverted);

if (run_at_launch) {
if (gpio_read(gpio) == button_type) {
typedef void (*button_callback_fn)(uint8_t gpio, void *args);
button_callback_fn run_callback = callback;
run_callback(gpio, hk_ch);
}
}
}
}

Expand Down Expand Up @@ -583,7 +651,7 @@ void normal_mode_init() {
}

// Buttons to enter setup mode
buttons_setup(cJSON_GetObjectItem(json_config, BUTTONS_ARRAY), setup_mode_call, NULL);
buttons_setup(cJSON_GetObjectItem(json_config, BUTTONS_ARRAY), setup_mode_call, NULL, false);

// ----- END CONFIG SECTION

Expand All @@ -596,6 +664,7 @@ void normal_mode_init() {
acc_type = (uint8_t) cJSON_GetObjectItem(cJSON_GetArrayItem(json_accessories, i), ACCESSORY_TYPE)->valuedouble;
}

// Kill Switch Accessory count
if (cJSON_GetObjectItem(cJSON_GetArrayItem(json_accessories, i), KILL_SWITCH) != NULL) {
const uint8_t kill_switch = (uint8_t) cJSON_GetObjectItem(cJSON_GetArrayItem(json_accessories, i), KILL_SWITCH)->valuedouble;
switch (kill_switch) {
Expand All @@ -613,6 +682,7 @@ void normal_mode_init() {
}
}

// Accessory Type Accessory count
switch (acc_type) {
default:
hk_total_ac += 1;
Expand Down Expand Up @@ -738,7 +808,7 @@ void normal_mode_init() {
homekit_characteristic_t *new_kill_switch(const uint8_t accessory, cJSON *json_context) {
new_accessory(accessory, 3);

homekit_characteristic_t *ch = NEW_HOMEKIT_CHARACTERISTIC(ON, false, .getter_ex=hkc_getter, .context=json_context);
homekit_characteristic_t *ch = NEW_HOMEKIT_CHARACTERISTIC(ON, false, .getter_ex=hkc_getter, .setter_ex=hkc_kill_switch_on_setter, .context=json_context);

accessories[accessory]->services[1] = calloc(1, sizeof(homekit_service_t));
accessories[accessory]->services[1]->id = 8;
Expand Down Expand Up @@ -797,13 +867,13 @@ void normal_mode_init() {
accessories[accessory]->services[1]->characteristics = calloc(2, sizeof(homekit_characteristic_t*));
accessories[accessory]->services[1]->characteristics[0] = ch0;

buttons_setup(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), button_on, (void*) ch0);
buttons_setup(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), button_on, (void*) ch0, false);

const uint8_t new_accessory = build_kill_switches(accessory + 1, ch_group, json_context);
const uint8_t new_accessory_count = build_kill_switches(accessory + 1, ch_group, json_context);

hkc_on_setter(ch0, HOMEKIT_BOOL((bool) set_initial_state(accessory, 0, json_context, ch0, CH_TYPE_BOOL, 0)));

return new_accessory;
return new_accessory_count;
}

uint8_t new_outlet(uint8_t accessory, cJSON *json_context) {
Expand All @@ -825,13 +895,13 @@ void normal_mode_init() {
accessories[accessory]->services[1]->characteristics[0] = ch0;
accessories[accessory]->services[1]->characteristics[1] = NEW_HOMEKIT_CHARACTERISTIC(OUTLET_IN_USE, true, .getter_ex=hkc_getter, .context=json_context);;

buttons_setup(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), button_on, (void*) ch0);
buttons_setup(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), button_on, (void*) ch0, false);

const uint8_t new_accessory = build_kill_switches(accessory + 1, ch_group, json_context);
const uint8_t new_accessory_count = build_kill_switches(accessory + 1, ch_group, json_context);

hkc_on_setter(ch0, HOMEKIT_BOOL((bool) set_initial_state(accessory, 0, json_context, ch0, CH_TYPE_BOOL, 0)));

return new_accessory ;
return new_accessory_count;
}

uint8_t new_button(uint8_t accessory, cJSON *json_context) {
Expand All @@ -854,9 +924,9 @@ void normal_mode_init() {

buttons_setup_programable(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), (void*) ch0);

const uint8_t new_accessory = build_kill_switches(accessory + 1, ch_group, json_context);
const uint8_t new_accessory_count = build_kill_switches(accessory + 1, ch_group, json_context);

return new_accessory;
return new_accessory_count;
}

uint8_t new_lock(const uint8_t accessory, cJSON *json_context) {
Expand All @@ -880,13 +950,31 @@ void normal_mode_init() {
accessories[accessory]->services[1]->characteristics[0] = ch0;
accessories[accessory]->services[1]->characteristics[1] = ch1;

buttons_setup(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), button_lock, (void*) ch1);
buttons_setup(cJSON_GetObjectItem(json_context, BUTTONS_ARRAY), button_lock, (void*) ch1, false);

const uint8_t new_accessory = build_kill_switches(accessory + 1, ch_group, json_context);
const uint8_t new_accessory_count = build_kill_switches(accessory + 1, ch_group, json_context);

hkc_lock_setter(ch1, HOMEKIT_UINT8((uint8_t) set_initial_state(accessory, 0, json_context, ch1, CH_TYPE_INT8, 1)));

return new_accessory;
return new_accessory_count;
}

uint8_t new_contact_sensor(const uint8_t accessory, cJSON *json_context) {
new_accessory(accessory, 3);

homekit_characteristic_t *ch0 = NEW_HOMEKIT_CHARACTERISTIC(CONTACT_SENSOR_STATE, 0, .getter_ex=hkc_getter, .context=json_context);

accessories[accessory]->services[1] = calloc(1, sizeof(homekit_service_t));
accessories[accessory]->services[1]->id = 8;
accessories[accessory]->services[1]->type = HOMEKIT_SERVICE_CONTACT_SENSOR;
accessories[accessory]->services[1]->primary = true;
accessories[accessory]->services[1]->characteristics = calloc(2, sizeof(homekit_characteristic_t*));
accessories[accessory]->services[1]->characteristics[0] = ch0;

buttons_setup(cJSON_GetObjectItem(json_context, FIXED_BUTTONS_ARRAY_0), sensor_off, (void*) ch0, true);
buttons_setup(cJSON_GetObjectItem(json_context, FIXED_BUTTONS_ARRAY_1), sensor_on, (void*) ch0, true);

return accessory + 1;
}

// Accessory Builder
Expand Down Expand Up @@ -935,10 +1023,16 @@ void normal_mode_init() {
printf("HAA > Accessory type=%i\n", acc_type);
if (acc_type == ACC_TYPE_OUTLET) {
acc_count = new_outlet(acc_count, json_accessory);

} else if (acc_type == ACC_TYPE_BUTTON) {
acc_count = new_button(acc_count, json_accessory);

} else if (acc_type == ACC_TYPE_LOCK) {
acc_count = new_lock(acc_count, json_accessory);

} else if (acc_type == ACC_TYPE_CONTACT_SENSOR) {
acc_count = new_contact_sensor(acc_count, json_accessory);

} else { // case ACC_TYPE_SWITCH:
acc_count = new_switch(acc_count, json_accessory);
}
Expand Down Expand Up @@ -966,6 +1060,9 @@ void normal_mode_init() {
void user_init(void) {
sysparam_status_t status;
bool haa_setup = false;

//sysparam_set_bool("setup", true);; // Force to enter always in setup mode. Only for tests. Keep comment for releases

status = sysparam_get_bool("setup", &haa_setup);
if (status == SYSPARAM_OK && haa_setup == true) {
uart_set_baud(0, 115200);
Expand Down
3 changes: 2 additions & 1 deletion external_libs/wifi_config_haa/content/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
.field.required label::before {content: "*"; color: red;}
</style></head>
<body><div class="container">
<h1>Home Accessory Architect v0.1.2</h1>
<h1>Home Accessory Architect v0.1.3</h1>
<form action="/settings" method="get">
<input type="submit" id="refresh" value="⟲ Refresh" />
</form>
Expand All @@ -57,6 +57,7 @@ <h1>Home Accessory Architect v0.1.2</h1>
<br>
<input type="checkbox" name="reset" value="y"> Reset HomeKit ID<br>
<!-- part HTML_SETTINGS_OTA --><input type="checkbox" name="ota" value="y"> OTA Update<br>
<input type="checkbox" name="autoota" value="y" <!-- part HTML_SETTINGS_AUTOOTA -->> Auto OTA Updates<br>
<!-- part HTML_SETTINGS_POSTOTA --></div>
<input type="submit" id="join" value="Save" />
<div class="nonetworks" style="display: none;">
Expand Down
Loading

0 comments on commit 1eb2223

Please sign in to comment.