Subversion Repositories heating

Rev

Rev 49 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
15 andreas 1
/*
2
 * Copyright (C) 2015 by Andreas Theofilu. All rights reserved!
3
 *
4
 * All rights reserved. No warranty, explicit or implicit, provided.
5
 *
6
 * NOTICE:  All information contained herein is, and remains
7
 * the property of Andreas Theofilu and his suppliers, if any.
8
 * The intellectual and technical concepts contained
9
 * herein are proprietary to Andreas Theofilu and its suppliers and
10
 * may be covered by European and Foreign Patents, patents in process,
11
 * and are protected by trade secret or copyright law.
12
 * Dissemination of this information or reproduction of this material
13
 * is strictly forbidden unless prior written permission is obtained
14
 * from Andreas Theofilu.
15
 * 
16
 * Author: Andreas Theofilu <andreas@theosys.at>
17
 */
18
#include <iostream>
19
#include <string>
20
#include <cstring>
21
#include <cctype>
22
#include <cstddef>
23
#include <cstdio>
24
#include <cstdlib>
17 andreas 25
#include <syslog.h>
15 andreas 26
#include <microhttpd.h>
40 andreas 27
#include <sqlite3.h>
15 andreas 28
#include "config.h"
29
#include "helper.h"
17 andreas 30
#include "controller.h"
15 andreas 31
#include "html.h"
32
 
33
using namespace std;
34
 
17 andreas 35
#define POSTBUFFERSIZE  512
36
#define MAXNAMESIZE     20
37
#define MAXANSWERSIZE   512
38
 
39
#define GET             0
40
#define POST            1
41
 
42
class HttpController : public DynamicController
43
{
44
	public:
19 andreas 45
		typedef struct
46
		{
47
			int connectiontype;
48
			string answerstring;
49
			struct MHD_PostProcessor *postprocessor;
50
		}connection_info_struct;
17 andreas 51
 
41 andreas 52
		enum REQUEST
53
		{
54
			NONE,
55
			GLOBALS,
56
			ROOM,
57
			DETAILS
58
		};
59
 
19 andreas 60
	public:
40 andreas 61
		HttpController(string mp, int *r, html::HTCONF *ht)
19 andreas 62
		{
63
			mainPage = mp;
23 andreas 64
			room = r;
65
			HeatConf = ht;
19 andreas 66
		}
35 andreas 67
 
36 andreas 68
		inline static time_t strToTime(const char *str)						// Convert a time string into a time value
35 andreas 69
		{
70
			int hour, min;
71
 
36 andreas 72
			if (strchr(str, ':') != NULL)
35 andreas 73
			{
36 andreas 74
				sscanf(str, "%d:%d", &hour, &min);
35 andreas 75
				return (time_t)hour * 3600 + (time_t)min * 60;
76
			}
77
 
78
			return 0;
79
		}
80
 
81
		inline static std::string timeToStr(time_t t)					// Convert a time value into a string
82
		{
83
			int hour, min;
36 andreas 84
			char hv0[48];
35 andreas 85
 
86
			hour = (int)(t / 3600);
39 andreas 87
			min = (int)((t - (time_t)hour * 3600) / 60);
36 andreas 88
			sprintf(hv0, "%02d:%02d", hour, min);
89
			string zeit(hv0);
35 andreas 90
			return zeit;
91
		}
92
 
40 andreas 93
		inline static void setGlobals(double *n, double *a, bool *m)
19 andreas 94
		{
95
			glb_minimal = a;
96
			glb_night = n;
97
			onoff = m;
98
		}
99
 
40 andreas 100
		inline static double getGlbNight() { return *glb_night; }
101
		inline static double getGlbAbsent() { return *glb_minimal; }
102
		inline static bool getGlbPower() { return *onoff; }
103
		inline static int getSelRoom() { return *room; }
104
		inline static html::HTCONF *getHConf() { return HeatConf; }
41 andreas 105
		inline static REQUEST getLastRequest() { return rq; }
19 andreas 106
 
17 andreas 107
		virtual bool validPath(const char* path, const char* method)
108
		{
19 andreas 109
			if (Configure.debug)
110
				syslog(LOG_DEBUG, "path=%s, method=%s", path, method);
18 andreas 111
 
19 andreas 112
			if((strcmp(path, "/") == 0 && strcmp("GET", method) == 0) ||
34 andreas 113
				(strcmp(path, "/global") == 0 && strcmp("POST", method) == 0) ||
114
				(strcmp(path, "/room") == 0 && strcmp("POST", method) == 0) ||
115
				(strcmp(path, "/details") == 0 && strcmp("POST", method) == 0))
41 andreas 116
			{
117
				if (strcmp (path, "/global") == 0)
118
					HttpController::rq = GLOBALS;
119
				else if (strcmp (path, "/room") == 0)
120
					HttpController::rq = ROOM;
121
				else if (strcmp (path, "/details") == 0)
122
					HttpController::rq = DETAILS;
123
				else
124
					HttpController::rq = NONE;
125
 
17 andreas 126
				return true;
41 andreas 127
			}
17 andreas 128
 
129
			return false;
130
		}
19 andreas 131
 
132
		static int iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
133
								const char *filename, const char *content_type,
134
								const char *transfer_encoding, const char *data, uint64_t off,
135
								size_t size)
136
		{
137
			helper h;
138
			connection_info_struct *con_info = (connection_info_struct *)coninfo_cls;
139
 
140
			if (Configure.debug)
141
				syslog(LOG_DEBUG, "Iterate: key=%s, data=%s", key, data);
142
 
143
			if (strcmp (key, "gnight") == 0)
144
			{
145
				if (size > 0 && size <= MAXNAMESIZE)
146
				{
40 andreas 147
					*glb_night = strtod(data, NULL);
148
					con_info->answerstring = h.doubleToString(*glb_night, 1);
19 andreas 149
				}
150
				else
151
					con_info->answerstring.clear();
152
			}
153
			else if (strcmp(key, "gabsent") == 0)
154
			{
155
				if (size > 0 && size <= MAXNAMESIZE)
156
				{
40 andreas 157
					*glb_minimal = strtod(data, NULL);
158
					con_info->answerstring = h.doubleToString(*glb_minimal, 1);
19 andreas 159
				}
160
				else
161
					con_info->answerstring.clear();
162
			}
23 andreas 163
			else if (strcmp(key, "mode") == 0)
164
			{
40 andreas 165
				if (data && size > 0)
23 andreas 166
				{
167
					if (strcmp(data, "normal") == 0)
40 andreas 168
						*onoff = true;
28 andreas 169
					else if (strcmp(data, "off") == 0)
40 andreas 170
						*onoff = false;
23 andreas 171
				}
172
			}
173
			else if (strcmp(key, "room") == 0)
174
			{
40 andreas 175
				if (data && size > 0)
23 andreas 176
				{
177
					int r = atoi(data);
178
 
179
					if (r)
40 andreas 180
						*room = r;
23 andreas 181
				}
182
			}
24 andreas 183
			else if (strcmp(key, "soll") == 0)
184
			{
40 andreas 185
				if (data && size > 0)
24 andreas 186
				{
187
					html::HTCONF *akt = HeatConf;
23 andreas 188
 
24 andreas 189
					while (akt)
190
					{
40 andreas 191
						if (akt->rnum == *room)
24 andreas 192
						{
193
							akt->soll = strtod(data, NULL);
194
							break;
195
						}
196
 
197
						akt = akt->next;
198
					}
199
				}
200
			}
201
			else if (strcmp(key, "night") == 0)
202
			{
40 andreas 203
				if (data && size > 0)
24 andreas 204
				{
205
					html::HTCONF *akt = HeatConf;
206
 
207
					while (akt)
208
					{
40 andreas 209
						if (akt->rnum == *room)
24 andreas 210
						{
211
							akt->night = strtod(data, NULL);
212
							break;
213
						}
214
 
215
						akt = akt->next;
216
					}
217
				}
218
			}
219
			else if (strcmp(key, "absent") == 0)
220
			{
40 andreas 221
				if (data && size > 0)
24 andreas 222
				{
223
					html::HTCONF *akt = HeatConf;
224
 
225
					while (akt)
226
					{
40 andreas 227
						if (akt->rnum == *room)
24 andreas 228
						{
229
							akt->minimal = strtod(data, NULL);
230
							break;
231
						}
232
 
233
						akt = akt->next;
234
					}
235
				}
236
			}
35 andreas 237
			else if (strcmp(key, "start1") == 0)
238
			{
40 andreas 239
				if (data && size > 0)
35 andreas 240
				{
241
					html::HTCONF *akt = HeatConf;
24 andreas 242
 
35 andreas 243
					while (akt)
244
					{
40 andreas 245
						if (akt->rnum == *room)
35 andreas 246
						{
36 andreas 247
							akt->start1 = strToTime(data);
35 andreas 248
							break;
249
						}
250
 
251
						akt = akt->next;
252
					}
253
				}
254
			}
255
			else if (strcmp(key, "end1") == 0)
256
			{
40 andreas 257
				if (data && size > 0)
35 andreas 258
				{
259
					html::HTCONF *akt = HeatConf;
260
 
261
					while (akt)
262
					{
40 andreas 263
						if (akt->rnum == *room)
35 andreas 264
						{
36 andreas 265
							akt->end1 = strToTime(data);
35 andreas 266
							break;
267
						}
268
 
269
						akt = akt->next;
270
					}
271
				}
272
			}
273
			else if (strcmp(key, "start2") == 0)
274
			{
40 andreas 275
				if (data && size > 0)
35 andreas 276
				{
277
					html::HTCONF *akt = HeatConf;
278
 
279
					while (akt)
280
					{
40 andreas 281
						if (akt->rnum == *room)
35 andreas 282
						{
36 andreas 283
							akt->start2 = strToTime(data);
35 andreas 284
							break;
285
						}
286
 
287
						akt = akt->next;
288
					}
289
				}
290
			}
291
			else if (strcmp(key, "end2") == 0)
292
			{
40 andreas 293
				if (data && size > 0)
35 andreas 294
				{
295
					html::HTCONF *akt = HeatConf;
296
 
297
					while (akt)
298
					{
40 andreas 299
						if (akt->rnum == *room)
35 andreas 300
						{
36 andreas 301
							akt->end2 = strToTime(data);
35 andreas 302
							break;
303
						}
304
 
305
						akt = akt->next;
306
					}
307
				}
308
			}
309
 
19 andreas 310
			return MHD_YES;
311
		}
312
 
17 andreas 313
		virtual void createResponse(struct MHD_Connection *connection,
19 andreas 314
        				const char *url, const char *method, const char *upload_data,
315
        				size_t *upload_data_size, std::stringstream& response, void **ptr)
17 andreas 316
		{
19 andreas 317
			string mp = mainPage;
318
			helper h;
23 andreas 319
			html::HTCONF *akt = HeatConf;
19 andreas 320
 
321
			// Replace the place holders with data
40 andreas 322
			mp.replace(mp.find("#01#"), 4, h.doubleToString(*glb_night, 1));
323
			mp.replace(mp.find("#02#"), 4, h.doubleToString(*glb_minimal, 1));
19 andreas 324
 
40 andreas 325
			if (*onoff)
19 andreas 326
			{
327
				mp.replace(mp.find("#03#"), 4, " checked");
328
				mp.erase(mp.find("#04#"), 4);
329
			}
330
			else
331
			{
332
				mp.erase(mp.find("#03#"), 4);
333
				mp.replace(mp.find("#04#"), 4, " checked");
334
			}
335
 
27 andreas 336
			int c = 100;
337
 
23 andreas 338
			while (akt)
339
			{
40 andreas 340
				if (akt->rnum == *room)
23 andreas 341
				{
27 andreas 342
					mp.replace(mp.find("#"+h.itostring(c)+"#"), 5, " selected");
35 andreas 343
					mp.replace(mp.find("#05#"), 4, h.doubleToString(akt->soll, 1));
344
					mp.replace(mp.find("#06#"), 4, h.doubleToString(akt->night, 1));
345
					mp.replace(mp.find("#07#"), 4, h.doubleToString(akt->minimal, 1));
346
					mp.replace(mp.find("#08#"), 4, timeToStr(akt->start1));
347
					mp.replace(mp.find("#09#"), 4, timeToStr(akt->end1));
348
					mp.replace(mp.find("#10#"), 4, timeToStr(akt->start2));
349
					mp.replace(mp.find("#11#"), 4, timeToStr(akt->end2));
23 andreas 350
				}
27 andreas 351
				else
352
					mp.erase(mp.find("#"+h.itostring(c)+"#"), 5);
23 andreas 353
 
354
				akt = akt->next;
27 andreas 355
				c++;
23 andreas 356
			}
357
 
19 andreas 358
			response << mp;
17 andreas 359
		}
360
 
361
	private:
362
		string mainPage;
40 andreas 363
		static double *glb_minimal;						// The global temperature for normal (day) mode
364
		static double *glb_night;						// The global temperature for night mode
365
		static bool *onoff;								// True if heating is in normal or night mode
366
		static int *room;
41 andreas 367
		static REQUEST rq;
24 andreas 368
		static html::HTCONF *HeatConf;
17 andreas 369
};
370
 
40 andreas 371
double *HttpController::glb_night = nullptr;
372
double *HttpController::glb_minimal = nullptr;
373
bool *HttpController::onoff = nullptr;
374
int *HttpController::room = nullptr;
24 andreas 375
html::HTCONF *HttpController::HeatConf;
41 andreas 376
HttpController::REQUEST HttpController::rq = HttpController::REQUEST::NONE;
19 andreas 377
 
378
std::string html::intErrorPage;
46 andreas 379
bool html::datar = false;
19 andreas 380
 
15 andreas 381
html::html()
382
{
18 andreas 383
	enableDebug(Configure.debug);
17 andreas 384
	HeatConf = nullptr;
385
	glb_night = 0.0;
386
	glb_absent = 0.0;
387
	stop = false;
388
	daemon = nullptr;
23 andreas 389
	room = 0;
16 andreas 390
}
391
 
392
html::~html()
393
{
17 andreas 394
HTCONF *akt = HeatConf;
16 andreas 395
 
17 andreas 396
	if (daemon)
397
		MHD_stop_daemon (daemon);
398
 
399
	while (akt)
400
	{
401
		HTCONF *p;
402
 
403
		p = akt->next;
404
		delete akt;
405
		akt = p;
406
	}
16 andreas 407
}
408
 
17 andreas 409
void html::run()
16 andreas 410
{
18 andreas 411
	initPages();
40 andreas 412
	HttpController HtmlPage(mainPage, &room, HeatConf);
413
	HtmlPage.setGlobals(&glb_night, &glb_absent, &mode);
18 andreas 414
	addController(&HtmlPage);
19 andreas 415
	daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, Configure.html_port, NULL, NULL,
416
							  &request_handler, this,
417
							  MHD_OPTION_NOTIFY_COMPLETED, &request_completed, NULL,
418
							  MHD_OPTION_END);
17 andreas 419
 
420
	while (!stop)
421
		sleep(60);
16 andreas 422
 
17 andreas 423
	MHD_stop_daemon (daemon);
424
}
425
 
426
void html::initPages()
427
{
428
HTCONF *akt = HeatConf;
429
 
15 andreas 430
	// This is the main page
431
	mainPage = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n";
432
	mainPage.append ("\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n");
433
	mainPage.append ("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"de\" lang=\"de\">\n\n");
434
	mainPage.append ("<head>\n");
435
	mainPage.append ("<title>Heizungsteuerung</title>\n");
436
	mainPage.append ("<META NAME=\"author\" CONTENT=\"Andreas Theofilu\">\n");
437
	mainPage.append ("<META NAME=\"publisher\" CONTENT=\"Andreas Theofilu (TheoSys)\">\n");
438
	mainPage.append ("<META NAME=\"copyright\" CONTENT=\"(C) 2015 by Andreas Theofilu\">\n");
439
	mainPage.append ("<meta name=\"Description\" content=\"Heating control\">\n");
440
	mainPage.append ("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
441
	mainPage.append ("<meta NAME=\"content-language\" content=\"de\">\n");
442
	mainPage.append ("</head>\n");
443
	mainPage.append ("<body>\n");
16 andreas 444
 
15 andreas 445
	mainPage.append ("<h1>Heizungsteuerung</h1>\n");
446
	mainPage.append ("<table border=1 cellpadding=0 cellspacing=0>\n");
447
	mainPage.append ("<tr><td>");
16 andreas 448
 
15 andreas 449
	mainPage.append ("<table border=0>\n");
34 andreas 450
	mainPage.append ("<form name=\"global\" action=\"/global\" method=\"post\">");
35 andreas 451
	mainPage.append ("<tr><td>Nachtabsenkung</td><td><input type=\"number\" name=\"gnight\"  min=\"16.0\" max=\"25.0\" step=\"0.5\" value=\"#01#\"></td></tr>\n");
40 andreas 452
	mainPage.append ("<tr><td>Abwesend</td><td><input type=\"number\" name=\"gabsent\" min=\"16.0\" max=\"25.0\" step=\"0.5\" value=\"#02#\"></td></tr>\n");
33 andreas 453
	mainPage.append ("</table></td></tr>\n");
19 andreas 454
	mainPage.append ("<tr><td><input type=\"radio\" name=\"mode\" value=\"normal\"#03#>Anwesend&nbsp;&nbsp;<input type=\"radio\" name=\"mode\" value=\"off\"#04#>Abwesend</td></tr>\n");
17 andreas 455
 
33 andreas 456
	mainPage.append ("<tr><td><input type=\"submit\" value=\"Speichern\"></form></td></tr>\n");
15 andreas 457
	mainPage.append ("</table>\n");
16 andreas 458
 
15 andreas 459
	mainPage.append ("<table border=1 cellpadding=0 cellspacing=0>\n");
460
	mainPage.append ("<tr><td>");
16 andreas 461
 
34 andreas 462
	mainPage.append ("<form name=\"choose\" action=\"/room\" method=\"post\">");
15 andreas 463
	mainPage.append ("<table border=0>\n");
33 andreas 464
	mainPage.append ("<tr><td>Raum</td><td><select name=\"room\" onChange=\"javascript:document.choose.submit()\">\n");
32 andreas 465
 
27 andreas 466
	int c = 100;
467
 
17 andreas 468
	while (akt)
469
	{
23 andreas 470
		if (!room)
471
			room = akt->rnum;
472
 
32 andreas 473
		mainPage.append ("<option value=\"" + itostring(akt->rnum) + "\"#" + itostring(c) + "#>" + ToString(akt->rname) +"</option>\n");
17 andreas 474
		akt = akt->next;
27 andreas 475
		c++;
17 andreas 476
	}
477
 
478
	akt = HeatConf;
35 andreas 479
	mainPage.append ("</select>\n<input type=\"submit\" value=\"Auswahl\"></form>\n");
480
	mainPage.append ("<form name=\"details\" action=\"/details\" method=\"post\"></td></tr>\n");
481
	mainPage.append ("<tr><td>Solltemperatur</td><td><input type=\"number\" name=\"soll\" min=\"16.0\" max=\"30.0\" step=\"0.5\" value=\"#05#\"></td></tr>\n");
45 andreas 482
	mainPage.append ("<tr><td>Nachtabsenkung</td><td><input type=\"number\" name=\"night\" min=\"0.0\" max=\"25.0\" step=\"0.5\" value=\"#06#\"></td></tr>\n");
483
	mainPage.append ("<tr><td>Abwesenheit</td><td><input type=\"number\" name=\"absent\" min=\"0.0\" max=\"25.0\" step=\"0.5\" value=\"#07#\"></td></tr>\n");
35 andreas 484
	mainPage.append ("<tr><td colspan=2>&nbsp;</td></tr>\n");
485
	mainPage.append ("<tr><td>Startzeit Tagbetrieb</td><td><input type=\"time\" name=\"start1\" placeholder=\"23:59\" value=\"#08#\"></td></tr>\n");
40 andreas 486
	mainPage.append ("<tr><td>Startzeit Nachtbetrieb</td><td><input type=\"time\" name=\"end1\" placeholder=\"23:59\" value=\"#09#\"></td></tr>\n");
487
	mainPage.append ("<tr><td>Startzeit Werktag</td><td><input type=\"time\" name=\"start2\" placeholder=\"23:59\" value=\"#10#\"></td></tr>\n");
488
	mainPage.append ("<tr><td>Endzeit Werktag</td><td><input type=\"time\" name=\"end2\" placeholder=\"23:59\" value=\"#11#\"></td></tr>\n");
33 andreas 489
	mainPage.append ("<tr><td>&nbsp;</td><td><input type=\"submit\" value=\"Speichern\"></form></td></tr>\n");
16 andreas 490
 
15 andreas 491
	mainPage.append ("</table></td></tr></table>\n");
492
	mainPage.append ("</body>\n</html>\n");
19 andreas 493
 
494
	// Internal error page
495
	intErrorPage = "<html><body>An internal server error has occured!</body></html>";
15 andreas 496
}
17 andreas 497
 
498
html::HTCONF *html::addConfig(HTCONF *ht)
499
{
500
HTCONF *akt;
501
 
502
	akt = new HTCONF;
503
	memmove (akt, ht, sizeof(HTCONF));
504
	akt->next = nullptr;
505
 
506
	if (HeatConf == nullptr)
507
		HeatConf = akt;
508
	else
509
	{
50 andreas 510
		HTCONF *p, *prev;
17 andreas 511
 
50 andreas 512
		p = prev = HeatConf;
17 andreas 513
 
50 andreas 514
		while (p)
49 andreas 515
		{
50 andreas 516
			prev = p;
517
 
49 andreas 518
			if (p->rnum == ht->rnum)
519
			{
520
				p->soll = ht->soll;
521
				p->night = ht->night;
522
				p->minimal = ht->minimal;
523
				p->start1 = ht->start1;
524
				p->end1 = ht->end1;
525
				p->start2 = p->start2;
526
				p->end2 = p->end2;
527
				delete akt;
50 andreas 528
				debug("html::addConfig(): rname="+ToString(p->rname)+", rnum="+itostring(p->rnum)+", Orig:"+ToString(ht->rname)+":"+itostring(ht->rnum));
49 andreas 529
				return p;
530
			}
531
 
17 andreas 532
			p = p->next;
49 andreas 533
		}
17 andreas 534
 
50 andreas 535
		prev->next = akt;
17 andreas 536
	}
537
 
18 andreas 538
	debug("html::addConfig(): rname="+ToString(akt->rname)+", rnum="+itostring(akt->rnum));
17 andreas 539
	return akt;
540
}
541
 
542
/*
543
 * The following functions are callbacks for the HTML server
544
 */
19 andreas 545
int html::request_handler(void* cls, struct MHD_Connection *connection,
546
							   const char *url, const char *method, const char* version,
547
							   const char *upload_data, size_t *upload_data_size, void **ptr)
17 andreas 548
{
549
html *server = (html *)cls;
550
 
551
	Controller *controller = 0;
552
 
553
	for (int i = 0; i < (int)server->controllers.size(); i++)
554
	{
555
		Controller *c = server->controllers.at(i);
556
 
557
		if(c->validPath(url, method))
558
		{
559
			controller = c;
560
			break;
561
		}
562
	}
563
 
564
	if (!controller)
565
	{
18 andreas 566
		syslog(LOG_WARNING, "Path <%s> not found.", url);
19 andreas 567
		struct MHD_Response* response = MHD_create_response_from_buffer(strlen(intErrorPage.c_str()), (void *)intErrorPage.c_str(), MHD_RESPMEM_PERSISTENT);
568
		return MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
17 andreas 569
	}
19 andreas 570
	else
571
	{
572
		if (*ptr == NULL)
573
		{
574
			HttpController::connection_info_struct *con_info;
22 andreas 575
 
19 andreas 576
			if (Configure.debug)
577
				syslog(LOG_DEBUG, "Initializing postprocessor (url=%s, method=%s, upload_data=%s, upload_data_size=%d)", url, method, upload_data, upload_data_size);
22 andreas 578
 
579
			if (Configure.debug)
580
				syslog(LOG_DEBUG, "Initializing postprocessor (url=%s, method=%s, upload_data=%s, upload_data_size=%d)", url, method, upload_data, upload_data_size);
581
 
19 andreas 582
			con_info = new HttpController::connection_info_struct;
583
			con_info->answerstring.clear();
22 andreas 584
 
19 andreas 585
			if (strcmp (method, "POST") == 0)
586
			{
587
				con_info->postprocessor = MHD_create_post_processor (connection, POSTBUFFERSIZE, HttpController::iterate_post, (void *)con_info);
22 andreas 588
 
19 andreas 589
				if (con_info->postprocessor == NULL)
590
				{
591
					delete con_info;
592
					syslog(LOG_WARNING, "Error creating a HTML post processor");
593
					return MHD_NO;
594
				}
22 andreas 595
 
19 andreas 596
				con_info->connectiontype = POST;
597
			}
598
			else
599
				con_info->connectiontype = GET;
22 andreas 600
 
19 andreas 601
			*ptr = (void *)con_info;
22 andreas 602
			return MHD_YES;
19 andreas 603
		}
20 andreas 604
 
605
		if (strcmp (method, "POST") == 0)
606
		{
607
			HttpController::connection_info_struct *con_info = (HttpController::connection_info_struct *)*ptr;
22 andreas 608
 
609
			if (Configure.debug)
610
				syslog(LOG_DEBUG, "Executing postprocessor (url=%s, method=%s, upload_data=%s, upload_data_size=%d)", url, method, upload_data, upload_data_size);
611
 
20 andreas 612
			if (*upload_data_size != 0)
613
			{
614
				MHD_post_process (con_info->postprocessor, upload_data, *upload_data_size);
615
				*upload_data_size = 0;
616
				return MHD_YES;
617
			}
618
		}
19 andreas 619
	}
17 andreas 620
 
19 andreas 621
	return controller->handleRequest(connection, url, method, upload_data, upload_data_size, ptr);
17 andreas 622
}
623
 
19 andreas 624
void html::request_completed (void *cls, struct MHD_Connection *connection,
625
							void **con_cls, enum MHD_RequestTerminationCode toe)
626
{
40 andreas 627
sqlite3 *db;
628
sqlite3_stmt *res;
629
int rc;
630
char *zErrMsg = nullptr;
631
string query;
632
html::HTCONF *akt = HttpController::getHConf();
633
helper h;
634
 
19 andreas 635
	HttpController::connection_info_struct *con_info = (HttpController::connection_info_struct *)*con_cls;
28 andreas 636
 
637
	if (Configure.debug)
638
		syslog(LOG_DEBUG, "Request was completed.");
639
 
19 andreas 640
	if (con_info == nullptr)
641
		return;
28 andreas 642
 
19 andreas 643
	if (con_info->connectiontype == POST)
644
		MHD_destroy_post_processor (con_info->postprocessor);
28 andreas 645
 
19 andreas 646
	delete con_info;
647
	*con_cls = nullptr;
40 andreas 648
 
649
	// Here everything should be processed. So it's time to get the results.
43 andreas 650
	if (HttpController::getLastRequest() == HttpController::REQUEST::GLOBALS ||
651
		HttpController::getLastRequest() == HttpController::REQUEST::DETAILS)
652
	{
653
		if (Configure.debug)
654
			syslog(LOG_DEBUG, "Values %s will be saved...", (HttpController::getLastRequest() == HttpController::REQUEST::GLOBALS)?"GLOBALS":"DETAILS");
41 andreas 655
 
43 andreas 656
		rc = sqlite3_open(Configure.home, &db);
41 andreas 657
 
43 andreas 658
		if (rc)
659
		{
660
			syslog(LOG_DAEMON, "Error opening database %s: %s", Configure.home, sqlite3_errmsg(db));
661
			return;
662
		}
40 andreas 663
 
43 andreas 664
		if (HttpController::getLastRequest() == HttpController::REQUEST::DETAILS)
40 andreas 665
		{
43 andreas 666
			while (akt)
41 andreas 667
			{
43 andreas 668
				if (akt->rnum == HttpController::getSelRoom())
669
				{
670
					query = "update heating ";
671
					query.append("set name = \""+string(akt->rname)+"\"");
672
					query.append(",soll = "+h.doubleToString(akt->soll, 1));
673
					query.append(",night = "+h.doubleToString(akt->night, 1));
674
					query.append(",minimal = "+h.doubleToString(akt->minimal, 1));
675
					query.append(",start = "+h.itostring(akt->start1));
676
					query.append(",end = "+h.itostring(akt->end1));
677
					query.append(" where id = " + h.itostring(akt->rnum));
678
					rc = sqlite3_exec(db, query.c_str(), NULL, NULL, &zErrMsg);
40 andreas 679
 
43 andreas 680
					if (rc != SQLITE_OK)
681
					{
682
						syslog(LOG_WARNING, "SQL error [%s]: %s", query.c_str(), zErrMsg);
683
						sqlite3_free(zErrMsg);
684
						sqlite3_close(db);
685
						return;
686
					}
41 andreas 687
				}
43 andreas 688
 
689
				akt = akt->next;
40 andreas 690
			}
46 andreas 691
 
692
			datar = true;
40 andreas 693
		}
694
 
43 andreas 695
		if (HttpController::getLastRequest() == HttpController::REQUEST::GLOBALS)
696
		{
697
			query = "update glbheat set night = ";
698
			query.append(h.doubleToString(HttpController::getGlbNight(), 1));
699
			query.append(", minimal = "+h.doubleToString(HttpController::getGlbAbsent(), 1));
700
			query.append(", onoff = "+h.itostring(HttpController::getGlbPower()));
40 andreas 701
 
43 andreas 702
			rc = sqlite3_exec(db, query.c_str(), NULL, NULL, &zErrMsg);
40 andreas 703
 
43 andreas 704
			if (rc != SQLITE_OK)
705
			{
706
				syslog(LOG_WARNING, "SQL error [%s]: %s", query.c_str(), zErrMsg);
707
				sqlite3_free(zErrMsg);
708
				sqlite3_close(db);
709
				return;
710
			}
46 andreas 711
 
712
			datar = true;
41 andreas 713
		}
40 andreas 714
 
43 andreas 715
		sqlite3_close(db);
42 andreas 716
 
43 andreas 717
		if (Configure.debug)
718
			syslog(LOG_DEBUG, "Values successfully saved.");
719
	}
19 andreas 720
}
721
 
17 andreas 722
void html::addController(Controller* controller)
723
{
724
	controllers.push_back(controller);
725
}