Skip to content

Commit 2e4fb84

Browse files
committed
Implemented regular and long press handling for switches
Made virtual devices behave like regular ZWAVE sensors
1 parent ef3cdb7 commit 2e4fb84

File tree

13 files changed

+335
-190
lines changed

13 files changed

+335
-190
lines changed

BuiltinServices/SensorEvent.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "stack.h"
55
#include "../data_callbacks.h"
66
#include "../command_class.h"
7+
#include "../vdev_manager.h"
78

89
extern ZWay zway;
910
USING_LOGGER(BuiltinService)
@@ -109,16 +110,37 @@ variant_t* event_device_value_impl(struct service_method_t* method, va_list arg
109110

110111
if(NULL != event_data_variant)
111112
{
113+
command_class_t* cmd_class = NULL;
112114
sensor_event_data_t* event_data = (sensor_event_data_t*)variant_get_ptr(event_data_variant);
113-
zdata_acquire_lock(ZDataRoot(zway));
114-
//ZDataHolder dh = zdata_find(event_data->data_holder, variant_get_string(path_variant));
115+
device_record_t* device_record = resolver_resolve_id(event_data->node_id, event_data->instance_id, event_data->command_id);
115116

116-
ZDataHolder dh = zway_find_device_instance_cc_data(zway, event_data->node_id, event_data->instance_id, event_data->command_id, variant_get_string(path_variant));
117-
118-
variant_t* result = command_class_extract_data(dh);
119-
zdata_release_lock(ZDataRoot(zway));
117+
if(NULL != device_record && device_record->devtype == VDEV)
118+
{
119+
cmd_class = vdev_manager_get_command_class(event_data->node_id);
120+
}
121+
else
122+
{ /*
123+
zdata_acquire_lock(ZDataRoot(zway));
124+
//ZDataHolder dh = zdata_find(event_data->data_holder, variant_get_string(path_variant));
125+
126+
ZDataHolder dh = zway_find_device_instance_cc_data(zway, event_data->node_id, event_data->instance_id, event_data->command_id, variant_get_string(path_variant));
127+
128+
variant_t* result = command_class_extract_data(dh);
129+
zdata_release_lock(ZDataRoot(zway));
120130
121-
return result;
131+
return result;
132+
*/
133+
cmd_class = get_command_class_by_id(event_data->command_id);
134+
}
135+
136+
if(NULL != cmd_class)
137+
{
138+
return command_class_exec(cmd_class, "Get", device_record, variant_get_string(path_variant));
139+
}
140+
else
141+
{
142+
LOG_ERROR(BuiltinService, "Command class not handled: %d", event_data->command_id);
143+
}
122144
}
123145
else
124146
{

cli_rest.c

Lines changed: 103 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -144,51 +144,65 @@ void vdev_enumerate(device_record_t* record, void* arg)
144144

145145
json_object* cmd_value = json_object_new_object();
146146
command_class_t* vdev_cmd_class = vdev_manager_get_command_class(record->nodeId);
147-
variant_t* value = command_class_exec(vdev_cmd_class, vdev_command->name, record);
148-
char* string_value;
149-
variant_to_string(value, &string_value);
150147

151-
if(NULL == vdev_command->data_holder)
148+
// Get device record
149+
device_record_t* device_record = resolver_resolve_id(record->nodeId, 0, vdev_command->command_id);
150+
151+
152+
if(NULL == device_record)
152153
{
153-
// The string value is json string to be appended directly under "dh" key
154-
json_object_put(cmd_value);
155-
cmd_value = json_tokener_parse(string_value);
154+
// We dont have resolver entry for this command class. Lets query the root device
155+
device_record = record;
156156
}
157-
else if(strchr(vdev_command->data_holder, '.') != NULL)
158-
{
159-
json_object* parameter_array = json_object_new_array();
160-
char* data_holder = strdup(vdev_command->data_holder);
161-
char* saveptr;
162-
char* tok = strtok_r(data_holder, ".", &saveptr);
163-
json_object* dh_item = json_object_new_object();
164157

165-
if(NULL != tok)
158+
if(NULL != device_record)
159+
{
160+
variant_t* value = command_class_exec(vdev_cmd_class, vdev_command->name, device_record);
161+
char* string_value;
162+
variant_to_string(value, &string_value);
163+
164+
if(NULL == vdev_command->data_holder)
165+
{
166+
// The string value is json string to be appended directly under "dh" key
167+
json_object_put(cmd_value);
168+
cmd_value = json_tokener_parse(string_value);
169+
}
170+
else if(strchr(vdev_command->data_holder, '.') != NULL)
166171
{
172+
json_object* parameter_array = json_object_new_array();
173+
char* data_holder = strdup(vdev_command->data_holder);
174+
char* saveptr;
175+
char* tok = strtok_r(data_holder, ".", &saveptr);
176+
json_object* dh_item = json_object_new_object();
177+
178+
if(NULL != tok)
179+
{
180+
181+
json_object_object_add(dh_item, "data_holder", json_object_new_string(tok));
182+
}
183+
184+
tok = strtok_r(NULL, ".", &saveptr);
185+
186+
if(NULL != tok)
187+
{
188+
json_object_object_add(dh_item, tok, json_object_new_string(string_value));
189+
}
167190

168-
json_object_object_add(dh_item, "data_holder", json_object_new_string(tok));
191+
json_object_array_add(parameter_array, dh_item);
192+
json_object_object_add(cmd_value, "parameters", parameter_array);
193+
free(data_holder);
169194
}
170-
171-
tok = strtok_r(NULL, ".", &saveptr);
172-
173-
if(NULL != tok)
195+
else
174196
{
175-
json_object_object_add(dh_item, tok, json_object_new_string(string_value));
197+
198+
json_object_object_add(cmd_value, vdev_command->data_holder, json_object_new_string(string_value));
176199
}
177200

178-
json_object_array_add(parameter_array, dh_item);
179-
json_object_object_add(cmd_value, "parameters", parameter_array);
180-
free(data_holder);
181-
}
182-
else
183-
{
184-
185-
json_object_object_add(cmd_value, vdev_command->data_holder, json_object_new_string(string_value));
186-
}
187-
188-
free(string_value);
189-
variant_free(value);
201+
free(string_value);
202+
variant_free(value);
190203

191-
json_object_object_add(cmd_class, "dh", cmd_value);
204+
json_object_object_add(cmd_class, "dh", cmd_value);
205+
}
192206

193207
json_object_array_add(cmd_classes_array, cmd_class);
194208
}
@@ -575,42 +589,56 @@ bool cmd_get_sensor_command_class_info(vty_t* vty, variant_stack_t* params)
575589
bool get_sensor_command_class_data(vty_t* vty, ZWBYTE node_id, ZWBYTE instance_id, ZWBYTE command_id, const char* path)
576590
{
577591
json_object* json_resp = json_object_new_object();
578-
const char* resolver_name = resolver_name_from_id(node_id, instance_id, command_id);
579-
if(NULL != resolver_name)
592+
593+
device_record_t* record = resolver_resolve_id(node_id, instance_id, command_id);
594+
595+
if(NULL == record)
580596
{
581-
json_object_object_add(json_resp, "name", json_object_new_string(resolver_name));
582-
583-
zdata_acquire_lock(ZDataRoot(zway));
584-
ZDataHolder dh = zway_find_device_instance_cc_data(zway, node_id, instance_id, command_id, path);
585-
586-
if(NULL == dh)
587-
{
588-
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_USER_ERR);
589-
}
590-
else
597+
// Maybe its virtual device, lets get its root
598+
const char* name = resolver_name_from_node_id(node_id);
599+
if(NULL != name)
591600
{
592-
json_object* device_data = json_object_new_object();
593-
zway_json_data_holder_to_json(device_data, dh);
594-
json_object_object_add(json_resp, "device_data", device_data);
595-
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_OK);
601+
record = resolver_get_device_record(name);
596602
}
597-
zdata_release_lock(ZDataRoot(zway));
598603
}
599-
else
604+
605+
if(NULL != record)
600606
{
601-
resolver_name = resolver_name_from_node_id(node_id);
602-
if(NULL != resolver_name)
607+
//const char* resolver_name = resolver_name_from_id(node_id, instance_id, command_id);
608+
if(record->devtype == ZWAVE)
603609
{
604-
device_record_t* record = resolver_get_device_record(resolver_name);
605-
if(NULL != record && record->devtype == VDEV)
610+
json_object_object_add(json_resp, "name", json_object_new_string(record->deviceName));
611+
612+
zdata_acquire_lock(ZDataRoot(zway));
613+
ZDataHolder dh = zway_find_device_instance_cc_data(zway, node_id, instance_id, command_id, path);
614+
615+
if(NULL == dh)
606616
{
607-
// This is VDEV response...
608-
// { "name": "3.0.SensorBinary", "device_data": { "sensorTypeString": "General purpose", "level": false, "parameters": [ ] } }
617+
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_USER_ERR);
618+
}
619+
else
620+
{
621+
json_object* device_data = json_object_new_object();
622+
zway_json_data_holder_to_json(device_data, dh);
623+
json_object_object_add(json_resp, "device_data", device_data);
624+
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_OK);
625+
}
626+
zdata_release_lock(ZDataRoot(zway));
627+
}
628+
else
629+
{
630+
// This is VDEV response...
631+
// { "name": "3.0.SensorBinary", "device_data": { "sensorTypeString": "General purpose", "level": false, "parameters": [ ] } }
609632

610-
json_object_object_add(json_resp, "name", json_object_new_string(resolver_name));
611-
612-
vdev_t* vdev = vdev_manager_get_vdev(record->deviceName);
633+
json_object_object_add(json_resp, "name", json_object_new_string(record->deviceName));
634+
635+
// Find root VDEV
636+
const char* root_vdev_name = resolver_name_from_node_id(node_id);
613637

638+
if(NULL != root_vdev_name)
639+
{
640+
vdev_t* vdev = vdev_manager_get_vdev(root_vdev_name);
641+
614642
stack_for_each(vdev->supported_method_list, vdev_command_variant)
615643
{
616644
vdev_command_t* vdev_command = VARIANT_GET_PTR(vdev_command_t, vdev_command_variant);
@@ -621,8 +649,14 @@ bool get_sensor_command_class_data(vty_t* vty, ZWBYTE node_id, ZWBYTE instanc
621649
variant_t* value = command_class_exec(vdev_cmd_class, vdev_command->name, record);
622650
char* string_value;
623651
variant_to_string(value, &string_value);
624-
625-
if(strchr(vdev_command->data_holder, '.') != NULL)
652+
653+
if(NULL == vdev_command->data_holder)
654+
{
655+
// The string value is json string to be appended directly under "dh" key
656+
json_object_put(cmd_value);
657+
cmd_value = json_tokener_parse(string_value);
658+
}
659+
else if(strchr(vdev_command->data_holder, '.') != NULL)
626660
{
627661
char* data_holder = strdup(vdev_command->data_holder);
628662
char* saveptr;
@@ -660,13 +694,11 @@ bool get_sensor_command_class_data(vty_t* vty, ZWBYTE node_id, ZWBYTE instanc
660694

661695
json_object_object_add(cmd_value, vdev_command->data_holder, json_object_new_string(string_value));
662696
}
663-
664-
665-
697+
666698
//json_object_object_add(cmd_value, vdev_command->data_holder, json_object_new_string(string_value));
667699
free(string_value);
668700
variant_free(value);
669-
701+
670702
json_object_object_add(json_resp, "device_data", cmd_value);
671703
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_OK);
672704
break;
@@ -678,10 +710,10 @@ bool get_sensor_command_class_data(vty_t* vty, ZWBYTE node_id, ZWBYTE instanc
678710
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_SERVER_ERR);
679711
}
680712
}
681-
else
682-
{
683-
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_USER_ERR);
684-
}
713+
}
714+
else
715+
{
716+
http_set_response((http_vty_priv_t*)vty->priv, HTTP_RESP_USER_ERR);
685717
}
686718

687719
http_set_content_type((http_vty_priv_t*)vty->priv, CONTENT_TYPE_JSON);

cli_scene.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ cli_command_t scene_root_list[] = {
6464
};
6565

6666
cli_command_t scene_command_list[] = {
67-
{"source Sensor|WORD", cmd_set_scene_source, "Add scene source"},
68-
{"no source Sensor|WORD", cmd_del_scene_source, "Del scene source"},
67+
{"source Sensor|VDEV|WORD", cmd_set_scene_source, "Add scene source"},
68+
{"no source Sensor|VDEV|WORD", cmd_del_scene_source, "Del scene source"},
6969
{"condition LINE", cmd_set_scene_condition, "Set scene condition"},
7070
{"no condition LINE", cmd_del_scene_condition, "Delete scene condition"},
7171
{"action script WORD", cmd_config_scene_action_script, "Configure scene action script"},

command_class.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ static command_class_t command_class_table[] = {
8080
NULL, 0, NULL},
8181
&command_class_eval_node_naming},
8282
{0x5b, "CentralScene", {"CurrentScene", 0, "Get current scene",
83+
"KeyAttribute", 0, "Get key attribute (0 - pressed, 1 - released, 2 - held down)",
8384
NULL, 0, NULL},
8485
&command_class_eval_current_scene},
8586

@@ -251,7 +252,7 @@ variant_t* command_class_eval_basic(const char* method, device_record_t* recor
251252

252253
if(strcmp(method, "Get") == 0)
253254
{
254-
variant_t* arg1 = va_arg(args, variant_t*);
255+
//variant_t* arg1 = va_arg(args, variant_t*);
255256
/*zway_data_read_ctx_t* ctx = malloc(sizeof(zway_data_read_ctx_t));
256257
ctx->record = record;
257258
zway_cc_basic_get(zway, record->nodeId, record->instanceId, zway_data_read_success_cb, zway_data_read_fail_cb, (void*)ctx);
@@ -263,14 +264,14 @@ variant_t* command_class_eval_basic(const char* method, device_record_t* recor
263264
zdata_get_integer(dh, &int_val);
264265
ret_val = variant_create_int32(DT_INT32, int_val);
265266
zdata_release_lock(ZDataRoot(zway));*/
266-
zway_data_read_ctx_t* ctx = malloc(sizeof(zway_data_read_ctx_t));
267+
/*zway_data_read_ctx_t* ctx = malloc(sizeof(zway_data_read_ctx_t));
267268
ctx->record = record;
268269
ZWError err = zway_cc_basic_get(zway, record->nodeId, record->instanceId, zway_data_read_success_cb, zway_data_read_fail_cb, (void*)ctx);
269270
if(0 != event_wait(DataCallback, COMMAND_DATA_READY_EVENT, 1000))
270271
{
271272
LOG_DEBUG(DataCallback, "Failed to get a response in 1000 msec");
272-
}
273-
ret_val = command_class_read_data(record, variant_get_string(arg1));
273+
}*/
274+
ret_val = command_class_read_data(record, ".");
274275
}
275276
else if(strcmp(method, "Set") == 0)
276277
{
@@ -452,14 +453,14 @@ variant_t* command_class_eval_wakeup(const char* method, device_record_t* reco
452453

453454
if(strcmp(method, "Get") == 0)
454455
{
455-
zway_data_read_ctx_t* ctx = malloc(sizeof(zway_data_read_ctx_t));
456+
/*zway_data_read_ctx_t* ctx = malloc(sizeof(zway_data_read_ctx_t));
456457
ctx->record = record;
457458
zway_cc_wakeup_get(zway, record->nodeId, record->instanceId, zway_data_read_success_cb, zway_data_read_fail_cb, (void*)ctx);
458459
// Block here...
459460
if(0 != event_wait(DataCallback, COMMAND_DATA_READY_EVENT, 1000))
460461
{
461462
LOG_DEBUG(DataCallback, "Failed to get a response in 1000 msec");
462-
}
463+
}*/
463464
ret_val = command_class_read_data(record, NULL);
464465
}
465466
else if(strcmp(method, "Capabilities") == 0)
@@ -613,6 +614,10 @@ variant_t* command_class_eval_current_scene(const char* method, device_record_
613614
{
614615
ret_val = command_class_read_data(record, "currentScene");
615616
}
617+
else if(strcmp(method, "KeyAttribute") == 0)
618+
{
619+
ret_val = command_class_read_data(record, "keyAttribute");
620+
}
616621

617622
return ret_val;
618623
}

0 commit comments

Comments
 (0)