1
/* -----------------------------------------------------------------------
4
Copyright 1996-2004 by Brian C. Lane <bcl@brianlane.com>
7
This program is free software; you can redistribute it and/or modify it
8
under the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2 of the License, or (at your option)
12
This program is distributed in the hope that it will be useful, but WITHOUT
13
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17
You should have received a copy of the GNU General Public License along
18
with this program; if not, write to the Free Software Foundation, Inc.,
19
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21
digitemp -w Walk the LAN & show all
22
digitemp -i Initalize .digitemprc file
23
digitemp -s/dev/ttyS0 Set serial port (required)
24
digitemp -cdigitemp.conf Configuration File
25
digitemp -r1000 Set Read timeout to 1000mS
26
digitemp -l/var/log/temperature Send output to logfile
27
digitemp -v Verbose mode
28
digitemp -t0 Read Temperature
29
digitemp -q Quiet, no copyright banner
30
digitemp -a Read all Temperatures
31
digitemp -d5 Delay between samples (in sec.)
32
digitemp -n50 Number of times to repeat. 0=forever
33
digitemp -A Treat DS2438 as A/D converter
34
digitemp -o1 Output format for logfile
36
digitemp -o"output format string" See description below
37
digitemp -O"counter format" See description below
38
digitemp -H"Humidity format" See description below
41
1 = (default) - 1 line per sensor, time, C, F
42
1 line for each sample, elapsed time, sensor #1, #2, ... tab seperated
46
The format string uses strftime tokens plus 6 special
47
ones for digitemp - %s for sensor #, %C for centigrade,
48
%F for fahrenheit, %R for hex serial number, %N for seconds since Epoch
50
Humidity uses %h for the relative humidity in percent
52
The counter format uses %n for the counter # and %C for the count
55
Remember the case of the token is important!
57
=======================================================================
58
01/25/2004 A user reported a bug in the humidity temperature, it
59
bcl wasn't converting negative temperatures correctly.
60
I also see a potential problem with the DS18B20 and DS1822
61
which use a short int type and depend on it being 16 bits
62
so that the sign comes out correct. But can we count on a
63
short int always being 16 bits? I need to look into it.
65
01/10/2003 Finally, humidity is working, thanks in large part to work
66
bcl by Eric Wilde. Need to add logging of DS2438. I think it
67
will be hard-coded, if it needs to be in another format
68
it can be parsed with perl or python or whatever.
69
Fixed a bug that wasn't allowing %% to be embedded in the
72
Adding lockfile support using the lockdev library under
73
Linux. Wrapping it in LINUX checks until other systems
74
indicate that they can use it.
76
Lockfiles are working, but - the binary has to be sgid to
77
the lock group so that it can access /var/lock, adding
78
the user to the lock group would also accomplish this.
80
01/08/2003 Still trying to get DS2438 and Humidity support working
81
bcl Also changing strcpy to strncpy, dunno why they weren't
84
01/04/2003 Adding DS2438 based humidity support from Eric Wilde.
87
11/29/2003 Trying to get a first pass at DS2438 (A/D & Battery monitor)
88
bcl support up and running.
89
Found a bug, init wouldn't record counters found on branches
92
10/27/2003 Added patch from Sven Geggus to allow -n0 to make it run
93
bcl in an infinite loop. Need to check for exit conditions
94
and clean up logfile, serial port, etc. in a nice manner.
96
08/13/2003 Adding DS2490 USB to 1-wire adapter support. Bumping the
97
bcl version number to 3.3.0 without a release of 3.2.1
99
06/14/2003 Made change to hub search from Jesús Roncer, it wouldn't
100
bcl work right if run with -q (a owFirst was inside the
101
quiet check). Also adding the manpage created by Jesú.
103
Version changed to 3.2.1
105
05/24/2003 Adding a banner that reports what library the binary was
106
bcl compiled for (DS9097 or DS9097U).
107
Adjusted the makefile a bit, change the dist to be one of
108
dist-9097 or dist-9097u to build for the right target.
110
05/23/2003 Adding kludges for USB to Serial adapter. Added a loop of
111
bcl 10 tries to the DS2480Detect routine. Added DEBUG_USERIAL
112
compile time wrappers for diagnostic information about the
113
ReadCOM routine. Part of the key to this is the delay used
114
in ReadCOM, its just too short for use with the USB to
115
serial adapter. I've changed it to 1 second + 10-15mS --
116
I'm not sure that the global_msec is really needed with the
117
longer timeout time, its a fail-safe anyway; the character
118
ought to come back a long time before the timeout.
120
Changed version to v3.2.0
122
02/14/2003 Adding logging of read values. Need to change the way it
123
bcl handles building the output string.
124
It works, but the counter really needs its own format
125
string. Kinda hard to automatically integrate it into the
126
current temperature oriented format string.
128
02/12/2003 Adding more code... Needs more work, the family code may
129
bcl be buried in the coupler linked list. I may need to move the
130
decision as to how to read it to after it finds the coupler
132
Change read_temp to read_sensor. device selection is common
133
to all devices, then switch based on the serial number
134
finally selected (saved as it is selected).
136
02/06/2003 Changed version number to v3.1.0
137
bcl Adding support for counters
138
Happy 92nd Birthday to Ronald Reagan!
140
11/21/2002 Changed sleep method to use less CPU cycles, thanks to
141
bcl peter enderborg for pointing it out.
143
08/21/2002 Small bug with -i crept in, it wants another command to be
144
bcl present, it won't just initalize.
146
08/16/2002 Adding %N token to output seconds since Epoch, which is
147
bcl masked by my use of %s for the sensor number. I don't want
148
to remove %s, because that would break old code. So %N
149
now maps to %s in the strftime format.
150
The check for commands is too strict, it isn't allowing
151
-i to be combined with any of the other commands.
152
Added permission checking on the serial device with a clean
153
exit if the user doesn't have access to the serial device.
155
06/23/2002 Releasing new version today. Really! Making -q turn off
156
bcl the extra output I added for initalizing the 1-wire lan.
158
06/08/2002 Adding patches from John. exit() codes are now #defines
159
bcl and .digitemprc now outputs the serial numbers as hex
160
instead of decimal. But maintains backwards compatibility
161
until a new .digitemprc is written.
162
Output format string now includes an option to output the
163
Sensor's serial number in hex (%R).
165
05/11/2002 Adding more changes from John Stoffel
168
05/08/2002 Integrating changes for Solaris, AIX, FreeBSD from John
169
bcl Stoffel. Changes to getopt initial settings, Makefile
172
05/06/2002 Adding changes and fixes from DT v2.5 for Windows.
173
bcl Family code for DS1822 was wrong, it is really 0x22
174
Lots of changes to the read_temp routine, added a better
175
scratchpad dump routine (previous one only worked for
177
Quite a bit needs to be changed, I have switched to using
178
a structure to store the sensor and coupler lists. I
179
updated the core temperature read routine, the lan walk
180
and device search routines. Reading when using a hub
181
is now faster when reading multiple devices on the
184
01/15/2002 Cleaning up, preparing for release
186
01/14/2002 Adding support for reading sensors on DS2409 couplers.
188
01/13/2002 Walking the tree now works -- after changing the swt1f.c
189
routine to use the Smart-On Main command while searching
190
for devices (otherwise it only finds the first).
192
Adding support for Coupler to the main program.
193
Init now works, writing .digitemprc now works.
194
Read .digitemprc appears to work.
195
Need to add reading of specified sensors and of all
199
01/12/2002 Adding a diagnostic walk of the attached network, working
200
on DS2409 MicroLAN Coupler support.
201
Added release1WireNet calls before all exit calls.
202
Switching to the userial library v3.0.0, I seem to have
203
run into a problem with the old library and I cannot read
204
either of my DS9097U adapters with v2.2 digitemp code.
207
05/26/2001 The 18B20 and 1822 patch didn't work. It was reading the
208
wrong scratchpad registers. (2,1 instead of 1,0).
209
Changed version to v2.2
211
03/16/2001 Integrating the AIX patch from Ewan Leith
212
<ejl@man.fraser-williams.com>
213
It amounts to return value checking on getopt and changes
214
in the wirelnk.c file.
215
Adding DS1822 and DS18B20 changes from Roland Roberts
216
<roland@astrofoto.org>
218
03/05/2001 Adding a command line option to specify the configuration
219
file to use. -c config_file will override the default of
222
02/17/2001 If there is an error with strong pullup on/off it shouldn't
223
abort the conversion! Just log an error to stderr.
225
01/31/2001 Added a dummy temperature output when a sensor cannot be
226
read. It outputs a 0 so that scripts like my grapher
227
don't get confused and log the wrong sensor in the wrong
230
An error message is also output to stderr.
232
01/29/2001 Oops. It seems that I missed the line in the DS1820
233
datasheet that says Vdd needs to be tied to GND for
234
Parasite power to work correctly.
235
Various curses come to mind.
236
The DS1820 works better than the DS18S20 with Vdd floating
237
but this probably explains the infrequent glitches I
238
saw before adding the DS18S20s.
240
01/15/2001 Still getting glitches.
241
Adding a reset and delay before retry
243
01/14/2001 Changed Version number to 2.1
245
I now have 2 DS18S20 sensors which supposedly fix the
246
Temperature accuracy problems of the DS1820 (see the
247
ds1820-report.pdf from Dallas). But now I get a huge
248
number of glitches in the DS18S20's readings.
249
The DS18S20 has an error condition, but it is +85C and
250
the glitches I am seeing are because DigiTemp doesn't
251
output anything at all for the DS18S20's reading.
253
Adding a check for the DS18S20's error condition:
259
If this error case is encountered, the reading should be
260
repeated. If it comes up again, use it.
262
There is also a glitch possible in the DS1820 that exhibits
263
itself by COUNT_PER_C - COUNT_REMAIN = 1, this should be
264
checked for, and the reading repeated and the next result
267
The problem with no reading from the device seems to
268
happen when MLanAccess is called. There is no good way to
269
tell what the problem is, so I will change the code to
270
try 3 times before failing. Changes are in read_temp.
272
01/04/2000 Changing the default read timeout to 1000mS. I had problems
273
with it set to 500mS and a 30' sensor wire (the reading
274
was low by about 10 degrees).
276
01/01/2000 Well, no release last year. Adding -q to make the banner
277
dissapear for batchfiles that want to get the output
280
12/28/99 Changed Version number to 2.0
281
Adding GNU public license
282
Changing this code to use the DS9097-U adapter
284
06/03/99 Finishing this thing up.
286
06/02/99 Use 2 logging routines, log_time to log a single line
287
per sensor with optional time data and log_str to log
288
a single line for multiple sensors with elapsed time at
289
the beginning of the line.
291
05/29/99 Added 2 new init file tags, LOG_FORMAT and LOG_TYPE
292
New formatting works, need to clean up the logic now.
294
05/27/99 Adding user specified format string. To use it, first
295
parse out the digitemp specific stuff and create a new
296
string to feed into strftime, with the sensor, temperature
299
05/24/99 Adding a output specifier string, this will allow users
300
to configure the output to look however they want it to.
301
The format string uses strftime tokens plus 3 special
302
ones for digitemp - %s for sensor #, %C for centigrade,
305
05/23/99 Adding Solaris support via -DSOLARIS define
306
Fixing the time problems once and for all, using localtime
307
in the log_line routine. The user should have TZ set
308
correctly for their timezone. This has been tested
311
Changed version number to v1.3
313
01/14/99 A user in Sweden (and another in Finland) discovered a
314
long standing bug. In do_temp I should have been using
315
0x100 instead of 0xFF for the subtraction. This caused
316
temperatures below 0 degrees C to jump up 1 degree as
317
it decreased. This is fixed.
319
Changed version number to v1.2
321
10/20/98 Adding new features from DOS version to keep things
322
consistent. Removing the debug command, not used anyway.
323
Added a free() to error condition edit from read_rcfile()
324
Set some cases of freeing to = NULL, also freed the rom
325
list before doing a search rom (searchROM checks too, but
326
this is the right place for it).
328
08/31/98 Adding a check for family 0x10 so that we can read DS1820s
329
while they are on a network that includes other 1-wire
331
Fixed a problem with freeing uninitalized rom_list when
332
starting a SearchROM. Not sure why this never appeared
335
03/06/98 Adding a -d debug level to help figure out why this thing
336
is no longer working.
338
03/13/97 Error in CRC calculation. Wrong # of bytes.
339
Error with 3 sensors. Sometimes doesn't store correct ROM
340
data to .digitemprc -- need to malloc more memory dummy!
342
03/08/97 Adding user defined timeouts for failure and for the
345
01/24/97 Changed over to correct baud rate and 6 bits @ 115.2k
346
ROM search function is now working. All low level code
347
is functioning except for Alarm Search. Starting to move
348
into a seperate object file with API for users to write
351
01/22/97 Working on ROM search routine, double cannot handle a full
352
64 bits for some reason, converting to 64 byte array for
355
01/19/97 Rewriting for new interface. This programs handles all the
356
low level communications with the temperature sensor using
357
the 115200k serial adapter.
359
01/02/96 Rewriting this code to be more user friendly
361
-----------------------------------------------------------------------*/
366
#if !defined(AIX) && !defined(SOLARIS) && !defined(FREEBSD) && !defined(DARWIN)
368
#endif /* !AIX and !SOLARIS and !FREEBSD and !DARWIN */
369
#include <sys/types.h>
370
#include <sys/stat.h>
371
#include <sys/time.h>
385
#include "digitemp.h"
386
#include "device_name.h"
391
/* Setup the correct getopt starting point */
394
#define OPTINDSTART 0
398
#define OPTINDSTART 0
399
#define GETOPTEOF 255
403
#define GETOPTEOF EOF
404
#define OPTINDSTART 1
408
#define GETOPTEOF EOF
409
#define OPTINDSTART 1
413
#define GETOPTEOF EOF
414
#define OPTINDSTART 1
418
#define GETOPTEOF EOF
419
#define OPTINDSTART 1
423
#define GETOPTEOF EOF
424
#define OPTINDSTART 1
428
#define GETOPTEOF EOF
429
#define OPTINDSTART 1
433
/* For tracking down strange errors */
437
extern int optind, opterr, optopt;
439
#if defined(FREEBSD) || defined(DARWIN)
441
#endif /* FREEBSD or DARWIN */
443
extern const char dtlib[]; /* Library Used */
445
char serial_port[40], /* Path to the serial port */
447
serial_dev[40], /* Device name without /dev/ */
448
log_file[1024], /* Path to the log file */
450
temp_format[80], /* Format for temperature readings */
452
counter_format[80], /* Format for counter readings */
453
tmp_counter_format[80],
454
humidity_format[80], /* Format for Humidity readings */
455
tmp_humidity_format[80],
456
conf_file[1024], /* Configuration File */
458
int read_time, /* Pause during read */
460
log_type, /* output format type */
462
num_cs = 0, /* Number of sensors on cplr */
463
opts = 0; /* Bitmask of flags */
465
struct _coupler *coupler_top = NULL; /* Linked list of couplers */
467
unsigned char Last2409[9]; /* Last selected coupler */
470
int global_msec = 10; /* For ReadCOM delay */
471
int global_msec_max = 15;
473
/* ----------------------------------------------------------------------- *
474
Print out the program usage
475
* ----------------------------------------------------------------------- */
480
printf(BANNER_3, dtlib ); /* Report Library version */
481
printf("\nUsage: digitemp [-s -i -U -l -r -v -t -a -d -n -o -c]\n");
482
printf(" -i Initalize .digitemprc file\n");
483
printf(" -w Walk the full device tree\n");
484
/* printf(" -U Use the DS909-U adapter\n"); */
485
printf(" -s /dev/ttyS0 Set serial port\n");
486
printf(" -l /var/log/temperature Send output to logfile\n");
487
printf(" -c digitemp.conf Configuration File\n");
488
printf(" -r 1000 Read delay in mS\n");
489
printf(" -v Verbose output\n");
490
printf(" -t 0 Read Sensor #\n");
491
printf(" -q No Copyright notice\n");
492
printf(" -a Read all Sensors\n");
493
printf(" -d 5 Delay between samples (in sec.)\n");
494
printf(" -n 50 Number of times to repeat\n");
495
printf(" 0=loop forever\n");
496
printf(" -A Treat DS2438 as A/D converter\n");
497
printf(" -O\"counter format string\" See description below\n");
498
printf(" -o 2 Output format for logfile\n");
499
printf(" -o\"output format string\" See description below\n");
500
printf(" -H\"Humidity format string\" See description below\n");
501
printf("\nLogfile formats: 1 = One line per sensor, time, C, F (default)\n");
502
printf(" 2 = One line per sample, elapsed time, temperature in C\n");
503
printf(" 3 = Same as #2, except temperature is in F\n");
504
printf(" #2 and #3 have the data seperated by tabs, suitable for import\n");
505
printf(" into a spreadsheet or other graphing software.\n");
506
printf("\n The format string uses strftime tokens plus 5 special ones for\n");
507
printf(" digitemp - %%s for sensor #, %%C for centigrade, %%F for fahrenheit,\n");
508
printf(" %%R to output the hex serial number, and %%N for seconds since Epoch.\n");
509
printf(" The case of the token is important! The default format string is:\n");
510
printf(" \"%%b %%d %%H:%%M:%%S Sensor %%s C: %%.2C F: %%.2F\" which gives you an\n");
511
printf(" output of: May 24 21:25:43 Sensor 0 C: 23.66 F: 74.59\n\n");
512
printf(" The counter format string has 2 special specifiers:\n");
513
printf(" %%n is the counter # and %%C is the count in decimal.\n");
514
printf(" The humidity format uses %%h for the humidity in percent\n\n");
518
/* ----------------------------------------------------------------------- *
519
Free up all memory used by the coupler list
520
* ----------------------------------------------------------------------- */
529
/* Turn off the Coupler */
530
SetSwitch1F(0, c->SN, ALL_LINES_OFF, 0, a, TRUE);
532
/* Free up the serial number lists */
533
if( c->num_main > 0 )
539
/* Point to the next in the list */
540
coupler_top = c->next;
542
/* Free up the current entry */
546
} /* Coupler free loop */
548
/* Make sure its null */
553
/* -----------------------------------------------------------------------
554
Convert degrees C to degrees F
555
----------------------------------------------------------------------- */
556
float c2f( float temp )
558
return 32 + ((temp*9)/5);
562
/* -----------------------------------------------------------------------
563
Take the log_format string and parse out the
564
digitemp tags (%*s %*C and %*F) including any format
565
specifiers to pass to sprintf. Build a new string
566
with the strftime tokens and the temperatures mixed
569
If humidity is <0 then it is invalid
570
----------------------------------------------------------------------- */
571
int build_tf( char *time_format, char *format, int sensor,
572
float temp_c, int humidity, unsigned char *sn )
581
if( !time_format || !format )
584
tf_ptr = time_format;
591
*tf_ptr++ = *lf_ptr++;
593
/* Found a token, decide if its one of ours... */
594
/* save initial pointer, grab everything up to... */
599
At this point it has a potential format specifier, copy it over
600
to the token variable, up to the alpha-numeric specifier.
602
It needs to stop copying after it gets the alpha character
604
while( isalnum( *lf_ptr ) || (*lf_ptr == '.') || (*lf_ptr == '*')
605
|| (*lf_ptr == '%') )
607
*tk_ptr++ = *lf_ptr++;
610
/* Break out when the alpha character is copied over */
611
if( isalpha( *(lf_ptr-1) ) )
615
/* see if the format specifier is digitemp or strftime */
616
switch( *(tk_ptr-1) )
620
/* Change the specifier to a d */
623
/* Pass it through sprintf */
624
sprintf( temp, token, sensor );
626
/* Insert this into the time format string */
629
*tf_ptr++ = *tk_ptr++;
633
/* Relative humidity % */
634
/* Change the specifier to a d */
637
/* Pass it through sprintf */
638
sprintf( temp, token, humidity );
640
/* Insert this into the time format string */
643
*tf_ptr++ = *tk_ptr++;
647
/* Degrees Fahrenheit */
648
/* Change the specifier to a f */
651
/* Pass it through sprintf */
652
sprintf( temp, token, c2f(temp_c) );
654
/* Insert this into the time format string */
657
*tf_ptr++ = *tk_ptr++;
662
/* Degrees Centigrade */
663
/* Change the specifier to a f */
666
/* Pass it through sprintf */
667
sprintf( temp, token, temp_c );
669
/* Insert this into the time format string */
672
*tf_ptr++ = *tk_ptr++;
676
/* ROM Serial Number */
677
/* Change the specifier to a hex (x) */
680
/* Insert the serial number in HEX, yes its ugly,
681
but it works and saves using another temporary
682
location and variable.
684
sprintf( temp, "%02X%02X%02X%02X%02X%02X%02X%02X",
685
sn[0],sn[1],sn[2],sn[3],sn[4],sn[5],sn[6],sn[7]);
687
/* Insert this into the time format string */
690
*tf_ptr++ = *tk_ptr++;
694
/* Seconds since Epoch */
695
/* Change the specifier to a s and pass to time */
698
/* Intentional fall through */
700
/* Not something for us, copy it into the time format */
703
*tf_ptr++ = *tk_ptr++;
710
/* Terminate the string */
718
/* -----------------------------------------------------------------------
719
Take the log_format string and parse out the
720
digitemp tags (%*s %*C and %*F) including any format
721
specifiers to pass to sprintf. Build a new string
722
with the strftime tokens and the temperatures mixed
724
----------------------------------------------------------------------- */
725
int build_cf( char *time_format, char *format, int sensor, int page,
726
unsigned long count, unsigned char *sn )
735
if( !time_format || !format )
738
tf_ptr = time_format;
745
*tf_ptr++ = *lf_ptr++;
747
/* Found a token, decide if its one of ours... */
748
/* save initial pointer, grab everything up to... */
752
/* Take numbers, astrix, period and letters */
753
while( isalnum( *lf_ptr ) || (*lf_ptr == '.') ||
754
(*lf_ptr == '*') || (*lf_ptr == '%') )
756
*tk_ptr++ = *lf_ptr++;
760
/* see if the format specifier is digitemp or strftime */
761
switch( *(tk_ptr-1) )
765
/* Change the specifier to a d */
768
/* Pass it through sprintf */
769
sprintf( temp, token, sensor );
771
/* Insert this into the time format string */
774
*tf_ptr++ = *tk_ptr++;
781
/* Show the page/counter # (0 or 1) */
782
/* Change the specifier to a d */
785
/* Pass it through sprintf */
786
sprintf( temp, token, page );
788
/* Insert this into the time format string */
791
*tf_ptr++ = *tk_ptr++;
795
/* Counter reading, 32 bit value */
796
/* Change the specifier to a ld */
801
/* Pass it through sprintf */
802
sprintf( temp, token, count );
804
/* Insert this into the time format string */
807
*tf_ptr++ = *tk_ptr++;
811
/* ROM Serial Number */
812
/* Change the specifier to a hex (x) */
815
/* Insert the serial number in HEX, yes its ugly,
816
but it works and saves using another temporary
817
location and variable.
819
sprintf( temp, "%02X%02X%02X%02X%02X%02X%02X%02X",
820
sn[0],sn[1],sn[2],sn[3],sn[4],sn[5],sn[6],sn[7]);
822
/* Insert this into the time format string */
825
*tf_ptr++ = *tk_ptr++;
829
/* Seconds since Epoch */
830
/* Change the specifier to a s and pass to time */
833
/* Intentional fall through */
835
/* Not something for us, copy it into the time format */
838
*tf_ptr++ = *tk_ptr++;
844
/* Terminate the string */
851
/* -----------------------------------------------------------------------
852
Print a string to the console or the logfile
853
----------------------------------------------------------------------- */
854
int log_string( char *line )
859
if( log_file[0] != 0 )
861
if( (fd = open( log_file, O_CREAT | O_WRONLY | O_APPEND,
862
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ) == -1 )
864
printf("Error opening logfile: %s\n", log_file );
867
if( write( fd, line, strlen( line ) ) == -1)
868
perror("Error loging to logfile");
877
/* -----------------------------------------------------------------------
878
Log one line of text to the logfile with the current date and time
880
Used with temperatures
881
----------------------------------------------------------------------- */
882
int log_temp( int sensor, float temp_c, unsigned char *sn )
884
unsigned char temp[1024],
892
/* Build the time format string from log_format */
893
build_tf( time_format, temp_format, sensor, temp_c, -1, sn );
895
/* Handle the time format tokens */
896
strftime( temp, 1024, time_format, localtime( &mytime ) );
898
strcat( temp, "\n" );
900
sprintf( temp, "Time Error\n" );
902
/* Log it to stdout, logfile or both */
909
/* -----------------------------------------------------------------------
910
Log one line of text to the logfile with the current date and time
913
----------------------------------------------------------------------- */
914
int log_counter( int sensor, int page, unsigned long counter, unsigned char *sn )
916
unsigned char temp[1024],
924
/* Build the time format string from counter_format */
925
build_cf( time_format, counter_format, sensor, page, counter, sn );
927
/* Handle the time format tokens */
928
strftime( temp, 1024, time_format, localtime( &mytime ) );
930
strcat( temp, "\n" );
932
sprintf( temp, "Time Error\n" );
934
/* Log it to stdout, logfile or both */
941
/* -----------------------------------------------------------------------
942
Log one line of text to the logfile with the current date and time
944
Used with temperatures
945
----------------------------------------------------------------------- */
946
int log_humidity( int sensor, double temp_c, int humidity, unsigned char *sn )
948
unsigned char temp[1024],
956
/* Build the time format string from log_format */
957
build_tf( time_format, humidity_format, sensor, temp_c, humidity, sn );
959
/* Handle the time format tokens */
960
strftime( temp, 1024, time_format, localtime( &mytime ) );
962
strcat( temp, "\n" );
964
sprintf( temp, "Time Error\n" );
966
/* Log it to stdout, logfile or both */
973
/* -----------------------------------------------------------------------
974
Compare two serial numbers and return 1 of they match
976
The second one has an additional byte indicating the main (0) or aux (1)
978
----------------------------------------------------------------------- */
979
int cmpSN( unsigned char *sn1, unsigned char *sn2, int branch )
983
for(i = 0; i < 8; i++ )
985
if( sn1[i] != sn2[i] )
990
if( branch != sn2[8] )
995
/* Everything Matches */
1000
/* -----------------------------------------------------------------------
1001
Show the verbose contents of the scratchpad
1002
----------------------------------------------------------------------- */
1003
void show_scratchpad( unsigned char *scratchpad, int sensor_family )
1005
unsigned char temp[80];
1008
if( log_file[0] != 0 )
1010
switch( sensor_family )
1013
sprintf( temp, " Temperature : 0x%02X\n", scratchpad[1] );
1014
sprintf( temp, " Sign : 0x%02X\n", scratchpad[2] );
1015
sprintf( temp, " TH : 0x%02X\n", scratchpad[3] );
1016
sprintf( temp, " TL : 0x%02X\n", scratchpad[4] );
1017
sprintf( temp, " Remain : 0x%02X\n", scratchpad[7] );
1018
sprintf( temp, " Count Per C : 0x%02X\n", scratchpad[8] );
1019
sprintf( temp, " CRC : 0x%02X\n", scratchpad[9] );
1022
case DS18B20_FAMILY:
1024
sprintf( temp, " Temp. LSB : 0x%02X\n", scratchpad[1] );
1025
sprintf( temp, " Temp. MSB : 0x%02X\n", scratchpad[2] );
1026
sprintf( temp, " TH : 0x%02X\n", scratchpad[3] );
1027
sprintf( temp, " TL : 0x%02X\n", scratchpad[4] );
1028
sprintf( temp, " Config Reg. : 0x%02X\n", scratchpad[5] );
1029
sprintf( temp, " CRC : 0x%02X\n", scratchpad[9] );
1036
} /* sensor_family switch */
1038
switch( sensor_family )
1041
printf(" Temperature : 0x%02X\n", scratchpad[1] );
1042
printf(" Sign : 0x%02X\n", scratchpad[2] );
1043
printf(" TH : 0x%02X\n", scratchpad[3] );
1044
printf(" TL : 0x%02X\n", scratchpad[4] );
1045
printf(" Remain : 0x%02X\n", scratchpad[7] );
1046
printf(" Count Per C : 0x%02X\n", scratchpad[8] );
1047
printf(" CRC : 0x%02X\n", scratchpad[9] );
1050
case DS18B20_FAMILY:
1052
printf( " Temp. LSB : 0x%02X\n", scratchpad[1] );
1053
printf( " Temp. MSB : 0x%02X\n", scratchpad[2] );
1054
printf( " TH : 0x%02X\n", scratchpad[3] );
1055
printf( " TL : 0x%02X\n", scratchpad[4] );
1056
printf( " Config Reg. : 0x%02X\n", scratchpad[5] );
1057
printf( " CRC : 0x%02X\n", scratchpad[9] );
1064
} /* sensor_family switch */
1067
/* Dump the complete contents of the scratchpad */
1068
for( i = 0; i < 10; i++ )
1070
printf( "scratchpad[%d] = 0x%02X\n", i, scratchpad[i] );
1076
/* -----------------------------------------------------------------------
1077
Read the temperature from one sensor
1079
Return the high-precision temperature value
1081
Calculated using formula from DS1820 datasheet
1083
Temperature = scratchpad[1]
1084
Sign = scratchpad[2]
1087
Count Remain = scratchpad[7]
1088
Count Per C = scratchpad[8]
1091
count_per_C - count_remain
1092
(temp - 0.25) * --------------------------
1095
If Sign is not 0x00 then it is a negative (Centigrade) number, and
1096
the temperature must be subtracted from 0x100 and multiplied by -1
1097
----------------------------------------------------------------------- */
1098
int read_temperature( int sensor_family, int sensor )
1100
char temp[1024]; /* For output string */
1101
unsigned char lastcrc8,
1102
scratchpad[30], /* Scratchpad block from the sensor */
1106
try, /* Number of tries at reading device */
1107
strong_err, /* Error with strong pullup? */
1108
ds1820_try, /* Allow ds1820 glitch 1 time */
1109
ds18s20_try; /* Allow DS18S20 error 1 time */
1110
float temp_c, /* Calculated temperature in Centigrade */
1118
for( try = 0; try < MAX_READ_TRIES; try++ )
1122
/* Convert Temperature */
1123
if( !owWriteBytePower( 0, 0x44 ) )
1128
/* Sleep for conversion second */
1129
msDelay( read_time );
1131
/* Turn off the strong pullup */
1132
if( owLevel( 0, MODE_NORMAL ) != MODE_NORMAL )
1138
/* Now read the scratchpad from the device */
1141
/* Use Read_Scratchpad instead? */
1142
/* Build a block for the Scratchpad read */
1143
scratchpad[0] = 0xBE;
1144
for( j = 1; j < 10; j++ )
1145
scratchpad[j] = 0xFF;
1147
/* Send the block */
1148
if( owBlock( 0, FALSE, scratchpad, 10 ) )
1150
/* Calculate the CRC 8 checksum on the received data */
1152
for( j = 1; j < 10; j++ )
1153
lastcrc8 = docrc8( 0, scratchpad[j] );
1155
/* If the CRC8 is valid then calculate the temperature */
1156
if( lastcrc8 == 0x00 )
1158
/* DS1822 and DS18B20 use a different calculation */
1159
if( (sensor_family == DS18B20_FAMILY) ||
1160
(sensor_family == DS1822_FAMILY) )
1162
short int temp2 = (scratchpad[2] << 8) | scratchpad[1];
1163
temp_c = temp2 / 16.0;
1166
/* Handle the DS1820 and DS18S20 */
1167
if( sensor_family == DS1820_FAMILY )
1169
/* Check for DS1820 glitch condition */
1170
/* COUNT_PER_C - COUNT_REMAIN == 1 */
1171
if( ds1820_try == 0 )
1173
if( (scratchpad[7] - scratchpad[6]) == 1 )
1177
} /* DS1820 error */
1180
/* Check for DS18S20 Error condition */
1186
if( ds18s20_try == 0 )
1188
if( (scratchpad[4]==0xAA) &&
1189
(scratchpad[3]==0x00) &&
1190
(scratchpad[7]==0x0C) &&
1191
(scratchpad[8]==0x10)
1196
} /* DS18S20 error condition */
1199
/* Convert data to temperature */
1200
if( scratchpad[2] == 0 )
1202
temp_c = (int) scratchpad[1] >> 1;
1204
temp_c = -1 * (int) (0x100-scratchpad[1]) >> 1;
1205
} /* Negative temp calculation */
1207
hi_precision = (int) scratchpad[8] - (int) scratchpad[7];
1208
hi_precision = hi_precision / (int) scratchpad[8];
1209
temp_c = temp_c + hi_precision;
1210
} /* DS1820_FAMILY */
1212
/* Log the temperature */
1215
/* Multiple Centigrade temps per line */
1216
case 2: sprintf( temp, "\t%3.2f", temp_c );
1220
/* Multiple Fahrenheit temps per line */
1221
case 3: sprintf( temp, "\t%3.2f", c2f(temp_c) );
1225
default: owSerialNum( 0, &TempSN[0], TRUE );
1226
log_temp( sensor, temp_c, TempSN );
1228
} /* switch( log_type ) */
1230
/* Show the scratchpad if verbose is seelcted */
1231
if( opts & OPT_VERBOSE )
1233
show_scratchpad( scratchpad, sensor_family );
1234
} /* if OPT_VERBOSE */
1236
/* Good conversion finished */
1239
fprintf( stderr, "CRC Failed. CRC is %02X instead of 0x00\n", lastcrc8 );
1241
if( opts & OPT_VERBOSE )
1243
show_scratchpad( scratchpad, sensor_family );
1244
} /* if OPT_VERBOSE */
1246
} /* Scratchpad Read */
1247
} /* owAccess failed */
1248
} /* owAccess failed */
1250
/* Failed to read, rest the network, delay and try again */
1252
msDelay( read_time );
1255
/* Failed, no good reads after MAX_READ_TRIES */
1260
/* -----------------------------------------------------------------------
1261
Read the current counter values
1262
----------------------------------------------------------------------- */
1263
int read_counter( int sensor_family, int sensor )
1265
char temp[1024]; /* For output string */
1266
unsigned char TempSN[8];
1268
unsigned long counter_value;
1270
if( sensor_family == DS2422_FAMILY )
1272
/* Read Pages 2, 3 */
1273
for( page=2; page<=3; page++ )
1275
if( ReadCounter( 0, page, &counter_value ) )
1277
/* Log the counter */
1280
/* Multiple Centigrade temps per line */
1282
case 3: sprintf( temp, "\t%ld", counter_value );
1286
default: owSerialNum( 0, &TempSN[0], TRUE );
1287
log_counter( sensor, page-2, counter_value, TempSN );
1289
} /* switch( log_type ) */
1292
} else if( sensor_family == DS2423_FAMILY ) {
1293
/* Read Pages 14, 15 */
1294
for( page=14; page<=15; page++ )
1296
if( ReadCounter( 0, page, &counter_value ) )
1298
/* Log the counter */
1301
/* Multiple Centigrade temps per line */
1303
case 3: sprintf( temp, "\t%ld", counter_value );
1307
default: owSerialNum( 0, &TempSN[0], TRUE );
1308
log_counter( sensor, page-14, counter_value, TempSN );
1310
} /* switch( log_type ) */
1319
/* -----------------------------------------------------------------------
1326
!!!! Not finished !!!!
1327
Needs an output format string system. Hard-coded for the moment.
1328
----------------------------------------------------------------------- */
1329
int read_ds2438( int sensor_family, int sensor )
1334
unsigned char temp[1024],
1339
if( sensor_family == DS2438_FAMILY )
1341
temperature = Get_Temperature(0);
1344
vdd = Volt_Reading(0, 1);
1347
ad = Volt_Reading(0, 0);
1349
mytime = time(NULL);
1352
sprintf( time_format, "%%b %%d %%H:%%M:%%S Sensor %d VDD: %0.2f AD: %0.2f C: %0.2f", sensor, vdd, ad, temperature );
1354
/* Handle the time format tokens */
1355
strftime( temp, 1024, time_format, localtime( &mytime ) );
1357
strcat( temp, "\n" );
1359
sprintf( temp, "Time Error\n" );
1362
/* Log it to stdout, logfile or both */
1370
/* -----------------------------------------------------------------------
1371
(This routine is modified from code by Eric Wilde)
1373
Read the humidity from one sensor (e.g. the AAG TAI8540x).
1375
Log the temperature value and relative humidity.
1377
Calculated using formula cribbed from the Dallas source code (gethumd.c),
1378
DS2438 data sheet and HIH-3610 data sheet.
1380
Sensors like the TAI8540x use a DS2438 battery monitor to sense temperature
1381
and convert humidity readings from a Honeywell HIH-3610. The DS2438
1384
Status/config = scratchpad[2]
1385
Temp LSB = scratchpad[3]
1386
Temp MSB = scratchpad[4]
1387
Voltage LSB = scratchpad[5]
1388
Voltage MSB = scratchpad[6]
1389
CRC = scratchpad[10]
1392
temp = (Temp MSB * 32) + -------- * 0.03125
1395
The temperature is a two's complement signed number.
1397
voltage = ((Voltage MSB * 256) + Voltage LSB) / 100
1399
There are two voltages that must be read to get an accurate humidity
1400
reading. The supply voltage (VDD) is read to determine what voltage the
1401
humidity sensor is running at (this affects the zero offset and slope of
1402
the humidity curve). The sensor voltage (VAD) is read to get the humidity
1403
value. Here is the formula for the humidity (temperature and voltage
1406
((VAD/VDD) - 0.16) * 161.29
1407
humidity = ---------------------------
1408
1.0546 - (0.00216 * temp)
1410
The humidity sensor is linear from approx 10% to 100% R.H. Accuracy is
1413
!!!! Not Finished !!!!
1414
----------------------------------------------------------------------- */
1415
int read_humidity( int sensor_family, int sensor )
1417
double temp_c; /* Converted temperature in degrees C */
1418
float sup_voltage, /* Supply voltage in volts */
1419
hum_voltage, /* Humidity sensor voltage in volts */
1420
humidity; /* Calculated humidity in %RH */
1421
unsigned char TempSN[8];
1424
for( try = 0; try < MAX_READ_TRIES; try++ )
1426
/* Read Vdd, the supply voltage */
1427
if( (sup_voltage = Volt_Reading(0, 1)) != -1.0 )
1429
/* Read A/D reading from the humidity sensor */
1430
if( (hum_voltage = Volt_Reading(0, 0)) != -1.0 )
1432
/* Read the temperature */
1433
temp_c = Get_Temperature(0);
1435
/* Convert the measured voltage to humidity */
1436
humidity = (((hum_voltage/sup_voltage) - 0.16) * 161.29)
1437
/ (1.0546 - (0.00216 * temp_c));
1438
if( humidity > 100.0 )
1440
else if( humidity < 0.0 )
1443
/* Log the temperature and humidity */
1444
owSerialNum( 0, &TempSN[0], TRUE );
1445
log_humidity( sensor, temp_c, humidity, TempSN );
1447
/* Good conversion finished */
1460
/* -----------------------------------------------------------------------
1461
Select the indicated device, turning on any required couplers
1462
----------------------------------------------------------------------- */
1463
int read_device( struct _roms *sensor_list, int sensor )
1465
unsigned char TempSN[8],
1470
struct _coupler *c_ptr; /* Coupler linked list */
1472
/* Tell the sensor to do a temperature conversion */
1474
/* Sort out how to address the sensor.
1475
If sensor < num_sensors then it can be directly addressed
1476
if sensor >= num_sensors then the coupler must first be
1477
addressed and the correct branch turned on.
1479
if( sensor < sensor_list->max )
1481
/* Address the sensor directly */
1482
owSerialNum( 0, &sensor_list->roms[sensor*8], FALSE );
1484
/* Step through the coupler list until the right sensor is found.
1485
Sensors are in order.
1487
s = sensor - sensor_list->max;
1488
c_ptr = coupler_top;
1491
if( s < c_ptr->num_main )
1493
/* Found the right area */
1495
/* Is this coupler & branch already on? */
1496
if( !cmpSN( c_ptr->SN, Last2409, 0 ) )
1498
/* Turn on the main branch */
1499
if(!SetSwitch1F(0, c_ptr->SN, DIRECT_MAIN_ON, 0, a, TRUE))
1501
printf("Setting Switch to Main ON state failed\n");
1504
/* Remember the last selected coupler & Branch */
1505
memcpy( &Last2409, &c_ptr->SN, 8 );
1509
/* Select the sensor */
1510
owSerialNum( 0, &c_ptr->main[s*8], FALSE );
1513
s -= c_ptr->num_main;
1514
if( s < c_ptr->num_aux )
1516
/* Found the right area */
1518
/* Is this coupler & branch already on? */
1519
if( !cmpSN( c_ptr->SN, Last2409, 1 ) )
1521
/* Turn on the aux branch */
1522
if(!SetSwitch1F(0, c_ptr->SN, AUXILARY_ON, 2, a, TRUE))
1524
printf("Setting Switch to Aux ON state failed\n");
1527
/* Remember the last selected coupler & Branch */
1528
memcpy( &Last2409, &c_ptr->SN, 8 );
1530
} /* Last2409 check */
1532
/* Select the sensor */
1533
owSerialNum( 0, &c_ptr->aux[s*8], FALSE );
1537
s -= c_ptr->num_aux;
1538
c_ptr = c_ptr->next;
1542
/* Get the Serial # selected */
1543
owSerialNum( 0, &TempSN[0], TRUE );
1544
sensor_family = TempSN[0];
1546
switch( sensor_family )
1550
case DS18B20_FAMILY:
1551
status = read_temperature( sensor_family, sensor );
1556
status = read_counter( sensor_family, sensor );
1560
if( opts & OPT_DS2438 )
1562
status = read_ds2438( sensor_family, sensor );
1564
status = read_humidity( sensor_family, sensor );
1575
/* -----------------------------------------------------------------------
1576
Read the temperaturess for all the connected sensors
1578
Step through all the sensors in the list of serial numbers
1579
----------------------------------------------------------------------- */
1580
int read_all( struct _roms *sensor_list )
1584
for( x = 0; x < (num_cs+sensor_list->max); x++ )
1586
read_device( sensor_list, x );
1593
/* -----------------------------------------------------------------------
1594
Read a .digitemprc file from the current directory
1596
The rc file contains:
1600
READ_TIME <time in mS>
1602
LOG_FORMAT <format string for temperature logging and printing>
1603
CNT_FORMAT <format string for counter logging and printing>
1604
SENSORS <number of ROM lines>
1605
Multiple ROM x <serial number in bytes> lines
1608
Multiple COUPLER x <serial number in decimal> lines
1609
CROM x <COUPLER #> <M or A> <Serial number in decimal>
1611
----------------------------------------------------------------------- */
1612
int read_rcfile( char *fname, struct _roms *sensor_list )
1618
struct _coupler *c_ptr, *coupler_end;
1622
c_ptr = coupler_top;
1623
coupler_end = coupler_top;
1625
if( ( fp = fopen( fname, "r" ) ) == NULL )
1627
/* No rcfile to read, could be part of an -i so don't die */
1631
while( fgets( temp, 80, fp ) != 0 )
1633
if( (temp[0] == '\n') || (temp[0] == '#') )
1636
ptr = strtok( temp, " \t\n" );
1638
if( strncasecmp( "TTY", ptr, 3 ) == 0 )
1640
ptr = strtok( NULL, " \t\n" );
1641
strncpy( serial_port, ptr, sizeof(serial_port)-1 );
1642
} else if( strncasecmp( "LOG_TYPE", ptr, 8 ) == 0 ) {
1643
ptr = strtok( NULL, " \t\n");
1644
log_type = atoi( ptr );
1645
} else if( strncasecmp( "LOG_FORMAT", ptr, 10 ) == 0 ) {
1646
ptr = strtok( NULL, "\"\n");
1647
strncpy( temp_format, ptr, sizeof(temp_format)-1 );
1648
} else if( strncasecmp( "CNT_FORMAT", ptr, 10 ) == 0 ) {
1649
ptr = strtok( NULL, "\"\n");
1650
strncpy( counter_format, ptr, sizeof(counter_format)-1 );
1651
} else if( strncasecmp( "HUM_FORMAT", ptr, 10 ) == 0 ) {
1652
ptr = strtok( NULL, "\"\n");
1653
strncpy( humidity_format, ptr, sizeof(humidity_format)-1 );
1654
} else if( strncasecmp( "LOG", ptr, 3 ) == 0 ) {
1655
ptr = strtok( NULL, " \t\n" );
1656
strncpy( log_file, ptr, sizeof(log_file)-1 );
1657
} else if( strncasecmp( "FAIL_TIME", ptr, 9 ) == 0 ) {
1659
} else if( strncasecmp( "READ_TIME", ptr, 9 ) == 0 ) {
1660
ptr = strtok( NULL, " \t\n");
1661
read_time = atoi( ptr );
1662
} else if( strncasecmp( "SENSORS", ptr, 7 ) == 0 ) {
1663
ptr = strtok( NULL, " \t\n" );
1664
sensors = atoi( ptr );
1668
/* Reserve some memory for the list */
1669
if( ( sensor_list->roms = malloc( sensors * 8 ) ) == NULL )
1671
fprintf( stderr, "Error reserving memory for %d sensors\n", sensors );
1674
sensor_list->max = sensors;
1676
} else if( strncasecmp( "ROM", ptr, 3 ) == 0 ) {
1677
/* Main LAN sensors */
1678
ptr = strtok( NULL, " \t\n" );
1679
sensors = atoi( ptr );
1681
/* Read the 8 byte ROM address */
1682
for( x = 0; x < 8; x++ )
1684
ptr = strtok( NULL, " \t\n" );
1685
sensor_list->roms[(sensors * 8) + x] = strtol( ptr, (char **)NULL, 0 );
1687
} else if( strncasecmp( "COUPLER", ptr, 7 ) == 0 ) {
1688
/* DS2409 Coupler list, they are ALWAYS in order, so ignore the
1689
coupler # and create the list in the order found
1692
/* Allocate space for this coupler */
1693
/* Create a new entry in the coupler linked list */
1694
if( (c_ptr = malloc( sizeof( struct _coupler ) ) ) == NULL )
1696
fprintf( stderr, "Failed to allocate %d bytes for coupler linked list\n", sizeof( struct _coupler ) );
1698
if( sensor_list != NULL )
1703
owRelease(0, temp );
1704
fprintf( stderr, "USB ERROR: %s\n", temp );
1710
c_ptr->num_main = 0;
1715
if( coupler_top == NULL )
1717
/* First coupler, add it to the top of the list */
1718
coupler_top = c_ptr;
1719
coupler_end = c_ptr;
1721
/* Add the new coupler to the list, point to new end */
1722
coupler_end->next = c_ptr;
1723
coupler_end = c_ptr;
1726
/* Ignore the coupler # */
1727
ptr = strtok( NULL, " \t\n" );
1729
/* Read the 8 byte ROM address */
1730
for( x = 0; x < 8; x++ )
1732
ptr = strtok( NULL, " \t\n" );
1733
c_ptr->SN[x] = strtol( ptr, (char **)NULL, 0);
1735
} else if( strncasecmp( "CROM", ptr, 4 ) == 0 ) {
1736
/* Count the number of coupler connected sensors */
1739
/* DS2409 Coupler sensors */
1740
/* Ignore sensor #, they are all created in order */
1741
ptr = strtok( NULL, " \t\n" );
1743
/* Get the coupler number, and set the pointer to the right
1746
ptr = strtok( NULL, " \t\n" );
1748
c_ptr = coupler_top;
1749
while( c_ptr && (x > 0) )
1751
c_ptr = c_ptr->next;
1755
/* Make sure we are pointing to something */
1758
/* Main/Aux branch */
1759
ptr = strtok( NULL, " \t\n" );
1763
/* Add to the main list */
1766
/* Allocate enough space for the new serial number */
1767
if( (c_ptr->main = realloc( c_ptr->main, c_ptr->num_main * 8 ) ) == NULL )
1769
fprintf( stderr, "Failed to allocate %d bytes for main branch\n", c_ptr->num_main * 8 );
1771
if( sensor_list != NULL )
1772
free( sensor_list );
1776
owRelease(0, temp );
1777
fprintf( stderr, "USB ERROR: %s\n", temp );
1782
/* Add the serial number to the list */
1783
for( x = 0; x < 8; x++ )
1785
ptr = strtok( NULL, " \t\n" );
1786
c_ptr->main[((c_ptr->num_main-1)*8)+x] = strtol( ptr, (char **)NULL,0);
1789
/* Add to the aux list */
1792
/* Allocate enough space for the new serial number */
1793
if( (c_ptr->aux = realloc( c_ptr->aux, c_ptr->num_aux * 8 ) ) == NULL )
1795
fprintf( stderr, "Failed to allocate %d bytes for aux branch\n", c_ptr->num_aux * 8 );
1797
if( sensor_list != NULL )
1798
free( sensor_list );
1802
owRelease(0, temp );
1803
fprintf( stderr, "USB ERROR: %s\n", temp );
1806
} /* Allocate more aux space */
1808
/* Add the serial number to the list */
1809
for( x = 0; x < 8; x++ )
1811
ptr = strtok( NULL, " \t\n" );
1812
c_ptr->aux[((c_ptr->num_aux-1)*8)+x] = strtol( ptr, (char **)NULL, 0 );
1813
} /* aux serial number loop */
1814
} /* Main/Aux branch check */
1815
} /* c_ptr Pointing somewhere check */
1817
fprintf( stderr, "Error reading %s file\n", fname );
1818
free( sensor_list );
1830
/* -----------------------------------------------------------------------
1831
Write a .digitemprc file, it contains:
1835
READ_TIME <time in mS>
1837
LOG_FORMAT <format string for temperature logging and printing>
1838
CNT_FORMAT <format string for counter logging and printing>
1839
SENSORS <number of ROM lines>
1840
Multiple ROM x <serial number in bytes> lines
1843
Multiple COUPLER x <serial number in decimal> lines
1844
CROM x <COUPLER #> <M or A> <Serial number in decimal>
1847
All serial numbers are now in Hex. Still can read older decimal
1849
Added 'ALIAS # <string>'
1850
----------------------------------------------------------------------- */
1851
int write_rcfile( char *fname, struct _roms *sensor_list )
1855
struct _coupler *c_ptr;
1857
if( ( fp = fopen( fname, "wb" ) ) == NULL )
1862
fprintf( fp, "TTY %s\n", serial_port );
1863
if( log_file[0] != 0 )
1864
fprintf( fp, "LOG %s\n", log_file );
1866
fprintf( fp, "READ_TIME %d\n", read_time ); /* mSeconds */
1868
fprintf( fp, "LOG_TYPE %d\n", log_type );
1869
fprintf( fp, "LOG_FORMAT \"%s\"\n", temp_format );
1870
fprintf( fp, "CNT_FORMAT \"%s\"\n", counter_format );
1871
fprintf( fp, "HUM_FORMAT \"%s\"\n", humidity_format );
1873
fprintf( fp, "SENSORS %d\n", sensor_list->max );
1875
for( x = 0; x < sensor_list->max; x++ )
1877
fprintf( fp, "ROM %d ", x );
1879
for( y = 0; y < 8; y++ )
1881
fprintf( fp, "0x%02X ", sensor_list->roms[(x * 8) + y] );
1883
fprintf( fp, "\n" );
1886
/* If any DS2409 Couplers were found, write out their information too */
1887
/* Write out the couplers first */
1888
c_ptr = coupler_top;
1892
fprintf( fp, "COUPLER %d ", x );
1893
for( y = 0; y < 8; y++ )
1895
fprintf( fp, "0x%02X ", c_ptr->SN[y] );
1897
fprintf( fp, "\n" );
1899
c_ptr = c_ptr->next;
1900
} /* Coupler list */
1902
/* Sendor # ID for coupler starts at num_sensors */
1905
/* Start at the top of the coupler list */
1906
c_ptr = coupler_top;
1910
/* Print the devices on this coupler's main branch */
1911
if( c_ptr->num_main > 0 )
1913
for( i = 0; i < c_ptr->num_main; i++ )
1915
fprintf( fp, "CROM %d %d M ", sensor_list->max+num_cs++, x );
1917
for( y = 0; y < 8; y++ )
1919
fprintf( fp, "0x%02X ", c_ptr->main[(i * 8) + y] );
1921
fprintf( fp, "\n" );
1925
/* Print the devices on this coupler's aux branch */
1926
if( c_ptr->num_aux > 0 )
1928
for( i = 0; i < c_ptr->num_aux; i++ )
1930
fprintf( fp, "CROM %d %d A ", sensor_list->max+num_cs++, x );
1932
for( y = 0; y < 8; y++ )
1934
fprintf( fp, "0x%02X ", c_ptr->aux[(i * 8) + y] );
1936
fprintf( fp, "\n" );
1941
c_ptr = c_ptr->next;
1942
} /* Coupler list */
1946
if( !(opts & OPT_QUIET) )
1948
fprintf( stderr, "Wrote %s\n",fname);
1954
/* -----------------------------------------------------------------------
1955
Print out a serial number
1956
----------------------------------------------------------------------- */
1957
void printSN( unsigned char *TempSN, int crlf )
1961
/* Print the serial number */
1962
for( y = 0; y < 8; y++ )
1964
printf("%02X", TempSN[y] );
1971
/* -----------------------------------------------------------------------
1972
Walk the entire connected 1-wire LAN and display the serial number
1974
----------------------------------------------------------------------- */
1977
unsigned char TempSN[8],
1980
struct _roms coupler_list; /* Attached Roms */
1983
bzero( &coupler_list, sizeof( struct _roms ) );
1985
/* Find any DS2409 Couplers and turn them all off.
1986
This WILL NOT WORK if there is a coupler attached to the
1987
bus of another coupler. DigiTemp on;y supports couplers
1988
on the main 1-Wire LAN.
1990
We also don't record any couplers in this loop because if
1991
one was one and we detected a branch that is closed off
1992
after it is turned off we will end up with multiple copies
1993
of the same couplers.
1995
if( !(opts & OPT_QUIET) )
1997
printf("Turning off all DS2409 Couplers\n");
1999
result = owFirst( 0, TRUE, FALSE );
2002
owSerialNum( 0, TempSN, TRUE );
2003
if( !(opts & OPT_QUIET) )
2008
if( TempSN[0] == SWITCH_FAMILY )
2010
/* Turn off the Coupler */
2011
if(!SetSwitch1F(0, TempSN, ALL_LINES_OFF, 0, InfoByte, TRUE))
2013
fprintf( stderr, "Setting Coupler to OFF state failed\n");
2015
if( coupler_list.roms != NULL )
2016
free( coupler_list.roms );
2021
result = owNext( 0, TRUE, FALSE );
2023
if( !(opts &OPT_QUIET) )
2028
/* Now we know all the couplers on the main LAN are off, we
2029
can now start mapping the 1-Wire LAN
2031
if( !(opts & OPT_QUIET) )
2033
printf("Devices on the Main LAN\n");
2035
result = owFirst( 0, TRUE, FALSE );
2038
owSerialNum( 0, TempSN, TRUE );
2039
/* Print the serial number */
2040
printSN( TempSN, 0 );
2041
printf(" : %s\n", device_name( TempSN[0]) );
2043
if( TempSN[0] == SWITCH_FAMILY )
2045
/* Save the Coupler's serial number so we can explore it later */
2046
/* Count the sensors detected */
2049
/* Allocate enough space for the new serial number */
2050
if( (coupler_list.roms = realloc( coupler_list.roms, coupler_list.max * 8 ) ) == NULL )
2052
fprintf( stderr,"Failed to allocate %d bytes for coupler_list\n", coupler_list.max * 8 );
2054
if( coupler_list.roms != NULL )
2055
free( coupler_list.roms );
2059
owSerialNum( 0, &coupler_list.roms[(coupler_list.max-1)*8], TRUE );
2061
/* Turn off the Coupler */
2062
if(!SetSwitch1F(0, TempSN, ALL_LINES_OFF, 0, InfoByte, TRUE))
2064
fprintf(stderr, "Setting Switch to OFF state failed\n");
2066
if( coupler_list.roms != NULL )
2067
free( coupler_list.roms );
2072
result = owNext( 0, TRUE, FALSE );
2074
if( !(opts & OPT_QUIET) )
2079
/* If there were any 2409 Couplers present walk their trees too */
2080
if( coupler_list.max > 0 )
2082
for(x = 0; x < coupler_list.max; x++ )
2084
if( !(opts & OPT_QUIET) )
2086
printf("\nDevices on Main Branch of Coupler : ");
2087
printSN( &coupler_list.roms[x*8], 1 );
2089
result = owBranchFirst( 0, &coupler_list.roms[x * 8], FALSE, TRUE );
2092
owSerialNum( 0, TempSN, TRUE );
2094
/* Print the serial number */
2095
printSN( TempSN, 0 );
2096
printf(" : %s\n", device_name( TempSN[0]) );
2098
result = owBranchNext(0, &coupler_list.roms[x * 8], FALSE, TRUE );
2099
} /* Main branch loop */
2101
if( !(opts & OPT_QUIET) )
2104
printf("Devices on Aux Branch of Coupler : ");
2105
printSN( &coupler_list.roms[x*8], 1 );
2107
result = owBranchFirst( 0, &coupler_list.roms[x * 8], FALSE, FALSE );
2110
owSerialNum( 0, TempSN, TRUE );
2112
/* Print the serial number */
2113
printSN( TempSN, 0 );
2114
printf(" : %s\n", device_name( TempSN[0]) );
2116
result = owBranchNext(0, &coupler_list.roms[x * 8], FALSE, FALSE );
2117
} /* Aux Branch loop */
2118
} /* Coupler loop */
2119
} /* num_couplers check */
2121
if( coupler_list.roms != NULL )
2122
free( coupler_list.roms );
2129
/* -----------------------------------------------------------------------
2130
Find all the supported temperature sensors on the bus, searching down
2131
DS2409 hubs on the main bus (but not on other hubs).
2132
----------------------------------------------------------------------- */
2133
int Init1WireLan( struct _roms *sensor_list )
2135
unsigned char TempSN[8],
2139
unsigned int found_sensors = 0;
2140
struct _coupler *c_ptr, /* Coupler pointer */
2141
*coupler_end; /* end of the list */
2143
/* Free up any thing that was read from .digitemprc */
2144
if( sensor_list->roms != NULL )
2146
free( sensor_list->roms );
2147
sensor_list->roms = NULL;
2149
sensor_list->max = 0;
2152
/* Free up the coupler list */
2155
/* Initalize the coupler pointer */
2156
coupler_end = coupler_top;
2158
if( !(opts & OPT_QUIET) )
2160
printf("Turning off all DS2409 Couplers\n");
2162
result = owFirst( 0, TRUE, FALSE );
2165
owSerialNum( 0, TempSN, TRUE );
2166
if( !(opts & OPT_QUIET) )
2171
if( TempSN[0] == SWITCH_FAMILY )
2173
/* Turn off the Coupler */
2174
if(!SetSwitch1F(0, TempSN, ALL_LINES_OFF, 0, InfoByte, TRUE))
2176
fprintf( stderr, "Setting Coupler to OFF state failed\n");
2181
result = owNext( 0, TRUE, FALSE );
2182
} /* HUB OFF search */
2183
if( !(opts & OPT_QUIET) )
2188
if( !(opts & OPT_QUIET) )
2190
printf("Searching the 1-Wire LAN\n");
2192
/* Find any DS2409 Couplers and turn them all off */
2193
result = owFirst( 0, TRUE, FALSE );
2196
owSerialNum( 0, TempSN, TRUE );
2198
if( TempSN[0] == SWITCH_FAMILY )
2200
/* Print the serial number */
2201
printSN( TempSN, 0 );
2202
printf(" : %s\n", device_name( TempSN[0]) );
2204
/* Save the Coupler's serial number */
2205
/* Create a new entry in the coupler linked list */
2206
if( (c_ptr = malloc( sizeof( struct _coupler ) ) ) == NULL )
2208
fprintf( stderr, "Failed to allocate %d bytes for coupler linked list\n", sizeof( struct _coupler ) );
2214
c_ptr->num_main = 0;
2219
if( coupler_top == NULL )
2221
/* First coupler, add it to the top of the list */
2222
coupler_top = c_ptr;
2223
coupler_end = c_ptr;
2225
/* Add the new coupler to the list, point to new end */
2226
coupler_end->next = c_ptr;
2227
coupler_end = c_ptr;
2230
/* Write the serial number to the new list entry */
2231
owSerialNum( 0, coupler_end->SN, TRUE );
2232
} else if( (TempSN[0] == DS1820_FAMILY) ||
2233
(TempSN[0] == DS1822_FAMILY) ||
2234
(TempSN[0] == DS18B20_FAMILY) ||
2235
(TempSN[0] == DS2422_FAMILY) ||
2236
(TempSN[0] == DS2423_FAMILY) ||
2237
(TempSN[0] == DS2438_FAMILY)
2240
/* Print the serial number */
2241
printSN( TempSN, 0 );
2242
printf(" : %s\n", device_name( TempSN[0]) );
2245
/* Count the sensors detected */
2248
/* Allocate enough space for the new serial number */
2249
if( (sensor_list->roms = realloc( sensor_list->roms, sensor_list->max * 8 ) ) == NULL )
2251
fprintf( stderr, "Failed to allocate %d bytes for sensor_list\n", sensor_list->max * 8 );
2252
if( sensor_list->roms )
2254
if( sensor_list->roms )
2256
free( sensor_list->roms );
2257
sensor_list->roms = NULL;
2262
owSerialNum( 0, &sensor_list->roms[(sensor_list->max-1)*8], TRUE );
2264
result = owNext( 0, TRUE, FALSE );
2267
/* Now go through each coupler branch and search there */
2268
c_ptr = coupler_top;
2271
/* Search the Main branch */
2272
result = owBranchFirst( 0, c_ptr->SN, FALSE, TRUE );
2275
owSerialNum( 0, TempSN, TRUE );
2277
/* Check to see if it is a temperature sensor */
2278
if( (TempSN[0] == DS1820_FAMILY) ||
2279
(TempSN[0] == DS1822_FAMILY) ||
2280
(TempSN[0] == DS18B20_FAMILY)||
2281
(TempSN[0] == DS2422_FAMILY) ||
2282
(TempSN[0] == DS2423_FAMILY) ||
2283
(TempSN[0] == DS2438_FAMILY)
2286
/* Print the serial number */
2287
printSN( TempSN, 0 );
2288
printf(" : %s\n", device_name( TempSN[0]) );
2291
/* Count the number of sensors on the main branch */
2294
/* Allocate enough space for the new serial number */
2295
if( (c_ptr->main = realloc( c_ptr->main, c_ptr->num_main * 8 ) ) == NULL )
2297
fprintf( stderr, "Failed to allocate %d bytes for main branch\n", c_ptr->num_main * 8 );
2299
if( sensor_list->roms )
2301
free( sensor_list->roms );
2302
sensor_list->roms = NULL;
2306
owSerialNum( 0, &c_ptr->main[(c_ptr->num_main-1)*8], TRUE );
2307
} /* Add serial number to list */
2309
/* Find the next device on this branch */
2310
result = owBranchNext(0, c_ptr->SN, FALSE, TRUE );
2311
} /* Main branch loop */
2313
/* Search the Aux branch */
2314
result = owBranchFirst( 0, c_ptr->SN, FALSE, FALSE );
2317
owSerialNum( 0, TempSN, TRUE );
2319
if( (TempSN[0] == DS1820_FAMILY) ||
2320
(TempSN[0] == DS1822_FAMILY) ||
2321
(TempSN[0] == DS18B20_FAMILY)||
2322
(TempSN[0] == DS2422_FAMILY) ||
2323
(TempSN[0] == DS2423_FAMILY) ||
2324
(TempSN[0] == DS2438_FAMILY)
2327
/* Print the serial number */
2328
printSN( TempSN, 0 );
2329
printf(" : %s\n", device_name( TempSN[0]) );
2332
/* Count the number of sensors on the aux branch */
2335
/* Allocate enough space for the new serial number */
2336
if( (c_ptr->aux = realloc( c_ptr->aux, c_ptr->num_aux * 8 ) ) == NULL )
2338
fprintf( stderr, "Failed to allocate %d bytes for aux branch\n", c_ptr->num_main * 8 );
2340
if( sensor_list->roms )
2342
free( sensor_list->roms );
2343
sensor_list->roms = NULL;
2347
owSerialNum( 0, &c_ptr->aux[(c_ptr->num_aux-1)*8], TRUE );
2348
} /* Add serial number to list */
2350
/* Find the next device on this branch */
2351
result = owBranchNext(0, c_ptr->SN, FALSE, FALSE );
2352
} /* Aux branch loop */
2354
c_ptr = c_ptr->next;
2355
} /* Coupler loop */
2359
Did the search find any sensors? Even if there was an error it may
2360
have found some valid sensors
2364
/* Was anything found on the main branch? */
2365
if( sensor_list->max > 0 )
2367
for( x = 0; x < sensor_list->max; x++ )
2369
printf("ROM #%d : ", x );
2370
printSN( &sensor_list->roms[x*8], 1 );
2372
} /* num_sensors check */
2374
/* Was anything found on any DS2409 couplers? */
2375
c_ptr = coupler_top;
2378
/* Check the main branch */
2379
if( c_ptr->num_main > 0 )
2381
for( x = 0; x < c_ptr->num_main; x++ )
2383
printf("ROM #%d : ", sensor_list->max+num_cs++ );
2384
printSN( &c_ptr->main[x*8], 1 );
2388
/* Check the aux branch */
2389
if( c_ptr->num_aux > 0 )
2391
for( x = 0; x < c_ptr->num_aux; x++ )
2393
printf("ROM #%d : ", sensor_list->max+num_cs++ );
2394
printSN( &c_ptr->aux[x*8], 1 );
2399
c_ptr = c_ptr->next;
2400
} /* Coupler list loop */
2402
/* Write the new list of sensors to the current directory */
2403
write_rcfile( conf_file, sensor_list );
2409
/* ----------------------------------------------------------------------- *
2410
DigiTemp main routine
2412
Parse command line options, run functions
2413
* ----------------------------------------------------------------------- */
2414
int main( int argc, char *argv[] )
2416
int sensor; /* Single sensor index to read */
2417
char temp[1024]; /* Temporary strings */
2420
int sample_delay = 0; /* Delay between samples (SEC) */
2422
num_samples = 1; /* Number of samples */
2423
time_t last_time, /* Last time we started samples */
2424
start_time; /* Starting time */
2425
long int elapsed_time; /* Elapsed from start */
2426
struct _roms sensor_list; /* Attached Roms */
2427
pid_t pid; /* pid of process using serial */
2430
/* Make sure the structure is erased */
2431
bzero( &sensor_list, sizeof( struct _roms ) );
2436
fprintf(stderr,"Error! Not enough arguements.\n\n");
2442
serial_port[0] = 0; /* No default port */
2444
strcpy( serial_port, "USB" );
2446
tmp_serial_port[0] = 0;
2447
log_file[0] = 0; /* No default log file */
2448
tmp_log_file[0] = 0;
2449
tmp_counter_format[0] = 0;
2450
tmp_temp_format[0] = 0;
2451
tmp_humidity_format[0] = 0;
2452
read_time = 1000; /* 1000mS read delay */
2454
sensor = 0; /* First sensor in list */
2455
log_type = 1; /* Normal DigiTemp logfile */
2457
sample_delay = 0; /* No delay */
2458
num_samples = 1; /* Only do it once by default */
2460
/* Default log format string: */
2461
/* May 24 21:25:43 Sensor 0 C: 23.66 F: 74.59 */
2462
strcpy( temp_format, "%b %d %H:%M:%S Sensor %s C: %.2C F: %.2F" );
2463
strcpy( counter_format, "%b %d %H:%M:%S Sensor %s #%n %C" );
2464
strcpy( humidity_format, "%b %d %H:%M:%S Sensor %s C: %.2C F: %.2F H: %h%%" );
2465
strcpy( conf_file, ".digitemprc" );
2466
strcpy( option_list, "?hqiaAvwr:f:s:l:t:d:n:o:c:O:H:" );
2469
/* Command line options override any .digitemprc options temporarily */
2470
/* Unless the -i parameter is specified, then changes are saved to */
2471
/* .digitemprc file */
2473
optind = OPTINDSTART;
2476
while( (c = getopt(argc, argv, option_list)) != GETOPTEOF )
2478
/* Process the command line arguments */
2481
case 'c': if( optarg ) /* Configuration file */
2483
strncpy( conf_file, optarg, sizeof( conf_file ) - 1 );
2487
case 'w': opts |= OPT_WALK; /* Walk the LAN */
2490
case 'i': opts |= OPT_INIT; /* Initalize the s#'s */
2493
case 'r': tmp_read_time = atoi(optarg); /* Read delay in mS */
2496
case 'v': opts |= OPT_VERBOSE; /* Verbose */
2499
case 's': if(optarg) /* Serial port */
2501
strncpy( tmp_serial_port, optarg, sizeof(tmp_serial_port) - 1 );
2505
case 'l': if(optarg) /* Log Filename */
2507
strncpy( tmp_log_file, optarg, sizeof( tmp_log_file ) - 1);
2511
case 't': if(optarg) /* Single Sensor # */
2513
sensor = atoi(optarg);
2518
case 'a': opts |= OPT_ALL; /* Read All sensors */
2521
case 'd': if(optarg) /* Sample Delay */
2523
sample_delay = atoi(optarg);
2527
case 'n': if(optarg) /* Number of samples */
2529
num_samples = atoi(optarg);
2533
case 'A': opts |= OPT_DS2438; /* Treat DS2438 as A/D converter */
2536
case 'o': if(optarg) /* Temperature Logfile format */
2538
if( isdigit( optarg[0] ) )
2540
/* Its a number, get it */
2541
tmp_log_type = atoi(optarg);
2543
/* Not a nuber, get the string */
2544
if( strlen( optarg ) > sizeof(tmp_temp_format)-1 )
2545
printf("Temperature format string too long! > %d\n", sizeof(tmp_temp_format)-1);
2547
strncpy( tmp_temp_format, optarg, sizeof(tmp_temp_format)-1 );
2553
case 'O': if(optarg) /* Counter Logfile format */
2555
if( strlen( optarg ) > sizeof(tmp_counter_format)-1 )
2556
printf("Counter format string too long! > %d\n", sizeof(tmp_counter_format)-1);
2558
strncpy( tmp_counter_format, optarg, sizeof(tmp_counter_format)-1 );
2562
case 'H': if(optarg) /* Humidity Logfile format */
2564
if( strlen( optarg ) > sizeof(tmp_humidity_format)-1 )
2565
printf("Humidity format string too long! > %d\n", sizeof(tmp_humidity_format)-1);
2567
strncpy( tmp_humidity_format, optarg, sizeof(tmp_humidity_format)-1 );
2571
case 'q': opts |= OPT_QUIET;
2581
} /* switch getopt */
2582
} /* while getopt */
2584
/* Require one 1 action command, no more, no less. */
2585
if ((opts & (OPT_WALK|OPT_INIT|OPT_SINGLE|OPT_ALL)) == 0 )
2587
fprintf( stderr, "Error! You need 1 of the following action commands, -w -a -i -t\n");
2591
if ( read_rcfile( conf_file, &sensor_list ) < 0 ) {
2595
/* Now we go through and override with values from the command line */
2596
if (tmp_read_time > 0) {
2597
read_time = tmp_read_time;
2600
if (tmp_serial_port[0] != 0) {
2601
strncpy( serial_port, tmp_serial_port, sizeof(serial_port)-1 );
2604
if (tmp_log_file[0] != 0) {
2605
strncpy( log_file, tmp_log_file, sizeof(log_file)-1 );
2608
if (tmp_log_type != -1) {
2609
log_type = tmp_log_type;
2610
if ( tmp_log_type == 0 )
2612
strncpy( temp_format, tmp_temp_format, sizeof(temp_format)-1 );
2616
if( tmp_counter_format[0] != 0 ) {
2617
strncpy( counter_format, tmp_counter_format, sizeof(counter_format)-1 );
2620
if( tmp_humidity_format[0] != 0 ) {
2621
strncpy( humidity_format, tmp_humidity_format, sizeof(humidity_format)-1 );
2624
/* Show the copyright banner? */
2625
if( !(opts & OPT_QUIET) )
2632
/* Check to make sure we have permission to access the port */
2634
if( access( serial_port, R_OK|W_OK ) < 0 ) {
2635
fprintf( stderr, "Error, you don't have +rw permission to access %s\n", serial_port );
2637
if( sensor_list.roms != NULL )
2638
free( sensor_list.roms );
2640
if( coupler_top != NULL )
2646
/* Lock our use of the serial port, exit if it is in use */
2650
/* First turn serial_port into just the final device name */
2651
if( !(p = strrchr( serial_port, '/' )) )
2653
fprintf( stderr, "Error getting serial device from %s\n", serial_port );
2655
if( sensor_list.roms != NULL )
2656
free( sensor_list.roms );
2658
if( coupler_top != NULL )
2663
strncpy( serial_dev, p+1, sizeof(serial_dev)-1 );
2665
if( (pid = dev_lock( serial_dev )) != 0 )
2669
fprintf( stderr, "Error locking %s. Do you have permission to write to /var/lock?\n", serial_dev );
2671
fprintf( stderr, "Error, %s is locked by process %d\n", serial_dev, pid );
2674
if( sensor_list.roms != NULL )
2675
free( sensor_list.roms );
2677
if( coupler_top != NULL )
2682
#endif /* LOCKDEV */
2687
/* Connect to the MLan network */
2689
if( !owAcquire( 0, serial_port) )
2692
if( !owAcquire( 0, serial_port, temp ) )
2694
fprintf( stderr, "USB ERROR: %s\n", temp );
2697
/* Error connecting, print the error and exit */
2698
OWERROR_DUMP(stdout);
2700
if( sensor_list.roms != NULL )
2701
free( sensor_list.roms );
2703
if( coupler_top != NULL )
2709
dev_unlock( serial_dev, 0 );
2710
#endif /* LOCKDEV */
2717
/* Should we walk the whole LAN and display all devices? */
2718
if( opts & OPT_WALK )
2722
if( sensor_list.roms != NULL )
2723
free( sensor_list.roms );
2725
if( coupler_top != NULL )
2731
owRelease(0, temp );
2737
dev_unlock( serial_dev, 0 );
2738
#endif /* LOCKDEV */
2746
/* ------------------------------------------------------------------*/
2747
/* Should we initalize the sensors? */
2748
/* This should store the serial numbers to the .digitemprc file */
2749
if( opts & OPT_INIT )
2751
if( Init1WireLan( &sensor_list ) != 0 )
2753
if( sensor_list.roms != NULL )
2754
free( sensor_list.roms );
2756
if( coupler_top != NULL )
2759
/* Close the serial port */
2763
owRelease(0, temp );
2764
fprintf( stderr, "USB ERROR: %s\n", temp );
2770
dev_unlock( serial_dev, 0 );
2771
#endif /* LOCKDEV */
2780
/* Record the starting time */
2781
start_time = time(NULL);
2783
/* Sample the prescribed number of times, 0=infinity */
2784
for( x = 0;num_samples==0 || x < num_samples; x++ )
2786
last_time = time(NULL);
2787
elapsed_time = last_time - start_time;
2791
/* For this type of logging we print out the elapsed time at the
2795
case 2: sprintf(temp, "%ld", elapsed_time );
2803
/* Should we read just one sensor? */
2804
if( opts & OPT_SINGLE )
2806
read_device( &sensor_list, sensor );
2809
/* Should we read all connected sensors? */
2810
if( opts & OPT_ALL )
2812
read_all( &sensor_list );
2817
/* For this type of logging we print out the elapsed time at the
2821
case 2: log_string( "\n" );
2827
/* Wait until we have passed last_time + sample_delay. We do it
2828
this way because reading the sensors takes a certain amount
2829
of time, and sample_delay may be less then the time needed
2830
to read all the sensors. We should complain about this.
2832
if( (time(NULL) > last_time + sample_delay) && (sample_delay > 0) )
2834
fprintf(stderr, "Warning: delay (-d) is less than the time needed to ");
2835
fprintf(stderr, "read all of the attached sensors. It took %ld seconds", (long int) time(NULL) - last_time );
2836
fprintf(stderr, " to read the sensors\n" );
2839
/* Should we delay before the next sample? */
2840
if( sample_delay > 0 )
2842
/* Sleep for the remaining time, if there is any */
2843
if( (time(NULL) - last_time) < sample_delay )
2844
sleep( sample_delay - (time(NULL) - last_time) );
2848
if( sensor_list.roms != NULL )
2849
free( sensor_list.roms );
2856
owRelease(0, temp );
2862
dev_unlock( serial_dev, 0 );
2863
#endif /* LOCKDEV */
2872
/* Local Variables: */
2874
/* compile-command: "cd ..; make -k" */