diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/CHANGELOG.md b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/CHANGELOG.md new file mode 100644 index 0000000..4331410 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/CHANGELOG.md @@ -0,0 +1,7 @@ +# Project change log + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [1.0.0] 2018-10-15 +Initial version diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/LICENSE b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/LICENSE new file mode 100644 index 0000000..0a04128 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/README.md b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/README.md new file mode 100644 index 0000000..b56c332 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/README.md @@ -0,0 +1,160 @@ +# MessagePack + +MessagePack is a library for AVR, SAMD, ESP8266 and ESP32 platforms to pack/unpack values into a compact, self-explanatory binary message. + +[![version](https://img.shields.io/badge/version-1.0.0-brightgreen.svg)](CHANGELOG.md) +[![travis](https://travis-ci.org/xoseperez/messagepack.svg?branch=master)](https://travis-ci.org/xoseperez/messagepack) +[![codacy](https://img.shields.io/codacy/grade/54c6bf3a367745509677e28dfbe1e0d1/master.svg)](https://www.codacy.com/app/xoseperez/messagepack/dashboard) +[![license](https://img.shields.io/github/license/xoseperez/MessagePack.svg)](LICENSE) +
+[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xose%2eperez%40gmail%2ecom&lc=US&no_note=0¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest) +[![twitter](https://img.shields.io/twitter/follow/xoseperez.svg?style=social)](https://twitter.com/intent/follow?screen_name=xoseperez) + +## Features + +The main features of the MessagePack library are: + +* Compact yet self-explanatory message format +* Targeted to wireless communication +* Support for boolean, short, integer, long, and float numbers and c-strings. + +## Usage + +Check the examples folder for working examples of the library. + +### Packing + +``` + +#include "MessagePack.h" + +void send(unsigned char * data, unsigned char length) { + // ... +} + +void setup() { + + MessagePack * message = new MessagePack(); + + // Add some values, for instance temperature, humidity and pressure + message->addFloat(25.4); + message->addShort(67); + message->addFloat(1013.45); + + // Send message + send(message->pack(), message->length()); + +} + +loop() {} + +``` + +### Unpacking + +``` + +#include "MessagePack.h" + +void parse(unsigned char * data, unsigned char length) { + + MessagePack * message = new MessagePack(); + + // Load the data + message->unpack(data, length); + + // Number of elements + unsigned char count = message->count(); + Serial.print("Number of values: "); + Serial.println(count); + + // Walk elements (only for integer numbers, see example for full functionality) + char buffer[32]; + for (unsigned char i=0; itype(i); + if (MESSAGE_PACK_BOOLEAN == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is a BOOLEAN: %d\n", i, message->getBoolean(i) ? 1 : 0); + } else if (MESSAGE_PACK_SHORT == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is a SHORT: %u\n", i, message->getShort(i)); + } else if (MESSAGE_PACK_INTEGER == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is an INTEGER: %u\n", i, message->getInteger(i)); + } else if (MESSAGE_PACK_LONG == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is a LONG: %lu\n", i, message->getLong(i)); + } + Serial.print(buffer); + } + +} + +setup() {} + +loop() { + + if (Serial.available()) { + + // ... + + // send the message to the parser routine + parse(data, length); + + } + +} + +``` + +## Format + +This library works under the following assumptions: + +* Data is in little-endian format (least significant byte, is at the lowest address) +* Integers have a length of 8, 16 or 32 bits (for SHORT, INTEGER and LONG types) +* Floats are represented in IEEE 754 single-precision format, and have a length of 32 bits +* Booleans are represented in a byte (1 = true, 0 = false) +* Strings are ended by the NULL char (0x00) + +Data is binary packed with this format: + +* First byte: number of values packed in the string +* N bytes with the information about the data type of each packed value. Each byte have information about 2 packed values, one for each nibble. Data types are coded in this way: + * 0b0000: Null + * 0b0001: Boolean + * 0b0010: Short + * 0b0011: Integer + * 0b0100: Long + * 0b0101: Float + * 0b0110: String +* N bytes of data + +``` +The pack string (without spaces) for 17 (short), true (boolean), nil and 452 (integer) are: + +03 21 30 11 01 C401 + +03 is the number of packed values, in this case 3 +21 is the type of the first and second packed values: short and boolean +30 is the type of the third and fourth packed values: integer and null +11 is integer 17 (0x11) in hexadecimal 1-byte integer (a.k.a. short) +01 is boolean true +C401 is integer 452 (0x01C4) in 2-bytes little-endian + +Total length is 7 bytes. Take note that the nil value is only present in the header and has not representation in the data. + +``` + +## License + +Copyright (C) 2018 by Xose Pérez + +The MessagePack library is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The MessagePack library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the MessagePack library. If not, see . diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/pack.ino b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/pack.ino new file mode 100644 index 0000000..72e1b54 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/pack.ino @@ -0,0 +1,53 @@ +/* + +MessagePack - Packing example + +Copyright (C) 2018 by Xose Pérez + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . + +*/ + +#include "MessagePack.h" + +void setup() { + + // Init serial communications + Serial.begin(115200); + while (!Serial); + Serial.println(); + Serial.println("MessagePack Library - Packing example"); + Serial.println(); + + // Create a message pack object, defaults to 100 bytes of memory + MessagePack * message = new MessagePack(); + + // Add some values, for instance temperature, humidity and pressure + message->addFloat(25.4); + message->addShort(67); + message->addFloat(1013.45); + + // Now dump message to serial + char buffer[6]; + Serial.print("Packed message: { "); + for (unsigned char i=0; ilength(); i++) { + if (i>0) Serial.print(", "); + snprintf(buffer, sizeof(buffer), "0x%02X", message->pack()[i]); + Serial.print(buffer); + } + Serial.println(" }"); + +} + +void loop() {} diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/platformio.ini new file mode 100644 index 0000000..dd428de --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/pack/platformio.ini @@ -0,0 +1,9 @@ +[platformio] +src_dir = . +lib_extra_dirs = ../.. +env_default = leonardo + +[env:leonardo] +platform = atmelavr +board = leonardo +framework = arduino diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/platformio.ini new file mode 100644 index 0000000..dd428de --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/platformio.ini @@ -0,0 +1,9 @@ +[platformio] +src_dir = . +lib_extra_dirs = ../.. +env_default = leonardo + +[env:leonardo] +platform = atmelavr +board = leonardo +framework = arduino diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/unpack.ino b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/unpack.ino new file mode 100644 index 0000000..a27c72a --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/examples/unpack/unpack.ino @@ -0,0 +1,94 @@ +/* + +MessagePack - Unpacking example + +Copyright (C) 2018 by Xose Pérez + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . + +*/ + +#include "MessagePack.h" + +char * snfloat(char * buffer, uint8_t len, uint8_t decimals, float value) { + + bool negative = value < 0; + + uint32_t mul = 1; + for (uint8_t i=0; iunpack(data, sizeof(data)); + + // Number of elements + unsigned char count = message->count(); + Serial.print("Number of values: "); + Serial.println(count); + + // Walk elements + char buffer[32]; + for (unsigned char i=0; itype(i); + if (MESSAGE_PACK_BOOLEAN == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is a BOOLEAN: %d\n", i, message->getBoolean(i) ? 1 : 0); + } else if (MESSAGE_PACK_SHORT == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is a SHORT: %u\n", i, message->getShort(i)); + } else if (MESSAGE_PACK_INTEGER == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is an INTEGER: %u\n", i, message->getInteger(i)); + } else if (MESSAGE_PACK_LONG == type) { + snprintf(buffer, sizeof(buffer), "Value #%d is a LONG: %lu\n", i, message->getLong(i)); + } else if (MESSAGE_PACK_FLOAT == type) { + char number[10]; + snfloat(number, sizeof(number), 2, message->getFloat(i)); + snprintf(buffer, sizeof(buffer), "Value #%d is a FLOAT: %s\n", i, number); + } else if (MESSAGE_PACK_TEXT == type) { + unsigned char size = message->getTextLength(i); + char text[size+1]; + snprintf(buffer, sizeof(buffer), "Value #%d is a TEXT: %s\n", i, message->getText(i, text)); + } else { + snprintf(buffer, sizeof(buffer), "Value #%d is UNKNOWN\n", i); + } + Serial.print(buffer); + } + + +} + +void loop() {} diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/keywords.txt b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/keywords.txt new file mode 100644 index 0000000..bc25c15 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/keywords.txt @@ -0,0 +1,53 @@ +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Classes (KEYWORD1) +####################################### + +MessagePack KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +addNull KEYWORDS2 +addBoolean KEYWORDS2 +addShort KEYWORDS2 +addInteger KEYWORDS2 +addLong KEYWORDS2 +addFloat KEYWORDS2 +addText KEYWORDS2 + +getBoolean KEYWORDS2 +getShort KEYWORDS2 +getInteger KEYWORDS2 +getLong KEYWORDS2 +getFloat KEYWORDS2 +getTextLength KEYWORDS2 +getText KEYWORDS2 + +count KEYWORDS2 +type KEYWORDS2 +length KEYWORDS2 +pack KEYWORDS2 +unpack KEYWORDS2 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + +MESSAGE_PACK_NULL LITERAL1 +MESSAGE_PACK_BOOLEAN LITERAL1 +MESSAGE_PACK_SHORT LITERAL1 +MESSAGE_PACK_INTEGER LITERAL1 +MESSAGE_PACK_LONG LITERAL1 +MESSAGE_PACK_FLOAT LITERAL1 +MESSAGE_PACK_TEXT LITERAL1 +MESSAGE_PACK_MAX LITERAL1 +MESSAGE_PACK_ERROR LITERAL1 diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.json b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.json new file mode 100644 index 0000000..b5e3d59 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.json @@ -0,0 +1,23 @@ +{ + "name": "MessagePack", + "keywords": "message,packing,binary,transmission", + "description": "Library to pack/unpack values into a compact, self-explanatory binary message", + "repository": { + "type": "git", + "url": "https://github.com/xoseperez/messagepack.git" + }, + "version": "1.0.0", + "license": "LGPL-3.0", + "exclude": "tests", + "frameworks": "arduino", + "platforms": ["atmelavr", "atmelsam", "espressif8266", "espressif32"], + "authors": { + "name": "Xose Perez", + "email": "xose.perez@gmail.com", + "url": "http://tinkerman.cat", + "maintainer": true + }, + "examples": [ + "examples/*/*.ino" + ] +} diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.properties b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.properties new file mode 100644 index 0000000..43ba4d1 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/library.properties @@ -0,0 +1,10 @@ +name=MessagePack +version=1.0.0 +author=Xose Pérez +maintainer=Xose Pérez +sentence=Library to pack/unpack values into a compact, self-explanatory binary message +paragraph= +category=Communication +url=https://github.com/xoseperez/messagepack.git +architectures=avr,samd,esp8266,esp32 +includes=MessagePack.h diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/pre-commit b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/pre-commit new file mode 100644 index 0000000..b17ad39 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/pre-commit @@ -0,0 +1,119 @@ +#!/usr/bin/env python +""" + +Referencing current branch in github README.md [1] +This pre-commit hook [2] updates the README.md file's +Travis badge with the current branch. Based on [4]. + +[1] http://stackoverflow.com/questions/18673694/referencing-current-branch-in-github-readme-md +[2] http://www.git-scm.com/book/en/v2/Customizing-Git-Git-Hooks +[3] https://docs.travis-ci.com/user/status-images/ +[4] https://gist.github.com/dandye/dfe0870a6a1151c89ed9 + +Copy this file to .git/hooks/ + +""" + +import os +import sys +import re + +from subprocess import call, check_output +try: + from urllib.parse import urlparse +except ImportError: + from urlparse import urlparse + +from fileinput import FileInput +# https://github.com/python/cpython/commit/6cb7b659#diff-78790b53ff259619377058acd4f74672 +if sys.version_info[0] < 3: + class FileInputCtx(FileInput): + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + FileInput = FileInputCtx + + +def run(cmd, cwd=None): + out = check_output(cmd, cwd=cwd) + out = out.decode("latin1").strip() + + return out + + +def git_parse_remote(cwd=None, remote="origin"): + remote_url = run([ + "git", "config", "--local", + "--get", "remote.{}.url".format(remote)], cwd) + + if remote_url.startswith("git"): + _, _, repo = remote_url.partition(":") + elif remote_url.startswith("https"): + parsed = urlparse(remote_url) + repo = parsed.path[1:] + + path = repo.replace(".git", "") + return path.split("/") + + +def git_branch(cwd=None): + return run(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd) + + +def get_version(base, version_h="library.properties"): + version = "unknown" + + path = os.path.join(base, version_h) + with open(path, "r") as version_f: + for line in version_f: + if line.startswith("version="): + version = line.replace("version=", "").strip() + break + + return version + +TEMPLATES = { + "![travis]": "[![travis](https://travis-ci.org/{USER}/{REPO}.svg?branch={BRANCH})]" \ + "(https://travis-ci.org/{USER}/{REPO})\n", + "![version]": "[![version](https://img.shields.io/badge/version-{VERSION}-brightgreen.svg)](CHANGELOG.md)\n", + "![branch]": "[![branch](https://img.shields.io/badge/branch-{BRANCH}-orange.svg)]" \ + "(https://github.org/{USER}/{REPO}/tree/{BRANCH}/)\n", + "![codacy]": "[![codacy](https://img.shields.io/codacy/grade/{CODACY}/{BRANCH}.svg)]" \ + "(https://www.codacy.com/app/{USER}/{REPO}/dashboard)\n" +} + +README = "README.md" + +if __name__ == "__main__": + base = os.getcwd() + + user, repo = git_parse_remote() + fmt = { + "USER": user, + "REPO": repo, + "BRANCH": git_branch(), + "VERSION": get_version(base), + "CODACY": "54c6bf3a367745509677e28dfbe1e0d1" + } + templates = [ + (k, tmpl.format(**fmt)) + for k, tmpl in TEMPLATES.items() + ] + + def fmt_line(line): + for match, tmpl in templates: + if match in line: + return tmpl + + return line + + path = os.path.join(base, README) + + with FileInput(path, inplace=True) as readme: + for line in readme: + sys.stdout.write(fmt_line(line)) + + sys.exit(call(["git", "add", README])) diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.cpp new file mode 100644 index 0000000..a867c2f --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.cpp @@ -0,0 +1,4 @@ +#include +#include "MessagePack.h" + +unsigned char MESSAGE_PACK_LEN[] = {0, 1, 1, 2, 4, 4, 0}; \ No newline at end of file diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.h b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.h new file mode 100644 index 0000000..67ec4df --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/src/MessagePack.h @@ -0,0 +1,271 @@ +/* + +Message pack + +Message binary packing/unpacking library + +Copyright (C) 2018 by Xose Pérez + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . + +*/ + +#ifndef MESSAGE_PACK_H +#define MESSAGE_PACK_H + + +#ifdef LUA_COMPATIBILITY_MODE + +enum { + + MESSAGE_PACK_FLOAT, + MESSAGE_PACK_LONG, + MESSAGE_PACK_NULL, + MESSAGE_PACK_BOOLEAN, + MESSAGE_PACK_TEXT, + MESSAGE_PACK_SHORT, + MESSAGE_PACK_INTEGER, + + MESSAGE_PACK_MAX, + MESSAGE_PACK_ERROR = 0x0F + +}; + +unsigned char MESSAGE_PACK_LEN[] = {4, 4, 0, 1, 0, 1, 2}; + +#else + +enum { + + MESSAGE_PACK_NULL, + MESSAGE_PACK_BOOLEAN, + MESSAGE_PACK_SHORT, + MESSAGE_PACK_INTEGER, + MESSAGE_PACK_LONG, + MESSAGE_PACK_FLOAT, + MESSAGE_PACK_TEXT, + + MESSAGE_PACK_MAX, + MESSAGE_PACK_ERROR = 0x0F + +}; + +//unsigned char MESSAGE_PACK_LEN[] = {0, 1, 1, 2, 4, 4, 0}; +extern unsigned char MESSAGE_PACK_LEN[]; +#endif + + +class MessagePack { + + public: + + + MessagePack(unsigned char buffer_size = 100) : _buffer_size(buffer_size) { + _buffer = (unsigned char *) malloc(_buffer_size); + if (_buffer) _buffer[0] = 0; + } + + ~MessagePack() { + if (_buffer) free(_buffer); + } + + // --------------------------------------------------------------------- + + bool addNull() { + return _addVoid(MESSAGE_PACK_NULL, NULL, 0); + } + + bool addBoolean(bool value) { + unsigned char tmp = value ? 1 : 0; + return _addVoid(MESSAGE_PACK_BOOLEAN, (void *) &tmp, 1); + } + + bool addShort(unsigned char value) { + return _addVoid(MESSAGE_PACK_SHORT, (void *) &value, 1); + } + + bool addInteger(unsigned int value) { + return _addVoid(MESSAGE_PACK_INTEGER, (void *) &value, 2); + } + + bool addLong(unsigned long value) { + return _addVoid(MESSAGE_PACK_LONG, (void *) &value, 4); + } + + bool addFloat(float value) { + return _addVoid(MESSAGE_PACK_FLOAT, (void *) &value, 4); + } + + bool addText(const char * value) { + return _addVoid(MESSAGE_PACK_TEXT, (void *) value, strlen(value) + 1); + } + + // --------------------------------------------------------------------- + + bool getBoolean(unsigned char index) { + unsigned char value = 0; + _getVoid(index, MESSAGE_PACK_BOOLEAN, &value); + return value == 1; + } + + unsigned char getShort(unsigned char index) { + unsigned char value = 0; + _getVoid(index, MESSAGE_PACK_SHORT, &value); + return value; + } + + unsigned int getInteger(unsigned char index) { + unsigned int value = 0; + _getVoid(index, MESSAGE_PACK_INTEGER, &value); + return value; + } + + unsigned long getLong(unsigned char index) { + unsigned long value = 0; + _getVoid(index, MESSAGE_PACK_LONG, &value); + return value; + } + + float getFloat(unsigned char index) { + float value = 0; + _getVoid(index, MESSAGE_PACK_FLOAT, &value); + return value; + } + + unsigned char getTextLength(unsigned char index) { + if (MESSAGE_PACK_TEXT != _type(index)) return 0; + unsigned char start = _getPosition(index); + unsigned char position = start; + while (0x00 != _buffer[position]) ++position; + return position - start; + } + + char * getText(unsigned char index, char * text) { + if (MESSAGE_PACK_TEXT != _type(index)) return 0; + unsigned char position = _getPosition(index); + unsigned char len = getTextLength(index); + memcpy(text, &_buffer[position], len+1); + return text; + } + + // --------------------------------------------------------------------- + + unsigned char count() { + return _buffer[0]; + } + + unsigned char type(unsigned char index) { + if (!_buffer) return MESSAGE_PACK_ERROR; + if (index >= count()) return MESSAGE_PACK_ERROR; + return _type(index); + } + + unsigned char length() { + return _length; + } + + void pack(unsigned char * buffer) { + memcpy(buffer, _buffer, _length); + } + + unsigned char * pack() { + return _buffer; + } + + bool unpack(unsigned char * buffer, unsigned char len) { + if (len > _buffer_size) return false; + memcpy(_buffer, buffer, len); + _length = len; + return true; + } + + private: + + bool _addVoid(unsigned char type, void * data, unsigned char len) { + + if (!_buffer) return false; + if (_buffer_size - _length < len) return false; + + memcpy(&_buffer[_length], data, len); + _length += len; + + // Check if we have to move everything forward 1 byte + if (0 == count() % 2) { + unsigned char start = count() / 2 + 1; + for (unsigned char i=_length; i > start; i--) { + _buffer[i] = _buffer[i-1]; + } + _buffer[start] = 0; + _length++; + } + + // Save the type in the header + _setType(count(), type); + + // Increment counter + _buffer[0] = count() + 1; + + return true; + + } + + bool _getVoid(unsigned char index, unsigned char type, void * data) { + if (type != _type(index)) return false; + unsigned char position = _getPosition(index); + memcpy(data, &_buffer[position], MESSAGE_PACK_LEN[type]); + return true; + } + + unsigned char _getHeaderLength() { + return ( count() + 1 ) / 2 + 1; + } + + unsigned char _getPosition(unsigned char index) { + unsigned char position = _getHeaderLength(); + for (unsigned char i=0; i>= 4; + } + return byte & 0x0F; + } + + void _setType(unsigned char index, unsigned char type) { + unsigned char byte = _buffer[index / 2 + 1]; + type = type & 0x0F; + if (0 == index % 2) { + type <<= 4; + } + _buffer[index / 2 + 1] = byte | type; + } + + unsigned char * _buffer; + unsigned char _buffer_size = 0; + unsigned char _length = 1; + +}; + +#endif // MESSAGE_PACK_H diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/UnitTest.ino b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/UnitTest.ino new file mode 100644 index 0000000..4c6aad1 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/UnitTest.ino @@ -0,0 +1,252 @@ +/* + +Message pack + +Unit test suite +This test suite uses Aunit unit testing framework (https://github.com/bxparks/AUnit) + +Copyright (C) 2018 by Xose Pérez + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see . + +*/ + + +#include "MessagePack.h" +#include "AUnit.h" +using namespace aunit; + +//#define DEBUG + +// ----------------------------------------------------------------------------- +// Test class +// ----------------------------------------------------------------------------- + +class CustomTest: public TestOnce { + + protected: + + virtual void setup() override { + message = new MessagePack(); + } + + virtual void teardown() override { + delete message; + } + + virtual void compare(size_t len, unsigned char * expected) { + + size_t buffer_len = message->length(); + unsigned char buffer[buffer_len]; + message->pack(buffer); + + #ifdef DEBUG + char b[4]; + for (uint8_t i=0; icount(), 0); + assertEqual(message->length(), 1); +} + +// ----------------------------------------------------------------------------- + +testF(CustomTest, test_pack_null) { + message->addNull(); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_NULL << 4}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_NULL); +} + +testF(CustomTest, test_pack_boolean) { + message->addBoolean(true); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_BOOLEAN << 4, 0x01}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_BOOLEAN); + assertEqual(message->getBoolean(0), (bool) true); +} + +testF(CustomTest, test_pack_short) { + message->addShort(0x3F); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_SHORT << 4, 0x3F}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_SHORT); + assertEqual(message->getShort(0), (unsigned char) 0x03F); +} + +testF(CustomTest, test_pack_integer) { + message->addInteger(0x45A0); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_INTEGER << 4, 0xA0, 0x45}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_INTEGER); + assertEqual(message->getInteger(0), (unsigned int) 0x45A0); +} + +testF(CustomTest, test_pack_long) { + message->addLong(0x45A0FF); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_LONG << 4, 0xFF, 0xA0, 0x45, 0x00}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_LONG); + assertEqual(message->getLong(0), (unsigned long) 0x45A0FF); +} + +testF(CustomTest, test_pack_float) { + message->addFloat(3.1415926); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_FLOAT << 4, 0xDA, 0x0F, 0x49, 0x40}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_FLOAT); + assertEqual(message->getFloat(0), (float) 3.1415926); +} + +testF(CustomTest, test_pack_text) { + message->addText("HOLA"); + assertEqual(message->count(), 1); + uint8_t expected[] = {1, MESSAGE_PACK_TEXT << 4, 'H', 'O', 'L', 'A', 0x00}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_TEXT); + assertEqual(message->getTextLength(0), 4); + char buffer[5]; + assertEqual(message->getText(0, buffer), "HOLA"); +} + +// ----------------------------------------------------------------------------- + +testF(CustomTest, test_pack_short_long) { + message->addShort(0x2E); + message->addLong(0x45A0FF); + assertEqual(message->count(), 2); + uint8_t expected[] = {2, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_LONG, 0x2E, 0xFF, 0xA0, 0x45, 0x00}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_SHORT); + assertEqual(message->type(1), MESSAGE_PACK_LONG); +} + +testF(CustomTest, test_pack_long_boolean_long) { + message->addLong(1); + message->addBoolean(true); + message->addLong(4); + assertEqual(message->count(), 3); + uint8_t expected[] = {3, MESSAGE_PACK_LONG << 4 | MESSAGE_PACK_BOOLEAN, MESSAGE_PACK_LONG << 4, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_LONG); + assertEqual(message->type(1), MESSAGE_PACK_BOOLEAN); + assertEqual(message->type(2), MESSAGE_PACK_LONG); +} + +testF(CustomTest, test_pack_short_integer_long) { + message->addShort(0x2E); + message->addInteger(0x34AB); + message->addLong(0x45A0FF); + assertEqual(message->count(), 3); + uint8_t expected[] = {3, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_INTEGER, MESSAGE_PACK_LONG << 4, 0x2E, 0xAB, 0x34, 0xFF, 0xA0, 0x45, 0x00}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_SHORT); + assertEqual(message->type(1), MESSAGE_PACK_INTEGER); + assertEqual(message->type(2), MESSAGE_PACK_LONG); +} + +testF(CustomTest, test_pack_short_text_long) { + message->addShort(0x2E); + message->addText("HOLA"); + message->addLong(0x45A0FF); + assertEqual(message->count(), 3); + uint8_t expected[] = {3, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_TEXT, MESSAGE_PACK_LONG << 4, 0x2E, 'H', 'O', 'L', 'A', 0x00, 0xFF, 0xA0, 0x45, 0x00}; + compare(sizeof(expected), expected); + assertEqual(message->type(0), MESSAGE_PACK_SHORT); + assertEqual(message->type(1), MESSAGE_PACK_TEXT); + assertEqual(message->type(2), MESSAGE_PACK_LONG); +} + +// ----------------------------------------------------------------------------- + +testF(CustomTest, test_unpack_text) { + unsigned char data[] = {1, MESSAGE_PACK_TEXT << 4, 'H', 'O', 'L', 'A', 0x00}; + assertTrue(message->unpack(data, sizeof(data))); + assertEqual(message->count(), 1); + assertEqual(message->type(0), MESSAGE_PACK_TEXT); + assertEqual(message->getTextLength(0), 4); + char buffer[5]; + assertEqual(message->getText(0, buffer), "HOLA"); +} + +testF(CustomTest, test_unpack_short_float_long) { + unsigned char data[] = {3, MESSAGE_PACK_SHORT << 4 | MESSAGE_PACK_FLOAT, MESSAGE_PACK_LONG << 4, 0x2E, 0xDA, 0x0F, 0x49, 0x40, 0xFF, 0xA0, 0x45, 0x00}; + assertTrue(message->unpack(data, sizeof(data))); + assertEqual(message->count(), 3); + assertEqual(message->type(0), MESSAGE_PACK_SHORT); + assertEqual(message->type(1), MESSAGE_PACK_FLOAT); + assertEqual(message->type(2), MESSAGE_PACK_LONG); + assertEqual(message->getShort(0), (unsigned char) 0x2E); + assertEqual(message->getFloat(1), (float) 3.1415926); + assertEqual(message->getLong(2), (unsigned long) 0x45A0FF); +} + +testF(CustomTest, test_unpack_long_boolean_long) { + unsigned char data[] = {3, MESSAGE_PACK_LONG << 4 | MESSAGE_PACK_BOOLEAN, MESSAGE_PACK_LONG << 4, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00}; + assertTrue(message->unpack(data, sizeof(data))); + assertEqual(message->count(), 3); + assertEqual(message->type(0), MESSAGE_PACK_LONG); + assertEqual(message->type(1), MESSAGE_PACK_BOOLEAN); + assertEqual(message->type(2), MESSAGE_PACK_LONG); + assertEqual(message->getLong(0), (unsigned long) 1); + assertEqual(message->getBoolean(1), (bool) true); + assertEqual(message->getLong(2), (unsigned long) 4); +} + +// ----------------------------------------------------------------------------- +// Main +// ----------------------------------------------------------------------------- + +void setup() { + + Serial.begin(115200); + while (!Serial); + + Printer::setPrinter(&Serial); + #ifdef DEBUG + //TestRunner::setVerbosity(Verbosity::kAll); + #endif + +} + +void loop() { + TestRunner::run(); +} diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/platformio.ini new file mode 100644 index 0000000..56df861 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/lib/MessagePack/tests/platformio.ini @@ -0,0 +1,18 @@ +[platformio] +src_dir = . +lib_extra_dirs = .. +env_default = leonardo + +[env:leonardo] +platform = atmelavr +board = leonardo +framework = arduino +lib_deps = + https://github.com/bxparks/AUnit + +[env:esp8266] +platform = espressif8266 +board = esp12e +framework = arduino +lib_deps = + https://github.com/bxparks/AUnit diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini index 5d33b76..b0c8dd9 100644 --- a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/platformio.ini @@ -22,7 +22,8 @@ board_upload.flash_size = 2MB ;board_upload.flash_size = 4MB board_build.filesystem = littlefs -upload_speed = 115200 +;upload_speed = 115200 +upload_speed = 921600 monitor_speed = 115200 monitor_filters = esp32_exception_decoder monitor_rts = 0 @@ -37,14 +38,16 @@ lib_ldf_mode = deep+ ; paulstoffregen/Time ; https://github.com/spacehuhn/SimpleList ; https://github.com/spacehuhn/SimpleMap +; https://github.com/xoseperez/messagepack.git build_flags = - -D ARDUINO_USB_MODE=1 - -D ARDUINO_USB_CDC_ON_BOOT=1 +; -D ARDUINO_USB_MODE=1 +; -D ARDUINO_USB_CDC_ON_BOOT=1 -D CONFIG_ARDUHAL_LOG_COLORS=1 -D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_WARNING + -D ENABLE_MESSAGEPACK=0 build_type = debug debug_tool = esp-builtin diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/ESP32C3Temperature.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/ESP32C3Temperature.cpp new file mode 100644 index 0000000..363bf7e --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/ESP32C3Temperature.cpp @@ -0,0 +1,44 @@ +/* Temperature Sensor Example + This example code is in the Public Domain (or CC0 licensed, at your option.) + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include + +/* Note: ESP32 don't support temperature sensor */ +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 +#include "driver/temp_sensor.h" + +/** + * @brief readTempSensor() + * + * @return float, tempSensor data, -10~80°C + */ +float readTempSensor() +{ + float tsens_out; + temp_sensor_read_celsius(&tsens_out); + + return tsens_out; +} + +void setupTempSensor() +{ + // Initialize touch pad peripheral, it will start a timer to run a filter + log_v("Initializing Temperature sensor"); + float tsens_out; + temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT(); + temp_sensor_get_config(&temp_sensor); + //log_v("default dac %d, clk_div %d", temp_sensor.dac_offset, temp_sensor.clk_div); + temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃. + temp_sensor_set_config(temp_sensor); + temp_sensor_start(); + log_i("Temperature sensor(-10℃ ~ 80℃) started..."); + +} + + +#else +#error TempSensor N/A +#endif \ No newline at end of file diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/_QEspNowSyncMsgPack.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/_QEspNowSyncMsgPack.cpp new file mode 100644 index 0000000..1c23bea --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/_QEspNowSyncMsgPack.cpp @@ -0,0 +1,382 @@ +/** + * @file _QEspNowSync.cpp + * @author jimmy.su + * @brief QEspNow LED Sync + * Dependancy library:QuickEspNow, SimpleMap, Esp32Ticker + * @version 0.1 + * @date 2023-01-06 + * + * @copyright Copyright (c) 2023 + * + */ +#include +#include +#include +#include "QuickEspNow.h" +//PeerListClass myPeers; + +//#define LED_ON 0 +//#define LED_OFF 1 +#define DEST_ADDR ESPNOW_BROADCAST_ADDRESS + +#include "myEspNow.h" //struct && enum +espnow_struct EspNow; + +bool isEspNowRXed=false; + +uint64_t myMac, macLeader; +//Preferences +#include +uint8_t _pinBlink=0; +bool _pinBlinkOn=0; +Preferences myPref; + + +//----------------------------------------------------------------------------- +#include +Ticker tickBlinkLED; +Ticker tickOffLED; +void offLED() +{ + digitalWrite(_pinBlink, !_pinBlinkOn); //OFF LED +} +void blinkLED() +{ + digitalWrite(_pinBlink, _pinBlinkOn); //toggle LED + tickOffLED.once_ms(100, offLED); //Off LED 100ms later + } + +bool isUnicastSent = false; +uint32_t utimeDataSent; //micros starting sent +/** + * @brief EspNow dataSentCB + * + * @param address + * @param status + */ +void dataSentCB (uint8_t* address, uint8_t status ) { + if (ESP_NOW_SEND_SUCCESS==status) { + isUnicastSent = true; + utimeDataSent = micros()-utimeDataSent; + Serial.printf ("Unicast to *%02X%02X:%luus!\n", address[4], address[5], utimeDataSent); + } + else + Serial.printf ("Unicast to *%02X%02X:FAIL!\n", address[4], address[5]); +} +/**---------------------------------------------------------------------------- + * @brief EspNow dataReceivedCB + * + * @param address + * @param data + * @param len + * @param rssi + * @param broadcast + */ +void dataReceivedCB (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) { + if (len<=0) return; + switch (*data) { + case myEspNowMsgType::HELLO: + case myEspNowMsgType::ECHO_REQ: + case myEspNowMsgType::ECHO_ACK: + memcpy(&EspNow, data, len); + EspNow.rssi = rssi; + { + uint32_t uOUI= address[0]<<16 | address[1]<<8 | address[2]; + uint32_t uID = address[3]<<16 | address[4]<<8 | address[5]; + EspNow.macAddr64 = ((uint64_t)uOUI) << 24 | uID; //convert OUI|ID into uint64_t + } + //Serial.printf("RX peer:%llX time:%lu\n", EspNow.macAddr64, EspNow.ums); + break; + case myEspNowMsgType::MSGPACK: + EspNow.msgType = myEspNowMsgType::MSGPACK; //copy msgType to EspNow + EspNow.rssi = rssi; //copy rssi to EspNow + _myMessagePack.unpack(data+1, len-1); //unpack msg data + if (0) { + Serial.print("Rx msgPack:"); + for (int i=0;iaddLong(myMac >> 32); + EspMsgPack->addLong(myMac & 0xFFFFFF); + EspMsgPack->addLong(millis()); + EspMsgPack->addFloat(readTempSensor()); + + uint8_t uSize = EspMsgPack->length()+1; + uint8_t aESP[uSize]; + aESP[0]=myEspNowMsgType::MSGPACK; + memcpy(aESP+1, EspMsgPack->pack(), EspMsgPack->length()); + //for (int i=0;i>>>>>>>>>> myEspNowMsgPack sent!\n"); + } + else { + Serial.printf (">>>>>>>>>> myEspNowMsgPack NOT sent\n"); + } + +} +void broadcastEspNowHello() +{ + espnow_struct myData; + myData.msgType = myEspNowMsgType::HELLO; + myData.macAddr64 = myMac; + //myData.frames = counter++; + myData.ums = millis(); + if (0==quickEspNow.send (DEST_ADDR, (uint8_t*)&myData, sizeof(espnow_struct)) ) { + //Serial.printf ("[%lu]>>>", millis()); + //Serial.printf("ID:%0X Millis:%lu\n", myData.id, myData.ums); + macLeader = _myNodesTime->getKey(_myNodesTime->size()-1); + if (myData.macAddr64 == macLeader) { //Leader do 1000ms blink by himself + uint32_t iums = myData.ums%1000; + tickBlinkLED.once_ms(1002-iums, blinkLED); //Scheduling for next blink, with 2ms RTTI adjustment + } + else { + //Team member following blink upon ESPNOW RX + } + //Update nodes time + if (!_myNodesTime->has(myData.macAddr64)) { //New member + _myNodesAlive->put(myData.macAddr64, 0); //Add 0 to nodesAlive + _myNodesRSSI->put(myData.macAddr64, 0); //Add 0 to nodesRSSI + _myNodesTime->put(myData.macAddr64, myData.ums); + Serial.printf("<%0llX> Added!\n", myData.macAddr64); + //printNodesOld(); + //printNodes(); + } + else { //Old member + _myNodesTime->put(myData.macAddr64, myData.ums); + //Update RSSI for myself + _myNodesRSSI->put(myData.macAddr64, 0); //No talk to myself! + } + } + else { + Serial.printf (">>>>>>>>>> Message NOT sent\n"); + } +} +void unicastEspNowEchoReq(uint64_t mac) +{ + espnow_struct myData; + myData.msgType = myEspNowMsgType::ECHO_REQ; + myData.macAddr64 = myMac; + myData.ums = micros(); + quickEspNow.onDataSent(dataSentCB); + //convert uint64 to mac array + uint8_t mArray[6]; + mArray[0]=(mac>>40)&0x00FF; + mArray[1]=(mac>>32)&0x00FF; + mArray[2]=(mac>>24)&0x00FF; + mArray[3]=(mac>>16)&0x00FF; + mArray[4]=(mac>>8) &0x00FF; + mArray[5]=mac &0x00FF; + + utimeDataSent= micros(); + if (0==quickEspNow.send (mArray, (uint8_t*)&myData, sizeof(espnow_struct)) ) { + //Serial.printf ("[%lu]>>>", millis()); + //Serial.printf("ID:%0X Millis:%lu\n", myData.id, myData.ms); + //Serial.printf(">>> ECHO_REQ sent!\n"); + } + else { + Serial.printf(">>> ECHO_REQ NOT sent!\n"); + } +} +void sendEspNowEchoAck() +{ + espnow_struct myData; + myData.msgType = myEspNowMsgType::ECHO_ACK; + myData.macAddr64 = EspNow.macAddr64; + myData.ums = EspNow.ums; + if (0==quickEspNow.send (DEST_ADDR, (uint8_t*)&myData, sizeof(espnow_struct)) ) { + //Serial.printf ("[%lu]>>>", millis()); + //Serial.printf("ID:%0X Millis:%lu\n", myData.id, myData.ms); + //Serial.printf(">>> ECHO_ACK sent!\n"); + } + else { + Serial.printf(">>> ECHO_ACK NOT sent!\n"); + } +} +Ticker tickSendHello; +void espSendHelloCB() +{ + quickEspNow.onDataSent(NULL); + broadcastEspNowHello(); +} + + + +//============================================================================= +void setup () { + //pinMode(_pinBlink, OUTPUT); + + #if (ARDUINO_USB_CDC_ON_BOOT) + log_w("USB_CDC_ON_BOOT enabled!"); + if (isUSBCDC()) { + if (!Serial) {Serial.begin(115200); delay(300);} + // Workaround for when USB CDC is unplugged #7583 + Serial.setTxTimeoutMs(0); // <<<====== solves USBCDC issue of delay + } + #else + log_w("USB_CDC_ON_BOOT disabled!"); + if (!Serial) {Serial.begin(115200); delay(300);} + #endif + + printESP32info(); + + //Save pinBlink to NVS::my-app + //---------------------------- + //myPref.begin("my-app", false); //ReadWrite mode + //_pinBlink = 3; + //_pinBlinkOn=1; + //myPref.putChar("pinBlink", _pinBlink); //reset pinBlink + //myPref.putChar("pinBlinkOn", _pinBlinkOn); + + //Read pinBlink from NVS::my-app + //------------------------------ + myPref.begin("my-app", true); //ReadOnly mode + _pinBlink=myPref.getChar("pinBlink", 0); + _pinBlinkOn=myPref.getChar("pinBlinkOn", 0); + + Serial.printf("NVS pinBlink:%d\n", _pinBlink); + Serial.printf("NVS pinBlinkOn:%d\n", _pinBlinkOn); + + myPref.end(); + pinMode(_pinBlink, OUTPUT); //reset pinBlink as OUTPUT + + WiFi.mode(WIFI_MODE_STA); + /* Config LR Mode + For LR-enabled AP of ESP32, it is incompatible with traditional 802.11 mode, because the beacon is sent in LR mode. + For LR-enabled station of ESP32 whose mode is NOT LR-only mode, it is compatible with traditional 802.11 mode. + If both station and AP are ESP32 devices and both of them have enabled LR mode, the negotiated mode supports LR.*/ + esp_wifi_set_protocol( WIFI_IF_STA, WIFI_PROTOCOL_LR ); //11B/11G/11N/LR + // + WiFi.disconnect(false); + //quickEspNow.onDataSent(dataSentCB); + quickEspNow.onDataRcvd(dataReceivedCB); + quickEspNow.begin(1); // If you are not connected to WiFi, channel should be specified + tickSendHello.attach_ms(1000, espSendHelloCB); //Send HELLO every 1000ms + + //myId=getESP32ChipID24(); //get my ID + //myMac = ESP.getEfuseMac(); + //Serial.printf("EfuseMAC:%012X", myMac); + uint8_t mac[6]; + WiFi.macAddress(mac); + Serial.printf("WiFiMAC:" MACSTR "\n", MAC2STR(mac)); + uint32_t uOui = mac[0]<<16 | mac[1]<<8 | mac[2]; + uint32_t uId = mac[3]<<16 | mac[4]<<8 | mac[5]; + myMac = ((uint64_t)uOui)<<24 | uId; + macLeader = myMac; + //Serial.printf("uOui Id:%X:%X", uOui, uId); + Serial.printf("My MAC address:%llX\n", myMac); + + + setupNodesMap(); + _myNodesAlive->clear(); + _myNodesTime->put(myMac, millis()); + printNodesAlive(); + //===================================== + +} + +uint32_t lastStatusMs=0; +uint8_t counter=0; +void loop () { + //print Nodes & check KeepAlive every 3seconds + if ((millis()-lastStatusMs)>=3000) { + lastStatusMs = millis(); //update lastStatus counter + //printNodesOld(); + //printNodesAlive(); + //Check KeepAlive, drop node when timeDiff<1000ms + for (int i=0;i<_myNodesTime->size();i++) { + uint64_t mac=_myNodesTime->getKey(i); //get key + uint32_t timeOld = _myNodesAlive->getData(_myNodesAlive->getIndex(mac)); //find key/value in alive nodes + uint32_t timeNew = _myNodesTime->getData(i); + uint32_t timeDiff= timeNew - timeOld; + + _myNodesAlive->put(mac, timeNew); //update NodesAlive w/ new time + //Serial.printf(" %0llX:%lu", mac, timeDiff); + if (timeDiff<1000){ + _myNodesTime->remove(_myNodesTime->getIndex(mac)); + _myNodesAlive->remove(_myNodesAlive->getIndex(mac)); + _myNodesRSSI->remove(_myNodesRSSI->getIndex(mac)); + Serial.printf("<%0llX> Dropped!\n", mac); + } + } + printNodesRSSI(); + //printNodes(); + //Serial.println(); + //sendEspNowEchoReq(); //request a HELLO ECHO! + #if (ENABLE_MESSAGEPACK) + sendEspNowMsgPack(); + #endif + #if (ENABLE_UNICAST) + //unicast to members in myNodes + if (counter <_myNodesTime->size()) { + uint64_t mac = _myNodesTime->getKey(counter); + if (mac != myMac) + unicastEspNowEchoReq(mac); + counter++; + } + else counter=0; + #endif + } + if (isEspNowRXed) { //Got EspNow RX data? + isEspNowRXed=false; + switch (EspNow.msgType) { + case myEspNowMsgType::HELLO: + //idLeader is the last one in _myNodesTime + macLeader = _myNodesTime->getKey(_myNodesTime->size()-1); + if (EspNow.macAddr64 == macLeader) { //Leader's HELLO + tickBlinkLED.once_ms(1000-(EspNow.ums%1000), blinkLED); //Scheduling for next blink and try to sync w/ Leader + } + if (!_myNodesTime->has(EspNow.macAddr64)) { //New memeber + _myNodesAlive->put(EspNow.macAddr64, 0); //Add 0 to nodesAlive + _myNodesRSSI->put(EspNow.macAddr64, 0); //Add 0 to nodesRSSI + _myNodesTime->put(EspNow.macAddr64, EspNow.ums); + Serial.printf("<%0llX> Added!\n", EspNow.macAddr64); + //printNodesOld(); + //printNodes(); + } + else { //Old member + _myNodesTime->put(EspNow.macAddr64, EspNow.ums); + //Average RSSI for node + int8_t rssiOld = _myNodesRSSI->getData(_myNodesRSSI->getIndex(EspNow.macAddr64)); + //Serial.printf("<%0llX>RSSI:%d/%d\n", EspNow.macAddr64, rssiOld, EspNow.rssi); + _myNodesRSSI->put(EspNow.macAddr64, (EspNow.rssi/2 + rssiOld/2)); + } + break; + case myEspNowMsgType::ECHO_REQ: + //sendEspNowEchoAck(); //Ack the REQ, send back HELLO + //break; + case myEspNowMsgType::ECHO_ACK: //Echo acked! calculate RTTI + if (myMac == EspNow.macAddr64) { + uint32_t uRTTI = micros() - EspNow.ums; + Serial.printf("!!! ECHO RTTI=%luus from:%llX (%d)dBm\n", uRTTI, EspNow.macAddr64, EspNow.rssi); + //Serial.printf(" From mac:%02x:%02x:%02x:%02x:%02x:%02x\n", MAC2STR(EspNow.mac)); + } + break; + case myEspNowMsgType::MSGPACK: + parseMessagePack(_myMessagePack.pack()); + break; + } + } +} \ No newline at end of file diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h index 71b8671..58093c2 100644 --- a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myEspNow.h @@ -5,22 +5,27 @@ #define LED0 0 +#include +extern MessagePack _myMessagePack; + enum myEspNowMsgType { HELLO =0x10, // ID+frames+millis - SYNC_REQ =0x80, // Request to sync - SYNC_ACK, + ECHO_REQ, // HELLO ECHO request, send HELLO packets back! + ECHO_ACK, // HELLO ECHO ackowledge + MSGPACK =0x80, // MsgPack Data + Reserved // Reserved }; struct espnow_struct { uint8_t msgType; //msgType: 0x10:time-report, 0x18:echo time-report - uint32_t id; - uint16_t frames; - uint32_t ms; + uint64_t macAddr64; + //uint16_t frames; + uint32_t ums; int8_t rssi; }; - +extern bool isUSBCDC(); extern uint32_t getESP32ChipID24(); extern void neopixelRGB(uint8_t r, uint8_t g, uint8_t b); extern void neopixelSetupBlink(int msBlink); @@ -29,14 +34,21 @@ extern void printESP32info(); //extern SimpleList* listID; //extern void printListID(); //extern void setupListID(); - -extern SimpleMap *_myNodes, *_myNodesOld; + +extern uint64_t myMac; +extern SimpleMap *_myNodesTime, *_myNodesAlive; +extern SimpleMap *_myNodesRSSI; extern void setupNodesMap(); -extern void printNodes(); +extern void printNodesTime(); extern void printNodesOld(); - +extern void printNodesAlive(); +extern void printNodesRSSI(); //WiFi Promiscuous Sniff //extern void setupWiFiSniffer(); +extern float readTempSensor(); +extern void setupTempSensor(); + +extern void parseMessagePack(unsigned char * data); #endif \ No newline at end of file diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myMessagePack.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myMessagePack.cpp new file mode 100644 index 0000000..667c860 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/myMessagePack.cpp @@ -0,0 +1,39 @@ + +#include +#include + +MessagePack _myMessagePack; //MessagePack for rx + +void parseMessagePack(unsigned char * data) { + //MessagePack * message = new MessagePack(); + Serial.print("myMessagePack:"); + for (int i=0;i<_myMessagePack.length();i++) { + Serial.printf(" %02X", _myMessagePack.pack()[i]); + } + Serial.println(); + // Load the data + //message->unpack(data, message->length()); + // Number of elements + unsigned char count = _myMessagePack.count(); + //Serial.print("Number of values: "); + //Serial.println(count); + // Walk elements + Serial.print("("); + char buffer[32]; + for (unsigned char i=0; i #include -SimpleMap *_myNodes, *_myNodesOld; +SimpleMap *_myNodesTime, *_myNodesAlive; +SimpleMap *_myNodesRSSI; +#include "myEspNow.h" void setupNodesMap() { - _myNodes = new SimpleMap([](uint32_t &a, uint32_t &b) ->int { + _myNodesTime = new SimpleMap([](uint64_t &a, uint64_t &b) ->int { if (a == b) return 0; // a and b are equal else if (a > b) return 1; // a is bigger than b else return -1; // a is smaller than b }); - _myNodesOld = new SimpleMap([](uint32_t &a, uint32_t &b) ->int { + _myNodesAlive = new SimpleMap([](uint64_t &a, uint64_t &b) ->int { if (a == b) return 0; // a and b are equal else if (a > b) return 1; // a is bigger than b else return -1; // a is smaller than b }); + _myNodesRSSI = new SimpleMap([](uint64_t &a, uint64_t &b) ->int { + if (a == b) return 0; // a and b are equal + else if (a > b) return 1; // a is bigger than b + else return -1; // a is smaller than b + }); } -void printNodes() +void printNodesTime() { - Serial.printf("[%lu]===>[", millis()); - for (int i=0;i<_myNodes->size();i++) { - Serial.printf(" %0X:%lu",_myNodes->getKey(i), _myNodes->getData(i)); + Serial.printf("[%lu]===>%d[", millis(), _myNodesTime->size()); + for (int i=0;i<_myNodesTime->size();i++) { + Serial.printf(" %0llX:%lu",_myNodesTime->getKey(i), _myNodesTime->getData(i)/1000); } - Serial.printf("]<===\n"); + int32_t imsLeader= _myNodesTime->getData(_myNodesTime->size()-1)%1000; + Serial.println("]<==="); + //Serial.printf("]<=== %03lu(%03lu)\n", imsLeader, 1000-imsLeader); } void printNodesOld() { - Serial.printf("--->("); - for (int i=0;i<_myNodesOld->size();i++) { - Serial.printf(" %0X:%lu",_myNodesOld->getKey(i), _myNodesOld->getData(i)); + Serial.printf("[%lu]--->%d(", millis(), _myNodesAlive->size()); + for (int i=0;i<_myNodesAlive->size();i++) { + Serial.printf(" %0llX:%lu",_myNodesAlive->getKey(i), _myNodesAlive->getData(i)/1000); } Serial.printf(")<---\n"); -} \ No newline at end of file +} + +/** + * @brief print Nodes && KeepAlive time + * + */ +void printNodesAlive() +{ + Serial.printf("[%lu]>>>%d[", millis(), _myNodesTime->size()); + for (int i=0;i<_myNodesTime->size();i++) { //print macId:alive seconds + uint64_t mac = _myNodesTime->getKey(i); + char cMark = '*'; + if (mac == myMac) cMark='#'; + Serial.printf(" %c%04llX:%3lu", cMark, mac&0x00FFFF, (_myNodesTime->getData(i)-_myNodesAlive->getData(i))/1000); + } + int32_t imsLeader= _myNodesTime->getData(_myNodesTime->size()-1)%1000; + Serial.printf("]<<< %03lu(%03lu)ms\n", imsLeader, 1000-imsLeader); //blink millis +} + +void printNodesRSSI() +{ + Serial.printf("[%lu]\t>>>%d[", millis(), _myNodesTime->size()); + for (int i=0;i<_myNodesRSSI->size();i++) { //print macId:alive seconds + uint64_t mac = _myNodesRSSI->getKey(i); + char cMark = '*'; + if (mac == myMac) cMark='#'; + Serial.printf(" %c%04llX:%03d", cMark, mac&0x00FFFF, (mac==myMac)? 0:_myNodesRSSI->getData(i)); + } + int32_t imsLeader= _myNodesTime->getData(_myNodesTime->size()-1)%1000; + Serial.printf("]<<< \tSync:%03lu(%03lu)ms\n", imsLeader, 1000-imsLeader); //blink millis +} diff --git a/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/utilCDC.cpp b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/utilCDC.cpp new file mode 100644 index 0000000..69554e2 --- /dev/null +++ b/C3MikroBUS/PlatformIO/ESP32C3CDC_QuickEspNowSync/src/utilCDC.cpp @@ -0,0 +1,18 @@ +#include +#include + +bool isUSBCDC() + { + uint32_t regSOF1= *((volatile uint32_t *) USB_SERIAL_JTAG_FRAM_NUM_REG); + delay(5); + uint32_t regSOF2= *((volatile uint32_t *) USB_SERIAL_JTAG_FRAM_NUM_REG); + Serial.printf("USB SOF 3ms diff:%02d\n", regSOF2-regSOF1); + + bool isUSBCDCconnected = ((regSOF2-regSOF1)>0) ? true:false; + if (isUSBCDCconnected) + log_d("USBCDC Connected!"); + else + log_w("USBCDC NOT Connected!"); + + return isUSBCDCconnected; + }