forked from bewest/decoding-carelink
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlist_dates.py
More file actions
144 lines (121 loc) · 3.07 KB
/
list_dates.py
File metadata and controls
144 lines (121 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import sys
import argparse
import textwrap
from pprint import pprint, pformat
from binascii import hexlify
from datetime import datetime
class NotADate(Exception): pass
class Mask:
time = 0xC0
invert = 0x3F
year = 0x0F
def get_opt_parser( ):
parser = argparse.ArgumentParser( )
parser.add_argument('infile', nargs="+",
default=sys.stdin,
type=argparse.FileType('r'),
help="Find dates in this file.")
parser.add_argument('--out',
default=sys.stdout,
type=argparse.FileType('w'),
help="Write records here.")
return parser
def parse_seconds(sec):
"""
>>> parse_seconds(0x92)
18
"""
return sec & Mask.invert
def parse_minutes(minutes):
"""
>>> parse_minutes(0x9e)
30
"""
return minutes & Mask.invert
def parse_hours(hours):
"""
>>> parse_hours(0x0b)
11
"""
return int(hours)
def parse_day(day):
"""
>>> parse_day( 0x01 )
1
"""
return day & Mask.year
def parse_months(seconds, minutes):
"""
>>> parse_months( 0x92, 0x9e )
10
"""
high = (seconds & Mask.time) >> 4
low = (minutes & Mask.time) >> 6
return high | low
def parse_years(year):
y = (year & Mask.year) + 2000
if year > 15 or y < 0 or y < 2002 or y > 2015:
raise ValueError(y)
return y
def parse_date(data):
try:
seconds = parse_seconds(data[0])
minutes = parse_minutes(data[1])
hours = parse_minutes(data[2])
day = parse_minutes(data[3])
year = parse_years(data[4])
month = parse_months( data[0], data[1] )
date = datetime(year, month, day, hours, minutes, seconds)
return date
except ValueError, e:
raise NotADate(e)
def opcode_read_ahead(opcode, fd):
TABLE = {
0x07: 55,
}
if TABLE.get(opcode, False) is not False:
print "special opcode"
return bytearray(fd.read(TABLE[opcode]))
return bytearray('')
def sniff_invalid_opcode(opcode):
if opcode == 0x00:
raise NotADate("invalid opcode")
def find_dates(stream):
records = [ ]
bolus = bytearray(stream.read(4))
for B in iter(lambda: stream.read(1), ""):
bolus.append(B)
try:
date = parse_date(bolus[-5:])
if len(bolus) <= 5:
raise NotADate('too short of a record')
#sniff_invalid_opcode( bolus[0] )
#bolus.extend( opcode_read_ahead(bolus[0], stream) )
records.append( (date, bolus[:-5]) )
bolus = bytearray(stream.read(4))
except NotADate, e:
pass
return records
def main( ):
parser = get_opt_parser( )
opts = parser.parse_args( )
tw_opts = {
'width': 40,
'subsequent_indent': ' ',
'initial_indent': ' ',
}
wrapper = textwrap.TextWrapper(**tw_opts)
for stream in opts.infile:
records = find_dates(stream)
print "%s: %s records" % (stream.name, len(records))
for rec in records:
date, datum = rec
opcode = datum[0]
print "%s %02x" % (date.isoformat( ), opcode)
print wrapper.fill(hexlify(str(datum)))
if __name__ == '__main__':
import doctest
doctest.testmod( )
main( )
#####
# EOF