Package kenozooid :: Module dc

Source Code for Module kenozooid.dc

  1  # 
  2  # Kenozooid - dive planning and analysis toolbox. 
  3  # 
  4  # Copyright (C) 2009-2019 by Artur Wroblewski <wrobell@riseup.net> 
  5  # 
  6  # This program is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 18  # 
 19   
 20  """ 
 21  Dive computer functionality. 
 22  """ 
 23   
 24  from datetime import datetime 
 25  from functools import partial 
 26  import lxml.etree as et 
 27  import logging 
 28  import re 
 29   
 30  import kenozooid.component as kc 
 31  import kenozooid.data as kd 
 32  import kenozooid.flow as kf 
 33  import kenozooid.uddf as ku 
 34   
 35  log = logging.getLogger('kenozooid.dc') 
 36   
 37  RE_VERSION = re.compile(r' \d+\.\d+$') 
38 39 -def backup(drv_name, port, fout):
40 """ 41 Backup dive computer data. 42 43 :Parameters: 44 drv_name 45 Dive computer driver name. 46 port 47 Dive computer port. 48 fout 49 Output file. 50 """ 51 drv = _mem_dump(drv_name, port) 52 data = drv.dump() 53 54 _save_dives(drv, datetime.now(), data, fout)
55
56 57 -def convert(drv_name, fin, fout):
58 """ 59 Convert binary dive computer data into UDDF. 60 61 :Parameters: 62 drv_name 63 Dive computer driver name. 64 fin 65 Binary dive computer data file name. 66 fout 67 Output file. 68 """ 69 drv = _mem_dump(drv_name) 70 with open(fin, 'rb') as f: 71 data = f.read() 72 _save_dives(drv, datetime.now(), data, fout)
73
74 75 -def extract_dives(fin, fout):
76 """ 77 Extract dives from dive computer dump data. 78 79 :Parameters: 80 fin 81 UDDF file with dive computer raw data. 82 fout 83 Output file. 84 """ 85 xp_dc = ku.XPath('//uddf:divecomputerdump') 86 87 din = et.parse(fin) 88 nodes = xp_dc(din) 89 if not nodes: 90 raise ValueError('No dive computer dump data found in {}' 91 .format(fin)) 92 93 assert len(nodes) == 1 94 95 dump = ku.dump_data(nodes[0]) 96 97 log.debug('dive computer dump data found: ' \ 98 '{0.dc_id}, {0.dc_model}, {0.datetime}'.format(dump)) 99 100 model = RE_VERSION.sub('', dump.dc_model) 101 drv = _mem_dump(model) 102 _save_dives(drv, dump.datetime, dump.data, fout)
103
104 105 -def _mem_dump(name, port=None):
106 """ 107 Find data parser device driver. 108 109 :Parameters: 110 name 111 Dive computer driver name. 112 port 113 Dive computer port. 114 """ 115 from kenozooid.driver import DataParser, find_driver 116 117 drv = find_driver(DataParser, name, port) 118 if drv is None: 119 raise ValueError('Device driver {} does not support data parsing' 120 .format(name)) 121 return drv
122
123 124 -def _save_dives(drv, time, data, fout):
125 """ 126 Convert raw dive computer data into UDDF format and store it in output 127 file. 128 129 :Parameters: 130 drv 131 Dive computer driver used to parse raw data. 132 time 133 Time of raw dive computer data fetch. 134 data 135 Raw dive computer data. 136 fout 137 Output file. 138 """ 139 model = drv.version(data) 140 dc_id = ku.gen_id(model) 141 log.debug('dive computer version {}'.format(model)) 142 143 # convert raw data into dive data and store in output file 144 bdata = kd.BinaryData(datetime=time, data=data) 145 146 eq = ku.create_dc_data(dc_id, model) 147 dump = ku.create_dump_data(dc_id=dc_id, datetime=time, data=data) 148 149 p = kc.params(drv.__class__) 150 if 'gas' in p['data']: 151 log.debug('gas data pipeline') 152 with kf.buffer_open(2) as (f_g, f_d): 153 154 # store gas and dives in two separate files, 155 # then merge the data into one UDDF file 156 save = kf.sink(partial(ku.save, fout=fout)) 157 m = kf.concat(2, partial(cat_gd, equipment=eq, dump=dump), save) 158 kf.send( 159 kf.pipe( 160 drv.dives(bdata), 161 kd.sort_dives, 162 kd.uniq_dives 163 ), 164 kf.split( 165 extract_gases(uniq_gases(kf.buffer(f_g, m))), 166 create_dives(kf.buffer(f_d, m), equipment=(dc_id,)) 167 ) 168 ) 169 170 else: 171 log.debug('simple data pipeline') 172 dives = kf.pipe(drv.dives(bdata), 173 kd.sort_dives, 174 kd.uniq_dives, 175 partial(ku.create_dives, equipment=(dc_id,))) 176 ku.save(ku.create_uddf(equipment=eq, dives=dives, dump=dump), fout)
177
178 # 179 # fixme: put the functions/coroutines below into proper modules 180 # 181 @kf.coroutine 182 -def create_dives(tg, equipment=None):
183 while True: 184 dive = yield 185 n = ku.create_dive(dive, equipment=equipment) 186 tg.send(n)
187
188 @kf.coroutine 189 -def extract_gases(tc):
190 while True: 191 dive = yield 192 for s in dive.profile: 193 if s.gas is not None: 194 tc.send(s.gas)
195
196 @kf.coroutine 197 -def uniq_gases(tc):
198 gases = set() 199 while True: 200 gas = yield 201 if gas not in gases: 202 gases.add(gas) 203 n = ku.create_gas(gas) 204 tc.send(n)
205
206 -def cat_gd(fg, fd, equipment=None, dump=None):
207 xfg = xfd = None 208 fg.seek(0) 209 fd.seek(0) 210 if len(fg.read(1)) > 0: 211 xfg = ku.xml_file_copy(fg) 212 if len(fd.read(1)) > 0: 213 xfd = ku.xml_file_copy(fd) 214 fg.seek(0) 215 fd.seek(0) 216 return ku.create_uddf(equipment=equipment, 217 dump=dump, 218 gases=xfg, 219 dives=xfd)
220 221 # vim: sw=4:et:ai 222