addrutil: Re-indent.
[wk-misc.git] / heating-daemon.c
1 /* heating-daemon.c - Collect data from heating-control.c
2  * Copyright (C) 2010 Werner Koch
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 3 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include <termios.h>
26 #include <unistd.h>
27 #include <time.h>
28
29 #define PGM           "heating-daemon"
30 #define PGM_VERSION   "0.1"
31 #define PGM_BUGREPORT "wk@gnupg.org"
32
33 /* Option flags. */
34 static int verbose;
35 static int debug;
36
37 /* Error counter.  */
38 static int any_error;
39
40
41 /* Print diagnostic message and exit with failure. */
42 static void
43 die (const char *format, ...)
44 {
45   va_list arg_ptr;
46
47   fflush (stdout);
48   fprintf (stderr, "%s: ", PGM);
49
50   va_start (arg_ptr, format);
51   vfprintf (stderr, format, arg_ptr);
52   va_end (arg_ptr);
53   putc ('\n', stderr);
54
55   exit (1);
56 }
57
58
59 /* Print diagnostic message. */
60 static void
61 err (const char *format, ...)
62 {
63   va_list arg_ptr;
64
65   any_error = 1;
66
67   fflush (stdout);
68   fprintf (stderr, "%s: ", PGM);
69
70   va_start (arg_ptr, format);
71   vfprintf (stderr, format, arg_ptr);
72   va_end (arg_ptr);
73   putc ('\n', stderr);
74 }
75
76 /* Print a info message message. */
77 static void
78 inf (const char *format, ...)
79 {
80   va_list arg_ptr;
81
82   if (verbose)
83     {
84       fprintf (stderr, "%s: ", PGM);
85
86       va_start (arg_ptr, format);
87       vfprintf (stderr, format, arg_ptr);
88       va_end (arg_ptr);
89       putc ('\n', stderr);
90     }
91 }
92
93
94 static FILE *
95 open_line (void)
96 {
97   FILE *fp;
98   int fd;
99   struct termios term;
100
101   /* FIXME get device lock.  */
102
103   fp = fopen ("/dev/ttyS0", "r+");
104   if (!fp || (fd = fileno (fp)) == -1)
105     die ("can't open `%s': %s", "/dev/ttyS0", strerror (errno));
106
107   if (tcgetattr (fd, &term))
108     die ("tcgetattr(%d) failed: %s", fd, strerror (errno));
109
110   term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
111                     | INLCR | IGNCR | ICRNL | IXON);
112   term.c_oflag &= ~OPOST;
113   term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
114   term.c_cflag &= ~(CSIZE | PARENB);
115   term.c_cflag |= CS8;
116
117   if (cfsetospeed (&term, B9600) || cfsetispeed (&term, B9600))
118     die ("setting terminal speed to 9600 failed: %s", strerror (errno));
119
120   if (tcsetattr (fd, TCSANOW, &term ) )
121     die ("tcsetattr(%d) failed: %s", fd, strerror (errno));
122
123   inf ("connected to '%s' at 9600bps", "/dev/ttyS0");
124
125   return fp;
126 }
127
128
129 static void
130 run_loop (FILE *fp)
131 {
132   char line[1024];
133   size_t len;
134   int c;
135   time_t lasttime = 0;
136   time_t curtime;
137
138   fseek (fp, 0L, SEEK_CUR);
139   fputs ("\r\n\r\nAT+M1\r\n", fp);
140   fseek (fp, 0L, SEEK_CUR);
141
142   while (fgets (line, sizeof line, fp))
143     {
144       len = strlen (line);
145       if (!len || line[len-1] != '\n')
146         {
147           err ("line too long - skipping");
148           while ((c = getc (fp)) != EOF && c != '\n')
149             ;
150           continue;
151         }
152       while (len && (line[len-1] == '\n' || line[len-1] == '\r'))
153         len--;
154       line[len] = 0;
155
156       if (*line && line[1] == ':')
157         {
158           curtime = time (NULL);
159           if (curtime >= lasttime + 60)
160             {
161               lasttime = curtime;
162               printf ("$:%lu:\n", (unsigned long)curtime);
163             }
164
165           fputs (line, stdout);
166           putchar ('\n');
167         }
168       else
169         inf ("message: %s", line);
170     }
171
172   if (ferror (fp))
173     err ("processing stopped due to a read error: %s", strerror (errno));
174   else
175     inf ("processing stopped due to an EOF");
176 }
177
178
179
180 static int
181 show_usage (int ex)
182 {
183   fputs ("Usage: " PGM "\n"
184          "Control the heating controller and collect data.\n\n"
185          "  --verbose      enable extra informational output\n"
186          "  --debug        enable additional debug output\n"
187          "  --help         display this help and exit\n\n"
188          "Report bugs to " PGM_BUGREPORT ".\n",
189          ex? stderr:stdout);
190   exit (ex);
191 }
192
193
194 int
195 main (int argc, char **argv)
196 {
197   int last_argc = -1;
198   FILE *fp;
199
200   if (argc)
201     {
202       argc--; argv++;
203     }
204   while (argc && last_argc != argc )
205     {
206       last_argc = argc;
207       if (!strcmp (*argv, "--"))
208         {
209           argc--; argv++;
210           break;
211         }
212       else if (!strcmp (*argv, "--version"))
213         {
214           fputs (PGM " " PGM_VERSION "\n", stdout);
215           exit (0);
216         }
217       else if (!strcmp (*argv, "--help"))
218         {
219           show_usage (0);
220         }
221       else if (!strcmp (*argv, "--verbose"))
222         {
223           verbose = 1;
224           argc--; argv++;
225         }
226       else if (!strcmp (*argv, "--debug"))
227         {
228           verbose = debug = 1;
229           argc--; argv++;
230         }
231       else if (!strncmp (*argv, "--", 2))
232         show_usage (1);
233     }
234
235   if (argc)
236     show_usage (1);
237
238   setvbuf (stdout, NULL, _IOLBF, 0);
239
240   fp = open_line ();
241   run_loop (fp);
242   fclose (fp);
243
244   return any_error? 1:0;
245 }
246
247
248 /*
249 Local Variables:
250 compile-command: "gcc -Wall -W -O2 -g -o heating-daemon heating-daemon.c"
251 End:
252 */