summaryrefslogtreecommitdiff
path: root/wasp/steplogger.py
blob: 1c8798586623bd4512eeacabf3fff2389d65980e (plain)
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
# SPDX-License-Identifier: LGPL-3.0-or-later
# Copyright (C) 2020 Daniel Thompson

"""Step logger
~~~~~~~~~~~~~~

Capture and record data from the step counter
"""

import array
import os
import time
import wasp

from micropython import const

TICK_PERIOD = const(6 * 60)
DUMP_LENGTH = const(5)
DUMP_PERIOD = const(DUMP_LENGTH * TICK_PERIOD)

class StepLogger:
    def __init__(self):
        self._data = array.array('H', (0,) * DUMP_LENGTH)
        self._steps = wasp.watch.accel.steps

        try:
            os.mkdir('logs')
        except:
            pass

        # Queue a tick
        self._t = int(wasp.watch.rtc.time()) // TICK_PERIOD * TICK_PERIOD
        wasp.system.set_alarm(self._t + TICK_PERIOD, self._tick)

    def _tick(self):
        """Capture the current step count in N minute intervals.

        The samples are queued in a small RAM buffer in order to reduce
        the number of flash access. The data is written out every few hours
        in a binary format ready to be reloaded and graphed when it is
        needed.
        """
        t = self._t

        # Work out where we are in the dump period
        i = t % DUMP_PERIOD // TICK_PERIOD

        # Get the current step count and record it
        steps = wasp.watch.accel.steps
        self._data[i] = steps - self._steps 
        self._steps = steps

        # Queue the next tick
        wasp.system.set_alarm(t + TICK_PERIOD, self._tick)
        self._t += TICK_PERIOD

        if i < (DUMP_LENGTH-1):
            return

        # Record the data in the flash
        walltime = time.localtime(t)
        yyyy = walltime[0]
        mm = walltime[1]
        dd = walltime[2]

        # Find when (in seconds) "today" started
        then = int(time.mktime((yyyy, mm, dd, 0, 0, 0, 0, 0, 0)))
        elapsed = t - then

        # Work out how dumps we expect to find in today's dumpfile
        dump_num = elapsed // DUMP_PERIOD

        # Update the log data
        try:
            os.mkdir('logs/' + str(yyyy))
        except:
            pass
        fname = 'logs/{}/{:02d}-{:02d}.steps'.format(yyyy, mm, dd)
        offset = dump_num * DUMP_LENGTH * 2
        try:
            sz = os.stat(fname)[6]
        except:
            sz = 0
        f = open(fname, 'ab')
        # This is a portable (between real Python and MicroPython) way to
        # grow the file to the right size.
        f.seek(min(sz, offset))
        for _ in range(sz, offset, 2):
            f.write(b'\x00\x00')
        f.write(self._data)
        f.close()

        # Wipe the data
        data = self._data
        for i in range(DUMP_LENGTH):
            data[i] = 0