summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Thompson <daniel@redfelineninja.org.uk>2021-02-21 20:27:48 (GMT)
committerDaniel Thompson <daniel@redfelineninja.org.uk>2021-02-21 20:27:48 (GMT)
commit8940b7c3abf2d41ecbc80b227cfdfd0c87446d54 (patch)
tree01341e1f5b150e6dcf1892f0e566454afc1eff51
parentb7340371151617b0c602616ab6c85800dd00a870 (diff)
steplogger: Introduce code to perform data logging
The code is not yet enabled by default but it can be tested by adding custom code to an interested user's main.py . Signed-off-by: Daniel Thompson <daniel@redfelineninja.org.uk>
-rw-r--r--docs/wasp.rst4
-rw-r--r--wasp/boards/manifest_240x240.py1
-rw-r--r--wasp/steplogger.py96
3 files changed, 101 insertions, 0 deletions
diff --git a/docs/wasp.rst b/docs/wasp.rst
index e7c7953..3f0b7a2 100644
--- a/docs/wasp.rst
+++ b/docs/wasp.rst
@@ -38,6 +38,10 @@ System
:members:
:undoc-members:
+.. automodule:: steplogger
+ :members:
+ :undoc-members:
+
.. automodule:: widgets
:members:
diff --git a/wasp/boards/manifest_240x240.py b/wasp/boards/manifest_240x240.py
index d691542..e36896f 100644
--- a/wasp/boards/manifest_240x240.py
+++ b/wasp/boards/manifest_240x240.py
@@ -29,5 +29,6 @@ manifest = (
'fonts/sans28.py',
'fonts/sans36.py',
'icons.py',
+ 'steplogger.py',
'widgets.py',
)
diff --git a/wasp/steplogger.py b/wasp/steplogger.py
new file mode 100644
index 0000000..1c87985
--- /dev/null
+++ b/wasp/steplogger.py
@@ -0,0 +1,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