Commit 263c5e28 authored by Nelso Jost's avatar Nelso Jost

FIX: finished refactoring and docs/DevelopOverview

parent 27cccac5
PYBIN := python3
VENV := .venv
VENVPY := ${VENV}/bin/python
VENVDIR := $(shell pwd)/.venv
VENVPY := ${VENVDIR}/bin/python
INO_DIR := .ino
USE := ino
ARDUINO :=#~/Downloads/arduino-1.6.5
.PHONY: help setup firmware
all: help
help:
@ echo "USAGE: make <command>"
@ echo ""
@ echo "COMMANDS:"
@ echo ""
@ echo " install -- Install required tools, build and upload firmware, and"
@ echo " deploy logger daemon (background process)"
@ echo ""
@ echo " uninstall -- Remove daemon process (if present) and clean this folder"
@ echo ""
@ echo " tail-log -- Exibits and follow last modified execution log file"
@ echo " tail-data -- Exibits and follow last modified datalog file"
@ echo ""
@ echo " plot-data col=<C> -- Uses Gnuplot to plot last modified datalog file"
@ echo ""
@ echo " help -- Shows the full help"
help-full:
@ echo "USAGE: make <command>"
@ echo ""
@ echo "COMMANDS:"
@ echo "USAGE: make <target> where <target> can be:"
@ echo ""
@ echo " install -- setup & bu & deploy-logger"
@ echo " uninstall -- undeploy-logger & clean-venv & clean-ino"
@ echo " setup Execute once to prepare the required Python virtual environment"
@ echo " firmware Compile and upload the firmware to the Arduino board via serial"
@ echo " serial Starts a serial session with Python for board communication"
@ echo ""
@ echo " apt-install -- Uses Debian's apt to install required system tools"
@ echo " venv -- Creates a Python local virtual environment at ${VENV}"
@ echo " setup -- apt-install & venv"
@ echo ""
@ echo " serial -- Enter IPython session with serial opened"
@ echo " bu -- build & upload firmware (with Arturo)"
@ echo " bus -- build & upload & serial"
@ echo ""
@ echo " sync-rtc -- Synchronizes the board's clock with the system's"
@ echo ""
@ echo " run -- Starts the logger. Keep log at logger/logs"
@ echo " deploy -- Activate logger daemon. Keep log at logger/logs/"
@ echo " undeploy -- Deactivate logger daemon"
@ echo ""
@ echo " tail-log -- Exibits and follow last modified execution log file"
@ echo " tail-data -- Exibits and follow last modified datalog file"
@ echo ""
@ echo " plot-data col=<C> -- Uses Gnuplot to plot last modified datalog file"
@ echo " Replace <C> with the column number to plot as y axis"
@ echo " clean-venv -- Remove Python's virtual environment directory"
@ echo " clean-ino -- Remove Ino folder"
@ echo " clean-data -- !!! CAUTION !!! Remove all datalog files"
@ echo " clean-logs -- !!! CAUTION !!! Remove all execution log files"
@ echo " clean-all -- Performs all the above cleans"
@ echo " run Execute the logger on the foreground. Hit Ctrl+C to stop it."
@ echo " deploy Install logger on the Supervisor daemon tool (exec background)"
@ echo " undeploy Undo the 'deploy' command"
@ echo ""
@ echo " tail-log Follow updates on the last execution log"
@ echo " tail-data Follow updates on the last data log"
@ echo " plot-data col=x Uses Gnuplot to plot last data log col number x"
apt-install:
chmod +x scripts/apt-install.sh
......@@ -75,42 +41,42 @@ setup: clean-venv create-venv
create-venv:
@ echo "-------------------------------------------------------"
virtualenv -v --python='${PYBIN}' ${VENV}
@ echo "Virtualenv with '${PYBIN}' interpreter was created at ${VENV}"
virtualenv -v --python='${PYBIN}' ${VENVDIR} --no-site-packages
${VENVDIR}/bin/pip install --upgrade pip
${VENVDIR}/bin/pip install -r logger/requirements.pip
@ echo "-------------------------------------------------------"
${VENV}/bin/pip install --upgrade pip
@ echo "-------------------------------------------------------"
${VENV}/bin/pip install -r logger/requirements.pip
@ echo "-------------------------------------------------------"
@ echo "Virtualenv is ready at ${VENV}!"
@ echo " "~/Downloads/arduino-1.0.1
@ echo "TOTAL SIZE: "
@ du -sh ${VENV}
@ echo "Required Python virtual environment installed at "
@ du -sh ${VENVDIR}
clean-venv:
rm -rf ${VENV}
rm -rf ${VENVDIR}
serial:
${VENVPY} -i logger/init_serial.py
check-venv:
@ command -v ${VENVPY} >/dev/null 2>&1 || \
{ printf "You need to prepare the required Python virtual environment";\
printf "\nfor running this software. Excecute, just once:";\
printf "\n\n $$ make setup\n\nor\n\n ";\
printf "$$ make setup PYBIN=<python_binary>\n\nfor specifying a ";\
printf "Python binary other than 'python3', like\n'python-3.x' ";\
printf "(where x is a number) for instance. \n\n"; exit 1; }
firmware: ${USE}-install
chmod +x scripts/ino-build.sh
./scripts/ino-build.sh ${USE} ${INO_DIR} ${ARDUINO}
sync-rtc:
${VENVPY} logger/run.py --syncrtc
serial:
cd logger && ${VENVPY} -i init_serial.py
logger-run:
${VENVPY} logger/run.py --verbose
run: check-venv
${VENVPY} logger/run.py
deploy: undeploy
mkdir -p logger/logs
deploy:
sudo ${VENVPY} logger/deploy.py
undeploy:
sudo ${VENVPY} logger/deploy.py -u
logger-tail:
tail-log:
$(eval TMP := $(shell ls -t -I "pid*|stdout*" logger/logs | head -n 1))
@ echo "Last log file updated: logger/logs/$(TMP)"
@ echo "File size: `du -h logger/logs/$(TMP) | cut -f1`"
......@@ -118,7 +84,7 @@ logger-tail:
@ tail -F logger/logs/$(TMP)
tail-data:
$(eval TMP := $(shell ls -t -I outgoing* data/ | head -n 1))
$(eval TMP := $(shell ls -t -I "outgoing.json" data/ | head -n 1))
@ echo "Last datalog file updated: data/$(TMP)"
@ echo "Number of lines/points: `cat data/$(TMP) | wc -l`"
@ echo "File size: `du -h data/$(TMP) | cut -f1`"
......
This diff is collapsed.
# Makefile for Sphinx documentation
#
PYBIN := python3
VENVDIR := $(shell pwd)/.venv
VENVPY := ${VENVDIR}/bin/python
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXBUILD = ${VENVDIR}/bin/sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
# ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
# $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
# endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
......@@ -20,7 +19,7 @@ I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext setup
help:
help: check-venv
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
......@@ -50,38 +49,38 @@ help:
clean:
rm -rf $(BUILDDIR)/*
html:
html: check-venv
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
dirhtml: check-venv
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
singlehtml: check-venv
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
pickle: check-venv
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
json: check-venv
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
htmlhelp: check-venv
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
qthelp: check-venv
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
......@@ -90,7 +89,7 @@ qthelp:
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/arduino-meteorolog.qhc"
applehelp:
applehelp: check-venv
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
......@@ -98,7 +97,7 @@ applehelp:
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
devhelp: check-venv
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
......@@ -107,85 +106,113 @@ devhelp:
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/arduino-meteorolog"
@echo "# devhelp"
epub:
epub: check-venv
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
latex: check-venv
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
latexpdf: check-venv
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
latexpdfja: check-venv
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
text: check-venv
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
man: check-venv
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
texinfo: check-venv
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
info: check-venv
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
gettext: check-venv
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
changes: check-venv
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
linkcheck: check-venv
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
doctest: check-venv
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
coverage: check-venv
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
xml: check-venv
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
pseudoxml: check-venv
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
setup: clean-venv create-venv
create-venv:
@ echo "-------------------------------------------------------"
virtualenv -v --python='${PYBIN}' ${VENVDIR} --no-site-packages
${VENVDIR}/bin/pip install --upgrade pip
${VENVDIR}/bin/pip install -r requirements.pip
@ echo "-------------------------------------------------------"
@ echo "Required Python virtual environment installed at "
@ du -sh ${VENVDIR}
clean-venv:
rm -rf ${VENVDIR}
check-venv:
@ command -v ${VENVPY} >/dev/null 2>&1 || \
{ printf "You need to prepare the required Python virtual environment";\
printf "\nfor running this software. Excecute, just once:";\
printf "\n\n $$ make setup\n\nor\n\n ";\
printf "$$ make setup PYBIN=<python_binary>\n\nfor specifying a ";\
printf "Python binary other than 'python3', like\n'python-3.x' ";\
printf "(where x is a number) for instance. \n\n"; exit 1; }
# User-friendly check for sphinx-build
# ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
# $(error The "'$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/")
# endif
......@@ -77,7 +77,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
exclude_patterns = ['_build', '.venv']
# The reST default role (used for this markup: `text`) to use for all
# documents.
......
......@@ -13,19 +13,6 @@ Contents:
DevelopOverview.rst
Let me tell you: this is a test.
Since Pythagoras, we know that :math:`a^2 + b^2 = c^2`.
But now that how it goes:
.. math::
(a + b)^2 = a^2 + 2ab + b^2
(a - b)^2 = a^2 - 2ab + b^2
Indices and tables
==================
......
sphinx-rtd-theme==0.1.8
......@@ -16,48 +16,38 @@ BOARD_ID =
; authentication token for the board's user
USER_HASH =
[reading]
; CSV list of sensor names/nicknames (order reflect columns on datalog files)
SENSORS = DHT22_TEMP, DHT22_AH, BMP085_PRESSURE, LDR
; time between logger cycles -- format: hours:minutes:seconds
INTERVAL = 0:5:0
; time between logger cycles, in minutes
SLEEP_MINUTES = 5
; true for read board clock; if fail, or false, system's time will be used
RTC_DS1307 = true
[datalog]
; CSV delimiter for local log files (sugestions: ',' or ';' or '\t')
CSV_SEP = '\t'
; CSV delimiter for local log files (valid options: , or ; or \t )
CSV_SEP = \t
; format of the datetime column (see Python docs on datetime module)
; format of the datetime column
; %Y : years | %m : months | %d : days | %H : hours | %M : mins | %S : secs
DATETIME_FORMAT = %Y-%m-%d-%H-%M-%S
[arduino]
; CSV list of ports to attempt or blank for automatic search on
; /dev/ttyACM* and /dev/ttyUSB* (where * varies from 0 to 10)
; CSV list of ports to attempt connection or blank for automatic search on
; /dev/ttyACM* and /dev/ttyUSB* (where * varies from 0 to 4)
SERIAL_PORT =
"""
"""
DEFAULT_INI_LINES = DEFAULT_INI.splitlines()
def make_path_here(filename):
''' Append filename to the current __file__ path. '''
return os.path.join(os.path.abspath(os.path.dirname(__file__)), filename)
class RTCDateTime:
SENSOR_NAME = 'RTC_DS1307'
READ_TIMESTAMP = '%Y-%m-%d %H:%M:%S'
__qualname__ = "RTCDateTime fmt='{}'".format(READ_TIMESTAMP)
def __init__(self, s):
self.dt = datetime.strptime(s, self.RTC_DT_FMT)
def __str__(self):
return self.dt.strftime('%Y%m%d%H%M%S')
return os.path.realpath(os.path.join(
os.path.abspath(os.path.dirname(__file__)), filename))
class Config:
......@@ -69,19 +59,75 @@ class Config:
URL_API_POST_RAWSENSORDATA = '{base}api/post/rawsensordata/{bid}'
SERIAL_CSV_SEP = ','
RTC_NAME = 'RTC_DS1307'
RTC_FORMAT = '%Y-%m-%d %H:%M:%S'
class ConfigMissingSectionError(Exception):
def __init__(self, section, parent):
self.message = "\nConfigurationError: At file\n {filename}\n\n"\
"[{section}]\n ^\n"\
"Missing section!".format(
filename=parent.SETTINGS_FILENAME,
section=section)
class ConfigMissingKeyError(Exception):
def __init__(self, section, key, parent):
self.message = "\nConfigurationError: At file\n {filename}\n\n"\
"[{section}]\n{comment}\n{key} = \n{indicator}\n"\
"Missing key!".format(
filename=parent.SETTINGS_FILENAME,
comment=parent.extract_comment(key),
section=section, key=key.upper(),
indicator=' '*len(key + ' = ') + '^')
class ConfigValueError(Exception):
def __init__(self, section, key, message, parent):
self.message = "\nConfigurationError: At file\n {filename}\n\n"\
"[{section}]\n{comment}\n{key} = {value}\n"\
"{indicator}\n{msg}".format(
filename=parent.SETTINGS_FILENAME,
section=section, key=key, msg=message,
comment=parent.extract_comment(key),
value=parent[section][key.lower()],
indicator=' '*len(key + ' = ') + '^')
def __init__(self):
super().__init__()
self.default = configparser.ConfigParser()
self.default.read_string(DEFAULT_INI)
try:
self.load_settings()
except Exception as e:
print('\nConfigurationError:', e)
print('Exception: {}'.format(e))
raise e
def __getitem__(self, key):
return self._parser._sections[key]
def __contains__(self, key):
return key in self._parser._sections
def extract_comment(self, key):
key, comment_lines = key.upper() + ' =', []
for i, line in enumerate(DEFAULT_INI_LINES):
if key in line:
j = i - 1
while j >= 0:
if not DEFAULT_INI_LINES[j].startswith(';'):
return '\n'.join(DEFAULT_INI_LINES[k]
for k in range(j+1, i))
j -= 1
def assert_config_keys(self):
for section in self.default:
if section == 'DEFAULT':
continue
if section in self:
for key in self.default[section]:
if not key in self[section]:
raise self.ConfigMissingKeyError(section, key, self)
else:
raise self.ConfigMissingSectionError(section, self)
def ask_restore_settings_file(self):
a = input("\nRestore default file now and overwrite all"
......@@ -109,19 +155,16 @@ class Config:
except:
print("Unable to open configuration file at\n {}".format(
self.SETTINGS_FILENAME))
return
pprint(self._parser._sections)
self.validate_server_url()
self.validate_reading_sensors()
self.validate_reading_interval()
self.validate_datalog_csv_sep()
self.validate_arduino_serial_port()
pprint(self._parser._sections)
self.assert_config_keys()
self.validate_server()
self.validate_reading()
self.validate_datalog()
self.validate_arduino()
def validate_server_url(self):
def validate_server(self):
try:
bid = int(self['server']['board_id'])
except:
......@@ -135,7 +178,7 @@ class Config:
('' if self['server']['url'].endswith('/') else '/'),
bid=bid)
def validate_reading_sensors(self):
def validate_reading(self):
self['reading']['sensors'] = [x.strip() for x in
self['reading']['sensors'].split(',') if x.strip() != '']
......@@ -145,31 +188,20 @@ class Config:
"SENSORS key.")
if 'true' in self['reading']['rtc_ds1307'].lower():
self['reading']['sensors'].append(RTCDateTime.SENSOR_NAME)
self['reading']['sensors'].append(self.RTC_NAME)
self['reading']['command'] = 'readSensors,' + ','.join(
self['reading']['command'] = 'read,' + ','.join(
self['reading']['sensors'])
def validate_reading_interval(self):
try:
numbers = self['reading']['interval'].split(':')
if len(numbers) != 3: raise Exception
self['reading']['interval'] = {k: int(v) for k, v in
zip(['H', 'M', 'S'], numbers)}
self['reading']['interval_seconds'] =\
3600 * self['reading']['interval']['H'] + \
60 * self['reading']['interval']['M'] + \
self['reading']['interval']['S']
self['reading']['sleep_minutes'] =\
float(self['reading']['sleep_minutes'].replace(',', '.'))
except:
raise Exception(
"Invalid time value for the reading/INTERVAL key.\n"
"Expected format:\n"
" hours:minutes:seconds (integer numbers)\n"
"Was given:\n {}".format(self['reading']['interval']))
raise self.ConfigValueError('reading', 'SLEEP_MINUTES',
'TypeError: Number expected!', self)
def validate_datalog_csv_sep(self):
def validate_datalog(self):
value = self['datalog']['csv_sep']
self['datalog']['csv_sep'] = bytes(value, 'utf8').decode(
'unicode_escape')
......@@ -179,7 +211,7 @@ class Config:
"Supported values:\n ',' ';' '\\t'\n"
"Was given:\n {}".format(value))
def validate_arduino_serial_port(self):
def validate_arduino(self):
self['arduino']['serial_port'] = [x.strip() for x in
self['arduino']['serial_port'].split(',') if x.strip() != '']
......
......@@ -5,7 +5,7 @@
#-------------------------------------------------------------------------------
from __future__ import print_function, division
from .config import Config, RTCDateTime
from .config import Config
from datetime import datetime
from pprint import pprint
......@@ -37,32 +37,31 @@ class Meteorologger:
BOARD_RESET_TIMEOUT = 2 # seconds
BOARD_RESPONSE_DELAY = 3 # seconds
def __init__(self, verbose=False):
self.verbose = verbose
config = None
def __init__(self, background=False):
self.background = background
self.config = Config()
def _decode_bytes(self, raw_bytes, encoding='ascii'):
result = None
try:
result = raw_bytes.decode(encoding).strip()
except:
if self.verbose:
print("Invalid bytes!")
return result
return raw_bytes.decode(encoding).strip()
except Exception as e:
logging.error(" ASCIIDecodeError : {}".format(e))
return None
def setup_logging(self):
'''
Prepares the execution log file mechanism, which uses the standard
library logging. This way de app is prepared for background execution.
'''
logging.basicConfig(
level=logging.INFO,
filename=self.SESSION_EXECUTION_LOG_FILENAME,
format='%(asctime)s : %(levelname)s : %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
if self.verbose:
if not self.background:
root = logging.getLogger('')
root.setLevel(logging.INFO)
console = logging.StreamHandler()
......@@ -78,10 +77,10 @@ class Meteorologger:
'''
session_datetime = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
self.SESSION_DATALOG_FILENAME = self.config.DATALOG_PATH \
+ 'datalog-' + session_datetime + '.csv'
self.SESSION_EXECUTION_LOG_FILENAME = self.config.EXECUTION_LOG_PATH \
+ 'exec-' + session_datetime + '.log'
self.SESSION_DATALOG_FILENAME = os.path.join(self.config.DATALOG_PATH,
'datalog-' + session_datetime + '.csv')
self.SESSION_EXECUTION_LOG_FILENAME = os.path.join(
self.config.EXECUTION_LOG_PATH, 'exec-' + session_datetime + '.log')
try:
with open(self.SESSION_DATALOG_FILENAME, 'w') as f:
......@@ -89,17 +88,12 @@ class Meteorologger:
f.write(self.config['datalog']['csv_sep'].join(
['dt' + self.config['datalog']['datetime_format']] +
[x for x in self.config['reading']['sensors']
if x != RTCDateTime.SENSOR_NAME]) + '\n')
if x != self.config.RTC_NAME]) + '\n')
except Exception as e:
logging.info("Unable to write at\n {}".format(
self.SESSION_DATALOG_FILENAME))
raise e
def sync_rtc(self):
'''
TO BE IMPLEMENTED
'''
pass
def get_serial(self, verbose=True):
''' Keep trying to get a serial connection on any port listed on the
......@@ -121,7 +115,7 @@ class Meteorologger:
return ser
except Exception as e:
if verbose:
logging.info("SerialError: {}".format(e))
logging.error("{}".format(e))
if i < len(self.config['arduino']['serial_port']) - 1:
i += 1
......@@ -159,8 +153,6 @@ class Meteorologger:
finally:
if ser:
ser.close()
return None
def create_json(self, readline):
'''
......@@ -172,15 +164,17 @@ class Meteorologger:
for name, value in zip(self.config['reading']['sensors'],
readline.split(self.config.SERIAL_CSV_SEP)):
if name == RTCDateTime.SENSOR_NAME:
if name == self.config.RTC_NAME:
try:
d['datetime'].update(
source = RTCDateTime.SENSOR_NAME,
value = datetime.strptime(v, RTCDateTime.READ_TIMESTAMP)
source = self.config.RTC_NAME,
value = datetime.strptime(value, self.config.RTC_FORMAT)
.strftime(d['datetime']['format']))
except:
logging.warning("DateTimeError: [{}]: '{}'"
.format(name, value))
except Exception as e: