diff --git a/.github/workflows/build_documentation.yaml b/.github/workflows/build_documentation.yaml index 5c1c16067..87b7be34b 100644 --- a/.github/workflows/build_documentation.yaml +++ b/.github/workflows/build_documentation.yaml @@ -39,11 +39,11 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - # Using anwer from here to get the exit code and pass the output: https://stackoverflow.com/questions/59191913/how-do-i-get-the-output-of-a-specific-step-in-github-actions + # Using answer from here to get the exit code and pass the output: https://stackoverflow.com/questions/59191913/how-do-i-get-the-output-of-a-specific-step-in-github-actions - name: check for classes in the menu example id: check_component continue-on-error: true @@ -89,12 +89,12 @@ jobs: path: code_docs/ModularSensors - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' - name: Restore Python Dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache_python with: path: ~/.cache/pip @@ -107,7 +107,7 @@ jobs: - name: Restore Doxygen, Graphviz, and TeX Live id: cache_doxygen - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | /usr/lib/x86_64-linux-gnu/texlive diff --git a/.github/workflows/build_examples.yaml b/.github/workflows/build_examples.yaml index 4c86d8be2..bfdc620ee 100644 --- a/.github/workflows/build_examples.yaml +++ b/.github/workflows/build_examples.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' cache: 'pip' @@ -34,7 +34,7 @@ jobs: python continuous_integration/generate_job_matrix.py - name: Store generated examples - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: generated_examples path: | @@ -83,7 +83,7 @@ jobs: run: | echo "Pull Request from the fork ${{ github.event.pull_request.head.repo.full_name }} at ${{ github.event.pull_request.head.ref }}" echo "LIBRARY_INSTALL_ZIP=https://github.com/${{ github.event.pull_request.head.repo.full_name }}/archive/${{ github.event.pull_request.head.ref }}.zip" >> $GITHUB_ENV - echo "LIBRARY_INSTALL_GIT=https://github.com${{ github.event.pull_request.head.repo.full_name }}.git#${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV + echo "LIBRARY_INSTALL_GIT=https://github.com/${{ github.event.pull_request.head.repo.full_name }}.git#${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV - name: store enviroment variables as output id: store_vars @@ -126,7 +126,7 @@ jobs: uses: arduino/setup-arduino-cli@v1.1.2 - name: Restore Arduino platforms and libraries - uses: actions/cache@v3 + uses: actions/cache@v4 id: cache_libraries with: path: | @@ -150,7 +150,7 @@ jobs: sh continuous_integration/install-test-version-arduino-cli.sh - name: Download the prepared examples - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: generated_examples path: | @@ -179,7 +179,7 @@ jobs: runs-on: ubuntu-latest needs: [generate_matrix, determine_library_source] env: - LIBRARY_INSTALL_GIT: ${{ needs.determine_library_source.outputs.library_install_zip }} + LIBRARY_INSTALL_GIT: ${{ needs.determine_library_source.outputs.library_install_git }} strategy: matrix: job_info: ${{ fromJSON(needs.generate_matrix.outputs.pio_job_matrix) }} @@ -188,7 +188,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' cache: 'pip' @@ -196,8 +196,8 @@ jobs: - name: Install python dependencies, including PlatformIO run: pip install -r continuous_integration/requirements.txt - - name: Restore PlatformIO and Arduino platforms and libraries - uses: actions/cache@v3 + - name: Restore PlatformIO platforms and libraries + uses: actions/cache@v4 id: cache_libraries with: path: | @@ -222,7 +222,7 @@ jobs: pio pkg install -g --library ${{ env.LIBRARY_INSTALL_GIT }} - name: Download the prepared examples - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: generated_examples path: | diff --git a/.github/workflows/changelog_reminder.yaml b/.github/workflows/changelog_reminder.yaml index c0af65bcb..90115a0cb 100644 --- a/.github/workflows/changelog_reminder.yaml +++ b/.github/workflows/changelog_reminder.yaml @@ -15,4 +15,4 @@ jobs: changelog_regex: '/CHANGELOG\/.*\/*.md' customPrMessage: 'Please add your changes to the change log!' env: - GITHUB_TOKEN: ${{ secrets.SARA_PUSH_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/prepare_release.yaml b/.github/workflows/prepare_release.yaml index ef54a2e54..299b2ebd9 100644 --- a/.github/workflows/prepare_release.yaml +++ b/.github/workflows/prepare_release.yaml @@ -30,7 +30,7 @@ jobs: echo "ZIP_NAME=$ZIP_FILE" >> $GITHUB_ENV - name: Set up python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.github/workflows/verify_library_structure.yaml b/.github/workflows/verify_library_structure.yaml index 753fd2bd7..2d8aad016 100644 --- a/.github/workflows/verify_library_structure.yaml +++ b/.github/workflows/verify_library_structure.yaml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.x' diff --git a/.gitignore b/.gitignore index f668ae57c..9c278f49b 100644 --- a/.gitignore +++ b/.gitignore @@ -109,3 +109,6 @@ continuous_integration_artifacts/* arduino_cli.log **/sensor_tests/* docs/Doxyfile.bak +continuous_integration/output_check_component_inclusion.log +continuous_integration/platformio_ci_local.ini +pioScripts/install_shared_deps.py diff --git a/ChangeLog.md b/ChangeLog.md index f59567474..54f53cbc7 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,11 +17,57 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed ### Fixed -- Fixed GitHub actions for pull requests from forks. *** +## [0.35.0] + +### Changed +- **BREAKING** Refactored how the publisher transmit buffer works. This will require adjustment to custom data publishers. +- Update GitHub actions +- Remove date from copyright for easier tracking +- Turn modem off at end of setup, regardless of time +- Clean function to set file timestamp on SD card +- Use equation rather than table for CSQ +- Only polling modem for enabled parameters +- INCREASED THE MAXIMUM NUMBER OF VARIABLES FROM A SINGLE SENSOR and implemented an option to set this by build flag. + - This will increase memory use for the entire library. +If you are not using the GroPoint sensors which require many variables, I recommend you change this value via the build flag `-D MAX_NUMBER_VARS=8` +- Allow all WiFi modems to first attempt to connect using existing on-modem saved credentials rather than immediately sending new credentials. +- Add further debug printouts to the processor stats + +### Added +- Support [GroPoint Profile GPLP-8 Eight-Segment Soil Moisture and Temperature Profiling Probe](https://www.gropoint.com/products/soil-sensors/gropoint-profile) +- Support [Vega Puls 21 Radar](https://www.vega.com/en-us/products/product-catalog/level/radar/vegapuls-21) +- Functions to enable and disable modem metadata polling by bitmask + +### Removed +- Removed the (unused) sendOffset parameter from dataPublisherBase. + +### Fixed +- Minor bug fixes for XBee Wifi +- Handle no SIM card response from SIM7080G (EnviroDIY LTE Bee) +- Fixed Keller debugging output. +- Fixed file reference for SDFat 2.2.3 + +### Known Issues +- The modem hardware, firmware, and serial number is only implemented for the Digi XBee WiFi. + +## [0.34.1] + +### Changed +- Incorporated improvements to the XBee Wifi - from [neilh10](https://github.com/EnviroDIY/ModularSensors/commits?author=neilh10) + - #347 -WiFi S6B stability - tears dwon TCP/IP before going to sleep, doesn't automatically poll for meta data + +### Added +- Added the ability to enable or disable polling of modem attached variables. +By default, all polling is off, but polling is enabled for a modem sensor when a sensor is created and attached to a modem. +This functionailty is inspired from [neilh10](https://github.com/EnviroDIY/ModularSensors/commits?author=neilh10). + +### Fixed +- Fixed GitHub actions for pull requests from forks. + ## [0.34.0] ### Changed diff --git a/LICENSE.md b/LICENSE.md index 4f77081af..5e24c3b2f 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ # Software License Agreement (BSD-3 License) -**Copyright (c) 2010-2017, Stroud Water Research Center (SWRC) and the EnviroDIY Development Team.** +**Copyright (c) 2010-2024, Stroud Water Research Center (SWRC) and the EnviroDIY Development Team.** All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index 798aa5b85..557731c0f 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,9 @@ For some generalized information about attaching sensors to an Arduino style boa - [Decagon Devices ES-2: conductivity ](https://envirodiy.github.io/ModularSensors/group__sensor__es2.html) - [Decagon Devices CTD-10: conductivity, temperature & depth ](https://envirodiy.github.io/ModularSensors/group__sensor__decagon__ctd.html) - [Everlight ALS-PT19 Analog Light Sensor (via processor ADC)](https://envirodiy.github.io/ModularSensors/group__sensor__alspt19.html) -- [Freescale Semiconductor MPL115A2: barometric pressure and temperature](https://envirodiy.github.io/ModularSensors/group__sensor__mpl115a2.html) - [External Arduino I2C Rain Tipping Bucket Counter: rainfall totals](https://envirodiy.github.io/ModularSensors/group__sensor__i2c__rain.html) +- [Freescale Semiconductor MPL115A2: barometric pressure and temperature](https://envirodiy.github.io/ModularSensors/group__sensor__mpl115a2.html) +- [GroPoint Profile GPLP-8 Eight-Segment Soil Moisture and Temperature Profiling Probe](https://envirodiy.github.io/ModularSensors/group__sensor__gplp8.html) - [In-Situ RDO PRO-X: dissolved oxygen](https://envirodiy.github.io/ModularSensors/group__sensor__insitu__rdo.html) - [In-Situ SDI-12 TROLLs: pressure, temperature, and depth](https://envirodiy.github.io/ModularSensors/group__sensor__insitu__troll.html) - [Keller Submersible Level Transmitters: pressure and temperature](https://envirodiy.github.io/ModularSensors/group__keller__group.html) @@ -82,6 +83,7 @@ For some generalized information about attaching sensors to an Arduino style boa - [TI ADS1115: external voltage with support for divided current](https://envirodiy.github.io/ModularSensors/group__sensor__ads1x15.html) - [TI INA219: current, voltage, and power draw](https://envirodiy.github.io/ModularSensors/group__sensor__ina219.html) - [Turner Cyclops-7F: various parameters](https://envirodiy.github.io/ModularSensors/group__sensor__cyclops.html) +- [Vega Puls 21: radar distance](https://envirodiy.github.io/ModularSensors/group__sensor__vega__puls21.html) - [Yosemitech: water quality sensors](https://envirodiy.github.io/ModularSensors/group__yosemitech__group.html) - [Y502-A or Y504-A: Optical DO and Temperature](https://envirodiy.github.io/ModularSensors/group__sensor__y504.html) - [Y510-B: Optical Turbidity and Temperature](https://envirodiy.github.io/ModularSensors/group__sensor__y510.html) diff --git a/VERSION b/VERSION index 85e60ed18..7b52f5e51 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.34.0 +0.35.0 diff --git a/continuous_integration/check_component_inclusion.py b/continuous_integration/check_component_inclusion.py index 9e8080cc9..485926cf5 100644 --- a/continuous_integration/check_component_inclusion.py +++ b/continuous_integration/check_component_inclusion.py @@ -65,7 +65,7 @@ def camel_to_snake(name, lower_case=True): #%% # make sure class names match file names -class_pattern = re.compile("^\s*class[\s\n]+(\w+)[\s\n]", re.MULTILINE) +class_pattern = re.compile(r"^\s*class[\s\n]+(\w+)[\s\n]", re.MULTILINE) for header_file in header_files: textfile = open(header_file, mode="r", encoding="utf-8") diff --git a/continuous_integration/dependencies.json b/continuous_integration/dependencies.json index fc36ee07e..874230ccb 100644 --- a/continuous_integration/dependencies.json +++ b/continuous_integration/dependencies.json @@ -1,5 +1,5 @@ { - "action_cache_version": 16, + "action_cache_version": 18, "dependencies": [ { "name": "EnviroDIY_DS3231", @@ -8,10 +8,7 @@ "url": "https://github.com/EnviroDIY/Sodaq_DS3231", "version": "~1.3.4", "note": "An Arduino library for the DS3231 RTC (Real Time Clock), based off of the Sodaq_DS3231 library.", - "authors": [ - "Kees Bakker", - "Sara Damiano" - ], + "authors": ["Kees Bakker", "Sara Damiano"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -22,9 +19,7 @@ "url": "https://github.com/arduino-libraries/RTCZero", "version": "~1.6.0", "note": "Functions for using the processor real time clock in SAMD21 processors", - "authors": [ - "Arduino" - ], + "authors": ["Arduino"], "frameworks": "arduino", "platforms": "atmelsam" }, @@ -35,9 +30,7 @@ "url": "https://github.com/GreyGnome/EnableInterrupt", "version": "~1.1.0", "note": "GreyGnome's EnableInterrupt - Assign an interrupt to any supported pin on all Arduinos", - "authors": [ - "Mike 'GreyGnome' Schwager" - ], + "authors": ["Mike 'GreyGnome' Schwager"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -46,23 +39,18 @@ "owner": "greiman", "library id": "322", "url": "https://github.com/greiman/SdFat", - "version": "~2.1.2", + "version": "~2.2.3", "note": "SdFat - FAT16/FAT32 file system for SD cards.", - "authors": [ - "Bill Greiman" - ], + "authors": ["Bill Greiman"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, { "name": "TinyGSM", "owner": "vshymanskyy", - "version": "~0.11.5", + "version": "~0.11.7", "note": "A small Arduino library for GPRS modules.", - "authors": [ - "Volodymyr Shymanskyy", - "Sara Damiano" - ], + "authors": ["Volodymyr Shymanskyy", "Sara Damiano"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -73,20 +61,16 @@ "url": "https://github.com/knolleary/pubsubclient", "version": "~2.8", "note": "A client library for MQTT messaging.", - "authors": [ - "Nick O'Leary" - ] + "authors": ["Nick O'Leary"] }, { "name": "Adafruit BusIO", "owner": "adafruit", "library id": "6214", "url": "https://github.com/adafruit/Adafruit_BusIO", - "version": "~1.11.6", + "version": "~1.16.0", "note": "Adafruit BusIO, a dependency of other Adafruit libraries", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -95,11 +79,9 @@ "owner": "adafruit", "library id": "31", "url": "https://github.com/adafruit/Adafruit_Sensor", - "version": "~1.1.9", + "version": "~1.1.14", "note": "Adafruit's unified sensor library is used by their other libraries", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -109,9 +91,7 @@ "version_note": "=1.2.0", "version": "https://github.com/soligen2010/Adafruit_ADS1X15.git#7d67b451f739e9a63f40f2d6d139ab582258572b", "note": "Driver for TI's ADS1015: 12-bit Differential or Single-Ended ADC with PGA and Comparator. This fork removes bugs in the Adafruit original library.", - "authors_note": [ - "soligen2010" - ], + "authors_note": ["soligen2010"], "frameworks_note": "arduino", "platforms_note": "*" }, @@ -122,9 +102,7 @@ "url": "https://github.com/adafruit/Adafruit_AM2315", "version": "~2.2.3", "note": "AOSong AM2315 I2C Temp/Humidity Sensor Library by Adafruit", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -133,11 +111,9 @@ "owner": "adafruit", "library id": "166", "url": "https://github.com/adafruit/Adafruit_BME280_Library", - "version": "~2.2.2", + "version": "~2.2.4", "note": "Bosch BME280 Temp/Humidity/Pressure Sensor Library by Adafruit", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -146,9 +122,7 @@ "owner": "MartinL1", "version": "~1.0.11", "note": "An Arduino compatible, non-blocking, I2C/SPI library for the Bosch BMP388 barometer.", - "authors": [ - "Martin Lindupp" - ], + "authors": ["Martin Lindupp"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -157,11 +131,9 @@ "owner": "adafruit", "library id": "19", "url": "https://github.com/adafruit/DHT-sensor-library", - "version": "~1.4.4", + "version": "~1.4.6", "note": "AOSong DHT Sensor Library by Adafruit", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -170,11 +142,9 @@ "owner": "adafruit", "library id": "160", "url": "https://github.com/adafruit/Adafruit_INA219", - "version": "~1.2.1", + "version": "~1.2.3", "note": "This is a library for the Adafruit INA219 high side DC current sensor boards", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -185,9 +155,7 @@ "url": "https://github.com/adafruit/Adafruit_MPL115A2", "version": "~2.0.2", "note": "MPL115A2 Barometer Library by Adafruit", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino" }, { @@ -195,11 +163,9 @@ "owner": "adafruit", "library id": "11710", "url": "https://github.com/adafruit/Adafruit_SHT4X", - "version": "~1.0.2", + "version": "~1.0.4", "note": "Sensirion SHT4x Library by Adafruit", - "authors": [ - "Adafruit" - ], + "authors": ["Adafruit"], "frameworks": "arduino" }, { @@ -207,7 +173,7 @@ "owner": "paulstoffregen", "library id": "1", "url": "https://github.com/PaulStoffregen/OneWire", - "version": "~2.3.7", + "version": "~2.3.8", "note": "OneWire - Control 1-Wire protocol (DS18S20, DS18B20, DS2408 and etc)", "authors": [ "Paul Stoffregen", @@ -231,14 +197,9 @@ "owner": "milesburton", "library id": "54", "url": "https://github.com/milesburton/Arduino-Temperature-Control-Library", - "version": "~3.9.1", + "version": "~3.11.0", "note": "DallasTemperature - Arduino Library for Dallas Temperature ICs (DS18B20, DS18S20, DS1822, DS1820)", - "authors": [ - "Guil Barros", - "Miles Burton", - "Rob Tillart", - "Tim Nuewsome" - ], + "authors": ["Guil Barros", "Miles Burton", "Rob Tillart", "Tim Nuewsome"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -265,22 +226,14 @@ "url": "https://github.com/NorthernWidget/MS5803", "version": "~0.1.2", "note": "General interface to MS5803-series pressure transducers", - "authors": [ - "Bobby Schulz", - "Andrew Wickert", - "Chad Sandell", - "Sara Damiano" - ] + "authors": ["Bobby Schulz", "Andrew Wickert", "Chad Sandell", "Sara Damiano"] }, { "name": "Tally_Library_I2C", "version": "https://github.com/EnviroDIY/Tally_Library.git#Dev_I2C", "version_note": "Uses `Dev_I2C` feature branch", "note": "An Arduino library for interfacing to the Project Tally Event counter from NorthernWidget.", - "authors": [ - "Bobby Schulz", - "Anthony Aufdenkampe" - ], + "authors": ["Bobby Schulz", "Anthony Aufdenkampe"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -291,9 +244,7 @@ "url": "https://github.com/EnviroDIY/SensorModbusMaster", "version": "~0.6.8", "note": "EnviroDIY SensorModbusMaster - Arduino library for communicating via modbus with the Arduino acting as the modbus master.", - "authors": [ - "Sara Damiano" - ], + "authors": ["Sara Damiano"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" }, @@ -304,23 +255,28 @@ "url": "https://github.com/EnviroDIY/KellerModbus", "version": "~0.2.2", "note": "Arduino library for communication with Keller pressure and water level sensors via Modbus.", - "authors": [ - "Anthony Aufdenkampe" - ] + "authors": ["Anthony Aufdenkampe"] }, { "name": "YosemitechModbus", "owner": "envirodiy", "library id": "2078", "url": "https://github.com/EnviroDIY/YosemitechModbus", - "version": "~0.4.0", + "version": "~0.4.1", "note": "Arduino library for communication with Yosemitech sensors via Modbus.", - "authors": [ - "Sara Damiano", - "Anthony Aufdenkampe" - ], + "authors": ["Sara Damiano", "Anthony Aufdenkampe"], + "frameworks": "arduino", + "platforms": "atmelavr, atmelsam" + }, + { + "name": "GroPointModbus", + "owner": "envirodiy", + "url": "https://github.com/EnviroDIY/GroPointModbus.git", + "version": "~0.1.0", + "note": "A library to use an Arduino as a master to control and communicate via modbus with GroPoint soil moisture sensors. ", + "authors": ["Anthony Aufdenkampe"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" } ] -} \ No newline at end of file +} diff --git a/continuous_integration/generate_job_matrix.py b/continuous_integration/generate_job_matrix.py index 3c05f66a4..495ee97ff 100644 --- a/continuous_integration/generate_job_matrix.py +++ b/continuous_integration/generate_job_matrix.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -#%% +# %% import json import shutil import re @@ -9,7 +9,7 @@ import os import copy -#%% +# %% # Some working directories # The workspace directory if "GITHUB_WORKSPACE" in os.environ.keys(): @@ -37,7 +37,7 @@ os.makedirs(artifact_dir) compilers = ["Arduino CLI", "PlatformIO"] -#%% +# %% # The locations of some important files # The massive "menu" example @@ -72,6 +72,8 @@ "megaatmega2560": {"fqbn": "arduino:avr:mega"}, "zeroUSB": {"fqbn": "arduino:samd:mzero_bl"}, "adafruit_feather_m0": {"fqbn": "adafruit:samd:adafruit_feather_m0"}, + "adafruit_feather_m4": {"fqbn": "adafruit:samd:adafruit_feather_m4"}, + "adafruit_grandcentral_m4": {"fqbn": "adafruit:samd:adafruit_grandcentral_m4"}, } @@ -110,8 +112,6 @@ def create_pio_ci_command(pio_env_file: str, pio_env: str, code_subfolder: str) # "--verbose", "--project-conf", pio_env_file, - "--project-conf", - pio_env_file, "--environment", pio_env, os.path.join(examples_path, code_subfolder), @@ -183,14 +183,14 @@ def snake_to_camel(snake_str): return camel_str -#%% +# %% # set up outputs arduino_job_matrix = [] pio_job_matrix = [] start_job_commands = "status=0" end_job_commands = "\n\nexit $status" -#%% +# %% # Create job info for the basic examples # Use one job per board with one command per example for pio_env in pio_config.envs(): @@ -234,7 +234,7 @@ def snake_to_camel(snake_str): ) -#%% +# %% # Helper functions for preparing the menu-a-la-carte example for building def modify_example_filename(example_subfolder, in_file_defines): @@ -309,10 +309,10 @@ def extend_pio_config(added_envs): return new_config_path -#%% read build flags out of the menu-a-la-cart example +# %% read build flags out of the menu-a-la-cart example # Pattern for flags in the menu-a-la-cart example pattern = re.compile( - "^(?:#if|#elif) defined[\s\(](?PBUILD_\w+)((?:[\s\n\\\)]*?\|\|[\s\n\\]*defined[\s\n\\\(]*?)(?PBUILD_\w+))*", + r"^(?:#if|#elif) defined[\s\(](?PBUILD_\w+)((?:[\s\n\\\)]*?\|\|[\s\n\\]*defined[\s\n\\\(]*?)(?PBUILD_\w+))*", re.MULTILINE, ) @@ -350,7 +350,7 @@ def extend_pio_config(added_envs): all_publisher_flags.append(match.group("flag1")) -#%% +# %% # Create jobs for all of the modems together for pio_env in pio_config.envs(): arduino_modem_commands = [ @@ -396,7 +396,7 @@ def extend_pio_config(added_envs): } ) -#%% +# %% # Create jobs for all of the publishers together for pio_env in pio_config.envs(): arduino_pub_commands = [ @@ -442,7 +442,7 @@ def extend_pio_config(added_envs): } ) -#%% +# %% # Create jobs for all of the sensors together # The sensors are a bit different because we run extra PlatformIO enviroments for some of the sensors for pio_env in pio_config.envs(): @@ -540,7 +540,7 @@ def extend_pio_config(added_envs): } ) -#%% +# %% # Tack on a few extra build configurations for the menu example for pio_env in pio_config.envs(): arduino_loop_commands = [ @@ -596,7 +596,7 @@ def extend_pio_config(added_envs): } ) -#%% +# %% # Tack on a few more extra build configurations for the software serial libraries for pio_env in ["Mayfly"]: arduino_serial_commands = [ @@ -654,7 +654,7 @@ def extend_pio_config(added_envs): ) -#%% +# %% # Convert commands in the matrix into bash scripts for matrix_job in arduino_job_matrix + pio_job_matrix: bash_file_name = matrix_job["job_name"].replace(" ", "") + ".sh" @@ -676,7 +676,7 @@ def extend_pio_config(added_envs): del items["command"] -#%% +# %% # Write out output print( 'echo "arduino_job_matrix={}" >> $GITHUB_OUTPUT'.format( @@ -694,14 +694,14 @@ def extend_pio_config(added_envs): json_out.close() -#%% +# %% # different attempt to save output with open(os.environ["GITHUB_OUTPUT"], "a") as fh: print("arduino_job_matrix={}".format(json.dumps(arduino_job_matrix)), file=fh) print("pio_job_matrix={}".format(json.dumps(pio_job_matrix)), file=fh) -#%% +# %% if "GITHUB_WORKSPACE" not in os.environ.keys(): try: shutil.rmtree(artifact_dir) diff --git a/continuous_integration/install-deps-arduino-cli.sh b/continuous_integration/install-deps-arduino-cli.sh index 1fb6d4667..61ba26a4b 100644 --- a/continuous_integration/install-deps-arduino-cli.sh +++ b/continuous_integration/install-deps-arduino-cli.sh @@ -91,14 +91,8 @@ arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install "A echo "\n\e[32mInstalling Adafruit SHT4x Library from Arduino library index\e[0m" arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install "Adafruit SHT4x Library" -echo "\n\e[32mDownloading Martin Lindupp's BMP388 Library as a zip" -# Soligen fork needs to be manually unzipped and moved because the CLI chokes on the library name not matching the h file -curl -L --retry 15 --retry-delay 0 https://github.com/MartinL1/BMP388_DEV/archive/master.zip --create-dirs -o home/arduino/downloads/BMP388_DEV.zip -echo "\e[32mDecompressing BMP388_DEV\e[0m" -unzip -q -o home/arduino/downloads/BMP388_DEV.zip -d home/arduino/downloads/ -echo "\e[32mMoving BMP388_DEV to the libraries folder\e[0m" -mkdir -p home/arduino/user/libraries/BMP388_DEV -mv home/arduino/downloads/BMP388_DEV-master/* home/arduino/user/libraries/BMP388_DEV +echo "\n\e[32mInstalling Martin Lindupp's BMP388 Library from Arduino library index\e[0m" +arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install "BMP388_DEV" echo "\n\e[32mInstalling OneWire library from Arduino library index\e[0m" arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install OneWire @@ -132,6 +126,9 @@ arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install Ke echo "\n\e[32mInstalling EnviroDIY YosemitechModbus library from Arduino library index\e[0m" arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install YosemitechModbus +echo "\n\e[32mInstalling EnviroDIY GropointModbus library from Arduino library index\e[0m" +arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install GropointModbus + echo "\n\e[32mInstalling StreamDebugger library from Arduino library index\e[0m" arduino-cli --config-file continuous_integration/arduino_cli.yaml lib install StreamDebugger diff --git a/continuous_integration/install-deps-platformio.sh b/continuous_integration/install-deps-platformio.sh index 7866985ad..22219218e 100644 --- a/continuous_integration/install-deps-platformio.sh +++ b/continuous_integration/install-deps-platformio.sh @@ -81,7 +81,7 @@ echo "\e[32mInstalling adafruit/'Adafruit SHT'\e[0m" pio pkg install -g --library adafruit/'Adafruit SHT4x Library' echo "\e[32mInstalling Martin Lindupp's BMP388 Library\e[0m" -pio pkg install -g --library https://github.com/MartinL1/BMP388_DEV.git +pio pkg install -g --library MartinL1/BMP388_DEV echo "\e[32mInstalling paulstoffregen/OneWire\e[0m" pio pkg install -g --library paulstoffregen/OneWire @@ -107,6 +107,9 @@ pio pkg install -g --library envirodiy/KellerModbus echo "\e[32mInstalling envirodiy/YosemitechModbus\e[0m" pio pkg install -g --library envirodiy/YosemitechModbus +echo "\e[32mInstalling envirodiy/GroPointModbus\e[0m" +pio pkg install -g --library envirodiy/GroPointModbus + echo "\e[32mInstalling vshymanskyy/StreamDebugger\e[0m" pio pkg install -g --library vshymanskyy/StreamDebugger diff --git a/continuous_integration/platformio.ini b/continuous_integration/platformio.ini index ee9ea3d7a..263173d30 100644 --- a/continuous_integration/platformio.ini +++ b/continuous_integration/platformio.ini @@ -6,20 +6,13 @@ ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples -; http://docs.platformio.org/page/projectconf.html -; -; src_dir = sensor_tests/XBee_Command -; src_dir = examples/logger_test/ -; build_flags = -E -dD -; +; https://docs.platformio.org/page/projectconf.html [platformio] [env] framework = arduino lib_ldf_mode = deep+ -build_flags = - -D SDI12_EXTERNAL_PCINT lib_ignore = Adafruit NeoPixel Adafruit GFX Library @@ -28,6 +21,10 @@ lib_ignore = Adafruit STMPE610 Adafruit TouchScreen Adafruit ILI9341 +build_flags = + -Wextra + -D SDI12_EXTERNAL_PCINT + -D NEOSWSERIAL_EXTERNAL_PCINT [env:Mayfly] board = mayfly @@ -49,8 +46,7 @@ lib_ignore = build_flags = ${env.build_flags} - -[env:ArduinoZero] +[env:Zero] platform = atmelsam board = zeroUSB lib_ignore = @@ -62,8 +58,7 @@ lib_ignore = build_flags = ${env.build_flags} - -[env:AdafruitFeatherM0] +[env:FeatherM0] platform = atmelsam board = adafruit_feather_m0 lib_ignore = @@ -75,3 +70,33 @@ lib_ignore = build_flags = ${env.build_flags} build_unflags = -D USE_TINYUSB + +; [env:FeatherM4] +; platform = atmelsam +; board = adafruit_feather_m4 +; lib_ignore = +; ${env.lib_ignore} +; RTCZero +; SoftwareSerial_ExtInts +; AltSoftSerial +; NeoSWSerial +; SoftwareWire +; build_flags = +; ${env.build_flags} +; -D MS_SAMD_DS3231 +; build_unflags = -D USE_TINYUSB + +; [env:GrandCentralM4] +; platform = atmelsam +; board = adafruit_grandcentral_m4 +; lib_ignore = +; ${env.lib_ignore} +; RTCZero +; SoftwareSerial_ExtInts +; AltSoftSerial +; NeoSWSerial +; SoftwareWire +; build_flags = +; ${env.build_flags} +; -D MS_SAMD_DS3231 +; build_unflags = -D USE_TINYUSB diff --git a/docs/Doxyfile b/docs/Doxyfile index db06a11c2..840f599d3 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ModularSensors # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.34.0 +PROJECT_NUMBER = 0.35.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/docs/FAQ/Developer-Setup.md b/docs/FAQ/Developer-Setup.md index 152ce82f2..19db0b93c 100644 --- a/docs/FAQ/Developer-Setup.md +++ b/docs/FAQ/Developer-Setup.md @@ -78,7 +78,7 @@ lib_deps = adafruit/Adafruit INA219 adafruit/Adafruit MPL115A2 adafruit/Adafruit SHT4x Library - https://github.com/MartinL1/BMP388_DEV + MartinL1/BMP388_DEV paulstoffregen/OneWire milesburton/DallasTemperature envirodiy/SDI-12 diff --git a/docs/copyFunctions.py b/docs/copyFunctions.py index 802179121..3e0c64f56 100644 --- a/docs/copyFunctions.py +++ b/docs/copyFunctions.py @@ -68,13 +68,13 @@ def get_section_to_paste(match: re.Match) -> str: i += 1 new_line = line match = re.search( - '\{\{ - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -33,10 +32,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/DRWI_DigiLTE/DRWI_DigiLTE.ino b/examples/DRWI_DigiLTE/DRWI_DigiLTE.ino index 4f23db6e2..c051cf25f 100644 --- a/examples/DRWI_DigiLTE/DRWI_DigiLTE.ino +++ b/examples/DRWI_DigiLTE/DRWI_DigiLTE.ino @@ -3,11 +3,10 @@ * @brief Example for DRWI CitSci LTE sites. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -33,10 +32,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/DRWI_Mayfly1/DRWI_Mayfly1.ino b/examples/DRWI_Mayfly1/DRWI_Mayfly1.ino index 9df2638da..469752715 100644 --- a/examples/DRWI_Mayfly1/DRWI_Mayfly1.ino +++ b/examples/DRWI_Mayfly1/DRWI_Mayfly1.ino @@ -9,9 +9,8 @@ * Hydros21 CTD sensor * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger @@ -39,10 +38,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/DRWI_Mayfly1_WiFi/DRWI_Mayfly1_WiFi.ino b/examples/DRWI_Mayfly1_WiFi/DRWI_Mayfly1_WiFi.ino index 90742932d..5ca4cb510 100644 --- a/examples/DRWI_Mayfly1_WiFi/DRWI_Mayfly1_WiFi.ino +++ b/examples/DRWI_Mayfly1_WiFi/DRWI_Mayfly1_WiFi.ino @@ -9,9 +9,8 @@ * Hydros21 CTD sensor * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger @@ -39,10 +38,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/DRWI_NoCellular/DRWI_NoCellular.ino b/examples/DRWI_NoCellular/DRWI_NoCellular.ino index cc40aab26..e5928cedb 100644 --- a/examples/DRWI_NoCellular/DRWI_NoCellular.ino +++ b/examples/DRWI_NoCellular/DRWI_NoCellular.ino @@ -3,11 +3,10 @@ * @brief Example for DRWI CitSci without cellular service. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -21,10 +20,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/DRWI_SIM7080LTE/DRWI_SIM7080LTE.ino b/examples/DRWI_SIM7080LTE/DRWI_SIM7080LTE.ino index 440671d9f..3b08000e3 100644 --- a/examples/DRWI_SIM7080LTE/DRWI_SIM7080LTE.ino +++ b/examples/DRWI_SIM7080LTE/DRWI_SIM7080LTE.ino @@ -10,9 +10,8 @@ * Campbell Scientific OBS3+ Turbidity sensor * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger @@ -40,10 +39,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/baro_rho_correction/baro_rho_correction.ino b/examples/baro_rho_correction/baro_rho_correction.ino index 01a10cf6f..929f08184 100644 --- a/examples/baro_rho_correction/baro_rho_correction.ino +++ b/examples/baro_rho_correction/baro_rho_correction.ino @@ -3,11 +3,10 @@ * @brief Example demonstrating calculated variables. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -35,10 +34,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/data_saving/data_saving.ino b/examples/data_saving/data_saving.ino index 0283b7409..ce4e179ac 100644 --- a/examples/data_saving/data_saving.ino +++ b/examples/data_saving/data_saving.ino @@ -3,11 +3,10 @@ * @brief Example publishing only a portion of the logged variables. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -34,10 +33,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/double_logger/double_logger.ino b/examples/double_logger/double_logger.ino index a560601de..85f7f2f63 100644 --- a/examples/double_logger/double_logger.ino +++ b/examples/double_logger/double_logger.ino @@ -3,11 +3,10 @@ * @brief Example logging at two different timing intervals * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -33,10 +32,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/logging_to_MMW/logging_to_MMW.ino b/examples/logging_to_MMW/logging_to_MMW.ino index c590dabec..d48d98046 100644 --- a/examples/logging_to_MMW/logging_to_MMW.ino +++ b/examples/logging_to_MMW/logging_to_MMW.ino @@ -3,11 +3,10 @@ * @brief Example logging data and publishing to Monitor My Watershed. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -33,10 +32,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/logging_to_ThingSpeak/logging_to_ThingSpeak.ino b/examples/logging_to_ThingSpeak/logging_to_ThingSpeak.ino index 9e584a7ea..7a0044662 100644 --- a/examples/logging_to_ThingSpeak/logging_to_ThingSpeak.ino +++ b/examples/logging_to_ThingSpeak/logging_to_ThingSpeak.ino @@ -3,11 +3,10 @@ * @brief Example logging data and publishing to ThingSpeak. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -36,10 +35,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/menu_a_la_carte/ReadMe.md b/examples/menu_a_la_carte/ReadMe.md index 34fb35438..a67c77ae7 100644 --- a/examples/menu_a_la_carte/ReadMe.md +++ b/examples/menu_a_la_carte/ReadMe.md @@ -77,6 +77,7 @@ ___ - [Everlight ALS-PT19 Ambient Light Sensor ](#everlight-als-pt19-ambient-light-sensor-) - [External Voltage via TI ADS1x15 ](#external-voltage-via-ti-ads1x15-) - [Freescale Semiconductor MPL115A2 Miniature I2C Digital Barometer ](#freescale-semiconductor-mpl115a2-miniature-i2c-digital-barometer-) + - [GroPoint Profile GPLP-8 Eight-Segment Soil Moisture and Temperature Profiling Probe ](#gropoint-profile-gplp-8-eight-segment-soil-moisture-and-temperature-profiling-probe-) - [In-Situ Aqua/Level TROLL Pressure, Temperature, and Depth Sensor ](#in-situ-aqualevel-troll-pressure-temperature-and-depth-sensor-) - [In-Situ RDO PRO-X Rugged Dissolved Oxygen Probe ](#in-situ-rdo-pro-x-rugged-dissolved-oxygen-probe-) - [Keller RS485/Modbus Water Level Sensors ](#keller-rs485modbus-water-level-sensors-) @@ -96,6 +97,7 @@ ___ - [TI INA219 High Side Current Sensor ](#ti-ina219-high-side-current-sensor-) - [Turner Cyclops-7F Submersible Fluorometer ](#turner-cyclops-7f-submersible-fluorometer-) - [Analog Electrical Conductivity using the Processor's Analog Pins ](#analog-electrical-conductivity-using-the-processors-analog-pins-) + - [VEGA VEGA PULS 21 ](#vega-vega-puls-21-) - [Yosemitech RS485/Modbus Environmental Sensors ](#yosemitech-rs485modbus-environmental-sensors-) - [Yosemitech Y504 Dissolved Oxygen Sensor ](#yosemitech-y504-dissolved-oxygen-sensor-) - [Yosemitech Y510 Turbidity Sensor ](#yosemitech-y510-turbidity-sensor-) @@ -832,6 +834,15 @@ Because this sensor can have only one I2C address (0x60), it is only possible to ___ +### GroPoint Profile GPLP-8 Eight-Segment Soil Moisture and Temperature Profiling Probe + +@see @ref sensor_gplp8 + +[//]: # ( @menusnip{gro_point_gplp8} ) + +___ + + #### In-Situ Aqua/Level TROLL Pressure, Temperature, and Depth Sensor @see @ref sensor_insitu_troll @@ -1076,6 +1087,15 @@ For best results, you should also connect the AREF pin of your processors ADC to ___ +#### VEGA VEGA PULS 21 + +@see @ref sensor_vega_puls21 + +[//]: # ( @menusnip{vega_puls21} ) + +___ + + ### Yosemitech RS485/Modbus Environmental Sensors The next several sections are for Yosemitech brand sensors. diff --git a/examples/menu_a_la_carte/menu_a_la_carte.ino b/examples/menu_a_la_carte/menu_a_la_carte.ino index eaa75eda7..89ceb7e85 100644 --- a/examples/menu_a_la_carte/menu_a_la_carte.ino +++ b/examples/menu_a_la_carte/menu_a_la_carte.ino @@ -3,11 +3,10 @@ * @brief Example with all possible functionality. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -37,10 +36,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ @@ -267,7 +262,7 @@ const int8_t greenLED = 8; // Pin for the green LED const int8_t redLED = 9; // Pin for the red LED const int8_t buttonPin = 21; // Pin for debugging mode (ie, button pin) const int8_t wakePin = 31; // MCU interrupt/alarm pin to wake from sleep -// Mayfly 0.x D31 = A7 +// Mayfly 0.x, 1.x D31 = A7 // Set the wake pin to -1 if you do not want the main processor to sleep. // In a SAMD system where you are using the built-in rtc, set wakePin to 1 const int8_t sdCardPwrPin = -1; // MCU SD card power pin @@ -433,8 +428,7 @@ DigiXBeeWifi modem = modemXBWF; // ========================================================================== -#elif defined BUILD_MODEM_ESPRESSIF_ESP8266 || \ - defined BUILD_MODEM_ESPRESSIF_ESP32 +#elif defined BUILD_MODEM_ESPRESSIF_ESP8266 /** Start [espressif_esp8266] */ // For almost anything based on the Espressif ESP8266 using the // AT command firmware @@ -469,6 +463,41 @@ EspressifESP8266 modem = modemESP; // ========================================================================== +#elif defined BUILD_MODEM_ESPRESSIF_ESP32 +/** Start [espressif_esp32] */ +// For almost anything based on the Espressif ESP8266 using the +// AT command firmware +#include + +// NOTE: Extra hardware and software serial ports are created in the "Settings +// for Additional Serial Ports" section +const int32_t modemBaud = 57600; // Communication speed of the modem +// NOTE: This baud rate too fast for an 8MHz board, like the Mayfly! The +// module should be programmed to a slower baud rate or set to auto-baud using +// the AT+UART_CUR or AT+UART_DEF command. + +// Modem Pins - Describe the physical pin connection of your modem to your board +// NOTE: Use -1 for pins that do not apply +// Example pins here are for a EnviroDIY ESP32 Bluetooth/Wifi Bee with +// Mayfly 1.1 +const int8_t modemVccPin = 18; // MCU pin controlling modem power +const int8_t modemResetPin = -1; // MCU pin connected to modem reset pin +const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem + // status + +// Network connection information +const char* wifiId = "xxxxx"; // WiFi access point name +const char* wifiPwd = "xxxxx"; // WiFi password (WPA2) + +// Create the modem object +EspressifESP32 modemESP(&modemSerial, modemVccPin, modemResetPin, wifiId, + wifiPwd); +// Create an extra reference to the modem by a generic name +EspressifESP32 modem = modemESP; +/** End [espressif_esp32] */ +// ========================================================================== + + #elif defined BUILD_MODEM_QUECTEL_BG96 /** Start [quectel_bg96] */ // For the Dragino, Nimbelink or other boards based on the Quectel BG96 @@ -1363,6 +1392,78 @@ Variable* mplTemp = new FreescaleMPL115A2_Temp( /** End [freescale_mpl115a2] */ #endif +#if defined BUILD_SENSOR_GRO_POINT_GPLP8 +// ========================================================================== +// GroPoint Profile GPLP-8 Soil Moisture and Temperature Sensor +// ========================================================================== +/** Start [gro_point_gplp8] */ +#include + +// NOTE: Extra hardware and software serial ports are created in the "Settings +// for Additional Serial Ports" section + +// NOTE: Use -1 for any pins that don't apply or aren't being used. +byte gplp8ModbusAddress = 0x19; // The modbus address of the gplp8 +// Raw Request >>> {0x19, 0x03, 0x00, 0xC8, 0x00, 0x01, 0x06, 0x2C} +const int8_t gplp8AdapterPower = sensorPowerPin; // RS485 adapter power pin +const int8_t gplp8SensorPower = A3; // Sensor power pin +const int8_t gplp8EnablePin = -1; // Adapter RE/DE pin +const uint8_t gplp8NumberReadings = 1; +// The manufacturer recommends averaging 10 readings, but we take 5 to minimize +// power consumption + +// Create a GroPoint Profile GPLP-8 sensor object +GroPointGPLP8 gplp8(gplp8ModbusAddress, modbusSerial, gplp8AdapterPower, + gplp8SensorPower, gplp8EnablePin, gplp8NumberReadings); + +// Create moisture variable pointers for each segment of the GPLP-8 +Variable* gplp8Moist1 = new GroPointGPLP8_Moist( + &gplp8, 0, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist1"); +Variable* gplp8Moist2 = new GroPointGPLP8_Moist( + &gplp8, 1, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist2"); +Variable* gplp8Moist3 = new GroPointGPLP8_Moist( + &gplp8, 2, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist3"); +Variable* gplp8Moist4 = new GroPointGPLP8_Moist( + &gplp8, 3, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist4"); +Variable* gplp8Moist5 = new GroPointGPLP8_Moist( + &gplp8, 4, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist5"); +Variable* gplp8Moist6 = new GroPointGPLP8_Moist( + &gplp8, 5, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist6"); +Variable* gplp8Moist7 = new GroPointGPLP8_Moist( + &gplp8, 6, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist7"); +Variable* gplp8Moist8 = new GroPointGPLP8_Moist( + &gplp8, 7, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Moist8"); + +// Create temperature variable pointers for each sensor of the GPLP-8 +Variable* gplp8Temp1 = new GroPointGPLP8_Temp( + &gplp8, 8, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp1"); +Variable* gplp8Temp2 = new GroPointGPLP8_Temp( + &gplp8, 9, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp1"); +Variable* gplp8Temp3 = new GroPointGPLP8_Temp( + &gplp8, 10, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp3"); +Variable* gplp8Temp4 = new GroPointGPLP8_Temp( + &gplp8, 11, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp4"); +Variable* gplp8Temp5 = new GroPointGPLP8_Temp( + &gplp8, 12, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp5"); +Variable* gplp8Temp6 = new GroPointGPLP8_Temp( + &gplp8, 13, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp6"); +Variable* gplp8Temp7 = new GroPointGPLP8_Temp( + &gplp8, 14, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp7"); +Variable* gplp8Temp8 = new GroPointGPLP8_Temp( + &gplp8, 15, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp8"); +Variable* gplp8Temp9 = new GroPointGPLP8_Temp( + &gplp8, 16, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp9"); +Variable* gplp8Temp10 = new GroPointGPLP8_Temp( + &gplp8, 17, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp10"); +Variable* gplp8Temp11 = new GroPointGPLP8_Temp( + &gplp8, 18, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp11"); +Variable* gplp8Temp12 = new GroPointGPLP8_Temp( + &gplp8, 19, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp12"); +Variable* gplp8Temp13 = new GroPointGPLP8_Temp( + &gplp8, 20, "12345678-abcd-1234-ef00-1234567890ab", "GPLP8Temp13"); +/** End [gro_point_gplp8] */ +#endif + #if defined BUILD_SENSOR_IN_SITU_RDO // ========================================================================== @@ -1931,6 +2032,39 @@ Variable* analogEc_spcond = new Variable( #endif +#if defined BUILD_SENSOR_VEGA_PULS21 +// ========================================================================== +// VEGA PULS 21 Radar Sensor +// ========================================================================== +/** Start [vega_puls21] */ +#include + +// NOTE: Use -1 for any pins that don't apply or aren't being used. +const char* VegaPulsSDI12address = "0"; // The SDI-12 Address of the VegaPuls10 +const int8_t VegaPulsPower = sensorPowerPin; // Power pin +const int8_t VegaPulsData = 7; // The SDI-12 data pin +// NOTE: you should NOT take more than one readings. THe sensor already takes +// and averages 8 by default. + +// Create a Campbell VegaPusl21 sensor object +VegaPuls21 VegaPuls(*VegaPulsSDI12address, VegaPulsPower, VegaPulsData); + +// Create stage, distance, temperature, reliability, and error variable pointers +// for the VegaPuls21 +Variable* VegaPulsStage = + new VegaPuls21_Stage(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab"); +Variable* VegaPulsDistance = + new VegaPuls21_Distance(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab"); +Variable* VegaPulsTemp = + new VegaPuls21_Temp(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab"); +Variable* VegaPulsRelia = new VegaPuls21_Reliability( + &VegaPuls, "12345678-abcd-1234-ef00-1234567890ab"); +Variable* VegaPulsError = + new VegaPuls21_ErrorCode(&VegaPuls, "12345678-abcd-1234-ef00-1234567890ab"); +/** End [vega_puls21] */ +#endif + + #if defined BUILD_SENSOR_YOSEMITECH_Y504 // ========================================================================== // Yosemitech Y504 Dissolved Oxygen Sensor @@ -2376,7 +2510,7 @@ Variable* calculatedVar = new Variable( #if defined BUILD_TEST_CREATE_IN_ARRAY // ========================================================================== // Creating the Variable Array[s] and Filling with Variable Objects -// NOTE: This shows three differnt ways of creating the same variable array +// NOTE: This shows three different ways of creating the same variable array // and filling it with variables // ========================================================================== /** Start [variables_create_in_array] */ @@ -2539,6 +2673,29 @@ Variable* variableList[] = { mplTemp, mplPress, #endif +#if defined BUILD_SENSOR_GRO_POINT_GPLP8 + gplp8Moist1, + gplp8Moist2, + gplp8Moist3, + gplp8Moist4, + gplp8Moist5, + gplp8Moist6, + gplp8Moist7, + gplp8Moist8, + gplp8Temp1, + gplp8Temp2, + gplp8Temp3, + gplp8Temp4, + gplp8Temp5, + gplp8Temp6, + gplp8Temp7, + gplp8Temp8, + gplp8Temp9, + gplp8Temp10, + gplp8Temp11, + gplp8Temp12, + gplp8Temp13, +#endif #if defined BUILD_SENSOR_IN_SITU_RDO rdoTemp, rdoDOpct, @@ -2625,6 +2782,13 @@ Variable* variableList[] = { analogEc_cond, analogEc_spcond, #endif +#if defined BUILD_SENSOR_VEGA_PULS21 + VegaPulsStage, + VegaPulsDistance, + VegaPulsTemp, + VegaPulsRelia, + VegaPulsError, +#endif #if defined BUILD_SENSOR_YOSEMITECH_Y504 y504DOpct, y504DOmgL, @@ -2816,8 +2980,8 @@ void greenredflash(uint8_t numFlash = 4, uint8_t rate = 75) { // Uses the processor sensor object to read the battery voltage // NOTE: This will actually return the battery level from the previous update! float getBatteryVoltage() { - if (mcuBoard.sensorValues[0] == -9999) mcuBoard.update(); - return mcuBoard.sensorValues[0]; + if (mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM] == -9999) mcuBoard.update(); + return mcuBoard.sensorValues[PROCESSOR_BATTERY_VAR_NUM]; } /** End [working_functions] */ @@ -2853,15 +3017,15 @@ void setup() { Serial.print(F("TinyGSM Library version ")); Serial.println(TINYGSM_VERSION); Serial.println(); -/** End [setup_prints] */ + /** End [setup_prints] */ /** Start [setup_softserial] */ // Allow interrupts for software serial -#if defined SoftwareSerial_ExtInts_h +#if defined BUILD_TEST_SOFTSERIAL enableInterrupt(softSerialRx, SoftwareSerial_ExtInts::handle_interrupt, CHANGE); #endif -#if defined NeoSWSerial_h +#if defined BUILD_TEST_NEOSWSERIAL enableInterrupt(neoSSerial1Rx, neoSSerial1ISR, CHANGE); #endif /** End [setup_softserial] */ @@ -2906,6 +3070,9 @@ void setup() { greenredflash(); /** End [setup_flashing_led] */ + pinMode(20, OUTPUT); // for proper operation of the onboard flash memory + // chip's ChipSelect (Mayfly v1.0 and later) + /** Start [setup_logger] */ // Set the timezones for the logger/data and the RTC // Logging in the given time zone diff --git a/examples/simple_logging/simple_logging.ino b/examples/simple_logging/simple_logging.ino index ec810f886..a31804449 100644 --- a/examples/simple_logging/simple_logging.ino +++ b/examples/simple_logging/simple_logging.ino @@ -3,11 +3,10 @@ * @brief A simple data logging example. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -21,10 +20,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/simple_logging_LearnEnviroDIY/simple_logging_LearnEnviroDIY.ino b/examples/simple_logging_LearnEnviroDIY/simple_logging_LearnEnviroDIY.ino index 9b69aae8e..5edeaa3ab 100644 --- a/examples/simple_logging_LearnEnviroDIY/simple_logging_LearnEnviroDIY.ino +++ b/examples/simple_logging_LearnEnviroDIY/simple_logging_LearnEnviroDIY.ino @@ -3,11 +3,10 @@ * @brief A data logging example for the Learn EnviroDIY tutorial. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: @@ -21,10 +20,6 @@ // The Arduino library is needed for every Arduino program. #include -// EnableInterrupt is used by ModularSensors for external and pin change -// interrupts and must be explicitly included in the main program. -#include - // Include the main header for ModularSensors #include /** End [includes] */ diff --git a/examples/single_sensor/single_sensor.ino b/examples/single_sensor/single_sensor.ino index b0b7bdf6c..76d3863df 100644 --- a/examples/single_sensor/single_sensor.ino +++ b/examples/single_sensor/single_sensor.ino @@ -3,11 +3,10 @@ * @brief An example using only sensor functions and no logging. * * @author Sara Geleskie Damiano - * @copyright (c) 2017-2022 Stroud Water Research Center (SWRC) - * and the EnviroDIY Development Team - * This example is published under the BSD-3 license. + * @copyright Stroud Water Research Center + * This example is published under the BSD-3 license. * - * Build Environment: Visual Studios Code with PlatformIO + * Build Environment: Visual Studio Code with PlatformIO * Hardware Platform: EnviroDIY Mayfly Arduino Datalogger * * DISCLAIMER: diff --git a/extras/mega_serial_spy/mega_serial_spy.ino b/extras/mega_serial_spy/mega_serial_spy.ino index 019393f52..7d9316369 100644 --- a/extras/mega_serial_spy/mega_serial_spy.ino +++ b/extras/mega_serial_spy/mega_serial_spy.ino @@ -10,6 +10,7 @@ void changeBauds(void) { Serial.println("[1] - 9600"); Serial.println("[2] - 57600"); Serial.println("[3] - 115200"); + Serial.println("[4] - 74880"); Serial.println(""); Serial.println( "Enter you selection in the Serial Monitor and press "); @@ -38,6 +39,7 @@ void changeBauds(void) { default: baud = 9600; break; case 2: baud = 57600; break; case 3: baud = 115200; break; + case 4: baud = 74880; break; } } diff --git a/library.json b/library.json index c6ce2e086..687ebf63a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "EnviroDIY_ModularSensors", - "version": "0.34.0", + "version": "0.35.0", "description": "A library that allows access to multiple sensors through a unified interface. This allows the user to simply access many sensors to log the data or send the data to data repositories like the EnviroDIY data portal.", "keywords": "modular, sensor, sensors, datalogger, logger, low power, sleeping, EnviroDIY, ModularSensors, Mayfly, WikiWatershed, Monitor My Watershed, ThingSpeak", "platforms": "atmelavr, atmelsam", @@ -100,7 +100,7 @@ "owner": "greiman", "library id": "322", "url": "https://github.com/greiman/SdFat", - "version": "~2.1.2", + "version": "~2.2.3", "note": "SdFat - FAT16/FAT32 file system for SD cards.", "authors": ["Bill Greiman"], "frameworks": "arduino", @@ -109,7 +109,7 @@ { "name": "TinyGSM", "owner": "vshymanskyy", - "version": "~0.11.5", + "version": "~0.11.7", "note": "A small Arduino library for GPRS modules.", "authors": ["Volodymyr Shymanskyy", "Sara Damiano"], "frameworks": "arduino", @@ -129,7 +129,7 @@ "owner": "adafruit", "library id": "6214", "url": "https://github.com/adafruit/Adafruit_BusIO", - "version": "~1.11.6", + "version": "~1.16.0", "note": "Adafruit BusIO, a dependency of other Adafruit libraries", "authors": ["Adafruit"], "frameworks": "arduino", @@ -140,7 +140,7 @@ "owner": "adafruit", "library id": "31", "url": "https://github.com/adafruit/Adafruit_Sensor", - "version": "~1.1.9", + "version": "~1.1.14", "note": "Adafruit's unified sensor library is used by their other libraries", "authors": ["Adafruit"], "frameworks": "arduino", @@ -172,7 +172,7 @@ "owner": "adafruit", "library id": "166", "url": "https://github.com/adafruit/Adafruit_BME280_Library", - "version": "~2.2.2", + "version": "~2.2.4", "note": "Bosch BME280 Temp/Humidity/Pressure Sensor Library by Adafruit", "authors": ["Adafruit"], "frameworks": "arduino", @@ -192,7 +192,7 @@ "owner": "adafruit", "library id": "19", "url": "https://github.com/adafruit/DHT-sensor-library", - "version": "~1.4.4", + "version": "~1.4.6", "note": "AOSong DHT Sensor Library by Adafruit", "authors": ["Adafruit"], "frameworks": "arduino", @@ -203,7 +203,7 @@ "owner": "adafruit", "library id": "160", "url": "https://github.com/adafruit/Adafruit_INA219", - "version": "~1.2.1", + "version": "~1.2.3", "note": "This is a library for the Adafruit INA219 high side DC current sensor boards", "authors": ["Adafruit"], "frameworks": "arduino", @@ -224,7 +224,7 @@ "owner": "adafruit", "library id": "11710", "url": "https://github.com/adafruit/Adafruit_SHT4X", - "version": "~1.0.2", + "version": "~1.0.4", "note": "Sensirion SHT4x Library by Adafruit", "authors": ["Adafruit"], "frameworks": "arduino" @@ -234,7 +234,7 @@ "owner": "paulstoffregen", "library id": "1", "url": "https://github.com/PaulStoffregen/OneWire", - "version": "~2.3.7", + "version": "~2.3.8", "note": "OneWire - Control 1-Wire protocol (DS18S20, DS18B20, DS2408 and etc)", "authors": [ "Paul Stoffregen", @@ -258,7 +258,7 @@ "owner": "milesburton", "library id": "54", "url": "https://github.com/milesburton/Arduino-Temperature-Control-Library", - "version": "~3.9.1", + "version": "~3.11.0", "note": "DallasTemperature - Arduino Library for Dallas Temperature ICs (DS18B20, DS18S20, DS1822, DS1820)", "authors": ["Guil Barros", "Miles Burton", "Rob Tillart", "Tim Nuewsome"], "frameworks": "arduino", @@ -323,11 +323,21 @@ "owner": "envirodiy", "library id": "2078", "url": "https://github.com/EnviroDIY/YosemitechModbus", - "version": "~0.4.0", + "version": "~0.4.1", "note": "Arduino library for communication with Yosemitech sensors via Modbus.", "authors": ["Sara Damiano", "Anthony Aufdenkampe"], "frameworks": "arduino", "platforms": "atmelavr, atmelsam" + }, + { + "name": "GroPointModbus", + "owner": "envirodiy", + "url": "https://github.com/EnviroDIY/GroPointModbus.git", + "version": "~0.1.0", + "note": "A library to use an Arduino as a master to control and communicate via modbus with GroPoint soil moisture sensors. ", + "authors": ["Anthony Aufdenkampe"], + "frameworks": "arduino", + "platforms": "atmelavr, atmelsam" } ] } diff --git a/library.properties b/library.properties index fe0a35b7b..8fd05ee5d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ModularSensors -version=0.34.0 +version=0.35.0 author=Sara Damiano , Shannon Hicks maintainer=Sara Damiano sentence=A library that allows access to multiple sensors through a unified interface. diff --git a/pioScripts/generate_compile_commands.py b/pioScripts/generate_compile_commands.py index 6e584b3a6..f3e9ccaa8 100644 --- a/pioScripts/generate_compile_commands.py +++ b/pioScripts/generate_compile_commands.py @@ -1,8 +1,13 @@ import os + Import("env") +print("Generating compile commands!") + # include toolchain paths env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True) # override compilation DB path -env.Replace(COMPILATIONDB_PATH=os.path.join("$PROJECT_DIR/.vscode", "compile_commands.json")) \ No newline at end of file +env.Replace( + COMPILATIONDB_PATH=os.path.join("$PROJECT_DIR/.vscode", "compile_commands.json") +) diff --git a/src/LoggerBase.cpp b/src/LoggerBase.cpp index c125f0180..cfe4db7bc 100644 --- a/src/LoggerBase.cpp +++ b/src/LoggerBase.cpp @@ -1,7 +1,8 @@ /** * @file LoggerBase.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the Logger class. @@ -17,7 +18,7 @@ */ #define LIBCALL_ENABLEINTERRUPT // To handle external and pin change interrupts -#include +#include "ModSensorInterrupts.h" // For all i2c communication, including with the real time clock #include @@ -34,8 +35,8 @@ volatile bool Logger::isLoggingNow = false; volatile bool Logger::isTestingNow = false; volatile bool Logger::startTesting = false; -// Initialize the RTC for the SAMD boards -#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAMD_ZERO) +// Initialize the RTC for the SAMD boards using build in RTC +#if not defined(MS_SAMD_DS3231) && defined(ARDUINO_ARCH_SAMD) RTCZero Logger::zero_sleep_rtc; #endif @@ -305,25 +306,11 @@ bool Logger::syncRTC() { PRINTOUT(F("Could not wake modem for clock sync.")); } watchDogTimer.resetWatchDog(); - // Power down the modem - but only if there will be more than 15 seconds - // before the NEXT logging interval - it can take the modem that long to - // shut down - - uint32_t setupFinishTime = getNowLocalEpoch(); - if (setupFinishTime % (_loggingIntervalMinutes * 60) > 15) { - MS_DBG(F("At"), formatDateTime_ISO8601(setupFinishTime), F("with"), - setupFinishTime % (_loggingIntervalMinutes * 60), - F("seconds until next logging interval, putting modem to " - "sleep")); - _logModem->disconnectInternet(); - _logModem->modemSleepPowerDown(); - } else { - MS_DBG(F("At"), formatDateTime_ISO8601(setupFinishTime), - F("there are only"), - setupFinishTime % (_loggingIntervalMinutes * 60), - F("seconds until next logging interval; leaving modem on " - "and connected to the internet.")); - } + + // Power down the modem now that we are done with it + MS_DBG(F("Powering down modem after clock sync.")); + _logModem->disconnectInternet(); + _logModem->modemSleepPowerDown(); } watchDogTimer.resetWatchDog(); return success; @@ -499,7 +486,7 @@ String Logger::formatDateTime_ISO8601(DateTime& dt) { tzString = tzString.substring(0, 1) + '0' + tzString.substring(1, 2) + F(":00"); } else if (_loggerTimeZone == 0) { - tzString = 'Z'; + tzString = "Z"; } else if (0 < _loggerTimeZone && _loggerTimeZone < 10) { tzString = "+0" + tzString + F(":00"); } else if (10 <= _loggerTimeZone && _loggerTimeZone <= 24) { @@ -1052,13 +1039,11 @@ bool Logger::initializeSDCard(void) { // Protected helper function - This sets a timestamp on a file -void Logger::setFileTimestamp(File fileToStamp, uint8_t stampFlag) { - fileToStamp.timestamp(stampFlag, dtFromEpoch(getNowLocalEpoch()).year(), - dtFromEpoch(getNowLocalEpoch()).month(), - dtFromEpoch(getNowLocalEpoch()).date(), - dtFromEpoch(getNowLocalEpoch()).hour(), - dtFromEpoch(getNowLocalEpoch()).minute(), - dtFromEpoch(getNowLocalEpoch()).second()); +void Logger::setFileTimestamp(File& fileToStamp, uint8_t stampFlag) { + DateTime dt = dtFromEpoch(getNowLocalEpoch()); + + fileToStamp.timestamp(stampFlag, dt.year(), dt.month(), dt.date(), + dt.hour(), dt.minute(), dt.second()); } @@ -1272,14 +1257,6 @@ void Logger::testingMode() { PRINTOUT(F("------------------------------------------")); // Update the modem metadata - // NOTE: the extra get signal quality is an annoying redundancy - // needed only for the wifi XBee. Update metadata will also ask the - // module for current signal quality using the underlying TinyGSM - // getSignalQuality() function, but for the WiFi XBee it will not - // actually measure anything except by explicitly making a connection, - // which getModemSignalQuality() does. For all of the other modules, - // getModemSignalQuality() is just a straight pass-through to - // getSignalQuality(). if (gotInternetConnection) { _logModem->updateModemMetadata(); } watchDogTimer.resetWatchDog(); @@ -1352,7 +1329,7 @@ void Logger::begin() { // Enable the watchdog watchDogTimer.enableWatchDog(); -#if defined ARDUINO_ARCH_SAMD +#if not defined(MS_SAMD_DS3231) && defined(ARDUINO_ARCH_SAMD) MS_DBG(F("Beginning internal real time clock")); zero_sleep_rtc.begin(); #endif diff --git a/src/LoggerBase.h b/src/LoggerBase.h index 36040f426..57556b40e 100644 --- a/src/LoggerBase.h +++ b/src/LoggerBase.h @@ -1,7 +1,8 @@ /** * @file LoggerBase.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the LoggerBase class which handles basic logging functions. @@ -35,7 +36,9 @@ // Bring in the libraries to handle the processor sleep/standby modes // The SAMD library can also the built-in clock on those modules #if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAMD_ZERO) +#if not defined(MS_SAMD_DS3231) #include +#endif #include "WatchDogs/WatchDogSAMD.h" #elif defined(ARDUINO_ARCH_AVR) || defined(__AVR__) #include @@ -47,6 +50,7 @@ // clock This also implements a needed date/time class #include +#ifndef EPOCH_TIME_OFF /** * @brief January 1, 2000 00:00:00 in "epoch" time * @@ -55,6 +59,7 @@ * epoch beginning 1970-jan-01 00:00:00. */ #define EPOCH_TIME_OFF 946684800 +#endif #include // To communicate with the SD card @@ -677,7 +682,8 @@ class Logger { // This gets the current epoch time (unix time, ie, the number of seconds // from January 1, 1970 00:00:00 UTC) and corrects it for the specified time // zone -#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAMD_ZERO) +#if (defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_SAMD_ZERO)) && \ + not defined(MS_SAMD_DS3231) /** * @brief The RTC object. * @@ -1057,7 +1063,7 @@ class Logger { * @param stampFlag The "flag" of the timestamp to change - should be * T_CREATE, T_WRITE, or T_ACCESS */ - void setFileTimestamp(File fileToStamp, uint8_t stampFlag); + void setFileTimestamp(File& fileToStamp, uint8_t stampFlag); /** * @brief Open or creates a file, converting a string file name to a diff --git a/src/LoggerModem.cpp b/src/LoggerModem.cpp index b44fa8159..3b3be5cd7 100644 --- a/src/LoggerModem.cpp +++ b/src/LoggerModem.cpp @@ -1,7 +1,8 @@ /** * @file LoggerModem.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the loggerModem class. @@ -63,6 +64,12 @@ String loggerModem::getModemName(void) { return _modemName; } +// @TODO Implement this for all modems +String loggerModem::getModemDevId(void) { + return _modemName + F(" Sn ") + _modemSerialNumber + F(" HwVer ") + + _modemHwVersion + F(" FwVer ") + _modemFwVersion; +} + void loggerModem::modemPowerUp(void) { if (_powerPin >= 0) { if (_modemSleepRqPin >= 0) { @@ -305,6 +312,17 @@ void loggerModem::setModemPinModes(void) { } +void loggerModem::enableMetadataPolling(uint8_t pollingBitmask) { + _pollModemMetaData |= pollingBitmask; +} +void loggerModem::disableMetadataPolling(uint8_t pollingBitmask) { + _pollModemMetaData |= ~pollingBitmask; +} +void loggerModem::setMetadataPolling(uint8_t pollingBitmask) { + _pollModemMetaData = pollingBitmask; +} + + bool loggerModem::updateModemMetadata(void) { bool success = true; @@ -323,40 +341,64 @@ bool loggerModem::updateModemMetadata(void) { int8_t bpercent = -99; uint16_t volt = 9999; - // Try for up to 15 seconds to get a valid signal quality - uint32_t startMillis = millis(); - do { - success &= getModemSignalQuality(rssi, percent); - loggerModem::_priorRSSI = rssi; - loggerModem::_priorSignalPercent = percent; - if (rssi != 0 && rssi != -9999) break; - delay(250); - } while ((rssi == 0 || rssi == -9999) && millis() - startMillis < 15000L && - success); - MS_DBG(F("CURRENT RSSI:"), rssi); - MS_DBG(F("CURRENT Percent signal strength:"), percent); - - success &= getModemBatteryStats(state, bpercent, volt); - MS_DBG(F("CURRENT Modem Battery Charge State:"), state); - MS_DBG(F("CURRENT Modem Battery Charge Percentage:"), bpercent); - MS_DBG(F("CURRENT Modem Battery Voltage:"), volt); - if (state != 99) - loggerModem::_priorBatteryState = static_cast(state); - else - loggerModem::_priorBatteryState = static_cast(-9999); - - if (bpercent != -99) - loggerModem::_priorBatteryPercent = static_cast(bpercent); - else - loggerModem::_priorBatteryPercent = static_cast(-9999); - - if (volt != 9999) - loggerModem::_priorBatteryVoltage = static_cast(volt); - else - loggerModem::_priorBatteryVoltage = static_cast(-9999); - - loggerModem::_priorModemTemp = getModemChipTemperature(); - MS_DBG(F("CURRENT Modem Chip Temperature:"), loggerModem::_priorModemTemp); + MS_DBG(F("Modem polling settings:"), String(_pollModemMetaData, BIN)); + + if ((_pollModemMetaData & MODEM_RSSI_ENABLE_BITMASK) == + MODEM_RSSI_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) == + MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) { + // Try for up to 15 seconds to get a valid signal quality + uint32_t startMillis = millis(); + do { + success &= getModemSignalQuality(rssi, percent); + loggerModem::_priorRSSI = rssi; + loggerModem::_priorSignalPercent = percent; + if (rssi != 0 && rssi != -9999) break; + delay(250); + } while ((rssi == 0 || rssi == -9999) && + millis() - startMillis < 15000L && success); + MS_DBG(F("CURRENT RSSI:"), rssi); + MS_DBG(F("CURRENT Percent signal strength:"), percent); + } else { + MS_DBG(F("Polling for both RSSI and signal strength is disabled")); + } + + if ((_pollModemMetaData & MODEM_BATTERY_STATE_ENABLE_BITMASK) == + MODEM_BATTERY_STATE_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_BATTERY_PERCENT_ENABLE_BITMASK) == + MODEM_BATTERY_PERCENT_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) == + MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) { + success &= getModemBatteryStats(state, bpercent, volt); + MS_DBG(F("CURRENT Modem Battery Charge State:"), state); + MS_DBG(F("CURRENT Modem Battery Charge Percentage:"), bpercent); + MS_DBG(F("CURRENT Modem Battery Voltage:"), volt); + if (state != 99) + loggerModem::_priorBatteryState = static_cast(state); + else + loggerModem::_priorBatteryState = static_cast(-9999); + + if (bpercent != -99) + loggerModem::_priorBatteryPercent = static_cast(bpercent); + else + loggerModem::_priorBatteryPercent = static_cast(-9999); + + if (volt != 9999) + loggerModem::_priorBatteryVoltage = static_cast(volt); + else + loggerModem::_priorBatteryVoltage = static_cast(-9999); + } else { + MS_DBG(F("Polling for all modem battery parameters is disabled")); + } + + if ((_pollModemMetaData & MODEM_TEMPERATURE_ENABLE_BITMASK) == + MODEM_TEMPERATURE_ENABLE_BITMASK) { + loggerModem::_priorModemTemp = getModemChipTemperature(); + MS_DBG(F("CURRENT Modem Chip Temperature:"), + loggerModem::_priorModemTemp); + } else { + MS_DBG(F("Polling for modem chip temperature is disabled")); + } return success; } @@ -394,31 +436,16 @@ float loggerModem::getModemTemperature() { // Helper to get approximate RSSI from CSQ (assuming no noise) int16_t loggerModem::getRSSIFromCSQ(int16_t csq) { - int16_t CSQs[33] = {0, 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, 99}; - int16_t RSSIs[33] = {-113, -111, -109, -107, -105, -103, -101, -99, -97, - -95, -93, -91, -89, -87, -85, -83, -81, -79, - -77, -75, -73, -71, -69, -67, -65, -63, -61, - -59, -57, -55, -53, -51, 0}; - for (uint8_t i = 0; i < 33; i++) { - if (CSQs[i] == csq) return RSSIs[i]; - } - return 0; + if ((csq < 0) || (csq > 31)) return 0; + // equation matches previous table. not sure the original motivation. + return ((csq * 2) - 113); } // Helper to get signal percent from CSQ int16_t loggerModem::getPctFromCSQ(int16_t csq) { - int16_t CSQs[33] = {0, 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, 99}; - int16_t PCTs[33] = {0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, - 36, 39, 42, 45, 48, 52, 55, 58, 61, 65, 68, - 71, 74, 78, 81, 84, 87, 90, 94, 97, 100, 0}; - for (uint8_t i = 0; i < 33; i++) { - if (CSQs[i] == csq) return PCTs[i]; - } - return 0; + if ((csq < 0) || (csq > 31)) return 0; + // equation matches previous table. not sure the original motivation. + return (csq * 827 + 127) >> 8; } // Helper to get signal percent from RSSI diff --git a/src/LoggerModem.h b/src/LoggerModem.h index 2b2c7b116..a55736dcc 100644 --- a/src/LoggerModem.h +++ b/src/LoggerModem.h @@ -1,7 +1,8 @@ /** * @file LoggerModem.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the loggerModem class and the variable subclasses @@ -43,7 +44,7 @@ * Variable objects to be tied to a loggerModem. These are measured by a modem, * but are implemented as calculated variables. * - * @note The modem is NOT set up as a sensor. ALl of these variables for the + * @note The modem is NOT set up as a sensor. ALL of these variables for the * modem object are actually being called as calculated variables where the * calculation function is to ask the modem object for the values from the last * time it connected to the internet. @@ -68,6 +69,9 @@ * RSSI is a rough calculation, so it has 0 decimal place resolution */ #define MODEM_RSSI_RESOLUTION 0 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable RSSI +/// polling. +#define MODEM_RSSI_ENABLE_BITMASK 0b00000001 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "RSSI" @@ -94,6 +98,9 @@ * Percent signal is a rough calculation, so it has 0 decimal place resolution */ #define MODEM_PERCENT_SIGNAL_RESOLUTION 0 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable percent +/// signal polling. +#define MODEM_PERCENT_SIGNAL_ENABLE_BITMASK 0b00000010 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "signalPercent" @@ -124,6 +131,9 @@ * Battery state is a code value; it has 0 decimal place resolution */ #define MODEM_BATTERY_STATE_RESOLUTION 0 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable modem +/// battery charging state polling. +#define MODEM_BATTERY_STATE_ENABLE_BITMASK 0b00000100 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "batteryChargeState" @@ -151,6 +161,9 @@ /// @brief Decimals places in string representation; battery charge percent /// should have 0. #define MODEM_BATTERY_PERCENT_RESOLUTION 0 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable modem +/// battery percent polling. +#define MODEM_BATTERY_PERCENT_ENABLE_BITMASK 0b00001000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "batteryVoltage" @@ -181,6 +194,9 @@ * No supported module has higher than 1mV resolution in battery reading. */ #define MODEM_BATTERY_VOLTAGE_RESOLUTION 0 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable modem +/// battery voltage polling. +#define MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK 0b00010000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "batteryVoltage" @@ -210,6 +226,9 @@ * Most modules that can measure temperature measure to 0.1°C */ #define MODEM_TEMPERATURE_RESOLUTION 1 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable modem +/// temperature polling. +#define MODEM_TEMPERATURE_ENABLE_BITMASK 0b00100000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "temperature" @@ -236,6 +255,9 @@ /// @brief Decimals places in string representation; total active time should /// have 3. #define MODEM_ACTIVATION_RESOLUTION 3 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable modem +/// activation time polling. +#define MODEM_ACTIVATION_ENABLE_BITMASK 0b01000000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "timeElapsed" @@ -260,6 +282,9 @@ /// @brief Decimals places in string representation; total powered time should /// have 3. #define MODEM_POWERED_RESOLUTION 3 +/// @brief The bit mask for loggerModem::_pollModemMetaData to enable modem +/// power time polling +#define MODEM_POWERED_ENABLE_BITMASK 0b10000000 /// @brief Variable name in /// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); /// "timeElapsed" @@ -340,6 +365,18 @@ class loggerModem { */ String getModemName(void); + /** + * @brief Get a detailed printable description of the modem. + * + * @note These values are polled for and cached in memory till needed + * + * @return **String** The concatenated name, hardware version, firmware + * version, and serial number of the modem. + * + * @todo Implement this for modems other than the XBee WiFi + */ + String getModemDevId(void); + /** * @brief Set up the modem before first use. * @@ -535,6 +572,7 @@ class loggerModem { * called after the modem is connected to the internet. */ /**@{*/ + /** * @brief Query the modem for the current signal quality and write the * results to the supplied non-constant references. @@ -572,13 +610,45 @@ class loggerModem { */ virtual float getModemChipTemperature(void) = 0; + + /** + * @brief Enables metadata polling for one or more modem measured + * variables. Setting this to 0b11111111 will enable polling for all modem + * measured variables. + * + * @note This will **not** disable polling for any unset bits in the + * provided bitmask. It will only enable those bits that are set. + */ + void enableMetadataPolling(uint8_t pollingBitmask); + + /** + * @brief Disables metadata polling for one or more modem measured + * variables. Setting this to 0b11111111 will disable polling for all modem + * measured variables. + * + * @note This will **not** enable polling for any unset bits in the + * provided bitmask. It will only disable polling for those bits that are + * set. + */ + void disableMetadataPolling(uint8_t pollingBitmask); + + /** + * @brief Sets the bitmask for modem metadata polling. + * + * This will enable polling for 1 bits and disable polling for 0 bits. + * Setting this to 0 (0b00000000) will disable polling for all metadata + * parameters. Setting it to 256 (0b11111111) will enable polling for all + * parameters. + */ + void setMetadataPolling(uint8_t pollingBitmask); + /** * @brief Query the modem for signal quality, battery, and temperature * information and store the values to the static internal variables. * - * @return **bool** True indicates that the communication with the modem was - * successful and the values of the internal static variables should be - * valid. + * @return **bool** True indicates that the communication with the modem + * was successful and the values of the internal static variables should + * be valid. */ virtual bool updateModemMetadata(void); /**@}*/ @@ -989,6 +1059,56 @@ class loggerModem { // modemType gsmModem; // modemClientType gsmClient; + + // @TODO: Implement these for all modems; most support it. + + /** + * @brief The modem hardware version. + * + * Set in #modemSetup(). + * Returned as a portion of the #getModemDevId(). + * + * @todo Implement this for modems other than the XBee WiFi + */ + String _modemHwVersion; + /** + * @brief The modem firmware version. + * + * Set in #modemSetup(). + * Returned as a portion of the #getModemDevId(). + * + * @todo Implement this for modems other than the XBee WiFi + */ + String _modemFwVersion; + /** + * @brief The modem serial number. + * + * Set in #modemSetup(). + * Returned as a portion of the #getModemDevId(). + * + * @todo Implement this for modems other than the XBee WiFi + */ + String _modemSerialNumber; + + /** + * @brief An 8-bit code for the enabled modem polling variables + * + * Setting a bit to 0 will disable polling, to 1 will enable it. By default + * no polling is enabled to save time and power by not requesting + * unnecessary information from the modem. When modem measured variables + * are attached to a modem, polling for those results is automatically + * enabled. + * + * Bit | Variable Class | Relevent Define + * ----|----------------|---------------- + * 0 | #Modem_RSSI | #MODEM_RSSI_ENABLE_BITMASK + * 1 | #Modem_SignalPercent | #MODEM_PERCENT_SIGNAL_ENABLE_BITMASK + * 2 | #Modem_BatteryState | #MODEM_BATTERY_STATE_ENABLE_BITMASK + * 3 | #Modem_BatteryPercent | #MODEM_BATTERY_PERCENT_ENABLE_BITMASK + * 4 | #Modem_BatteryVoltage | #MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK + * 5 | #Modem_Temp | #MODEM_TEMPERATURE_ENABLE_BITMASK + */ + uint8_t _pollModemMetaData = 0; }; // typedef float (loggerModem::_*loggerGetValueFxn)(void); @@ -1017,7 +1137,9 @@ class Modem_RSSI : public Variable { const char* varCode = MODEM_RSSI_DEFAULT_CODE) : Variable(&parentModem->getModemRSSI, (uint8_t)MODEM_RSSI_RESOLUTION, &*MODEM_RSSI_VAR_NAME, &*MODEM_RSSI_UNIT_NAME, varCode, - uuid) {} + uuid) { + parentModem->enableMetadataPolling(MODEM_RSSI_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_RSSI object - no action needed. */ @@ -1050,7 +1172,9 @@ class Modem_SignalPercent : public Variable { : Variable(&parentModem->getModemSignalPercent, (uint8_t)MODEM_PERCENT_SIGNAL_RESOLUTION, &*MODEM_PERCENT_SIGNAL_VAR_NAME, - &*MODEM_PERCENT_SIGNAL_UNIT_NAME, varCode, uuid) {} + &*MODEM_PERCENT_SIGNAL_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling(MODEM_PERCENT_SIGNAL_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_SignalPercent object - no action needed. */ @@ -1086,7 +1210,9 @@ class Modem_BatteryState : public Variable { : Variable(&parentModem->getModemBatteryChargeState, (uint8_t)MODEM_BATTERY_STATE_RESOLUTION, &*MODEM_BATTERY_STATE_VAR_NAME, - &*MODEM_BATTERY_STATE_UNIT_NAME, varCode, uuid) {} + &*MODEM_BATTERY_STATE_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling(MODEM_BATTERY_STATE_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_BatteryState object - no action needed. */ @@ -1122,7 +1248,10 @@ class Modem_BatteryPercent : public Variable { : Variable(&parentModem->getModemBatteryChargePercent, (uint8_t)MODEM_BATTERY_PERCENT_RESOLUTION, &*MODEM_BATTERY_PERCENT_VAR_NAME, - &*MODEM_BATTERY_PERCENT_UNIT_NAME, varCode, uuid) {} + &*MODEM_BATTERY_PERCENT_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling( + MODEM_BATTERY_PERCENT_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_BatteryPercent object - no action needed. */ @@ -1158,7 +1287,10 @@ class Modem_BatteryVoltage : public Variable { : Variable(&parentModem->getModemBatteryVoltage, (uint8_t)MODEM_BATTERY_VOLTAGE_RESOLUTION, &*MODEM_BATTERY_VOLTAGE_VAR_NAME, - &*MODEM_BATTERY_VOLTAGE_UNIT_NAME, varCode, uuid) {} + &*MODEM_BATTERY_VOLTAGE_UNIT_NAME, varCode, uuid) { + parentModem->enableMetadataPolling( + MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_BatteryVoltage object - no action needed. */ @@ -1193,7 +1325,9 @@ class Modem_Temp : public Variable { : Variable(&parentModem->getModemTemperature, (uint8_t)MODEM_TEMPERATURE_RESOLUTION, &*MODEM_TEMPERATURE_VAR_NAME, &*MODEM_TEMPERATURE_UNIT_NAME, - varCode, uuid) {} + varCode, uuid) { + parentModem->enableMetadataPolling(MODEM_TEMPERATURE_ENABLE_BITMASK); + } /** * @brief Destroy the Modem_Temp object - no action needed. */ diff --git a/src/ModSensorDebugger.h b/src/ModSensorDebugger.h index 5693906e9..7561c33ff 100644 --- a/src/ModSensorDebugger.h +++ b/src/ModSensorDebugger.h @@ -1,7 +1,8 @@ /** - * @file ModSensorDebugger.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @file ModSensorDebugger.h + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @author Volodymyr Shymanskyy * diff --git a/src/ModSensorInterrupts.h b/src/ModSensorInterrupts.h new file mode 100644 index 000000000..cb3650f81 --- /dev/null +++ b/src/ModSensorInterrupts.h @@ -0,0 +1,29 @@ +/** + * @file ModSensorInterrupts.h + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. + * @author Sara Geleskie Damiano + * + * @brief A work-around for the AVR interrupt library not supporting SAMD + * boards. That libary isn't necessary for them. + */ + + +// Header Guards +#ifndef SRC_MODSENSORINTERRUPTS_H_ +#define SRC_MODSENSORINTERRUPTS_H_ + +#if defined(__AVR__) || defined(ARDUINO_ARCH_AVR) || defined __SAM3U4E__ || \ + defined __SAM3X8E__ || defined __SAM3X8H__ || defined ARDUINO_SAMD_ZERO || \ + defined __SAMD21G18A__ || defined __SAMD21J18A__ +// #define LIBCALL_ENABLEINTERRUPT // To prevent compiler/linker crashes +#include // To handle external and pin change interrupts +#else +#define enableInterrupt(pin, userFunc, mode) \ + attachInterrupt(pin, userFunc, mode) +#define disableInterrupt(pin) detachInterrupt(pin) +#endif + + +#endif // SRC_MODSENSORINTERRUPTS_H_ diff --git a/src/ModularSensors.h b/src/ModularSensors.h index 32fe3c74b..313cb58cd 100644 --- a/src/ModularSensors.h +++ b/src/ModularSensors.h @@ -1,10 +1,11 @@ /** * @file ModularSensors.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * - * @brief A simple include file for the Arduino command line interface (CLI).s + * @brief A simple include file for the Arduino command line interface (CLI). */ // Header Guards @@ -13,8 +14,15 @@ /** * @brief The current library version number + * https://semver.org/ + * Add hypen '-' and alpha number for a branches unique tracking number + * A pre-release version will always be indicated as slightly ahead of the + * EnviroDIY branch that it is based on. */ -#define MODULAR_SENSORS_VERSION "0.34.0" +#define MODULAR_SENSORS_VERSION "0.35.0" + +// To support interrupts +#include "ModSensorInterrupts.h" // To get all of the base classes for ModularSensors, include LoggerBase. // NOTE: Individual sensor definitions must be included separately. diff --git a/src/SensorBase.cpp b/src/SensorBase.cpp index f89d8ab64..f3a056141 100644 --- a/src/SensorBase.cpp +++ b/src/SensorBase.cpp @@ -1,7 +1,8 @@ /** * @file SensorBase.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the Sensor class. diff --git a/src/SensorBase.h b/src/SensorBase.h index 6d581e377..44a1d68a3 100644 --- a/src/SensorBase.h +++ b/src/SensorBase.h @@ -1,7 +1,8 @@ /** * @file SensorBase.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the Sensor class. @@ -35,11 +36,13 @@ #undef MS_DEBUGGING_STD #include +#ifndef MAX_NUMBER_VARS /** * @brief The largest number of variables from a single sensor */ -#define MAX_NUMBER_VARS 8 - +#define MAX_NUMBER_VARS 21 +// GroPoint Profile GPLP-8 has 8 Moisture and 13 Temperature values +#endif class Variable; // Forward declaration diff --git a/src/VariableArray.cpp b/src/VariableArray.cpp index b6e37b7c9..161af36be 100644 --- a/src/VariableArray.cpp +++ b/src/VariableArray.cpp @@ -1,7 +1,8 @@ /** * @file VariableArray.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the VariableArray class. diff --git a/src/VariableArray.h b/src/VariableArray.h index 6675d4867..8e768aaa8 100644 --- a/src/VariableArray.h +++ b/src/VariableArray.h @@ -1,7 +1,8 @@ /** * @file VariableArray.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the VariableArray class. diff --git a/src/VariableBase.cpp b/src/VariableBase.cpp index f330bf234..4fc8cc0ab 100644 --- a/src/VariableBase.cpp +++ b/src/VariableBase.cpp @@ -1,7 +1,8 @@ /** * @file VariableBase.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the Variable class. @@ -228,7 +229,8 @@ bool Variable::checkUUIDFormat(void) { int first_invalid = strspn(_uuid, acceptableChars); if (first_invalid != 36) { MS_DBG(F("UUID for"), getVarCode(), '(', _uuid, ')', - F("has a bad character"), _uuid[first_invalid], F("at"), first_invalid); + F("has a bad character"), _uuid[first_invalid], F("at"), + first_invalid); return false; } return true; diff --git a/src/VariableBase.h b/src/VariableBase.h index 83b1c007e..35c413acd 100644 --- a/src/VariableBase.h +++ b/src/VariableBase.h @@ -1,7 +1,8 @@ /** * @file VariableBase.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the Variable class. diff --git a/src/WatchDogs/WatchDogAVR.cpp b/src/WatchDogs/WatchDogAVR.cpp index 6144bbf9a..b3614b88f 100644 --- a/src/WatchDogs/WatchDogAVR.cpp +++ b/src/WatchDogs/WatchDogAVR.cpp @@ -1,7 +1,8 @@ /** * @file WatchDogAVR.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the extendedWatchDogAVR class. diff --git a/src/WatchDogs/WatchDogAVR.h b/src/WatchDogs/WatchDogAVR.h index b816eaf57..30b48454f 100644 --- a/src/WatchDogs/WatchDogAVR.h +++ b/src/WatchDogs/WatchDogAVR.h @@ -1,7 +1,8 @@ /** * @file WatchDogAVR.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the extendedWatchDogAVR class diff --git a/src/WatchDogs/WatchDogSAMD.cpp b/src/WatchDogs/WatchDogSAMD.cpp index 3e680b7cc..ff63e78bd 100644 --- a/src/WatchDogs/WatchDogSAMD.cpp +++ b/src/WatchDogs/WatchDogSAMD.cpp @@ -1,7 +1,8 @@ /** * @file WatchDogSAMD.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the extendedWatchDogSAMD class @@ -97,10 +98,19 @@ void extendedWatchDogSAMD::setupWatchDog(uint32_t resetTime_s) { #endif // Set up the watch dog control parameters - WDT->CTRL.bit.WEN = 0; // Disable window mode - waitForWDTBitSync(); // ?? Needed here ?? +#if defined(__SAMD51__) + WDT->CTRLA.bit.WEN = 0; // Disable window mode +#else + WDT->CTRL.bit.WEN = 0; // Disable window mode +#endif + waitForWDTBitSync(); // ?? Needed here ?? +#if defined(__SAMD51__) + WDT->CTRLA.bit.ALWAYSON = 0; // NOT always on! +#else WDT->CTRL.bit.ALWAYSON = 0; // NOT always on! - waitForWDTBitSync(); // ?? Needed here ?? +#endif + + waitForWDTBitSync(); // ?? Needed here ?? WDT->CONFIG.bit.PER = 0xB; // Period = 16384 clockcycles @ 1024hz = 16 seconds @@ -134,7 +144,7 @@ void extendedWatchDogSAMD::enableWatchDog() { #if defined(__SAMD51__) WDT->CTRLA.bit.ENABLE = 1; #else - WDT->CTRL.bit.ENABLE = 1; + WDT->CTRL.bit.ENABLE = 1; #endif waitForWDTBitSync(); } @@ -144,7 +154,7 @@ void extendedWatchDogSAMD::disableWatchDog() { #if defined(__SAMD51__) WDT->CTRLA.bit.ENABLE = 0; #else - WDT->CTRL.bit.ENABLE = 0; + WDT->CTRL.bit.ENABLE = 0; #endif waitForWDTBitSync(); MS_DBG(F("Watch dog disabled.")); diff --git a/src/WatchDogs/WatchDogSAMD.h b/src/WatchDogs/WatchDogSAMD.h index c11eada2c..9b3fe1681 100644 --- a/src/WatchDogs/WatchDogSAMD.h +++ b/src/WatchDogs/WatchDogSAMD.h @@ -1,7 +1,8 @@ /** * @file WatchDogSAMD.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the extendedWatchDogSAMD class. diff --git a/src/dataPublisherBase.cpp b/src/dataPublisherBase.cpp index 76e298b6c..5429a696f 100644 --- a/src/dataPublisherBase.cpp +++ b/src/dataPublisherBase.cpp @@ -1,7 +1,8 @@ /** * @file dataPublisherBase.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the dataPublisher class. @@ -10,7 +11,9 @@ */ #include "dataPublisherBase.h" -char dataPublisher::txBuffer[MS_SEND_BUFFER_SIZE] = {'\0'}; +char dataPublisher::txBuffer[MS_SEND_BUFFER_SIZE]; +Client* dataPublisher::txBufferOutClient = nullptr; +size_t dataPublisher::txBufferLen; // Basic chunks of HTTP const char* dataPublisher::getHeader = "GET "; @@ -21,19 +24,16 @@ const char* dataPublisher::hostHeader = "\r\nHost: "; // Constructors dataPublisher::dataPublisher() {} -dataPublisher::dataPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) +dataPublisher::dataPublisher(Logger& baseLogger, int sendEveryX) : _baseLogger(&baseLogger), - _sendEveryX(sendEveryX), - _sendOffset(sendOffset) { + _sendEveryX(sendEveryX) { _baseLogger->registerDataPublisher(this); // register self with logger } dataPublisher::dataPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) + int sendEveryX) : _baseLogger(&baseLogger), _inClient(inClient), - _sendEveryX(sendEveryX), - _sendOffset(sendOffset) { + _sendEveryX(sendEveryX) { _baseLogger->registerDataPublisher(this); // register self with logger } // Destructor @@ -53,11 +53,10 @@ void dataPublisher::attachToLogger(Logger& baseLogger) { } -// Sets the parameters for frequency of sending and any offset, if needed -// NOTE: These parameters are not currently used!! -void dataPublisher::setSendFrequency(uint8_t sendEveryX, uint8_t sendOffset) { +// Sets the interval (in units of the logging interval) between attempted +// data transmissions +void dataPublisher::setSendInterval(int sendEveryX) { _sendEveryX = sendEveryX; - _sendOffset = sendOffset; } @@ -71,34 +70,56 @@ void dataPublisher::begin(Logger& baseLogger) { } -// Empties the outgoing buffer -void dataPublisher::emptyTxBuffer(void) { - MS_DBG(F("Dumping the TX Buffer")); - for (int i = 0; i < MS_SEND_BUFFER_SIZE; i++) { txBuffer[i] = '\0'; } +void dataPublisher::txBufferInit(Client* outClient) { + // remember client we are sending to + txBufferOutClient = outClient; + + // reset buffer length to be empty + txBufferLen = 0; } +void dataPublisher::txBufferAppend(const char* data, size_t length) { + while (length > 0) { + // space left in the buffer + size_t remaining = MS_SEND_BUFFER_SIZE - txBufferLen; + // the number of characters that will be added to the buffer + // this will be the lesser of the length desired and the space left in + // the buffer + size_t amount = remaining < length ? remaining : length; + + // copy as much as possible into the buffer + memcpy(&txBuffer[txBufferLen], data, amount); + // re-count how much is left to go + length -= amount; + // bump forward the pointer to where we're currently adding + data += amount; + // bump up the current length of the buffer + txBufferLen += amount; + + // write out the buffer if it fills + if (txBufferLen == MS_SEND_BUFFER_SIZE) { txBufferFlush(); } + } +} -// Returns how much space is left in the buffer -int dataPublisher::bufferFree(void) { - MS_DBG(F("Current TX Buffer Size:"), strlen(txBuffer)); - return MS_SEND_BUFFER_SIZE - strlen(txBuffer); +void dataPublisher::txBufferAppend(const char* s) { + txBufferAppend(s, strlen(s)); } +void dataPublisher::txBufferAppend(char c) { + txBufferAppend(&c, 1); +} -// Sends the tx buffer to a stream and then clears it -void dataPublisher::printTxBuffer(Stream* stream, bool addNewLine) { -// Send the out buffer so far to the serial for debugging +void dataPublisher::txBufferFlush() { #if defined(STANDARD_SERIAL_OUTPUT) - STANDARD_SERIAL_OUTPUT.write(txBuffer, strlen(txBuffer)); - if (addNewLine) { PRINTOUT('\n'); } + // write out to the printout stream + STANDARD_SERIAL_OUTPUT.write((const uint8_t*)txBuffer, txBufferLen); STANDARD_SERIAL_OUTPUT.flush(); #endif - stream->write(txBuffer, strlen(txBuffer)); - if (addNewLine) { stream->print("\r\n"); } - stream->flush(); + // write out to the client + txBufferOutClient->write((const uint8_t*)txBuffer, txBufferLen); + txBufferOutClient->flush(); - // empty the buffer after printing it - emptyTxBuffer(); + txBufferLen = 0; } diff --git a/src/dataPublisherBase.h b/src/dataPublisherBase.h index d43ba5dde..6ccefa91d 100644 --- a/src/dataPublisherBase.h +++ b/src/dataPublisherBase.h @@ -1,7 +1,8 @@ /** * @file dataPublisherBase.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the dataPublisher class - a virtual class used by other @@ -32,11 +33,10 @@ * @def MS_SEND_BUFFER_SIZE * @brief Send Buffer * - * This determines how many characters to set out at once over the TCP/UDP - * connection. Increasing this may decrease data use by a loger, while - * decreasing it will save memory. Do not make it smaller than 47 (to keep all - * variable values with their UUID's) or bigger than 1500 (a typical TCP/UDP - * Maximum Transmission Unit). + * This determines how many characters to set out at once over the TCP + * connection. Increasing this may decrease data use by a logger, while + * decreasing it will save memory. Do not make it smaller than 32 or bigger + * than 1500 (a typical TCP Maximum Transmission Unit). * * This can be changed by setting the build flag MS_SEND_BUFFER_SIZE when * compiling. @@ -86,20 +86,10 @@ class dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. */ - explicit dataPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit dataPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new data Publisher object. * @@ -107,20 +97,10 @@ class dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. */ - dataPublisher(Logger& baseLogger, Client* inClient, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + dataPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); /** * @brief Destroy the data Publisher object - no action is taken. */ @@ -145,30 +125,19 @@ class dataPublisher { */ void attachToLogger(Logger& baseLogger); /** - * @brief Set the parameters for frequency of sending and any offset, if - * needed. + * @brief Sets the interval (in units of the logging interval) between + * attempted data transmissions * - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note These parameters are not currently used! + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. */ - void setSendFrequency(uint8_t sendEveryX, uint8_t sendOffset); + void setSendInterval(int sendEveryX); /** * @brief Begin the publisher - linking it to the client and logger. * * This can be used as an alternative to adding the logger and client in the - * constructor. This is slightly "safer" because we expect the publishers - * to be created in the "global scope" and we cannot control the order in - * which objects in that global scope will be created. That is, we cannot - * guarantee that the logger will actually be created before the publisher - * that wants to attach to it unless we wait to attach the publisher until - * in the setup or loop function of the main program. In reality, it is - * very unlikely that this is necessary. + * constructor. * * @param baseLogger The logger supplying the data to be published * @param inClient An Arduino client instance to use to print data to. @@ -186,13 +155,7 @@ class dataPublisher { * logger. * * This can be used as an alternative to adding the logger and client in the - * constructor. This is slightly "safer" because we expect the publishers - * to be created in the "global scope" and we cannot control the order in - * which objects in that global scope will be created. That is, we cannot - * guarantee that the logger will actually be created before the publisher - * that wants to attach to it unless we wait to attach the publisher until - * in the setup or loop function of the main program. In reality, it is - * very unlikely that this is necessary. + * constructor. * * @param baseLogger The logger supplying the data to be published */ @@ -280,40 +243,54 @@ class dataPublisher { Client* _inClient = nullptr; /** - * @brief A buffer for outgoing data. + * @brief The buffer for outgoing data. */ static char txBuffer[MS_SEND_BUFFER_SIZE]; /** - * @brief Get the number of empty spots in the buffer. + * @brief The pointer to the client instance the TX buffer is writing to. + */ + static Client* txBufferOutClient; + /** + * @brief The number of used characters in the TX buffer. + */ + static size_t txBufferLen; + /** + * @brief Initialize the TX buffer to be empty and start writing to the + * given client. * - * @return **int** The number of available characters in the buffer + * @param outClient The client to transmit to. */ - static int bufferFree(void); + static void txBufferInit(Client* outClient); /** - * @brief Fill the TX buffer with nulls ('\0'). + * @brief Append the given data to the TX buffer, flushing if necessary. + * + * @param data The data start pointer. + * @param length The number of bytes to add. */ - static void emptyTxBuffer(void); + static void txBufferAppend(const char* data, size_t length); /** - * @brief Write the TX buffer to a stream and also to the debugging - * port. + * @brief Append the given string to the TX buffer, flushing if necessary. * - * @param stream A pointer to an Arduino Stream instance to use to print - * data - * @param addNewLine True to add a new line character ("\n") at the end of - * the print + * @param s The null-terminated string to append. */ - static void printTxBuffer(Stream* stream, bool addNewLine = false); - + static void txBufferAppend(const char* s); + /** + * @brief Append the given char to the TX buffer, flushing if necessary. + * + * @param c The char to append. + */ + static void txBufferAppend(char c); /** - * @brief Unimplemented; intended for future use to enable caching and bulk - * publishing. + * @brief Write the TX buffer contents to the initialized stream and also to + * the debugging port. */ - uint8_t _sendEveryX = 1; + static void txBufferFlush(); + /** - * @brief Unimplemented; intended for future use to enable publishing data - * at a time slightly delayed from when it is collected. + * @brief Interval (in units of the logging interval) between + * attempted data transmissions. Not respected by all publishers. */ - uint8_t _sendOffset = 0; + int _sendEveryX = 1; // Basic chunks of HTTP /** diff --git a/src/modems/DigiXBee.cpp b/src/modems/DigiXBee.cpp index f179a04ad..0bfd930e1 100644 --- a/src/modems/DigiXBee.cpp +++ b/src/modems/DigiXBee.cpp @@ -1,7 +1,8 @@ /** * @file DigiXBee.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the DigiXBee class. @@ -27,7 +28,7 @@ DigiXBee::~DigiXBee() {} // Create the wake and sleep methods for the modem // These can be functions of any type and must return a boolean // After enabling pin sleep, the sleep request pin is held `LOW` to keep the -// XBee on Enable pin sleep in the setup function or using XCTU prior to +// XBee on. Enable pin sleep in the setup function or using XCTU prior to // connecting the XBee bool DigiXBee::modemWakeFxn(void) { if (_modemSleepRqPin >= 0) { diff --git a/src/modems/DigiXBee.h b/src/modems/DigiXBee.h index bc72bfc0a..22ed69fdb 100644 --- a/src/modems/DigiXBee.h +++ b/src/modems/DigiXBee.h @@ -1,7 +1,8 @@ /** * @file DigiXBee.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DigiXBee modem subclass of loggerModem, which itself is a @@ -31,6 +32,18 @@ * * @section modem_digi_mayfly-and-digi-xbee-connections Mayfly and Digi XBee Connections * + * @subsection modem_digi_raw_pins_1x Pin Numbers for connecting Digi XBee's Directly to a Mayfly v1.x + * + * This applies to _all_ Digi XBees and XBee3's when attached directly to the Mayfly's bee slot. + * @code{cpp} + * const int8_t modemVccPin = 18; // MCU pin controlling modem power + * const bool useCTSforStatus = true; // Flag to use the XBee `CTS` pin for status + * const int8_t modemStatusPin = 19; // MCU pin used to read modem status + * const int8_t modemResetPin = A5; // MCU pin connected to modem reset pin + * const int8_t modemSleepRqPin = 23; // MCU pin used for modem sleep/wake request + * const int8_t modemLEDPin = redLED; // MCU pin connected an LED to show modem status + * @endcode + * * @subsection modem_digi_raw_pins Pin Numbers for connecting Digi XBee's Directly to a Mayfly v0.3-v0.5c * * This applies to _all_ Digi XBees and XBee3's when attached directly to the Mayfly's bee slot. @@ -96,7 +109,7 @@ * - the `ON/SLEEP_N/DIO9` will be `HIGH` when the XBee is awake * (ie, yes, I am not sleeping) * - but the `CTS_N/DIO7` will be `LOW` when the - * board is away (ie, no it's not not clear to send). + * board is awake (ie, no it's not not clear to send). * * To use the `CTS_N/DIO7` as the status indicator, set useCTSStatus to true in * the constructor. diff --git a/src/modems/DigiXBee3GBypass.cpp b/src/modems/DigiXBee3GBypass.cpp index 6b494aaa6..9b5906056 100644 --- a/src/modems/DigiXBee3GBypass.cpp +++ b/src/modems/DigiXBee3GBypass.cpp @@ -1,7 +1,8 @@ /** * @file DigiXBee3GBypass.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the DigiXBee3GBypass class. diff --git a/src/modems/DigiXBee3GBypass.h b/src/modems/DigiXBee3GBypass.h index 0e793952d..c9767e34b 100644 --- a/src/modems/DigiXBee3GBypass.h +++ b/src/modems/DigiXBee3GBypass.h @@ -1,7 +1,8 @@ /** * @file DigiXBee3GBypass.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DigiXBee3GBypass subclass of the DigiXBee class for Digi diff --git a/src/modems/DigiXBeeCellularTransparent.cpp b/src/modems/DigiXBeeCellularTransparent.cpp index 69694405f..02eed366e 100644 --- a/src/modems/DigiXBeeCellularTransparent.cpp +++ b/src/modems/DigiXBeeCellularTransparent.cpp @@ -1,7 +1,8 @@ /** * @file DigiXBeeCellularTransparent.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * @author Greg Cutrell * @@ -259,37 +260,59 @@ bool DigiXBeeCellularTransparent::updateModemMetadata(void) { // Initialize variable int16_t signalQual = -9999; + MS_DBG(F("Modem polling settings:"), String(_pollModemMetaData, BIN)); + + // if not enabled don't collect data + if (_pollModemMetaData == 0) { + MS_DBG(F("No modem metadata to update")); + return false; + } + // Enter command mode only once - MS_DBG(F("Entering Command Mode:")); + MS_DBG(F("Entering Command Mode to update modem metadata:")); gsmModem.commandMode(); - // Try for up to 15 seconds to get a valid signal quality - // NOTE: We can't actually distinguish between a bad modem response, no - // modem response, and a real response from the modem of no service/signal. - // The TinyGSM getSignalQuality function returns the same "no signal" - // value (99 CSQ or 0 RSSI) in all 3 cases. - uint32_t startMillis = millis(); - do { - MS_DBG(F("Getting signal quality:")); - signalQual = gsmModem.getSignalQuality(); - MS_DBG(F("Raw signal quality:"), signalQual); - if (signalQual != 0 && signalQual != -9999) break; - delay(250); - } while ((signalQual == 0 || signalQual == -9999) && - millis() - startMillis < 15000L && success); + if ((_pollModemMetaData & MODEM_RSSI_ENABLE_BITMASK) == + MODEM_RSSI_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) == + MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) { // Try for up to 15 seconds + // to get a valid signal + // quality + // NOTE: We can't actually distinguish between a bad modem response, no + // modem response, and a real response from the modem of no + // service/signal. The TinyGSM getSignalQuality function returns the + // same "no signal" value (99 CSQ or 0 RSSI) in all 3 cases. + uint32_t startMillis = millis(); + do { + MS_DBG(F("Getting signal quality:")); + signalQual = gsmModem.getSignalQuality(); + MS_DBG(F("Raw signal quality:"), signalQual); + if (signalQual != 0 && signalQual != -9999) break; + delay(250); + } while ((signalQual == 0 || signalQual == -9999) && + millis() - startMillis < 15000L && success); - // Convert signal quality to RSSI - loggerModem::_priorRSSI = signalQual; - MS_DBG(F("CURRENT RSSI:"), signalQual); - loggerModem::_priorSignalPercent = getPctFromRSSI(signalQual); - MS_DBG(F("CURRENT Percent signal strength:"), getPctFromRSSI(signalQual)); + // Convert signal quality to RSSI + loggerModem::_priorRSSI = signalQual; + MS_DBG(F("CURRENT RSSI:"), signalQual); + loggerModem::_priorSignalPercent = getPctFromRSSI(signalQual); + MS_DBG(F("CURRENT Percent signal strength:"), + getPctFromRSSI(signalQual)); + } else { + MS_DBG(F("Polling for both RSSI and signal strength is disabled")); + } - MS_DBG(F("Getting chip temperature:")); - loggerModem::_priorModemTemp = getModemChipTemperature(); - MS_DBG(F("CURRENT Modem temperature:"), loggerModem::_priorModemTemp); + if ((_pollModemMetaData & MODEM_TEMPERATURE_ENABLE_BITMASK) == + MODEM_TEMPERATURE_ENABLE_BITMASK) { + MS_DBG(F("Getting chip temperature:")); + loggerModem::_priorModemTemp = getModemChipTemperature(); + MS_DBG(F("CURRENT Modem temperature:"), loggerModem::_priorModemTemp); + } else { + MS_DBG(F("Polling for modem chip temperature is disabled")); + } // Exit command modem - MS_DBG(F("Leaving Command Mode:")); + MS_DBG(F("Leaving Command Mode after updating modem metadata:")); gsmModem.exitCommand(); return success; diff --git a/src/modems/DigiXBeeCellularTransparent.h b/src/modems/DigiXBeeCellularTransparent.h index 26ef52fc7..602e2f3a3 100644 --- a/src/modems/DigiXBeeCellularTransparent.h +++ b/src/modems/DigiXBeeCellularTransparent.h @@ -1,7 +1,8 @@ /** * @file DigiXBeeCellularTransparent.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * @author Greg Cutrell * diff --git a/src/modems/DigiXBeeLTEBypass.cpp b/src/modems/DigiXBeeLTEBypass.cpp index 4873c1f4a..3b32264a9 100644 --- a/src/modems/DigiXBeeLTEBypass.cpp +++ b/src/modems/DigiXBeeLTEBypass.cpp @@ -1,7 +1,8 @@ /** * @file DigiXBeeLTEBypass.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the DigiXBeeLTEBypass class. diff --git a/src/modems/DigiXBeeLTEBypass.h b/src/modems/DigiXBeeLTEBypass.h index bd6d2853f..0f473dce7 100644 --- a/src/modems/DigiXBeeLTEBypass.h +++ b/src/modems/DigiXBeeLTEBypass.h @@ -1,7 +1,8 @@ /** * @file DigiXBeeLTEBypass.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DigiXBeeLTEBypass subclass of the DigiXBee class for Digi diff --git a/src/modems/DigiXBeeWifi.cpp b/src/modems/DigiXBeeWifi.cpp index cb782f0bf..a874915ab 100644 --- a/src/modems/DigiXBeeWifi.cpp +++ b/src/modems/DigiXBeeWifi.cpp @@ -1,7 +1,8 @@ /** * @file DigiXBeeWifi.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the DigiXBeeWifi class. @@ -15,7 +16,8 @@ DigiXBeeWifi::DigiXBeeWifi(Stream* modemStream, int8_t powerPin, int8_t statusPin, bool useCTSStatus, int8_t modemResetPin, int8_t modemSleepRqPin, - const char* ssid, const char* pwd) + const char* ssid, const char* pwd, + bool maintainAssociation) : DigiXBee(powerPin, statusPin, useCTSStatus, modemResetPin, modemSleepRqPin), #ifdef MS_DIGIXBEEWIFI_DEBUG_DEEP @@ -26,7 +28,8 @@ DigiXBeeWifi::DigiXBeeWifi(Stream* modemStream, int8_t powerPin, #endif gsmClient(gsmModem), _ssid(ssid), - _pwd(pwd) { + _pwd(pwd), + _maintainAssociation(maintainAssociation) { } // Destructor @@ -35,7 +38,53 @@ DigiXBeeWifi::~DigiXBeeWifi() {} MS_IS_MODEM_AWAKE(DigiXBeeWifi); MS_MODEM_WAKE(DigiXBeeWifi); -MS_MODEM_CONNECT_INTERNET(DigiXBeeWifi); + +// This is different MS_MODEM_CONNECT_INTERNET in that it doesn't attempt to +// resend credentials +bool DigiXBeeWifi::connectInternet(uint32_t maxConnectionTime) { + bool success = true; + + /** Power up, if necessary */ + bool wasPowered = true; + if (_millisPowerOn == 0) { + modemPowerUp(); + wasPowered = false; + } + + /** Check if the modem was awake, wake it if not */ + bool wasAwake = isModemAwake(); + if (!wasAwake) { + MS_DBG(F("Waiting for modem to boot after power on ...")); + while (millis() - _millisPowerOn < _wakeDelayTime_ms) { /** wait */ + } + MS_DBG(F("Waking up the modem to connect to the internet ...")); + success &= modemWake(); + } else { + MS_DBG(F("Modem was already awake and should be ready.")); + } + + if (success) { + MS_START_DEBUG_TIMER + MS_DBG(F("\nAttempting to connect to WiFi without sending new " + "credentials...")); + if (!(gsmModem.isNetworkConnected())) { + if (!gsmModem.waitForNetwork(maxConnectionTime)) { + PRINTOUT(F("... WiFi connection failed")); + success = false; + } + } + MS_DBG(F("... WiFi connected after"), MS_PRINT_DEBUG_TIMER, + F("milliseconds!")); + } + if (!wasPowered) { + MS_DBG(F("Modem was powered to connect to the internet! " + "Remember to turn it off when you're done.")); + } else if (!wasAwake) { + MS_DBG(F("Modem was woken up to connect to the internet! " + "Remember to put it to sleep when you're done.")); + } + return success; +} MS_MODEM_IS_INTERNET_AVAILABLE(DigiXBeeWifi); MS_MODEM_GET_MODEM_BATTERY_DATA(DigiXBeeWifi); @@ -46,32 +95,104 @@ bool DigiXBeeWifi::extraModemSetup(void) { /** First run the TinyGSM init() function for the XBee. */ MS_DBG(F("Initializing the XBee...")); success &= gsmModem.init(); + if (!success) { MS_DBG(F("Failed TinyGSM init")); } gsmClient.init(&gsmModem); _modemName = gsmModem.getModemName(); /** Then enter command mode to set pin outputs. */ MS_DBG(F("Putting XBee into command mode...")); if (gsmModem.commandMode()) { + MS_DBG(F("Getting Detailed Modem Version...")); + + gsmModem.getSeries(); + _modemName = gsmModem.getModemName(); + String xbeeSnLow = gsmModem.sendATGetString( + GFP("SL")); // Request Module MAC/Serial Number Low + String xbeeSnHigh = gsmModem.sendATGetString( + GFP("SH")); // Request Module MAC/Serial Number High + _modemSerialNumber = xbeeSnHigh + xbeeSnLow; + _modemHwVersion = + gsmModem.sendATGetString(GFP("HV")); // Request Module Hw Version + _modemFwVersion = + gsmModem.sendATGetString(GFP("VR")); // Firmware Version + PRINTOUT(F("Digi XBee"), _modemName, F("Mac/SN"), xbeeSnHigh, xbeeSnLow, + F("HwVer"), _modemHwVersion, F("FwVer"), _modemFwVersion); + + bool changesMade = false; + MS_DBG(F("Enabling XBee Pin Pullups...")); + // Leave all unused pins disconnected. Use the PR command to pull + // all of the inputs on the device high using 40 k internal pull-up + // resistors. You do not need a specific treatment for unused + // outputs. + // Mask Bit Description + // 1 0001 0 TH11 DIO4 + // 1 0002 1 TH17 DIO3 + // 1 0004 2 TH18 DIO2 + // 1 0008 3 TH19 DIO1 + // 1 0010 4 TH20 DIO0 + // 1 0020 5 TH16 DIO6/RTS + // 0 0040 6 TH09 DIO8/DTR/Sleep Request + // 0 0080 7 TH03 DIN + // 1 0100 8 TH15 DIO5/Associate + // 0 0200 9 TH13 DIO9/- OnSLEEP + // 1 0400 10 TH04 DIO12 + // 1 0800 11 TH06 DIO10/PWM RSSI + // 1 1000 12 TH07 DIO11/PWM1 + // 1 2000 13 TH12 DIO7/-CTR + // 0 4000 14 TH02 DIO13/DOUT + // 3D3F + bool changedRP = gsmModem.changeSettingIfNeeded(GF("PR"), "3D3F"); + changesMade |= changedRP; + if (changedRP) { + MS_DBG(F("Pin pullup bits changed to"), F("3D3F")); + } else { + MS_DEEP_DBG(F("Pin pullup bits not changed")); + } + + MS_DBG(F("Setting I/O Pins...")); - /** Enable pin sleep functionality on `DIO9`. + // To use sleep pins they physically need to be enabled. + /** Enable pin sleep functionality on `DIO8` if a pin is assigned. * NOTE: Only the `DTR_N/SLEEP_RQ/DIO8` pin (9 on the bee socket) can be * used for this pin sleep/wake. */ - gsmModem.sendAT(GF("D8"), 1); - success &= gsmModem.waitResponse() == 1; - /** Enable status indication on `DIO9` - it will be HIGH when the XBee - * is awake. + bool changedD8 = gsmModem.changeSettingIfNeeded(GF("D8"), + _modemSleepRqPin >= 0); + changesMade |= changedD8; + if (changedD8) { + MS_DBG(F("DTR_N/SLEEP_RQ/DIO8 changed to"), _modemSleepRqPin >= 0); + } else { + MS_DEEP_DBG(F("DTR_N/SLEEP_RQ/DIO8 not changed")); + } + + /** Enable status indication on `DIO9` if a pin is assigned - it will be + * HIGH when the XBee is awake. * NOTE: Only the `ON/SLEEP_N/DIO9` pin (13 on the bee socket) can be * used for direct status indication. */ - gsmModem.sendAT(GF("D9"), 1); - success &= gsmModem.waitResponse() == 1; - /** Enable CTS on `DIO7` - it will be `LOW` when it is clear to send - * data to the XBee. This can be used as proxy for status indication if - * that pin is not readable. + bool changedD9 = gsmModem.changeSettingIfNeeded(GF("D9"), + _statusPin >= 0); + changesMade |= changedD9; + if (changedD9) { + MS_DBG(F("ON/SLEEP_N/DIO9 changed to"), _statusPin >= 0); + } else { + MS_DEEP_DBG(F("ON/SLEEP_N/DIO9 not changed")); + } + + /** Enable CTS on `DIO7` if a pin is assigned - it will be `LOW` when + * it is clear to send data to the XBee. This can be used as proxy for + * status indication if that pin is not readable. * NOTE: Only the `CTS_N/DIO7` pin (12 on the bee socket) can be used * for CTS. */ - gsmModem.sendAT(GF("D7"), 1); - success &= gsmModem.waitResponse() == 1; - /** Enable association indication on `DIO5` - this is should be directly - * attached to an LED if possible. + bool changedD7 = gsmModem.changeSettingIfNeeded( + GF("D7"), _statusPin >= 0 && !_statusLevel); + changesMade |= changedD7; + if (changedD7) { + MS_DBG(F("CTS_N/DIO7 changed to"), + _statusPin >= 0 && !_statusLevel); + } else { + MS_DEEP_DBG(F("CTS_N/DIO7 not changed")); + } + + /** Enable association indication on `DIO5` - this is should be + * directly attached to an LED if possible. * - Solid light indicates no connection * - Single blink indicates connection * - double blink indicates connection but failed TCP link on last @@ -79,57 +200,161 @@ bool DigiXBeeWifi::extraModemSetup(void) { * * NOTE: Only the `Associate/DIO5` pin (15 on the bee socket) can be * used for this function. */ - gsmModem.sendAT(GF("D5"), 1); - success &= gsmModem.waitResponse() == 1; - /** Enable RSSI PWM output on `DIO10` - this should be directly attached - * to an LED if possible. A higher PWM duty cycle (and thus brighter - * LED) indicates better signal quality. - * NOTE: Only the `DIO10/PWM0` pin (6 on the bee socket) can be used for - * this function. */ - gsmModem.sendAT(GF("P0"), 1); - success &= gsmModem.waitResponse() == 1; - /** Enable pin sleep on the XBee. */ - MS_DBG(F("Setting Sleep Options...")); - gsmModem.sendAT(GF("SM"), 1); - success &= gsmModem.waitResponse() == 1; - /** Disassociate from the network for the lowest power deep sleep. */ - gsmModem.sendAT(GF("SO"), 200); - success &= gsmModem.waitResponse() == 1; + bool changedD5 = gsmModem.changeSettingIfNeeded(GF("D5"), 1); + changesMade |= changedD5; + if (changedD5) { + MS_DBG(F("Associate/DIO5 changed to"), 1); + } else { + MS_DEEP_DBG(F("Associate/DIO5 not changed")); + } + + /** Enable RSSI PWM output on `DIO10` - this should be directly + * attached to an LED if possible. A higher PWM duty cycle (and + * thus brighter LED) indicates better signal quality. NOTE: Only + * the `DIO10/PWM0` pin (6 on the bee socket) can be used for this + * function. */ + bool changedP0 = gsmModem.changeSettingIfNeeded(GF("D5"), 1); + changesMade |= changedP0; + if (changedP0) { + MS_DBG(F("DIO10/PWM0 changed to"), 1); + } else { + MS_DEEP_DBG(F("ADIO10/PWM0 not changed")); + } + + /** Put the XBee in pin sleep mode in conjuction with D8=1 */ + // From the S6B User Guide: + // 0 - Normal. In this mode the device never sleeps. + // 1 - Pin Sleep. In this mode the device honors the SLEEP_RQ pin. + // Set D8 (DIO8 Configuration) to the sleep request function: 1. + // 4 - Cyclic Sleep. In this mode the device repeatedly sleeps for the + // value specified by SP and spends ST time awake. + // 5 - Cyclic Sleep with Pin Wake. In this mode the device acts as in + // Cyclic Sleep but does not sleep if the SLEEP_RQ pin is inactive, + // allowing the device to be kept awake or woken by the connected + // system. + bool changedSM = gsmModem.changeSettingIfNeeded(GF("SM"), + _modemSleepRqPin >= 0); + changesMade |= changedSM; + if (changedSM) { + MS_DBG(F("Sleep mode changed to"), _modemSleepRqPin >= 0); + } else { + MS_DEEP_DBG(F("Sleep mode not changed")); + } + // Disassociate from the network for the lowest power deep sleep. + // From S6B User Guide: + // 0x40 - Stay associated with AP during sleep. Draw more current + // (+10mA?) during sleep with this option enabled, but also avoid data + // loss. [0x40 = 64] + // 0x100 - For cyclic sleep, ST specifies the time before returning + // to sleep. With this bit set, new receptions from either the serial or + // the RF port do not restart the ST timer. Current implementation does + // not support this bit being turned off. [0x100 = 256] + bool changedSO = gsmModem.changeSettingIfNeeded( + GF("SO"), _maintainAssociation ? "40" : "100"); + changesMade |= changedSO; + if (changedSO) { + MS_DBG(F("Sleep options changed to"), + _maintainAssociation ? "0x40" : "0x100"); + } else { + MS_DEEP_DBG(F("Sleep options not changed")); + } + + /** Write pin and sleep options to flash and apply them, if needed. */ + if (changesMade) { + MS_DBG(F("Applying changes to pin and sleep options...")); + gsmModem.writeChanges(); + } else { + MS_DBG(F("No pin or sleep option changes to apply")); + } + MS_DBG(F("Setting Wifi Network Options...")); - /** Set the socket timeout to 10s (this is default). */ - gsmModem.sendAT(GF("TM"), 64); - success &= gsmModem.waitResponse() == 1; - /** Save the network connection parameters. */ + // Put the network connection parameters into flash + // NOTE: This will write to the flash every time if there is a password + // set! success &= gsmModem.networkConnect(_ssid, _pwd); - MS_DBG(F("Ensuring XBee is in transparent mode...")); - /* Make sure we're really in transparent mode. */ - gsmModem.sendAT(GF("AP0")); - success &= gsmModem.waitResponse() == 1; + if (!success) { + MS_DBG(F("Fail Connect "), success); + success = true; + } + + // Set to TCP mode + changesMade = false; + bool changedIPMode = gsmModem.changeSettingIfNeeded(GF("IP"), 1); + changesMade |= changedIPMode; + if (changedIPMode) { + MS_DBG(F("IP mode changed to"), 1); + } else { + MS_DEEP_DBG(F("IP mode not changed")); + } + + + /** Set the socket timeout to 10s (this is default).*/ + bool changedTM = gsmModem.changeSettingIfNeeded(GF("TM"), "64"); + changesMade |= changedTM; + if (changedTM) { + MS_DBG(F("Socket timeout changed to"), F("0x64")); + } else { + MS_DEEP_DBG(F("Socket timeout not changed")); + } + + /** Set the destination IP to 0 (this is default). */ + bool changedDL = gsmModem.changeSettingIfNeeded(GF("DL"), + GF("0.0.0.0")); + changesMade |= changedDL; + if (changedDL) { + MS_DBG(F("Destination IP changed to"), F("0.0.0.0")); + } else { + MS_DEEP_DBG(F("Destination IP not changed")); + } + /** Write all changes to flash and apply them. */ - MS_DBG(F("Applying changes...")); - gsmModem.writeChanges(); - /** Finally, exit command mode. */ + if (changesMade) { + MS_DBG(F("Applying changes to socket times...")); + success &= gsmModem.writeChanges(); + } + + if (success) { + MS_DBG(F("Successfully setup Wifi Network"), _ssid); + } else { + MS_DBG(F("Failed Setting WiFi"), _ssid); + } + + // Since this is the only time we're going to send the credentials, + // confirm that we can connect to the network and get both an IP and DNS + // address. + if (!(gsmModem.isNetworkConnected())) { + if (!gsmModem.waitForNetwork()) { + PRINTOUT( + F("... Initial WiFi connection failed - resetting module")); + loggerModem::modemHardReset(); + delay(50); + success = false; + } else { + PRINTOUT(F("... Initial WiFi connection succeeded!")); + success = true; + } + } else { + PRINTOUT(F("... Initial WiFi connection succeeded!")); + success = true; + } gsmModem.exitCommand(); - /** Force restart the modem to make sure all settings take. */ - MS_DBG(F("Restarting XBee...")); - success &= gsmModem.restart(); - } else { - success = false; } - if (success) { - MS_DBG(F("... setup successful!")); - } else { - MS_DBG(F("... setup failed!")); - } return success; } void DigiXBeeWifi::disconnectInternet(void) { - // Wifi XBee doesn't like to disconnect AT ALL, so we're doing nothing - // If you do disconnect, you must power cycle before you can reconnect - // to the same access point. + // Ensure Wifi XBee IP socket torn down by forcing connection to + // localhost IP For A XBee S6B bug, then force restart. + + String oldRemoteIp = gsmClient.remoteIP(); + IPAddress newHostIp = IPAddress(127, 0, 0, 1); // localhost + gsmClient.connect(newHostIp, 80); + MS_DBG(gsmModem.getBeeName(), oldRemoteIp, F("disconnectInternet set to"), + gsmClient.remoteIP()); + + gsmModem.restart(); } @@ -143,26 +368,47 @@ uint32_t DigiXBeeWifi::getNISTTime(void) { gsmClient.stop(); - // Try up to 12 times to get a timestamp from NIST - for (uint8_t i = 0; i < 12; i++) { - // Must ensure that we do not ping the daylight more than once every 4 - // seconds. NIST clearly specifies here that this is a requirement for - // all software that accesses its servers: + // Try up to 4 NIST IP addresses attempting to get a timestamp from NIST +#if !defined NIST_SERVER_RETRYS +#define NIST_SERVER_RETRYS 4 +#endif // NIST_SERVER_RETRYS + + for (uint8_t i = 0; i < NIST_SERVER_RETRYS; i++) { + // Must ensure that we do not ping the daylight servers more than once + // every 4 seconds. NIST clearly specifies here that this is a + // requirement for all software that accesses its servers: // https://tf.nist.gov/tf-cgi/servers.cgi while (millis() < _lastNISTrequest + 4000) { // wait } // Make TCP connection + // Uses "TIME" protocol on port 37 NIST: This protocol is expensive, + // since it uses the complete tcp machinery to transmit only 32 bits + // of data. FUTURE Users are *strongly* encouraged to upgrade to the + // network time protocol (NTP), which is both more accurate and more + // robust. MS_DBG(F("\nConnecting to NIST daytime Server")); bool connectionMade = false; - // This is the IP address of time-e-wwv.nist.gov + // These are is the IP address of time-[a,b,c,d]-wwv.nist.gov // XBee's address lookup falters on time.nist.gov + +#define TIME_PROTOCOL_PORT 37 +#define IP_STR_LEN 18 + const char ipAddr[NIST_SERVER_RETRYS][IP_STR_LEN] = { + {"132, 163, 97, 1"}, + {"132, 163, 97, 2"}, + {"132, 163, 97, 3"}, + {"132, 163, 97, 4"}}; + IPAddress ip1(132, 163, 97, 1); // Initialize + ip1.fromString(ipAddr[i]); + MS_DBG(F("NIST lookup mdmIP["), i, "/", NIST_SERVER_RETRYS, + F("] with "), ip1); + // NOTE: This "connect" only sets up the connection parameters, the TCP // socket isn't actually opened until we first send data (the '!' below) - IPAddress ip(132, 163, 97, 6); - connectionMade = gsmClient.connect(ip, 37); + connectionMade = gsmClient.connect(ip1, TIME_PROTOCOL_PORT); // Need to send something before connection is made gsmClient.println('!'); @@ -200,31 +446,13 @@ bool DigiXBeeWifi::getModemSignalQuality(int16_t& rssi, int16_t& percent) { percent = -9999; rssi = -9999; - // NOTE: using Google doesn't work because there's no reply - MS_DBG(F("Opening connection to NIST to check connection strength...")); - // This is the IP address of time-c-g.nist.gov - // XBee's address lookup falters on time.nist.gov - // NOTE: This "connect" only sets up the connection parameters, the TCP - // socket isn't actually opened until we first send data (the '!' below) - IPAddress ip(132, 163, 97, 6); - gsmClient.connect(ip, 37); - // Wait so NIST doesn't refuse us! - while (millis() < _lastNISTrequest + 4000) { - // wait - } - // Need to send something before connection is made - gsmClient.println('!'); - uint32_t start = millis(); - delay(100); // Need this delay! Can get away with 50, but 100 is safer. - while (gsmClient && gsmClient.available() < 4 && millis() - start < 5000L) { - // wait - } + // Assume measurement from previous connection // Get signal quality // NOTE: We can't actually distinguish between a bad modem response, no // modem response, and a real response from the modem of no service/signal. - // The TinyGSM getSignalQuality function returns the same "no signal" - // value (99 CSQ or 0 RSSI) in all 3 cases. + // The TinyGSM getSignalQuality function returns the same "no signal" value + // (99 CSQ or 0 RSSI) in all 3 cases. MS_DBG(F("Getting signal quality:")); signalQual = gsmModem.getSignalQuality(); MS_DBG(F("Raw signal quality:"), signalQual); @@ -253,45 +481,183 @@ bool DigiXBeeWifi::updateModemMetadata(void) { loggerModem::_priorBatteryPercent = -9999; loggerModem::_priorModemTemp = -9999; - // Initialize variable - int16_t rssi = -9999; - int16_t percent = -9999; - uint16_t volt = 9999; - - // Try up to 5 times to get a signal quality - that is, ping NIST 5 times - // and see if the value updates - int8_t num_pings_remaining = 5; - do { - getModemSignalQuality(rssi, percent); - MS_DBG(F("Raw signal quality:"), rssi); - if (percent != 0 && percent != -9999) break; - num_pings_remaining--; - } while ((percent == 0 || percent == -9999) && num_pings_remaining); - - // Convert signal quality to RSSI - loggerModem::_priorRSSI = rssi; - loggerModem::_priorSignalPercent = percent; + MS_DBG(F("Modem polling settings:"), String(_pollModemMetaData, BIN)); + // if not enabled don't collect data + if (_pollModemMetaData == 0) { + MS_DBG(F("No modem metadata to update")); + return false; + } - // Enter command mode only once for temp and battery - MS_DBG(F("Entering Command Mode:")); + // Enter command mode only once + MS_DBG(F("Entering Command Mode to update modem metadata:")); success &= gsmModem.commandMode(); - MS_DBG(F("Getting input voltage:")); - volt = gsmModem.getBattVoltage(); - MS_DBG(F("CURRENT Modem input battery voltage:"), volt); - if (volt != 9999) - loggerModem::_priorBatteryVoltage = static_cast(volt); - else - loggerModem::_priorBatteryVoltage = static_cast(-9999); + if ((_pollModemMetaData & MODEM_RSSI_ENABLE_BITMASK) == + MODEM_RSSI_ENABLE_BITMASK || + (_pollModemMetaData & MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) == + MODEM_PERCENT_SIGNAL_ENABLE_BITMASK) { + // Assume a signal has already been established. + // Try to get a valid signal quality + // NOTE: We can't actually distinguish between a bad modem response, no + // modem response, and a real response from the modem of no + // service/signal. The TinyGSM getSignalQuality function returns the + // same "no signal" value (99 CSQ or 0 RSSI) in all 3 cases. + + // Try up to 5 times to get a signal quality + int8_t num_trys_remaining = 5; + int16_t rssi = -9999; + do { + rssi = gsmModem.getSignalQuality(); + MS_DBG(F("Raw signal quality ("), num_trys_remaining, F("):"), + rssi); + if (rssi != 0 && rssi != -9999) break; + num_trys_remaining--; + } while ((rssi == 0 || rssi == -9999) && num_trys_remaining); + + + // Convert signal quality to a percent + loggerModem::_priorSignalPercent = getPctFromRSSI(rssi); + MS_DBG(F("CURRENT Percent signal strength:"), + loggerModem::_priorSignalPercent); + + loggerModem::_priorRSSI = rssi; + MS_DBG(F("CURRENT RSSI:"), rssi); + + success &= ((rssi != -9999) && (rssi != 0)); + } else { + MS_DBG(F("Polling for both RSSI and signal strength is disabled")); + } + - MS_DBG(F("Getting chip temperature:")); - loggerModem::_priorModemTemp = getModemChipTemperature(); - MS_DBG(F("CURRENT Modem temperature:"), loggerModem::_priorModemTemp); + if ((_pollModemMetaData & MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) == + MODEM_BATTERY_VOLTAGE_ENABLE_BITMASK) { + MS_DBG(F("Getting input voltage:")); + uint16_t volt_mV = 9999; + volt_mV = gsmModem.getBattVoltage(); + MS_DBG(F("CURRENT Modem battery (mV):"), volt_mV); + if (volt_mV != 9999) { + loggerModem::_priorBatteryVoltage = + static_cast(volt_mV / 1000); + } else { + loggerModem::_priorBatteryVoltage = static_cast(-9999); + } - // Exit command modem - MS_DBG(F("Leaving Command Mode:")); + success &= ((volt_mV != 9999) && (volt_mV != 0)); + } else { + MS_DBG(F("Polling for modem battery voltage is disabled")); + } + + if ((_pollModemMetaData & MODEM_TEMPERATURE_ENABLE_BITMASK) == + MODEM_TEMPERATURE_ENABLE_BITMASK) { + MS_DBG(F("Getting chip temperature:")); + float chip_temp = -9999; + chip_temp = getModemChipTemperature(); + MS_DBG(F("CURRENT Modem temperature(C):"), + loggerModem::_priorModemTemp); + if (chip_temp != -9999.f) { + loggerModem::_priorModemTemp = chip_temp; + } else { + loggerModem::_priorModemTemp = static_cast(-9999); + } + + success &= ((chip_temp != -9999.f) && (chip_temp != 0)); + } else { + MS_DBG(F("Polling for modem chip temperature is disabled")); + } + + // Exit command mode + MS_DBG(F("Leaving Command Mode after updating modem metadata:")); gsmModem.exitCommand(); + + // bump up the failure count if we didn't successfully update any of the + // metadata parameters + if (!success) { metadata_failure_count++; } + + // If the metadata update has failed more than the XBEE_RESET_THRESHOLD + // number of times, restart the modem for next time. This is likely to take + // over 2 seconds. + if (metadata_failure_count >= XBEE_RESET_THRESHOLD) { + metadata_failure_count = 0; // reset the count + PRINTOUT(F("updateModemMetadata forcing restart xbee...")); + gsmModem.restart(); + } + return success; } + + +// Az extensions +void DigiXBeeWifi::setWiFiId(const char* newSsid, bool copyId) { + uint8_t newSsid_sz = strlen(newSsid); + _ssid = newSsid; + if (copyId) { +/* Do size checks, allocate memory for the LoggerID, copy it there + * then set assignment. + */ +#define WIFI_SSID_MAX_sz 32 + if (newSsid_sz > WIFI_SSID_MAX_sz) { + char* WiFiId2 = (char*)newSsid; + PRINTOUT(F("\n\r LoggerModem:setWiFiId too long: Trimmed to "), + newSsid_sz); + WiFiId2[newSsid_sz] = 0; // Trim max size + newSsid_sz = WIFI_SSID_MAX_sz; + } + if (NULL == _ssid_buf) { + _ssid_buf = new char[newSsid_sz + 2]; // Allow for trailing 0 + } else { + PRINTOUT(F("\nLoggerModem::setWiFiId error - expected NULL ptr")); + } + if (NULL == _ssid_buf) { + // Major problem + PRINTOUT(F("\nLoggerModem::setWiFiId error -no buffer "), + _ssid_buf); + } else { + strcpy(_ssid_buf, newSsid); + _ssid = _ssid_buf; + //_ssid2 = _ssid_buf; + } + MS_DBG(F("\nsetWiFiId cp "), _ssid, " sz: ", newSsid_sz); + } +} + +void DigiXBeeWifi::setWiFiPwd(const char* newPwd, bool copyId) { + uint8_t newPwd_sz = strlen(newPwd); + _pwd = newPwd; + + if (copyId) { +/* Do size checks, allocate memory for the LoggerID, copy it there + * then set assignment. + */ +#define WIFI_PWD_MAX_sz 63 // Len 63 printable chars + 0 + if (newPwd_sz > WIFI_PWD_MAX_sz) { + char* pwd2 = (char*)newPwd; + PRINTOUT(F("\n\r LoggerModem:setWiFiPwd too long: Trimmed to "), + newPwd_sz); + pwd2[newPwd_sz] = 0; // Trim max size + newPwd_sz = WIFI_PWD_MAX_sz; + } + if (NULL == _pwd_buf) { + _pwd_buf = new char[newPwd_sz + 2]; // Allow for trailing 0 + } else { + PRINTOUT(F("\nLoggerModem::setWiFiPwd error - expected NULL ptr")); + } + if (NULL == _pwd_buf) { + // Major problem + PRINTOUT(F("\nLoggerModem::setWiFiPwd error -no buffer "), + _pwd_buf); + } else { + strcpy(_pwd_buf, newPwd); + _pwd = _pwd_buf; + } + MS_DEEP_DBG(F("\nsetWiFiPwd cp "), _ssid, " sz: ", newPwd_sz); + } +} + +String DigiXBeeWifi::getWiFiId(void) { + return _ssid; +} +String DigiXBeeWifi::getWiFiPwd(void) { + return _pwd; +} diff --git a/src/modems/DigiXBeeWifi.h b/src/modems/DigiXBeeWifi.h index 1354addea..9be12dc88 100644 --- a/src/modems/DigiXBeeWifi.h +++ b/src/modems/DigiXBeeWifi.h @@ -1,7 +1,8 @@ /** * @file DigiXBeeWifi.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DigiXBeeWifi subclass of the DigiXBee class for Digi S6B @@ -50,6 +51,10 @@ #define MS_DEBUGGING_STD "DigiXBeeWifi" #endif +#ifdef MS_DIGIXBEEWIFI_DEBUG_DEEP +#define MS_DEBUGGING_DEEP "DigiXBeeWifi" +#endif + /** @ingroup modem_digi_wifi */ /**@{*/ @@ -75,6 +80,12 @@ #include #endif +/** + * @brief This causes the Xbee to reset after this number of transmission + * attempts + */ +#define XBEE_RESET_THRESHOLD 4 + /** * @brief The class for the [Digi XBee](@ref modem_digi) * [S6B wifi](@ref modem_digi_wifi) module operating in Digi's "transparent" @@ -105,10 +116,15 @@ class DigiXBeeWifi : public DigiXBee { * reference. * @param ssid The wifi network ID. * @param pwd The wifi network password, assuming WPA2. + * @param maintainAssociation Whether to maintain association with the + * access point during sleep. Maitaining the association during sleep draws + * more current (+10mA?), but also allows a faster reconnection on the next + * wake. */ DigiXBeeWifi(Stream* modemStream, int8_t powerPin, int8_t statusPin, bool useCTSStatus, int8_t modemResetPin, - int8_t modemSleepRqPin, const char* ssid, const char* pwd); + int8_t modemSleepRqPin, const char* ssid, const char* pwd, + bool maintainAssociation = false); /** * @brief Destroy the Digi XBee Wifi object - no action taken */ @@ -128,6 +144,12 @@ class DigiXBeeWifi : public DigiXBee { bool updateModemMetadata(void) override; + // Access Management + void setWiFiId(const char* WiFiId, bool copyId = false); + void setWiFiPwd(const char* WiFiPwd, bool copyId = false); + String getWiFiId(void); + String getWiFiPwd(void); + #ifdef MS_DIGIXBEEWIFI_DEBUG_DEEP StreamDebugger _modemATDebugger; #endif @@ -158,6 +180,13 @@ class DigiXBeeWifi : public DigiXBee { private: const char* _ssid; const char* _pwd; + bool _maintainAssociation; + + // Access Management + char* _ssid_buf = NULL; + char* _pwd_buf = NULL; + + uint16_t metadata_failure_count = 0; }; /**@}*/ #endif // SRC_MODEMS_DIGIXBEEWIFI_H_ diff --git a/src/modems/EspressifESP32.h b/src/modems/EspressifESP32.h index 7cbe0468a..d136fec5e 100644 --- a/src/modems/EspressifESP32.h +++ b/src/modems/EspressifESP32.h @@ -1,7 +1,8 @@ /** * @file EspressifESP32.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the EspressifESP32 subclass of loggerModem which is merely a diff --git a/src/modems/EspressifESP8266.cpp b/src/modems/EspressifESP8266.cpp index d4a2bdb1e..3018c1261 100644 --- a/src/modems/EspressifESP8266.cpp +++ b/src/modems/EspressifESP8266.cpp @@ -1,7 +1,8 @@ /** * @file EspressifESP8266.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the EspressifESP8266 class. @@ -38,7 +39,7 @@ EspressifESP8266::~EspressifESP8266() {} MS_IS_MODEM_AWAKE(EspressifESP8266); MS_MODEM_WAKE(EspressifESP8266); -MS_MODEM_CONNECT_INTERNET(EspressifESP8266); +MS_MODEM_CONNECT_INTERNET(EspressifESP8266, ESP8266_RECONNECT_TIME_MS); MS_MODEM_DISCONNECT_INTERNET(EspressifESP8266); MS_MODEM_IS_INTERNET_AVAILABLE(EspressifESP8266); diff --git a/src/modems/EspressifESP8266.h b/src/modems/EspressifESP8266.h index 71ce94792..30775c230 100644 --- a/src/modems/EspressifESP8266.h +++ b/src/modems/EspressifESP8266.h @@ -1,7 +1,8 @@ /** * @file EspressifESP8266.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the EspressifESP8266 subclass of loggerModem which _SHOULD_ @@ -173,6 +174,12 @@ */ #define ESP8266_DISCONNECT_TIME_MS 500 +/** + * @brief The amount of time in ms it takes the ESP8266 to reconnect using saved + * credentials. + */ +#define ESP8266_RECONNECT_TIME_MS 2500 + // Included Dependencies #include "ModSensorDebugger.h" #undef MS_DEBUGGING_STD diff --git a/src/modems/LoggerModemMacros.h b/src/modems/LoggerModemMacros.h index 8fa3a4be4..2611ffc08 100644 --- a/src/modems/LoggerModemMacros.h +++ b/src/modems/LoggerModemMacros.h @@ -1,7 +1,8 @@ /** * @file LoggerModemMacros.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains PRE-ROCESSOR MACROS for use with logger modems. @@ -100,13 +101,14 @@ */ #define MS_MODEM_WAKE(specificModem) \ bool specificModem::modemWake(void) { \ - /* Power up */ \ - if (_millisPowerOn == 0) { modemPowerUp(); } \ - \ /** Set-up pin modes. \ Because the modem calls wake BEFORE the first setup, we must set \ the pin modes in the wake function. */ \ setModemPinModes(); \ + \ + /* Power up */ \ + if (_millisPowerOn == 0) { modemPowerUp(); } \ + \ if (millis() - _millisPowerOn < _wakeDelayTime_ms) { \ MS_DBG(F("Wait"), _wakeDelayTime_ms - (millis() - _millisPowerOn), \ F("ms longer for warm-up")); \ @@ -358,12 +360,16 @@ * wait for network registration, then provide the access point name, and then * establish a GPRS/EPS connection. * + * @note WiFi modems can frequently reconnect with saved credentials instead of + * sending new credentials each time. This function waits for an automatic + * connection to be made, if possible. + * * @param specificModem The modem subclass * * @return The text of a connectInternet(uint32_t maxConnectionTime) function * specific to a single modem subclass. */ -#define MS_MODEM_CONNECT_INTERNET(specificModem) \ +#define MS_MODEM_CONNECT_INTERNET(specificModem, auto_reconnect_time) \ bool specificModem::connectInternet(uint32_t maxConnectionTime) { \ bool success = true; \ \ @@ -387,24 +393,32 @@ MS_DBG(F("Modem was already awake and should be ready.")); \ } \ \ + /** Wait to see if a connection was made automatically from saved \ + * credentials */ \ if (success) { \ MS_START_DEBUG_TIMER \ - MS_DBG(F("\nAttempting to connect to WiFi network...")); \ + MS_DBG(F("\nWaiting"), auto_reconnect_time, \ + F("ms to see if WiFi connects without sending new " \ + "credentials...")); \ if (!(gsmModem.isNetworkConnected())) { \ - MS_DBG(F("Sending credentials...")); \ - for (uint8_t i = 0; i < 5; i++) { \ - if (gsmModem.networkConnect(_ssid, _pwd)) { break; } \ - } \ - MS_DBG(F("Waiting up to"), maxConnectionTime / 1000, \ - F("seconds for connection")); \ - if (!gsmModem.waitForNetwork(maxConnectionTime)) { \ - MS_DBG(F("... WiFi connection failed")); \ - return false; \ + /** If still not connected, send new credentials */ \ + if (!(gsmModem.waitForNetwork(auto_reconnect_time))) { \ + MS_DBG(F("Sending credentials...")); \ + for (uint8_t i = 0; i < 5; i++) { \ + if (gsmModem.networkConnect(_ssid, _pwd)) { break; } \ + } \ + MS_DBG(F("Waiting up to"), maxConnectionTime / 1000, \ + F("seconds for connection")); \ + if (!gsmModem.waitForNetwork(maxConnectionTime)) { \ + MS_DBG(F("... WiFi connection failed")); \ + return false; \ + } \ } \ } \ MS_DBG(F("... WiFi connected after"), MS_PRINT_DEBUG_TIMER, \ F("milliseconds!")); \ } \ + \ if (!wasPowered) { \ MS_DBG(F("Modem was powered to connect to the internet! " \ "Remember to turn it off when you're done.")); \ diff --git a/src/modems/QuectelBG96.cpp b/src/modems/QuectelBG96.cpp index 8b8a39e96..ca1530654 100644 --- a/src/modems/QuectelBG96.cpp +++ b/src/modems/QuectelBG96.cpp @@ -1,7 +1,8 @@ /** * @file QuectelBG96.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the QuectelBG96 class. diff --git a/src/modems/QuectelBG96.h b/src/modems/QuectelBG96.h index 00fca3d6b..94185ecd4 100644 --- a/src/modems/QuectelBG96.h +++ b/src/modems/QuectelBG96.h @@ -1,7 +1,8 @@ /** * @file QuectelBG96.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the QuectelBG96 subclass of loggerModem for Dragino, diff --git a/src/modems/SIMComSIM7000.cpp b/src/modems/SIMComSIM7000.cpp index dc3f90d06..026fcb93c 100644 --- a/src/modems/SIMComSIM7000.cpp +++ b/src/modems/SIMComSIM7000.cpp @@ -1,7 +1,8 @@ /** * @file SIMComSIM7000.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SIMComSIM7000 class. diff --git a/src/modems/SIMComSIM7000.h b/src/modems/SIMComSIM7000.h index 6ff7511c4..ad23daa76 100644 --- a/src/modems/SIMComSIM7000.h +++ b/src/modems/SIMComSIM7000.h @@ -1,7 +1,8 @@ /** * @file SIMComSIM7000.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SIMComSIM7000 subclass of loggerModem for diff --git a/src/modems/SIMComSIM7080.cpp b/src/modems/SIMComSIM7080.cpp index 4a644fe1a..834712154 100644 --- a/src/modems/SIMComSIM7080.cpp +++ b/src/modems/SIMComSIM7080.cpp @@ -1,7 +1,8 @@ /** * @file SIMComSIM7080.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SIMComSIM7080 class. @@ -58,7 +59,18 @@ bool SIMComSIM7080::modemWakeFxn(void) { digitalWrite(_modemSleepRqPin, _wakeLevel); delay(_wakePulse_ms); // >1s digitalWrite(_modemSleepRqPin, !_wakeLevel); - return gsmModem.waitResponse(30000L, GF("SMS Ready")) == 1; + int ready_response = gsmModem.waitResponse(30000L, GF("SMS Ready"), + GF("+CPIN: NOT INSERTED")); + if (ready_response == 1) { + MS_DBG(F("Got SMS Ready indicating modem is awake and ready")); + } else if (ready_response == 2) { + MS_DBG(F("Got +CPIN: NOT INSERTED indicating modem is awake and " + "ready but has no SIM card")); + } else { + MS_DBG(F("Didn't get expected finish URC for modem wake!")); + } + + return ready_response == 1 || ready_response == 2; } return true; } diff --git a/src/modems/SIMComSIM7080.h b/src/modems/SIMComSIM7080.h index 26a1d643d..ef0f10e2e 100644 --- a/src/modems/SIMComSIM7080.h +++ b/src/modems/SIMComSIM7080.h @@ -1,7 +1,8 @@ /** * @file SIMComSIM7080.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SIMComSIM7080 subclass of loggerModem for diff --git a/src/modems/SIMComSIM800.cpp b/src/modems/SIMComSIM800.cpp index f3211390f..94d0ee942 100644 --- a/src/modems/SIMComSIM800.cpp +++ b/src/modems/SIMComSIM800.cpp @@ -1,7 +1,8 @@ /** * @file SIMComSIM800.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SIMComSIM800 class. diff --git a/src/modems/SIMComSIM800.h b/src/modems/SIMComSIM800.h index 751fc853c..51ebeb421 100644 --- a/src/modems/SIMComSIM800.h +++ b/src/modems/SIMComSIM800.h @@ -1,7 +1,8 @@ /** * @file SIMComSIM800.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SIMComSIM800 subclass of loggerModem for Adafruit Fona diff --git a/src/modems/SequansMonarch.cpp b/src/modems/SequansMonarch.cpp index 01e82f87b..4ea31e30b 100644 --- a/src/modems/SequansMonarch.cpp +++ b/src/modems/SequansMonarch.cpp @@ -1,7 +1,8 @@ /** * @file SequansMonarch.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SequansMonarch class. diff --git a/src/modems/SequansMonarch.h b/src/modems/SequansMonarch.h index 5a08de4e8..a1262ef90 100644 --- a/src/modems/SequansMonarch.h +++ b/src/modems/SequansMonarch.h @@ -1,7 +1,8 @@ /** * @file SequansMonarch.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SequansMonarch subclass of loggerModem for Nimbelink or diff --git a/src/modems/Sodaq2GBeeR6.cpp b/src/modems/Sodaq2GBeeR6.cpp index 204e3ec38..8d75f67a0 100644 --- a/src/modems/Sodaq2GBeeR6.cpp +++ b/src/modems/Sodaq2GBeeR6.cpp @@ -1,7 +1,8 @@ /** * @file Sodaq2GBeeR6.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the Sodaq2GBeeR6 class. diff --git a/src/modems/Sodaq2GBeeR6.h b/src/modems/Sodaq2GBeeR6.h index 013385ace..07302642b 100644 --- a/src/modems/Sodaq2GBeeR6.h +++ b/src/modems/Sodaq2GBeeR6.h @@ -1,7 +1,8 @@ /** * @file Sodaq2GBeeR6.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the Sodaq2GBeeR6 subclass of the SIMComSIM800 class and is diff --git a/src/modems/SodaqUBeeR410M.cpp b/src/modems/SodaqUBeeR410M.cpp index b7a4090ea..76f419aec 100644 --- a/src/modems/SodaqUBeeR410M.cpp +++ b/src/modems/SodaqUBeeR410M.cpp @@ -1,7 +1,8 @@ /** * @file SodaqUBeeR410M.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SodaqUBeeR410M class. diff --git a/src/modems/SodaqUBeeR410M.h b/src/modems/SodaqUBeeR410M.h index 8d2d3af71..103b52747 100644 --- a/src/modems/SodaqUBeeR410M.h +++ b/src/modems/SodaqUBeeR410M.h @@ -1,7 +1,8 @@ /** * @file SodaqUBeeR410M.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SodaqUBeeR410M subclass of loggerModem for the Sodaq UBee diff --git a/src/modems/SodaqUBeeU201.cpp b/src/modems/SodaqUBeeU201.cpp index 543f19168..6e7b33e58 100644 --- a/src/modems/SodaqUBeeU201.cpp +++ b/src/modems/SodaqUBeeU201.cpp @@ -1,7 +1,8 @@ /** * @file SodaqUBeeU201.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SodaqUBeeU201 class. diff --git a/src/modems/SodaqUBeeU201.h b/src/modems/SodaqUBeeU201.h index 666a83f00..e71e7eb85 100644 --- a/src/modems/SodaqUBeeU201.h +++ b/src/modems/SodaqUBeeU201.h @@ -1,7 +1,8 @@ /** * @file SodaqUBeeU201.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SodaqUBeeU201 subclass of loggerModem for the Sodaq UBee diff --git a/src/publishers/DreamHostPublisher.cpp b/src/publishers/DreamHostPublisher.cpp index fbfa07e7d..40ffad715 100644 --- a/src/publishers/DreamHostPublisher.cpp +++ b/src/publishers/DreamHostPublisher.cpp @@ -1,7 +1,8 @@ /** * @file DreamHostPublisher.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the DreamHostPublisher class. @@ -23,23 +24,21 @@ const char* DreamHostPublisher::timestampTagDH = "&Loggertime="; // Constructors DreamHostPublisher::DreamHostPublisher() : dataPublisher() {} -DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, const char* dhUrl, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setDreamHostPortalRX(dhUrl); } DreamHostPublisher::DreamHostPublisher(Logger& baseLogger, Client* inClient, - const char* dhUrl, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + const char* dhUrl, int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setDreamHostPortalRX(dhUrl); } // Destructor @@ -52,41 +51,6 @@ void DreamHostPublisher::setDreamHostPortalRX(const char* dhUrl) { } -// This prints the URL out to an Arduino stream -void DreamHostPublisher::printSensorDataDreamHost(Stream* stream) { - stream->print(_DreamHostPortalRX); - stream->print(loggerTag); - stream->print(_baseLogger->getLoggerID()); - stream->print(timestampTagDH); - stream->print(String(Logger::markedLocalEpochTime - - 946684800)); // Correct time from epoch to y2k - - for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - stream->print('&'); - stream->print(_baseLogger->getVarCodeAtI(i)); - stream->print('='); - stream->print(_baseLogger->getValueStringAtI(i)); - } -} - - -// This prints a fully structured GET request for DreamHost to the -// specified stream -void DreamHostPublisher::printDreamHostRequest(Stream* stream) { - // Start the request - stream->print(getHeader); - - // Stream the full URL with parameters - printSensorDataDreamHost(stream); - - // Send the rest of the HTTP header - stream->print(HTTPtag); - stream->print(hostHeader); - stream->print(dreamhostHost); - stream->print(F("\r\n\r\n")); -} - - // A way to begin with everything already set void DreamHostPublisher::begin(Logger& baseLogger, Client* inClient, const char* dhUrl) { @@ -111,59 +75,41 @@ int16_t DreamHostPublisher::publishData(Client* outClient) { MS_START_DEBUG_TIMER; if (outClient->connect(dreamhostHost, dreamhostPort)) { MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms\n")); + txBufferInit(outClient); // copy the initial post header into the tx buffer - snprintf(txBuffer, sizeof(txBuffer), "%s", getHeader); + txBufferAppend(getHeader); // add in the dreamhost receiver URL - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", _DreamHostPortalRX); + txBufferAppend(_DreamHostPortalRX); // start the URL parameters - if (bufferFree() < 16) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", loggerTag); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _baseLogger->getLoggerID()); - - if (bufferFree() < 22) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", timestampTagDH); + txBufferAppend(loggerTag); + txBufferAppend(_baseLogger->getLoggerID()); + + txBufferAppend(timestampTagDH); ltoa((Logger::markedLocalEpochTime - 946684800), tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend(tempBuffer); for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - // Once the buffer fills, send it out - if (bufferFree() < 47) printTxBuffer(outClient); - - txBuffer[strlen(txBuffer)] = '&'; - _baseLogger->getVarCodeAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '='; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend('&'); + txBufferAppend(_baseLogger->getVarCodeAtI(i).c_str()); + txBufferAppend('='); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); } // add the rest of the HTTP GET headers to the outgoing buffer - if (bufferFree() < 52) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", HTTPtag); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", hostHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", dreamhostHost); - txBuffer[strlen(txBuffer)] = '\r'; - txBuffer[strlen(txBuffer)] = '\n'; - txBuffer[strlen(txBuffer)] = '\r'; - txBuffer[strlen(txBuffer)] = '\n'; - - // Send out the finished request (or the last unsent section of it) - printTxBuffer(outClient); + txBufferAppend(HTTPtag); + txBufferAppend(hostHeader); + txBufferAppend(dreamhostHost); + txBufferAppend('\r'); + txBufferAppend('\n'); + txBufferAppend('\r'); + txBufferAppend('\n'); + + // Flush the complete request + txBufferFlush(); // Wait 10 seconds for a response from the server uint32_t start = millis(); @@ -189,6 +135,7 @@ int16_t DreamHostPublisher::publishData(Client* outClient) { int16_t responseCode = 0; if (did_respond > 0) { char responseCode_char[4]; + responseCode_char[3] = 0; for (uint8_t i = 0; i < 3; i++) { responseCode_char[i] = tempBuffer[i + 9]; } @@ -197,7 +144,7 @@ int16_t DreamHostPublisher::publishData(Client* outClient) { responseCode = 504; } - PRINTOUT(F("-- Response Code --")); + PRINTOUT(F("\n-- Response Code --")); PRINTOUT(responseCode); return responseCode; diff --git a/src/publishers/DreamHostPublisher.h b/src/publishers/DreamHostPublisher.h index 6a7fe1a46..ba88e4d11 100644 --- a/src/publishers/DreamHostPublisher.h +++ b/src/publishers/DreamHostPublisher.h @@ -1,7 +1,8 @@ /** * @file DreamHostPublisher.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DreamHostPublisher subclass of dataPublisher for @@ -51,20 +52,10 @@ class DreamHostPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ - explicit DreamHostPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit DreamHostPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new DreamHost Publisher object * @@ -72,33 +63,21 @@ class DreamHostPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ DreamHostPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new DreamHost Publisher object * * @param baseLogger The logger supplying the data to be published * @param dhUrl The URL for sending data to DreamHost - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ DreamHostPublisher(Logger& baseLogger, const char* dhUrl, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new DreamHost Publisher object * @@ -107,14 +86,11 @@ class DreamHostPublisher : public dataPublisher { * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance * @param dhUrl The URL for sending data to DreamHost - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ DreamHostPublisher(Logger& baseLogger, Client* inClient, const char* dhUrl, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Destroy the DreamHost Publisher object */ @@ -133,26 +109,6 @@ class DreamHostPublisher : public dataPublisher { */ void setDreamHostPortalRX(const char* dhUrl); - /** - * @brief This creates all of the URL parameter tags and values and writes - * the result to an Arduino stream. - * - * HTML headers are not included. - * - * @param stream The Arduino stream to write out the URL and parameters to. - */ - void printSensorDataDreamHost(Stream* stream); - - /** - * @brief This prints a fully structured GET request for DreamHost to the - * specified stream. - * - * This includes the HTML headers. - * - * @param stream The Arduino stream to write out the URL and parameters to. - */ - void printDreamHostRequest(Stream* stream); - // A way to begin with everything already set /** * @copydoc dataPublisher::begin(Logger& baseLogger, Client* inClient) @@ -165,7 +121,6 @@ class DreamHostPublisher : public dataPublisher { */ void begin(Logger& baseLogger, const char* dhUrl); - // int16_t postDataDreamHost(void); /** * @brief Utilizes an attached modem to make a TCP connection to the * DreamHost URL and then stream out a get request over that connection. diff --git a/src/publishers/EnviroDIYPublisher.cpp b/src/publishers/EnviroDIYPublisher.cpp index 5d017ea99..5a6a043d8 100644 --- a/src/publishers/EnviroDIYPublisher.cpp +++ b/src/publishers/EnviroDIYPublisher.cpp @@ -1,7 +1,8 @@ /** * @file EnviroDIYPublisher.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the EnviroDIYPublisher class. @@ -31,25 +32,24 @@ const char* EnviroDIYPublisher::timestampTag = "\",\"timestamp\":\""; // Constructors EnviroDIYPublisher::EnviroDIYPublisher() : dataPublisher() {} -EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, const char* registrationToken, const char* samplingFeatureUUID, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setToken(registrationToken); _baseLogger->setSamplingFeatureUUID(samplingFeatureUUID); } EnviroDIYPublisher::EnviroDIYPublisher(Logger& baseLogger, Client* inClient, const char* registrationToken, const char* samplingFeatureUUID, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setToken(registrationToken); _baseLogger->setSamplingFeatureUUID(samplingFeatureUUID); } @@ -83,45 +83,6 @@ uint16_t EnviroDIYPublisher::calculateJsonSize() { return jsonLength; } -// This prints a properly formatted JSON for EnviroDIY to an Arduino stream -void EnviroDIYPublisher::printSensorDataJSON(Stream* stream) { - stream->print(samplingFeatureTag); - stream->print(_baseLogger->getSamplingFeatureUUID()); - stream->print(timestampTag); - stream->print(Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime)); - stream->print(F("\",")); - - for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - stream->print('"'); - stream->print(_baseLogger->getVarUUIDAtI(i)); - stream->print(F("\":")); - stream->print(_baseLogger->getValueStringAtI(i)); - if (i + 1 != _baseLogger->getArrayVarCount()) { stream->print(','); } - } - - stream->print('}'); -} - - -// This prints a fully structured post request for EnviroDIY to the -// specified stream. -void EnviroDIYPublisher::printEnviroDIYRequest(Stream* stream) { - // Stream the HTTP headers for the post request - stream->print(postHeader); - stream->print(postEndpoint); - stream->print(HTTPtag); - stream->print(hostHeader); - stream->print(enviroDIYHost); - stream->print(tokenHeader); - stream->print(_registrationToken); - stream->print(contentLengthHeader); - stream->print(calculateJsonSize()); - stream->print(contentTypeHeader); - - // Stream the JSON itself - printSensorDataJSON(stream); -} - // A way to begin with everything already set void EnviroDIYPublisher::begin(Logger& baseLogger, Client* inClient, @@ -144,7 +105,6 @@ void EnviroDIYPublisher::begin(Logger& baseLogger, // EnviroDIY/ODM2DataSharingPortal and then streams out a post request // over that connection. // The return is the http status code of the response. -// int16_t EnviroDIYPublisher::postDataEnviroDIY(void) int16_t EnviroDIYPublisher::publishData(Client* outClient) { // Create a buffer for the portions of the request and response char tempBuffer[37] = ""; @@ -156,84 +116,52 @@ int16_t EnviroDIYPublisher::publishData(Client* outClient) { MS_DBG(F("Connecting client")); MS_START_DEBUG_TIMER; if (outClient->connect(enviroDIYHost, enviroDIYPort)) { - MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms\n")); + MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms")); + txBufferInit(outClient); // copy the initial post header into the tx buffer - snprintf(txBuffer, sizeof(txBuffer), "%s", postHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", postEndpoint); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", HTTPtag); + txBufferAppend(postHeader); + txBufferAppend(postEndpoint); + txBufferAppend(HTTPtag); // add the rest of the HTTP POST headers to the outgoing buffer - // before adding each line/chunk to the outgoing buffer, we make sure - // there is space for that line, sending out buffer if not - if (bufferFree() < 28) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", hostHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", enviroDIYHost); - - if (bufferFree() < 47) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tokenHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", _registrationToken); - - if (bufferFree() < 26) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - contentLengthHeader); + txBufferAppend(hostHeader); + txBufferAppend(enviroDIYHost); + txBufferAppend(tokenHeader); + txBufferAppend(_registrationToken); + + txBufferAppend(contentLengthHeader); itoa(calculateJsonSize(), tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend(tempBuffer); - if (bufferFree() < 42) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", contentTypeHeader); + txBufferAppend(contentTypeHeader); // put the start of the JSON into the outgoing response_buffer - if (bufferFree() < 21) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", samplingFeatureTag); - - if (bufferFree() < 36) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _baseLogger->getSamplingFeatureUUID()); - - if (bufferFree() < 42) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", timestampTag); - Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime) - .toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ','; + txBufferAppend(samplingFeatureTag); + txBufferAppend(_baseLogger->getSamplingFeatureUUID()); + + txBufferAppend(timestampTag); + txBufferAppend( + Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime) + .c_str()); + txBufferAppend('"'); + txBufferAppend(','); for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - // Once the buffer fills, send it out - if (bufferFree() < 47) printTxBuffer(outClient); - - txBuffer[strlen(txBuffer)] = '"'; - _baseLogger->getVarUUIDAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ':'; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend('"'); + txBufferAppend(_baseLogger->getVarUUIDAtI(i).c_str()); + txBufferAppend('"'); + txBufferAppend(':'); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); if (i + 1 != _baseLogger->getArrayVarCount()) { - txBuffer[strlen(txBuffer)] = ','; + txBufferAppend(','); } else { - txBuffer[strlen(txBuffer)] = '}'; + txBufferAppend('}'); } } - // Send out the finished request (or the last unsent section of it) - printTxBuffer(outClient, true); + // Write out the complete request + txBufferFlush(); // Wait 10 seconds for a response from the server uint32_t start = millis(); @@ -260,6 +188,7 @@ int16_t EnviroDIYPublisher::publishData(Client* outClient) { int16_t responseCode = 0; if (did_respond > 0) { char responseCode_char[4]; + responseCode_char[3] = 0; for (uint8_t i = 0; i < 3; i++) { responseCode_char[i] = tempBuffer[i + 9]; } @@ -268,7 +197,7 @@ int16_t EnviroDIYPublisher::publishData(Client* outClient) { responseCode = 504; } - PRINTOUT(F("-- Response Code --")); + PRINTOUT(F("\n-- Response Code --")); PRINTOUT(responseCode); return responseCode; diff --git a/src/publishers/EnviroDIYPublisher.h b/src/publishers/EnviroDIYPublisher.h index 8a728dd1d..025ece3df 100644 --- a/src/publishers/EnviroDIYPublisher.h +++ b/src/publishers/EnviroDIYPublisher.h @@ -1,7 +1,8 @@ /** * @file EnviroDIYPublisher.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the EnviroDIYPublisher subclass of dataPublisher for @@ -51,20 +52,10 @@ class EnviroDIYPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ - explicit EnviroDIYPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit EnviroDIYPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new EnviroDIY Publisher object * @@ -72,20 +63,11 @@ class EnviroDIYPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ EnviroDIYPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new EnviroDIY Publisher object * @@ -94,15 +76,11 @@ class EnviroDIYPublisher : public dataPublisher { * Monitor My Watershed data portal. * @param samplingFeatureUUID The sampling feature UUID for the site on the * Monitor My Watershed data portal. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ EnviroDIYPublisher(Logger& baseLogger, const char* registrationToken, - const char* samplingFeatureUUID, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + const char* samplingFeatureUUID, int sendEveryX = 1); /** * @brief Construct a new EnviroDIY Publisher object * @@ -114,16 +92,12 @@ class EnviroDIYPublisher : public dataPublisher { * Monitor My Watershed data portal. * @param samplingFeatureUUID The sampling feature UUID for the site on the * Monitor My Watershed data portal. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ EnviroDIYPublisher(Logger& baseLogger, Client* inClient, const char* registrationToken, - const char* samplingFeatureUUID, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + const char* samplingFeatureUUID, int sendEveryX = 1); /** * @brief Destroy the EnviroDIY Publisher object */ @@ -149,30 +123,7 @@ class EnviroDIYPublisher : public dataPublisher { * @return uint16_t The number of characters in the JSON object. */ uint16_t calculateJsonSize(); - // /** - // * @brief Calculates how long the full post request will be, including - // * headers - // * - // * @return uint16_t The length of the full request including HTTP - // headers. - // */ - // uint16_t calculatePostSize(); - /** - * @brief This generates a properly formatted JSON for EnviroDIY and prints - * it to the input Arduino stream object. - * - * @param stream The Arduino stream to write out the JSON to. - */ - void printSensorDataJSON(Stream* stream); - - /** - * @brief This prints a fully structured post request for Monitor My - * Watershed/EnviroDIY to the specified stream. - * - * @param stream The Arduino stream to write out the request to. - */ - void printEnviroDIYRequest(Stream* stream); // A way to begin with everything already set /** @@ -194,7 +145,6 @@ class EnviroDIYPublisher : public dataPublisher { void begin(Logger& baseLogger, const char* registrationToken, const char* samplingFeatureUUID); - // int16_t postDataEnviroDIY(void); /** * @brief Utilize an attached modem to open a a TCP connection to the * EnviroDIY/ODM2DataSharingPortal and then stream out a post request over @@ -217,12 +167,10 @@ class EnviroDIYPublisher : public dataPublisher { * * @{ */ - static const char* postEndpoint; ///< The endpoint - static const char* enviroDIYHost; ///< The host name - static const int enviroDIYPort; ///< The host port - static const char* tokenHeader; ///< The token header text - // static const char *cacheHeader; ///< The cache header text - // static const char *connectionHeader; ///< The keep alive header text + static const char* postEndpoint; ///< The endpoint + static const char* enviroDIYHost; ///< The host name + static const int enviroDIYPort; ///< The host port + static const char* tokenHeader; ///< The token header text static const char* contentLengthHeader; ///< The content length header text static const char* contentTypeHeader; ///< The content type header text /**@}*/ diff --git a/src/publishers/ThingSpeakPublisher.cpp b/src/publishers/ThingSpeakPublisher.cpp index e1b0e3a7f..f13780260 100644 --- a/src/publishers/ThingSpeakPublisher.cpp +++ b/src/publishers/ThingSpeakPublisher.cpp @@ -1,7 +1,8 @@ /** * @file ThingSpeakPublisher.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the ThingSpeakPublisher class. @@ -25,18 +26,17 @@ const char* ThingSpeakPublisher::mqttUser = THING_SPEAK_USER_NAME; // Constructors ThingSpeakPublisher::ThingSpeakPublisher() : dataPublisher() {} -ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, const char* thingSpeakChannelKey, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setMQTTKey(thingSpeakMQTTKey); setChannelID(thingSpeakChannelID); setChannelKey(thingSpeakChannelKey); @@ -45,8 +45,8 @@ ThingSpeakPublisher::ThingSpeakPublisher(Logger& baseLogger, Client* inClient, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, const char* thingSpeakChannelKey, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setMQTTKey(thingSpeakMQTTKey); setChannelID(thingSpeakChannelID); setChannelKey(thingSpeakChannelKey); @@ -129,27 +129,19 @@ int16_t ThingSpeakPublisher::publishData(Client* outClient) { _thingSpeakChannelKey); MS_DBG(F("Topic ["), strlen(topicBuffer), F("]:"), String(topicBuffer)); - emptyTxBuffer(); + // buffer is used only locally, it does not transmit + txBufferInit(nullptr); - Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime) - .toCharArray(tempBuffer, 26); - snprintf(txBuffer + strlen(txBuffer), sizeof(txBuffer) - strlen(txBuffer), - "%s", "created_at="); - snprintf(txBuffer + strlen(txBuffer), sizeof(txBuffer) - strlen(txBuffer), - "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '&'; + txBufferAppend("created_at="); + txBufferAppend( + Logger::formatDateTime_ISO8601(Logger::markedLocalEpochTime).c_str()); for (uint8_t i = 0; i < numChannels; i++) { - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "field"); + txBufferAppend("&field"); itoa(i + 1, tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '='; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 26); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - if (i + 1 != numChannels) { txBuffer[strlen(txBuffer)] = '&'; } + txBufferAppend(tempBuffer); + txBufferAppend('='); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); } MS_DBG(F("Message ["), strlen(txBuffer), F("]:"), String(txBuffer)); diff --git a/src/publishers/ThingSpeakPublisher.h b/src/publishers/ThingSpeakPublisher.h index 2b0bbe89d..1a924b500 100644 --- a/src/publishers/ThingSpeakPublisher.h +++ b/src/publishers/ThingSpeakPublisher.h @@ -1,7 +1,8 @@ /** * @file ThingSpeakPublisher.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the ThingSpeakPublisher subclass of dataPublisher for @@ -76,20 +77,10 @@ class ThingSpeakPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ - explicit ThingSpeakPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit ThingSpeakPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new ThingSpeak Publisher object * @@ -97,20 +88,11 @@ class ThingSpeakPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ ThingSpeakPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Construct a new ThingSpeak Publisher object * @@ -118,15 +100,12 @@ class ThingSpeakPublisher : public dataPublisher { * @param thingSpeakMQTTKey Your MQTT API Key from Account > MyProfile. * @param thingSpeakChannelID The numeric channel id for your channel * @param thingSpeakChannelKey The write API key for your channel - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ ThingSpeakPublisher(Logger& baseLogger, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, - const char* thingSpeakChannelKey, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + const char* thingSpeakChannelKey, int sendEveryX = 1); /** * @brief Construct a new ThingSpeak Publisher object * @@ -137,17 +116,13 @@ class ThingSpeakPublisher : public dataPublisher { * @param thingSpeakMQTTKey Your MQTT API Key from Account > MyProfile. * @param thingSpeakChannelID The numeric channel id for your channel * @param thingSpeakChannelKey The write API key for your channel - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ ThingSpeakPublisher(Logger& baseLogger, Client* inClient, const char* thingSpeakMQTTKey, const char* thingSpeakChannelID, - const char* thingSpeakChannelKey, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + const char* thingSpeakChannelKey, int sendEveryX = 1); /** * @brief Destroy the ThingSpeak Publisher object */ diff --git a/src/publishers/UbidotsPublisher.cpp b/src/publishers/UbidotsPublisher.cpp index c840cdfcf..4a111d631 100644 --- a/src/publishers/UbidotsPublisher.cpp +++ b/src/publishers/UbidotsPublisher.cpp @@ -1,7 +1,8 @@ /** * @file UbidotsPublisher.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Greg Cutrell * @author Sara Geleskie Damiano * @@ -34,26 +35,23 @@ const char* UbidotsPublisher::payload = "{"; // Constructors UbidotsPublisher::UbidotsPublisher() : dataPublisher() {} -UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) {} +UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) {} UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX, uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) {} + int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) {} UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, const char* authentificationToken, - const char* deviceID, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, sendEveryX, sendOffset) { + const char* deviceID, int sendEveryX) + : dataPublisher(baseLogger, sendEveryX) { setToken(authentificationToken); _baseLogger->setSamplingFeatureUUID(deviceID); MS_DBG(F("dataPublisher object created")); } UbidotsPublisher::UbidotsPublisher(Logger& baseLogger, Client* inClient, const char* authentificationToken, - const char* deviceID, uint8_t sendEveryX, - uint8_t sendOffset) - : dataPublisher(baseLogger, inClient, sendEveryX, sendOffset) { + const char* deviceID, int sendEveryX) + : dataPublisher(baseLogger, inClient, sendEveryX) { setToken(authentificationToken); _baseLogger->setSamplingFeatureUUID(deviceID); MS_DBG(F("dataPublisher object created")); @@ -93,46 +91,6 @@ uint16_t UbidotsPublisher::calculateJsonSize() { } -// This prints a properly formatted JSON for EnviroDIY to an Arduino stream -void UbidotsPublisher::printSensorDataJSON(Stream* stream) { - stream->print(payload); - - for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - stream->print('"'); - stream->print(_baseLogger->getVarUUIDAtI(i)); - stream->print(F("\":{'value':")); - stream->print(_baseLogger->getValueStringAtI(i)); - stream->print(",'timestamp':"); - stream->print(Logger::markedUTCEpochTime); - stream->print( - F("000}")); // Convert microseconds to milliseconds for ubidots - if (i + 1 != _baseLogger->getArrayVarCount()) { stream->print(','); } - } - - stream->print(F("}}")); -} - - -// This prints a fully structured post request for Ubidots to the -// specified stream. -void UbidotsPublisher::printUbidotsRequest(Stream* stream) { - // Stream the HTTP headers for the post request - stream->print(postHeader); - stream->print(postEndpoint); - stream->print(HTTPtag); - stream->print(hostHeader); - stream->print(ubidotsHost); - stream->print(tokenHeader); - stream->print(_authentificationToken); - stream->print(contentLengthHeader); - stream->print(calculateJsonSize()); - stream->print(contentTypeHeader); - - // Stream the JSON itself - printSensorDataJSON(stream); -} - - // A way to begin with everything already set void UbidotsPublisher::begin(Logger& baseLogger, Client* inClient, const char* authentificationToken, @@ -167,93 +125,48 @@ int16_t UbidotsPublisher::publishData(Client* outClient) { MS_START_DEBUG_TIMER; if (outClient->connect(ubidotsHost, ubidotsPort)) { MS_DBG(F("Client connected after"), MS_PRINT_DEBUG_TIMER, F("ms\n")); + txBufferInit(outClient); // copy the initial post header into the tx buffer - snprintf(txBuffer, sizeof(txBuffer), "%s", postHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", postEndpoint); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _baseLogger->getSamplingFeatureUUID()); - txBuffer[strlen(txBuffer)] = '/'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", HTTPtag); + txBufferAppend(postHeader); + txBufferAppend(postEndpoint); + txBufferAppend(_baseLogger->getSamplingFeatureUUID()); + txBufferAppend('/'); + txBufferAppend(HTTPtag); // add the rest of the HTTP POST headers to the outgoing buffer - // before adding each line/chunk to the outgoing buffer, we make sure - // there is space for that line, sending out buffer if not - if (bufferFree() < 28) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", hostHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", ubidotsHost); + txBufferAppend(hostHeader); + txBufferAppend(ubidotsHost); + txBufferAppend(tokenHeader); + txBufferAppend(_authentificationToken); - if (bufferFree() < 47) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tokenHeader); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - _authentificationToken); - - if (bufferFree() < 26) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", - contentLengthHeader); + txBufferAppend(contentLengthHeader); itoa(calculateJsonSize(), tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); + txBufferAppend(tempBuffer); - if (bufferFree() < 42) printTxBuffer(outClient); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", contentTypeHeader); + txBufferAppend(contentTypeHeader); // put the start of the JSON into the outgoing response_buffer - if (bufferFree() < 21) printTxBuffer(outClient); - - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", payload); + txBufferAppend(payload); for (uint8_t i = 0; i < _baseLogger->getArrayVarCount(); i++) { - // Once the buffer fills, send it out - if (bufferFree() < 47) printTxBuffer(outClient); - - txBuffer[strlen(txBuffer)] = '"'; - _baseLogger->getVarUUIDAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = '"'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", ":{"); - txBuffer[strlen(txBuffer)] = '"'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "value"); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ':'; - _baseLogger->getValueStringAtI(i).toCharArray(tempBuffer, 37); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - txBuffer[strlen(txBuffer)] = ','; - txBuffer[strlen(txBuffer)] = '"'; - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "timestamp"); - txBuffer[strlen(txBuffer)] = '"'; - txBuffer[strlen(txBuffer)] = ':'; + txBufferAppend('"'); + txBufferAppend(_baseLogger->getVarUUIDAtI(i).c_str()); + txBufferAppend("\":{\"value\":"); + txBufferAppend(_baseLogger->getValueStringAtI(i).c_str()); + txBufferAppend(",\"timestamp\":"); ltoa(Logger::markedUTCEpochTime, tempBuffer, 10); // BASE 10 - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", tempBuffer); - snprintf(txBuffer + strlen(txBuffer), - sizeof(txBuffer) - strlen(txBuffer), "%s", "000"); + txBufferAppend(tempBuffer); + txBufferAppend("000}"); if (i + 1 != _baseLogger->getArrayVarCount()) { - txBuffer[strlen(txBuffer)] = '}'; - txBuffer[strlen(txBuffer)] = ','; + txBufferAppend(','); } else { - txBuffer[strlen(txBuffer)] = '}'; - txBuffer[strlen(txBuffer)] = '}'; + txBufferAppend('}'); } } - // Send out the finished request (or the last unsent section of it) - printTxBuffer(outClient, true); + // Flush the complete request + txBufferFlush(); // Wait 10 seconds for a response from the server uint32_t start = millis(); @@ -279,6 +192,7 @@ int16_t UbidotsPublisher::publishData(Client* outClient) { int16_t responseCode = 0; if (did_respond > 0) { char responseCode_char[4]; + responseCode_char[3] = 0; for (uint8_t i = 0; i < 3; i++) { responseCode_char[i] = tempBuffer[i + 9]; } @@ -287,7 +201,7 @@ int16_t UbidotsPublisher::publishData(Client* outClient) { responseCode = 504; } - PRINTOUT(F("-- Response Code --")); + PRINTOUT(F("\n-- Response Code --")); PRINTOUT(responseCode); return responseCode; diff --git a/src/publishers/UbidotsPublisher.h b/src/publishers/UbidotsPublisher.h index adb47f9e2..c8926eb2e 100644 --- a/src/publishers/UbidotsPublisher.h +++ b/src/publishers/UbidotsPublisher.h @@ -1,7 +1,8 @@ /** * @file UbidotsPublisher.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Greg Cutrell * @author Sara Geleskie Damiano * @@ -50,20 +51,10 @@ class UbidotsPublisher : public dataPublisher { * logger. * * @param baseLogger The logger supplying the data to be published - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ - explicit UbidotsPublisher(Logger& baseLogger, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + explicit UbidotsPublisher(Logger& baseLogger, int sendEveryX = 1); /** * @brief Construct a new Ubidots Publisher object * @@ -71,20 +62,10 @@ class UbidotsPublisher : public dataPublisher { * @param inClient An Arduino client instance to use to print data to. * Allows the use of any type of client and multiple clients tied to a * single TinyGSM modem instance - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected - * - * @note It is possible (though very unlikey) that using this constructor - * could cause errors if the compiler attempts to initialize the publisher - * instance before the logger instance. If you suspect you are seeing that - * issue, use the null constructor and a populated begin(...) within your - * set-up function. + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ - UbidotsPublisher(Logger& baseLogger, Client* inClient, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + UbidotsPublisher(Logger& baseLogger, Client* inClient, int sendEveryX = 1); /** * @brief Construct a new Ubidots Publisher object * @@ -95,15 +76,11 @@ class UbidotsPublisher : public dataPublisher { * specific device's setup panel). * @param deviceID The device API Label from Ubidots, derived from the * user-specified device name. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ UbidotsPublisher(Logger& baseLogger, const char* authentificationToken, - const char* deviceID, uint8_t sendEveryX = 1, - uint8_t sendOffset = 0); + const char* deviceID, int sendEveryX = 1); /** * @brief Construct a new Ubidots Publisher object * @@ -117,15 +94,12 @@ class UbidotsPublisher : public dataPublisher { * specific device's setup panel). * @param deviceID The device API Label from Ubidots, derived from the * user-specified device name. - * @param sendEveryX Currently unimplemented, intended for future use to - * enable caching and bulk publishing - * @param sendOffset Currently unimplemented, intended for future use to - * enable publishing data at a time slightly delayed from when it is - * collected + * @param sendEveryX Interval (in units of the logging interval) between + * attempted data transmissions. NOTE: not implemented by this publisher! */ UbidotsPublisher(Logger& baseLogger, Client* inClient, const char* authentificationToken, const char* deviceID, - uint8_t sendEveryX = 1, uint8_t sendOffset = 0); + int sendEveryX = 1); /** * @brief Destroy the EnviroDIY Publisher object */ @@ -153,30 +127,6 @@ class UbidotsPublisher : public dataPublisher { * @return uint16_t The number of characters in the JSON object. */ uint16_t calculateJsonSize(); - // /** - // * @brief Calculates how long the full post request will be, including - // * headers - // * - // * @return uint16_t The length of the full request including HTTP - // headers. - // */ - // uint16_t calculatePostSize(); - - /** - * @brief This generates a properly formatted JSON for Ubidots and prints - * it to the input Arduino stream object. - * - * @param stream The Arduino stream to write out the JSON to. - */ - void printSensorDataJSON(Stream* stream); - - /** - * @brief This prints a fully structured post request for the Ubidots API - * to the specified stream. - * - * @param stream The Arduino stream to write out the request to. - */ - void printUbidotsRequest(Stream* stream); // A way to begin with everything already set /** @@ -225,12 +175,10 @@ class UbidotsPublisher : public dataPublisher { * * @{ */ - static const char* postEndpoint; ///< The endpoint - static const char* ubidotsHost; ///< The host name - static const int ubidotsPort; ///< The host port - static const char* tokenHeader; ///< The token header text - // static const char *cacheHeader; ///< The cache header text - // static const char *connectionHeader; ///< The keep alive header text + static const char* postEndpoint; ///< The endpoint + static const char* ubidotsHost; ///< The host name + static const int ubidotsPort; ///< The host port + static const char* tokenHeader; ///< The token header text static const char* contentLengthHeader; ///< The content length header text static const char* contentTypeHeader; ///< The content type header text /**@}*/ diff --git a/src/sensors/AOSongAM2315.cpp b/src/sensors/AOSongAM2315.cpp index bf801c334..7735dd11b 100644 --- a/src/sensors/AOSongAM2315.cpp +++ b/src/sensors/AOSongAM2315.cpp @@ -1,7 +1,8 @@ /** * @file AOSongAM2315.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the AOSongAM2315 class. diff --git a/src/sensors/AOSongAM2315.h b/src/sensors/AOSongAM2315.h index 33ff73ca5..2788b5842 100644 --- a/src/sensors/AOSongAM2315.h +++ b/src/sensors/AOSongAM2315.h @@ -1,7 +1,8 @@ /** * @file AOSongAM2315.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the AOSongAM2315 sensor subclass and the variable subclasses diff --git a/src/sensors/AOSongDHT.cpp b/src/sensors/AOSongDHT.cpp index f00dc0557..8475feb3f 100644 --- a/src/sensors/AOSongDHT.cpp +++ b/src/sensors/AOSongDHT.cpp @@ -1,7 +1,8 @@ /** * @file AOSongDHT.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the AOSongDHT class. diff --git a/src/sensors/AOSongDHT.h b/src/sensors/AOSongDHT.h index eb206e3cf..45e99f55e 100644 --- a/src/sensors/AOSongDHT.h +++ b/src/sensors/AOSongDHT.h @@ -1,7 +1,8 @@ /** * @file AOSongDHT.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the AOSongDHT sensor subclass and the variable subclasses diff --git a/src/sensors/AnalogElecConductivity.cpp b/src/sensors/AnalogElecConductivity.cpp index 560558080..e1b49b01e 100644 --- a/src/sensors/AnalogElecConductivity.cpp +++ b/src/sensors/AnalogElecConductivity.cpp @@ -1,11 +1,13 @@ /** * @file AnalogElecConductivity.cpp - * @copyright 2017-2022 Stroud Water Research Center + * @copyright Stroud Water Research Center and Neil Hancock * Part of the EnviroDIY ModularSensors library - * @copyright 2020 Neil Hancock + * This library is published under the BSD-3 license. + * @author Written By: Neil Hancock ; Edited by Sara + * Geleskie Damiano * - * * @brief This encapsulates an Electrical Conductivity sensors using an anlog - *input and onboard ADC and ADC ref. + * @brief This encapsulates an Electrical Conductivity sensors using an anlog + * input and onboard ADC and ADC ref. */ #include "AnalogElecConductivity.h" diff --git a/src/sensors/AnalogElecConductivity.h b/src/sensors/AnalogElecConductivity.h index d29d96672..57351fe86 100644 --- a/src/sensors/AnalogElecConductivity.h +++ b/src/sensors/AnalogElecConductivity.h @@ -1,12 +1,11 @@ /** * @file AnalogElecConductivity.h - * @copyright 2017-2022 Stroud Water Research Center + * @copyright Stroud Water Research Center and Neil Hancock * Part of the EnviroDIY ModularSensors library - * @copyright 2020 Neil Hancock + * This library is published under the BSD-3 license. * @author Written By: Neil Hancock ; Edited by Sara * Geleskie Damiano * - * * @brief Encapsulates an Electrical Conductivity sensors using an anlog * input and onboard ADC and ADC ref. */ diff --git a/src/sensors/ApogeeSQ212.cpp b/src/sensors/ApogeeSQ212.cpp index 9a0936712..ff5936b76 100644 --- a/src/sensors/ApogeeSQ212.cpp +++ b/src/sensors/ApogeeSQ212.cpp @@ -1,7 +1,8 @@ /** * @file ApogeeSQ212.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * Adapted from CampbellOBS3.cpp by Sara Geleskie Damiano diff --git a/src/sensors/ApogeeSQ212.h b/src/sensors/ApogeeSQ212.h index cad5dca4f..c2b4d3c24 100644 --- a/src/sensors/ApogeeSQ212.h +++ b/src/sensors/ApogeeSQ212.h @@ -1,7 +1,8 @@ /** * @file ApogeeSQ212.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * Adapted from CampbellOBS3.h by Sara Geleskie Damiano diff --git a/src/sensors/AtlasParent.cpp b/src/sensors/AtlasParent.cpp index 94496c2df..a055ebb5a 100644 --- a/src/sensors/AtlasParent.cpp +++ b/src/sensors/AtlasParent.cpp @@ -1,7 +1,8 @@ /** * @file AtlasParent.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasParent.h b/src/sensors/AtlasParent.h index 6e308b143..e872f3204 100644 --- a/src/sensors/AtlasParent.h +++ b/src/sensors/AtlasParent.h @@ -1,7 +1,8 @@ /** * @file AtlasParent.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificCO2.cpp b/src/sensors/AtlasScientificCO2.cpp index 8c17ebfc2..df2994d4e 100644 --- a/src/sensors/AtlasScientificCO2.cpp +++ b/src/sensors/AtlasScientificCO2.cpp @@ -1,7 +1,8 @@ /** * @file AtlasScientificCO2.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificCO2.h b/src/sensors/AtlasScientificCO2.h index 559fdce73..fdaa99cea 100644 --- a/src/sensors/AtlasScientificCO2.h +++ b/src/sensors/AtlasScientificCO2.h @@ -1,7 +1,8 @@ /** * @file AtlasScientificCO2.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificDO.cpp b/src/sensors/AtlasScientificDO.cpp index 5994be05b..5a46e246e 100644 --- a/src/sensors/AtlasScientificDO.cpp +++ b/src/sensors/AtlasScientificDO.cpp @@ -1,7 +1,8 @@ /** * @file AtlasScientificDO.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificDO.h b/src/sensors/AtlasScientificDO.h index 76f0ba693..3cafe86c9 100644 --- a/src/sensors/AtlasScientificDO.h +++ b/src/sensors/AtlasScientificDO.h @@ -1,7 +1,8 @@ /** * @file AtlasScientificDO.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificEC.cpp b/src/sensors/AtlasScientificEC.cpp index d91e087af..e35513a0f 100644 --- a/src/sensors/AtlasScientificEC.cpp +++ b/src/sensors/AtlasScientificEC.cpp @@ -1,7 +1,8 @@ /** * @file AtlasScientificEC.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificEC.h b/src/sensors/AtlasScientificEC.h index 746702b38..9908c810f 100644 --- a/src/sensors/AtlasScientificEC.h +++ b/src/sensors/AtlasScientificEC.h @@ -1,7 +1,8 @@ /** * @file AtlasScientificEC.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificORP.h b/src/sensors/AtlasScientificORP.h index 8219997c1..e722dfc38 100644 --- a/src/sensors/AtlasScientificORP.h +++ b/src/sensors/AtlasScientificORP.h @@ -1,7 +1,8 @@ /** * @file AtlasScientificORP.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificRTD.h b/src/sensors/AtlasScientificRTD.h index 2502e64d2..b9b20b066 100644 --- a/src/sensors/AtlasScientificRTD.h +++ b/src/sensors/AtlasScientificRTD.h @@ -1,7 +1,8 @@ /** * @file AtlasScientificRTD.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/AtlasScientificpH.h b/src/sensors/AtlasScientificpH.h index f2c7c2e97..c2d198445 100644 --- a/src/sensors/AtlasScientificpH.h +++ b/src/sensors/AtlasScientificpH.h @@ -1,7 +1,8 @@ /** * @file AtlasScientificpH.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Initial developement for Atlas Sensors was done by Adam Gold * Files were edited by Sara Damiano * diff --git a/src/sensors/BoschBME280.cpp b/src/sensors/BoschBME280.cpp index 13bfcac80..ac63bcf00 100644 --- a/src/sensors/BoschBME280.cpp +++ b/src/sensors/BoschBME280.cpp @@ -1,7 +1,8 @@ /** * @file BoschBME280.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the BoschBME280 class. diff --git a/src/sensors/BoschBME280.h b/src/sensors/BoschBME280.h index bd9b77e5d..6edd6ac26 100644 --- a/src/sensors/BoschBME280.h +++ b/src/sensors/BoschBME280.h @@ -1,7 +1,8 @@ /** * @file BoschBME280.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the BoschBME280 sensor subclass and the variable subclasses diff --git a/src/sensors/BoschBMP3xx.cpp b/src/sensors/BoschBMP3xx.cpp index e3797aadf..6a7bfdf3e 100644 --- a/src/sensors/BoschBMP3xx.cpp +++ b/src/sensors/BoschBMP3xx.cpp @@ -1,7 +1,8 @@ /** * @file BoschBMP3xx.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the BoschBMP3xx class. diff --git a/src/sensors/BoschBMP3xx.h b/src/sensors/BoschBMP3xx.h index d64e1d68c..9f7899d61 100644 --- a/src/sensors/BoschBMP3xx.h +++ b/src/sensors/BoschBMP3xx.h @@ -1,7 +1,8 @@ /** * @file BoschBMP3xx.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the BoschBMP3xx sensor subclass and the variable subclasses diff --git a/src/sensors/CampbellClariVUE10.h b/src/sensors/CampbellClariVUE10.h index 3f3f0ca8e..3b6012221 100644 --- a/src/sensors/CampbellClariVUE10.h +++ b/src/sensors/CampbellClariVUE10.h @@ -1,7 +1,8 @@ /** * @file CampbellClariVUE10.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the CampbellClariVUE10 sensor subclass and the variable diff --git a/src/sensors/CampbellOBS3.cpp b/src/sensors/CampbellOBS3.cpp index bd270d683..fc7ab97d7 100644 --- a/src/sensors/CampbellOBS3.cpp +++ b/src/sensors/CampbellOBS3.cpp @@ -1,7 +1,8 @@ /** * @file CampbellOBS3.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the CampbellOBS3 class. diff --git a/src/sensors/CampbellOBS3.h b/src/sensors/CampbellOBS3.h index 7b0a0a9f9..bfe92c782 100644 --- a/src/sensors/CampbellOBS3.h +++ b/src/sensors/CampbellOBS3.h @@ -1,7 +1,8 @@ /** * @file CampbellOBS3.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the CampbellOBS3 sensor subclass and the variable subclasses diff --git a/src/sensors/CampbellRainVUE10.h b/src/sensors/CampbellRainVUE10.h index 41f0c8b45..bbf8b938c 100644 --- a/src/sensors/CampbellRainVUE10.h +++ b/src/sensors/CampbellRainVUE10.h @@ -1,7 +1,8 @@ /** * @file CampbellRainVUE10.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the CampbellRainVUE10 sensor subclass and the variable diff --git a/src/sensors/Decagon5TM.cpp b/src/sensors/Decagon5TM.cpp index 9244afdc3..e5bfb046a 100644 --- a/src/sensors/Decagon5TM.cpp +++ b/src/sensors/Decagon5TM.cpp @@ -1,7 +1,8 @@ /** * @file Decagon5TM.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the Decagon5TM class. diff --git a/src/sensors/Decagon5TM.h b/src/sensors/Decagon5TM.h index a0f18c4bb..fcee6d289 100644 --- a/src/sensors/Decagon5TM.h +++ b/src/sensors/Decagon5TM.h @@ -1,7 +1,8 @@ /** * @file Decagon5TM.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the Decagon5TM subclass of the SDI12Sensors class along with diff --git a/src/sensors/DecagonCTD.h b/src/sensors/DecagonCTD.h index 9649a3f32..59efae7d3 100644 --- a/src/sensors/DecagonCTD.h +++ b/src/sensors/DecagonCTD.h @@ -1,7 +1,8 @@ /** * @file DecagonCTD.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DecagonCTD subclass of the SDI12Sensors class along with diff --git a/src/sensors/DecagonES2.h b/src/sensors/DecagonES2.h index 11e55ba74..956847ebd 100644 --- a/src/sensors/DecagonES2.h +++ b/src/sensors/DecagonES2.h @@ -1,7 +1,8 @@ /** * @file DecagonES2.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the DecagonES2 subclass of the SDI12Sensors class along with diff --git a/src/sensors/EverlightALSPT19.cpp b/src/sensors/EverlightALSPT19.cpp index e34d25816..9f885f87f 100644 --- a/src/sensors/EverlightALSPT19.cpp +++ b/src/sensors/EverlightALSPT19.cpp @@ -1,7 +1,8 @@ /** * @file EverlightALSPT19.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the EverlightALSPT19 class. diff --git a/src/sensors/EverlightALSPT19.h b/src/sensors/EverlightALSPT19.h index 3518e879f..53508dd45 100644 --- a/src/sensors/EverlightALSPT19.h +++ b/src/sensors/EverlightALSPT19.h @@ -1,7 +1,8 @@ /** * @file EverlightALSPT19.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the EverlightALSPT19 sensor subclass and the variable diff --git a/src/sensors/ExternalVoltage.h b/src/sensors/ExternalVoltage.h index 3ad9e6672..308bbd0a2 100644 --- a/src/sensors/ExternalVoltage.h +++ b/src/sensors/ExternalVoltage.h @@ -1,7 +1,8 @@ /** * @file ExternalVoltage.h * - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * Adapted from CampbellOBS3.h by Sara Geleskie Damiano diff --git a/src/sensors/FreescaleMPL115A2.cpp b/src/sensors/FreescaleMPL115A2.cpp index a1b817d44..98367d49a 100644 --- a/src/sensors/FreescaleMPL115A2.cpp +++ b/src/sensors/FreescaleMPL115A2.cpp @@ -1,7 +1,8 @@ /** * @file FreescaleMPL115A2.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/FreescaleMPL115A2.h b/src/sensors/FreescaleMPL115A2.h index 8fb079dc1..1a27efdfc 100644 --- a/src/sensors/FreescaleMPL115A2.h +++ b/src/sensors/FreescaleMPL115A2.h @@ -1,7 +1,8 @@ /** * @file FreescaleMPL115A2.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/GroPointGPLP8.h b/src/sensors/GroPointGPLP8.h new file mode 100644 index 000000000..869ea74b3 --- /dev/null +++ b/src/sensors/GroPointGPLP8.h @@ -0,0 +1,300 @@ +/** + * @file GroPointGPLP8.h + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. + * @author Anthony Aufdenkampe + * + * @brief Contains the GroPointGPLP8 sensor subclass and the variable + * subclasses GroPointGPLP8_Moist and GroPointGPLP8_Temp + * + * These are for the GroPoint Profile GPLP-8 Eight-Segment Soil Moisture + * and Temperature Profiling Probe. + * + * This depends on the GroPointParent super class. + * + * Documentation for the Modbus Protocol commands and responses can be found + * within the documentation in the GroPointModbus library at: + * https://github.com/EnviroDIY/GroPointModbus + * + * More detailed infromation on each variable can be found in the documentation + * for the individual sensor probes + */ +/* clang-format off */ +/** + * @defgroup sensor_gplp8 GroPoint Profile GPLP-8 Soil Moisture & Temperature + * Profiling Probe. Classes for the GroPoint Profile GPLP-8 Soil Moisture & + * Temperature Probe. + * + * @ingroup GroPoint_group + * + * @tableofcontents + * @m_footernavigation + * + * @section sensor_gplp8_datasheet Sensor Datasheet + * - [GroPoint Profile User Manual](https://www.gropoint.com/s/2625-N-T-GroPoint-Profile-User-Manual-V113.pdf), including Modbus Instructions. + * - [GroPoint Profile Technical Info](https://www.gropoint.com/s/GroPoint-Profile-Technical-Info.pdf) + * * + * @section sensor_gplp8_ctor Sensor Constructor + * {{ @ref GroPointGPLP8::GroPointGPLP8 }} + * + * ___ + * @section sensor_gplp8_examples Example Code + * The GPLP-8 Probe is used in the @menulink{gro_point_gplp8} example. + * + * @menusnip{gro_point_gplp8} + */ +/* clang-format on */ + +// Header Guards +#ifndef SRC_SENSORS_GROPOINTGPLP8_H_ +#define SRC_SENSORS_GROPOINTGPLP8_H_ + +// Included Dependencies +#include "sensors/GroPointParent.h" + +/** @ingroup sensor_gplp8 */ +/**@{*/ + +// Sensor Specific Defines +/// @brief Sensor::_numReturnedValues; the GPLP8 can report 8 values. +#define GPLP8_NUM_VARIABLES 21 +/// @brief Sensor::_incCalcValues; we don't calculate any additional values. +#define GPLP8_INC_CALC_VARIABLES 0 + +/** + * @anchor sensor_gplp8_timing + * @name Sensor Timing + * The sensor timing for a GroPoint Profile GPLP-8 + */ +/**@{*/ +/** + * @brief Sensor::_warmUpTime_ms; time before sensor responds after power - 1.6 + * seconds (1600ms). + * + * This is the time for communication to begin. + */ +#define GPLP8_WARM_UP_TIME_MS 350 +/** + * @brief Sensor::_stabilizationTime_ms; the GPLP-8 is stable after 100 ms. + * + */ +#define GPLP8_STABILIZATION_TIME_MS 100 +/// @brief Sensor::_measurementTime_ms; the GPLP-8 takes ~200 ms to complete a +/// measurement. +#define GPLP8_MEASUREMENT_TIME_MS 200 +/**@}*/ + +/** + * @anchor sensor_gplp8_moist + * @name Moisture + * The volumetric soil moisture variable from a GroPoint Profile GPLP-8 + * - Range is 0% to 50% volumetric water content + * - Accuracy is ± 1% + * + * {{ @ref GroPointGPLP8_Moist::GroPointGPLP8_Moist }} + */ +/**@{*/ +/// @brief Decimals places in string representation; soil moisture should have 1 +/// - resolution is 0.1 %. +#define GPLP8_MOIST_RESOLUTION 1 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +#define GPLP8_MOIST_VAR_NAME "volumetricWaterContent" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +#define GPLP8_MOIST_UNIT_NAME "percent" +/// @brief Default variable short code; "GPLP8Moist" +#define GPLP8_MOIST_DEFAULT_CODE "GPLP8Moist" +/**@}*/ + +/** + * @anchor sensor_gplp8_temp + * @name Temperature + * The temperature variable from a GroPoint Profile GPLP-8 + * - Range is -20°C to + 70°C + * - Accuracy is ± 0.5°C + * + * {{ @ref GroPointGPLP8_Temp::GroPointGPLP8_Temp }} + */ +/**@{*/ +/// @brief Decimals places in string representation; temperature should have 1 - +/// resolution is 0.1°C. +#define GPLP8_TEMP_RESOLUTION 1 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +/// "temperature" +#define GPLP8_TEMP_VAR_NAME "temperature" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +/// "degreeCelsius" (°C) +#define GPLP8_TEMP_UNIT_NAME "degreeCelsius" +/// @brief Default variable short code; "GPLP8Temp" +#define GPLP8_TEMP_DEFAULT_CODE "GPLP8Temp" +/**@}*/ + + +/* clang-format off */ +/** + * @brief The Sensor sub-class for the + * [GroPoint Profile GPLP8 probe](@ref sensor_gplp8). + * + * @ingroup sensor_gplp8 + */ +/* clang-format on */ +class GroPointGPLP8 : public GroPointParent { + public: + // Constructors with overloads + /** + * @brief Construct a new GroPoint GPLP8 object. + * + * @param modbusAddress The modbus address of the sensor. + * @param stream An Arduino data stream for modbus communication. See + * [notes](@ref page_arduino_streams) for more information on what streams + * can be used. + * @param powerPin The pin on the mcu controlling power to the GPLP-8. + * Use -1 if it is continuously powered. + * @param powerPin2 The pin on the mcu controlling power to the RS485 + * adapter, if it is different from that used to power the sensor. Use -1 + * or omit if not applicable. + * @param enablePin The pin on the mcu controlling the direction enable on + * the RS485 adapter, if necessary; use -1 or omit if not applicable. + * @note An RS485 adapter with integrated flow control is strongly + * recommended. + * @param measurementsToAverage The number of measurements to take and + * average before giving a "final" result from the sensor; optional with a + * default value of 1. + */ + GroPointGPLP8(byte modbusAddress, Stream* stream, int8_t powerPin, + int8_t powerPin2 = -1, int8_t enablePin = -1, + uint8_t measurementsToAverage = 1) + : GroPointParent(modbusAddress, stream, powerPin, powerPin2, enablePin, + measurementsToAverage, GPLP8, "GroPointGPLP8", + GPLP8_NUM_VARIABLES, GPLP8_WARM_UP_TIME_MS, + GPLP8_STABILIZATION_TIME_MS, GPLP8_MEASUREMENT_TIME_MS, + GPLP8_INC_CALC_VARIABLES) {} + /** + * @copydoc GroPointGPLP8::GroPointGPLP8 + */ + GroPointGPLP8(byte modbusAddress, Stream& stream, int8_t powerPin, + int8_t powerPin2 = -1, int8_t enablePin = -1, + uint8_t measurementsToAverage = 1) + : GroPointParent(modbusAddress, stream, powerPin, powerPin2, enablePin, + measurementsToAverage, GPLP8, "GroPointGPLP8", + GPLP8_NUM_VARIABLES, GPLP8_WARM_UP_TIME_MS, + GPLP8_STABILIZATION_TIME_MS, GPLP8_MEASUREMENT_TIME_MS, + GPLP8_INC_CALC_VARIABLES) {} + /** + * @brief Destroy the GroPoint GPLP8 object + */ + ~GroPointGPLP8() {} +}; + + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [soil moisture output](@ref sensor_gplp8_moist) from a + * [GroPoint Profile GPLP8 probe](@ref sensor_gplp8). + * + * @ingroup sensor_gplp8 + */ +/* clang-format on */ +class GroPointGPLP8_Moist : public Variable { + public: + /** + * @brief Construct a new GroPointGPLP8_Moist object. + * + * @param parentSense The parent GroPointGPLP8 providing the result + * values. + * @param sensorVarNum The position the variable result holds in the + * variable result array. The GroPoint GPLP8 can have up to 8 soil moisture + * results. When creating the variable for soil moisture, you must specify + * the output number from the sensor. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "GPLP8Moist". + */ + explicit GroPointGPLP8_Moist(GroPointGPLP8* parentSense, + const uint8_t sensorVarNum, + const char* uuid = "", + const char* varCode = GPLP8_MOIST_DEFAULT_CODE) + : Variable(parentSense, sensorVarNum, (uint8_t)GPLP8_MOIST_RESOLUTION, + GPLP8_MOIST_VAR_NAME, GPLP8_MOIST_UNIT_NAME, varCode, uuid) { + } + /** + * @brief Construct a new GroPointGPLP8_Moist object. + * + * @param sensorVarNum The position the variable result holds in the + * variable result array. The GroPoint GPLP8 can have up to 8 soil moisture + * results. When creating the variable for soil moisture, you must specify + * the output number from the sensor. + * + * @note This must be tied with a parent GroPointGPLP8 before it can be + * used. + */ + GroPointGPLP8_Moist(const uint8_t sensorVarNum) + : Variable(sensorVarNum, (uint8_t)GPLP8_MOIST_RESOLUTION, + GPLP8_MOIST_VAR_NAME, GPLP8_MOIST_UNIT_NAME, + GPLP8_MOIST_DEFAULT_CODE) {} + /** + * @brief Destroy the GroPointGPLP8_Moist object - no action needed. + */ + ~GroPointGPLP8_Moist() {} +}; + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [temperature output](@ref sensor_gplp8_temp) from a + * [GroPoint Profile GPLP8 probe](@ref sensor_gplp8). + * + * @ingroup sensor_gplp8 + */ +/* clang-format on */ +class GroPointGPLP8_Temp : public Variable { + public: + /** + * @brief Construct a new GroPointGPLP8_Temp object. + * + * @param parentSense The parent GroPointGPLP8 providing the result + * values. + * @param sensorVarNum The position the variable result holds in the + * variable result array. The GroPoint GPLP8 can have up to 8 temperature + * results. When creating the variable for temperature, you must specify the + * output number from the sensor. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "GPLP8Temp". + */ + explicit GroPointGPLP8_Temp(GroPointGPLP8* parentSense, + const uint8_t sensorVarNum, + const char* uuid = "", + const char* varCode = GPLP8_TEMP_DEFAULT_CODE) + : Variable(parentSense, sensorVarNum, (uint8_t)GPLP8_TEMP_RESOLUTION, + GPLP8_TEMP_VAR_NAME, GPLP8_TEMP_UNIT_NAME, varCode, uuid) {} + /** + * @brief Construct a new GroPointGPLP8_Temp object. + * + * @param sensorVarNum The position the variable result holds in the + * variable result array. The GroPoint GPLP8 can have up to 8 temperature + * results. When creating the variable for temperature, you must specify the + * output number from the sensor. + * + * @note This must be tied with a parent GroPointGPLP8 before it can be + * used. + */ + GroPointGPLP8_Temp(const uint8_t sensorVarNum) + : Variable(sensorVarNum, (uint8_t)GPLP8_TEMP_RESOLUTION, + GPLP8_TEMP_VAR_NAME, GPLP8_TEMP_UNIT_NAME, + GPLP8_TEMP_DEFAULT_CODE) {} + /** + * @brief Destroy the GroPointGPLP8_Temp object - no action needed. + */ + ~GroPointGPLP8_Temp() {} +}; + +/**@}*/ +#endif // SRC_SENSORS_GROPOINTGPLP8_H_ diff --git a/src/sensors/GroPointParent.cpp b/src/sensors/GroPointParent.cpp new file mode 100644 index 000000000..038b4f768 --- /dev/null +++ b/src/sensors/GroPointParent.cpp @@ -0,0 +1,302 @@ +/** + * @file GroPointParent.cpp + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. + * @author Anthony Aufdenkampe + * + * @brief Implements the GroPointParent class. + */ + +#include "GroPointParent.h" + +// The constructor - need the sensor type, modbus address, power pin, stream for +// data, and number of readings to average +GroPointParent::GroPointParent(byte modbusAddress, Stream* stream, + int8_t powerPin, int8_t powerPin2, + int8_t enablePin, uint8_t measurementsToAverage, + gropointModel model, const char* sensName, + uint8_t numVariables, uint32_t warmUpTime_ms, + uint32_t stabilizationTime_ms, + uint32_t measurementTime_ms, + uint8_t incCalcValues) + : Sensor(sensName, numVariables, warmUpTime_ms, stabilizationTime_ms, + measurementTime_ms, powerPin, -1, measurementsToAverage, + incCalcValues), + _model(model), + _modbusAddress(modbusAddress), + _stream(stream), + _RS485EnablePin(enablePin), + _powerPin2(powerPin2) {} +GroPointParent::GroPointParent(byte modbusAddress, Stream& stream, + int8_t powerPin, int8_t powerPin2, + int8_t enablePin, uint8_t measurementsToAverage, + gropointModel model, const char* sensName, + uint8_t numVariables, uint32_t warmUpTime_ms, + uint32_t stabilizationTime_ms, + uint32_t measurementTime_ms, + uint8_t incCalcValues) + : Sensor(sensName, numVariables, warmUpTime_ms, stabilizationTime_ms, + measurementTime_ms, powerPin, -1, measurementsToAverage, + incCalcValues), + _model(model), + _modbusAddress(modbusAddress), + _stream(&stream), + _RS485EnablePin(enablePin), + _powerPin2(powerPin2) {} +// Destructor +GroPointParent::~GroPointParent() {} + + +// The sensor installation location on the Mayfly +String GroPointParent::getSensorLocation(void) { + String sensorLocation = F("modbus_0x"); + if (_modbusAddress < 16) sensorLocation += "0"; + sensorLocation += String(_modbusAddress, HEX); + return sensorLocation; +} + + +bool GroPointParent::setup(void) { + bool retVal = + Sensor::setup(); // this will set pin modes and the setup status bit + if (_RS485EnablePin >= 0) pinMode(_RS485EnablePin, OUTPUT); + if (_powerPin2 >= 0) pinMode(_powerPin2, OUTPUT); + +#ifdef MS_GROPOINTPARENT_DEBUG_DEEP + _gsensor.setDebugStream(&DEEP_DEBUGGING_SERIAL_OUTPUT); +#endif + + // This sensor begin is just setting more pin modes, etc, no sensor power + // required This realy can't fail so adding the return value is just for + // show + retVal &= _gsensor.begin(_model, _modbusAddress, _stream, _RS485EnablePin); + + return retVal; +} + + +// The function to wake up a sensor +// Different from the standard in that it waits for warm up and starts +// measurements +bool GroPointParent::wake(void) { + // Sensor::wake() checks if the power pin is on and sets the wake timestamp + // and status bits. If it returns false, there's no reason to go on. + if (!Sensor::wake()) return false; + + // Send the command to begin taking readings, trying up to 5 times + bool success = false; + uint8_t ntries = 0; + MS_DBG(F("Start Measurement on"), getSensorNameAndLocation()); + while (!success && ntries < 5) { + MS_DBG('(', ntries + 1, F("):")); + success = _gsensor.startMeasurement(); + ntries++; + } + + if (success) { + // Update the time that the sensor was activated + _millisSensorActivated = millis(); + MS_DBG(getSensorNameAndLocation(), F("activated and measuring.")); + } else { + MS_DBG(getSensorNameAndLocation(), F("was NOT activated!")); + // Make sure the activation time is zero and the wake success bit (bit + // 4) is unset + _millisSensorActivated = 0; + _sensorStatus &= 0b11101111; + } + + return success; +} + + +// The function to put the sensor to sleep +// Different from the standard in that it stops measurements +bool GroPointParent::sleep(void) { + if (!checkPowerOn()) { return true; } + if (_millisSensorActivated == 0) { + MS_DBG(getSensorNameAndLocation(), F("was not measuring!")); + return true; + } + + // Send the command to begin taking readings, trying up to 5 times + bool success = false; + uint8_t ntries = 0; + MS_DBG(F("Stop Measurement on"), getSensorNameAndLocation()); + while (!success && ntries < 5) { + MS_DBG('(', ntries + 1, F("):")); + success = _gsensor.stopMeasurement(); + ntries++; + } + if (success) { + // Unset the activation time + _millisSensorActivated = 0; + // Unset the measurement request time + _millisMeasurementRequested = 0; + // Unset the status bits for sensor activation (bits 3 & 4) and + // measurement request (bits 5 & 6) + _sensorStatus &= 0b10000111; + MS_DBG(F("Measurements stopped.")); + } else { + MS_DBG(F("Measurements NOT stopped!")); + } + + return success; +} + + +// This turns on sensor power +void GroPointParent::powerUp(void) { + if (_powerPin >= 0) { + MS_DBG(F("Powering"), getSensorNameAndLocation(), F("with pin"), + _powerPin); + digitalWrite(_powerPin, HIGH); + // Mark the time that the sensor was powered + _millisPowerOn = millis(); + } + if (_powerPin2 >= 0) { + MS_DBG(F("Applying secondary power to"), getSensorNameAndLocation(), + F("with pin"), _powerPin2); + digitalWrite(_powerPin2, HIGH); + } + if (_powerPin < 0 && _powerPin2 < 0) { + MS_DBG(F("Power to"), getSensorNameAndLocation(), + F("is not controlled by this library.")); + } + // Set the status bit for sensor power attempt (bit 1) and success (bit 2) + _sensorStatus |= 0b00000110; +} + + +// This turns off sensor power +void GroPointParent::powerDown(void) { + if (_powerPin >= 0) { + MS_DBG(F("Turning off power to"), getSensorNameAndLocation(), + F("with pin"), _powerPin); + digitalWrite(_powerPin, LOW); + // Unset the power-on time + _millisPowerOn = 0; + // Unset the activation time + _millisSensorActivated = 0; + // Unset the measurement request time + _millisMeasurementRequested = 0; + // Unset the status bits for sensor power (bits 1 & 2), + // activation (bits 3 & 4), and measurement request (bits 5 & 6) + _sensorStatus &= 0b10000001; + } + if (_powerPin2 >= 0) { + MS_DBG(F("Turning off secondary power to"), getSensorNameAndLocation(), + F("with pin"), _powerPin2); + digitalWrite(_powerPin2, LOW); + } + if (_powerPin < 0 && _powerPin2 < 0) { + MS_DBG(F("Power to"), getSensorNameAndLocation(), + F("is not controlled by this library.")); + // Do NOT unset any status bits or timestamps if we didn't really power + // down! + } +} + + +bool GroPointParent::addSingleMeasurementResult(void) { + bool success = false; + bool successT = false; + // Initialize moisture variables for each probe segement + float M1, M2, M3, M4, M5, M6, M7, M8 = -9999; + // Initialize temperature variables for each probe sensor + float T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 = -9999; + + // Check a measurement was *successfully* started (status bit 6 set) + // Only go on to get a result if it was + if (bitRead(_sensorStatus, 6)) { + switch (_model) { + case GPLP8: { + // Get Moisture Values + MS_DBG(F("Get Values from"), getSensorNameAndLocation()); + success = _gsensor.getValues(M1, M2, M3, M4, M5, M6, M7, M8); + + // Fix not-a-number values + if (!success || isnan(M1)) M1 = -9999; + if (!success || isnan(M2)) M2 = -9999; + if (!success || isnan(M3)) M3 = -9999; + if (!success || isnan(M4)) M4 = -9999; + if (!success || isnan(M5)) M5 = -9999; + if (!success || isnan(M6)) M6 = -9999; + if (!success || isnan(M7)) M7 = -9999; + if (!success || isnan(M8)) M8 = -9999; + + MS_DBG(F(" "), _gsensor.getParameter()); + MS_DBG(F(" "), _gsensor.getUnits()); + MS_DBG(F(" "), M1, ',', M2, ',', M3, ',', M4, ',', M5, ',', + M6, ',', M7, ',', M8); + + // Get Temperature Values + successT = _gsensor.getTemperatureValues( + T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); + + // Fix not-a-number values + if (!successT || isnan(T1)) T1 = -9999; + if (!successT || isnan(T2)) T2 = -9999; + if (!successT || isnan(T3)) T3 = -9999; + if (!successT || isnan(T4)) T4 = -9999; + if (!successT || isnan(T5)) T5 = -9999; + if (!successT || isnan(T6)) T6 = -9999; + if (!successT || isnan(T7)) T7 = -9999; + if (!successT || isnan(T8)) T8 = -9999; + if (!successT || isnan(T9)) T9 = -9999; + if (!successT || isnan(T10)) T10 = -9999; + if (!successT || isnan(T11)) T11 = -9999; + if (!successT || isnan(T12)) T12 = -9999; + if (!successT || isnan(T13)) T13 = -9999; + + MS_DBG(F(" "), _gsensor.getParameter1()); + MS_DBG(F(" "), _gsensor.getUnits1()); + MS_DBG(F(" "), T1, ',', T2, ',', T3, ',', T4, ',', T5, ',', + T6, ',', T7, ',', T8, ',', T9, ',', T10, ',', T11, ',', + T12, ',', T13); + + + // Put values into the array + verifyAndAddMeasurementResult(0, M1); + verifyAndAddMeasurementResult(1, M2); + verifyAndAddMeasurementResult(2, M3); + verifyAndAddMeasurementResult(3, M4); + verifyAndAddMeasurementResult(4, M5); + verifyAndAddMeasurementResult(5, M6); + verifyAndAddMeasurementResult(6, M7); + verifyAndAddMeasurementResult(7, M8); + + verifyAndAddMeasurementResult(8, T1); + verifyAndAddMeasurementResult(9, T2); + verifyAndAddMeasurementResult(10, T3); + verifyAndAddMeasurementResult(11, T4); + verifyAndAddMeasurementResult(12, T5); + verifyAndAddMeasurementResult(13, T6); + verifyAndAddMeasurementResult(14, T7); + verifyAndAddMeasurementResult(15, T8); + verifyAndAddMeasurementResult(16, T9); + verifyAndAddMeasurementResult(17, T10); + verifyAndAddMeasurementResult(18, T11); + verifyAndAddMeasurementResult(19, T12); + verifyAndAddMeasurementResult(20, T13); + + + break; + } + default: { + // Get Values + MS_DBG(F("Other GroPoint models not yet implemented.")); + } + } + } else { + MS_DBG(getSensorNameAndLocation(), F("is not currently measuring!")); + } + + // Unset the time stamp for the beginning of this measurement + _millisMeasurementRequested = 0; + // Unset the status bits for a measurement request (bits 5 & 6) + _sensorStatus &= 0b10011111; + + // Return true when finished + return success && successT; +} diff --git a/src/sensors/GroPointParent.h b/src/sensors/GroPointParent.h new file mode 100644 index 000000000..8a27f0b59 --- /dev/null +++ b/src/sensors/GroPointParent.h @@ -0,0 +1,211 @@ +/** + * @file GroPointParent.cpp + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. + * @author Anthony Aufdenkampe + * + * @brief Contains the GroPointParent sensor subclass, itself a parent + * class for all GroPoint Soil Moisture and Temperature sensors + * that communicate via SDI-12 or Modbus. + * NOTE: Presently this library only supports Modbus communication and GroPoint + * Profile Multi Segment Soil Moisture & Temperature Profiling Probes (GPLP-X) + * via the EnviroDIY GroPointModbus library. + * + * Documentation for the GroPointModbus Modbus Protocol commands and responses, + * along with information about the various variables, can be found in the + * EnviroDIY GroPointModbus library at: + * https://github.com/EnviroDIY/GroPointModbus + */ +/* clang-format off */ +/** + * @defgroup gropoint_group GroPoint Sensors + * The Sensor and Variable objects for all GroPoint sensors. + * + * @ingroup the_sensors + * + * + * This library currently supports the following [GroPoint](https://www.gropoint.com) sensors: + * - [GroPoint Profile GPLP-8](https://www.gropoint.com/products/soil-sensors/gropoint-profile), 8-Segment Soil Moisture & Temperature Profiling Probe + * - [GroPoint Profile User Manual](https://www.gropoint.com/s/2625-N-T-GroPoint-Profile-User-Manual-V113.pdf), including Modbus Instructions. + * - [GroPoint Profile Technical Info](https://www.gropoint.com/s/GroPoint-Profile-Technical-Info.pdf) + * - [Class Documentation](@ref sensor_gplp8) + * + * These sensors operate a 7.5 to 14.0 VDC power supply (Max 18.0 VDC). The power supply can be stopped between measurements for all. + * They communicate via [Modbus RTU](https://en.wikipedia.org/wiki/Modbus) over [RS-485](https://en.wikipedia.org/wiki/RS-485). + * To interface with them, you will need an RS485-to-TTL adapter. + * + * The sensor constructor requires as input: the sensor modbus address, a stream instance for data (ie, ```Serial```), and one or two power pins. + * The Arduino pin controlling the receive and data enable on your RS485-to-TTL adapter and the number of readings to average are optional. + * (Use -1 for the second power pin and -1 for the enable pin if these don't apply and you want to average more than one reading.) + * Please see the section "[Notes on Arduino Streams and Software Serial](@ref page_arduino_streams)" + * for more information about what streams can be used along with this library. + * In tests on these sensors, SoftwareSerial_ExtInts _did not work_ to communicate with these sensors, because it isn't stable enough. + * AltSoftSerial and HardwareSerial work fine. + * Up to two power pins are provided so that the RS485 adapter, the sensor and/or an external power relay can be controlled separately. + * If the power to everything is controlled by the same pin, use -1 for the second power pin or omit the argument. + * If they are controlled by different pins _and no other sensors are dependent on power from either pin_ then the order of the pins doesn't matter. + * If the RS485 adapter, sensor, or relay are controlled by different pins _and any other sensors are controlled by the same pins_ you should put the shared pin first and the un-shared pin second. + * Both pins _cannot_ be shared pins. + * + * By default, this library cuts power to the sensors between readings, causing them to lose track of their brushing interval. + * The library manually activates the brushes as part of the "wake" command. + * There are currently no other ways to set the brushing interval in this library. + * + * The lower level details of the communication with the sensors is managed by the + * [EnviroDIY GroPointModbus library](https://github.com/EnviroDIY/GroPointModbus) + */ +/* clang-format on */ + +// Header Guards +#ifndef SRC_SENSORS_GROPOINTPARENT_H_ +#define SRC_SENSORS_GROPOINTPARENT_H_ + +// Debugging Statement +// #define MS_GROPOINTPARENT_DEBUG +// #define MS_GROPOINTPARENT_DEBUG_DEEP + +#ifdef MS_GROPOINTPARENT_DEBUG +#define MS_DEBUGGING_STD "GroPointParent" +#endif + +#ifdef MS_GROPOINTPARENT_DEBUG_DEEP +#define MS_DEBUGGING_DEEP "GroPointParent" +#endif + +// Included Dependencies +#include "ModSensorDebugger.h" +#undef MS_DEBUGGING_STD +#undef MS_DEBUGGING_DEEP +#include "VariableBase.h" +#include "SensorBase.h" +#include "GroPointModbus.h" + +/* clang-format off */ +/** + * @brief The Sensor sub-class for all the [GroPoint sensors](@ref gropoint_group) + * + * @ingroup gropoint_group + */ +/* clang-format on */ +class GroPointParent : public Sensor { + public: + /** + * @brief Construct a new GroPoint Parent object. This is only intended + * to be used within this library. + * + * @param modbusAddress The modbus address of the sensor. + * @param stream An Arduino data stream for modbus communication. See + * [notes](@ref page_arduino_streams) for more information on what streams + * can be used. + * @param powerPin The pin on the mcu controlling power to the GroPoint. + * Use -1 if it is continuously powered. + * @param powerPin2 The pin on the mcu controlling power to the RS485 + * adapter, if it is different from that used to power the sensor. Use -1 + * or omit if not applicable. + * @param enablePin The pin on the mcu controlling the direction enable on + * the RS485 adapter, if necessary; use -1 or omit if not applicable. An + * RS485 adapter with integrated flow control is strongly recommended. + * @param measurementsToAverage The number of measurements to take and + * average before giving a "final" result from the sensor; optional with a + * default value of 1. + * @param model The model of GroPoint sensor. + * @param sensName The name of the sensor. Defaults to "SDI12-Sensor". + * @param numVariables The number of variable results returned by the + * sensor. Defaults to 2. + * @param warmUpTime_ms The time in ms between when the sensor is powered on + * and when it is ready to receive a wake command. Defaults to 1500. + * @param stabilizationTime_ms The time in ms between when the sensor + * receives a wake command and when it is able to return stable values. + * Defaults to 20,000 (20s). + * @param measurementTime_ms The time in ms between when a measurement is + * started and when the result value is available. Defaults to 2000. + * @param incCalcValues The number of included calculated variables from the + * sensor, if any. These are used for values that we would always calculate + * for a sensor and depend only on the raw results of that single sensor; + * optional with a default value of 0. + */ + GroPointParent(byte modbusAddress, Stream* stream, int8_t powerPin, + int8_t powerPin2, int8_t enablePin = -1, + uint8_t measurementsToAverage = 1, + gropointModel model = GPLPX, + const char* sensName = "GroPoint-Sensor", + uint8_t numVariables = 2, uint32_t warmUpTime_ms = 350, + uint32_t stabilizationTime_ms = 100, + uint32_t measurementTime_ms = 200, + uint8_t incCalcValues = 0); + /** + * @copydoc GroPointParent::GroPointParent + */ + GroPointParent(byte modbusAddress, Stream& stream, int8_t powerPin, + int8_t powerPin2, int8_t enablePin = -1, + uint8_t measurementsToAverage = 1, + gropointModel model = GPLPX, + const char* sensName = "GroPoint-Sensor", + uint8_t numVariables = 2, uint32_t warmUpTime_ms = 350, + uint32_t stabilizationTime_ms = 100, + uint32_t measurementTime_ms = 200, + uint8_t incCalcValues = 0); + /** + * @brief Destroy the GroPoint Parent object - no action taken + */ + virtual ~GroPointParent(); + + /** + * @copydoc Sensor::getSensorLocation() + */ + String getSensorLocation(void) override; + + /** + * @brief Do any one-time preparations needed before the sensor will be able + * to take readings. + * + * This sets pin modes on the #_powerPin, adapter power, and adapter + * enable pins. It also sets the expected stream timeout for modbus and + * updates the #_sensorStatus. No sensor power is required. This will + * always return true. + * + * @return **bool** True if the setup was successful. + */ + bool setup(void) override; + /** + * @brief Wake the sensor up, if necessary. Do whatever it takes to get a + * sensor in the proper state to begin a measurement. + * + * Verifies that the power is on and updates the #_sensorStatus. This also + * sets the #_millisSensorActivated timestamp. + * + * @note This does NOT include any wait for sensor readiness. + * + * @return **bool** True if the wake function completed successfully. + */ + bool wake(void) override; + /** + * @brief Puts the sensor to sleep, if necessary. + * + * This also un-sets the #_millisSensorActivated timestamp (sets it to 0). + * This does NOT power down the sensor! + * + * @return **bool** True if the sleep function completed successfully. + */ + bool sleep(void) override; + + // Override these to use two power pins + void powerUp(void) override; + void powerDown(void) override; + + /** + * @copydoc Sensor::addSingleMeasurementResult() + */ + bool addSingleMeasurementResult(void) override; + + private: + gropoint _gsensor; + gropointModel _model; + byte _modbusAddress; + Stream* _stream; + int8_t _RS485EnablePin; + int8_t _powerPin2; +}; + +#endif // SRC_SENSORS_GROPOINTPARENT_H_ diff --git a/src/sensors/InSituRDO.h b/src/sensors/InSituRDO.h index 5c468ef33..09e43ba9e 100644 --- a/src/sensors/InSituRDO.h +++ b/src/sensors/InSituRDO.h @@ -1,7 +1,8 @@ /** * @file InSituRDO.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the InSituRDO sensor subclass and the variable subclasses diff --git a/src/sensors/InSituTrollSdi12a.h b/src/sensors/InSituTrollSdi12a.h index 442f60895..b8031cd84 100644 --- a/src/sensors/InSituTrollSdi12a.h +++ b/src/sensors/InSituTrollSdi12a.h @@ -1,7 +1,8 @@ /* * @file InSituTrollSdi12a.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY modular sensors + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Neil Hancock https://github.com/neilh10/ModularSensors/ * @author Sara Geleskie Damiano * diff --git a/src/sensors/KellerAcculevel.h b/src/sensors/KellerAcculevel.h index 7a60fbd1b..45e81a439 100644 --- a/src/sensors/KellerAcculevel.h +++ b/src/sensors/KellerAcculevel.h @@ -1,7 +1,8 @@ /** * @file KellerAcculevel.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/KellerNanolevel.h b/src/sensors/KellerNanolevel.h index e3449d7a7..bcffae086 100644 --- a/src/sensors/KellerNanolevel.h +++ b/src/sensors/KellerNanolevel.h @@ -1,7 +1,8 @@ /** * @file KellerNanolevel.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe and Neil * Hancock Edited by Sara Geleskie Damiano * diff --git a/src/sensors/KellerParent.cpp b/src/sensors/KellerParent.cpp index ff51a1e3e..532db6927 100644 --- a/src/sensors/KellerParent.cpp +++ b/src/sensors/KellerParent.cpp @@ -1,7 +1,8 @@ /** * @file KellerParent.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * @@ -62,7 +63,7 @@ bool KellerParent::setup(void) { if (_powerPin2 >= 0) pinMode(_powerPin2, OUTPUT); #ifdef MS_KELLERPARENT_DEBUG_DEEP - sensor.setDebugStream(&DEEP_DEBUGGING_SERIAL_OUTPUT); + _ksensor.setDebugStream(&DEEP_DEBUGGING_SERIAL_OUTPUT); #endif // This sensor begin is just setting more pin modes, etc, no sensor power diff --git a/src/sensors/KellerParent.h b/src/sensors/KellerParent.h index 98e26e490..98e7c70b1 100644 --- a/src/sensors/KellerParent.h +++ b/src/sensors/KellerParent.h @@ -1,7 +1,8 @@ /** * @file KellerParent.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/MaxBotixSonar.cpp b/src/sensors/MaxBotixSonar.cpp index 001d1093d..84dfac7b8 100644 --- a/src/sensors/MaxBotixSonar.cpp +++ b/src/sensors/MaxBotixSonar.cpp @@ -1,7 +1,8 @@ /** * @file MaxBotixSonar.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the MaxBotixSonar class. diff --git a/src/sensors/MaxBotixSonar.h b/src/sensors/MaxBotixSonar.h index 676886f6f..8c0a43b06 100644 --- a/src/sensors/MaxBotixSonar.h +++ b/src/sensors/MaxBotixSonar.h @@ -1,7 +1,8 @@ /** * @file MaxBotixSonar.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the MaxBotixSonar sensor subclass and the MaxBotixSonar_Range diff --git a/src/sensors/MaximDS18.cpp b/src/sensors/MaximDS18.cpp index d1f6d010c..93946c6b4 100644 --- a/src/sensors/MaximDS18.cpp +++ b/src/sensors/MaximDS18.cpp @@ -1,7 +1,8 @@ /** * @file MaximDS18.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the MaximDS18 class. diff --git a/src/sensors/MaximDS18.h b/src/sensors/MaximDS18.h index d5de1c32d..09562d726 100644 --- a/src/sensors/MaximDS18.h +++ b/src/sensors/MaximDS18.h @@ -1,7 +1,8 @@ /** * @file MaximDS18.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the MaximDS18 sensor subclass and the MaximDS18_Temp variable diff --git a/src/sensors/MaximDS3231.cpp b/src/sensors/MaximDS3231.cpp index e5d601909..21431a0ff 100644 --- a/src/sensors/MaximDS3231.cpp +++ b/src/sensors/MaximDS3231.cpp @@ -1,7 +1,8 @@ /** * @file MaximDS3231.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the MaximDS18 class. diff --git a/src/sensors/MaximDS3231.h b/src/sensors/MaximDS3231.h index 9be37f0fc..42f0f9b98 100644 --- a/src/sensors/MaximDS3231.h +++ b/src/sensors/MaximDS3231.h @@ -1,7 +1,8 @@ /** * @file MaximDS3231.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the MaximDS3231 sensor subclass and the MaximDS3231_Temp diff --git a/src/sensors/MeaSpecMS5803.cpp b/src/sensors/MeaSpecMS5803.cpp index 7569ba6a1..0e2a9ca84 100644 --- a/src/sensors/MeaSpecMS5803.cpp +++ b/src/sensors/MeaSpecMS5803.cpp @@ -1,7 +1,8 @@ /** * @file MeaSpecMS5803.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Anthony Aufdenkampe with help from Beth * Fisher, Evan Host and Bobby Schulz. * Edited by Sara Geleskie Damiano diff --git a/src/sensors/MeaSpecMS5803.h b/src/sensors/MeaSpecMS5803.h index e16650782..f8c764685 100644 --- a/src/sensors/MeaSpecMS5803.h +++ b/src/sensors/MeaSpecMS5803.h @@ -1,7 +1,8 @@ /** * @file MeaSpecMS5803.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Anthony Aufdenkampe with help from Beth * Fisher, Evan Host and Bobby Schulz. * Heavliy edited by Sara Geleskie Damiano diff --git a/src/sensors/MeterHydros21.h b/src/sensors/MeterHydros21.h index e948c4751..f66b8f926 100644 --- a/src/sensors/MeterHydros21.h +++ b/src/sensors/MeterHydros21.h @@ -1,7 +1,8 @@ /** * @file MeterHydros21.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the MeterHydros21 subclass of the SDI12Sensors class along diff --git a/src/sensors/MeterTeros11.cpp b/src/sensors/MeterTeros11.cpp index bf8dab12c..d6e4b4e15 100644 --- a/src/sensors/MeterTeros11.cpp +++ b/src/sensors/MeterTeros11.cpp @@ -1,7 +1,8 @@ /** * @file MeterTeros11.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/MeterTeros11.h b/src/sensors/MeterTeros11.h index d75b7b777..6f8b92361 100644 --- a/src/sensors/MeterTeros11.h +++ b/src/sensors/MeterTeros11.h @@ -1,7 +1,8 @@ /** * @file MeterTeros11.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/PaleoTerraRedox.h b/src/sensors/PaleoTerraRedox.h index 64a4c8ce1..6419bf0cc 100644 --- a/src/sensors/PaleoTerraRedox.h +++ b/src/sensors/PaleoTerraRedox.h @@ -1,7 +1,8 @@ /** * @file PaleoTerraRedox.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Anthony Aufdenkampe with help from Beth * Fisher, Evan Host and Bobby Schulz. * Heavliy edited by Sara Geleskie Damiano diff --git a/src/sensors/ProcessorStats.cpp b/src/sensors/ProcessorStats.cpp index 3dd860646..2a964fadd 100644 --- a/src/sensors/ProcessorStats.cpp +++ b/src/sensors/ProcessorStats.cpp @@ -1,7 +1,8 @@ /** * @file ProcessorStats.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the ProcessorStats class. @@ -136,7 +137,7 @@ int16_t FreeRam() { bool ProcessorStats::addSingleMeasurementResult(void) { // Get the battery voltage - MS_DBG(F("Getting battery voltage")); + MS_DBG(F("Getting battery voltage from pin"), _batteryPin); float sensorValue_battery = -9999; @@ -146,8 +147,10 @@ bool ProcessorStats::addSingleMeasurementResult(void) { // The return value from analogRead() is IN BITS NOT IN VOLTS!! analogRead(_batteryPin); // priming reading float rawBattery = analogRead(_batteryPin); + MS_DBG(F("Raw battery pin reading in bits:"), rawBattery); // convert bits to volts sensorValue_battery = (3.3 / 1023.) * 1.47 * rawBattery; + MS_DBG(F("Battery in Volts:"), sensorValue_battery); } if (strcmp(_version, "v0.5") == 0 || strcmp(_version, "v0.5b") || strcmp(_version, "v1.0") || strcmp(_version, "v1.1") == 0) { @@ -155,8 +158,10 @@ bool ProcessorStats::addSingleMeasurementResult(void) { // The return value from analogRead() is IN BITS NOT IN VOLTS!! analogRead(_batteryPin); // priming reading float rawBattery = analogRead(_batteryPin); + MS_DBG(F("Raw battery pin reading in bits:"), rawBattery); // convert bits to volts sensorValue_battery = (3.3 / 1023.) * 4.7 * rawBattery; + MS_DBG(F("Battery in Volts:"), sensorValue_battery); } #elif defined(ARDUINO_AVR_FEATHER32U4) || defined(ARDUINO_SAMD_FEATHER_M0) || \ @@ -170,20 +175,26 @@ bool ProcessorStats::addSingleMeasurementResult(void) { #elif defined(ARDUINO_SODAQ_ONE) || defined(ARDUINO_SODAQ_ONE_BETA) if (strcmp(_version, "v0.1") == 0) { // Get the battery voltage - float rawBattery = analogRead(_batteryPin); + float rawBattery = analogRead(_batteryPin); + MS_DBG(F("Raw battery pin reading in bits:"), rawBattery); sensorValue_battery = (3.3 / 1023.) * 2 * rawBattery; + MS_DBG(F("Battery in Volts:"), sensorValue_battery); } if (strcmp(_version, "v0.2") == 0) { // Get the battery voltage - float rawBattery = analogRead(_batteryPin); + float rawBattery = analogRead(_batteryPin); + MS_DBG(F("Raw battery pin reading in bits:"), rawBattery); sensorValue_battery = (3.3 / 1023.) * 1.47 * rawBattery; + MS_DBG(F("Battery in Volts:"), sensorValue_battery); } #elif defined(ARDUINO_AVR_SODAQ_NDOGO) || defined(ARDUINO_SODAQ_AUTONOMO) || \ defined(ARDUINO_AVR_SODAQ_MBILI) // Get the battery voltage - float rawBattery = analogRead(_batteryPin); + float rawBattery = analogRead(_batteryPin); + MS_DBG(F("Raw battery pin reading in bits:"), rawBattery); sensorValue_battery = (3.3 / 1023.) * 1.47 * rawBattery; + MS_DBG(F("Battery in Volts:"), sensorValue_battery); #else sensorValue_battery = -9999; diff --git a/src/sensors/ProcessorStats.h b/src/sensors/ProcessorStats.h index 29babfbd0..34b4d95ff 100644 --- a/src/sensors/ProcessorStats.h +++ b/src/sensors/ProcessorStats.h @@ -1,7 +1,8 @@ /** * @file ProcessorStats.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the ProcessorStats sensor subclass and the variable diff --git a/src/sensors/RainCounterI2C.cpp b/src/sensors/RainCounterI2C.cpp index a334a6895..b2777f1cf 100644 --- a/src/sensors/RainCounterI2C.cpp +++ b/src/sensors/RainCounterI2C.cpp @@ -1,7 +1,8 @@ /** * @file RainCounterI2C.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/RainCounterI2C.h b/src/sensors/RainCounterI2C.h index 80f617368..69034d88c 100644 --- a/src/sensors/RainCounterI2C.h +++ b/src/sensors/RainCounterI2C.h @@ -1,7 +1,8 @@ /** * @file RainCounterI2C.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/SDI12Sensors.cpp b/src/sensors/SDI12Sensors.cpp index 90665fce2..132f5929e 100644 --- a/src/sensors/SDI12Sensors.cpp +++ b/src/sensors/SDI12Sensors.cpp @@ -1,14 +1,21 @@ /** * @file SDI12Sensors.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SDI12Sensors class. */ -#define LIBCALL_ENABLEINTERRUPT // To prevent compiler/linker crashes -#include // To handle external and pin change interrupts +/** + * @brief To prevent compiler/linker crashes with enable interrupt library, we + * must define LIBCALL_ENABLEINTERRUPT before importing EnableInterrupt within a + * library. + */ +#define LIBCALL_ENABLEINTERRUPT +// To handle external and pin change interrupts +#include "ModSensorInterrupts.h" #include "SDI12Sensors.h" @@ -549,7 +556,8 @@ bool SDI12Sensors::addSingleMeasurementResult(void) { // that the measurement is ready. uint32_t timerStart = millis(); - while ((millis() - timerStart) < (1000 * (wait))) { + while ((millis() - timerStart) < + static_cast(1000 * (wait))) { // sensor can interrupt us to let us know it is done early if (_SDI12Internal.available()) { #ifdef MS_SDI12SENSORS_DEBUG_DEEP diff --git a/src/sensors/SDI12Sensors.h b/src/sensors/SDI12Sensors.h index 3b2016f2e..d779a8591 100644 --- a/src/sensors/SDI12Sensors.h +++ b/src/sensors/SDI12Sensors.h @@ -1,7 +1,8 @@ /** * @file SDI12Sensors.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SDI12Sensors sensor subclass, itself a parent class for diff --git a/src/sensors/SensirionSHT4x.cpp b/src/sensors/SensirionSHT4x.cpp index 62615e0c8..c63a042f6 100644 --- a/src/sensors/SensirionSHT4x.cpp +++ b/src/sensors/SensirionSHT4x.cpp @@ -1,7 +1,8 @@ /** * @file SensirionSHT4x.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the SensirionSHT4x class. diff --git a/src/sensors/SensirionSHT4x.h b/src/sensors/SensirionSHT4x.h index d240b8708..39e0e1e60 100644 --- a/src/sensors/SensirionSHT4x.h +++ b/src/sensors/SensirionSHT4x.h @@ -1,7 +1,8 @@ /** * @file SensirionSHT4x.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the SensirionSHT4x sensor subclass and the variable diff --git a/src/sensors/TIADS1x15.cpp b/src/sensors/TIADS1x15.cpp index bd9119d47..edb2b5d77 100644 --- a/src/sensors/TIADS1x15.cpp +++ b/src/sensors/TIADS1x15.cpp @@ -1,7 +1,8 @@ /** * @file TIADS1x15.cpp * - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * Adapted from CampbellOBS3.h by Sara Geleskie Damiano diff --git a/src/sensors/TIADS1x15.h b/src/sensors/TIADS1x15.h index 7e4803802..cc13be6f7 100644 --- a/src/sensors/TIADS1x15.h +++ b/src/sensors/TIADS1x15.h @@ -1,7 +1,8 @@ /** * @file TIADS1x15.h * - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Bobby Schulz * Edited by Sara Geleskie Damiano * Adapted from CampbellOBS3.h by Sara Geleskie Damiano diff --git a/src/sensors/TIINA219.cpp b/src/sensors/TIINA219.cpp index 3042ecb65..d1a82b212 100644 --- a/src/sensors/TIINA219.cpp +++ b/src/sensors/TIINA219.cpp @@ -1,7 +1,8 @@ /** * @file TIINA219.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Neil Hancock * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/TIINA219.h b/src/sensors/TIINA219.h index 8bb9189b4..0f0995030 100644 --- a/src/sensors/TIINA219.h +++ b/src/sensors/TIINA219.h @@ -1,7 +1,8 @@ /** * @file TIINA219.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Neil Hancock * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/TallyCounterI2C.cpp b/src/sensors/TallyCounterI2C.cpp index 79ccd9571..47df771fc 100644 --- a/src/sensors/TallyCounterI2C.cpp +++ b/src/sensors/TallyCounterI2C.cpp @@ -1,7 +1,8 @@ /** * @file TallyCounterI2C.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/TallyCounterI2C.h b/src/sensors/TallyCounterI2C.h index 79dbb1fc5..a42fd13f9 100644 --- a/src/sensors/TallyCounterI2C.h +++ b/src/sensors/TallyCounterI2C.h @@ -1,7 +1,8 @@ /** * @file TallyCounterI2C.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/TurnerCyclops.cpp b/src/sensors/TurnerCyclops.cpp index ee5864267..0f74fc0e9 100644 --- a/src/sensors/TurnerCyclops.cpp +++ b/src/sensors/TurnerCyclops.cpp @@ -1,7 +1,8 @@ /** * @file TurnerCyclops.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the TurnerCyclops class. diff --git a/src/sensors/TurnerCyclops.h b/src/sensors/TurnerCyclops.h index 1db566b9a..753e61433 100644 --- a/src/sensors/TurnerCyclops.h +++ b/src/sensors/TurnerCyclops.h @@ -1,7 +1,8 @@ /** * @file TurnerCyclops.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the TurnerCyclops sensor subclass and the variable subclasses diff --git a/src/sensors/VegaPuls21.h b/src/sensors/VegaPuls21.h new file mode 100644 index 000000000..815739b1b --- /dev/null +++ b/src/sensors/VegaPuls21.h @@ -0,0 +1,531 @@ +/** + * @file VegaPuls21.h + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. + * @author Sara Geleskie Damiano + * + * @brief Contains the VegaPuls21 sensor subclass and the variable + * subclasses VegaPuls21_Stage, VegaPuls21_Distance, VegaPuls21_Reliability, and + * VegaPuls21_ErrorCode. + * + * These are for the VEGAPULS C 21 digital SDI-12 radar level sensor. + * + * This depends on the SDI12Sensors parent class. + */ +/* clang-format off */ +/** + * @defgroup sensor_vega_puls21 VEGAPULS C 21 + * Classes for the [VEGAPULS C 21](https://www.vega.com/en-us/products/product-catalog/level/radar/vegapuls-c-21) radar sensor. + * + * @ingroup sdi12_group + * + * @tableofcontents + * @m_footernavigation + * + * @section sensor_vega_puls21_intro Introduction + * + * > VEGAPULS C 21 is the ideal sensor for non-contact level measurement in simple applications + * > where a high degree of protection is required. It is particularly suitable for use in water treatment, + * > pumping stations and rain overflow basins, for flow measurement in open channels and level monitoring. + * > In bulk solids the sensors are used in small bulk solids silos or open containers. + * + * The sensor is implemented as a sub-classes of the SDI12Sensors class. + * It requires a 8 to 30 Vdc power supply, which can be turned off between measurements. + * It pulls 25 mW in low-power mode and 100 mW in standard mode. + * + * @section sensor_vega_puls21_datasheet Sensor Datasheet + * The specifications and datasheet are available at https://www.vega.com/api/sitecore/DocumentDownload/Handler?documentContainerId=1006748&languageId=2&fileExtension=pdf&softwareVersion=&documentGroupId=58354&version=03-04-2023 + * + * @section sensor_vega_puls21_flags Build flags + * @see @ref sdi12_group_flags + * + * @section sensor_vega_puls21_ctor Sensor Constructor + * {{ @ref VegaPuls21::VegaPuls21 }} + * + * ___ + * @section sensor_vega_puls21_examples Example Code + * The VEGAPULS C 21 is used in the @menulink{vega_puls21} example. + * + * @menusnip{vega_puls21} + */ +/* clang-format on */ + +// Header Guards +#ifndef SRC_SENSORS_VEGAPULS21_H_ +#define SRC_SENSORS_VEGAPULS21_H_ + +// Included Dependencies +#include "sensors/SDI12Sensors.h" + +/** @ingroup sensor_vega_puls21 */ +/**@{*/ + +// Sensor Specific Defines +/// @brief Sensor::_numReturnedValues; the VEGA PULS 21 can report 5 values +#define VEGAPULS21_NUM_VARIABLES 5 +/// @brief Sensor::_incCalcValues; +#define VEGAPULS21_INC_CALC_VARIABLES 0 + +/** + * @anchor sensor_vega_puls21_timing + * @name Sensor Timing + * The sensor timing for a VEGAPULS C 21 + */ +/**@{*/ +/** @brief Sensor::_warmUpTime_ms; the VEGA PULS 21 warms up in ~5200ms. + * + * This is longer than the expected 250ms for a SDI-12 sensor, but I couldn't + * get a response from the sensor faster than that. The instruction sheet says + * the warm-up is less than 10s, but also says that the initial tests on + * power-up can take up to 3 minutes. + */ +#define VEGAPULS21_WARM_UP_TIME_MS 5200 +/// @brief Sensor::_stabilizationTime_ms; the VEGA PULS 21 is stable as soon as +/// it warms up (0ms stabilization). +#define VEGAPULS21_STABILIZATION_TIME_MS 0 +/** + * @brief Sensor::_measurementTime_ms; the VEGA PULS 21 takes ~6000ms to + * complete a measurement. + * + * Spec sheet says the measurement time is 250ms but when you ask the sensor it + * says it won't return for 14s. When taking a standard measurement I was + * getting a result after about 5800-6000 ms. + */ +#define VEGAPULS21_MEASUREMENT_TIME_MS 6050 +/// @brief Extra wake time required for an SDI-12 sensor between the "break" +/// and the time the command is sent. The VEGA PULS 21 requires no extra time. +#define VEGAPULS21_EXTRA_WAKE_TIME_MS 0 +/**@}*/ + +/** + * @anchor sensor_vega_puls21_stage + * @name Stage + * The stage variable from a VEGAPULS C 21 + * - Accuracy is ≤ 2 mm (meas. distance > 0.25 m/0.8202 ft) + * + * {{ @ref VegaPuls21_Stage::VegaPuls21_Stage }} + */ +/**@{*/ +/// @brief Decimals places in string representation; stage in meters should have +/// 3 - resolution is 1mm. +#define VEGAPULS21_STAGE_RESOLUTION 3 +/// @brief Sensor variable number; stage is stored in sensorValues[0]. +#define VEGAPULS21_STAGE_VAR_NUM 0 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +/// "gageHeight" +#define VEGAPULS21_STAGE_VAR_NAME "gageHeight" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +/// "meter" (m) +#define VEGAPULS21_STAGE_UNIT_NAME "meter" +/// @brief Default variable short code; "VegaPulsStage" +#define VEGAPULS21_STAGE_DEFAULT_CODE "VegaPulsStage" +/**@}*/ + +/** + * @anchor sensor_vega_puls21_distance + * @name Distance + * The distance variable from a VEGAPULS C 21 + * - Accuracy is ≤ 2 mm (meas. distance > 0.25 m/0.8202 ft) + * + * {{ @ref VegaPuls21_Distance::VegaPuls21_Distance }} + */ +/**@{*/ +/// @brief Decimals places in string representation; distance in meters should +/// have 3 - resolution is 1mm. +#define VEGAPULS21_DISTANCE_RESOLUTION 3 +/// @brief Sensor variable number; stage is stored in sensorValues[1]. +#define VEGAPULS21_DISTANCE_VAR_NUM 1 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +/// "distance" +#define VEGAPULS21_DISTANCE_VAR_NAME "distance" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +/// "meter" (m) +#define VEGAPULS21_DISTANCE_UNIT_NAME "meter" +/// @brief Default variable short code; "VegaPulsDistance" +#define VEGAPULS21_DISTANCE_DEFAULT_CODE "VegaPulsDistance" +/**@}*/ + +/** + * @anchor sensor_vega_puls21_temp + * @name Temperature + * The temperature variable from a VEGAPULS C 21 + * + * {{ @ref VegaPuls21_Temp::VegaPuls21_Temp }} + */ +/**@{*/ +/// @brief Decimals places in string representation; temperature should have 1 - +/// resolution is 0.1°C. +#define VEGAPULS21_TEMP_RESOLUTION 1 +/// @brief Sensor variable number; temperature is stored in sensorValues[2]. +#define VEGAPULS21_TEMP_VAR_NUM 2 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +/// "temperature" +#define VEGAPULS21_TEMP_VAR_NAME "temperature" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +/// "degreeCelsius" (°C) +#define VEGAPULS21_TEMP_UNIT_NAME "degreeCelsius" +/// @brief Default variable short code; "VegaPulsTemp" +#define VEGAPULS21_TEMP_DEFAULT_CODE "VegaPulsTemp" +/**@}*/ + +/** + * @anchor sensor_vega_puls21_reliability + * @name Reliability + * The reliability variable from a VEGAPULS C 21 + * + * {{ @ref VegaPuls21_Reliability::VegaPuls21_Reliability }} + */ +/**@{*/ +/// @brief Decimals places in string representation; reliability should have 1 +/// (resolution is 0.1 dB). +#define VEGAPULS21_RELIABILITY_RESOLUTION 1 +/// @brief Sensor variable number; reliability is stored in sensorValues[3] +#define VEGAPULS21_RELIABILITY_VAR_NUM 3 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +/// "reliability" +#define VEGAPULS21_RELIABILITY_VAR_NAME "reliability" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +/// "decibel" (dB) +#define VEGAPULS21_RELIABILITY_UNIT_NAME "decibel" +/// @brief Default variable short code; "VegaPulsReliability" +#define VEGAPULS21_RELIABILITY_DEFAULT_CODE "VegaPulsReliability" +/**@}*/ + +/** + * @anchor sensor_vega_puls21_error + * @name Error Code + * The error code variable from a VEGAPULS C 21 + * - Significance of error code values is unknown. + * + * {{ @ref VegaPuls21_ErrorCode::VegaPuls21_ErrorCode }} + */ +/**@{*/ +/// @brief Decimals places in string representation; the error code has 0. +#define VEGAPULS21_ERRORCODE_RESOLUTION 0 +/// @brief Sensor variable number; error code is stored in sensorValues[4] +#define VEGAPULS21_ERRORCODE_VAR_NUM 4 +/// @brief Variable name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/variablename/); +/// "instrumentStatusCode" +#define VEGAPULS21_ERRORCODE_VAR_NAME "instrumentStatusCode" +/// @brief Variable unit name in +/// [ODM2 controlled vocabulary](http://vocabulary.odm2.org/units/); +/// "dimensionless" +#define VEGAPULS21_ERRORCODE_UNIT_NAME "dimensionless" +/// @brief Default variable short code; "VegaPulsError" +#define VEGAPULS21_ERRORCODE_DEFAULT_CODE "VegaPulsError" +/**@}*/ + + +/* clang-format off */ +/** + * @brief The Sensor sub-class for the + * [VEGAPULS C 21 radar level sensor](@ref sensor_vega_puls21). + * + * @ingroup sensor_vega_puls21 + */ +/* clang-format on */ +class VegaPuls21 : public SDI12Sensors { + public: + // Constructors with overloads + /** + * @brief Construct a new VEGAPULS C 21 object. + * + * The SDI-12 address of the sensor, the Arduino pin controlling power + * on/off, and the Arduino pin sending and receiving data are required + * for the sensor constructor. Optionally, you can include a number of + * distinct readings to average. The data pin must be a pin that + * supports pin-change interrupts. + * + * @param SDI12address The SDI-12 address of the VEGA PULS 21; can be a + * char, char*, or int. + * @param powerPin The pin on the mcu controlling power to the + * VEGA PULS 21 Use -1 if it is continuously powered. + * - The VEGA PULS 21 requires a 8 to 30 Vdc power supply, which can be + * turned off between measurements + * @param dataPin The pin on the mcu connected to the data line of the + * SDI-12 circuit. + * @param measurementsToAverage The number of measurements to take and + * average before giving a "final" result from the sensor; optional with + * a default value of 1. + */ + VegaPuls21(char SDI12address, int8_t powerPin, int8_t dataPin, + uint8_t measurementsToAverage = 1) + : SDI12Sensors( + SDI12address, powerPin, dataPin, measurementsToAverage, + "VEGAPULS C 21", VEGAPULS21_NUM_VARIABLES, + VEGAPULS21_WARM_UP_TIME_MS, VEGAPULS21_STABILIZATION_TIME_MS, + VEGAPULS21_MEASUREMENT_TIME_MS, VEGAPULS21_EXTRA_WAKE_TIME_MS, + VEGAPULS21_INC_CALC_VARIABLES) {} + /** + * @copydoc VegaPuls21::VegaPuls21 + */ + VegaPuls21(char* SDI12address, int8_t powerPin, int8_t dataPin, + uint8_t measurementsToAverage = 1) + : SDI12Sensors( + SDI12address, powerPin, dataPin, measurementsToAverage, + "VEGAPULS C 21", VEGAPULS21_NUM_VARIABLES, + VEGAPULS21_WARM_UP_TIME_MS, VEGAPULS21_STABILIZATION_TIME_MS, + VEGAPULS21_MEASUREMENT_TIME_MS, VEGAPULS21_EXTRA_WAKE_TIME_MS, + VEGAPULS21_INC_CALC_VARIABLES) {} + /** + * @copydoc VegaPuls21::VegaPuls21 + */ + VegaPuls21(int SDI12address, int8_t powerPin, int8_t dataPin, + uint8_t measurementsToAverage = 1) + : SDI12Sensors( + SDI12address, powerPin, dataPin, measurementsToAverage, + "VEGAPULS C 21", VEGAPULS21_NUM_VARIABLES, + VEGAPULS21_WARM_UP_TIME_MS, VEGAPULS21_STABILIZATION_TIME_MS, + VEGAPULS21_MEASUREMENT_TIME_MS, VEGAPULS21_EXTRA_WAKE_TIME_MS, + VEGAPULS21_INC_CALC_VARIABLES) {} + + /** + * @brief Destroy the VEGAPULS C 21 object + */ + ~VegaPuls21() {} +}; + + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [temperature output](@ref sensor_vega_puls21_stage) from a + * [VEGAPULS C 21 radar level sensor](@ref sensor_vega_puls21). + * + * @ingroup sensor_vega_puls21 + */ +/* clang-format on */ +class VegaPuls21_Stage : public Variable { + public: + /** + * @brief Construct a new VegaPuls21_Stage object. + * + * @param parentSense The parent VegaPuls21 providing the result + * values. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "VegaPulsStage". + */ + explicit VegaPuls21_Stage( + VegaPuls21* parentSense, const char* uuid = "", + const char* varCode = VEGAPULS21_STAGE_DEFAULT_CODE) + : Variable(parentSense, (const uint8_t)VEGAPULS21_STAGE_VAR_NUM, + (uint8_t)VEGAPULS21_STAGE_RESOLUTION, + VEGAPULS21_STAGE_VAR_NAME, VEGAPULS21_STAGE_UNIT_NAME, + varCode, uuid) {} + /** + * @brief Construct a new VegaPuls21_Stage object. + * + * @note This must be tied with a parent VegaPuls21 before it can be + * used. + */ + VegaPuls21_Stage() + : Variable((const uint8_t)VEGAPULS21_STAGE_VAR_NUM, + (uint8_t)VEGAPULS21_STAGE_RESOLUTION, + VEGAPULS21_STAGE_VAR_NAME, VEGAPULS21_STAGE_UNIT_NAME, + VEGAPULS21_STAGE_DEFAULT_CODE) {} + /** + * @brief Destroy the VegaPuls21_Stage object - no action needed. + */ + ~VegaPuls21_Stage() {} +}; + + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [temperature output](@ref sensor_vega_puls21_distance) from a + * [VEGAPULS C 21 radar level sensor](@ref sensor_vega_puls21). + * + * @ingroup sensor_vega_puls21 + */ +/* clang-format on */ +class VegaPuls21_Distance : public Variable { + public: + /** + * @brief Construct a new VegaPuls21_Distance object. + * + * @param parentSense The parent VegaPuls21 providing the result + * values. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "VegaPulsDistance". + */ + explicit VegaPuls21_Distance( + VegaPuls21* parentSense, const char* uuid = "", + const char* varCode = VEGAPULS21_DISTANCE_DEFAULT_CODE) + : Variable(parentSense, (const uint8_t)VEGAPULS21_DISTANCE_VAR_NUM, + (uint8_t)VEGAPULS21_DISTANCE_RESOLUTION, + VEGAPULS21_DISTANCE_VAR_NAME, VEGAPULS21_DISTANCE_UNIT_NAME, + varCode, uuid) {} + /** + * @brief Construct a new VegaPuls21_Distance object. + * + * @note This must be tied with a parent VegaPuls21 before it can be + * used. + */ + VegaPuls21_Distance() + : Variable((const uint8_t)VEGAPULS21_DISTANCE_VAR_NUM, + (uint8_t)VEGAPULS21_DISTANCE_RESOLUTION, + VEGAPULS21_DISTANCE_VAR_NAME, VEGAPULS21_DISTANCE_UNIT_NAME, + VEGAPULS21_DISTANCE_DEFAULT_CODE) {} + /** + * @brief Destroy the VegaPuls21_Distance object - no action needed. + */ + ~VegaPuls21_Distance() {} +}; + + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [temperature output](@ref sensor_vega_puls21_temp) from a + * [VEGAPULS C 21 radar level sensor](@ref sensor_vega_puls21). + * + * @ingroup sensor_vega_puls21 + */ +/* clang-format on */ +class VegaPuls21_Temp : public Variable { + public: + /** + * @brief Construct a new VegaPuls21_Temp object. + * + * @param parentSense The parent VegaPuls21 providing the result + * values. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "VegaPulsTemp". + */ + explicit VegaPuls21_Temp(VegaPuls21* parentSense, const char* uuid = "", + const char* varCode = VEGAPULS21_TEMP_DEFAULT_CODE) + : Variable(parentSense, (const uint8_t)VEGAPULS21_TEMP_VAR_NUM, + (uint8_t)VEGAPULS21_TEMP_RESOLUTION, + VEGAPULS21_TEMP_VAR_NAME, VEGAPULS21_TEMP_UNIT_NAME, varCode, + uuid) {} + /** + * @brief Construct a new VegaPuls21_Temp object. + * + * @note This must be tied with a parent VegaPuls21 before it can be + * used. + */ + VegaPuls21_Temp() + : Variable((const uint8_t)VEGAPULS21_TEMP_VAR_NUM, + (uint8_t)VEGAPULS21_TEMP_RESOLUTION, + VEGAPULS21_TEMP_VAR_NAME, VEGAPULS21_TEMP_UNIT_NAME, + VEGAPULS21_TEMP_DEFAULT_CODE) {} + /** + * @brief Destroy the VegaPuls21_Temp object - no action needed. + */ + ~VegaPuls21_Temp() {} +}; + + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [reliability output](@ref sensor_vega_puls21_reliability) + * from a [VEGAPULS C 21 radar level sensor](@ref sensor_vega_puls21). + * + * @ingroup sensor_vega_puls21 + */ +/* clang-format on */ +class VegaPuls21_Reliability : public Variable { + public: + /** + * @brief Construct a new VegaPuls21_Reliability object. + * + * @param parentSense The parent VegaPuls21 providing the result + * values. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "VegaPulsReliability". + */ + explicit VegaPuls21_Reliability( + VegaPuls21* parentSense, const char* uuid = "", + const char* varCode = VEGAPULS21_RELIABILITY_DEFAULT_CODE) + : Variable(parentSense, (const uint8_t)VEGAPULS21_RELIABILITY_VAR_NUM, + (uint8_t)VEGAPULS21_RELIABILITY_RESOLUTION, + VEGAPULS21_RELIABILITY_VAR_NAME, + VEGAPULS21_RELIABILITY_UNIT_NAME, varCode, uuid) {} + /** + * @brief Construct a new VegaPuls21_Reliability object. + * + * @note This must be tied with a parent VegaPuls21 before it can be + * used. + */ + VegaPuls21_Reliability() + : Variable((const uint8_t)VEGAPULS21_RELIABILITY_VAR_NUM, + (uint8_t)VEGAPULS21_RELIABILITY_RESOLUTION, + VEGAPULS21_RELIABILITY_VAR_NAME, + VEGAPULS21_RELIABILITY_UNIT_NAME, + VEGAPULS21_RELIABILITY_DEFAULT_CODE) {} + /** + * @brief Destroy the VegaPuls21_Reliability object - no action + * needed. + */ + ~VegaPuls21_Reliability() {} +}; + + +/* clang-format off */ +/** + * @brief The Variable sub-class used for the + * [error code output](@ref sensor_vega_puls21_error) from a + * [VEGAPULS C 21 radar level sensor](@ref sensor_vega_puls21). + * + * @ingroup sensor_vega_puls21 + */ +/* clang-format on */ +class VegaPuls21_ErrorCode : public Variable { + public: + /** + * @brief Construct a new VegaPuls21_ErrorCode object. + * + * @param parentSense The parent VegaPuls21 providing the result + * values. + * @param uuid A universally unique identifier (UUID or GUID) for the + * variable; optional with the default value of an empty string. + * @param varCode A short code to help identify the variable in files; + * optional with a default value of "VegaPulsError". + */ + explicit VegaPuls21_ErrorCode( + VegaPuls21* parentSense, const char* uuid = "", + const char* varCode = VEGAPULS21_ERRORCODE_DEFAULT_CODE) + : Variable(parentSense, (const uint8_t)VEGAPULS21_ERRORCODE_VAR_NUM, + (uint8_t)VEGAPULS21_ERRORCODE_RESOLUTION, + VEGAPULS21_ERRORCODE_VAR_NAME, + VEGAPULS21_ERRORCODE_UNIT_NAME, varCode, uuid) {} + /** + * @brief Construct a new VegaPuls21_ErrorCode object. + * + * @note This must be tied with a parent VegaPuls21 before it can be + * used. + */ + VegaPuls21_ErrorCode() + : Variable((const uint8_t)VEGAPULS21_ERRORCODE_VAR_NUM, + (uint8_t)VEGAPULS21_ERRORCODE_RESOLUTION, + VEGAPULS21_ERRORCODE_VAR_NAME, + VEGAPULS21_ERRORCODE_UNIT_NAME, + VEGAPULS21_ERRORCODE_DEFAULT_CODE) {} + /** + * @brief Destroy the VegaPuls21_ErrorCode object - no action + * needed. + */ + ~VegaPuls21_ErrorCode() {} +}; +/**@}*/ +#endif // SRC_SENSORS_VEGAPULS21_H_ diff --git a/src/sensors/YosemitechParent.cpp b/src/sensors/YosemitechParent.cpp index 6100c833e..eebe0e6b4 100644 --- a/src/sensors/YosemitechParent.cpp +++ b/src/sensors/YosemitechParent.cpp @@ -1,7 +1,8 @@ /** * @file YosemitechParent.cpp - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Implements the YosemitechParent class. diff --git a/src/sensors/YosemitechParent.h b/src/sensors/YosemitechParent.h index b3fa4bcbe..b034177b1 100644 --- a/src/sensors/YosemitechParent.h +++ b/src/sensors/YosemitechParent.h @@ -1,7 +1,8 @@ /** * @file YosemitechParent.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechParent sensor subclass, itself a parent class diff --git a/src/sensors/YosemitechY4000.h b/src/sensors/YosemitechY4000.h index 70a7ca487..400d61ddc 100644 --- a/src/sensors/YosemitechY4000.h +++ b/src/sensors/YosemitechY4000.h @@ -1,7 +1,8 @@ /** * @file YosemitechY4000.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Written By: Anthony Aufdenkampe * Edited by Sara Geleskie Damiano * diff --git a/src/sensors/YosemitechY504.h b/src/sensors/YosemitechY504.h index db28088d3..2f5ff2019 100644 --- a/src/sensors/YosemitechY504.h +++ b/src/sensors/YosemitechY504.h @@ -1,7 +1,8 @@ /** * @file YosemitechY504.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY504 sensor subclass and the variable diff --git a/src/sensors/YosemitechY510.h b/src/sensors/YosemitechY510.h index 85b832375..c726f67d3 100644 --- a/src/sensors/YosemitechY510.h +++ b/src/sensors/YosemitechY510.h @@ -1,7 +1,8 @@ /** * @file YosemitechY510.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY510 sensor subclass and the variable diff --git a/src/sensors/YosemitechY511.h b/src/sensors/YosemitechY511.h index 63947ea45..e49ee49ae 100644 --- a/src/sensors/YosemitechY511.h +++ b/src/sensors/YosemitechY511.h @@ -1,7 +1,8 @@ /** * @file YosemitechY511.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY511 sensor subclass and the variable diff --git a/src/sensors/YosemitechY514.h b/src/sensors/YosemitechY514.h index 60158bb22..138f44cea 100644 --- a/src/sensors/YosemitechY514.h +++ b/src/sensors/YosemitechY514.h @@ -1,7 +1,8 @@ /** * @file YosemitechY514.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY514 sensor subclass and the variable diff --git a/src/sensors/YosemitechY520.h b/src/sensors/YosemitechY520.h index 9f673fee2..755db66e6 100644 --- a/src/sensors/YosemitechY520.h +++ b/src/sensors/YosemitechY520.h @@ -1,7 +1,8 @@ /** * @file YosemitechY520.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY520 sensor subclass and the variable diff --git a/src/sensors/YosemitechY532.h b/src/sensors/YosemitechY532.h index 8ce218470..3ca91bdec 100644 --- a/src/sensors/YosemitechY532.h +++ b/src/sensors/YosemitechY532.h @@ -1,7 +1,8 @@ /** * @file YosemitechY532.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY532 sensor subclass and the variable diff --git a/src/sensors/YosemitechY533.h b/src/sensors/YosemitechY533.h index a5c170bfe..8e5e81627 100644 --- a/src/sensors/YosemitechY533.h +++ b/src/sensors/YosemitechY533.h @@ -1,7 +1,8 @@ /** * @file YosemitechY533.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY533 sensor subclass and the variable diff --git a/src/sensors/YosemitechY551.h b/src/sensors/YosemitechY551.h index 7227f61b7..8cc2fbb13 100644 --- a/src/sensors/YosemitechY551.h +++ b/src/sensors/YosemitechY551.h @@ -1,7 +1,8 @@ /** * @file YosemitechY551.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY551 sensor subclass and the variable diff --git a/src/sensors/YosemitechY560.h b/src/sensors/YosemitechY560.h index 6d8d44795..31bb9227c 100644 --- a/src/sensors/YosemitechY560.h +++ b/src/sensors/YosemitechY560.h @@ -1,7 +1,8 @@ /** * @file YosemitechY560.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the YosemitechY560 sensor subclass and the variable diff --git a/src/sensors/YosemitechY700.h b/src/sensors/YosemitechY700.h index 6a146bac6..f4923a472 100644 --- a/src/sensors/YosemitechY700.h +++ b/src/sensors/YosemitechY700.h @@ -1,13 +1,14 @@ /** * @file YosemitechY700.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Anthony Aufdenkampe * * @brief Contains the YosemitechY700 sensor subclass and the variable * subclasses YosemitechY700_Pressure and YosemitechY700_Temp. * - * These are for the Yosemitech Y700 Pressure sensor. + * These are for the Yosemitech Y700 Pressure Sensor. * * This depends on the YosemitechParent super class. * @@ -70,11 +71,11 @@ /// 1000 ms. #define Y700_WARM_UP_TIME_MS 1000 /// @brief Sensor::_stabilizationTime_ms; time between "StartMeasurement" -/// command and stable reading - Y700 takes 4 s to get stability <1 mm, +/// command and stable reading - Y700 takes 4 s to get stability <1 mm, /// but 12 s for <0.1 mm. If highest precision is required, increase to 12000. #define Y700_STABILIZATION_TIME_MS 4000 /// @brief Sensor::_measurementTime_ms; the Y700 takes <1 s for new values. -/// but >1 s for values that don't seem autocorrelated. +/// but >1 s for values that don't seem autocorrelated. #define Y700_MEASUREMENT_TIME_MS 1000 /**@}*/ @@ -211,9 +212,9 @@ class YosemitechY700_Pressure : public Variable { * @param varCode A short code to help identify the variable in files; * optional with a default value of "Y700Pres". */ - explicit YosemitechY700_Pressure(YosemitechY700* parentSense, - const char* uuid = "", - const char* varCode = Y700_PRES_DEFAULT_CODE) + explicit YosemitechY700_Pressure( + YosemitechY700* parentSense, const char* uuid = "", + const char* varCode = Y700_PRES_DEFAULT_CODE) : Variable(parentSense, (const uint8_t)Y700_PRES_VAR_NUM, (uint8_t)Y700_PRES_RESOLUTION, Y700_PRES_VAR_NAME, Y700_PRES_UNIT_NAME, varCode, uuid) {} diff --git a/src/sensors/ZebraTechDOpto.h b/src/sensors/ZebraTechDOpto.h index 92e618d23..26c4780d1 100644 --- a/src/sensors/ZebraTechDOpto.h +++ b/src/sensors/ZebraTechDOpto.h @@ -1,7 +1,8 @@ /** * @file ZebraTechDOpto.h - * @copyright 2017-2022 Stroud Water Research Center - * Part of the EnviroDIY ModularSensors library for Arduino + * @copyright Stroud Water Research Center + * Part of the EnviroDIY ModularSensors library for Arduino. + * This library is published under the BSD-3 license. * @author Sara Geleskie Damiano * * @brief Contains the ZebraTechDOpto sensor subclass and the variable