10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <sys/ioctl.h>
15 #define min(a, b) ((a) < (b) ? (a) : (b))
16 #define max(a, b) ((a) > (b) ? (a) : (b))
18 static inline char *_strlcat(char *dst, const char *src, size_t len)
20 strncat(dst, src, len - strnlen(dst, len) - 1);
26 static int read_1wire_temp(const char *_path, double *temp)
33 const char *path = _path;
38 fd = open(path, O_RDONLY);
40 printf("%s: Failed to open file %s: %m\n", __func__, path);
44 ret = read(fd, buf, sizeof(buf) - 1);
46 printf("%s: Failed read temperature from file %s: %m\n",
59 if (*temp != 85 || retries >= 3)
64 printf("Retrying 1wire read, try %d\n", retries);
69 /* Make an uncached path first */
70 c = strstr(_path, "/28.");
72 c = strstr(_path, "/10.");
74 printf("Unable to make uncached path of \"%s\", will not retry\n", _path);
79 strncpy(uncached, _path, len);
81 _strlcat(uncached, "/uncached/", sizeof(uncached));
82 _strlcat(uncached, c, sizeof(uncached));
95 static char *addrstr(struct sockaddr_in *addr)
99 snprintf(str, sizeof(str), "%s:%d",
100 inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
101 str[sizeof(str) - 1] = '\0';
106 static int fetch_bmed_data(struct sockaddr_in *addr, struct data_entry *data)
112 fd = socket(AF_INET, SOCK_STREAM, 0);
114 printf("%s: Failed to create socket: %m\n", __func__);
118 ret = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
120 printf("%s: Failed to connect at %s: %m\n", __func__, addrstr(addr));
125 * Send timestamp of the first entry we want. Data is
126 * generated every 60 seconds, so this should give us the last
129 ret = dprintf(fd, "%ld\n", time(NULL) - 60);
131 printf("%s: Failed to send timestamp to bmed at %s: %m\n",
132 __func__, addrstr(addr));
136 ret = read(fd, buf, sizeof(buf) - 1);
138 printf("%s: Failed read data from bmed at %s: %m\n",
139 __func__, addrstr(addr));
144 ret = sscanf(buf, "%ld:%lf:%lf:%lf:%lf",
151 printf("%s: Read only %d datapoints out of 5 from string: %s\n", __func__,
164 static int parse_ip_port(const char *str, struct sockaddr_in *addr)
171 s = strstr(str, ":");
173 if (len >= (long)sizeof(ip) || len < 0 || !s) {
174 printf("%s: Unable to parse ip:port from string %s, %ld\n",
179 strncpy(ip, str, len);
182 ret = inet_aton(ip, &addr->sin_addr);
184 printf("Invalid address: %s\n", ip);
189 addr->sin_port = htons(atoi(s));
191 printf("%s:Parsed %s from %s: \n", __func__, addrstr(addr), str);
193 addr->sin_family = AF_INET;
197 static int daemon_loop(const char *temp_path, struct sockaddr_in *bme_addr)
199 struct sockaddr_in addr_in;
200 struct data_entry data;
201 int listen_fd, fd, ret;
204 bzero(&addr_in, sizeof(addr_in));
206 listen_fd = socket(AF_INET, SOCK_STREAM, 0);
211 addr_in.sin_family = AF_INET;
212 addr_in.sin_port = htons(6000);
213 addr_in.sin_addr.s_addr = INADDR_ANY;
215 ret = bind(listen_fd, (struct sockaddr *)&addr_in, sizeof(addr_in));
217 printf("%s: Failed to bind to addr %s: %m\n",
218 __func__, addrstr(&addr_in));
222 ret = listen(listen_fd, 5);
224 printf("Failed to listen(): %m\n");
230 socklen_t peerlen = 0;
231 int onewire_ok, bme_ok;
234 fd = accept(listen_fd, (struct sockaddr *)&addr_in, &peerlen);
236 printf("%s: Error while accept(): %m\n", __func__);
240 ret = read_1wire_temp(temp_path, &temp);
243 printf("1wire data: %.2lf\n", temp);
246 ret = fetch_bmed_data(bme_addr, &data);
249 printf("bmed data: %ld %.4lf %.4lf %.4lf %.4lf\n",
250 data.time, data.temperature, data.humidity,
251 data.pressure, data.dew_point);
254 temp = data.temperature;
256 len = snprintf(buf, sizeof(buf), "%.1lf %.1lf %.1lf %.1lf\n\r",
257 min(temp, data.temperature),
262 for (i = 0; i < (int)sizeof(buf) && buf[i]; i++)
266 ret = write(fd, buf, len);
268 printf("%s: Failed to write to %s: %m\n", __func__, addrstr(&addr_in));
278 int main(int argc, char *argv[])
281 struct sockaddr_in addr;
285 printf("Usage: %s [1wire path] [bmed ip:addr]\n", argv[0]);
289 bzero(&addr, sizeof(addr));
290 ret = parse_ip_port(argv[2], &addr);
296 daemon_loop(path, &addr);