thermferm/server.c

changeset 48
d8c64f81b192
parent 46
000399c64d3f
child 49
92a9ca143677
equal deleted inserted replaced
47:e2c1f2373be0 48:d8c64f81b192
28 extern bool my_shutdown; 28 extern bool my_shutdown;
29 extern bool debug; 29 extern bool debug;
30 extern int lcdHandle; 30 extern int lcdHandle;
31 extern unsigned char lcdbuf[MAX_LCDS][20][4]; 31 extern unsigned char lcdbuf[MAX_LCDS][20][4];
32 extern sys_config Config; 32 extern sys_config Config;
33 extern int clients;
34 33
35 int s; /* connected socket */ 34 int s; /* connected socket */
36 int ls; /* listen socket */ 35 int ls; /* listen socket */
37 36
38 struct sockaddr_in myaddr_in; /* for local socket address */ 37 struct sockaddr_in myaddr_in; /* for local socket address */
41 struct hostent *hp; 40 struct hostent *hp;
42 41
43 #define SS_BUFSIZE 1024 42 #define SS_BUFSIZE 1024
44 #define SS_TIMEOUT 300 43 #define SS_TIMEOUT 300
45 44
45 unsigned char cs_mode = 'o'; /* o = Off, f = fridge, b = beer, p = profile-run */
46 float cs_beerSet = 20.0;
47 float cs_fridgeSet = 20.0;
48 float cs_heatEstimator = 0.2;
49 float cs_coolEstimator = 5;
50
51 unsigned char cc_tempFormat = 'C';
52 float cc_tempSetMin = 1.0;
53 float cc_tempSetMax = 30.0;
54 float cc_idleRangeH = 1.000;
55 float cc_idleRangeL = -1.000;
56
57 float cv_beerDiff = 0.0;
58
46 59
47 60
48 void defaultControlsettings(void) 61 void defaultControlsettings(void)
49 { 62 {
50 beer->cs_mode = 'o'; /* o = Off, f = fridge, b = beer, p = profile-run */ 63 cs_mode = 'o'; /* o = Off, f = fridge, b = beer, p = profile-run */
51 beer->cs_beerSet = 20.0; 64 cs_beerSet = 20.0;
52 beer->cs_fridgeSet = 20.0; 65 cs_fridgeSet = 20.0;
53 beer->cs_heatEstimator = 0.2; 66 cs_heatEstimator = 0.2;
54 beer->cs_coolEstimator = 5; 67 cs_coolEstimator = 5;
55 } 68 }
56 69
57 70
58 71
59 void defaultControlConstants(void) 72 void defaultControlConstants(void)
60 { 73 {
61 beer->cc_tempFormat = 'C'; 74 cc_tempFormat = 'C';
62 beer->cc_tempSetMin = 1.0; 75 cc_tempSetMin = 1.0;
63 beer->cc_tempSetMax = 30.0; 76 cc_tempSetMax = 30.0;
64 beer->cc_idleRangeH = 1.000; 77 cc_idleRangeH = 1.000;
65 beer->cc_idleRangeL = -1.000; 78 cc_idleRangeL = -1.000;
66 } 79 }
67 80
68 81
69 82
70 void defaultControlVariables(void) 83 void defaultControlVariables(void)
71 { 84 {
72 beer->cv_beerDiff = 0.0; 85 cv_beerDiff = 0.0;
73 } 86 }
74 87
75 88
76 89
77 /* 90 /*
87 100
88 va_start(va_ptr, format); 101 va_start(va_ptr, format);
89 vsnprintf(out, SS_BUFSIZE-1, format, va_ptr); 102 vsnprintf(out, SS_BUFSIZE-1, format, va_ptr);
90 va_end(va_ptr); 103 va_end(va_ptr);
91 104
92 syslog(LOG_NOTICE, "send: \"%s\"", out); 105 if (debug) {
93 if (debug) 106 syslog(LOG_NOTICE, "send: \"%s\"", out);
94 fprintf(stdout, "send: \"%s\"\n", out); 107 fprintf(stdout, "send: \"%s\"\n", out);
108 }
95 109
96 if (send(s, out, strlen(out), 0) != strlen(out)) { 110 if (send(s, out, strlen(out), 0) != strlen(out)) {
97 syslog(LOG_NOTICE, "srv_send failed"); 111 syslog(LOG_NOTICE, "srv_send failed");
98 return -1; 112 return -1;
99 } 113 }
118 132
119 133
120 void cmd_server(void) 134 void cmd_server(void)
121 { 135 {
122 char *inp, *hostname, buf[SS_BUFSIZE], obuf[SS_BUFSIZE]; 136 char *inp, *hostname, buf[SS_BUFSIZE], obuf[SS_BUFSIZE];
123 int i, rc, rlen, timer; 137 int i, rc, rlen;
124 socklen_t fromlen; 138 socklen_t fromlen;
125 struct pollfd pfd[1];
126 float newtemp; 139 float newtemp;
127
128 /*
129 * Close listen socket
130 */
131 close(ls);
132 /*
133 * Install private signal handler.
134 */
135 for (i = 0; i < NSIG; i++) {
136 if ((i == SIGHUP) || (i == SIGPIPE) || (i == SIGBUS) || (i == SIGILL) || (i == SIGSEGV))
137 signal(i, (void (*))cmd_die);
138 else
139 signal(i, SIG_IGN);
140 }
141 140
142 hp = gethostbyaddr ((char *) &peeraddr_in.sin_addr, sizeof(struct in_addr), peeraddr_in.sin_family); 141 hp = gethostbyaddr ((char *) &peeraddr_in.sin_addr, sizeof(struct in_addr), peeraddr_in.sin_family);
143 if (hp == NULL) { 142 if (hp == NULL) {
144 hostname = inet_ntoa(peeraddr_in.sin_addr); 143 hostname = inet_ntoa(peeraddr_in.sin_addr);
145 } else { 144 } else {
146 hostname = hp->h_name; 145 hostname = hp->h_name;
147 } 146 }
148 147
149 clients++; 148 if (debug) {
150 syslog(LOG_NOTICE, "Start new client connection (%d) from %s port %u", clients, hostname, ntohs(peeraddr_in.sin_port)); 149 syslog(LOG_NOTICE, "Start new client connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
151 if (debug) 150 fprintf(stdout, "Start new client connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port));
152 fprintf(stdout, "Start new client connection (%d) from %s port %u\n", clients, hostname, ntohs(peeraddr_in.sin_port)); 151 }
153 timer = SS_TIMEOUT * 4; 152
154 153 memset((char *)&buf, 0, SS_BUFSIZE);
155 /* 154 fromlen = sizeof(peeraddr_in);
156 * Receive loop 155 rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen);
157 */ 156 if (rlen == -1) {
158 for (;;) { 157 syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno));
159 /* 158 } else {
160 * Poll socket until a define timeout of 0,25 second. 159 for (i = 0; i < strlen(buf); i++) {
161 */ 160 if (buf[i] == '\n')
162 pfd[0].fd = s; 161 buf[i] = '\0';
163 pfd[0].events = POLLIN; 162 if (buf[i] == '\r')
164 pfd[0].revents = 0; 163 buf[i] = '\0';
165 rc = poll(pfd, 1, 250); 164 }
166 165 if (strlen(buf)) {
167 if (rc == -1) { 166 if (debug) {
167 syslog(LOG_NOTICE, "recv: \"%s\"", buf);
168 fprintf(stdout, "recv: \"%s\"\n", buf);
169 }
170
168 /* 171 /*
169 * Poll can be interrupted by a finished child so that's not a real error. 172 * Process commands from the client
170 */ 173 */
171 if (errno != EINTR) { 174 if (strncmp(buf, "ack", 3) == 0) {
172 syslog(LOG_NOTICE, "poll() rc=%d sock=%d events=%04x", rc, s, pfd[0].revents); 175 srv_send((char *)"ack");
173 } 176 } else if (strncmp(buf, "lcd", 3) == 0) {
174 } else if (rc) { 177 sprintf(obuf, "[\" \", \" \", \" \", \" \"]");
175 if (pfd[0].revents & POLLIN) { 178 for (i = 0; i < 20; i++) {
176 memset((char *)&buf, 0, SS_BUFSIZE); 179 obuf[i+2] = lcdbuf[lcdHandle][i][0];
177 fromlen = sizeof(peeraddr_in); 180 obuf[i+26] = lcdbuf[lcdHandle][i][1];
178 rlen = recvfrom(s, buf, sizeof(buf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); 181 obuf[i+50] = lcdbuf[lcdHandle][i][2];
179 if (rlen == -1) { 182 obuf[i+74] = lcdbuf[lcdHandle][i][3];
180 syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno));
181 } else {
182 for (i = 0; i < strlen(buf); i++) {
183 if (buf[i] == '\n')
184 buf[i] = '\0';
185 if (buf[i] == '\r')
186 buf[i] = '\0';
187 }
188 timer = SS_TIMEOUT * 4;
189 if (strlen(buf)) {
190 syslog(LOG_NOTICE, "recv: \"%s\"", buf);
191 if (debug)
192 fprintf(stdout, "recv: \"%s\"\n", buf);
193
194 /*
195 * Process commands from the client
196 */
197 if (strncmp(buf, "ack", 3) == 0) {
198 srv_send((char *)"ack");
199 } else if (strncmp(buf, "lcd", 3) == 0) {
200 sprintf(obuf, "[\" \", \" \", \" \", \" \"]");
201 for (i = 0; i < 20; i++) {
202 obuf[i+2] = lcdbuf[lcdHandle][i][0];
203 obuf[i+26] = lcdbuf[lcdHandle][i][1];
204 obuf[i+50] = lcdbuf[lcdHandle][i][2];
205 obuf[i+74] = lcdbuf[lcdHandle][i][3];
206 }
207 srv_send(obuf);
208 } else if (strncmp(buf, "getMode", 7) == 0) {
209 srv_send("%c", beer->cs_mode);
210 } else if (strncmp(buf, "getFridge", 9) == 0) {
211 srv_send("%.1f", beer->cs_fridgeSet);
212 } else if (strncmp(buf, "getBeer", 7) == 0) {
213 srv_send("%.1f", beer->cs_beerSet);
214 } else if (strncmp(buf, "getControlConstants", 19) == 0) {
215 srv_send("{ \"tempFormat\":\"%c\", \"tempSetMin\":%.1f, \"tempSetMax\":%.1f, \"idleRangeH\":%.3f, \"idleRangeL\":%.3f }",
216 beer->cc_tempFormat, beer->cc_tempSetMin, beer->cc_tempSetMax, beer->cc_idleRangeH, beer->cc_idleRangeL );
217 } else if (strncmp(buf, "getControlSettings", 18) == 0) {
218 srv_send("{ \"mode\":\"%c\", \"beerSet\":%.1f, \"fridgeSet\":%.1f, \"heatEstimator\":%.1f, \"coolEstimator\":%.1f }",
219 beer->cs_mode, beer->cs_beerSet, beer->cs_fridgeSet, beer->cs_heatEstimator, beer->cs_coolEstimator);
220 } else if (strncmp(buf, "getControlVariables", 19) == 0) {
221 srv_send("{ \"beerDiff\":%.2f }", beer->cv_beerDiff);
222 } else if (strncmp(buf, "setBeer=", 8) == 0) {
223 inp = xstrcpy(buf+8);
224 rc = sscanf(inp, "%f", &newtemp);
225 if (debug)
226 fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc);
227 if (rc == 1) {
228 srv_send("ack");
229 beer->cs_mode = 'b';
230 beer->cs_beerSet = newtemp;
231 } else {
232 srv_send("err");
233 }
234 } else if (strncmp(buf, "setFridge=", 10) == 0) {
235 inp = xstrcpy(buf+10);
236 rc = sscanf(inp, "%f", &newtemp);
237 if (debug)
238 fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc);
239 if (rc == 1) {
240 srv_send("ack");
241 beer->cs_mode = 'f';
242 beer->cs_fridgeSet = newtemp;
243 } else {
244 srv_send("err");
245 }
246 } else {
247 if (debug)
248 fprintf(stdout, "unknown command \"%s\"\n", buf);
249 srv_send((char *)"ERR");
250 }
251 break;
252 }
253 } 183 }
184 srv_send(obuf);
185 } else if (strncmp(buf, "getMode", 7) == 0) {
186 srv_send("%c", cs_mode);
187 } else if (strncmp(buf, "getFridge", 9) == 0) {
188 srv_send("%.1f", cs_fridgeSet);
189 } else if (strncmp(buf, "getBeer", 7) == 0) {
190 srv_send("%.1f", cs_beerSet);
191 } else if (strncmp(buf, "getControlConstants", 19) == 0) {
192 srv_send("{ \"tempFormat\":\"%c\", \"tempSetMin\":%.1f, \"tempSetMax\":%.1f, \"idleRangeH\":%.3f, \"idleRangeL\":%.3f }",
193 cc_tempFormat, cc_tempSetMin, cc_tempSetMax, cc_idleRangeH, cc_idleRangeL );
194 } else if (strncmp(buf, "getControlSettings", 18) == 0) {
195 srv_send("{ \"mode\":\"%c\", \"beerSet\":%.1f, \"fridgeSet\":%.1f, \"heatEstimator\":%.1f, \"coolEstimator\":%.1f }",
196 cs_mode, cs_beerSet, cs_fridgeSet, cs_heatEstimator, cs_coolEstimator);
197 } else if (strncmp(buf, "getControlVariables", 19) == 0) {
198 srv_send("{ \"beerDiff\":%.2f }", cv_beerDiff);
199 } else if (strncmp(buf, "setBeer=", 8) == 0) {
200 inp = xstrcpy(buf+8);
201 rc = sscanf(inp, "%f", &newtemp);
202 if (debug)
203 fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc);
204 if (rc == 1) {
205 srv_send("ack");
206 cs_mode = 'b';
207 cs_beerSet = newtemp;
208 } else {
209 srv_send("err");
210 }
211 free(inp);
212 } else if (strncmp(buf, "setFridge=", 10) == 0) {
213 inp = xstrcpy(buf+10);
214 rc = sscanf(inp, "%f", &newtemp);
215 if (debug)
216 fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc);
217 if (rc == 1) {
218 srv_send("ack");
219 cs_mode = 'f';
220 cs_fridgeSet = newtemp;
221 } else {
222 srv_send("err");
223 }
224 free(inp);
254 } else { 225 } else {
255 syslog(LOG_NOTICE, "poll other event"); 226 if (debug)
256 } 227 fprintf(stdout, "unknown command \"%s\"\n", buf);
257 228 srv_send((char *)"ERR");
258 } else {
259 /*
260 * Poll timeout, do some housekeeping
261 */
262 if (timer) {
263 timer--;
264 } else {
265 /* Inactivity timeout */
266 break;
267 }
268 if (my_shutdown) {
269 break;
270 } 229 }
271 } 230 }
272 } 231 }
273 232
274 if (clients) 233 if (debug) {
275 clients--; 234 syslog(LOG_NOTICE, "End connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
276 syslog(LOG_NOTICE, "End connection from %s port %u", hostname, ntohs(peeraddr_in.sin_port));
277 if (debug)
278 fprintf(stdout, "End connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port)); 235 fprintf(stdout, "End connection from %s port %u\n", hostname, ntohs(peeraddr_in.sin_port));
236 }
237
279 close(s); 238 close(s);
280 } 239 }
281 240
282 241
283 242
287 int optval = 1; 246 int optval = 1;
288 247
289 syslog(LOG_NOTICE, "Thread my_server_loop started"); 248 syslog(LOG_NOTICE, "Thread my_server_loop started");
290 if (debug) 249 if (debug)
291 fprintf(stdout, "Thread my_server_loop started\n"); 250 fprintf(stdout, "Thread my_server_loop started\n");
292
293 defaultControlsettings();
294 defaultControlConstants();
295 defaultControlVariables();
296 251
297 memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in)); 252 memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));
298 memset((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in)); 253 memset((char *)&peeraddr_in, 0, sizeof(struct sockaddr_in));
299 myaddr_in.sin_family = AF_INET; 254 myaddr_in.sin_family = AF_INET;
300 myaddr_in.sin_addr.s_addr = INADDR_ANY; 255 myaddr_in.sin_addr.s_addr = INADDR_ANY;
354 if (debug) 309 if (debug)
355 fprintf(stdout, "my_server_loop accept failed %s\n", strerror(errno)); 310 fprintf(stdout, "my_server_loop accept failed %s\n", strerror(errno));
356 return 0; 311 return 0;
357 } 312 }
358 313
359 switch (fork()) { 314 cmd_server();
360 case -1: /*
361 * Can't fork, just continue.
362 */
363 return 0;
364 case 0: /*
365 * Child process, the commandline server.
366 */
367 cmd_server();
368 return 0;
369 default: /*
370 * Daemon process comes here. The daemon
371 * needs to remember to close the new
372 * accept socket after forking the child.
373 */
374 close(s);
375 }
376 315
377 if (my_shutdown) { 316 if (my_shutdown) {
378 syslog(LOG_NOTICE, "Thread my_server_loop stopped"); 317 syslog(LOG_NOTICE, "Thread my_server_loop stopped");
379 if (debug) 318 if (debug)
380 fprintf(stdout, "Thread my_server_loop stopped\n"); 319 fprintf(stdout, "Thread my_server_loop stopped\n");

mercurial