예제 #1
0
 def test_uniq(self):
     """
     Test removal of duplicate removal
     """
     dives = (kd.Dive(datetime=datetime(2011, 5, 5)),
              kd.Dive(datetime=datetime(2011, 5, 5)),
              kd.Dive(datetime=datetime(2011, 5, 6)))
     ud = list(kd.uniq_dives(dives))
     self.assertEquals(2, len(ud))
예제 #2
0
 def test_dive_profiles_df(self):
     """
     Test dive profiles data frame creation
     """
     p1 = (
         kd.Sample(time=0, depth=10.0, temp=15.0, alarm=False),
         kd.Sample(time=10, depth=20.0, temp=14.0, alarm=False),
         kd.Sample(time=20, depth=10.0, temp=13.0, alarm=False),
     )
     p2 = (
         kd.Sample(time=1, depth=10.0, temp=15.0, alarm=False),
         kd.Sample(time=11,
                   depth=20.0,
                   temp=14.0,
                   deco_time=4,
                   deco_depth=9,
                   alarm=False),
         kd.Sample(time=21, depth=10.0, temp=13.0, alarm=False),
     )
     p3 = (
         kd.Sample(time=2, depth=10.0, temp=15.0, alarm=False),
         kd.Sample(time=12,
                   depth=20.0,
                   temp=14.0,
                   deco_time=1,
                   deco_depth=6,
                   alarm=True),
         kd.Sample(time=22, depth=12.0, temp=11.0, alarm=False),
         kd.Sample(time=23, depth=11.0, temp=12.0, alarm=False),
         kd.Sample(time=25, depth=10.0, temp=11.0, alarm=False),
     )
     d1 = kd.Dive(profile=p1)
     d2 = kd.Dive(profile=p2)
     d3 = kd.Dive(profile=p3)
     d = dive_profiles_df((d1, d2, d3))
     self.assertEquals(11, d.nrow)
     self.assertEquals(13, d.ncol)
     self.assertEquals((1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3), tuple(d[0]))
     self.assertEquals(
         (10.0, 20.0, 10.0, 10.0, 20.0, 10.0, 10.0, 20.0, 12.0, 11.0, 10.0),
         tuple(d[1]))
     self.assertEquals((0, 10, 20, 1, 11, 21, 2, 12, 22, 23, 25),
                       tuple(d[2]))
예제 #3
0
    def dives(self, dump):
        """
        Convert dive data into UDDF format.
        """
        ostc_data = ostc_parser.get_data(dump.data)

        for h, p in ostc_parser.profiles(ostc_data.profiles):
            log.debug('header: {}'.format(hexlify(h)))
            log.debug('profile: {}'.format(hexlify(p)))

            header = ostc_parser.header(h)
            dive_data = ostc_parser.dive_data(header, p)

            # set time of the start of dive
            st = datetime(2000 + header.year, header.month, header.day,
                          header.hour, header.minute)
            # ostc dive computer saves time at the end of dive in its
            # memory, so substract the dive time;
            # sampling amount is substracted as well as below (0, 0)
            # waypoint is added
            duration = timedelta(minutes=header.dive_time_m,
                                 seconds=header.dive_time_s + header.sampling)
            st -= duration

            # firmware ver < 1.91 has no average depth information
            avg_depth = header.avg_depth / 100.0 \
                    if hasattr(header, 'avg_depth') else None

            # firmware ver < 1.91 has no deco type information
            dive_mode = None
            if hasattr(header, 'deco_type'):
                if header.deco_type in (0, 4):
                    dive_mode = 'opencircuit'
                elif header.deco_type in (2, 5):
                    dive_mode = 'closedcircuit'
                elif header.doc_type == 3:
                    dive_mode = 'apnoe'

            try:
                profile = list(self._get_profile(header, dive_data))
                yield kd.Dive(datetime=st,
                              depth=header.max_depth / 100.0,
                              duration=duration.seconds,
                              temp=C2K(header.min_temp / 10.0),
                              avg_depth=avg_depth,
                              mode=dive_mode,
                              profile=profile)
            except ValueError as ex:
                log.error('invalid dive {0.year:>02d}-{0.month:>02d}-{0.day:>02d}' \
                    ' {0.hour:>02d}:{0.minute:>02d}' \
                    ' max depth={0.max_depth}'.format(header))
예제 #4
0
    def test_dive_reenum(self):
        """
        Test re-enumerating dives
        """
        kl.enum_dives([self.fin])

        r = ku.find(self.fin, '//uddf:dive//uddf:divenumber/text()')
        assert ['1', '2', '3'] == list(r)

        d = kd.Dive(datetime=datetime(2010, 1, 2, 5, 7),
                    depth=33.0,
                    duration=3540)
        kl.add_dive(d, self.fin)
        kl.enum_dives([self.fin])  # re-enumerate
        r = ku.find(self.fin, '//uddf:dive//uddf:divenumber/text()')
        self.assertEquals(['1', '2', '3', '4'], list(r))
예제 #5
0
    def test_dive_add_with_buddy(self):
        """
        Test adding dive with time, depth, duration and buddy
        """
        f = '{}/dive_add_buddy.uddf'.format(self.tdir)

        doc = ku.create()
        ku.create_buddy_data(doc, id='b1', fname='F', lname='N')
        ku.save(doc, f)

        d = kd.Dive(datetime=datetime(2010, 1, 2, 5, 7),
                    depth=33.0,
                    duration=3540)
        kl.add_dive(d, f, qbuddies=['b1'])

        nodes = ku.find(f, '//uddf:dive')
        dn = next(nodes)
        self.assertEquals('b1', ku.xp_first(dn, './/uddf:link/@ref'))
예제 #6
0
    def test_dive_add_with_site(self):
        """
        Test adding dive with time, depth, duration and dive site
        """
        f = '{}/dive_add_site.uddf'.format(self.tdir)

        doc = ku.create()
        ku.create_site_data(doc, id='s1', location='L1', name='N1')
        ku.save(doc, f)

        d = kd.Dive(datetime=datetime(2010, 1, 2, 5, 7),
                    depth=33.0,
                    duration=3102)
        kl.add_dive(d, f, qsite='s1')

        nodes = ku.find(f, '//uddf:dive')
        dn = next(nodes)
        self.assertEquals('s1', ku.xp_first(dn, './/uddf:link/@ref'))
예제 #7
0
    def __call__(self, args):
        """
        Execute command for adding dives into logbook file.
        """
        import kenozooid.logbook as kl
        import kenozooid.data as kd
        from dateutil.parser import parse as dparse

        lfile = args.logbook

        datetime = dparse(args.datetime)
        depth = float(args.depth)
        duration = float(args.duration) * 60

        site = args.site
        buddy = args.buddy

        dive = kd.Dive(datetime=datetime, depth=depth, duration=duration)
        kl.add_dive(dive, lfile, qsite=site, qbuddies=buddy)
예제 #8
0
    def test_dive_add(self):
        """
        Test adding dive with time, depth and duration
        """
        f = '{}/dive_add.uddf'.format(self.tdir)

        d = kd.Dive(datetime=datetime(2010, 1, 2, 5, 7),
                    depth=33.0,
                    duration=3540)
        kl.add_dive(d, f)
        nodes = ku.find(f, '//uddf:dive')

        dn = next(nodes)
        self.assertTrue(next(nodes, None) is None)

        self.assertEquals('2010-01-02T05:07:00',
                          ku.xp_first(dn, './/uddf:datetime/text()'))
        self.assertEquals('33.0',
                          ku.xp_first(dn, './/uddf:greatestdepth/text()'))
        self.assertEquals('3540', ku.xp_first(dn,
                                              './/uddf:diveduration/text()'))
예제 #9
0
    def test_dive_data_injection(self):
        """
        Test dive data injection
        """
        p1 = (
            kd.Sample(time=0, depth=10.0, temp=15.0, alarm=False),
            kd.Sample(time=10, depth=20.0, temp=14.0, alarm=False),
            kd.Sample(time=20, depth=10.0, temp=13.0, alarm=False),
        )
        p2 = (
            kd.Sample(time=1, depth=10.0, temp=15.0, alarm=False),
            kd.Sample(time=11,
                      depth=20.0,
                      temp=14.0,
                      deco_time=4,
                      deco_depth=9,
                      alarm=False),
            kd.Sample(time=21, depth=10.0, temp=13.0, alarm=False),
        )
        p3 = (
            kd.Sample(time=2, depth=10.0, temp=15.0, alarm=False),
            kd.Sample(time=12,
                      depth=20.0,
                      temp=14.0,
                      deco_time=1,
                      deco_depth=6,
                      alarm=True),
            kd.Sample(time=22, depth=12.0, temp=11.0, alarm=False),
            kd.Sample(time=23, depth=11.0, temp=12.0, alarm=False),
            kd.Sample(time=25, depth=10.0, temp=11.0, alarm=False),
        )

        d1 = kd.Dive(number=1,
                     datetime=datetime(2011, 10, 11),
                     depth=31.0,
                     duration=2010,
                     temp=12,
                     profile=p1)
        d2 = kd.Dive(number=2,
                     datetime=datetime(2011, 10, 12),
                     depth=32.0,
                     duration=2020,
                     temp=14,
                     profile=p2)
        d3 = kd.Dive(number=3,
                     datetime=datetime(2011, 10, 13),
                     depth=33.0,
                     duration=2030,
                     temp=None,
                     profile=p3)

        inject_dive_data((d1, d2, d3))

        d_df = ro.globalenv['kz.dives']

        self.assertEquals(3, d_df.nrow)
        self.assertEquals(6, d_df.ncol)
        self.assertEquals((31.0, 32.0, 33.0), tuple(d_df[2]))
        self.assertEquals((2010, 2020, 2030), tuple(d_df[3]))
        self.assertEquals((12, 14, ro.NA_Real), tuple(d_df[4]))

        p_df = ro.globalenv['kz.profiles']

        self.assertEquals(11, p_df.nrow)
        self.assertEquals(13, p_df.ncol)
        self.assertEquals((1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3), tuple(p_df[0]))
        self.assertEquals(
            (10.0, 20.0, 10.0, 10.0, 20.0, 10.0, 10.0, 20.0, 12.0, 11.0, 10.0),
            tuple(p_df[1]))
        self.assertEquals((0, 10, 20, 1, 11, 21, 2, 12, 22, 23, 25),
                          tuple(p_df[2]))
예제 #10
0
    def parse_dive(self, buffer, size, fingerprint, fsize, pdata, parser,
            boot_time, dives):
        """
        Callback used by libdivecomputer's library function to extract
        dives from a device and put it into dives queue.

        :Parameters:
         buffer
            Buffer with binary dive data.
         size
            Size of buffer dive data.
         fingerprint
            Fingerprint buffer.
         fsize
            Size of fingerprint buffer.
         pdata
            Parser user data (nothing at the moment).
         parser
            libdivecomputer parser instance.
         boot_time
            Sensus Ultra boot time.
         dives
            Queue of dives to be consumed by caller.
        """
        lib = ct.CDLL('libdivecomputer.so.0')
        lib.parser_set_data(parser, buffer, size)

        header = _dive_header(buffer)
        log.debug('parsing dive: {0}'.format(header))

        # dive time is in seconds since boot time
        # interval is substracted due to depth=0, time=0 sample injection
        st = datetime.fromtimestamp(boot_time - header.interval + header.time)
        log.debug('got dive time: {0}'.format(st))

        samples = []
        parse_sample = partial(self.parse_sample,
                dive_header=header,
                sdata={},
                sq=samples)
        
        f = FuncSample(parse_sample)
        lib.parser_samples_foreach(parser, f, None)

        log.debug('removing {} endcount samples'.format(header.endcount))
        del samples[-header.endcount:]

        # dive summary after endcount removal
        max_depth = max(samples, key=operator.attrgetter('depth')).depth
        min_temp = min(samples, key=operator.attrgetter('temp')).temp
        duration = samples[-1].time + header.interval
        
        # each dive starts below DiveHeader.threshold, therefore inject
        # first sample required by UDDF
        samples.insert(0, kd.Sample(depth=0.0, time=0))

        # each dive ends at about DiveHeader.threshold depth, therefore
        # inject last sample required by UDDF
        samples.append(kd.Sample(depth=0.0, time=duration))

        # finally, create dive data
        dive = kd.Dive(datetime=st, depth=max_depth, duration=duration,
                temp=min_temp, profile=samples)

        try:
            dives.put(dive, timeout=30)
        except Full:
            log.error('could not parse dives due to internal queue timeout')
            return 0

        return 1