thermometers/thermometers.c

changeset 407
ee8f851b4d93
parent 406
44566f986f76
child 408
ec507c1f1df7
equal deleted inserted replaced
406:44566f986f76 407:ee8f851b4d93
1 /*****************************************************************************
2 * Copyright (C) 2014
3 *
4 * Michiel Broek <mbroek at mbse dot eu>
5 *
6 * This file is part of the mbsePi-apps
7 *
8 * This is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * mbsePi-apps is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with EC-65K; see the file COPYING. If not, write to the Free
20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *****************************************************************************/
22
23 #include "thermometers.h"
24
25
26 static int my_shutdown = FALSE;
27 static pid_t pgrp, mypid;
28
29 extern int debug;
30 extern sys_config Config;
31 #ifdef HAVE_WIRINGPI_H
32 extern int lcdHandle;
33 #endif
34
35 int server(void);
36 void help(void);
37 void die(int);
38
39
40 void help(void)
41 {
42 fprintf(stdout, "mbsePi-apps thermometers v%s starting\n\n", VERSION);
43 fprintf(stdout, "Usage: thermomeneters [-d] [-h]\n");
44 fprintf(stdout, " -d --debug Debug and run in foreground\n");
45 fprintf(stdout, " -h --help Display this help\n");
46 }
47
48
49
50 void die(int onsig)
51 {
52 switch (onsig) {
53 case SIGHUP: syslog(LOG_NOTICE, "Got SIGHUP, shutting down");
54 break;
55 case SIGINT: syslog(LOG_NOTICE, "Keyboard interrupt, shutting down");
56 break;
57 case SIGTERM: syslog(LOG_NOTICE, "Got SIGTERM, shutting down");
58 break;
59 default: syslog(LOG_NOTICE, "die() on signal %d", onsig);
60 }
61
62 my_shutdown = TRUE;
63 }
64
65
66
67 #ifdef HAVE_WIRINGPI_H
68 void stopLCD(void)
69 {
70 lcdClear(lcdHandle);
71 setBacklight(0);
72 }
73 #endif
74
75
76
77 int main(int argc, char *argv[])
78 {
79 int rc, c, i;
80 pid_t frk;
81 #ifdef HAVE_WIRINGPI_H
82 char buf[80];
83 #endif
84
85 while (1) {
86 int option_index = 0;
87 static struct option long_options[] = {
88 {"debug", 0, 0, 'c'},
89 {"help", 0, 0, 'h'},
90 {0, 0, 0, 0}
91 };
92
93 c = getopt_long(argc, argv, "dh", long_options, &option_index);
94 if (c == -1)
95 break;
96
97 switch (c) {
98 case 'd': debug = TRUE;
99 break;
100 case 'h': help();
101 return 1;
102 }
103 }
104
105 openlog("thermometers", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_USER);
106 syslog(LOG_NOTICE, "mbsePi-apps thermometers v%s starting", VERSION);
107 if (debug)
108 fprintf(stdout, "mbsePi-apps thermometers v%s starting\n", VERSION);
109
110 if (rdconfig((char *)"thermometers.conf")) {
111 fprintf(stderr, "Error reading configuration\n");
112 syslog(LOG_NOTICE, "Error reading configuration, halted");
113 return 1;
114 }
115
116 /*
117 * Catch all the signals we can, and ignore the rest. Note that SIGKILL can't be ignored
118 * but that's live. This daemon should only be stopped by SIGTERM.
119 * Don't catch SIGCHLD.
120 */
121 for (i = 0; i < NSIG; i++) {
122 if ((i != SIGCHLD) && (i != SIGKILL) && (i != SIGSTOP))
123 signal(i, (void (*))die);
124 }
125
126 #ifdef HAVE_WIRINGPI_H
127
128 if (wiringPiSetup () )
129 return 1;
130
131 if ((rc = initLCD (16, 2))) {
132 fprintf(stderr, "Cannot initialize LCD display, rc=%d\n", rc);
133 return 1;
134 }
135
136 lcdPosition(lcdHandle, 0, 0);
137 lcdPuts(lcdHandle, "Thermometers");
138 lcdPosition(lcdHandle, 0, 1);
139 sprintf(buf, "Version %s", VERSION);
140 lcdPuts(lcdHandle, buf);
141 #endif
142
143 if (debug) {
144 /*
145 * For debugging run in foreground.
146 */
147 rc = server();
148 } else {
149 /*
150 * Server initialization is complete. Now we can fork the
151 * daemon and return to the user. We need to do a setpgrp
152 * so that the daemon will no longer be assosiated with the
153 * users control terminal. This is done before the fork, so
154 * that the child will not be a process group leader. Otherwise,
155 * if the child were to open a terminal, it would become
156 * associated with that terminal as its control terminal.
157 */
158 if ((pgrp = setpgid(0, 0)) == -1) {
159 syslog(LOG_NOTICE, "setpgpid failed");
160 }
161
162 frk = fork();
163 switch (frk) {
164 case -1:
165 syslog(LOG_NOTICE, "Daemon fork failed: %s", strerror(errno));
166 syslog(LOG_NOTICE, "Finished, rc=1");
167 #ifdef HAVE_WIRINGPI_H
168 stopLCD();
169 #endif
170 exit(1);
171 case 0: /*
172 * Run the daemon
173 */
174 fclose(stdin);
175 if (open("/dev/null", O_RDONLY) != 0) {
176 syslog(LOG_NOTICE, "Reopen of stdin to /dev/null failed");
177 _exit(2);
178 }
179 fclose(stdout);
180 if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 1) {
181 syslog(LOG_NOTICE, "Reopen of stdout to /dev/null failed");
182 _exit(2);
183 }
184 fclose(stderr);
185 if (open("/dev/null", O_WRONLY | O_APPEND | O_CREAT,0600) != 2) {
186 syslog(LOG_NOTICE, "Reopen of stderr to /dev/null failed");
187 _exit(2);
188 }
189 mypid = getpid();
190 rc = server();
191 break;
192 /* Not reached */
193 default:
194 /*
195 * Here we detach this process and let the child
196 * run the deamon process.
197 */
198 syslog(LOG_NOTICE, "Starting daemon with pid %d", frk);
199 exit(0);
200 }
201 }
202
203 syslog(LOG_NOTICE, "Finished, rc=%d", rc);
204 return rc;
205 }
206
207
208
209 int server(void)
210 {
211 int temp, rc = 0;
212 #ifdef HAVE_WIRINGPI_H
213 char buf[1024];
214 int lcdupdate;
215 #endif
216 w1_therm *tmp1;
217 char *device, line[60], *p = NULL;
218 FILE *fp;
219
220 if (debug)
221 fprintf(stdout, (char *)"Enter loop\n");
222
223 do {
224 #ifdef HAVE_WIRINGPI_H
225 lcdupdate = FALSE;
226 #endif
227
228 /*
229 * Here send our 1-wire sensors values
230 */
231 for (tmp1 = Config.w1therms; tmp1; tmp1 = tmp1->next) {
232
233 /*
234 * Build path and alias topic
235 */
236 device = xstrcpy((char *)"/sys/bus/w1/devices/");
237 device = xstrcat(device, tmp1->master);
238 device = xstrcat(device, (char *)"/");
239 device = xstrcat(device, tmp1->name);
240 device = xstrcat(device, (char *)"/w1_slave");
241
242 /*
243 * Read sensor data
244 */
245 if ((fp = fopen(device, "r"))) {
246 /*
247 * The output looks like:
248 * 72 01 4b 46 7f ff 0e 10 57 : crc=57 YES
249 * 72 01 4b 46 7f ff 0e 10 57 t=23125
250 */
251 fgets(line, 50, fp);
252 line[strlen(line)-1] = '\0';
253 if ((line[36] == 'Y') && (line[37] == 'E')) {
254 /*
255 * CRC is Ok, continue
256 */
257 fgets(line, 50, fp);
258 line[strlen(line)-1] = '\0';
259 strtok(line, (char *)"=");
260 p = strtok(NULL, (char *)"=");
261 rc = sscanf(p, "%d", &temp);
262 if ((rc == 1) && (tmp1->lastval != temp)) {
263 tmp1->lastval = temp;
264 #ifdef HAVE_WIRINGPI_H
265 lcdupdate = TRUE;
266 #endif
267 }
268 } else {
269 syslog(LOG_NOTICE, "sensor %s/%s CRC error", tmp1->master, tmp1->name);
270 }
271 fclose(fp);
272 tmp1->present = 1;
273 } else {
274 tmp1->present = 0;
275 if (debug)
276 printf("sensor %s is missing\n", tmp1->name);
277 }
278
279 free(device);
280 device = NULL;
281 }
282
283 #ifdef HAVE_WIRINGPI_H
284 if (lcdupdate) {
285 lcdPosition(lcdHandle, 0, 0);
286 tmp1 = Config.w1therms;
287 snprintf(buf, 16, "%5.1f %cC %s ", tmp1->lastval / 1000.0, 0xdf, tmp1->alias);
288 lcdPuts(lcdHandle, buf);
289 tmp1 = tmp1->next;
290 lcdPosition(lcdHandle, 0, 1);
291 snprintf(buf, 16, "%5.1f %cC %s ", tmp1->lastval / 1000.0, 0xdf, tmp1->alias);
292 lcdPuts(lcdHandle, buf);
293 }
294 #endif
295
296 if (my_shutdown) {
297 #ifdef HAVE_WIRINGPI_H
298 lcdClear(lcdHandle);
299 lcdPosition(lcdHandle, 0, 0);
300 lcdPuts(lcdHandle, "Shuting down ...");
301 #endif
302 }
303
304 usleep(100000);
305
306 } while (! my_shutdown);
307
308 if (debug)
309 fprintf(stdout, (char *)"Out of loop\n");
310
311 #ifdef HAVE_WIRINGPI_H
312 stopLCD();
313 #endif
314
315 return rc;
316 }
317

mercurial