Ejemplo n.º 1
0
static int checkValues(struct JsonNode *jvalues) {
	struct JsonNode *jid = NULL;

	if((jid = json_find_member(jvalues, "id"))) {
		struct settings_t *snode = NULL;
		struct JsonNode *jchild = NULL;
		struct JsonNode *jchild1 = NULL;
		double channel = -1, id = -1;
		int match = 0;

		jchild = json_first_child(jid);
		while(jchild) {
			jchild1 = json_first_child(jchild);
			while(jchild1) {
				if(strcmp(jchild1->key, "channel") == 0) {
					channel = jchild1->number_;
				}
				if(strcmp(jchild1->key, "id") == 0) {
					id = jchild1->number_;
				}
				jchild1 = jchild1->next;
			}
			jchild = jchild->next;
		}

		struct settings_t *tmp = settings;
		while(tmp) {
			if(fabs(tmp->id-id) < EPSILON && fabs(tmp->channel-channel) < EPSILON) {
				match = 1;
				break;
			}
			tmp = tmp->next;
		}

		if(match == 0) {
			if((snode = MALLOC(sizeof(struct settings_t))) == NULL) {
				fprintf(stderr, "out of memory\n");
				exit(EXIT_FAILURE);
			}
			snode->id = id;
			snode->channel = channel;
			snode->temp = 0;
			snode->humi = 0;

			json_find_number(jvalues, "temperature-offset", &snode->temp);
			json_find_number(jvalues, "humidity-offset", &snode->humi);

			snode->next = settings;
			settings = snode;
		}
	}
	return 0;
}
Ejemplo n.º 2
0
static void *thread(void *param) {
	struct protocol_threads_t *node = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)node->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	int id = 0, state = 0, nstate = 0;
	double itmp = 0.0;

	threads++;

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		if(json_find_number(jchild, "gpio", &itmp) == 0) {
			id = (int)round(itmp);
			pinMode(id, PINMODE_INPUT);
			state = digitalRead(id);
		}
	}

	createMessage(id, state);

	while(loop) {
		nstate = digitalRead(id);
		if(nstate != state) {
			state = nstate;
			createMessage(id, state);
		}
		usleep(100000);
	}

	threads--;
	return (void *)NULL;
}
Ejemplo n.º 3
0
int main(void)
{
    JsonNode *node;

    (void) chomp;

    plan_tests(49);

    ok1(json_find_element(NULL, 0) == NULL);
    ok1(json_find_member(NULL, "") == NULL);
    ok1(json_first_child(NULL) == NULL);

    node = json_mknull();
    should_be(node, "null");
    json_delete(node);

    node = json_mkbool(false);
    should_be(node, "false");
    json_delete(node);

    node = json_mkbool(true);
    should_be(node, "true");
    json_delete(node);

    test_string();
    test_number();
    test_array();
    test_object();

    return exit_status();
}
Ejemplo n.º 4
0
static int checkValues(struct JsonNode *jvalues) {
	double readonly = 0.0;
	char *platform = GPIO_PLATFORM;

	if(config_setting_get_string("gpio-platform", 0, &platform) != 0) {
		logprintf(LOG_ERR, "no gpio-platform configured");
		return -1;
	}
	if(strcmp(platform, "none") == 0) {
		FREE(platform);
		logprintf(LOG_ERR, "no gpio-platform configured");
		return -1;
	}
	if(wiringXSetup(platform, logprintf1) < 0) {
		FREE(platform);
		return -1;
	}
	FREE(platform);

	struct JsonNode *jid = NULL;
	if((jid = json_find_member(jvalues, "id"))) {
		struct JsonNode *jchild = NULL;
		struct JsonNode *jchild1 = NULL;

		jchild = json_first_child(jid);
		while(jchild) {
			jchild1 = json_first_child(jchild);
			while(jchild1) {
				if(strcmp(jchild1->key, "gpio") == 0) {
					if(wiringXValidGPIO((int)round(jchild1->number_)) != 0) {
						return -1;
					}
				}
				jchild1 = jchild1->next;
			}
			jchild = jchild->next;
		}
	}

	if(json_find_number(jvalues, "readonly", &readonly) == 0) {
		if((int)readonly != 1) {
			return -1;
		}
	}

	return 0;
}
Ejemplo n.º 5
0
void template_parse_color(JsonNode *root, unsigned short *color) {
	JsonNode *child = json_first_child(root);
	int i = 0;
	while(child != NULL) {
		color[i] = (unsigned short)child->number_;
		i++;
		child = child->next;
	}
}
Ejemplo n.º 6
0
static void registry_remove_empty_parent(struct JsonNode *root) {
	logprintf(LOG_STACK, "%s(...)", __FUNCTION__);

	struct JsonNode *parent = root->parent;
	if(json_first_child(root) == NULL) {
		if(parent != NULL) {
			json_remove_from_parent(root);
			registry_remove_empty_parent(parent);
			json_delete(root);
		}
	}
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
static int event_parse_action(char *action, struct rules_t *obj, int validate) {
	logprintf(LOG_STACK, "%s(...)", __FUNCTION__);

	struct JsonNode *jvalues = NULL;
	char *var1 = NULL, *func = NULL, *var2 = NULL, *tmp = action;
	char *var3 = NULL, *var4 = NULL;
	int element = 0, match = 0, error = 0, order = 0;
	int hasaction = 0, hasquote = 0, match1 = 0, match2 = 0;
	unsigned long len = strlen(tmp), pos = 0, word = 0, hadquote = 0;

	if(obj->arguments == NULL) {
		obj->arguments = json_mkobject();
		while(pos <= len) {
			/* If we encounter a space we have the formula part */
			if(tmp[pos] == '"') {
				hasquote ^= 1;
				if(hasquote == 1) {
					word++;
				} else {
					hadquote = 1;
				}
			}
			if(hasquote == 0 && (tmp[pos] == ' ' || pos == len)) {
				switch(element) {
					/* The first value of three is always the first variable.
						 The second value is always the function.
						 The third value of the three is always the second variable (or second formula).
					*/
					case 0:
						var1 = REALLOC(var1, ((pos-word)+1));
						memset(var1, '\0', ((pos-word)+1));
						strncpy(var1, &tmp[word], (pos-word)-hadquote);
					break;
					case 1:
						func = REALLOC(func, ((pos-word)+1));
						memset(func, '\0', ((pos-word)+1));
						strncpy(func, &tmp[word], (pos-word)-hadquote);
					break;
					case 2:
						var2 = REALLOC(var2, ((pos-word)+1));
						memset(var2, '\0', ((pos-word)+1));
						strncpy(var2, &tmp[word], (pos-word)-hadquote);
					break;
					default:;
				}
				hadquote = 0;
				word = pos+1;
				element++;
				if(element > 2) {
					element = 0;
				}
			}
			if(hasaction == 0 && var1 && strlen(var1) > 0) {
				match = 0;
				obj->action = event_actions;
				while(obj->action) {
					if(strcmp(obj->action->name, var1) == 0) {
						match = 1;
						break;
					}
					obj->action = obj->action->next;
				}
				if(match == 1) {
					hasaction = 1;
					element = 0;
				} else {
					logprintf(LOG_ERR, "action \"%s\" doesn't exists", var1);
					error = 1;
					break;
				}
			} else if(func && strlen(func) > 0 &&
				 var1 && strlen(var1) > 0 &&
				 var2 && strlen(var2) > 0) {
				 int hasand = 0;
				if(strcmp(var2, "AND") == 0) {
					hasand = 1;
					word -= strlen(var2)+1;
					if(jvalues == NULL) {
						jvalues = json_mkarray();
					}
					if(isNumeric(func) == 0) {
						json_append_element(jvalues, json_mknumber(atof(func), nrDecimals(func)));
					} else {
						json_append_element(jvalues, json_mkstring(func));
					}
					element = 0;
					while(pos <= len) {
						if(tmp[pos] == '"') {
							hasquote ^= 1;
							if(hasquote == 1) {
								word++;
							} else {
								hadquote = 1;
							}
						}
						if(hasquote == 0 && (tmp[pos] == ' ' || pos == len)) {
							switch(element) {
								/* The first value of three is always the first variable.
									 The second value is always the function.
									 The third value of the three is always the second variable (or second formula).
								*/
								case 0:
									var3 = REALLOC(var3, ((pos-word)+1));
									memset(var3, '\0', ((pos-word)+1));
									strncpy(var3, &tmp[word], (pos-word)-hadquote);
								break;
								case 1:
									var4 = REALLOC(var4, ((pos-word)+1));
									memset(var4, '\0', ((pos-word)+1));
									strncpy(var4, &tmp[word], (pos-word)-hadquote);
								break;
								default:;
							}
							hadquote = 0;
							word = pos+1;
							element++;
							if(element > 1) {
								element = 0;
							}
						}
						pos++;
						if(var3 && strlen(var3) > 0 &&
							 var4 && strlen(var4) > 0) {
							if(strcmp(var3, "AND") != 0) {
								var2 = REALLOC(var2, strlen(var3)+1);
								strcpy(var2, var3);
								pos -= strlen(var3)+strlen(var4)+2;
								word -= strlen(var3)+strlen(var4)+2;
								break;
							}
							if(isNumeric(var4) == 0) {
								json_append_element(jvalues, json_mknumber(atof(var4), nrDecimals(var4)));
							} else {
								json_append_element(jvalues, json_mkstring(var4));
							}
							element = 0;
							if(var3) {
								memset(var3, '\0', strlen(var3));
							} if(var4) {
								memset(var4, '\0', strlen(var4));
							}
						}
					}
				}
				match1 = 0, match2 = 0;
				struct options_t *opt = obj->action->options;
				while(opt) {
					if(strcmp(opt->name, var1) == 0) {
						match1 = 1;
					}
					if(strcmp(opt->name, var2) == 0) {
						match2 = 1;
					}
					if(match1 == 1 && match2 == 1) {
						break;
					}
					opt = opt->next;
				}
				/* If we are at the end of our rule
					 we only match the first option */
				if(pos == len+1) {
					match2 = 1;
				}
				if(match1 == 1 && match2 == 1) {
					struct JsonNode *jobj = json_mkobject();
					order++;
					if(hasand == 1) {
						json_append_member(jobj, "value", jvalues);
						json_append_member(jobj, "order", json_mknumber(order, 0));
						jvalues = NULL;
					} else {
						jvalues = json_mkarray();
						if(isNumeric(func) == 0) {
							json_append_element(jvalues, json_mknumber(atof(func), nrDecimals(func)));
							json_append_member(jobj, "value", jvalues);
							json_append_member(jobj, "order", json_mknumber(order, 0));
							jvalues = NULL;
						} else {
							json_append_element(jvalues, json_mkstring(func));
							json_append_member(jobj, "value", jvalues);
							json_append_member(jobj, "order", json_mknumber(order, 0));
							jvalues = NULL;
						}
					}
					json_append_member(obj->arguments, var1, jobj);
				} else if(match1 == 0) {
					logprintf(LOG_ERR, "action \"%s\" doesn't accept option \"%s\"", obj->action->name, var1);
					error = 1;
					if(jvalues) {
						json_delete(jvalues);
					}
					break;
				} else if(match2 == 0) {
					logprintf(LOG_ERR, "action \"%s\" doesn't accept option \"%s\"", obj->action->name, var2);
					error = 1;
					if(jvalues) {
						json_delete(jvalues);
					}
					break;
				}
				element = 0, match1 = 0, match2 = 0;
				if(hasand == 0) {
					pos -= strlen(var2)+1;
					word -= strlen(var2)+1;
				}
				if(var1) {
					memset(var1, '\0', strlen(var1));
				} if(func) {
					memset(func, '\0', strlen(func));
				} if(var2) {
					memset(var2, '\0', strlen(var2));
				} if(var3) {
					memset(var3, '\0', strlen(var3));
				} if(var4) {
					memset(var4, '\0', strlen(var4));
				}
				hasand = 0;
			}
			pos++;
		}
		if(error == 0) {
			if(var1 && strlen(var1) > 0 &&
				 func && strlen(func) > 0) {
				match1 = 0;
				struct options_t *opt = obj->action->options;
				while(opt) {
					if(strcmp(opt->name, var1) == 0) {
						match1 = 1;
					}
					if(match1 == 1) {
						break;
					}
					opt = opt->next;
				}
				if(match1 == 1) {
					struct JsonNode *jobj = json_mkobject();
					order++;
					jvalues = json_mkarray();
					if(isNumeric(func) == 0) {
						json_append_element(jvalues, json_mknumber(atof(func), nrDecimals(func)));
						json_append_member(jobj, "value", jvalues);
						json_append_member(jobj, "order", json_mknumber(order, 0));
						jvalues = NULL;
					} else {
						json_append_element(jvalues, json_mkstring(func));
						json_append_member(jobj, "value", jvalues);
						json_append_member(jobj, "order", json_mknumber(order, 0));
						jvalues = NULL;
					}
					json_append_member(obj->arguments, var1, jobj);
				} else {
					error = 1;
				}
			}
		}
		if(error == 0) {
			struct options_t *opt = obj->action->options;
			struct JsonNode *joption = NULL;
			struct JsonNode *jvalue = NULL;
			struct JsonNode *jchild = NULL;
			while(opt) {
				if((joption = json_find_member(obj->arguments, opt->name)) == NULL) {
					if(opt->conftype == DEVICES_VALUE) {
						logprintf(LOG_ERR, "action \"%s\" is missing option \"%s\"", obj->action->name, opt->name);
						error = 1;
						break;
					}
				} else {
					if((jvalue = json_find_member(joption, "value")) != NULL) {
						if(jvalue->tag == JSON_ARRAY) {
							jchild = json_first_child(jvalue);
							while(jchild) {
								if(jchild->tag != JSON_NUMBER && opt->vartype == JSON_NUMBER) {
									logprintf(LOG_ERR, "action \"%s\" option \"%s\" only accepts numbers", obj->action->name, opt->name);
									error = 1;
									break;
								}
								if(jchild->tag != JSON_STRING && opt->vartype == JSON_STRING) {
									logprintf(LOG_ERR, "action \"%s\" option \"%s\" only accepts strings", obj->action->name, opt->name);
									error = 1;
									break;
								}
								jchild = jchild->next;
							}
						}
					}
				}
				opt = opt->next;
			}
			if(error == 0) {
				jchild = json_first_child(obj->arguments);
				while(jchild) {
					match = 0;
					opt = obj->action->options;
					while(opt) {
						if(strcmp(jchild->key, opt->name) == 0) {
							match = 1;
							break;
						}
						opt = opt->next;
					}
					if(match == 0) {
						logprintf(LOG_ERR, "action \"%s\" doesn't accept option \"%s\"", obj->action->name, jchild->key);
						error = 1;
						break;
					}
					jchild = jchild->next;
				}
			}
		}
	}

	if(error == 0) {
		if(validate == 1) {
			if(obj->action->checkArguments) {
				error = obj->action->checkArguments(obj->arguments);
			}
		} else {
			if(obj->action->run) {
				error = obj->action->run(obj->arguments);
			}
		}
	}
	if(var1) {
		FREE(var1);
		var1 = NULL;
	} if(func) {
		FREE(func);
		func = NULL;
	} if(var2) {
		FREE(var2);
		var2 = NULL;
	}	if(var3) {
		FREE(var3);
		var3 = NULL;
	} if(var4) {
		FREE(var4);
		var4 = NULL;
	}
	return error;
}
Ejemplo n.º 9
0
static void *thread(void *param) {
	struct protocol_threads_t *node = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)node->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;

#ifndef _WIN32
	struct dirent *file = NULL;
	struct stat st;

	DIR *d = NULL;
	FILE *fp = NULL;
	char crcVar[5];
	int w1valid = 0;
	double w1temp = 0.0;
	size_t bytes = 0;
#endif
	char **id = NULL, *stmp = NULL, *content = NULL;
	char *ds18s20_sensor = NULL;
	int nrid = 0, interval = 10, nrloops = 0, y = 0;
	double temp_offset = 0.0, itmp = 0.0;

	threads++;

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		while(jchild) {
			if(json_find_string(jchild, "id", &stmp) == 0) {
				if((id = REALLOC(id, (sizeof(char *)*(size_t)(nrid+1)))) == NULL) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				if((id[nrid] = MALLOC(strlen(stmp)+1)) == NULL) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				strcpy(id[nrid], stmp);
				nrid++;
			}
			jchild = jchild->next;
		}
	}

	if(json_find_number(json, "poll-interval", &itmp) == 0)
		interval = (int)round(itmp);
	json_find_number(json, "temperature-offset", &temp_offset);

	while(loop) {
		if(protocol_thread_wait(node, interval, &nrloops) == ETIMEDOUT) {
#ifndef _WIN32
			pthread_mutex_lock(&lock);
			for(y=0;y<nrid;y++) {
				if((ds18s20_sensor = REALLOC(ds18s20_sensor, strlen(source_path)+strlen(id[y])+5)) == NULL) {
					fprintf(stderr, "out of memory\n");
					exit(EXIT_FAILURE);
				}
				sprintf(ds18s20_sensor, "%s10-%s/", source_path, id[y]);
				if((d = opendir(ds18s20_sensor))) {
					while((file = readdir(d)) != NULL) {
						if(file->d_type == DT_REG) {
							if(strcmp(file->d_name, "w1_slave") == 0) {
								size_t w1slavelen = strlen(ds18s20_sensor)+10;
								char ds18s20_w1slave[w1slavelen];
								memset(ds18s20_w1slave, '\0', w1slavelen);
								strncpy(ds18s20_w1slave, ds18s20_sensor, strlen(ds18s20_sensor));
								strcat(ds18s20_w1slave, "w1_slave");

								if(!(fp = fopen(ds18s20_w1slave, "rb"))) {
									logprintf(LOG_ERR, "cannot read w1 file: %s", ds18s20_w1slave);
									break;
								}

								fstat(fileno(fp), &st);
								bytes = (size_t)st.st_size;

								if(!(content = REALLOC(content, bytes+1))) {
									fprintf(stderr, "out of memory\n");
									fclose(fp);
									break;
								}
								memset(content, '\0', bytes+1);

								if(fread(content, sizeof(char), bytes, fp) == -1) {
									logprintf(LOG_ERR, "cannot read config file: %s", ds18s20_w1slave);
									fclose(fp);
									break;
								}
								fclose(fp);
								w1valid = 0;

								char **array = NULL;
								unsigned int n = explode(content, "\n", &array);
								if(n > 0) {
									sscanf(array[0], "%*x %*x %*x %*x %*x %*x %*x %*x %*x : crc=%*x %s", crcVar);
									if(strncmp(crcVar, "YES", 3) == 0 && n > 1) {
										w1valid = 1;
										sscanf(array[1], "%*x %*x %*x %*x %*x %*x %*x %*x %*x t=%lf", &w1temp);
										w1temp = (w1temp/1000)+temp_offset;
									}
								}
								array_free(&array, n);

								if(w1valid) {
									ds18s20->message = json_mkobject();

									JsonNode *code = json_mkobject();

									json_append_member(code, "id", json_mkstring(id[y]));
									json_append_member(code, "temperature", json_mknumber(w1temp, 1));

									json_append_member(ds18s20->message, "message", code);
									json_append_member(ds18s20->message, "origin", json_mkstring("receiver"));
									json_append_member(ds18s20->message, "protocol", json_mkstring(ds18s20->id));

									if(pilight.broadcast != NULL) {
										pilight.broadcast(ds18s20->id, ds18s20->message, PROTOCOL);
									}
									json_delete(ds18s20->message);
									ds18s20->message = NULL;
								}
							}
						}
					}
					closedir(d);
				} else {
					logprintf(LOG_ERR, "1-wire device %s does not exists", ds18s20_sensor);
				}
			}
#endif
			pthread_mutex_unlock(&lock);
		}
	}
	pthread_mutex_unlock(&lock);

	if(ds18s20_sensor) {
		FREE(ds18s20_sensor);
	}
	if(content) {
		FREE(content);
	}
	for(y=0;y<nrid;y++) {
		FREE(id[y]);
	}
	FREE(id);
	threads--;
	return (void *)NULL;
}
Ejemplo n.º 10
0
static void *dht22Parse(void *param) {
	struct protocol_threads_t *node = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)node->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	int *id = 0;
	int nrid = 0, y = 0, interval = 10, nrloops = 0;
	double temp_offset = 0.0, humi_offset = 0.0, itmp = 0.0;

	dht22_threads++;

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		while(jchild) {
			if(json_find_number(jchild, "gpio", &itmp) == 0) {
				id = REALLOC(id, (sizeof(int)*(size_t)(nrid+1)));
				id[nrid] = (int)round(itmp);
				nrid++;
			}
			jchild = jchild->next;
		}
	}

	if(json_find_number(json, "poll-interval", &itmp) == 0)
		interval = (int)round(itmp);
	json_find_number(json, "temperature-offset", &temp_offset);
	json_find_number(json, "humidity-offset", &humi_offset);

	while(dht22_loop) {
		if(protocol_thread_wait(node, interval, &nrloops) == ETIMEDOUT) {
			pthread_mutex_lock(&dht22lock);
			for(y=0;y<nrid;y++) {
				int tries = 5;
				unsigned short got_correct_date = 0;
				while(tries && !got_correct_date && dht22_loop) {

					uint8_t laststate = HIGH;
					uint8_t counter = 0;
					uint8_t j = 0, i = 0;

					int dht22_dat[5] = {0,0,0,0,0};

					// pull pin down for 18 milliseconds
					pinMode(id[y], OUTPUT);
					digitalWrite(id[y], HIGH);
					usleep(500000);  // 500 ms
					// then pull it up for 40 microseconds
					digitalWrite(id[y], LOW);
					usleep(20000);
					// prepare to read the pin
					pinMode(id[y], INPUT);

					// detect change and read data
					for(i=0; (i<MAXTIMINGS && dht22_loop); i++) {
						counter = 0;
						delayMicroseconds(10);
						while(sizecvt(digitalRead(id[y])) == laststate && dht22_loop) {
							counter++;
							delayMicroseconds(1);
							if(counter == 255) {
								break;
							}
						}
						laststate = sizecvt(digitalRead(id[y]));

						if(counter == 255)
							break;

						// ignore first 3 transitions
						if((i >= 4) && (i%2 == 0)) {

							// shove each bit into the storage bytes
							dht22_dat[(int)((double)j/8)] <<= 1;
							if(counter > 16)
								dht22_dat[(int)((double)j/8)] |= 1;
							j++;
						}
					}

					// check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
					// print it out if data is good
					if((j >= 40) && (dht22_dat[4] == ((dht22_dat[0] + dht22_dat[1] + dht22_dat[2] + dht22_dat[3]) & 0xFF))) {
						got_correct_date = 1;

						double h = dht22_dat[0] * 256 + dht22_dat[1];
						double t = (dht22_dat[2] & 0x7F)* 256 + dht22_dat[3];
						t += temp_offset;
						h += humi_offset;

						if((dht22_dat[2] & 0x80) != 0)
							t *= -1;

						dht22->message = json_mkobject();
						JsonNode *code = json_mkobject();
						json_append_member(code, "gpio", json_mknumber(id[y], 0));
						json_append_member(code, "temperature", json_mknumber(t/10, 1));
						json_append_member(code, "humidity", json_mknumber(h/10, 1));

						json_append_member(dht22->message, "message", code);
						json_append_member(dht22->message, "origin", json_mkstring("receiver"));
						json_append_member(dht22->message, "protocol", json_mkstring(dht22->id));

						if(pilight.broadcast != NULL) {
							pilight.broadcast(dht22->id, dht22->message);
						}
						json_delete(dht22->message);
						dht22->message = NULL;
					} else {
						logprintf(LOG_DEBUG, "dht22 data checksum was wrong");
						tries--;
						protocol_thread_wait(node, 1, &nrloops);
					}
				}
			}
			pthread_mutex_unlock(&dht22lock);
		}
	}
	pthread_mutex_unlock(&dht22lock);

	FREE(id);
	dht22_threads--;
	return (void *)NULL;
}
Ejemplo n.º 11
0
int fillTZData(void) {
	if(tzdatafilled == 1) {
		return EXIT_SUCCESS;
	}
	char *content = NULL;
	JsonNode *root = NULL;
	FILE *fp;
	size_t bytes;
	struct stat st;

	char tzdatafile[] = "tzdata.json";
	/* Read JSON tzdata file */
	if(!(fp = fopen(tzdatafile, "rb"))) {
		printf("cannot read tzdata file: %s\n", tzdatafile);
		return EXIT_FAILURE;
	}

	fstat(fileno(fp), &st);
	bytes = (size_t)st.st_size;

	if(!(content = calloc(bytes+1, sizeof(char)))) {
		printf("out of memory\n");
		return EXIT_FAILURE;
	}

	if(fread(content, sizeof(char), bytes, fp) == -1) {
		printf("cannot read tzdata file: %s\n", tzdatafile);
	}
	fclose(fp);

	/* Validate JSON and turn into JSON object */
	if(json_validate(content) == false) {
		printf("tzdata is not in a valid json format\n");
		free(content);
		return EXIT_FAILURE;
	}
	root = json_decode(content);

	JsonNode *alist = json_first_child(root);
	unsigned int i = 0, x = 0, y = 0;
	while(alist) {
		JsonNode *country = json_first_child(alist);
		while(country) {
			strcpy(tznames[i], country->key);
			if(!(tzcoords = realloc(tzcoords, sizeof(int **)*(i+1)))) {
				printf("out of memory\n");
			}
			tzcoords[i] = NULL;
			JsonNode *coords = json_first_child(country);
			x = 0;
			while(coords) {
				y = 0;
				if(!(tzcoords[i] = realloc(tzcoords[i], sizeof(int *)*(x+1)))) {
					printf("out of memory\n");
				}
				tzcoords[i][x] = NULL;
				if(!(tzcoords[i][x] = malloc(sizeof(int)*2))) {
					printf("out of memory\n");
				}
				JsonNode *lonlat = json_first_child(coords);
				while(lonlat) {
					tzcoords[i][x][y] = (int)lonlat->number_;
					y++;
					lonlat = lonlat->next;
				}
				x++;
				coords = coords->next;
			}
			tznrpolys[i] = x;
			i++;
			country = country->next;
		}
		alist = alist->next;
	}
	json_delete(root);
	free(content);
	tzdatafilled = 1;
	return EXIT_SUCCESS;
}
Ejemplo n.º 12
0
void *ds18b20Parse(void *param) {
	struct protocol_threads_t *node = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)node->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	struct dirent *file = NULL;
	struct stat st;

	DIR *d = NULL;
	FILE *fp = NULL;
	char *ds18b20_sensor = NULL;
	char *stmp = NULL;
	char **id = NULL;
	char *content = NULL;
	int w1valid = 0, w1temp = 0, interval = 10, x = 0;
	int temp_offset = 0, nrid = 0, y = 0, nrloops = 0;
	double itmp = 0;
	size_t bytes = 0;

	ds18b20_threads++;

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		while(jchild) {
			if(json_find_string(jchild, "id", &stmp) == 0) {
				id = realloc(id, (sizeof(char *)*(size_t)(nrid+1)));
				if(!id) {
					logprintf(LOG_ERR, "out of memory");
					exit(EXIT_FAILURE);
				}
				id[nrid] = malloc(strlen(stmp)+1);
				if(!id[nrid]) {
					logprintf(LOG_ERR, "out of memory");
					exit(EXIT_FAILURE);
				}
				strcpy(id[nrid], stmp);
				nrid++;
			}
			jchild = jchild->next;
		}
	}

	if(json_find_number(json, "poll-interval", &itmp) == 0)
		interval = (int)round(itmp);
	if(json_find_number(json, "device-temperature-offset", &itmp) == 0)
		temp_offset = (int)round(itmp);

	while(ds18b20_loop) {
		if(protocol_thread_wait(node, interval, &nrloops) == ETIMEDOUT) {
			for(y=0;y<nrid;y++) {
				ds18b20_sensor = realloc(ds18b20_sensor, strlen(ds18b20_path)+strlen(id[y])+5);
				if(!ds18b20_sensor) {
					logprintf(LOG_ERR, "out of memory");
					exit(EXIT_FAILURE);
				}
				sprintf(ds18b20_sensor, "%s28-%s/", ds18b20_path, id[y]);
				if((d = opendir(ds18b20_sensor))) {
					while((file = readdir(d)) != NULL) {
						if(file->d_type == DT_REG) {
							if(strcmp(file->d_name, "w1_slave") == 0) {
								size_t w1slavelen = strlen(ds18b20_sensor)+10;
								char ds18b20_w1slave[w1slavelen];
								memset(ds18b20_w1slave, '\0', w1slavelen);
								strncpy(ds18b20_w1slave, ds18b20_sensor, strlen(ds18b20_sensor));
								strcat(ds18b20_w1slave, "w1_slave");

								if(!(fp = fopen(ds18b20_w1slave, "rb"))) {
									logprintf(LOG_ERR, "cannot read w1 file: %s", ds18b20_w1slave);
									break;
								}

								fstat(fileno(fp), &st);
								bytes = (size_t)st.st_size;

								if(!(content = realloc(content, bytes+1))) {
									logprintf(LOG_ERR, "out of memory");
									fclose(fp);
									break;
								}
								memset(content, '\0', bytes+1);

								if(fread(content, sizeof(char), bytes, fp) == -1) {
									logprintf(LOG_ERR, "cannot read config file: %s", ds18b20_w1slave);
									fclose(fp);
									break;
								}
								fclose(fp);
								w1valid = 0;
								char *pch = strtok(content, "\n=: ");
								x = 0;
								while(pch) {
									if(strlen(pch) > 2) {
										if(x == 1 && strstr(pch, "YES")) {
											w1valid = 1;
										}
										if(x == 2) {	
											w1temp = atoi(pch)+temp_offset;
										}
										x++;
									}
									pch = strtok(NULL, "\n=: ");
								}

								if(w1valid) {
									ds18b20->message = json_mkobject();
									
									JsonNode *code = json_mkobject();
									
									json_append_member(code, "id", json_mkstring(id[y]));
									json_append_member(code, "temperature", json_mknumber(w1temp));
									
									json_append_member(ds18b20->message, "message", code);
									json_append_member(ds18b20->message, "origin", json_mkstring("receiver"));
									json_append_member(ds18b20->message, "protocol", json_mkstring(ds18b20->id));
									
									pilight.broadcast(ds18b20->id, ds18b20->message);
									json_delete(ds18b20->message);
									ds18b20->message = NULL;
								}
							}
						}
					}
					closedir(d);
				} else {
					logprintf(LOG_ERR, "1-wire device %s does not exists", ds18b20_sensor);
				}
			}
		}
	}
	if(ds18b20_sensor) {
		sfree((void *)&ds18b20_sensor);
	}
	if(content) {
		sfree((void *)&content);
	}
	for(y=0;y<nrid;y++) {
		sfree((void *)&id[y]);
	}
	sfree((void *)&id);
	ds18b20_threads--;
	return (void *)NULL;
}
Ejemplo n.º 13
0
static int rules_parse(JsonNode *root) {
	int have_error = 0, match = 0, x = 0;
	unsigned int i = 0;
	struct JsonNode *jrules = NULL;
	char *rule = NULL;
	double active = 1.0;

	if(root->tag == JSON_OBJECT) {
		jrules = json_first_child(root);
		while(jrules) {
			i++;
			if(jrules->tag == JSON_OBJECT) {
				if(json_find_string(jrules, "rule", &rule) != 0) {
					logprintf(LOG_ERR, "config rule #%d \"%s\", missing \"rule\"", i, jrules->key);
					have_error = 1;
					break;
				} else {
					active = 1.0;
					json_find_number(jrules, "active", &active);

					struct rules_t *tmp = rules;
					match = 0;
					while(tmp) {
						if(strcmp(tmp->name, jrules->key) == 0) {
							match = 1;
							break;
						}
						tmp = tmp->next;
					}
					if(match == 1) {
						logprintf(LOG_ERR, "config rule #%d \"%s\" already exists", i, jrules->key);
						have_error = 1;
						break;
					}
					for(x=0;x<strlen(jrules->key);x++) {
						if(!isalnum(jrules->key[x]) && jrules->key[x] != '-' && jrules->key[x] != '_') {
							logprintf(LOG_ERR, "config rule #%d \"%s\", not alphanumeric", i, jrules->key);
							have_error = 1;
							break;
						}
					}

					struct rules_t *node = MALLOC(sizeof(struct rules_t));
					if(node == NULL) {
						fprintf(stderr, "out of memory\n");
						exit(EXIT_FAILURE);
					}
					node->next = NULL;
					node->values = NULL;
					node->nrdevices = 0;
					node->status = 0;
					node->devices = NULL;
					node->actions = NULL;
					node->nr = i;
					if((node->name = MALLOC(strlen(jrules->key)+1)) == NULL) {
						fprintf(stderr, "out of memory\n");
						exit(EXIT_FAILURE);
					}
					strcpy(node->name, jrules->key);
					clock_gettime(CLOCK_MONOTONIC, &node->timestamp.first);
					if(event_parse_rule(rule, node, 0, 1) == -1) {
						have_error = 1;
					}
					clock_gettime(CLOCK_MONOTONIC, &node->timestamp.second);
					logprintf(LOG_INFO, "rule #%d %s was parsed in %.6f seconds", node->nr, node->name,
						((double)node->timestamp.second.tv_sec + 1.0e-9*node->timestamp.second.tv_nsec) -
						((double)node->timestamp.first.tv_sec + 1.0e-9*node->timestamp.first.tv_nsec));

					node->status = 0;
					if((node->rule = MALLOC(strlen(rule)+1)) == NULL) {
						fprintf(stderr, "out of memory\n");
						exit(EXIT_FAILURE);
					}
					strcpy(node->rule, rule);
					node->active = (unsigned short)active;

					tmp = rules;
					if(tmp) {
						while(tmp->next != NULL) {
							tmp = tmp->next;
						}
						tmp->next = node;
					} else {
						node->next = rules;
						rules = node;
					}
					/*
					 * In case of an error, we do want to
					 * save a pointer to our faulty rule
					 * so it can be properly garbage collected.
					 */
					if(have_error == 1) {
						break;
					}
				}
			}
			jrules = jrules->next;
		}
	} else {
		logprintf(LOG_ERR, "config rules should be placed in an object");
		have_error = 1;
	}

	return have_error;
}
Ejemplo n.º 14
0
int settings_parse(JsonNode *root) {
    int have_error = 0;

#ifdef WEBSERVER
    int web_port = 0;
    int own_port = 0;

    char *webgui_tpl = malloc(strlen(WEBGUI_TEMPLATE)+1);
    if(!webgui_tpl) {
        logprintf(LOG_ERR, "out of memory");
        exit(EXIT_FAILURE);
    }
    strcpy(webgui_tpl, WEBGUI_TEMPLATE);
    char *webgui_root = malloc(strlen(WEBSERVER_ROOT)+1);
    if(!webgui_root) {
        logprintf(LOG_ERR, "out of memory");
        exit(EXIT_FAILURE);
    }
    strcpy(webgui_root, WEBSERVER_ROOT);
#endif

#ifndef __FreeBSD__
    regex_t regex;
    int reti;
#endif

    JsonNode *jsettings = json_first_child(root);

    while(jsettings) {
        if(strcmp(jsettings->key, "port") == 0
                || strcmp(jsettings->key, "send-repeats") == 0
                || strcmp(jsettings->key, "receive-repeats") == 0) {
            if((int)jsettings->number_ == 0) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
#ifdef WEBSERVER
                if(strcmp(jsettings->key, "port") == 0) {
                    own_port = (int)jsettings->number_;
                }
#endif
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "standalone") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        }  else if(strcmp(jsettings->key, "firmware-update") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "log-level") == 0) {
            if((int)jsettings->number_ < 0 || (int)jsettings->number_ > 5) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a number from 0 till 5", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "pid-file") == 0 || strcmp(jsettings->key, "log-file") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                if(path_exists(jsettings->string_) != EXIT_SUCCESS) {
                    logprintf(LOG_ERR, "setting \"%s\" must point to an existing folder", jsettings->key);
                    have_error = 1;
                    goto clear;
                } else {
                    settings_add_string(jsettings->key, jsettings->string_);
                }
            }
        } else if(strcmp(jsettings->key, "config-file") == 0 || strcmp(jsettings->key, "hardware-file") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
                have_error = 1;
                goto clear;
            } else if(strlen(jsettings->string_) > 0) {
                if(settings_file_exists(jsettings->string_) == EXIT_SUCCESS) {
                    settings_add_string(jsettings->key, jsettings->string_);
                } else {
                    logprintf(LOG_ERR, "setting \"%s\" must point to an existing file", jsettings->key);
                    have_error = 1;
                    goto clear;
                }
            }
        } else if(strcmp(jsettings->key, "whitelist") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must contain valid ip addresses", jsettings->key);
                have_error = 1;
                goto clear;
            } else if(strlen(jsettings->string_) > 0) {
#ifndef __FreeBSD__
                char validate[] = "^((\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\\.(\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\\.(\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\\.(\\*|[0-9]|[1-9][0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))(,[\\ ]|,|$))+$";
                reti = regcomp(&regex, validate, REG_EXTENDED);
                if(reti) {
                    logprintf(LOG_ERR, "could not compile regex");
                    have_error = 1;
                    goto clear;
                }
                reti = regexec(&regex, jsettings->string_, 0, NULL, 0);
                if(reti == REG_NOMATCH || reti != 0) {
                    logprintf(LOG_ERR, "setting \"%s\" must contain valid ip addresses", jsettings->key);
                    have_error = 1;
                    regfree(&regex);
                    goto clear;
                }
                regfree(&regex);
#endif
                int l = (int)strlen(jsettings->string_)-1;
                if(jsettings->string_[l] == ' ' || jsettings->string_[l] == ',') {
                    logprintf(LOG_ERR, "setting \"%s\" must contain valid ip addresses", jsettings->key);
                    have_error = 1;
                    goto clear;
                }
                settings_add_string(jsettings->key, jsettings->string_);
            }
#ifdef WEBSERVER
        } else if(strcmp(jsettings->key, "webserver-port") == 0) {
            if(jsettings->number_ < 0) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                web_port = (int)jsettings->number_;
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "webserver-root") == 0) {
            if(!jsettings->string_ || path_exists(jsettings->string_) != 0) {
                logprintf(LOG_ERR, "setting \"%s\" must contain a valid path", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                webgui_root = realloc(webgui_root, strlen(jsettings->string_)+1);
                if(!webgui_root) {
                    logprintf(LOG_ERR, "out of memory");
                    exit(EXIT_FAILURE);
                }
                strcpy(webgui_root, jsettings->string_);
                settings_add_string(jsettings->key, jsettings->string_);
            }
        } else if(strcmp(jsettings->key, "webserver-enable") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "webserver-cache") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "webserver-user") == 0) {
            if(jsettings->string_ || strlen(jsettings->string_) > 0) {
                if(name2uid(jsettings->string_) == -1) {
                    logprintf(LOG_ERR, "setting \"%s\" must contain a valid system user", jsettings->key);
                    have_error = 1;
                    goto clear;
                } else {
                    settings_add_string(jsettings->key, jsettings->string_);
                }
            }
        } else if(strcmp(jsettings->key, "webserver-authentication") == 0 && jsettings->tag == JSON_ARRAY) {
            JsonNode *jtmp = json_first_child(jsettings);
            unsigned short i = 0;
            while(jtmp) {
                i++;
                if(jtmp->tag == JSON_STRING) {
                    if(i == 1) {
                        settings_add_string("webserver-authentication-username", jtmp->string_);
                    } else if(i == 2) {
                        settings_add_string("webserver-authentication-password", jtmp->string_);
                    }
                } else {
                    have_error = 1;
                    break;
                }
                if(i > 2) {
                    have_error = 1;
                    break;
                }
                jtmp = jtmp->next;
            }
            if(i != 2 || have_error == 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be in the format of [ \"username\", \"password\" ]", jsettings->key);
                have_error = 1;
                goto clear;
            }
        }  else if(strcmp(jsettings->key, "webgui-template") == 0) {
            if(!jsettings->string_) {
                logprintf(LOG_ERR, "setting \"%s\" must be a valid template", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                webgui_tpl = realloc(webgui_tpl, strlen(jsettings->string_)+1);
                if(!webgui_tpl) {
                    logprintf(LOG_ERR, "out of memory");
                    exit(EXIT_FAILURE);
                }
                strcpy(webgui_tpl, jsettings->string_);
                settings_add_string(jsettings->key, jsettings->string_);
            }
#endif
#ifdef UPDATE
        } else if(strcmp(jsettings->key, "update-check") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "update-development") == 0) {
            if(jsettings->number_ < 0 || jsettings->number_ > 1) {
                logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
                have_error = 1;
                goto clear;
            } else {
                settings_add_number(jsettings->key, (int)jsettings->number_);
            }
        } else if(strcmp(jsettings->key, "update-mirror") == 0) {
            char *filename = NULL;
            char *url = NULL;
            char *data = NULL;
            int lg = 0;
            char typebuf[70];

            if(jsettings->string_) {
                url = malloc(strlen(jsettings->string_)+1);
                if(!url) {
                    logprintf(LOG_ERR, "out of memory");
                    exit(EXIT_FAILURE);
                }
                strcpy(url, jsettings->string_);
                http_parse_url(url, &filename);
            }
            if(!jsettings->string_ || http_get(filename, &data, &lg, typebuf) != 200) {
                logprintf(LOG_ERR, "setting \"%s\" must be point to a valid (online) file", jsettings->key);
                /* clean-up http_lib global */
                if(http_server) sfree((void *)&http_server);
                if(filename) sfree((void *)&filename);
                if(url) sfree((void *)&url);
                if(data) sfree((void *)&data);
                have_error = 1;
                goto clear;
            } else {
                settings_add_string(jsettings->key, jsettings->string_);
                /* clean-up http_lib global */
                if(http_server) sfree((void *)&http_server);
                if(filename) sfree((void *)&filename);
                if(url) sfree((void *)&url);
                if(data) sfree((void *)&data);
            }
#endif
        } else {
            logprintf(LOG_ERR, "setting \"%s\" is invalid", jsettings->key);
            have_error = 1;
            goto clear;
        }
        jsettings = jsettings->next;
    }
    json_delete(jsettings);
#ifdef WEBSERVER
    if(webgui_tpl) {
        char *tmp = malloc(strlen(webgui_root)+strlen(webgui_tpl)+13);
        if(!tmp) {
            logprintf(LOG_ERR, "out of memory");
            exit(EXIT_FAILURE);
        }
        sprintf(tmp, "%s/%s/index.html", webgui_root, webgui_tpl);
        if(path_exists(tmp) != EXIT_SUCCESS) {
            logprintf(LOG_ERR, "setting \"webgui-template\", template does not exists");
            have_error = 1;
            sfree((void *)&tmp);
            goto clear;
        }
        sfree((void *)&tmp);
    }

    if(web_port == own_port) {
        logprintf(LOG_ERR, "setting \"port\" and \"webserver-port\" cannot be the same");
        have_error = 1;
        goto clear;
    }
#endif
clear:
#ifdef WEBSERVER
    if(webgui_tpl) {
        sfree((void *)&webgui_tpl);
    }
    if(webgui_root) {
        sfree((void *)&webgui_root);
    }
#endif
    return have_error;
}
Ejemplo n.º 15
0
static int rules_parse(JsonNode *root) {
	int have_error = 0, match = 0;
	unsigned int i = 0;
	struct JsonNode *jrules = NULL;
	char *rule = NULL;
	double active = 1.0;

	if(root->tag == JSON_OBJECT) {
		jrules = json_first_child(root);
		while(jrules) {
			i++;
			if(jrules->tag == JSON_OBJECT) {
				if(json_find_string(jrules, "rule", &rule) != 0) {
					logprintf(LOG_ERR, "config rules #%d \"%s\", missing \"rule\"", i, jrules->key);
					have_error = 1;
					break;
				} else {
					active = 1.0;
					json_find_number(jrules, "active", &active);

					struct rules_t *tmp = rules;
					match = 0;
					while(tmp) {
						if(strcmp(tmp->name, jrules->key) == 0) {
							match = 1;
							break;
						}
						tmp = tmp->next;
					}
					if(match == 1) {
						logprintf(LOG_ERR, "config rules #%d \"%s\" already exists", i, jrules->key);
						have_error = 1;
						break;
					}
					struct rules_t *node = MALLOC(sizeof(struct rules_t));
					if(node == NULL) {
						logprintf(LOG_ERR, "out of memory");
						exit(EXIT_FAILURE);
					}
					node->next = NULL;
					node->values = NULL;
					node->nrdevices = 0;
					node->status = 0;
					node->devices = NULL;
					node->action = NULL;
					node->arguments = NULL;
					if(event_parse_rule(rule, node, 0, i, 1) == -1) {
						for(i=0;i<node->nrdevices;i++) {
							FREE(node->devices[i]);
						}
						if(node->devices != NULL) {
							FREE(node->devices);
						}
						FREE(node);
						have_error = 1;
						break;
					}
					node->status = 0;
					node->rule = MALLOC(strlen(rule)+1);
					if(node->rule == NULL) {
						logprintf(LOG_ERR, "out of memory");
						exit(EXIT_FAILURE);
					}
					strcpy(node->rule, rule);
					node->name = MALLOC(strlen(jrules->key)+1);
					if(node->name == NULL) {
						logprintf(LOG_ERR, "out of memory");
						exit(EXIT_FAILURE);
					}
					strcpy(node->name, jrules->key);
					node->active = (unsigned short)active;

					tmp = rules;
					if(tmp) {
						while(tmp->next != NULL) {
							tmp = tmp->next;
						}
						tmp->next = node;
					} else {
						node->next = rules;
						rules = node;
					}
				}
			}
			jrules = jrules->next;
		}
	} else {
		logprintf(LOG_ERR, "config rules should be placed in an object");
		have_error = 1;
	}

	return have_error;
}
Ejemplo n.º 16
0
void *xbmcParse(void *param) {
	struct protocol_threads_t *node = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)node->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	struct JsonNode *jchild1 = NULL;
	struct sockaddr_in serv_addr;
	struct xbmc_data_t *xnode = malloc(sizeof(struct xbmc_data_t));

	char recvBuff[BUFFER_SIZE], action[10], media[15];
	char *m = NULL, *t = NULL;
	char shut[] = "shutdown";
	char home[] = "home";
	char none[] = "none";
	int nrloops = 0, bytes = 0, n = 0, has_server = 0;
	int has_port = 0, reset = 1, maxfd = 0;
	fd_set fdsread;	
	struct timeval timeout;
	timeout.tv_sec = 1;
	timeout.tv_usec = 0;

	if(!xnode) {
		logprintf(LOG_ERR, "out of memory");
		exit(EXIT_FAILURE);
	}	
	
	/* Clear the server address */
    memset(&serv_addr, '\0', sizeof(serv_addr));
	memset(&recvBuff, '\0', BUFFER_SIZE);
	memset(&action, '\0', 10);
	memset(&media, '\0', 15);
	
	xbmc_threads++;

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		while(jchild) {
			jchild1 = json_first_child(jchild);

			while(jchild1) {
				if(strcmp(jchild1->key, "server") == 0) {
					if(!(xnode->server = malloc(strlen(jchild1->string_)+1))) {
						logprintf(LOG_ERR, "out of memory");
						exit(EXIT_FAILURE);
					}
					strcpy(xnode->server, jchild1->string_);
					has_server = 1;
				}
				if(strcmp(jchild1->key, "port") == 0) {
					xnode->port = (int)round(jchild1->number_);
					has_port = 1;
				}
				jchild1 = jchild1->next;
			}
			if(has_server == 1 && has_port == 1) {
				xnode->sockfd = -1;
				xnode->next = xbmc_data;
				xbmc_data = xnode;
			} else {
				if(has_server == 1) {
					sfree((void *)&xnode->server);
				}
				sfree((void *)&xnode);
				xnode = NULL;
			}
			jchild = jchild->next;
		}
	}

	if(!xnode) {
		return 0;
	}

	while(xbmc_loop) {

		if(reset == 1) {
			xbmcCreateMessage(xnode->server, xnode->port, shut, none);
			reset = 0;
		}

		if(xnode->sockfd > -1) {
			close(xnode->sockfd);
			xnode->sockfd = -1;
		}

		/* Try to open a new socket */
		if((xnode->sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
			logprintf(LOG_DEBUG, "could not create XBMC socket");
			break;
		}

		serv_addr.sin_family = AF_INET;
		serv_addr.sin_port = htons((unsigned short)xnode->port);
		inet_pton(AF_INET, xnode->server, &serv_addr.sin_addr);	
		
		/* Connect to the server */
		if(connect(xnode->sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
			protocol_thread_wait(node, 3, &nrloops);
			continue;
		} else {
			xbmcCreateMessage(xnode->server, xnode->port, home, none);
			reset = 1;
		}

		struct xbmc_data_t *xtmp = xbmc_data;
		while(xtmp) {
			if(xtmp->sockfd > -1) {
				if(maxfd < xtmp->sockfd) {
					maxfd = xtmp->sockfd;
				}
			}
			xtmp = xtmp->next;
		}
		
		while(xbmc_loop) {
			FD_ZERO(&fdsread);
			FD_SET((unsigned long)xnode->sockfd, &fdsread);

			do {
				n = select(maxfd+1, &fdsread, NULL, NULL, &timeout);
			} while(n == -1 && errno == EINTR && xbmc_loop);

			if(xbmc_loop == 0) {
				break;
			}

			if(n == -1) {			
				break;
			} else if(n == 0) {
				usleep(10000);
			} else if(n > 0) {
				if(FD_ISSET((unsigned long)xnode->sockfd, &fdsread)) {
					bytes = (int)recv(xnode->sockfd, recvBuff, BUFFER_SIZE, 0);
					if(bytes <= 0) {
						break;
					} else {
						if(json_validate(recvBuff) == true) {
							JsonNode *joutput = json_decode(recvBuff);
							JsonNode *params = NULL;
							JsonNode *data = NULL;
							JsonNode *item = NULL;

							if(json_find_string(joutput, "method", &m) == 0) {
								if(strcmp(m, "GUI.OnScreensaverActivated") == 0) {
									strcpy(media, "screensaver");
									strcpy(action, "active");
								} else if(strcmp(m, "GUI.OnScreensaverDeactivated") == 0) {
									strcpy(media, "screensaver");
									strcpy(action, "inactive");
								} else {
									if((params = json_find_member(joutput, "params")) != NULL) {
										if((data = json_find_member(params, "data")) != NULL) {
											if((item = json_find_member(data, "item")) != NULL) {
												if(json_find_string(item, "type", &t) == 0) {
													xbmc->message = json_mkobject();

													strcpy(media, t);
													if(strcmp(m, "Player.OnPlay") == 0) {
														strcpy(action, "play");
													} else if(strcmp(m, "Player.OnStop") == 0) {
														strcpy(action, home);
														strcpy(media, none);
													} else if(strcmp(m, "Player.OnPause") == 0) {
														strcpy(action, "pause");
													}
												}
											}
										}
									}
								}
								if(strlen(media) > 0 && strlen(action) > 0) {
									xbmcCreateMessage(xnode->server, xnode->port, action, media);
									reset = 1;
								}							
							}
							json_delete(joutput);
						}
						memset(recvBuff, '\0', BUFFER_SIZE);
						memset(&action, '\0', 10);
						memset(&media, '\0', 15);
					}
				}
			}
		}
	}	
	
	xbmc_threads--;
	return (void *)NULL;
}
Ejemplo n.º 17
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;
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
0
void *lm76Parse(void *param) {
	struct JsonNode *json = (struct JsonNode *)param;
	struct JsonNode *jsettings = NULL;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	struct timeval tp;
	struct timespec ts;	
	struct lm76data_t *lm76data = malloc(sizeof(struct lm76data_t));	
	int y = 0, interval = 10, rc = 0;
	int temp_corr = 0;
	char *stmp = NULL;
	int firstrun = 1;

	lm76data->nrid = 0;
	lm76data->id = NULL;
	lm76data->fd = 0;
	
#ifndef __FreeBSD__
	pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;        
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
#else
	pthread_mutex_t mutex;
	pthread_cond_t cond;
	pthread_mutexattr_t attr;

	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutex_init(&mutex, &attr);
#endif

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		while(jchild) {
			if(json_find_string(jchild, "id", &stmp) == 0) {
				lm76data->id = realloc(lm76data->id, (sizeof(char *)*(size_t)(lm76data->nrid+1)));
				lm76data->id[lm76data->nrid] = malloc(strlen(stmp)+1);
				strcpy(lm76data->id[lm76data->nrid], stmp);
				lm76data->nrid++;
			}
			jchild = jchild->next;
		}
	}
	if((jsettings = json_find_member(json, "settings"))) {
		json_find_number(jsettings, "interval", &interval);
		json_find_number(jsettings, "temp-corr", &temp_corr);
	}
	json_delete(json);
#ifndef __FreeBSD__	
	lm76data->fd = realloc(lm76data->fd, (sizeof(int)*(size_t)(lm76data->nrid+1)));
	for(y=0;y<lm76data->nrid;y++) {
		lm76data->fd[y] = wiringPiI2CSetup((int)strtol(lm76data->id[y], NULL, 16));
	}
#endif
	pthread_cleanup_push(lm76ParseCleanUp, (void *)lm76data);
	
	while(lm76_loop) {	
		rc = gettimeofday(&tp, NULL);
		ts.tv_sec = tp.tv_sec;
		ts.tv_nsec = tp.tv_usec * 1000;
		if(firstrun) {
			ts.tv_sec += 1;
			firstrun = 0;
		} else {
			ts.tv_sec += interval;
		}

		pthread_mutex_lock(&mutex);
		rc = pthread_cond_timedwait(&cond, &mutex, &ts);
		if(rc == ETIMEDOUT) {
#ifndef __FreeBSD__	
			for(y=0;y<lm76data->nrid;y++) {
				if(lm76data->fd[y] > 0) {		
					int raw = wiringPiI2CReadReg16(lm76data->fd[y], 0x00);            
					float temp = ((float)((raw&0x00ff)+((raw>>12)*0.0625))*1000);

					lm76->message = json_mkobject();
					JsonNode *code = json_mkobject();
					json_append_member(code, "id", json_mkstring(lm76data->id[y]));
					json_append_member(code, "temperature", json_mknumber((int)temp+temp_corr));

					json_append_member(lm76->message, "code", code);
					json_append_member(lm76->message, "origin", json_mkstring("receiver"));
					json_append_member(lm76->message, "protocol", json_mkstring(lm76->id));

					pilight.broadcast(lm76->id, lm76->message);
					json_delete(lm76->message);
					lm76->message = NULL;
				} else {
					logprintf(LOG_DEBUG, "error connecting to lm76");
					logprintf(LOG_DEBUG, "(probably i2c bus error from wiringPiI2CSetup)");
					logprintf(LOG_DEBUG, "(maybe wrong id? use i2cdetect to find out)");
					sleep(1);
				}
			}
#endif
		}
Ejemplo n.º 20
0
int settings_parse(JsonNode *root) {
	int have_error = 0;
	int is_node = 0;
	char *server_ip = NULL;
	int server_port = 0;
	int web_port = 0;
	int own_port = 0;
	int has_config = 0;
	int has_lirc = 0;
	int has_socket = 0;
	int gpio_in = -1;
	int gpio_out = -1;

	JsonNode *jsettings = json_first_child(root);

	while(jsettings) {
		if(strcmp(jsettings->key, "port") == 0 || strcmp(jsettings->key, "send-repeats") == 0 || strcmp(jsettings->key, "receive-repeats") == 0) {
			if((int)jsettings->number_ == 0) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if(strcmp(jsettings->key, "port") == 0) {
					own_port = (int)jsettings->number_;
				}
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "mode") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must be \"server\" or \"client\"", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if(strcmp(jsettings->string_, "client") == 0) {
					is_node = 1;
				}
				if(strcmp(jsettings->string_, "server") == 0 || strcmp(jsettings->string_, "client") == 0) {
					settings_add_string_node(jsettings->key, jsettings->string_);
				} else {
					logprintf(LOG_ERR, "setting \"%s\" must be \"server\" or \"client\"", jsettings->key);
					have_error = 1;
					goto clear;
				}
			}
		} else if(strcmp(jsettings->key, "log-level") == 0) {
			if((int)jsettings->number_ == 0 || (int)jsettings->number_ > 5) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a number from 0 till 5", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "pid-file") == 0 || strcmp(jsettings->key, "log-file") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if(settings_path_exists(jsettings->string_) != 0) {
					logprintf(LOG_ERR, "setting \"%s\" must point to an existing folder", jsettings->key);
					have_error = 1;
					goto clear;				
				} else {
					settings_add_string_node(jsettings->key, jsettings->string_);
				}
			}
		} else if(strcmp(jsettings->key, "config-file") == 0 || strcmp(jsettings->key, "process-file") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must contain an existing file path", jsettings->key);
				have_error = 1;
				goto clear;
			} else if(strlen(jsettings->string_) > 0) {
				if(settings_file_exists(jsettings->string_) == 0) {
					has_config = 1;
					settings_add_string_node(jsettings->key, jsettings->string_);
				} else {
					logprintf(LOG_ERR, "setting \"%s\" must point to an existing file", jsettings->key);
					have_error = 1;
					goto clear;
				}
			}
		} else if(strcmp(jsettings->key, "socket") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must point an existing socket", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				has_socket = 1;
				settings_add_string_node(jsettings->key, jsettings->string_);
			}
		} else if(strcmp(jsettings->key, "use-lirc") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 1) {
				logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				if((int)jsettings->number_ == 1) {
					has_lirc = 1;
				}
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "webserver-port") == 0) {
			if(jsettings->number_ < 0) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a number larger than 0", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				web_port = (int)jsettings->number_;
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "webserver-root") == 0) {
			if(jsettings->string_ == NULL) {
				logprintf(LOG_ERR, "setting \"%s\" must contain a valid path", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				settings_add_string_node(jsettings->key, jsettings->string_);
			}
		} else if(strcmp(jsettings->key, "webserver-enable") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 1) {
				logprintf(LOG_ERR, "setting \"%s\" must be either 0 or 1", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}
		} else if(strcmp(jsettings->key, "gpio-receiver") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 7) {
				logprintf(LOG_ERR, "setting \"%s\" must be between 0 and 7", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				gpio_out = (int)jsettings->number_;
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}			
		} else if(strcmp(jsettings->key, "gpio-sender") == 0) {
			if(jsettings->number_ < 0 || jsettings->number_ > 7) {
				logprintf(LOG_ERR, "setting \"%s\" must be between 0 and 7", jsettings->key);
				have_error = 1;
				goto clear;
			} else {
				gpio_in = (int)jsettings->number_;
				settings_add_number_node(jsettings->key, (int)jsettings->number_);
			}			
		} else if(strcmp(jsettings->key, "server") == 0) {
			JsonNode *jserver = json_find_member(root, "server");
			JsonNode *jtmp = json_first_child(jserver);
			int i = 0;
			while(jtmp != NULL) {
				i++;
				if(jtmp->tag == JSON_STRING) {
					server_ip = strdup(jtmp->string_);
				} else if(jtmp->tag == JSON_NUMBER) {
					server_port = (int)jtmp->number_;
				}
				if(i > 2) {
					i++;
					break;
				}
				jtmp = jtmp->next;
			}
			if(i > 2) {
				logprintf(LOG_ERR, "setting \"%s\" must be in the format of [ \"x.x.x.x\", xxxx ]", jsettings->key);
				have_error = 1;
				goto clear;
			} else if(server_ip != NULL && server_port > 0 && is_node == 1) {
				settings_add_string_node("server-ip", server_ip);
				settings_add_number_node("server-port", server_port);
			} else {	
				logprintf(LOG_ERR, "setting \"%s\" must be in the format of [ \"x.x.x.x\", xxxx ]", jsettings->key);
				have_error = 1;
				goto clear;
			}
		} else {
			logprintf(LOG_ERR, "setting \"%s\" is invalid", jsettings->key);
			have_error = 1;
			goto clear;
		}
		jsettings = jsettings->next;
	}
	json_delete(jsettings);
	if(has_lirc == 1 && gpio_in > -1) {
		logprintf(LOG_ERR, "setting \"gpio-receiver\" and use-lirc cannot be combined");
		have_error = 1;
		goto clear;
	}
	if(has_lirc == 1 && gpio_out > -1) {
		logprintf(LOG_ERR, "setting \"gpio-sender\" and use-lirc cannot be combined");
		have_error = 1;
		goto clear;
	}	
	if(has_lirc == 0 && has_socket == 1) {
		logprintf(LOG_ERR, "setting \"socket\" must be combined with use-lirc");
		have_error = 1;
		goto clear;
	}
	if(server_port > 0 && server_port == own_port && is_node == 1) {
		logprintf(LOG_ERR, "setting \"port\" and \"server port\" cannot be the same");
		have_error = 1;
		goto clear;
	}
	if(web_port == own_port) {
		logprintf(LOG_ERR, "setting \"port\" and \"webserver-port\" cannot be the same");
		have_error = 1;
		goto clear;
	}
	if(is_node == 1 && has_config == 1) {
		logprintf(LOG_ERR, "a daemon running as client cannot have a config file defined");
		have_error = 1;
		goto clear;		
	}
clear:
	return have_error;
}
Ejemplo n.º 21
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, *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;
}
Ejemplo n.º 22
0
void *events_loop(void *param) {
	logprintf(LOG_STACK, "%s(...)", __FUNCTION__);

	pthread_mutexattr_init(&events_attr);
	pthread_mutexattr_settype(&events_attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutex_init(&events_lock, &events_attr);
	pthread_cond_init(&events_signal, NULL);

	struct JsonNode *jdevices = NULL, *jchilds = NULL;
	struct rules_t *tmp_rules = NULL;
	char *str = NULL;
	unsigned short match = 0;
	unsigned int i = 0;

	pthread_mutex_lock(&events_lock);
	while(loop) {
		if(eventsqueue_number > 0) {
			pthread_mutex_lock(&events_lock);

			logprintf(LOG_STACK, "%s::unlocked", __FUNCTION__);

			running = 1;

			jdevices = json_find_member(eventsqueue->jconfig, "devices");
			tmp_rules = rules_get();
			while(tmp_rules) {
				if(tmp_rules->active == 1) {
					match = 0;
					if((str = MALLOC(strlen(tmp_rules->rule)+1)) == NULL) {
						logprintf(LOG_ERR, "out of memory");
						exit(EXIT_FAILURE);
					}
					strcpy(str, tmp_rules->rule);
					/* Only run those events that affect the updates devices */
					if(jdevices != NULL) {
						jchilds = json_first_child(jdevices);
						while(jchilds) {
							for(i=0;i<tmp_rules->nrdevices;i++) {
								if(jchilds->tag == JSON_STRING &&
								   strcmp(jchilds->string_, tmp_rules->devices[i]) == 0) {
									match = 1;
									break;
								}
							}
							if(match == 1) {
								break;
							}
							jchilds = jchilds->next;
						}
					}
					if(match == 1 && tmp_rules->status == 0) {
						if(event_parse_rule(str, tmp_rules, 0, 1, 0) == 0) {
							if(tmp_rules->status) {
								logprintf(LOG_INFO, "executed rule: %s", tmp_rules->name);
							}
						}
						tmp_rules->status = 0;
					}
					FREE(str);
				}
				tmp_rules = tmp_rules->next;
			}
			struct eventsqueue_t *tmp = eventsqueue;
			json_delete(tmp->jconfig);
			eventsqueue = eventsqueue->next;
			FREE(tmp);
			eventsqueue_number--;
			running = 0;
			pthread_mutex_unlock(&events_lock);
		} else {
			pthread_cond_wait(&events_signal, &events_lock);
		}
	}
	return (void *)NULL;
}
Ejemplo n.º 23
0
void *programParse(void *param) {
	struct protocol_threads_t *pnode = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)pnode->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	struct JsonNode *jchild1 = NULL;
	char *prog = NULL, *args = NULL, *stopcmd = NULL, *startcmd = NULL;
	
	int interval = 1, nrloops = 0, currentstate = 0, laststate = -1;
	int pid = 0;
	double itmp = 0;

	program_threads++;

	json_find_string(json, "program", &prog);	
	json_find_string(json, "arguments", &args);
	json_find_string(json, "stop-command", &stopcmd);
	json_find_string(json, "start-command", &startcmd);
	
	struct programs_t *lnode = malloc(sizeof(struct programs_t));	
	lnode->wait = 0;
	lnode->pth = 0;
	
	if(args && strlen(args) > 0) {
		if(!(lnode->arguments = malloc(strlen(args)+1))) {
			logprintf(LOG_ERR, "out of memory");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->arguments, args);
	} else {
		lnode->arguments = NULL;
	}

	if(prog) {
		if(!(lnode->program = malloc(strlen(prog)+1))) {
			logprintf(LOG_ERR, "out of memory");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->program, prog);
	} else {
		lnode->program = NULL;
	}

	if(stopcmd) {
		if(!(lnode->stop = malloc(strlen(stopcmd)+1))) {
			logprintf(LOG_ERR, "out of memory");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->stop, stopcmd);
	} else {
		lnode->stop = NULL;
	}

	if(startcmd) {
		if(!(lnode->start = malloc(strlen(startcmd)+1))) {
			logprintf(LOG_ERR, "out of memory");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->start, startcmd);
	} else {
		lnode->start = NULL;
	}

	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		while(jchild) {
			jchild1 = json_first_child(jchild);
			while(jchild1) {
				if(strcmp(jchild1->key, "name") == 0) {
					if(!(lnode->name = malloc(strlen(jchild1->string_)+1))) {
						logprintf(LOG_ERR, "out of memory");
						exit(EXIT_FAILURE);
					}
					strcpy(lnode->name, jchild1->string_);
				}
				jchild1 = jchild1->next;
			}
			jchild = jchild->next;
		}
	}

	struct programs_t *tmp = programs;
	if(tmp) {
		while(tmp->next != NULL) {
			tmp = tmp->next;
		}
		tmp->next = lnode;
	} else {
		lnode->next = tmp;
		programs = lnode;
	}
	
	if(json_find_number(json, "poll-interval", &itmp) == 0)
		interval = (int)round(itmp);

	while(program_loop) {
		if(protocol_thread_wait(pnode, interval, &nrloops) == ETIMEDOUT) {
			if(lnode->wait == 0) {
				program->message = json_mkobject();

				JsonNode *code = json_mkobject();
				json_append_member(code, "name", json_mkstring(lnode->name));

				if((pid = (int)findproc(lnode->program, lnode->arguments)) > 0) {
					currentstate = 1;
					json_append_member(code, "state", json_mkstring("running"));
					json_append_member(code, "pid", json_mknumber((int)pid));
				} else {
					currentstate = 0;
					json_append_member(code, "state", json_mkstring("stopped"));
					json_append_member(code, "pid", json_mknumber(0));
				}

				json_append_member(program->message, "message", code);
				json_append_member(program->message, "origin", json_mkstring("receiver"));
				json_append_member(program->message, "protocol", json_mkstring(program->id));

				if(currentstate != laststate) {
					laststate = currentstate;									
					pilight.broadcast(program->id, program->message);
				}

				json_delete(program->message);
				program->message = NULL;
			}
		}
	}

	program_threads--;
	return (void *)NULL;
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
0
static void *thread(void *param) {
	struct protocol_threads_t *pnode = (struct protocol_threads_t *)param;
	struct JsonNode *json = (struct JsonNode *)pnode->param;
	struct JsonNode *jid = NULL;
	struct JsonNode *jchild = NULL;
	char *state = NULL, *onquery = NULL, *offquery = NULL, *onsuccess = NULL, *offsuccess = NULL;
	char *errresponse = NULL, *onuri = NULL, *offuri = NULL, *response = NULL, *method = NULL;
	int interval = 1, nrloops = 0;
	double itmp = 0;

	threads++;

	json_find_string(json, "method", &method);
	json_find_string(json, "on_uri", &onuri);
	json_find_string(json, "off_uri", &offuri);
	json_find_string(json, "on_query", &onquery);
	json_find_string(json, "off_query", &offquery);
	json_find_string(json, "on_success", &onsuccess);
	json_find_string(json, "off_success", &offsuccess);
	json_find_string(json, "err_response", &errresponse);
	json_find_string(json, "response", &response);
	json_find_string(json, "state", &state);

	struct settings_t *lnode = MALLOC(sizeof(struct settings_t));
	lnode->wait = 0;
	lnode->hasthread = 0;
	memset(&lnode->pth, '\0', sizeof(pthread_t));

	if(strcmp(state, "running") == 0) {
		lnode->newstate = 1;
	} else {
		lnode->newstate = 0;
	}
	
	lnode->id = 0;
	if((jid = json_find_member(json, "id"))) {
		jchild = json_first_child(jid);
		if(json_find_number(jchild, "id", &itmp) == 0)
			lnode->id = (int)round(itmp);
	}

	if(strcmp(method, "GET") != 0 && strcmp(method, "POST") != 0) {
		logprintf(LOG_ERR, "Webswitch %i: method must be either \"GET\" or \"POST\"", lnode->id);
		exit(EXIT_FAILURE);
	}
	
	
	if(method != NULL && strlen(method) > 0) {
		if((lnode->method = MALLOC(strlen(method)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->method, method);
	} else {
		lnode->method = NULL;
	}
	
	if(onuri != NULL && strlen(onuri) > 0) {
		if((lnode->on_uri = MALLOC(strlen(onuri)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->on_uri, onuri);
	} else {
		lnode->on_uri = NULL;
	}
	
	if(offuri != NULL && strlen(offuri) > 0) {
		if((lnode->off_uri = MALLOC(strlen(offuri)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->off_uri, offuri);
	} else {
		lnode->off_uri = NULL;
	}
	
	if(onquery != NULL && strlen(onquery) > 0) {
		if((lnode->on_query = MALLOC(strlen(onquery)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->on_query, onquery);
	} else {
		lnode->on_query = NULL;
	}

	if(offquery != NULL && strlen(offquery) > 0) {
		if((lnode->off_query = MALLOC(strlen(offquery)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->off_query, offquery);
	} else {
		lnode->off_query = NULL;
	}

	if(onsuccess != NULL && strlen(onsuccess) > 0) {
		if((lnode->on_success = MALLOC(strlen(onsuccess)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->on_success, onsuccess);
	} else {
		lnode->on_success = NULL;
	}
	
	if(offsuccess != NULL && strlen(offsuccess) > 0) {
		if((lnode->off_success = MALLOC(strlen(offsuccess)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->off_success, offsuccess);
	} else {
		lnode->off_success = NULL;
	}

	if(errresponse != NULL && strlen(errresponse) > 0) {
		if((lnode->err_response = MALLOC(strlen(errresponse)+1)) == NULL) {
			fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->err_response, errresponse);
	} else {
		lnode->err_response = NULL;
	}

	if(response != NULL && strlen(response) > 0) {
		if((lnode->response = MALLOC(strlen(response)+1)) == NULL) {
		//if((lnode->response = MALLOC(BUFFER_SIZE)) == NULL) {
		fprintf(stderr, "out of memory\n");
			exit(EXIT_FAILURE);
		}
		strcpy(lnode->response, response);
	} else {
		lnode->response = NULL;
	}

	lnode->thread = pnode;
	lnode->laststate = -1;
	lnode->currentstate = -1;

	lnode->next = settings;
	settings = lnode;

	if(json_find_number(json, "poll-interval", &itmp) == 0)
		interval = (int)round(itmp);

	while(loop) {

	if(protocol_thread_wait(pnode, interval, &nrloops) == ETIMEDOUT) {
			pthread_mutex_lock(&lock);
			if(lnode->wait == 0) {
				struct JsonNode *message = json_mkobject();

				JsonNode *code = json_mkobject();
				json_append_member(code, "id", json_mknumber(lnode->id, 0));
				json_append_member(code, "response", json_mkstring(lnode->response));
				if(lnode->currentstate == -1 && lnode->laststate == -1) {
					lnode->laststate=lnode->newstate;
				}
				if(lnode->newstate == 1) {
					lnode->currentstate = 1;
					json_append_member(code, "state", json_mkstring("running"));
				} else {
					lnode->currentstate = 0;
					json_append_member(code, "state", json_mkstring("stopped"));
				}
				json_append_member(message, "message", code);
				json_append_member(message, "origin", json_mkstring("receiver"));
				json_append_member(message, "protocol", json_mkstring(webswitch->id));

				if(lnode->currentstate != lnode->laststate) {
					lnode->laststate = lnode->currentstate;

					if(pilight.broadcast != NULL ) {
						pilight.broadcast(webswitch->id, message, PROTOCOL);
					}
				}
				json_delete(message);
				message = NULL;
			}
			pthread_mutex_unlock(&lock);
		}
	}
	pthread_mutex_unlock(&lock);

	threads--;
	return (void *)NULL;
}