static int actionDimRun(struct JsonNode *arguments) { struct JsonNode *jdevice = NULL; struct JsonNode *jto = NULL; struct JsonNode *jsvalues = NULL; struct JsonNode *jdvalues = NULL; struct JsonNode *jdchild = NULL; struct JsonNode *jdimlevel = NULL; double dimlevel = 0.0; char state[3]; if((jdevice = json_find_member(arguments, "DEVICE")) != NULL && (jto = json_find_member(arguments, "TO")) != NULL) { if((jdvalues = json_find_member(jdevice, "value")) != NULL) { jdchild = json_first_child(jdvalues); while(jdchild) { if(jdchild->tag == JSON_STRING) { struct devices_t *dev = NULL; if(devices_get(jdchild->string_, &dev) == 0) { if((jsvalues = json_find_member(jto, "value")) != NULL) { jdimlevel = json_find_element(jsvalues, 0); if(jdimlevel != NULL && jdimlevel->tag == JSON_NUMBER) { dimlevel = (int)jdimlevel->number_; strcpy(state, "on"); JsonNode *jvalues = json_mkobject(); json_append_member(jvalues, "dimlevel", json_mknumber(dimlevel, 0)); pilight.control(dev, state, json_first_child(jvalues)); json_delete(jvalues); } } } } jdchild = jdchild->next; } } } return 0; }
static int run(struct rules_t *obj, struct JsonNode *arguments, char **ret, enum origin_t origin) { struct JsonNode *childs = json_first_child(arguments); struct devices_t *dev = NULL; struct devices_settings_t *opt = NULL; struct protocols_t *protocol = NULL; struct tm tm; char *p = *ret, *datetime = NULL, *interval = NULL, **array = NULL; int nrunits = (sizeof(units)/sizeof(units[0])), values[nrunits], error = 0; int l = 0, i = 0, type = -1, match = 0; memset(&values, 0, nrunits); if(childs == NULL) { logprintf(LOG_ERR, "DATE_ADD two parameters e.g. DATE_ADD(datetime, 1 DAY)"); error = -1; goto close; } if(devices_get(childs->string_, &dev) == 0) { if(origin == RULE) { event_cache_device(obj, childs->string_); } protocol = dev->protocols; if(protocol->listener->devtype == DATETIME) { opt = dev->settings; while(opt) { if(strcmp(opt->name, "year") == 0) { tm.tm_year = opt->values->number_-1900; } if(strcmp(opt->name, "month") == 0) { tm.tm_mon = opt->values->number_-1; } if(strcmp(opt->name, "day") == 0) { tm.tm_mday = opt->values->number_; } if(strcmp(opt->name, "hour") == 0) { tm.tm_hour = opt->values->number_; } if(strcmp(opt->name, "minute") == 0) { tm.tm_min = opt->values->number_; } if(strcmp(opt->name, "second") == 0) { tm.tm_sec = opt->values->number_; } if(strcmp(opt->name, "weekday") == 0) { tm.tm_wday = opt->values->number_-1; } if(strcmp(opt->name, "dst") == 0) { tm.tm_isdst = opt->values->number_; } opt = opt->next; } } else { logprintf(LOG_ERR, "device \"%s\" is not a datetime protocol", childs->string_); error = -1; goto close; } } else { datetime = childs->string_; } childs = childs->next; if(childs == NULL) { logprintf(LOG_ERR, "DATE_ADD requires two parameters e.g. DATE_ADD(datetime, 1 DAY)"); error = -1; goto close; } interval = childs->string_; if(childs->next != NULL) { if(dev == NULL) { logprintf(LOG_ERR, "DATE_ADD requires two parameters e.g. DATE_ADD(2000-01-01 12:00:00, 1 DAY)"); } else { logprintf(LOG_ERR, "DATE_ADD requires two parameters e.g. DATE_ADD(datetime, 1 DAY)"); } error = -1; goto close; } l = explode(interval, " ", &array); if(l == 2) { if(isNumeric(array[0]) == 0) { for(i=0;i<nrunits;i++) { if(strcmp(array[1], units[i].name) == 0) { values[i] = atoi(array[0]); type = units[i].id; match = 1; break; } } } else { logprintf(LOG_ERR, "The DATE_ADD unit parameter requires a number and a unit e.g. \"1 DAY\" instead of \"%%Y-%%m-%%d %%H:%%M:%%S\""); error = -1; goto close; } } else { logprintf(LOG_ERR, "The DATE_ADD unit parameter is formatted as e.g. \"1 DAY\" instead of \"%%Y-%%m-%%d %%H:%%M:%%S\""); error = -1; goto close; } if(match == 0) { logprintf(LOG_ERR, "DATE_ADD does not accept \"%s\" as a unit", array[1]); error = -1; goto close; } if(dev == NULL) { if(strptime(datetime, "%Y-%m-%d %H:%M:%S", &tm) == NULL) { logprintf(LOG_ERR, "DATE_ADD requires the datetime parameter to be formatted as \"%%Y-%%m-%%d %%H:%%M:%%S\""); error = -1; goto close; } } add(&tm, values, type); int year = tm.tm_year+1900; int month = tm.tm_mon+1; int day = tm.tm_mday; int hour = tm.tm_hour; int minute = tm.tm_min; int second = tm.tm_sec; datefix(&year, &month, &day, &hour, &minute, &second); snprintf(p, BUFFER_SIZE, "\"%04d-%02d-%02d %02d:%02d:%02d\"", year, month, day, hour, minute, second); close: array_free(&array, l); return error; }
int main(int argc, char **argv) { // memtrack(); struct options_t *options = NULL; struct ssdp_list_t *ssdp_list = NULL; struct devices_t *dev = NULL; struct JsonNode *json = NULL; struct JsonNode *tmp = NULL; char *recvBuff = NULL, *message = NULL, *output = NULL; char *device = NULL, *state = NULL, *values = NULL; char *server = NULL; int has_values = 0, sockfd = 0, hasconfarg = 0; unsigned short port = 0, showhelp = 0, showversion = 0; log_file_disable(); log_shell_enable(); log_level_set(LOG_NOTICE); if(!(progname = MALLOC(16))) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(progname, "pilight-control"); /* Define all CLI arguments of this program */ options_add(&options, 'H', "help", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL); options_add(&options, 'V', "version", OPTION_NO_VALUE, 0, JSON_NULL, NULL, NULL); options_add(&options, 'd', "device", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL); options_add(&options, 's', "state", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL); options_add(&options, 'v', "values", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL); options_add(&options, 'S', "server", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"); options_add(&options, 'P', "port", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, "[0-9]{1,4}"); options_add(&options, 'C', "config", OPTION_HAS_VALUE, 0, JSON_NULL, NULL, NULL); /* Store all CLI arguments for later usage and also check if the CLI arguments where used correctly by the user. This will also fill all necessary values in the options struct */ while(1) { int c; c = options_parse(&options, argc, argv, 1, &optarg); if(c == -1) break; if(c == -2) { showhelp = 1; break; } switch(c) { case 'H': showhelp = 1; break; case 'V': showversion = 1; break; case 'd': if((device = REALLOC(device, strlen(optarg)+1)) == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(device, optarg); break; case 's': if((state = REALLOC(state, strlen(optarg)+1)) == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(state, optarg); break; case 'v': if((values = REALLOC(values, strlen(optarg)+1)) == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(values, optarg); break; case 'C': if(config_set_file(optarg) == EXIT_FAILURE) { return EXIT_FAILURE; } hasconfarg = 1; break; case 'S': if(!(server = REALLOC(server, strlen(optarg)+1))) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(server, optarg); break; case 'P': port = (unsigned short)atoi(optarg); break; default: printf("Usage: %s -l location -d device -s state\n", progname); goto close; break; } } options_delete(options); if(showversion == 1) { printf("%s %s\n", progname, PILIGHT_VERSION); goto close; } if(showhelp == 1) { printf("\t -H --help\t\t\tdisplay this message\n"); printf("\t -V --version\t\t\tdisplay version\n"); printf("\t -S --server=x.x.x.x\t\tconnect to server address\n"); printf("\t -C --config\t\t\tconfig file\n"); printf("\t -P --port=xxxx\t\t\tconnect to server port\n"); printf("\t -d --device=device\t\tthe device that you want to control\n"); printf("\t -s --state=state\t\tthe new state of the device\n"); printf("\t -v --values=values\t\tspecific comma separated values, e.g.:\n"); printf("\t\t\t\t\t-v dimlevel=10\n"); goto close; } if(device == NULL || state == NULL || strlen(device) == 0 || strlen(state) == 0) { printf("Usage: %s -d device -s state\n", progname); goto close; } if(server && port > 0) { if((sockfd = socket_connect(server, port)) == -1) { logprintf(LOG_ERR, "could not connect to pilight-daemon"); goto close; } } else if(ssdp_seek(&ssdp_list) == -1) { logprintf(LOG_ERR, "no pilight ssdp connections found"); goto close; } else { if((sockfd = socket_connect(ssdp_list->ip, ssdp_list->port)) == -1) { logprintf(LOG_ERR, "could not connect to pilight-daemon"); goto close; } } if(ssdp_list) { ssdp_free(ssdp_list); } protocol_init(); config_init(); if(hasconfarg == 1) { if(config_read() != EXIT_SUCCESS) { goto close; } } socket_write(sockfd, "{\"action\":\"identify\"}"); if(socket_read(sockfd, &recvBuff, 0) != 0 || strcmp(recvBuff, "{\"status\":\"success\"}") != 0) { goto close; } json = json_mkobject(); json_append_member(json, "action", json_mkstring("request config")); output = json_stringify(json, NULL); socket_write(sockfd, output); json_free(output); json_delete(json); if(socket_read(sockfd, &recvBuff, 0) == 0) { if(json_validate(recvBuff) == true) { json = json_decode(recvBuff); if(json_find_string(json, "message", &message) == 0) { if(strcmp(message, "config") == 0) { struct JsonNode *jconfig = NULL; if((jconfig = json_find_member(json, "config")) != NULL) { int match = 1; while(match) { struct JsonNode *jchilds = json_first_child(jconfig); match = 0; while(jchilds) { if(strcmp(jchilds->key, "devices") != 0) { json_remove_from_parent(jchilds); tmp = jchilds; match = 1; } jchilds = jchilds->next; if(tmp != NULL) { json_delete(tmp); } tmp = NULL; } } config_parse(jconfig); if(devices_get(device, &dev) == 0) { JsonNode *joutput = json_mkobject(); JsonNode *jcode = json_mkobject(); JsonNode *jvalues = json_mkobject(); json_append_member(jcode, "device", json_mkstring(device)); if(values != NULL) { char **array = NULL; unsigned int n = explode(values, ",=", &array), q = 0; for(q=0;q<n;q+=2) { char *name = MALLOC(strlen(array[q])+1); if(name == NULL) { logprintf(LOG_ERR, "out of memory\n"); exit(EXIT_FAILURE); } strcpy(name, array[q]); if(q+1 == n) { for(q=0;q<n;q++) { FREE(array[q]); } FREE(array); logprintf(LOG_ERR, "\"%s\" is missing a value for device \"%s\"", name, device); FREE(name); break; } else { char *val = MALLOC(strlen(array[q+1])+1); if(val == NULL) { logprintf(LOG_ERR, "out of memory\n"); exit(EXIT_FAILURE); } strcpy(val, array[q+1]); if(devices_valid_value(device, name, val) == 0) { if(isNumeric(val) == EXIT_SUCCESS) { char *ptr = strstr(array[q+1], "."); int decimals = 0; if(ptr != NULL) { decimals = (int)(strlen(array[q+1])-((size_t)(ptr-array[q+1])+1)); } json_append_member(jvalues, name, json_mknumber(atof(val), decimals)); } else { json_append_member(jvalues, name, json_mkstring(val)); } has_values = 1; } else { logprintf(LOG_ERR, "\"%s\" is an invalid value for device \"%s\"", name, device); for(q=0;q<n;q++) { FREE(array[q]); } FREE(array); FREE(name); json_delete(json); goto close; } } FREE(name); } unsigned int z = 0; for(z=q;z<n;z++) { FREE(array[z]); } if(n > 0) { FREE(array); } } if(devices_valid_state(device, state) == 0) { json_append_member(jcode, "state", json_mkstring(state)); } else { logprintf(LOG_ERR, "\"%s\" is an invalid state for device \"%s\"", state, device); json_delete(json); goto close; } if(has_values == 1) { json_append_member(jcode, "values", jvalues); } else { json_delete(jvalues); } json_append_member(joutput, "action", json_mkstring("control")); json_append_member(joutput, "code", jcode); output = json_stringify(joutput, NULL); socket_write(sockfd, output); json_free(output); json_delete(joutput); if(socket_read(sockfd, &recvBuff, 0) != 0 || strcmp(recvBuff, "{\"status\":\"success\"}") != 0) { logprintf(LOG_ERR, "failed to control %s", device); } } else { logprintf(LOG_ERR, "the device \"%s\" does not exist", device); json_delete(json); goto close; } } } } json_delete(json); } } close: if(recvBuff) { FREE(recvBuff); } if(sockfd > 0) { socket_close(sockfd); } if(server != NULL) { FREE(server); } if(device != NULL) { FREE(device); } if(state != NULL) { FREE(state); } if(values != NULL) { FREE(values); } log_shell_disable(); socket_gc(); config_gc(); protocol_gc(); options_gc(); event_operator_gc(); event_action_gc(); dso_gc(); log_gc(); threads_gc(); gc_clear(); FREE(progname); xfree(); return EXIT_SUCCESS; }
static int run(struct rules_t *obj, struct JsonNode *arguments, char **ret, enum origin_t origin) { struct JsonNode *childs = json_first_child(arguments); struct devices_t *dev = NULL; struct devices_settings_t *opt = NULL; struct protocols_t *protocol = NULL; struct tm tm; char *p = *ret, *datetime = NULL, *format = NULL; if(childs == NULL) { logprintf(LOG_ERR, "DATE_FORMAT requires at least two parameters e.g. DATE_FORMAT(datetime, %Y-%m-%d)"); return -1; } if(devices_get(childs->string_, &dev) == 0) { if(origin == RULE) { event_cache_device(obj, childs->string_); } protocol = dev->protocols; if(protocol->listener->devtype == DATETIME) { opt = dev->settings; while(opt) { if(strcmp(opt->name, "year") == 0) { tm.tm_year = opt->values->number_-1900; } if(strcmp(opt->name, "month") == 0) { tm.tm_mon = opt->values->number_-1; } if(strcmp(opt->name, "day") == 0) { tm.tm_mday = opt->values->number_; } if(strcmp(opt->name, "hour") == 0) { tm.tm_hour = opt->values->number_; } if(strcmp(opt->name, "minute") == 0) { tm.tm_min = opt->values->number_; } if(strcmp(opt->name, "second") == 0) { tm.tm_sec = opt->values->number_; } if(strcmp(opt->name, "weekday") == 0) { tm.tm_wday = opt->values->number_-1; } if(strcmp(opt->name, "dst") == 0) { tm.tm_isdst = opt->values->number_; } opt = opt->next; } } else { logprintf(LOG_ERR, "device \"%s\" is not a datetime protocol", childs->string_); return -1; } } else { datetime = childs->string_; } childs = childs->next; if(childs == NULL) { logprintf(LOG_ERR, "DATE_FORMAT requires at least two parameters e.g. DATE_FORMAT(datetime, %%Y-%%m-%%d)"); return -1; } format = childs->string_; if(childs->next == NULL && dev == NULL) { logprintf(LOG_ERR, "DATE_FORMAT requires at least three parameters when passing a datetime string e.g. DATE_FORMAT(01-01-2015, %%d-%%m-%%Y, %%Y-%%m-%%d)"); return -1; } if(childs->next != NULL && dev != NULL) { logprintf(LOG_ERR, "DATE_FORMAT requires at least two parameters e.g. DATE_FORMAT(datetime, %%Y-%%m-%%d)"); return -1; } if(dev == NULL) { childs = childs->next; if(strptime(datetime, format, &tm) == NULL) { logprintf(LOG_ERR, "DATE_FORMAT is unable to parse \"%s\" as \"%s\" ", datetime, format); return -1; } } int year = tm.tm_year+1900; int month = tm.tm_mon+1; int day = tm.tm_mday; int hour = tm.tm_hour; int minute = tm.tm_min; int second = tm.tm_sec; int weekday = tm.tm_wday; datefix(&year, &month, &day, &hour, &minute, &second); tm.tm_year = year-1900; tm.tm_mon = month-1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = minute; tm.tm_sec = second; tm.tm_wday = weekday; strftime(p, BUFFER_SIZE, childs->string_, &tm); return 0; }
/* This functions checks if the defined event variable is part of one of devices in the config. If it is, replace the variable with the actual value */ static int event_lookup_variable(char *var, struct rules_t *obj, unsigned int nr, int type, union varcont_t *varcont, unsigned short validate) { logprintf(LOG_STACK, "%s(...)", __FUNCTION__); int cached = 0; if(strcmp(true_, "1") != 0) { strcpy(true_, "1"); } if(strcmp(false_, "1") != 0) { strcpy(false_, "1"); } if(strcmp(var, "1") == 0 || strcmp(var, "0") == 0 || isNumeric(var) == 0 || strcmp(var, "true") == 0 || strcmp(var, "false") == 0) { if(type == JSON_NUMBER) { if(strcmp(var, "true") == 0) { varcont->number_ = 1; } else if(strcmp(var, "false") == 0) { varcont->number_ = 0; } else { varcont->number_ = atof(var); } } else if(type == JSON_STRING) { if(strcmp(var, "true") == 0) { varcont->string_ = true_; } else if(strcmp(var, "false") == 0) { varcont->string_ = false_; } else { varcont->string_ = var; } } return 0; } int len = (int)strlen(var); int i = 0; int nrdots = 0; for(i=0;i<len;i++) { if(var[i] == '.') { nrdots++; } } if(nrdots == 1) { char **array = NULL; unsigned int n = explode(var, ".", &array), q = 0; if(n < 2) { logprintf(LOG_ERR, "rule #%d: an unexpected error occured", nr, var); varcont->string_ = NULL; varcont->number_ = 0; for(q=0;q<n;q++) { FREE(array[q]); } FREE(array); return -1; } char device[strlen(array[0])+1]; strcpy(device, array[0]); char name[strlen(array[1])+1]; strcpy(name, array[1]); for(q=0;q<n;q++) { FREE(array[q]); } FREE(array); /* Check if the values are not already cached */ struct rules_values_t *tmp_values = obj->values; while(tmp_values) { if(strcmp(tmp_values->device, device) == 0 && strcmp(tmp_values->name, name) == 0) { if(tmp_values->settings->values->type == JSON_STRING) { varcont->string_ = tmp_values->settings->values->string_; } else if(tmp_values->settings->values->type == JSON_NUMBER) { varcont->number_ = tmp_values->settings->values->number_; } cached = 1; return 0; } tmp_values = tmp_values->next; } struct devices_t *dev = NULL; if(cached == 0) { if(devices_get(device, &dev) == 0) { if(validate == 1) { int exists = 0; int o = 0; for(o=0;o<obj->nrdevices;o++) { if(strcmp(obj->devices[o], device) == 0) { exists = 1; break; } } if(exists == 0) { /* Store all devices that are present in this rule */ if(!(obj->devices = REALLOC(obj->devices, sizeof(char *)*(unsigned int)(obj->nrdevices+1)))) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } if((obj->devices[obj->nrdevices] = MALLOC(strlen(device)+1)) == NULL) { logprintf(LOG_ERR, "out of memory"); exit(EXIT_FAILURE); } strcpy(obj->devices[obj->nrdevices], device); obj->nrdevices++; } struct protocols_t *tmp = dev->protocols; unsigned int match1 = 0, match2 = 0, match3 = 0; while(tmp) { struct options_t *opt = tmp->listener->options; while(opt) { if(opt->conftype == DEVICES_STATE && strcmp("state", name) == 0) { match1 = 1; match2 = 1; match3 = 1; break; } else if(strcmp(opt->name, name) == 0) { match1 = 1; if(opt->conftype == DEVICES_VALUE || opt->conftype == DEVICES_STATE || opt->conftype == DEVICES_SETTING) { match2 = 1; if(opt->vartype == JSON_STRING && type == JSON_STRING) { match3 = 1; } else if(opt->vartype == JSON_NUMBER && type == JSON_NUMBER) { match3 = 1; } break; } } opt = opt->next; } tmp = tmp->next; } if(!match1) { logprintf(LOG_ERR, "rule #%d invalid: device \"%s\" has no variable \"%s\"", nr, device, name); } else if(!match2) { logprintf(LOG_ERR, "rule #%d invalid: variable \"%s\" of device \"%s\" cannot be used in event rules", nr, device, name); } else if(!match3) { logprintf(LOG_ERR, "rule #%d invalid: trying to compare a integer variable \"%s.%s\" to a string", nr, device, name); } if(!match1 || !match2 || !match3) { varcont->string_ = NULL; varcont->number_ = 0; return -1; } } struct devices_settings_t *tmp_settings = dev->settings; while(tmp_settings) { if(strcmp(tmp_settings->name, name) == 0) { if(tmp_settings->values->type == JSON_STRING) { if(type == JSON_STRING) { /* Cache values for faster future lookup */ event_store_val_ptr(obj, device, name, tmp_settings); varcont->string_ = tmp_settings->values->string_; return 0; } else { logprintf(LOG_ERR, "rule #%d invalid: trying to compare integer variable \"%s.%s\" to a string", nr, device, name); varcont->string_ = NULL; return -1; } } else if(tmp_settings->values->type == JSON_NUMBER) { if(type == JSON_NUMBER) { /* Cache values for faster future lookup */ event_store_val_ptr(obj, device, name, tmp_settings); varcont->number_ = tmp_settings->values->number_; return 0; } else { logprintf(LOG_ERR, "rule #%d invalid: trying to compare string variable \"%s.%s\" to an integer", nr, device, name); varcont->number_ = 0; return -1; } } } tmp_settings = tmp_settings->next; } logprintf(LOG_ERR, "rule #%d invalid: device \"%s\" has no variable \"%s\"", nr, device, name); varcont->string_ = NULL; varcont->number_ = 0; return -1; } else { logprintf(LOG_ERR, "rule #%d invalid: device \"%s\" does not exist in the config", nr, device); varcont->string_ = NULL; varcont->number_ = 0; return -1; } } return 1; } else if(nrdots > 2) { logprintf(LOG_ERR, "rule #%d invalid: variable \"%s\" is invalid", nr, var); varcont->string_ = NULL; varcont->number_ = 0; return -1; } else { if(type == JSON_STRING) { varcont->string_ = var; } else if(type == JSON_NUMBER) { varcont->number_ = atof(var); } return 0; } }
static int actionDimArguments(struct JsonNode *arguments) { struct JsonNode *jdevice = NULL; struct JsonNode *jto = NULL; struct JsonNode *jsvalues = NULL; struct JsonNode *jdvalues = NULL; struct JsonNode *jschild = NULL; struct JsonNode *jdchild = NULL; double nr1 = 0.0, nr2 = 0.0; int nrvalues = 0; jdevice = json_find_member(arguments, "DEVICE"); jto = json_find_member(arguments, "TO"); if(jdevice == NULL) { logprintf(LOG_ERR, "dim action is missing a \"DEVICE\""); return -1; } if(jto == NULL) { logprintf(LOG_ERR, "dim action is missing a \"TO ...\" statement"); return -1; } json_find_number(jdevice, "order", &nr1); json_find_number(jto, "order", &nr2); if((int)nr1 != 1 || (int)nr2 != 2) { logprintf(LOG_ERR, "dim actions are formatted as \"dim DEVICE ... TO ...\""); return -1; } if((jsvalues = json_find_member(jto, "value")) != NULL) { jschild = json_first_child(jsvalues); while(jschild) { nrvalues++; jschild = jschild->next; } } if(nrvalues != 1) { logprintf(LOG_ERR, "dim actions are formatted as \"dim DEVICE ... TO ...\""); return -1; } if((jdvalues = json_find_member(jdevice, "value")) != NULL) { jdchild = json_first_child(jdvalues); while(jdchild) { if(jdchild->tag == JSON_STRING) { struct devices_t *dev = NULL; if(devices_get(jdchild->string_, &dev) == 0) { if((jsvalues = json_find_member(jto, "value")) != NULL) { jschild = json_first_child(jsvalues); while(jschild) { if(jschild->tag == JSON_NUMBER) { struct protocols_t *tmp_protocols = dev->protocols; if(tmp_protocols->listener->devtype == DIMMER) { struct devices_settings_t *tmp_settings = dev->settings; int match1 = 0, match2 = 0; while(tmp_settings) { if(strcmp(tmp_settings->name, "dimlevel-maximum") == 0) { if(tmp_settings->values->type == JSON_NUMBER && (int)tmp_settings->values->number_ < (int)jschild->number_) { logprintf(LOG_ERR, "device \"%s\" can't be set to dimlevel \"%d\"", jdchild->string_, (int)jschild->number_); return -1; } match1 = 1; } if(strcmp(tmp_settings->name, "dimlevel-minimum") == 0) { if(tmp_settings->values->type == JSON_NUMBER && (int)tmp_settings->values->number_ > (int)jschild->number_) { logprintf(LOG_ERR, "device \"%s\" can't be set to dimlevel \"%d\"", jdchild->string_, (int)jschild->number_); return -1; } match2 = 1; } tmp_settings = tmp_settings->next; } if(match1 == 0 || match2 == 0) { while(tmp_protocols) { struct options_t *opt = tmp_protocols->listener->options; while(opt) { if(match1 == 0 && strcmp(opt->name, "dimlevel-maximum") == 0 && opt->vartype == JSON_NUMBER && (int)(intptr_t)opt->def < (int)jschild->number_) { logprintf(LOG_ERR, "device \"%s\" can't be set to dimlevel \"%d\"", jdchild->string_, (int)jschild->number_); return -1; } if(match2 == 0 && strcmp(opt->name, "dimlevel-minimum") == 0 && opt->vartype == JSON_NUMBER && (int)(intptr_t)opt->def > (int)jschild->number_) { logprintf(LOG_ERR, "device \"%s\" can't be set to dimlevel \"%d\"", jdchild->string_, (int)jschild->number_); return -1; } opt = opt->next; } tmp_protocols = tmp_protocols->next; } } } else { logprintf(LOG_ERR, "device \"%s\" doesn't support dimming", jdchild->string_); return -1; } } else { logprintf(LOG_ERR, "device \"%s\" doesn't exists", jdchild->string_); return -1; } jschild = jschild->next; } } else { return -1; } } else { return -1; } } else { return -1; } jdchild = jdchild->next; } } else { return -1; } return 0; }