From 0b4542bb842258c64987039c9acf1768498c5258 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sun, 6 Jun 2021 23:51:54 -0700 Subject: [PATCH 01/24] add License; CMake builds this fine locally --- .gitignore | 13 +- CMakeLists.txt | 89 +++++++ LICENSE | 339 +++++++++++++++++++++++++ Readme.md | 6 +- cmake/CPackInfo.cmake | 73 ++++++ cmake/Cache.cmake | 31 +++ cmake/CompilerWarnings.cmake | 78 ++++++ cmake/GetLibInfo.cmake | 39 +++ cmake/PreventInSourceBuilds.cmake | 18 ++ cmake/StandardProjectSettings.cmake | 37 +++ cmake/detectCPU.cmake | 43 ++++ cmake/pico_sdk_import.cmake | 62 +++++ cmake/toolchains/arm64.cmake | 34 +++ cmake/toolchains/armhf.cmake | 34 +++ cmake/toolchains/default.cmake | 1 + cmake/toolchains/i686.cmake | 34 +++ cmake/toolchains/x86_64.cmake | 34 +++ examples/CMakeLists.txt | 37 +++ examples/addons/Sniffer/CMakeLists.txt | 13 + examples/gwNodeInt/CMakeLists.txt | 13 + examples/ncurses/CMakeLists.txt | 13 + examples/ncursesInt/CMakeLists.txt | 13 + 22 files changed, 1049 insertions(+), 5 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 cmake/CPackInfo.cmake create mode 100644 cmake/Cache.cmake create mode 100644 cmake/CompilerWarnings.cmake create mode 100644 cmake/GetLibInfo.cmake create mode 100644 cmake/PreventInSourceBuilds.cmake create mode 100644 cmake/StandardProjectSettings.cmake create mode 100644 cmake/detectCPU.cmake create mode 100644 cmake/pico_sdk_import.cmake create mode 100644 cmake/toolchains/arm64.cmake create mode 100644 cmake/toolchains/armhf.cmake create mode 100644 cmake/toolchains/default.cmake create mode 100644 cmake/toolchains/i686.cmake create mode 100644 cmake/toolchains/x86_64.cmake create mode 100644 examples/CMakeLists.txt create mode 100644 examples/addons/Sniffer/CMakeLists.txt create mode 100644 examples/gwNodeInt/CMakeLists.txt create mode 100644 examples/ncurses/CMakeLists.txt create mode 100644 examples/ncursesInt/CMakeLists.txt diff --git a/.gitignore b/.gitignore index 8fe78b1..b3ddf24 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ -# ignore doxygen generated files +# Generated library files +*.so +*.so.1 + +# ignore docs folder docs/html/ docs/xml/ + +# ignore CMake stuff +build/ +*CMakeUserPresets.json + +# ignore local vscode folder +.vscode/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..4c89691 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.15) + +# Set the project name to your project name +project(RF24Gateway C CXX) +include(cmake/StandardProjectSettings.cmake) +include(cmake/PreventInSourceBuilds.cmake) + +# Link this 'library' to set the c++ standard / compile-time options requested +add_library(project_options INTERFACE) +target_compile_features(project_options INTERFACE cxx_std_17) +add_compile_options(-Ofast -Wall) + +# detect CPU and add compiler flags accordingly +include(cmake/detectCPU.cmake) + +if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + option(ENABLE_BUILD_WITH_TIME_TRACE "Enable -ftime-trace to generate time tracing .json files on clang" OFF) + if(ENABLE_BUILD_WITH_TIME_TRACE) + add_compile_definitions(project_options INTERFACE -ftime-trace) + endif() +endif() + +# Link this 'library' to use the warnings specified in CompilerWarnings.cmake +add_library(project_warnings INTERFACE) + +# enable cache system +include(cmake/Cache.cmake) + +# standard compiler warnings +include(cmake/CompilerWarnings.cmake) +set_project_warnings(project_warnings) + +# get library info from Arduino IDE's required library.properties file +include(cmake/GetLibInfo.cmake) # sets the variable LibTargetName + +# setup CPack options +include(cmake/CPackInfo.cmake) + +find_library(RF24 rf24 REQUIRED) +message(STATUS "using RF24 library: ${RF24}") + +find_library(RF24Network rf24network REQUIRED) +message(STATUS "using RF24Network library: ${RF24Network}") + +find_library(RF24Mesh rf24mesh REQUIRED) +message(STATUS "using RF24Mesh library: ${RF24Mesh}") + +########################### +# create target for bulding the RF24Log lib +########################### +add_library(${LibTargetName} SHARED + RF24Gateway.cpp + ) +target_include_directories(${LibTargetName} PUBLIC + ${CMAKE_CURRENT_LIST_DIR} + ) + +target_link_libraries(${LibTargetName} INTERFACE + project_options + project_warnings + SHARED ${RF24} + SHARED ${RF24Network} + SHARED ${RF24Mesh} + ) + +set_target_properties( + ${LibTargetName} + PROPERTIES + SOVERSION ${${LibName}_VERSION_MAJOR} + VERSION ${${LibName}_VERSION_STRING} + ) + +########################### +# target install rules for the RF24Log lib +########################### +install(TARGETS ${LibTargetName} + DESTINATION lib + ) + +install(FILES + RF24Gateway.h + DESTINATION include/RF24Gateway + ) + +# CMAKE_CROSSCOMPILING is only TRUE when CMAKE_TOOLCHAIN_FILE is specified via CLI +if(CMAKE_HOST_UNIX AND "${CMAKE_CROSSCOMPILING}" STREQUAL "FALSE") + install(CODE "message(STATUS \"Updating ldconfig\")") + install(CODE "execute_process(COMMAND ldconfig)") +endif() diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..23cb790 --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + 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 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Readme.md b/Readme.md index a521589..e93d102 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,4 @@ - -**RF24Gateway** - +## RF24Gateway A complimentary library to RF24Ethernet, for RPi/Linux devices. RF24Ethernet allows small Arduino/AVR devices to communicate using TCP/IP over nrf24l01 radio modules. @@ -8,7 +6,7 @@ RF24Ethernet allows small Arduino/AVR devices to communicate using TCP/IP over n RF24Gateway allows a RPi/Linux device to act as a gateway for those nodes, handling IP traffic automatically, while allowing users to utilize standard RF24Network messages as well. -**Documentation:** +### Documentation: http://nRF24.github.io/RF24Gateway diff --git a/cmake/CPackInfo.cmake b/cmake/CPackInfo.cmake new file mode 100644 index 0000000..f5c9e3a --- /dev/null +++ b/cmake/CPackInfo.cmake @@ -0,0 +1,73 @@ +# This module will build a debian compatible package to install - handy for cross-compiling + +if(NOT PKG_REV) + set(PKG_REV "1") +endif() + +# get target arch if not cross-compiling +if(NOT TARGET_ARCH) # TARGET_ARCH is defined only in the toolchain_.cmake files + if(WIN32) + set(TARGET_ARCH $ENV{PROCESSOR_ARCHITECTURE}) + else() + execute_process(COMMAND dpkg --print-architecture + OUTPUT_VARIABLE TARGET_ARCH + ) + endif() + string(STRIP "${TARGET_ARCH}" TARGET_ARCH) +endif() + +# set the Cpack generators (specific to types of packages to create) +if(NOT WIN32) + set(CPACK_GENERATOR DEB RPM) # RPM requires rpmbuild executable +else() + set(CPACK_GENERATOR "") # should find out how to build vcpkg packages +endif() + +# assemble a debian package filename from known info +include(InstallRequiredSystemLibraries) +set(CPACK_PACKAGE_FILE_NAME "lib${LibTargetName}_${${LibName}_VERSION_STRING}-${PKG_REV}_${TARGET_ARCH}") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +set(CPACK_PACKAGE_VERSION_MAJOR "${${LibName}_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${${LibName}_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${${LibName}_VERSION_PATCH}") +set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/pkgs") # for easy uploading to github releases + +if(NOT WIN32) + ############################### + # info specific debian packages + ############################### + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) + set(CPACK_DEBIAN_PACKAGE_SECTION libs) + set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE) + set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) + + ############################### + # info specific rpm (fedora) packages + ############################### + set(CPACK_RPM_FILE_NAME "lib${LibTargetName}-${${LibName}_VERSION_STRING}-${PKG_REV}.${TARGET_ARCH}.rpm") + set(CPACK_RPM_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) + set(CPACK_RPM_PACKAGE_LICENSE "GPLv2.0") + set(CPACK_RPM_PACKAGE_VENDOR "Humanity") + + # create a post-install & post-removal scripts to update linker + set(POST_SCRIPTS + ${CMAKE_BINARY_DIR}/DEBIAN/postrm + ${CMAKE_BINARY_DIR}/DEBIAN/postinst + ) + foreach(script ${POST_SCRIPTS}) + file(WRITE ${script} /sbin/ldconfig) + execute_process(COMMAND chmod +x ${script}) + execute_process(COMMAND chmod 775 ${script}) + endforeach() + # declare scripts for deb pkgs + list(JOIN POST_SCRIPTS ";" EXTRA_CTRL_FILES) + set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA EXTRA_CTRL_FILES) + # declare scripts for rpm pkgs + list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE) + list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_INSTALL_SCRIPT_FILE) + + message(STATUS "ready to package: ${CPACK_PACKAGE_FILE_NAME}.deb") + message(STATUS "ready to package: ${CPACK_RPM_FILE_NAME}") +endif() + +include(CPack) diff --git a/cmake/Cache.cmake b/cmake/Cache.cmake new file mode 100644 index 0000000..4cc2e8c --- /dev/null +++ b/cmake/Cache.cmake @@ -0,0 +1,31 @@ +option(ENABLE_CACHE "Enable cache if available" ON) +if(NOT ENABLE_CACHE) + return() +endif() + +set(CACHE_OPTION + "ccache" + CACHE STRING "Compiler cache to be used" + ) +set(CACHE_OPTION_VALUES "ccache" "sccache") +set_property(CACHE CACHE_OPTION PROPERTY STRINGS ${CACHE_OPTION_VALUES}) +list( + FIND + CACHE_OPTION_VALUES + ${CACHE_OPTION} + CACHE_OPTION_INDEX + ) + +if(${CACHE_OPTION_INDEX} EQUAL -1) + message(STATUS + "Using custom compiler cache system: '${CACHE_OPTION}', explicitly supported entries are ${CACHE_OPTION_VALUES}" + ) +endif() + +find_program(CACHE_BINARY ${CACHE_OPTION}) +if(CACHE_BINARY) + message(STATUS "${CACHE_OPTION} found and enabled") + set(CMAKE_CXX_COMPILER_LAUNCHER ${CACHE_BINARY}) +else() + message(WARNING "${CACHE_OPTION} is enabled but was not found. Not using it") +endif() diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake new file mode 100644 index 0000000..9031160 --- /dev/null +++ b/cmake/CompilerWarnings.cmake @@ -0,0 +1,78 @@ +# from here: +# +# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md + +function(set_project_warnings project_name) + option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" TRUE) + + set(MSVC_WARNINGS + /W4 # Baseline reasonable warnings + /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not + # be destructed correctly + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside + # the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /permissive- # standards conformance mode for MSVC compiler. + ) + + set(CLANG_WARNINGS + -Wall + -Wextra # reasonable and standard + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps + # catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + ) + + if(WARNINGS_AS_ERRORS) + set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) + set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) + endif() + + set(GCC_WARNINGS + ${CLANG_WARNINGS} + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + -Wduplicated-cond # warn if if / else chain has duplicated conditions + -Wduplicated-branches # warn if if / else branches have duplicated code + -Wlogical-op # warn about logical operations being used where bitwise were probably wanted + -Wuseless-cast # warn if you perform a cast to the same type + ) + + if(MSVC) + set(PROJECT_WARNINGS ${MSVC_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + set(PROJECT_WARNINGS ${CLANG_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(PROJECT_WARNINGS ${GCC_WARNINGS}) + else() + message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") + endif() + + target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS}) + +endfunction() diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake new file mode 100644 index 0000000..9ed2bb0 --- /dev/null +++ b/cmake/GetLibInfo.cmake @@ -0,0 +1,39 @@ +# get lib info from the git cmds +execute_process(COMMAND git config --get remote.origin.url OUTPUT_VARIABLE CMAKE_PROJECT_HOMEPAGE_URL) +string(STRIP CMAKE_PROJECT_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) + +# use URL to get repo owner as Contact/Maintainer name +string(REGEX REPLACE "^http[s]?://github.com/(.+)/.+\\.git" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) + +# use URL to get the repo name as the Lib Name. Note that we don't use the folder name for this +string(REGEX REPLACE "^http[s]?://github.com/.+/(.+)\\.git" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(STRIP "${LibName}" LibName) + +# convert the LibName to lower case +string(TOLOWER ${LibName} LibTargetName) + +# have to hard-code the Repo Summary (which is copied from the parent repo's "About" info) +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "TCP/IP (RF24Ethernet) and RF24Network Gateway") + +# Use repo README.md to get the project description +file(READ "README.md" CPACK_PACKAGE_DESCRIPTION) +string(FIND "${CPACK_PACKAGE_DESCRIPTION}" "## RF24Gateway" README_TITLE) +math(EXPR README_TITLE "${README_TITLE} + 15") # compensates for '\n' char +string(FIND "${CPACK_PACKAGE_DESCRIPTION}" "### Documentation" DOC_LINK_TITLE) +math(EXPR DESCRIPTION_LENGTH "${DOC_LINK_TITLE} - ${README_TITLE}") +string(SUBSTRING "${CPACK_PACKAGE_DESCRIPTION}" ${README_TITLE} ${DESCRIPTION_LENGTH} CPACK_PACKAGE_DESCRIPTION) + +# parse the version information into pieces. +execute_process(COMMAND git describe --tags OUTPUT_VARIABLE VERSION) +string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") +string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") +string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}") + +# this is the library version +set(${LibName}_VERSION_MAJOR ${VERSION_MAJOR}) +set(${LibName}_VERSION_MINOR ${VERSION_MINOR}) +set(${LibName}_VERSION_PATCH ${VERSION_PATCH}) +set(${LibName}_VERSION_STRING ${${LibName}_VERSION_MAJOR}.${${LibName}_VERSION_MINOR}.${${LibName}_VERSION_PATCH}) + +message(STATUS "${LibName} library version: ${${LibName}_VERSION_STRING}") diff --git a/cmake/PreventInSourceBuilds.cmake b/cmake/PreventInSourceBuilds.cmake new file mode 100644 index 0000000..dc4fd81 --- /dev/null +++ b/cmake/PreventInSourceBuilds.cmake @@ -0,0 +1,18 @@ +# +# This function will prevent in-source builds +function(AssureOutOfSourceBuilds) + # make sure the user doesn't play dirty with symlinks + get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) + get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) + + # disallow in-source builds + if("${srcdir}" STREQUAL "${bindir}") + message("######################################################") + message("Warning: in-source builds are disabled") + message("Please create a separate build directory and run cmake from there") + message("######################################################") + message(FATAL_ERROR "Quitting configuration") + endif() +endfunction() + +assureoutofsourcebuilds() diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake new file mode 100644 index 0000000..0414e99 --- /dev/null +++ b/cmake/StandardProjectSettings.cmake @@ -0,0 +1,37 @@ +# Set a default build type if none was specified +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + set(CMAKE_BUILD_TYPE + RelWithDebInfo + CACHE STRING "Choose the type of build." FORCE + ) + # Set the possible values of build type for cmake-gui, ccmake + set_property( + CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS + "Debug" + "Release" + "MinSizeRel" + "RelWithDebInfo" + ) +endif() + +# Generate compile_commands.json to make it easier to work with clang based tools +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF) + +if(ENABLE_IPO) + include(CheckIPOSupported) + check_ipo_supported( + RESULT + result + OUTPUT + output + ) + if(result) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(SEND_ERROR "IPO is not supported: ${output}") + endif() +endif() diff --git a/cmake/detectCPU.cmake b/cmake/detectCPU.cmake new file mode 100644 index 0000000..ebd7fe7 --- /dev/null +++ b/cmake/detectCPU.cmake @@ -0,0 +1,43 @@ +# try to get the CPU model using a Linux bash command +execute_process(COMMAND cat /proc/cpuinfo + OUTPUT_VARIABLE CPU_MODEL + ) + +# If above command is not executed on an actual SOC board (& compatible OS), then +# there won't be a "Hardware" field to describe the CPU model +string(FIND ${CPU_MODEL} "Hardware" cpu_info_has_hw_field) +if(${cpu_info_has_hw_field} GREATER 0) # Hardware field does exist + string(SUBSTRING ${CPU_MODEL} ${cpu_info_has_hw_field} -1 CPU_MODEL) + string(REGEX MATCH "[ ]+([A-Za-z0-9_])+" SOC ${CPU_MODEL}) + string(STRIP ${SOC} SOC) +else() # Hardware field does not exist + set(SOC "UNKNOWN") # use this string as a sentinel +endif() + +# detect machine hardware name +execute_process(COMMAND uname -m + OUTPUT_VARIABLE CPU_TYPE) +string(STRIP "${CPU_TYPE}" CPU_TYPE) +message(STATUS "detected CPU type: ${CPU_TYPE}") + +# add compiler flags to optomize builds with arm-linux-gnueabihf-g* compilers +if("${CMAKE_C_COMPILER}" STREQUAL "/usr/bin/arm-linux-gnueabihf-gcc" AND + "${CMAKE_CXX_COMPILER}" STREQUAL "/usr/bin/arm-linux-gnueabihf-g++") + if("${SOC}" STREQUAL "BCM2835") + add_compile_options(-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard) + elseif("$SOC" STREQUAL "BCM2836") + add_compile_options(-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard) + elseif("$SOC" STREQUAL "AM33XX") + add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) + elseif("$SOC" STREQUAL "A10") + add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) + elseif("$SOC" STREQUAL "A13") + add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) + elseif("$SOC" STREQUAL "A20") + add_compile_options(-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard) + elseif("$SOC" STREQUAL "H3") + add_compile_options(-march=armv8-a -mtune=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard) + endif() +endif() + +message(STATUS "detected SoC: ${SOC}") \ No newline at end of file diff --git a/cmake/pico_sdk_import.cmake b/cmake/pico_sdk_import.cmake new file mode 100644 index 0000000..07bd143 --- /dev/null +++ b/cmake/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /external/pico_sdk_import.cmake +# +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if(DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif() + +if(DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif() + +if(DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif() + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if(NOT PICO_SDK_PATH) + if(PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if(PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif() + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if(NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif() + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif() +endif() + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if(NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif() + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if(NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif() + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/cmake/toolchains/arm64.cmake b/cmake/toolchains/arm64.cmake new file mode 100644 index 0000000..add14e1 --- /dev/null +++ b/cmake/toolchains/arm64.cmake @@ -0,0 +1,34 @@ +###################### FOR CROSS-COMPILING using the aarch64-linux-gnu-g** compiler +# invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` +# this file is meant to be used generically, but will not work for all CMake projects +# this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm64) +set(TARGET_ARCH arm64) # only used in cmake/createDebianPkg.cmake +set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++) + +# CMAKE_SYSROOT can only be set in a toolchain file +# set(CMAKE_SYSROOT /usr/aarch64-linux-gnu) # useful when a target machine's files are available + +# set the directory for searching installed headers +# add_compile_options(-I /usr/aarch64-linux-gnu/include) # this may not be best practice + +#[[ +# CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine +set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) + +CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) +if cross-compiling a dependent lib (like MRAA - which is optional), then +set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to RF24 lib's CMAKE_FIND_ROOT_PATH +example using MRAA: +(for MRAA/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/RF24/repo/cmake/toolchains/arm64.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/aarch64-linux-gnu +(for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm64.cmake +]] +list(APPEND CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) +# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called diff --git a/cmake/toolchains/armhf.cmake b/cmake/toolchains/armhf.cmake new file mode 100644 index 0000000..f1611f2 --- /dev/null +++ b/cmake/toolchains/armhf.cmake @@ -0,0 +1,34 @@ +###################### FOR CROSS-COMPILING using the arm-linux-gnueabihf-g** compiler +# invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` +# this file is meant to be used generically, but will not work for all CMake projects +# this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR armhf) +set(TARGET_ARCH armhf) # only used in cmake/CPackInfo.cmake +set(CMAKE_C_COMPILER /usr/bin/arm-linux-gnueabihf-gcc) +set(CMAKE_CXX_COMPILER /usr/bin/arm-linux-gnueabihf-g++) + +# CMAKE_SYSROOT can only be set in a toolchain file +# set(CMAKE_SYSROOT /usr/arm-linux-gnueabihf) # useful when a target machine's files are available + +# set the directory for searching installed headers +# add_compile_options(-I /usr/arm-linux-gnueabihf/include) # this may not be best practice + +#[[ +# CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine +set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) + +CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) +if cross-compiling a dependent lib (like MRAA - which is optional), then +set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to RF24 lib's CMAKE_FIND_ROOT_PATH +example using MRAA: +(for MRAA/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/RF24/repo/cmake/toolchains/arm.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/arm-linux-gnueabihf +(for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm.cmake +]] +list(APPEND CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf) +# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called diff --git a/cmake/toolchains/default.cmake b/cmake/toolchains/default.cmake new file mode 100644 index 0000000..e67d723 --- /dev/null +++ b/cmake/toolchains/default.cmake @@ -0,0 +1 @@ +# empty toolchain file to allow CI scripts to still use system default toolchains \ No newline at end of file diff --git a/cmake/toolchains/i686.cmake b/cmake/toolchains/i686.cmake new file mode 100644 index 0000000..344fd8b --- /dev/null +++ b/cmake/toolchains/i686.cmake @@ -0,0 +1,34 @@ +###################### FOR CROSS-COMPILING using the i686-linux-gnu-g** compiler +# invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` +# this file is meant to be used generically, but will not work for all CMake projects +# this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR i686) +set(TARGET_ARCH i686) # only used in cmake/createDebianPkg.cmake +set(CMAKE_C_COMPILER /usr/bin/i686-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER /usr/bin/i686-linux-gnu-g++) + +# CMAKE_SYSROOT can only be set in a toolchain file +# set(CMAKE_SYSROOT /usr/i686-linux-gnu) # useful when a target machine's files are available + +# set the directory for searching installed headers +# add_compile_options(-I /usr/i686-linux-gnu/include) # this may not be best practice + +#[[ +# CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine +set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) + +CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) +if cross-compiling a dependent lib (like MRAA - which is optional), then +set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to RF24 lib's CMAKE_FIND_ROOT_PATH +example using MRAA: +(for MRAA/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/RF24/repo/cmake/toolchains/i686.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/i686-linux-gnu +(for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686.cmake +]] +list(APPEND CMAKE_FIND_ROOT_PATH /usr/i686-linux-gnu) +# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called diff --git a/cmake/toolchains/x86_64.cmake b/cmake/toolchains/x86_64.cmake new file mode 100644 index 0000000..b75ab3f --- /dev/null +++ b/cmake/toolchains/x86_64.cmake @@ -0,0 +1,34 @@ +###################### FOR CROSS-COMPILING using the x86_64-linux-gnux32-g** compiler +# invoke this toolchain file using `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/.cmake` +# this file is meant to be used generically, but will not work for all CMake projects +# this toolchain file's cmds was copied from the CMake docs then modified for better explanation and re-use + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR x86_64) +set(TARGET_ARCH x86_64) # only used in cmake/createDebianPkg.cmake +set(CMAKE_C_COMPILER /usr/bin/x86_64-linux-gnux32-gcc) +set(CMAKE_CXX_COMPILER /usr/bin/x86_64-linux-gnux32-g++) + +# CMAKE_SYSROOT can only be set in a toolchain file +# set(CMAKE_SYSROOT /usr/x86_64-linux-gnux32) # useful when a target machine's files are available + +# set the directory for searching installed headers +# add_compile_options(-I /usr/x86_64-linux-gnux32/include) # this may not be best practice + +#[[ +# CMAKE_STAGING_PREFIX is only useful for transfering a built CMake project to a target machine +set(CMAKE_STAGING_PREFIX /home/devel/stage) # use CMAKE_INSTALL_PREFIX instead (see below comments) + +CMAKE_FIND_ROOT_PATH is an empty list by default (this list can be modified where applicable) +if cross-compiling a dependent lib (like MRAA - which is optional), then +set the lib's CMAKE_INSTALL_PREFIX to a value that is appended to RF24 lib's CMAKE_FIND_ROOT_PATH +example using MRAA: +(for MRAA/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=path/to/RF24/repo/cmake/toolchains/x86_64.cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr/x86_64-linux-gnux32 +(for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/x86_64.cmake +]] +list(APPEND CMAKE_FIND_ROOT_PATH /usr/x86_64-linux-gnux32) +# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_package() is called diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..aa71032 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.12) + +project(RF24GatewayExamples) +add_compile_options(-Ofast -Wall) # passing the compiler a `-pthread` flag doesn't work here + +# detect the CPU make and type +include(../cmake/detectCPU.cmake) # sets the variable SOC accordingly + +find_library(RF24 rf24 REQUIRED) +message(STATUS "using RF24 library: ${RF24}") + +find_library(RF24Network rf24network REQUIRED) +message(STATUS "using RF24Network library: ${RF24Network}") + +find_library(RF24Mesh rf24mesh REQUIRED) +message(STATUS "using RF24Mesh library: ${RF24Mesh}") + +find_library(RF24Gateway rf24gateway REQUIRED) +message(STATUS "using RF24Gateway library: ${RF24Gateway}") + +set(example RF24GatewayNode) +# make a target +add_executable(${example} ${example}.cpp) + +# link the RF24 lib to the target. Notice we specify pthread as a linked lib here +target_link_libraries(${example} PUBLIC + ${RF24} + pthread + ${RF24Network} + ${RF24Mesh} + ${RF24Gateway} + ) + +add_subdirectory(ncurses) +add_subdirectory(ncursesInt) +add_subdirectory(gwNodeInt) +add_subdirectory(addons/Sniffer) diff --git a/examples/addons/Sniffer/CMakeLists.txt b/examples/addons/Sniffer/CMakeLists.txt new file mode 100644 index 0000000..2b83a3f --- /dev/null +++ b/examples/addons/Sniffer/CMakeLists.txt @@ -0,0 +1,13 @@ +set(example Sniffer) + +# make a target +add_executable(${example} ${example}.cpp) + +# link the RF24 lib to the target. Notice we specify pthread as a linked lib here +target_link_libraries(${example} PUBLIC + ${RF24} + pthread + ${RF24Network} + ${RF24Mesh} + ${RF24Gateway} + ) diff --git a/examples/gwNodeInt/CMakeLists.txt b/examples/gwNodeInt/CMakeLists.txt new file mode 100644 index 0000000..572690a --- /dev/null +++ b/examples/gwNodeInt/CMakeLists.txt @@ -0,0 +1,13 @@ +set(example RF24GatewayNodeInt) + +# make a target +add_executable(${example} ${example}.cpp) + +# link the RF24 lib to the target. Notice we specify pthread as a linked lib here +target_link_libraries(${example} PUBLIC + ${RF24} + pthread + ${RF24Network} + ${RF24Mesh} + ${RF24Gateway} + ) diff --git a/examples/ncurses/CMakeLists.txt b/examples/ncurses/CMakeLists.txt new file mode 100644 index 0000000..4e7751f --- /dev/null +++ b/examples/ncurses/CMakeLists.txt @@ -0,0 +1,13 @@ +set(example RF24Gateway_ncurses) + +# make a target +add_executable(${example} ${example}.cpp) + +# link the RF24 lib to the target. Notice we specify pthread as a linked lib here +target_link_libraries(${example} PUBLIC + ${RF24} + pthread + ${RF24Network} + ${RF24Mesh} + ${RF24Gateway} + ) diff --git a/examples/ncursesInt/CMakeLists.txt b/examples/ncursesInt/CMakeLists.txt new file mode 100644 index 0000000..b27803e --- /dev/null +++ b/examples/ncursesInt/CMakeLists.txt @@ -0,0 +1,13 @@ +set(example RF24Gateway_ncursesInt) + +# make a target +add_executable(${example} ${example}.cpp) + +# link the RF24 lib to the target. Notice we specify pthread as a linked lib here +target_link_libraries(${example} PUBLIC + ${RF24} + pthread + ${RF24Network} + ${RF24Mesh} + ${RF24Gateway} + ) From 0da85b42781732e153afc14e4746164adea0e2c5 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 00:30:26 -0700 Subject: [PATCH 02/24] add linux_build CI --- .github/workflows/build_linux.yml | 164 ++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 .github/workflows/build_linux.yml diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml new file mode 100644 index 0000000..bb82c24 --- /dev/null +++ b/.github/workflows/build_linux.yml @@ -0,0 +1,164 @@ +name: Linux build + +on: + pull_request: + types: [opened, reopened] + push: + release: + types: [published, edited] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + using_cmake: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + + matrix: + toolchain: + - compiler: "armhf" + usr_dir: "arm-linux-gnueabihf" + - compiler: "arm64" + usr_dir: "aarch64-linux-gnu" + # - compiler: "x86_64" + # usr_dir: "x86_64-linux-gnux32" + # - compiler: "i686" + # usr_dir: "i686-linux-gnu" + - compiler: "default" # github runner is hosted on a "amd64" + usr_dir: "local" + + steps: + - name: install rpmbuild + run: sudo apt-get install rpm + + # - name: provide toolchain (for x86_64) + # if: ${{ matrix.toolchain.compiler == 'x86_64' }} + # run: | + # sudo apt-get update + # sudo apt-get install gcc-x86-64-linux-gnux32 g++-x86-64-linux-gnux32 + + # - name: provide toolchain (for i686) + # if: ${{ matrix.toolchain.compiler == 'i686' }} + # run: | + # sudo apt-get update + # sudo apt-get install gcc-i686-linux-gnu g++-i686-linux-gnu + + - name: provide toolchain (for arm64) + if: ${{ matrix.toolchain.compiler == 'arm64' }} + run: | + sudo apt-get update + sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + + - name: provide toolchain (for armhf) + if: ${{ matrix.toolchain.compiler == 'armhf' }} + run: | + sudo apt-get update + sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf + + - name: checkout RF24 + uses: actions/checkout@v2 + with: + repository: nRF24/RF24 + ref: rp2xxx + + - name: build & install RF24 + run: | + mkdir build + cd build + cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE -D RF24_DRIVER=SPIDEV \ + -D CMAKE_INSTALL_PREFIX=/usr/${{ matrix.toolchain.usr_dir }} \ + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/${{ matrix.toolchain.compiler }}.cmake + sudo make install + + - name: checkout RF24Network + uses: actions/checkout@v2 + with: + repository: nRF24/RF24Network + ref: CMake-4-Linux + + - name: build & install RF24Network + run: | + mkdir build + cd build + cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE \ + -D CMAKE_INSTALL_PREFIX=/usr/${{ matrix.toolchain.usr_dir }} \ + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/${{ matrix.toolchain.compiler }}.cmake + sudo make install + + - name: checkout RF24Mesh + uses: actions/checkout@v2 + + - name: build & install RF24Mesh + run: | + mkdir build + cd build + cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE \ + -D CMAKE_INSTALL_PREFIX=/usr/${{ matrix.toolchain.usr_dir }} \ + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/${{ matrix.toolchain.compiler }}.cmake + sudo make install + + - name: checkout RF24Gateway + uses: actions/checkout@v2 + + - name: create CMake build environment + run: cmake -E make_directory ${{ github.workspace }}/build + + - name: configure lib + if: ${{ matrix.toolchain.compiler == 'default' }} + working-directory: ${{ github.workspace }}/build + run: cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE + + - name: configure lib (with toolchain compilers) + if: ${{ matrix.toolchain.compiler != 'default' }} + working-directory: ${{ github.workspace }}/build + run: | + cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE \ + -D CMAKE_INSTALL_PREFIX=/usr/${{ matrix.toolchain.usr_dir }} \ + -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/${{ matrix.toolchain.compiler }}.cmake + + - name: build lib + working-directory: ${{ github.workspace }}/build + run: cmake --build . + + - name: install lib + working-directory: ${{ github.workspace }}/build + run: sudo cmake --install . + + - name: package lib + working-directory: ${{ github.workspace }}/build + run: sudo cpack + + - name: Save artifact + uses: actions/upload-artifact@v2 + with: + name: "pkg_RF24Mesh" + path: | + ${{ github.workspace }}/build/pkgs/*.deb + ${{ github.workspace }}/build/pkgs/*.rpm + + - name: Upload Release assets + if: github.event_name == 'release' && (matrix.toolchain.compiler == 'armhf' || matrix.toolchain.compiler == 'arm64') + uses: csexton/release-asset-action@master + with: + pattern: "${{ github.workspace }}/build/pkgs/librf24*" + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: clean build environment + working-directory: ${{ github.workspace }}/build + run: sudo rm -r ./* + + - name: configure examples + working-directory: ${{ github.workspace }}/build + run: | + cmake ../examples \ + -D CMAKE_TOOLCHAIN_FILE=../cmake/toolchains/${{ matrix.toolchain.compiler }}.cmake + + - name: build examples (none that use ncurses) + working-directory: ${{ github.workspace }}/build + run: | + cmake --build . --target RF24GatewayNode --target Sniffer --target RF24GatewayNodeInt + file ./RF24GatewayNode From 8c50a95f8c57907520e05381812d709d92fbfadd Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 00:31:56 -0700 Subject: [PATCH 03/24] oops! c-n-p much? --- .github/workflows/build_linux.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index bb82c24..f409fd7 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -91,6 +91,8 @@ jobs: - name: checkout RF24Mesh uses: actions/checkout@v2 + repository: nRF24/RF24Mesh + ref: CMake-4-Linux - name: build & install RF24Mesh run: | From 9df2a8ff4df681c7e418be7cb52cba7f68b89d13 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 00:33:19 -0700 Subject: [PATCH 04/24] [LinuxCI] forgot the "with:" line --- .github/workflows/build_linux.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index f409fd7..d54e65c 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -91,6 +91,7 @@ jobs: - name: checkout RF24Mesh uses: actions/checkout@v2 + with: repository: nRF24/RF24Mesh ref: CMake-4-Linux From c610e095f0f9ccc052255b0e36c5e63c9a8f86f5 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 00:35:36 -0700 Subject: [PATCH 05/24] linux FS is case sensitive --- cmake/GetLibInfo.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index 9ed2bb0..639e792 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -17,7 +17,7 @@ string(TOLOWER ${LibName} LibTargetName) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "TCP/IP (RF24Ethernet) and RF24Network Gateway") # Use repo README.md to get the project description -file(READ "README.md" CPACK_PACKAGE_DESCRIPTION) +file(READ "Readme.md" CPACK_PACKAGE_DESCRIPTION) string(FIND "${CPACK_PACKAGE_DESCRIPTION}" "## RF24Gateway" README_TITLE) math(EXPR README_TITLE "${README_TITLE} + 15") # compensates for '\n' char string(FIND "${CPACK_PACKAGE_DESCRIPTION}" "### Documentation" DOC_LINK_TITLE) From 5def5e40146f64cd86c1bf73d9401761adf86a1c Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 00:43:09 -0700 Subject: [PATCH 06/24] this will fail in CI; I need to debug it more --- cmake/GetLibInfo.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index 639e792..71eb161 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -1,7 +1,7 @@ # get lib info from the git cmds execute_process(COMMAND git config --get remote.origin.url OUTPUT_VARIABLE CMAKE_PROJECT_HOMEPAGE_URL) string(STRIP CMAKE_PROJECT_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) - +message("URL = ${CMAKE_PROJECT_HOMEPAGE_URL}") # use URL to get repo owner as Contact/Maintainer name string(REGEX REPLACE "^http[s]?://github.com/(.+)/.+\\.git" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) From 5109a132edd0e1f9aab527f87efba0882c1110f9 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 01:19:53 -0700 Subject: [PATCH 07/24] use regex to detect if returned url ends with .git --- cmake/GetLibInfo.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index 71eb161..f1479de 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -1,13 +1,13 @@ # get lib info from the git cmds execute_process(COMMAND git config --get remote.origin.url OUTPUT_VARIABLE CMAKE_PROJECT_HOMEPAGE_URL) string(STRIP CMAKE_PROJECT_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) -message("URL = ${CMAKE_PROJECT_HOMEPAGE_URL}") + # use URL to get repo owner as Contact/Maintainer name -string(REGEX REPLACE "^http[s]?://github.com/(.+)/.+\\.git" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(REGEX REPLACE "^http[s]?://github.com/(.+)/.+[\\.git]?.*&" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) # use URL to get the repo name as the Lib Name. Note that we don't use the folder name for this -string(REGEX REPLACE "^http[s]?://github.com/.+/(.+)\\.git" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(REGEX REPLACE "^http[s]?://github.com/.+/(.+)[\\.git]?.*&" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") string(STRIP "${LibName}" LibName) # convert the LibName to lower case From eabc7af12cfa83a67c5100de328bad9e0c5f355f Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 01:35:07 -0700 Subject: [PATCH 08/24] better regex pattern --- cmake/GetLibInfo.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index f1479de..3bd2dd9 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -3,11 +3,11 @@ execute_process(COMMAND git config --get remote.origin.url OUTPUT_VARIABLE CMAKE string(STRIP CMAKE_PROJECT_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) # use URL to get repo owner as Contact/Maintainer name -string(REGEX REPLACE "^http[s]?://github.com/(.+)/.+[\\.git]?.*&" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(REGEX REPLACE "^http[s]?:\/\/github.com\/(.+)\/.+[\\.git]?.*" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) # use URL to get the repo name as the Lib Name. Note that we don't use the folder name for this -string(REGEX REPLACE "^http[s]?://github.com/.+/(.+)[\\.git]?.*&" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/.+\/(.+)[\\.git]?.*" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") string(STRIP "${LibName}" LibName) # convert the LibName to lower case From 6a91d3f8d4fd32f1b21f841adde947081e05d9d8 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 01:57:13 -0700 Subject: [PATCH 09/24] show me what `git describe` returns on GH runner --- cmake/GetLibInfo.cmake | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index 3bd2dd9..b982659 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -3,7 +3,7 @@ execute_process(COMMAND git config --get remote.origin.url OUTPUT_VARIABLE CMAKE string(STRIP CMAKE_PROJECT_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) # use URL to get repo owner as Contact/Maintainer name -string(REGEX REPLACE "^http[s]?:\/\/github.com\/(.+)\/.+[\\.git]?.*" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") +string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/(.+)\/.+[\\.git]?.*" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) # use URL to get the repo name as the Lib Name. Note that we don't use the folder name for this @@ -25,7 +25,15 @@ math(EXPR DESCRIPTION_LENGTH "${DOC_LINK_TITLE} - ${README_TITLE}") string(SUBSTRING "${CPACK_PACKAGE_DESCRIPTION}" ${README_TITLE} ${DESCRIPTION_LENGTH} CPACK_PACKAGE_DESCRIPTION) # parse the version information into pieces. -execute_process(COMMAND git describe --tags OUTPUT_VARIABLE VERSION) +execute_process(COMMAND git describe --tags + OUTPUT_VARIABLE VERSION + ERROR_VARIABLE GIT_DESCRIBE_FAIL + ) +if(${GIT_DESCRIBE_FAIL}) + message(FATAL "`git describe --tags` failed with: ${GIT_DESCRIBE_FAIL}") +else() + message("git describes the version tag as ${VERSION}") +endif() string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}") From 4a05041314bcbc2853bd5da6a956dc67585f7693 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 02:03:07 -0700 Subject: [PATCH 10/24] try with fetch-depth = 0 --- .github/workflows/build_linux.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index d54e65c..85ef24f 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -106,6 +106,8 @@ jobs: - name: checkout RF24Gateway uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: create CMake build environment run: cmake -E make_directory ${{ github.workspace }}/build From ee7b259e01c71e6460050853ca2b7c1178191a27 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 02:05:34 -0700 Subject: [PATCH 11/24] that worked; remove debug prompts --- cmake/GetLibInfo.cmake | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index b982659..251afc9 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -25,15 +25,7 @@ math(EXPR DESCRIPTION_LENGTH "${DOC_LINK_TITLE} - ${README_TITLE}") string(SUBSTRING "${CPACK_PACKAGE_DESCRIPTION}" ${README_TITLE} ${DESCRIPTION_LENGTH} CPACK_PACKAGE_DESCRIPTION) # parse the version information into pieces. -execute_process(COMMAND git describe --tags - OUTPUT_VARIABLE VERSION - ERROR_VARIABLE GIT_DESCRIBE_FAIL - ) -if(${GIT_DESCRIBE_FAIL}) - message(FATAL "`git describe --tags` failed with: ${GIT_DESCRIBE_FAIL}") -else() - message("git describes the version tag as ${VERSION}") -endif() +execute_process(COMMAND git describe --tags OUTPUT_VARIABLE VERSION) string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}") string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}") string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${VERSION}") From c3965855f01de247c8f1868e8eeb7455470529a2 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Mon, 7 Jun 2021 02:06:32 -0700 Subject: [PATCH 12/24] [no ci] rename workflow assets DL file --- .github/workflows/build_linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 85ef24f..bd4c48a 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -140,7 +140,7 @@ jobs: - name: Save artifact uses: actions/upload-artifact@v2 with: - name: "pkg_RF24Mesh" + name: "pkg_RF24Gateway" path: | ${{ github.workspace }}/build/pkgs/*.deb ${{ github.workspace }}/build/pkgs/*.rpm From 029709e2881f92b2862bc79cc8be786199fe43bd Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 04:51:26 -0700 Subject: [PATCH 13/24] [no ci] code fmt; prep rename casing of READMEs --- .github/workflows/build_linux.yml | 16 + .github/workflows/doxygen.yml | 29 +- CMakeLists.txt | 18 +- Readme.md => READM.md | 0 cmake/CPackInfo.cmake | 68 +- cmake/Cache.cmake | 14 +- cmake/CompilerWarnings.cmake | 6 +- cmake/GetLibInfo.cmake | 20 +- cmake/StandardProjectSettings.cmake | 16 +- cmake/detectCPU.cmake | 87 +- cmake/enableNcursesExample.cmake | 15 + cmake/pico_sdk_import.cmake | 4 +- cmake/toolchains/arm64.cmake | 1 - cmake/toolchains/armhf.cmake | 1 - cmake/toolchains/i686.cmake | 1 - cmake/toolchains/x86_64.cmake | 1 - docs/{README.md => READM.md} | 0 examples/CMakeLists.txt | 10 +- examples/{README.txt => READM.txt} | 0 examples/RF24GatewayNode.cpp | 139 +-- examples/addons/{README.md => READM.md} | 0 examples/addons/Sniffer/Sniffer.cpp | 100 +- .../BashClient/{readme.md => READM.md} | 0 .../NodeJSClient/{readme.md => READM.md} | 0 .../PythonClient/{readme.md => READM.md} | 0 examples/clients/{readme.md => READM.md} | 0 examples/ncurses/CMakeLists.txt | 7 +- examples/ncurses/RF24Gateway_ncurses.cpp | 1021 ++++++++-------- examples/ncursesInt/CMakeLists.txt | 7 +- .../ncursesInt/RF24Gateway_ncursesInt.cpp | 1068 +++++++++-------- 30 files changed, 1439 insertions(+), 1210 deletions(-) rename Readme.md => READM.md (100%) create mode 100644 cmake/enableNcursesExample.cmake rename docs/{README.md => READM.md} (100%) rename examples/{README.txt => READM.txt} (100%) rename examples/addons/{README.md => READM.md} (100%) rename examples/clients/BashClient/{readme.md => READM.md} (100%) rename examples/clients/NodeJSClient/{readme.md => READM.md} (100%) rename examples/clients/PythonClient/{readme.md => READM.md} (100%) rename examples/clients/{readme.md => READM.md} (100%) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index bd4c48a..c2b8aaa 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -3,7 +3,23 @@ name: Linux build on: pull_request: types: [opened, reopened] + paths: + - '*.h' + - '*.cpp' + - 'CMakeLists.txt' + - 'cmake/**' + - 'examples/**.cpp' + - '!**Makefile' # old build system is not tested in this workflow + - '.github/workflows/build_linux.yml' push: + paths: + - '*.h' + - '*.cpp' + - 'CMakeLists.txt' + - 'cmake/**' + - 'examples/**.cpp' + - '!**Makefile' # old build system is not tested in this workflow + - '.github/workflows/build_linux.yml' release: types: [published, edited] diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 032b251..37a8b09 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -2,17 +2,28 @@ name: DoxyGen build on: pull_request: - branches: - - master + branches: [master] + paths: + - '*.h' + - '*.md' + - 'docs/**' + - '!**README.md' + - 'examples**.cpp' + - '.github/workflows/doxygen.yml' + - 'Doxyfile' push: - branches: - - master + branches: [master] + paths: + - '*.h' + - '*.md' + - 'docs/**' + - '!**README.md' + - 'examples**.cpp' + - '.github/workflows/doxygen.yml' + - 'Doxyfile' release: - branches: - - master - types: - - published - - edited + branches: [master] + types: [published, edited] jobs: build-doxygen: diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c89691..5ce4426 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,12 +48,8 @@ message(STATUS "using RF24Mesh library: ${RF24Mesh}") ########################### # create target for bulding the RF24Log lib ########################### -add_library(${LibTargetName} SHARED - RF24Gateway.cpp - ) -target_include_directories(${LibTargetName} PUBLIC - ${CMAKE_CURRENT_LIST_DIR} - ) +add_library(${LibTargetName} SHARED RF24Gateway.cpp) +target_include_directories(${LibTargetName} PUBLIC ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(${LibTargetName} INTERFACE project_options @@ -61,26 +57,24 @@ target_link_libraries(${LibTargetName} INTERFACE SHARED ${RF24} SHARED ${RF24Network} SHARED ${RF24Mesh} - ) +) set_target_properties( ${LibTargetName} PROPERTIES SOVERSION ${${LibName}_VERSION_MAJOR} VERSION ${${LibName}_VERSION_STRING} - ) +) ########################### # target install rules for the RF24Log lib ########################### -install(TARGETS ${LibTargetName} - DESTINATION lib - ) +install(TARGETS ${LibTargetName} DESTINATION lib) install(FILES RF24Gateway.h DESTINATION include/RF24Gateway - ) +) # CMAKE_CROSSCOMPILING is only TRUE when CMAKE_TOOLCHAIN_FILE is specified via CLI if(CMAKE_HOST_UNIX AND "${CMAKE_CROSSCOMPILING}" STREQUAL "FALSE") diff --git a/Readme.md b/READM.md similarity index 100% rename from Readme.md rename to READM.md diff --git a/cmake/CPackInfo.cmake b/cmake/CPackInfo.cmake index f5c9e3a..172fd2d 100644 --- a/cmake/CPackInfo.cmake +++ b/cmake/CPackInfo.cmake @@ -11,7 +11,7 @@ if(NOT TARGET_ARCH) # TARGET_ARCH is defined only in the toolchain_.c else() execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE TARGET_ARCH - ) + ) endif() string(STRIP "${TARGET_ARCH}" TARGET_ARCH) endif() @@ -32,42 +32,40 @@ set(CPACK_PACKAGE_VERSION_MINOR "${${LibName}_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${${LibName}_VERSION_PATCH}") set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/pkgs") # for easy uploading to github releases -if(NOT WIN32) - ############################### - # info specific debian packages - ############################### - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) - set(CPACK_DEBIAN_PACKAGE_SECTION libs) - set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE) - set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) +############################### +# info specific debian packages +############################### +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) +set(CPACK_DEBIAN_PACKAGE_SECTION libs) +set(CPACK_DEBIAN_PACKAGE_CONTROL_STRICT_PERMISSION TRUE) +set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON) - ############################### - # info specific rpm (fedora) packages - ############################### - set(CPACK_RPM_FILE_NAME "lib${LibTargetName}-${${LibName}_VERSION_STRING}-${PKG_REV}.${TARGET_ARCH}.rpm") - set(CPACK_RPM_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) - set(CPACK_RPM_PACKAGE_LICENSE "GPLv2.0") - set(CPACK_RPM_PACKAGE_VENDOR "Humanity") +############################### +# info specific rpm (fedora) packages +############################### +set(CPACK_RPM_FILE_NAME "lib${LibTargetName}-${${LibName}_VERSION_STRING}-${PKG_REV}.${TARGET_ARCH}.rpm") +set(CPACK_RPM_PACKAGE_ARCHITECTURE ${TARGET_ARCH}) +set(CPACK_RPM_PACKAGE_LICENSE "GPLv2.0") +set(CPACK_RPM_PACKAGE_VENDOR "Humanity") - # create a post-install & post-removal scripts to update linker - set(POST_SCRIPTS - ${CMAKE_BINARY_DIR}/DEBIAN/postrm - ${CMAKE_BINARY_DIR}/DEBIAN/postinst - ) - foreach(script ${POST_SCRIPTS}) - file(WRITE ${script} /sbin/ldconfig) - execute_process(COMMAND chmod +x ${script}) - execute_process(COMMAND chmod 775 ${script}) - endforeach() - # declare scripts for deb pkgs - list(JOIN POST_SCRIPTS ";" EXTRA_CTRL_FILES) - set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA EXTRA_CTRL_FILES) - # declare scripts for rpm pkgs - list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE) - list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_INSTALL_SCRIPT_FILE) +# create a post-install & post-removal scripts to update linker +set(POST_SCRIPTS + ${CMAKE_BINARY_DIR}/DEBIAN/postrm + ${CMAKE_BINARY_DIR}/DEBIAN/postinst +) +foreach(script ${POST_SCRIPTS}) + file(WRITE ${script} /sbin/ldconfig) + execute_process(COMMAND chmod +x ${script}) + execute_process(COMMAND chmod 775 ${script}) +endforeach() +# declare scripts for deb pkgs +list(JOIN POST_SCRIPTS ";" EXTRA_CTRL_FILES) +set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA EXTRA_CTRL_FILES) +# declare scripts for rpm pkgs +list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_UNINSTALL_SCRIPT_FILE) +list(POP_FRONT POST_SCRIPTS CPACK_RPM_POST_INSTALL_SCRIPT_FILE) - message(STATUS "ready to package: ${CPACK_PACKAGE_FILE_NAME}.deb") - message(STATUS "ready to package: ${CPACK_RPM_FILE_NAME}") -endif() +message(STATUS "ready to package: ${CPACK_PACKAGE_FILE_NAME}.deb") +message(STATUS "ready to package: ${CPACK_RPM_FILE_NAME}") include(CPack) diff --git a/cmake/Cache.cmake b/cmake/Cache.cmake index 4cc2e8c..8e7ae63 100644 --- a/cmake/Cache.cmake +++ b/cmake/Cache.cmake @@ -3,23 +3,15 @@ if(NOT ENABLE_CACHE) return() endif() -set(CACHE_OPTION - "ccache" - CACHE STRING "Compiler cache to be used" - ) +set(CACHE_OPTION "ccache" CACHE STRING "Compiler cache to be used") set(CACHE_OPTION_VALUES "ccache" "sccache") set_property(CACHE CACHE_OPTION PROPERTY STRINGS ${CACHE_OPTION_VALUES}) -list( - FIND - CACHE_OPTION_VALUES - ${CACHE_OPTION} - CACHE_OPTION_INDEX - ) +list(FIND CACHE_OPTION_VALUES ${CACHE_OPTION} CACHE_OPTION_INDEX) if(${CACHE_OPTION_INDEX} EQUAL -1) message(STATUS "Using custom compiler cache system: '${CACHE_OPTION}', explicitly supported entries are ${CACHE_OPTION_VALUES}" - ) + ) endif() find_program(CACHE_BINARY ${CACHE_OPTION}) diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index 9031160..af36206 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -29,7 +29,7 @@ function(set_project_warnings project_name) /w14906 # string literal cast to 'LPWSTR' /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied /permissive- # standards conformance mode for MSVC compiler. - ) + ) set(CLANG_WARNINGS -Wall @@ -47,7 +47,7 @@ function(set_project_warnings project_name) -Wnull-dereference # warn if a null dereference is detected -Wdouble-promotion # warn if float is implicit promoted to double -Wformat=2 # warn on security issues around functions that format output (ie printf) - ) + ) if(WARNINGS_AS_ERRORS) set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) @@ -61,7 +61,7 @@ function(set_project_warnings project_name) -Wduplicated-branches # warn if if / else branches have duplicated code -Wlogical-op # warn about logical operations being used where bitwise were probably wanted -Wuseless-cast # warn if you perform a cast to the same type - ) + ) if(MSVC) set(PROJECT_WARNINGS ${MSVC_WARNINGS}) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index 251afc9..6a58fc6 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -1,14 +1,20 @@ # get lib info from the git cmds -execute_process(COMMAND git config --get remote.origin.url OUTPUT_VARIABLE CMAKE_PROJECT_HOMEPAGE_URL) -string(STRIP CMAKE_PROJECT_HOMEPAGE_URL ${CMAKE_PROJECT_HOMEPAGE_URL}) +execute_process(COMMAND git config --get remote.origin.url + OUTPUT_VARIABLE CMAKE_PROJECT_HOMEPAGE_URL + OUTPUT_STRIP_TRAILING_WHITESPACE +) +string(FIND "${CMAKE_PROJECT_HOMEPAGE_URL}" ".git" has_git_ext REVERSE) +if(has_git_ext GREATER -1) + string(SUBSTRING "${CMAKE_PROJECT_HOMEPAGE_URL}" 0 ${has_git_ext} CMAKE_PROJECT_HOMEPAGE_URL) +endif() # use URL to get repo owner as Contact/Maintainer name -string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/(.+)\/.+[\\.git]?.*" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") -string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) +string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/(.+)\/.+$" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") +# string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) # use URL to get the repo name as the Lib Name. Note that we don't use the folder name for this -string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/.+\/(.+)[\\.git]?.*" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") -string(STRIP "${LibName}" LibName) +string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/.+\/(.+)$" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") +# string(STRIP "${LibName}" LibName) # convert the LibName to lower case string(TOLOWER ${LibName} LibTargetName) @@ -17,7 +23,7 @@ string(TOLOWER ${LibName} LibTargetName) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "TCP/IP (RF24Ethernet) and RF24Network Gateway") # Use repo README.md to get the project description -file(READ "Readme.md" CPACK_PACKAGE_DESCRIPTION) +file(READ "README.md" CPACK_PACKAGE_DESCRIPTION) string(FIND "${CPACK_PACKAGE_DESCRIPTION}" "## RF24Gateway" README_TITLE) math(EXPR README_TITLE "${README_TITLE} + 15") # compensates for '\n' char string(FIND "${CPACK_PACKAGE_DESCRIPTION}" "### Documentation" DOC_LINK_TITLE) diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake index 0414e99..75a379f 100644 --- a/cmake/StandardProjectSettings.cmake +++ b/cmake/StandardProjectSettings.cmake @@ -1,10 +1,10 @@ # Set a default build type if none was specified if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") + message(STATUS "Setting build type to 'Release' as none was specified.") set(CMAKE_BUILD_TYPE - RelWithDebInfo + Release CACHE STRING "Choose the type of build." FORCE - ) + ) # Set the possible values of build type for cmake-gui, ccmake set_property( CACHE CMAKE_BUILD_TYPE @@ -13,7 +13,7 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) "Release" "MinSizeRel" "RelWithDebInfo" - ) + ) endif() # Generate compile_commands.json to make it easier to work with clang based tools @@ -24,11 +24,9 @@ option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimizati if(ENABLE_IPO) include(CheckIPOSupported) check_ipo_supported( - RESULT - result - OUTPUT - output - ) + RESULT result + OUTPUT output + ) if(result) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) else() diff --git a/cmake/detectCPU.cmake b/cmake/detectCPU.cmake index ebd7fe7..bd702f9 100644 --- a/cmake/detectCPU.cmake +++ b/cmake/detectCPU.cmake @@ -1,43 +1,78 @@ # try to get the CPU model using a Linux bash command -execute_process(COMMAND cat /proc/cpuinfo - OUTPUT_VARIABLE CPU_MODEL - ) +if(NOT SOC) # if SOC variable not defined by user at CLI + if(EXISTS "/sys/class/sunxi_info/sys_info") + execute_process(COMMAND grep sunxi_platform /sys/class/sunxi_info/sys_info + OUTPUT_VARIABLE CPU_MODEL + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + else() + execute_process(COMMAND grep Hardware /proc/cpuinfo + OUTPUT_VARIABLE CPU_MODEL + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif() -# If above command is not executed on an actual SOC board (& compatible OS), then -# there won't be a "Hardware" field to describe the CPU model -string(FIND ${CPU_MODEL} "Hardware" cpu_info_has_hw_field) -if(${cpu_info_has_hw_field} GREATER 0) # Hardware field does exist - string(SUBSTRING ${CPU_MODEL} ${cpu_info_has_hw_field} -1 CPU_MODEL) - string(REGEX MATCH "[ ]+([A-Za-z0-9_])+" SOC ${CPU_MODEL}) - string(STRIP ${SOC} SOC) -else() # Hardware field does not exist - set(SOC "UNKNOWN") # use this string as a sentinel + string(FIND "${CPU_MODEL}" ":" cpu_is_described) + if(${cpu_is_described} GREATER 0) # Hardware field does exist + math(EXPR cpu_is_described "${cpu_is_described} + 1") + string(SUBSTRING "${CPU_MODEL}" ${cpu_is_described} -1 SOC) + string(STRIP "${SOC}" SOC) + else() # Hardware field does not exist + set(SOC "UNKNOWN") # use this string as a sentinel + endif() + message(STATUS "detected SoC: ${SOC}") +else() + message(STATUS "SOC set to ${SOC}") endif() -# detect machine hardware name +string(FIND "${SOC}" "Generic AM33XX" is_AM33XX) + +#[[ detect machine hardware name +This CPU_TYPE variable is not used anywhere. +It remains as useful prompt info & to be consistent with old build system ]] execute_process(COMMAND uname -m - OUTPUT_VARIABLE CPU_TYPE) -string(STRIP "${CPU_TYPE}" CPU_TYPE) + OUTPUT_VARIABLE CPU_TYPE + OUTPUT_STRIP_TRAILING_WHITESPACE +) message(STATUS "detected CPU type: ${CPU_TYPE}") +# identify the compiler base name for customizing flags +# THIS ONLY WORKS/TESTED FOR GNU COMPILERS +if(NOT CMAKE_CROSSCOMPILING) # need to use /usr/lib/gcc soft symlink + # NOTE the following command doesn't work with " | tail -1" appended + execute_process(COMMAND ls /usr/lib/gcc + OUTPUT_VARIABLE tool_name + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # use only last entry if multiple entries are returned + string(FIND "${tool_name}" "\n" last_list_delimiter REVERSE) + if(last_list_delimiter GREATER -1) + math(EXPR last_list_delimiter "${last_list_delimiter} + 1") + string(SUBSTRING "${tool_name}" ${last_list_delimiter} -1 tool_name) + endif() + +else() # we can use the compiler's name of the path set in the toolchain file + string(REGEX REPLACE "^\/usr\/bin\/(.*)-gcc.*" "\\1" tool_name "${CMAKE_C_COMPILER}") +endif() + +message(STATUS "tool name being used is ${tool_name}") + # add compiler flags to optomize builds with arm-linux-gnueabihf-g* compilers -if("${CMAKE_C_COMPILER}" STREQUAL "/usr/bin/arm-linux-gnueabihf-gcc" AND - "${CMAKE_CXX_COMPILER}" STREQUAL "/usr/bin/arm-linux-gnueabihf-g++") - if("${SOC}" STREQUAL "BCM2835") +if("${tool_name}" STREQUAL "arm-linux-gnueabihf") + if("${SOC}" STREQUAL "BCM2835" OR "${SOC}" STREQUAL "BCM2708") add_compile_options(-marm -march=armv6zk -mtune=arm1176jzf-s -mfpu=vfp -mfloat-abi=hard) - elseif("$SOC" STREQUAL "BCM2836") + elseif("$SOC" STREQUAL "BCM2836" OR "${SOC}" STREQUAL "BCM2709") add_compile_options(-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard) - elseif("$SOC" STREQUAL "AM33XX") + elseif(${is_AM33XX} GREATER -1) add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) - elseif("$SOC" STREQUAL "A10") + elseif("$SOC" STREQUAL "sun4i" OR "${SOC}" STREQUAL "Sun4iw1p1") # A10 add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) - elseif("$SOC" STREQUAL "A13") + elseif("$SOC" STREQUAL "sun5i" OR "${SOC}" STREQUAL "Sun4iw2p1") # A13 add_compile_options(-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=hard) - elseif("$SOC" STREQUAL "A20") + elseif("$SOC" STREQUAL "sun7i" OR "${SOC}" STREQUAL "Sun8iw2p1") # A20 add_compile_options(-march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard) - elseif("$SOC" STREQUAL "H3") + elseif("$SOC" STREQUAL "sun8i" OR "${SOC}" STREQUAL "Sun8iw7p1") # H3 add_compile_options(-march=armv8-a -mtune=cortex-a53 -mfpu=neon-vfpv4 -mfloat-abi=hard) endif() endif() - -message(STATUS "detected SoC: ${SOC}") \ No newline at end of file diff --git a/cmake/enableNcursesExample.cmake b/cmake/enableNcursesExample.cmake new file mode 100644 index 0000000..b016787 --- /dev/null +++ b/cmake/enableNcursesExample.cmake @@ -0,0 +1,15 @@ +find_package(Curses) +if(Curses_FOUND) + include_directories(${CURSES_INCLUDE_DIR}) + option(BUILD_NCURSES_EXAMPLE + "Enable/Disable building the ncurses example (requires libncurses5-dev installed)" + ON + ) +else() + message(STATUS "libncurses5-dev not found. Skipping ncurses example") + option(BUILD_NCURSES_EXAMPLE + "Enable/Disable building the ncurses example (requires libncurses5-dev installed)" + OFF + ) +endif() +message(STATUS "BUILD_NCURSES_EXAMPLE set to ${BUILD_NCURSES_EXAMPLE}") diff --git a/cmake/pico_sdk_import.cmake b/cmake/pico_sdk_import.cmake index 07bd143..0a1da56 100644 --- a/cmake/pico_sdk_import.cmake +++ b/cmake/pico_sdk_import.cmake @@ -33,7 +33,7 @@ if(NOT PICO_SDK_PATH) pico_sdk GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk GIT_TAG master - ) + ) if(NOT pico_sdk) message("Downloading Raspberry Pi Pico SDK") FetchContent_Populate(pico_sdk) @@ -43,7 +43,7 @@ if(NOT PICO_SDK_PATH) else () message(FATAL_ERROR "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." - ) + ) endif() endif() diff --git a/cmake/toolchains/arm64.cmake b/cmake/toolchains/arm64.cmake index add14e1..23e41ca 100644 --- a/cmake/toolchains/arm64.cmake +++ b/cmake/toolchains/arm64.cmake @@ -27,7 +27,6 @@ example using MRAA: (for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm64.cmake ]] list(APPEND CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) -# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called diff --git a/cmake/toolchains/armhf.cmake b/cmake/toolchains/armhf.cmake index f1611f2..488b81a 100644 --- a/cmake/toolchains/armhf.cmake +++ b/cmake/toolchains/armhf.cmake @@ -27,7 +27,6 @@ example using MRAA: (for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/arm.cmake ]] list(APPEND CMAKE_FIND_ROOT_PATH /usr/arm-linux-gnueabihf) -# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called diff --git a/cmake/toolchains/i686.cmake b/cmake/toolchains/i686.cmake index 344fd8b..f3c42be 100644 --- a/cmake/toolchains/i686.cmake +++ b/cmake/toolchains/i686.cmake @@ -27,7 +27,6 @@ example using MRAA: (for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/i686.cmake ]] list(APPEND CMAKE_FIND_ROOT_PATH /usr/i686-linux-gnu) -# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called diff --git a/cmake/toolchains/x86_64.cmake b/cmake/toolchains/x86_64.cmake index b75ab3f..e4ff737 100644 --- a/cmake/toolchains/x86_64.cmake +++ b/cmake/toolchains/x86_64.cmake @@ -27,7 +27,6 @@ example using MRAA: (for RF24/build dir) `cmake .. -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/x86_64.cmake ]] list(APPEND CMAKE_FIND_ROOT_PATH /usr/x86_64-linux-gnux32) -# message("CMAKE_FIND_ROOT_PATH = ${CMAKE_FIND_ROOT_PATH}") set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search CMAKE_SYSROOT when find_program() is called set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_library() is called set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # search CMAKE_FIND_ROOT_PATH entries when find_file() is called diff --git a/docs/README.md b/docs/READM.md similarity index 100% rename from docs/README.md rename to docs/READM.md diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index aa71032..b8ab01e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -29,9 +29,13 @@ target_link_libraries(${example} PUBLIC ${RF24Network} ${RF24Mesh} ${RF24Gateway} - ) +) -add_subdirectory(ncurses) -add_subdirectory(ncursesInt) add_subdirectory(gwNodeInt) add_subdirectory(addons/Sniffer) + +include(../cmake/enableNcursesExample.cmake) +if(BUILD_NCURSES_EXAMPLE) + add_subdirectory(ncurses) + add_subdirectory(ncursesInt) +endif() diff --git a/examples/README.txt b/examples/READM.txt similarity index 100% rename from examples/README.txt rename to examples/READM.txt diff --git a/examples/RF24GatewayNode.cpp b/examples/RF24GatewayNode.cpp index 048cfab..372375e 100644 --- a/examples/RF24GatewayNode.cpp +++ b/examples/RF24GatewayNode.cpp @@ -1,81 +1,82 @@ - - #include #include -#include +#include #include -//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); -RF24 radio(22,0); +RF24 radio(22, 0); RF24Network network(radio); -RF24Mesh mesh(radio,network); -RF24Gateway gw(radio,network,mesh); +RF24Mesh mesh(radio, network); +RF24Gateway gw(radio, network, mesh); uint32_t mesh_timer = 0; -int main(int argc, char** argv) { +int main(int argc, char **argv) +{ - //Config for use with RF24Mesh as Master Node - //uint8_t nodeID=0; - gw.begin(); + //Config for use with RF24Mesh as Master Node + //uint8_t nodeID=0; + gw.begin(); - //Config for use with RF24Mesh as child Node - // uint8_t nodeID = 2; - // gw.begin(nodeID); - - - //Config for use without RF24Mesh - // uint16_t RF24NetworkAddress = 0; - // gw.begin(RF24NetworkAddress); - - //Set this to your chosen IP/Subnet - char ip[] = "10.10.2.2"; - char subnet[] = "255.255.255.0"; - - gw.setIP(ip,subnet); - uint32_t failCounter = 0; - - while(1){ - - // The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface - // RF24Network user payloads are loaded into the user cache - gw.update(); - if( network.available() ){ - RF24NetworkHeader header; - size_t size = network.peek(header); - uint8_t buf[size]; - network.read(header,&buf,size); - printf("Received Network Message, type: %d id %d from %d\n",header.type,header.id,mesh.getNodeID(header.from_node)); - - RF24NetworkFrame frame = RF24NetworkFrame(header,buf,size); - gw.sendUDP(mesh.getNodeID(header.from_node),frame); - - } - delay(2); - - if(millis()-mesh_timer > 30000 && mesh.getNodeID()){ //Every 30 seconds, test mesh connectivity - mesh_timer = millis(); - if( ! mesh.checkConnection() ){ - //refresh the network address - mesh.renewAddress(); - } - } - //This section checks for failures detected by RF24 & RF24Network as well as - //checking for deviations from the default configuration (1MBPS data rate) - //The mesh is restarted on failure and failure count logged to failLog.txt - //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically - if(radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS){ - radio.failureDetected = 0; - std::ofstream myFile; - myFile.open ("failLog.txt"); - if (myFile.is_open()){ - myFile << ++failCounter << "\n"; - myFile.close(); - } - delay(500); - mesh.begin(); + //Config for use with RF24Mesh as child Node + // uint8_t nodeID = 2; + // gw.begin(nodeID); + + //Config for use without RF24Mesh + // uint16_t RF24NetworkAddress = 0; + // gw.begin(RF24NetworkAddress); + + //Set this to your chosen IP/Subnet + char ip[] = "10.10.2.2"; + char subnet[] = "255.255.255.0"; + + gw.setIP(ip, subnet); + uint32_t failCounter = 0; + + while (1) + { + + // The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface + // RF24Network user payloads are loaded into the user cache + gw.update(); + if (network.available()) + { + RF24NetworkHeader header; + size_t size = network.peek(header); + uint8_t buf[size]; + network.read(header, &buf, size); + printf("Received Network Message, type: %d id %d from %d\n", header.type, header.id, mesh.getNodeID(header.from_node)); + + RF24NetworkFrame frame = RF24NetworkFrame(header, buf, size); + gw.sendUDP(mesh.getNodeID(header.from_node), frame); + } + delay(2); + + if (millis() - mesh_timer > 30000 && mesh.getNodeID()) + { //Every 30 seconds, test mesh connectivity + mesh_timer = millis(); + if (!mesh.checkConnection()) + { + //refresh the network address + mesh.renewAddress(); + } + } + //This section checks for failures detected by RF24 & RF24Network as well as + //checking for deviations from the default configuration (1MBPS data rate) + //The mesh is restarted on failure and failure count logged to failLog.txt + //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically + if (radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS) + { + radio.failureDetected = 0; + std::ofstream myFile; + myFile.open("failLog.txt"); + if (myFile.is_open()) + { + myFile << ++failCounter << "\n"; + myFile.close(); + } + delay(500); + mesh.begin(); + } } - - } - return 0; + return 0; } diff --git a/examples/addons/README.md b/examples/addons/READM.md similarity index 100% rename from examples/addons/README.md rename to examples/addons/READM.md diff --git a/examples/addons/Sniffer/Sniffer.cpp b/examples/addons/Sniffer/Sniffer.cpp index d9ab0c2..b22f792 100644 --- a/examples/addons/Sniffer/Sniffer.cpp +++ b/examples/addons/Sniffer/Sniffer.cpp @@ -1,76 +1,72 @@ - /* RF24Network Scanner by TMRh20 Aug 2016 Outputs data to console & UDP port 32001 See the LUA script for Wireshark at https://github.com/TMRh20/RF24Gateway/tree/master/examples/addons - + Impersonate any RF24Network/RF24Mesh/RF24Gateway node & scan traffic without disruption to the network */ #include #include -#include +#include #include -//RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ); -RF24 radio(25,0); +RF24 radio(22, 0); RF24Network network(radio); -RF24Mesh mesh(radio,network); -RF24Gateway gw(radio,network,mesh); +RF24Mesh mesh(radio, network); +RF24Gateway gw(radio, network, mesh); uint8_t buffer[1000][32]; int sizes[1000]; int buffCtr = 0; uint32_t mesh_timer = 0; +int main(int argc, char **argv) +{ + radio.begin(); + radio.setAutoAck(0); + // Because AutoAck is disabled, and we are not transmitting any payloads, we will not interfere with the network + // Setup this node as a clone of any network node to scan for all payloads passing to or through that node + gw.begin(); -int main(int argc, char** argv) { + while (1) + { + // Buffer all payloads while the radio has data + while (radio.available()) + { + sizes[buffCtr] = radio.getDynamicPayloadSize(); + radio.read(&buffer[buffCtr][0], sizes[buffCtr]); + ++buffCtr; + } - radio.begin(); - radio.setAutoAck(0); - - // Because AutoAck is disabled, and we are not transmitting any payloads, we will not interfere with the network - // Setup this node as a clone of any network node to scan for all payloads passing to or through that node - gw.begin(); - - - - while(1){ - - // Buffer all payloads while the radio has data - while(radio.available()){ - sizes[buffCtr] = radio.getDynamicPayloadSize(); - radio.read(&buffer[buffCtr][0],sizes[buffCtr]); - ++buffCtr; - } - - // Dissect and print the data - if(buffCtr){ - for(int i=0; i * a: Interface statistics from /proc/net/dev
* b: RF24Mesh address/id assignments
* c: RF24Network/Radio information
* d: Active IP connections (optional)
* -* **Requirements: NCurses** +* **Requirements: NCurses** * Install NCurses: apt-get install libncurses5-dev * * **Controls** @@ -21,7 +19,7 @@ #include #include -#include +#include #include #include @@ -46,507 +44,586 @@ /******************************************************************/ -RF24 radio(22,0); +RF24 radio(22, 0); RF24Network network(radio); -RF24Mesh mesh(radio,network); -RF24Gateway gw(radio,network,mesh); +RF24Mesh mesh(radio, network); +RF24Gateway gw(radio, network, mesh); /******************************************************************/ -WINDOW * win; -WINDOW * meshPad; -WINDOW * connPad; -WINDOW * devPad; -WINDOW * rf24Pad; -WINDOW * cfgPad; -WINDOW * renewPad; - - void drawMain(void); - void drawHelp(void); - void drawCfg(bool isConf); - - void drawDevPad(void); - void drawMeshPad(void); - void drawConnPad(void); - void drawRF24Pad(void); - - int maxX,maxY; - int padSelection = 0; - int meshScroll = 0; - int connScroll = 0; - int rf24Scroll = 0; - unsigned long updateRate = 1000; - - uint32_t meshInfoTimer = 0; - uint32_t mesh_timer = 0; - std::string subIP; - std::string tunStr ("tun_nrf24"); - bool showConnPad; - - size_t bRX; - size_t bTX; - - -/******************************************************************/ -/***********************MAIN***************************************/ - -int main() { - - gw.begin(); - mesh.setStaticAddress(8,1); - - //uint8_t nodeID = 22; - //gw.begin(nodeID,3,RF24_2MBPS); - - //uint16_t address = 0; - //gw.begin(address,3,RF24_2MBPS); - - /** Setup NCurses**/ - /*******************************/ - win = initscr(); - cbreak(); - noecho(); - getmaxyx(win,maxX,maxY); - - start_color(); - curs_set(0); - init_pair(1, COLOR_GREEN, COLOR_BLACK); - init_pair(2, COLOR_RED, COLOR_BLACK); - - /** Setup Pads**/ - /*******************************/ - devPad = newpad(11,40); - meshPad = newpad(50,50); - rf24Pad = newpad(11,40); - connPad = newpad(21,150); - cfgPad = newpad(10,40); - renewPad = newpad(1,35); - - scrollok(meshPad,true); - scrollok(connPad,true); - scrollok(rf24Pad,true); - timeout(0); - - drawMain(); - - - -/******************************************************************/ -/***********************LOOP***************************************/ -bool ok = true; -uint32_t failCounter = 0; - - while(1){ - - /** - * The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface - * RF24Network user payloads are loaded into the user cache - */ - - if(millis()-mesh_timer > 30000 && mesh.getNodeID()){ //Every 30 seconds, test mesh connectivity - mesh_timer = millis(); - if( ! mesh.checkConnection() ){ - wclear(renewPad); - mvwprintw(renewPad,0,0,"*Renewing Address*"); - prefresh(renewPad,0,0, 3,26, 4, 55); - if( (ok = mesh.renewAddress()) ){ - wclear(renewPad); - prefresh(renewPad,0,0, 3,26, 3, 55); +WINDOW *win; +WINDOW *meshPad; +WINDOW *connPad; +WINDOW *devPad; +WINDOW *rf24Pad; +WINDOW *cfgPad; +WINDOW *renewPad; + +void drawMain(void); +void drawHelp(void); +void drawCfg(bool isConf); + +void drawDevPad(void); +void drawMeshPad(void); +void drawConnPad(void); +void drawRF24Pad(void); + +int maxX, maxY; +int padSelection = 0; +int meshScroll = 0; +int connScroll = 0; +int rf24Scroll = 0; +unsigned long updateRate = 1000; + +uint32_t meshInfoTimer = 0; +uint32_t mesh_timer = 0; +std::string subIP; +std::string tunStr("tun_nrf24"); +bool showConnPad; + +size_t bRX; +size_t bTX; + +/******************************************************************/ +/***********************MAIN***************************************/ + +int main() +{ + + gw.begin(); + mesh.setStaticAddress(8, 1); + + //uint8_t nodeID = 22; + //gw.begin(nodeID,3,RF24_2MBPS); + + //uint16_t address = 0; + //gw.begin(address,3,RF24_2MBPS); + + /** Setup NCurses**/ + /*******************************/ + win = initscr(); + cbreak(); + noecho(); + getmaxyx(win, maxX, maxY); + + start_color(); + curs_set(0); + init_pair(1, COLOR_GREEN, COLOR_BLACK); + init_pair(2, COLOR_RED, COLOR_BLACK); + + /** Setup Pads**/ + /*******************************/ + devPad = newpad(11, 40); + meshPad = newpad(50, 50); + rf24Pad = newpad(11, 40); + connPad = newpad(21, 150); + cfgPad = newpad(10, 40); + renewPad = newpad(1, 35); + + scrollok(meshPad, true); + scrollok(connPad, true); + scrollok(rf24Pad, true); + timeout(0); + + drawMain(); + + /******************************************************************/ + /***********************LOOP***************************************/ + bool ok = true; + uint32_t failCounter = 0; + + while (1) + { + + /** + * The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface + * RF24Network user payloads are loaded into the user cache + */ + + if (millis() - mesh_timer > 30000 && mesh.getNodeID()) + { //Every 30 seconds, test mesh connectivity + mesh_timer = millis(); + if (!mesh.checkConnection()) + { + wclear(renewPad); + mvwprintw(renewPad, 0, 0, "*Renewing Address*"); + prefresh(renewPad, 0, 0, 3, 26, 4, 55); + if ((ok = mesh.renewAddress())) + { + wclear(renewPad); + prefresh(renewPad, 0, 0, 3, 26, 3, 55); + } + } + } + if (ok) + { + gw.update(); + + /** Read RF24Network Payloads (Do nothing with them currently) **/ + /*******************************/ + if (network.available()) + { + RF24NetworkHeader header; + size_t size = network.peek(header); + uint8_t buf[size]; + + if (header.type == 1) + { + struct timeStruct + { + uint8_t hr; + uint8_t min; + } myTime; + + time_t mTime; + time(&mTime); + struct tm *tm = localtime(&mTime); + + myTime.hr = tm->tm_hour; + myTime.min = tm->tm_min; + RF24NetworkHeader hdr(header.from_node, 1); + network.write(hdr, &myTime, sizeof(myTime)); + } + network.read(header, &buf, size); + } + } + + /** Mesh address/id printout **/ + /*******************************/ + if (millis() - meshInfoTimer > updateRate) + { + + getmaxyx(win, maxX, maxY); + + // Draw the pads on screen + drawDevPad(); + prefresh(devPad, 0, 0, 4, 1, 14, 25); + + drawMeshPad(); + wscrl(meshPad, meshScroll); + prefresh(meshPad, 0, 0, 4, 26, 14, 47); + + drawRF24Pad(); + prefresh(rf24Pad, 0, 0, 4, 51, 14, 73); + + if (showConnPad) + { + drawConnPad(); + wscrl(connPad, connScroll); + prefresh(connPad, 0, 0, 15, 1, maxX - 1, maxY - 2); + } + } //MeshInfo Timer + + /** Handle keyboard input **/ + /*******************************/ + int myChar = getch(); + + if (myChar > -1) + { + //cout << myChar << endl; + switch (myChar) + { + // a: En/Disable display of active connections + case 'a': + showConnPad = !showConnPad; + if (!showConnPad) + { + wclear(connPad); + prefresh(connPad, 0, 0, 15, 1, maxX - 1, maxY - 2); + drawMain(); + } + break; + // w: Increase frame-rate of curses display + case 'w': + if (updateRate > 100) + { + updateRate -= 100; + } + mvwprintw(win, 2, 27, "Refresh Rate: %.1f fps", 1000.0 / updateRate); + refresh(); + break; + // s: Decrease frame-rate of curses display + case 's': + updateRate += 100; + mvwprintw(win, 2, 27, "Refresh Rate: %.1f fps \t", 1000.0 / updateRate); + refresh(); + break; + // c: Display IP configuration menu + case 'c': + drawCfg(1); + break; + // h: Display help menu + case 'h': + drawHelp(); + break; + case 'x': + clear(); + endwin(); + return 0; + break; + case 'A': + if (padSelection == 0) + { + meshScroll++; + } + else if (padSelection == 1) + { + connScroll++; + } + break; + case 'B': + if (padSelection == 0) + { + meshScroll--; + } + else if (padSelection == 1) + { + connScroll--; + } + break; + case 'C': + padSelection++; + padSelection = std::min(padSelection, 1); + break; //right + case 'D': + padSelection--; + padSelection = std::max(padSelection, 0); + break; //left + meshScroll = std::max(meshScroll, 0); + connScroll = std::max(connScroll, 0); + meshInfoTimer = 0; + } + } + + //This section checks for failures detected by RF24 & RF24Network as well as + //checking for deviations from the default configuration (1MBPS data rate) + //The mesh is restarted on failure and failure count logged to failLog.txt + //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically + if (radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS) + { + radio.failureDetected = 0; + std::ofstream myFile; + myFile.open("failLog.txt"); + if (myFile.is_open()) + { + myFile << ++failCounter << "\n"; + myFile.close(); + } + delay(500); + mesh.begin(); + } + + delay(2); + } //while 1 + + //delwin(meshPad); + //delwin(connPad); + clear(); + endwin(); + return 0; + +} //main + +/******************************************************************/ +/******************Main Drawing Functions**************************/ + +void drawMain() +{ + + clear(); + + attron(COLOR_PAIR(1)); + wprintw(win, "RF24Gateway Ncurses Interface by TMRh20 - 2015\n"); + whline(win, ACS_HLINE, maxY - 2); + attroff(COLOR_PAIR(1)); + refresh(); + /** Display Network Interface Info **/ + /*******************************/ + + //Interface Information + struct ifaddrs *ifap, *ifa; + int family, s, n; + char host[NI_MAXHOST]; + +retryIF: + + getifaddrs(&ifap); + for (ifa = ifap, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) + { + if (tunStr.compare(ifa->ifa_name) != 0 || ifa->ifa_addr == NULL) + { + + if (ifa->ifa_next == NULL) + { + drawCfg(0); + goto retryIF; + } + else + { + continue; + } + } + mvwprintw(win, 2, 0, "%8s ", ifa->ifa_name); + + family = ifa->ifa_addr->sa_family; + + //This is an IP interface, display the IP + if (family == AF_INET || family == AF_INET6) + { + s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (s == 0) + { + wprintw(win, "IP: %s\n", host); + std::string str1 = host; + unsigned found = str1.find_last_of("."); + subIP = str1.substr(0, found); + break; + } } - } - } - if(ok){ - gw.update(); - - /** Read RF24Network Payloads (Do nothing with them currently) **/ - /*******************************/ - if( network.available() ){ - RF24NetworkHeader header; - size_t size = network.peek(header); - uint8_t buf[size]; - - if(header.type == 1){ - struct timeStruct{ - uint8_t hr; - uint8_t min; - }myTime; - - time_t mTime; - time(&mTime); - struct tm* tm = localtime(&mTime); - - myTime.hr = tm->tm_hour; - myTime.min = tm->tm_min; - RF24NetworkHeader hdr(header.from_node,1); - network.write(hdr,&myTime,sizeof(myTime)); - - } - network.read(header,&buf,size); - } - - } - - /** Mesh address/id printout **/ - /*******************************/ - if(millis() - meshInfoTimer > updateRate){ - - getmaxyx(win,maxX,maxY); - - // Draw the pads on screen - drawDevPad(); - prefresh(devPad,0,0, 4,1, 14,25); - - drawMeshPad(); - wscrl(meshPad,meshScroll); - prefresh(meshPad,0,0, 4,26, 14,47); - - drawRF24Pad(); - prefresh(rf24Pad,0,0, 4,51, 14, 73); - - if(showConnPad){ - drawConnPad(); - wscrl(connPad,connScroll); - prefresh(connPad,0,0, 15,1, maxX-1,maxY-2); - } - } //MeshInfo Timer - - - /** Handle keyboard input **/ - /*******************************/ - int myChar = getch(); - - if(myChar > -1){ - //cout << myChar << endl; - switch(myChar){ - // a: En/Disable display of active connections - case 'a' : showConnPad = !showConnPad; if(!showConnPad){ wclear(connPad); prefresh(connPad,0,0, 15,1, maxX-1,maxY-2); drawMain();} break; - // w: Increase frame-rate of curses display - case 'w' : if(updateRate > 100){updateRate-=100;} mvwprintw(win,2,27,"Refresh Rate: %.1f fps",1000.0/updateRate); refresh(); break; - // s: Decrease frame-rate of curses display - case 's' : updateRate+=100; mvwprintw(win,2,27,"Refresh Rate: %.1f fps \t",1000.0/updateRate); refresh(); break; - // c: Display IP configuration menu - case 'c' : drawCfg(1); break; - // h: Display help menu - case 'h' : drawHelp(); break; - case 'x' : clear(); endwin(); return 0; break; - case 'A': if(padSelection == 0){meshScroll++;}else if(padSelection == 1){connScroll++;} break; - case 'B': if(padSelection == 0){meshScroll--;}else if(padSelection == 1){connScroll--;} break; - case 'C': padSelection++; padSelection= std::min(padSelection,1); break; //right - case 'D': padSelection--; padSelection= std::max(padSelection,0); break; //left - meshScroll = std::max(meshScroll,0); - connScroll = std::max(connScroll,0); - meshInfoTimer = 0; - } - - - } - - //This section checks for failures detected by RF24 & RF24Network as well as - //checking for deviations from the default configuration (1MBPS data rate) - //The mesh is restarted on failure and failure count logged to failLog.txt - //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically - if(radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS){ - radio.failureDetected = 0; - std::ofstream myFile; - myFile.open ("failLog.txt"); - if (myFile.is_open()){ - myFile << ++failCounter << "\n"; - myFile.close(); - } - delay(500); - mesh.begin(); } - - delay(2); - }//while 1 - - - //delwin(meshPad); - //delwin(connPad); - clear(); - endwin(); - return 0; - -}//main - - - -/******************************************************************/ -/******************Main Drawing Functions**************************/ - -void drawMain(){ - - clear(); - - attron(COLOR_PAIR(1)); - wprintw(win,"RF24Gateway Ncurses Interface by TMRh20 - 2015\n"); - whline(win,ACS_HLINE, maxY-2); - attroff(COLOR_PAIR(1)); - refresh(); - /** Display Network Interface Info **/ - /*******************************/ - - - - //Interface Information - struct ifaddrs *ifap, *ifa; - int family,s,n; - char host[NI_MAXHOST]; - -retryIF: - - getifaddrs (&ifap); - for (ifa = ifap, n=0; ifa != NULL; ifa = ifa->ifa_next, n++) { - if ( tunStr.compare(ifa->ifa_name) != 0 || ifa->ifa_addr == NULL){ - - if(ifa->ifa_next == NULL ){ - drawCfg(0); - goto retryIF; - }else{ - continue; - } - } - mvwprintw(win,2,0,"%8s ", ifa->ifa_name); - - family = ifa->ifa_addr->sa_family; - - //This is an IP interface, display the IP - if (family == AF_INET || family == AF_INET6) { - s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (s == 0) { - wprintw(win,"IP: %s\n", host); - std::string str1 = host; - unsigned found = str1.find_last_of("."); - subIP = str1.substr(0,found); - break; - } - } - } - - mvwhline(win,15,1,ACS_HLINE, maxY-2); - -refresh(); + mvwhline(win, 15, 1, ACS_HLINE, maxY - 2); + + refresh(); } /******************************************************************/ -void drawHelp(){ - - drawMain(); - - attron(COLOR_PAIR(1)); - mvwprintw(win, 4,1,"**RF24Gateway NCurses Help Menu**"); - wprintw(win," Controls:\n"); - wprintw(win," ARROW_UP/DOWN: Scroll up/down in supported menus\n"); - wprintw(win," ARROW_LEFT/RIGHT: Scroll between supported menus\n"); - wprintw(win," 'c' key: Open IP configuration menu\n"); - wprintw(win," 'w' key: Increase frame-rate of display\n"); - wprintw(win," 's' key: Decrease frame-rate of display\n"); - wprintw(win," 'a' key: Display active IP connections\n"); - wprintw(win," 'h' key: Display this menu\n"); - - timeout(30000); - getch(); - timeout(0); - - drawMain(); - +void drawHelp() +{ + + drawMain(); + + attron(COLOR_PAIR(1)); + mvwprintw(win, 4, 1, "**RF24Gateway NCurses Help Menu**"); + wprintw(win, " Controls:\n"); + wprintw(win, " ARROW_UP/DOWN: Scroll up/down in supported menus\n"); + wprintw(win, " ARROW_LEFT/RIGHT: Scroll between supported menus\n"); + wprintw(win, " 'c' key: Open IP configuration menu\n"); + wprintw(win, " 'w' key: Increase frame-rate of display\n"); + wprintw(win, " 's' key: Decrease frame-rate of display\n"); + wprintw(win, " 'a' key: Display active IP connections\n"); + wprintw(win, " 'h' key: Display this menu\n"); + + timeout(30000); + getch(); + timeout(0); + + drawMain(); } /******************************************************************/ -void drawCfg(bool isConf){ - - if(isConf){drawMain();} - nocbreak(); - echo(); - timeout(30000); - - sleep(1); - wattron(win,COLOR_PAIR(1)); - mvwprintw(win,5,1, isConf ? "IP Configuration\n" : "**Interface Not Configured:**\n"); - wattroff(win,COLOR_PAIR(1)); - mvwprintw(win,6,1,"Enter IP Address: \n"); - refresh(); - - char ip[20],mask[20]; - mvgetstr(6,19,ip); - - mvwprintw(win,7,1,"Enter Subnet Mask: \n"); - refresh(); - - mvgetstr(7,20,mask); - - if(strlen(ip) >= 6 && strlen(mask) >= 7){ - gw.setIP(ip,mask); - }else{ - mvwprintw(win,8,1,"Unable to set IP/Subnet \n"); - refresh(); - sleep(3); - } - - timeout(0); +void drawCfg(bool isConf) +{ + + if (isConf) + { + drawMain(); + } + nocbreak(); + echo(); + timeout(30000); + + sleep(1); + wattron(win, COLOR_PAIR(1)); + mvwprintw(win, 5, 1, isConf ? "IP Configuration\n" : "**Interface Not Configured:**\n"); + wattroff(win, COLOR_PAIR(1)); + mvwprintw(win, 6, 1, "Enter IP Address: \n"); + refresh(); + + char ip[20], mask[20]; + mvgetstr(6, 19, ip); + + mvwprintw(win, 7, 1, "Enter Subnet Mask: \n"); + refresh(); + + mvgetstr(7, 20, mask); + + if (strlen(ip) >= 6 && strlen(mask) >= 7) + { + gw.setIP(ip, mask); + } + else + { + mvwprintw(win, 8, 1, "Unable to set IP/Subnet \n"); + refresh(); + sleep(3); + } + + timeout(0); cbreak(); - noecho(); + noecho(); drawMain(); } +/******************************************************************/ +/******************Curses Pad Functions****************************/ -/******************************************************************/ -/******************Curses Pad Functions****************************/ - -void drawDevPad() { - - - wclear(devPad); - - std::string line; - std::ifstream inFile; - inFile.open("/proc/net/dev"); - while(inFile.good()){ - getline(inFile,line); // get line from file - // search - if(line.find(tunStr) != std::string::npos ) { - - char txBytes[20], txPackets[20], txErrs[20]; - char rxBytes[20], rxPackets[20], rxErrs[20]; - char dummy[20]; - - whline(devPad,ACS_HLINE, 20); - mvwprintw(devPad,0,3," IF Stats: "); - - sscanf(line.c_str(), "%s %s %s %s %s %s %s %s %s %s %s %s", dummy, rxBytes,rxPackets,rxErrs,dummy,dummy,dummy,dummy,dummy, txBytes,txPackets,txErrs); - - mvwprintw(devPad,1,0,"RX Bytes %s\nRX Packets %s\nRX Errs %s\nTX Bytes %s\nTX Packets %s\nTX Errs %s\n",rxBytes,rxPackets,rxErrs,txBytes,txPackets,txErrs); - - float bytesRNow = strtof (rxBytes,NULL) - bRX; - float bytesTNow = strtof (txBytes,NULL) - bTX; - - float RKBS = bytesRNow > 0 ? bytesRNow/updateRate : 0.0 ; - float TKBS = bytesRNow > 0 ? bytesTNow/updateRate : 0.0 ; - - wprintw(devPad,"\nRX %.03f KB/s\n",RKBS); - wprintw(devPad,"TX %.03f KB/s\n",TKBS); - - bRX = strtol (rxBytes,NULL,10); - bTX = strtol (txBytes,NULL,10); - - } - } - inFile.close(); - -} +void drawDevPad() +{ -/******************************************************************/ + wclear(devPad); -void drawMeshPad(){ - - wclear(meshPad); - - meshInfoTimer = millis(); - //uint8_t pos=5; - for(int i=0; i 0 ? bytesRNow / updateRate : 0.0; + float TKBS = bytesRNow > 0 ? bytesTNow / updateRate : 0.0; + + wprintw(devPad, "\nRX %.03f KB/s\n", RKBS); + wprintw(devPad, "TX %.03f KB/s\n", TKBS); + + bRX = strtol(rxBytes, NULL, 10); + bTX = strtol(txBytes, NULL, 10); + } + } + inFile.close(); } /******************************************************************/ -void drawRF24Pad(){ - - wclear(rf24Pad); - mvwprintw(rf24Pad,1,0,"Address: 0%o\n",mesh.mesh_address); - wprintw(rf24Pad,"nodeID: %d\n",mesh.getNodeID()); - wprintw(rf24Pad,"En Mesh: %s\n", gw.meshEnabled() ? "True" : "False"); - int dr = radio.getDataRate(); - wprintw(rf24Pad,"Data-Rate: %s\n", dr == 0 ? "1MBPS" : dr == 1 ? "2MBPS" : dr == 2 ? "250KBPS" : "ERROR" ); - int pa = radio.getPALevel(); - wprintw(rf24Pad,"PA Level: %s\n", pa == 0 ? "MIN" : pa == 1 ? "LOW" : pa == 2 ? "HIGH" : pa == 3 ? "MAX" : "ERROR" ); - wprintw(rf24Pad,"IF Type: %s\n", gw.config_TUN == 1 ? "TUN" : "TAP" ); - wprintw(rf24Pad,"IF Drops: %u\n", gw.ifDropped() ); - #if defined (ENABLE_NETWORK_STATS) - uint32_t ok,fail; - network.failures(&fail,&ok); - wprintw(rf24Pad,"TX Packets: %u\n", ok ); - wprintw(rf24Pad,"TX Drops: %u\n", fail ); - #endif - - if(padSelection == 1){ - wattron(rf24Pad,COLOR_PAIR(1)); - mvwhline(rf24Pad,rf24Scroll,0,ACS_HLINE, maxY); - wattroff(rf24Pad,COLOR_PAIR(1)); - mvwprintw(rf24Pad,rf24Scroll,3," RF24Network Info: "); - }else{ - wattroff(rf24Pad,COLOR_PAIR(1)); - mvwhline(rf24Pad,rf24Scroll,0,ACS_HLINE, maxY); - mvwprintw(rf24Pad,rf24Scroll,3," RF24Network Info: "); - - } +void drawMeshPad() +{ + + wclear(meshPad); + meshInfoTimer = millis(); + //uint8_t pos=5; + for (int i = 0; i < mesh.addrListTop; i++) + { + mvwprintw(meshPad, i + 1, 0, " Address: 0%o ID: %d \n", mesh.addrList[i].address, mesh.addrList[i].nodeID); + } + + if (padSelection == 0) + { + wattron(meshPad, COLOR_PAIR(1)); + mvwhline(meshPad, meshScroll, 0, ACS_HLINE, maxY); + wattroff(meshPad, COLOR_PAIR(1)); + mvwprintw(meshPad, meshScroll, 3, " Mesh Info: "); + } + else + { + wattroff(meshPad, COLOR_PAIR(1)); + mvwhline(meshPad, meshScroll, 0, ACS_HLINE, maxY); + mvwprintw(meshPad, meshScroll, 3, " Mesh Info: "); + } } /******************************************************************/ -void drawConnPad(){ - - int ctr = 2; - size_t lCtr = 1; - std::string line; - wclear(connPad); - //box(connPad,ACS_VLINE,ACS_HLINE); - - - std::ifstream inFile; - inFile.open("/proc/net/nf_conntrack"); - while(inFile.good()){ - getline(inFile,line); // get line from file - // search - if(line.find(subIP) != std::string::npos ) { - - std::string src = "src"; - unsigned fnd = line.find(src); - fnd = line.find_last_of("0123456789",fnd-2); - fnd = line.find_last_of(" ",fnd-2); - unsigned findEnd = line.find(" mark="); - line = line.substr(fnd,findEnd-fnd); - mvwprintw(connPad,ctr++,0,"%d %s\n",lCtr++,line.c_str()); - - if(ctr > maxX-15){ - break; - } - } - } - - inFile.close(); - - if(padSelection == 2){ - wattron(connPad,COLOR_PAIR(1)); - mvwhline(connPad,connScroll,0,ACS_HLINE, maxY); - wattroff(connPad,COLOR_PAIR(1)); - mvwprintw(connPad,connScroll,5," Active IP Connections: "); - }else{ - wattroff(connPad,COLOR_PAIR(1)); - mvwhline(connPad,connScroll,0,ACS_HLINE, maxY); - mvwprintw(connPad,connScroll,5," Active IP Connections: "); - } - +void drawRF24Pad() +{ + + wclear(rf24Pad); + mvwprintw(rf24Pad, 1, 0, "Address: 0%o\n", mesh.mesh_address); + wprintw(rf24Pad, "nodeID: %d\n", mesh.getNodeID()); + wprintw(rf24Pad, "En Mesh: %s\n", gw.meshEnabled() ? "True" : "False"); + int dr = radio.getDataRate(); + wprintw(rf24Pad, "Data-Rate: %s\n", dr == 0 ? "1MBPS" : dr == 1 ? "2MBPS" + : dr == 2 ? "250KBPS" + : "ERROR"); + int pa = radio.getPALevel(); + wprintw(rf24Pad, "PA Level: %s\n", pa == 0 ? "MIN" : pa == 1 ? "LOW" + : pa == 2 ? "HIGH" + : pa == 3 ? "MAX" + : "ERROR"); + wprintw(rf24Pad, "IF Type: %s\n", gw.config_TUN == 1 ? "TUN" : "TAP"); + wprintw(rf24Pad, "IF Drops: %u\n", gw.ifDropped()); +#if defined(ENABLE_NETWORK_STATS) + uint32_t ok, fail; + network.failures(&fail, &ok); + wprintw(rf24Pad, "TX Packets: %u\n", ok); + wprintw(rf24Pad, "TX Drops: %u\n", fail); +#endif + + if (padSelection == 1) + { + wattron(rf24Pad, COLOR_PAIR(1)); + mvwhline(rf24Pad, rf24Scroll, 0, ACS_HLINE, maxY); + wattroff(rf24Pad, COLOR_PAIR(1)); + mvwprintw(rf24Pad, rf24Scroll, 3, " RF24Network Info: "); + } + else + { + wattroff(rf24Pad, COLOR_PAIR(1)); + mvwhline(rf24Pad, rf24Scroll, 0, ACS_HLINE, maxY); + mvwprintw(rf24Pad, rf24Scroll, 3, " RF24Network Info: "); + } } /******************************************************************/ +void drawConnPad() +{ + + int ctr = 2; + size_t lCtr = 1; + std::string line; + wclear(connPad); + //box(connPad,ACS_VLINE,ACS_HLINE); + + std::ifstream inFile; + inFile.open("/proc/net/nf_conntrack"); + while (inFile.good()) + { + getline(inFile, line); // get line from file + // search + if (line.find(subIP) != std::string::npos) + { + + std::string src = "src"; + unsigned fnd = line.find(src); + fnd = line.find_last_of("0123456789", fnd - 2); + fnd = line.find_last_of(" ", fnd - 2); + unsigned findEnd = line.find(" mark="); + line = line.substr(fnd, findEnd - fnd); + mvwprintw(connPad, ctr++, 0, "%d %s\n", lCtr++, line.c_str()); + + if (ctr > maxX - 15) + { + break; + } + } + } + + inFile.close(); + + if (padSelection == 2) + { + wattron(connPad, COLOR_PAIR(1)); + mvwhline(connPad, connScroll, 0, ACS_HLINE, maxY); + wattroff(connPad, COLOR_PAIR(1)); + mvwprintw(connPad, connScroll, 5, " Active IP Connections: "); + } + else + { + wattroff(connPad, COLOR_PAIR(1)); + mvwhline(connPad, connScroll, 0, ACS_HLINE, maxY); + mvwprintw(connPad, connScroll, 5, " Active IP Connections: "); + } +} +/******************************************************************/ diff --git a/examples/ncursesInt/CMakeLists.txt b/examples/ncursesInt/CMakeLists.txt index b27803e..ce2b35b 100644 --- a/examples/ncursesInt/CMakeLists.txt +++ b/examples/ncursesInt/CMakeLists.txt @@ -1,3 +1,7 @@ +# this example needs the ncurses package installed +find_package(Curses REQUIRED) +include_directories(${CURSES_INCLUDE_DIR}) + set(example RF24Gateway_ncursesInt) # make a target @@ -10,4 +14,5 @@ target_link_libraries(${example} PUBLIC ${RF24Network} ${RF24Mesh} ${RF24Gateway} - ) + ${CURSES_LIBRARIES} +) diff --git a/examples/ncursesInt/RF24Gateway_ncursesInt.cpp b/examples/ncursesInt/RF24Gateway_ncursesInt.cpp index a05bcbd..be8b91d 100644 --- a/examples/ncursesInt/RF24Gateway_ncursesInt.cpp +++ b/examples/ncursesInt/RF24Gateway_ncursesInt.cpp @@ -1,16 +1,14 @@ - - /** * RF24Gateway NCurses interface - TMRh20 2015 * This is a generic tool for nodes supporting or combining with RF24Ethernet and/or RF24Network. -* +* * The tool provides a simple interface for monitoring information and activity regarding the RF24Gateway:
* a: Interface statistics from /proc/net/dev
* b: RF24Mesh address/id assignments
* c: RF24Network/Radio information
* d: Active IP connections (optional)
* -* **Requirements: NCurses** +* **Requirements: NCurses** * Install NCurses: apt-get install libncurses5-dev * * **Controls** @@ -21,7 +19,7 @@ #include #include -#include +#include #include #include @@ -46,546 +44,628 @@ /******************************************************************/ //User Configuration -RF24 radio(22,0); +RF24 radio(22, 0); RF24Network network(radio); -RF24Mesh mesh(radio,network); -RF24Gateway gw(radio,network,mesh); +RF24Mesh mesh(radio, network); +RF24Gateway gw(radio, network, mesh); uint8_t nodeID = 0; int interruptPin = 24; /******************************************************************/ -WINDOW * win; -WINDOW * meshPad; -WINDOW * connPad; -WINDOW * devPad; -WINDOW * rf24Pad; -WINDOW * cfgPad; -WINDOW * renewPad; - - void drawMain(void); - void drawHelp(void); - void drawCfg(bool isConf); - - void drawDevPad(void); - void drawMeshPad(void); - void drawConnPad(void); - void drawRF24Pad(void); - - int maxX,maxY; - int padSelection = 0; - int meshScroll = 0; - int connScroll = 0; - int rf24Scroll = 0; - unsigned long updateRate = 1000; - - uint32_t meshInfoTimer = 0; - uint32_t fifoTimer; - uint32_t fifoClears; - uint32_t mesh_timer = 0; - size_t networkPacketsRX = 0; - std::string subIP; - std::string tunStr ("tun_nrf24"); - bool showConnPad; - - size_t bRX; - size_t bTX; - - -/******************************************************************/ -/***********************MAIN***************************************/ -void intHandler(){ +WINDOW *win; +WINDOW *meshPad; +WINDOW *connPad; +WINDOW *devPad; +WINDOW *rf24Pad; +WINDOW *cfgPad; +WINDOW *renewPad; + +void drawMain(void); +void drawHelp(void); +void drawCfg(bool isConf); + +void drawDevPad(void); +void drawMeshPad(void); +void drawConnPad(void); +void drawRF24Pad(void); + +int maxX, maxY; +int padSelection = 0; +int meshScroll = 0; +int connScroll = 0; +int rf24Scroll = 0; +unsigned long updateRate = 1000; + +uint32_t meshInfoTimer = 0; +uint32_t fifoTimer; +uint32_t fifoClears; +uint32_t mesh_timer = 0; +size_t networkPacketsRX = 0; +std::string subIP; +std::string tunStr("tun_nrf24"); +bool showConnPad; + +size_t bRX; +size_t bTX; + +/******************************************************************/ +/***********************MAIN***************************************/ +void intHandler() +{ gw.update(true); } +int main() +{ + + gw.begin(nodeID); + //mesh.setStaticAddress(8,1); + + //uint8_t nodeID = 22; + //gw.begin(nodeID,3,RF24_2MBPS); + + //uint16_t address = 0; + //gw.begin(address,3,RF24_2MBPS); + + /** Setup NCurses**/ + /*******************************/ + win = initscr(); + cbreak(); + noecho(); + getmaxyx(win, maxX, maxY); + + keypad(win, TRUE); + start_color(); + curs_set(0); + init_pair(1, COLOR_GREEN, COLOR_BLACK); + init_pair(2, COLOR_RED, COLOR_BLACK); + + /** Setup Pads**/ + /*******************************/ + devPad = newpad(11, 40); + meshPad = newpad(50, 50); + rf24Pad = newpad(11, 40); + connPad = newpad(21, 150); + cfgPad = newpad(10, 40); + renewPad = newpad(1, 35); + + scrollok(meshPad, true); + scrollok(connPad, true); + scrollok(rf24Pad, true); + timeout(0); + + //MANUAL IP + //char ip[] = "10.10.3.1"; + //char subnet[] = "255.255.255.0"; + //gw.setIP(ip,subnet); + + drawMain(); -int main() { - - gw.begin(nodeID); - //mesh.setStaticAddress(8,1); - - //uint8_t nodeID = 22; - //gw.begin(nodeID,3,RF24_2MBPS); - - //uint16_t address = 0; - //gw.begin(address,3,RF24_2MBPS); - - /** Setup NCurses**/ - /*******************************/ - win = initscr(); - cbreak(); - noecho(); - getmaxyx(win,maxX,maxY); - - keypad(win, TRUE); - start_color(); - curs_set(0); - init_pair(1, COLOR_GREEN, COLOR_BLACK); - init_pair(2, COLOR_RED, COLOR_BLACK); - - /** Setup Pads**/ - /*******************************/ - devPad = newpad(11,40); - meshPad = newpad(50,50); - rf24Pad = newpad(11,40); - connPad = newpad(21,150); - cfgPad = newpad(10,40); - renewPad = newpad(1,35); - - scrollok(meshPad,true); - scrollok(connPad,true); - scrollok(rf24Pad,true); - timeout(0); - - - //MANUAL IP - //char ip[] = "10.10.3.1"; - //char subnet[] = "255.255.255.0"; - //gw.setIP(ip,subnet); - - drawMain(); - - radio.maskIRQ(1,1,0); - attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); - -/******************************************************************/ -/***********************LOOP***************************************/ -bool ok = true; -uint32_t failCounter = 0; - - while(1){ - - - gw.interrupts(0); //Disable interrupts before accessing the radio - - if(millis()-mesh_timer > 30000 && mesh.getNodeID() > 0){ //Every 30 seconds, test mesh connectivity - if( ! mesh.checkConnection() ){ - wclear(renewPad); - mvwprintw(renewPad,0,0,"*Renewing Address*"); - prefresh(renewPad,0,0, 3,26, 4, 55); - if( (ok = mesh.renewAddress()) ){ - wclear(renewPad); - prefresh(renewPad,0,0, 3,26, 4, 55); + radio.maskIRQ(1, 1, 0); + attachInterrupt(interruptPin, INT_EDGE_FALLING, intHandler); + + /******************************************************************/ + /***********************LOOP***************************************/ + bool ok = true; + uint32_t failCounter = 0; + + while (1) + { + + gw.interrupts(0); //Disable interrupts before accessing the radio + + if (millis() - mesh_timer > 30000 && mesh.getNodeID() > 0) + { //Every 30 seconds, test mesh connectivity + if (!mesh.checkConnection()) + { + wclear(renewPad); + mvwprintw(renewPad, 0, 0, "*Renewing Address*"); + prefresh(renewPad, 0, 0, 3, 26, 4, 55); + if ((ok = mesh.renewAddress())) + { + wclear(renewPad); + prefresh(renewPad, 0, 0, 3, 26, 4, 55); + } + } + mesh_timer = millis(); + } + gw.interrupts(); + + if (ok) + { //Non-master nodes need an active connection to the mesh in order to handle data + + /** Read RF24Network Payloads (Do nothing with them currently) **/ + /*******************************/ + gw.interrupts(0); + if (network.available()) + { + ++networkPacketsRX; + RF24NetworkHeader header; + + // un-needed variables + // size_t size = network.peek(header); + // uint8_t buf[size]; + + if (header.type == 1) // header.type is uninitialized + { + struct timeStruct + { + uint8_t hr; + uint8_t min; + } myTime; + + time_t mTime; + time(&mTime); + struct tm *tm = localtime(&mTime); + + myTime.hr = tm->tm_hour; + myTime.min = tm->tm_min; + RF24NetworkHeader hdr(header.from_node, 1); + network.write(hdr, &myTime, sizeof(myTime)); + } + network.read(header, 0, 0); + } + gw.interrupts(); //Re-enable interrupts when done accessing the radio + } + else + { + delay(100); //Big delay if connection to RF24Mesh is failing } - } - mesh_timer = millis(); - } - gw.interrupts(); - - if(ok){ //Non-master nodes need an active connection to the mesh in order to handle data - - - /** Read RF24Network Payloads (Do nothing with them currently) **/ - /*******************************/ - gw.interrupts(0); - if( network.available() ){ - ++networkPacketsRX; - RF24NetworkHeader header; - size_t size = network.peek(header); - uint8_t buf[size]; - - if(header.type == 1){ - struct timeStruct{ - uint8_t hr; - uint8_t min; - }myTime; - - time_t mTime; - time(&mTime); - struct tm* tm = localtime(&mTime); - - myTime.hr = tm->tm_hour; - myTime.min = tm->tm_min; - RF24NetworkHeader hdr(header.from_node,1); - network.write(hdr,&myTime,sizeof(myTime)); - - } - network.read(header,0,0); - } - gw.interrupts(); //Re-enable interrupts when done accessing the radio - - }else{ - delay(100); //Big delay if connection to RF24Mesh is failing - } - - /** - * The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface - * RF24Network user payloads are loaded into the user cache - */ - gw.poll(10); - - /** Mesh address/id printout **/ - /*******************************/ - if(millis() - meshInfoTimer > updateRate){ - - getmaxyx(win,maxX,maxY); - - // Draw the pads on screen - drawDevPad(); - prefresh(devPad,0,0, 4,1, 14,25); - - drawMeshPad(); - wscrl(meshPad,meshScroll); - prefresh(meshPad,0,0, 4,26, 14,47); - - drawRF24Pad(); - prefresh(rf24Pad,0,0, 4,51, 14, 73); - - if(showConnPad){ - drawConnPad(); - wscrl(connPad,connScroll); - prefresh(connPad,0,0, 15,1, maxX-1,maxY-2); - } - } //MeshInfo Timer - - - /** Handle keyboard input **/ - /*******************************/ - int myChar = getch(); - - if(myChar > -1){ - //cout << myChar << endl; - switch(myChar){ - // a: En/Disable display of active connections - case 'a' : showConnPad = !showConnPad; if(!showConnPad){ wclear(connPad); prefresh(connPad,0,0, 15,1, maxX-1,maxY-2); drawMain();} break; - // w: Increase frame-rate of curses display - case 'w' : if(updateRate > 100){updateRate-=100;} mvwprintw(win,2,27,"Refresh Rate: %.1f fps",1000.0/updateRate); refresh(); break; - // s: Decrease frame-rate of curses display - case 's' : updateRate+=100; mvwprintw(win,2,27,"Refresh Rate: %.1f fps \t",1000.0/updateRate); refresh(); break; - // c: Display IP configuration menu - case 'c' : drawCfg(1); break; - // h: Display help menu - case 'h' : drawHelp(); break; - case 'x' : clear(); endwin(); return 0; break; - case KEY_UP: if(padSelection == 0){meshScroll++;}else if(padSelection == 1){connScroll++;} break; - case KEY_DOWN: if(padSelection == 0){meshScroll--;}else if(padSelection == 1){connScroll--;} break; - case KEY_RIGHT: padSelection++; padSelection= std::min(padSelection,1); break; //right - case KEY_LEFT: padSelection--; padSelection= std::max(padSelection,0); break; //left - case 'Q': clear(); endwin(); return 0; break; - meshScroll = std::max(meshScroll,0); - connScroll = std::max(connScroll,0); - meshInfoTimer = 0; - } - - - } - - //This section checks for failures detected by RF24 & RF24Network as well as - //checking for deviations from the default configuration (1MBPS data rate) - //The mesh is restarted on failure and failure count logged to failLog.txt - //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically - gw.interrupts(0); - if(radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS){ - - std::ofstream myFile; - myFile.open ("failLog.txt"); - if (myFile.is_open()){ - myFile << ++failCounter << "\n"; - } - myFile.close(); - mesh.begin(); - delay(1000); - radio.failureDetected = 0; - } - gw.interrupts(1); - - }//while 1 + /** + * The gateway handles all IP traffic (marked as EXTERNAL_DATA_TYPE) and passes it to the associated network interface + * RF24Network user payloads are loaded into the user cache + */ + gw.poll(10); + + /** Mesh address/id printout **/ + /*******************************/ + if (millis() - meshInfoTimer > updateRate) + { + + getmaxyx(win, maxX, maxY); + + // Draw the pads on screen + drawDevPad(); + prefresh(devPad, 0, 0, 4, 1, 14, 25); + + drawMeshPad(); + wscrl(meshPad, meshScroll); + prefresh(meshPad, 0, 0, 4, 26, 14, 47); + + drawRF24Pad(); + prefresh(rf24Pad, 0, 0, 4, 51, 14, 73); + + if (showConnPad) + { + drawConnPad(); + wscrl(connPad, connScroll); + prefresh(connPad, 0, 0, 15, 1, maxX - 1, maxY - 2); + } + } //MeshInfo Timer + + /** Handle keyboard input **/ + /*******************************/ + int myChar = getch(); + + if (myChar > -1) + { + //cout << myChar << endl; + switch (myChar) + { + // a: En/Disable display of active connections + case 'a': + showConnPad = !showConnPad; + if (!showConnPad) + { + wclear(connPad); + prefresh(connPad, 0, 0, 15, 1, maxX - 1, maxY - 2); + drawMain(); + } + break; + // w: Increase frame-rate of curses display + case 'w': + if (updateRate > 100) + { + updateRate -= 100; + } + mvwprintw(win, 2, 27, "Refresh Rate: %.1f fps", 1000.0 / updateRate); + refresh(); + break; + // s: Decrease frame-rate of curses display + case 's': + updateRate += 100; + mvwprintw(win, 2, 27, "Refresh Rate: %.1f fps \t", 1000.0 / updateRate); + refresh(); + break; + // c: Display IP configuration menu + case 'c': + drawCfg(1); + break; + // h: Display help menu + case 'h': + drawHelp(); + break; + case 'x': + clear(); + endwin(); + return 0; + break; + case KEY_UP: + if (padSelection == 0) + { + meshScroll++; + } + else if (padSelection == 1) + { + connScroll++; + } + break; + case KEY_DOWN: + if (padSelection == 0) + { + meshScroll--; + } + else if (padSelection == 1) + { + connScroll--; + } + break; + case KEY_RIGHT: + padSelection++; + padSelection = std::min(padSelection, 1); + break; //right + case KEY_LEFT: + padSelection--; + padSelection = std::max(padSelection, 0); + break; //left + case 'Q': + clear(); + endwin(); + return 0; + break; + meshScroll = std::max(meshScroll, 0); + connScroll = std::max(connScroll, 0); + meshInfoTimer = 0; + } + } - //delwin(meshPad); - //delwin(connPad); - clear(); - endwin(); - return 0; - -}//main + //This section checks for failures detected by RF24 & RF24Network as well as + //checking for deviations from the default configuration (1MBPS data rate) + //The mesh is restarted on failure and failure count logged to failLog.txt + //This makes the radios hot-swappable, disconnect & reconnect as desired, it should come up automatically + gw.interrupts(0); + if (radio.failureDetected > 0 || radio.getDataRate() != RF24_1MBPS) + { + + std::ofstream myFile; + myFile.open("failLog.txt"); + if (myFile.is_open()) + { + myFile << ++failCounter << "\n"; + } + myFile.close(); + mesh.begin(); + delay(1000); + radio.failureDetected = 0; + } + gw.interrupts(1); + } //while 1 + //delwin(meshPad); + //delwin(connPad); + clear(); + endwin(); + return 0; -/******************************************************************/ -/******************Main Drawing Functions**************************/ +} //main -void drawMain(){ +/******************************************************************/ +/******************Main Drawing Functions**************************/ - clear(); +void drawMain() +{ - attron(COLOR_PAIR(1)); - wprintw(win,"RF24Gateway Ncurses Interface by TMRh20 - 2015\n"); - whline(win,ACS_HLINE, maxY-2); - attroff(COLOR_PAIR(1)); - refresh(); - /** Display Network Interface Info **/ - /*******************************/ + clear(); + attron(COLOR_PAIR(1)); + wprintw(win, "RF24Gateway Ncurses Interface by TMRh20 - 2015\n"); + whline(win, ACS_HLINE, maxY - 2); + attroff(COLOR_PAIR(1)); + refresh(); + /** Display Network Interface Info **/ + /*******************************/ - - //Interface Information - struct ifaddrs *ifap, *ifa; - int family,s,n; - char host[NI_MAXHOST]; + //Interface Information + struct ifaddrs *ifap, *ifa; + int family, s, n; + char host[NI_MAXHOST]; -retryIF: - - getifaddrs (&ifap); - for (ifa = ifap, n=0; ifa != NULL; ifa = ifa->ifa_next, n++) { - if ( tunStr.compare(ifa->ifa_name) != 0 || ifa->ifa_addr == NULL){ - - if(ifa->ifa_next == NULL ){ +retryIF: + + getifaddrs(&ifap); + for (ifa = ifap, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) + { + if (tunStr.compare(ifa->ifa_name) != 0 || ifa->ifa_addr == NULL) + { + + if (ifa->ifa_next == NULL) + { drawCfg(0); - goto retryIF; - }else{ - continue; - } - } - mvwprintw(win,2,0,"%8s ", ifa->ifa_name); - - family = ifa->ifa_addr->sa_family; - - //This is an IP interface, display the IP - if (family == AF_INET || family == AF_INET6) { - s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); - if (s == 0) { - wprintw(win,"IP: %s\n", host); - std::string str1 = host; - unsigned found = str1.find_last_of("."); - subIP = str1.substr(0,found); - break; - } - } - } - - mvwhline(win,15,1,ACS_HLINE, maxY-2); - -refresh(); + goto retryIF; + } + else + { + continue; + } + } + mvwprintw(win, 2, 0, "%8s ", ifa->ifa_name); + + family = ifa->ifa_addr->sa_family; + + //This is an IP interface, display the IP + if (family == AF_INET || family == AF_INET6) + { + s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (s == 0) + { + wprintw(win, "IP: %s\n", host); + std::string str1 = host; + unsigned found = str1.find_last_of("."); + subIP = str1.substr(0, found); + break; + } + } + } + mvwhline(win, 15, 1, ACS_HLINE, maxY - 2); + + refresh(); } /******************************************************************/ -void drawHelp(){ - - drawMain(); - - attron(COLOR_PAIR(1)); - mvwprintw(win, 4,1,"**RF24Gateway NCurses Help Menu**"); - wprintw(win," Controls:\n"); - wprintw(win," ARROW_UP/DOWN: Scroll up/down in supported menus\n"); - wprintw(win," ARROW_LEFT/RIGHT: Scroll between supported menus\n"); - wprintw(win," 'c' key: Open IP configuration menu\n"); - wprintw(win," 'w' key: Increase frame-rate of display\n"); - wprintw(win," 's' key: Decrease frame-rate of display\n"); - wprintw(win," 'a' key: Display active IP connections\n"); - wprintw(win," 'h' key: Display this menu\n"); - - timeout(30000); - getch(); - timeout(0); - - drawMain(); - +void drawHelp() +{ + + drawMain(); + + attron(COLOR_PAIR(1)); + mvwprintw(win, 4, 1, "**RF24Gateway NCurses Help Menu**"); + wprintw(win, " Controls:\n"); + wprintw(win, " ARROW_UP/DOWN: Scroll up/down in supported menus\n"); + wprintw(win, " ARROW_LEFT/RIGHT: Scroll between supported menus\n"); + wprintw(win, " 'c' key: Open IP configuration menu\n"); + wprintw(win, " 'w' key: Increase frame-rate of display\n"); + wprintw(win, " 's' key: Decrease frame-rate of display\n"); + wprintw(win, " 'a' key: Display active IP connections\n"); + wprintw(win, " 'h' key: Display this menu\n"); + + timeout(30000); + getch(); + timeout(0); + + drawMain(); } /******************************************************************/ -void drawCfg(bool isConf){ - - if(isConf){drawMain();} - nocbreak(); - echo(); - timeout(30000); - - sleep(1); - wattron(win,COLOR_PAIR(1)); - mvwprintw(win,5,1, isConf ? "IP Configuration\n" : "**Interface Not Configured:**\n"); - wattroff(win,COLOR_PAIR(1)); - mvwprintw(win,6,1,"Enter IP Address: \n"); - refresh(); - - char ip[20],mask[20]; - mvgetstr(6,19,ip); - - mvwprintw(win,7,1,"Enter Subnet Mask: \n"); - refresh(); - - mvgetstr(7,20,mask); - - if(strlen(ip) >= 6 && strlen(mask) >= 7){ - gw.setIP(ip,mask); - }else{ - mvwprintw(win,8,1,"Unable to set IP/Subnet \n"); - refresh(); - sleep(3); - } - - timeout(0); +void drawCfg(bool isConf) +{ + + if (isConf) + { + drawMain(); + } + nocbreak(); + echo(); + timeout(30000); + + sleep(1); + wattron(win, COLOR_PAIR(1)); + mvwprintw(win, 5, 1, isConf ? "IP Configuration\n" : "**Interface Not Configured:**\n"); + wattroff(win, COLOR_PAIR(1)); + mvwprintw(win, 6, 1, "Enter IP Address: \n"); + refresh(); + + char ip[20], mask[20]; + mvgetstr(6, 19, ip); + + mvwprintw(win, 7, 1, "Enter Subnet Mask: \n"); + refresh(); + + mvgetstr(7, 20, mask); + + if (strlen(ip) >= 6 && strlen(mask) >= 7) + { + gw.setIP(ip, mask); + } + else + { + mvwprintw(win, 8, 1, "Unable to set IP/Subnet \n"); + refresh(); + sleep(3); + } + + timeout(0); cbreak(); - noecho(); + noecho(); drawMain(); } +/******************************************************************/ +/******************Curses Pad Functions****************************/ -/******************************************************************/ -/******************Curses Pad Functions****************************/ - -void drawDevPad() { - - - wclear(devPad); - - std::string line; - std::ifstream inFile; - inFile.open("/proc/net/dev"); - while(inFile.good()){ - getline(inFile,line); // get line from file - // search - if(line.find(tunStr) != std::string::npos ) { - - char txBytes[20], txPackets[20], txErrs[20]; - char rxBytes[20], rxPackets[20], rxErrs[20]; - char dummy[20]; - - whline(devPad,ACS_HLINE, 20); - mvwprintw(devPad,0,3," IF Stats: "); - - sscanf(line.c_str(), "%s %s %s %s %s %s %s %s %s %s %s %s", dummy, rxBytes,rxPackets,rxErrs,dummy,dummy,dummy,dummy,dummy, txBytes,txPackets,txErrs); - - mvwprintw(devPad,1,0,"RX Bytes %s\nRX Packets %s\nRX Errs %s\nTX Bytes %s\nTX Packets %s\nTX Errs %s\n",rxBytes,rxPackets,rxErrs,txBytes,txPackets,txErrs); - - float bytesRNow = strtof (rxBytes,NULL) - bRX; - float bytesTNow = strtof (txBytes,NULL) - bTX; - - float RKBS = bytesRNow > 0 ? bytesRNow/updateRate : 0.0 ; - float TKBS = bytesRNow > 0 ? bytesTNow/updateRate : 0.0 ; - - wprintw(devPad,"\nRX %.03f KB/s\n",RKBS); - wprintw(devPad,"TX %.03f KB/s\n",TKBS); - - bRX = strtol (rxBytes,NULL,10); - bTX = strtol (txBytes,NULL,10); - - } - } - inFile.close(); - -} +void drawDevPad() +{ -/******************************************************************/ + wclear(devPad); + + std::string line; + std::ifstream inFile; + inFile.open("/proc/net/dev"); + while (inFile.good()) + { + getline(inFile, line); // get line from file + // search + if (line.find(tunStr) != std::string::npos) + { + + char txBytes[20], txPackets[20], txErrs[20]; + char rxBytes[20], rxPackets[20], rxErrs[20]; + char dummy[20]; -void drawMeshPad(){ - - wclear(meshPad); - - meshInfoTimer = millis(); - //uint8_t pos=5; - for(int i=0; i 0 ? bytesRNow / updateRate : 0.0; + float TKBS = bytesRNow > 0 ? bytesTNow / updateRate : 0.0; + + wprintw(devPad, "\nRX %.03f KB/s\n", RKBS); + wprintw(devPad, "TX %.03f KB/s\n", TKBS); + + bRX = strtol(rxBytes, NULL, 10); + bTX = strtol(txBytes, NULL, 10); + } + } + inFile.close(); } /******************************************************************/ -void drawRF24Pad(){ - - wclear(rf24Pad); - mvwprintw(rf24Pad,1,0,"Address: 0%o\n",mesh.mesh_address); - wprintw(rf24Pad,"nodeID: %d\n",mesh.getNodeID()); - wprintw(rf24Pad,"En Mesh: %s\n", gw.meshEnabled() ? "True" : "False"); - radio.maskIRQ(1,1,1); - int dr = radio.getDataRate(); - int pa = radio.getPALevel(); - radio.maskIRQ(1,1,0); - wprintw(rf24Pad,"Data-Rate: %s\n", dr == 0 ? "1MBPS" : dr == 1 ? "2MBPS" : dr == 2 ? "250KBPS" : "ERROR" ); - wprintw(rf24Pad,"PA Level: %s\n", pa == 0 ? "MIN" : pa == 1 ? "LOW" : pa == 2 ? "HIGH" : pa == 3 ? "MAX" : "ERROR" ); - wprintw(rf24Pad,"IF Type: %s\n", gw.config_TUN == 1 ? "TUN" : "TAP" ); - wprintw(rf24Pad,"IF Drops: %u\n", gw.ifDropped() ); - #if defined (ENABLE_NETWORK_STATS) - uint32_t ok,fail; - network.failures(&fail,&ok); - wprintw(rf24Pad,"TX Packets(sys): %u\n", ok ); - wprintw(rf24Pad,"TX Drops: %u\n", fail ); - #endif - wprintw(rf24Pad,"RX Packets(user): %u\n",networkPacketsRX); - if(gw.fifoCleared){ - ++fifoClears; - gw.fifoCleared=false; - } - wprintw(rf24Pad,"Interrupt Errors: %u",fifoClears); - - if(padSelection == 1){ - wattron(rf24Pad,COLOR_PAIR(1)); - mvwhline(rf24Pad,rf24Scroll,0,ACS_HLINE, maxY); - wattroff(rf24Pad,COLOR_PAIR(1)); - mvwprintw(rf24Pad,rf24Scroll,3," RF24Network Info: "); - }else{ - wattroff(rf24Pad,COLOR_PAIR(1)); - mvwhline(rf24Pad,rf24Scroll,0,ACS_HLINE, maxY); - mvwprintw(rf24Pad,rf24Scroll,3," RF24Network Info: "); - - } +void drawMeshPad() +{ + wclear(meshPad); + + meshInfoTimer = millis(); + //uint8_t pos=5; + for (int i = 0; i < mesh.addrListTop; i++) + { + mvwprintw(meshPad, i + 1, 0, " Address: 0%o ID: %d \n", mesh.addrList[i].address, mesh.addrList[i].nodeID); + } + + if (padSelection == 0) + { + wattron(meshPad, COLOR_PAIR(1)); + mvwhline(meshPad, meshScroll, 0, ACS_HLINE, maxY); + wattroff(meshPad, COLOR_PAIR(1)); + mvwprintw(meshPad, meshScroll, 3, " Mesh Info: "); + } + else + { + wattroff(meshPad, COLOR_PAIR(1)); + mvwhline(meshPad, meshScroll, 0, ACS_HLINE, maxY); + mvwprintw(meshPad, meshScroll, 3, " Mesh Info: "); + } } /******************************************************************/ -void drawConnPad(){ - - int ctr = 2; - size_t lCtr = 1; - std::string line; - wclear(connPad); - //box(connPad,ACS_VLINE,ACS_HLINE); - - - std::ifstream inFile; - inFile.open("/proc/net/nf_conntrack"); - while(inFile.good()){ - getline(inFile,line); // get line from file - // search - if(line.find(subIP) != std::string::npos ) { - - std::string src = "src"; - unsigned fnd = line.find(src); - fnd = line.find_last_of("0123456789",fnd-2); - fnd = line.find_last_of(" ",fnd-2); - unsigned findEnd = line.find(" mark="); - line = line.substr(fnd,findEnd-fnd); - mvwprintw(connPad,ctr++,0,"%d %s\n",lCtr++,line.c_str()); - - if(ctr > maxX-15){ - break; - } - } - } - - inFile.close(); - - if(padSelection == 2){ - wattron(connPad,COLOR_PAIR(1)); - mvwhline(connPad,connScroll,0,ACS_HLINE, maxY); - wattroff(connPad,COLOR_PAIR(1)); - mvwprintw(connPad,connScroll,5," Active IP Connections: "); - }else{ - wattroff(connPad,COLOR_PAIR(1)); - mvwhline(connPad,connScroll,0,ACS_HLINE, maxY); - mvwprintw(connPad,connScroll,5," Active IP Connections: "); - } - +void drawRF24Pad() +{ + + wclear(rf24Pad); + mvwprintw(rf24Pad, 1, 0, "Address: 0%o\n", mesh.mesh_address); + wprintw(rf24Pad, "nodeID: %d\n", mesh.getNodeID()); + wprintw(rf24Pad, "En Mesh: %s\n", gw.meshEnabled() ? "True" : "False"); + radio.maskIRQ(1, 1, 1); + int dr = radio.getDataRate(); + int pa = radio.getPALevel(); + radio.maskIRQ(1, 1, 0); + wprintw(rf24Pad, "Data-Rate: %s\n", dr == 0 ? "1MBPS" : dr == 1 ? "2MBPS" : dr == 2 ? "250KBPS" : "ERROR"); + wprintw(rf24Pad, "PA Level: %s\n", pa == 0 ? "MIN" : pa == 1 ? "LOW" : pa == 2 ? "HIGH" : pa == 3 ? "MAX" : "ERROR"); + wprintw(rf24Pad, "IF Type: %s\n", gw.config_TUN == 1 ? "TUN" : "TAP"); + wprintw(rf24Pad, "IF Drops: %u\n", gw.ifDropped()); +#if defined(ENABLE_NETWORK_STATS) + uint32_t ok, fail; + network.failures(&fail, &ok); + wprintw(rf24Pad, "TX Packets(sys): %u\n", ok); + wprintw(rf24Pad, "TX Drops: %u\n", fail); +#endif + wprintw(rf24Pad, "RX Packets(user): %u\n", networkPacketsRX); + if (gw.fifoCleared) + { + ++fifoClears; + gw.fifoCleared = false; + } + wprintw(rf24Pad, "Interrupt Errors: %u", fifoClears); + + if (padSelection == 1) + { + wattron(rf24Pad, COLOR_PAIR(1)); + mvwhline(rf24Pad, rf24Scroll, 0, ACS_HLINE, maxY); + wattroff(rf24Pad, COLOR_PAIR(1)); + mvwprintw(rf24Pad, rf24Scroll, 3, " RF24Network Info: "); + } + else + { + wattroff(rf24Pad, COLOR_PAIR(1)); + mvwhline(rf24Pad, rf24Scroll, 0, ACS_HLINE, maxY); + mvwprintw(rf24Pad, rf24Scroll, 3, " RF24Network Info: "); + } } /******************************************************************/ +void drawConnPad() +{ + + int ctr = 2; + size_t lCtr = 1; + std::string line; + wclear(connPad); + //box(connPad,ACS_VLINE,ACS_HLINE); + + std::ifstream inFile; + inFile.open("/proc/net/nf_conntrack"); + while (inFile.good()) + { + getline(inFile, line); // get line from file + // search + if (line.find(subIP) != std::string::npos) + { + + std::string src = "src"; + unsigned fnd = line.find(src); + fnd = line.find_last_of("0123456789", fnd - 2); + fnd = line.find_last_of(" ", fnd - 2); + unsigned findEnd = line.find(" mark="); + line = line.substr(fnd, findEnd - fnd); + mvwprintw(connPad, ctr++, 0, "%d %s\n", lCtr++, line.c_str()); + + if (ctr > maxX - 15) + { + break; + } + } + } + + inFile.close(); + + if (padSelection == 2) + { + wattron(connPad, COLOR_PAIR(1)); + mvwhline(connPad, connScroll, 0, ACS_HLINE, maxY); + wattroff(connPad, COLOR_PAIR(1)); + mvwprintw(connPad, connScroll, 5, " Active IP Connections: "); + } + else + { + wattroff(connPad, COLOR_PAIR(1)); + mvwhline(connPad, connScroll, 0, ACS_HLINE, maxY); + mvwprintw(connPad, connScroll, 5, " Active IP Connections: "); + } +} +/******************************************************************/ From 2b56b88fc1529fef614700a24aac201beaef107b Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 05:02:48 -0700 Subject: [PATCH 14/24] rename READMEs in uppercase --- READM.md => README.md | 0 docs/{READM.md => README.md} | 0 examples/{READM.txt => README.txt} | 0 examples/addons/{READM.md => README.md} | 0 examples/clients/BashClient/{READM.md => README.md} | 0 examples/clients/NodeJSClient/{READM.md => README.md} | 0 examples/clients/PythonClient/{READM.md => README.md} | 0 examples/clients/{READM.md => README.md} | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename READM.md => README.md (100%) rename docs/{READM.md => README.md} (100%) rename examples/{READM.txt => README.txt} (100%) rename examples/addons/{READM.md => README.md} (100%) rename examples/clients/BashClient/{READM.md => README.md} (100%) rename examples/clients/NodeJSClient/{READM.md => README.md} (100%) rename examples/clients/PythonClient/{READM.md => README.md} (100%) rename examples/clients/{READM.md => README.md} (100%) diff --git a/READM.md b/README.md similarity index 100% rename from READM.md rename to README.md diff --git a/docs/READM.md b/docs/README.md similarity index 100% rename from docs/READM.md rename to docs/README.md diff --git a/examples/READM.txt b/examples/README.txt similarity index 100% rename from examples/READM.txt rename to examples/README.txt diff --git a/examples/addons/READM.md b/examples/addons/README.md similarity index 100% rename from examples/addons/READM.md rename to examples/addons/README.md diff --git a/examples/clients/BashClient/READM.md b/examples/clients/BashClient/README.md similarity index 100% rename from examples/clients/BashClient/READM.md rename to examples/clients/BashClient/README.md diff --git a/examples/clients/NodeJSClient/READM.md b/examples/clients/NodeJSClient/README.md similarity index 100% rename from examples/clients/NodeJSClient/READM.md rename to examples/clients/NodeJSClient/README.md diff --git a/examples/clients/PythonClient/READM.md b/examples/clients/PythonClient/README.md similarity index 100% rename from examples/clients/PythonClient/READM.md rename to examples/clients/PythonClient/README.md diff --git a/examples/clients/READM.md b/examples/clients/README.md similarity index 100% rename from examples/clients/READM.md rename to examples/clients/README.md From d0d12d7edd1b4b18fd2efd2ca3fa1368864ef88a Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 05:04:17 -0700 Subject: [PATCH 15/24] [cmake] remove old STRIP cmds --- cmake/GetLibInfo.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmake/GetLibInfo.cmake b/cmake/GetLibInfo.cmake index 6a58fc6..2d1c602 100644 --- a/cmake/GetLibInfo.cmake +++ b/cmake/GetLibInfo.cmake @@ -10,11 +10,9 @@ endif() # use URL to get repo owner as Contact/Maintainer name string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/(.+)\/.+$" "\\1" CPACK_PACKAGE_CONTACT "${CMAKE_PROJECT_HOMEPAGE_URL}") -# string(STRIP "${CPACK_PACKAGE_CONTACT}" CPACK_PACKAGE_CONTACT) # use URL to get the repo name as the Lib Name. Note that we don't use the folder name for this string(REGEX REPLACE "^http[s]?:\/\/github\\.com\/.+\/(.+)$" "\\1" LibName "${CMAKE_PROJECT_HOMEPAGE_URL}") -# string(STRIP "${LibName}" LibName) # convert the LibName to lower case string(TOLOWER ${LibName} LibTargetName) From 43090081954226875f17e1dcf9dc603ab22fc3d1 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 05:13:17 -0700 Subject: [PATCH 16/24] clean up linux CI workflow --- .github/workflows/build_linux.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index c2b8aaa..d922ae8 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -48,9 +48,6 @@ jobs: usr_dir: "local" steps: - - name: install rpmbuild - run: sudo apt-get install rpm - # - name: provide toolchain (for x86_64) # if: ${{ matrix.toolchain.compiler == 'x86_64' }} # run: | @@ -129,12 +126,6 @@ jobs: run: cmake -E make_directory ${{ github.workspace }}/build - name: configure lib - if: ${{ matrix.toolchain.compiler == 'default' }} - working-directory: ${{ github.workspace }}/build - run: cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE - - - name: configure lib (with toolchain compilers) - if: ${{ matrix.toolchain.compiler != 'default' }} working-directory: ${{ github.workspace }}/build run: | cmake .. -D CMAKE_BUILD_TYPE=$BUILD_TYPE \ @@ -178,8 +169,8 @@ jobs: cmake ../examples \ -D CMAKE_TOOLCHAIN_FILE=../cmake/toolchains/${{ matrix.toolchain.compiler }}.cmake - - name: build examples (none that use ncurses) + - name: build examples working-directory: ${{ github.workspace }}/build run: | - cmake --build . --target RF24GatewayNode --target Sniffer --target RF24GatewayNodeInt + cmake --build . file ./RF24GatewayNode From 26960fbab2f45a60762f19a6405a023fe4f14d69 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 05:17:08 -0700 Subject: [PATCH 17/24] [no ci] add a comment --- .github/workflows/build_linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index d922ae8..cbe77dd 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -45,7 +45,7 @@ jobs: # - compiler: "i686" # usr_dir: "i686-linux-gnu" - compiler: "default" # github runner is hosted on a "amd64" - usr_dir: "local" + usr_dir: "local" # use default compiler to test build all examples (including the ncurses ones) steps: # - name: provide toolchain (for x86_64) From a76581d5d2b780a7b9d699b3b66e8d4075897652 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 14:49:11 -0700 Subject: [PATCH 18/24] Update CONTRIBUTING.md --- CONTRIBUTING.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a08eba..9f99c0f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -These are the current requirements for getting your code included in RF24: +These are the current requirements for getting your code included in RF24Gateway: * Try your best to follow the rest of the code, if you're unsure then the NASA C style can help as it's closest to the current style: https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19950022400.pdf @@ -7,3 +7,8 @@ These are the current requirements for getting your code included in RF24: * Follow the [Arduino IDE formatting style](https://www.arduino.cc/en/Reference/StyleGuide) for Arduino examples * Add [doxygen-compatible documentation](https://www.doxygen.nl/manual/docblocks.html) to any new functions you add, or update existing documentation if you change behaviour + +* CMake modules and CMakeLists.txt files should also have a uniform syntax. + - Indentation is a mandatory 4 spaces (not a `\t` character). + - Closing parenthesis for multi-line commands should have the same indentation as the line that opened the parenthesis. + - For other useful CMake syntax convention, please see [CMake docs for developers](https://cmake.org/cmake/help/v3.20/manual/cmake-developer.7.html) and [this useful best CMake practices article](https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1). The qiBuild project has some [well-reasoned "Dos & Don'ts" guideline](http://doc.aldebaran.com/qibuild/hacking/contrib/cmake/coding_guide.html), but beware that the nRF24 organization is not related to the qiBuild project in any way. From b3cb6267bf64cd94314fecf75bc299d74f50cfe4 Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 15:13:31 -0700 Subject: [PATCH 19/24] manually trigger CI workflows --- .github/workflows/build_linux.yml | 28 ++++++++++++++-------------- .github/workflows/doxygen.yml | 30 ++++++++++++++---------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index cbe77dd..e75a5dd 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -4,22 +4,22 @@ on: pull_request: types: [opened, reopened] paths: - - '*.h' - - '*.cpp' - - 'CMakeLists.txt' - - 'cmake/**' - - 'examples/**.cpp' - - '!**Makefile' # old build system is not tested in this workflow - - '.github/workflows/build_linux.yml' + - "*.h" + - "*.cpp" + - "CMakeLists.txt" + - "cmake/**" + - "examples/**.cpp" + - "!**Makefile" # old build system is not tested in this workflow + - ".github/workflows/build_linux.yml" push: paths: - - '*.h' - - '*.cpp' - - 'CMakeLists.txt' - - 'cmake/**' - - 'examples/**.cpp' - - '!**Makefile' # old build system is not tested in this workflow - - '.github/workflows/build_linux.yml' + - "*.h" + - "*.cpp" + - "CMakeLists.txt" + - "cmake/**" + - "examples/**.cpp" + - "!**Makefile" # old build system is not tested in this workflow + - ".github/workflows/build_linux.yml" release: types: [published, edited] diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 37a8b09..c73ac2b 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -2,25 +2,23 @@ name: DoxyGen build on: pull_request: - branches: [master] paths: - - '*.h' - - '*.md' - - 'docs/**' - - '!**README.md' - - 'examples**.cpp' - - '.github/workflows/doxygen.yml' - - 'Doxyfile' + - "*.h" + - "*.md" + - "docs/**" + - "!**README.md" + - "examples**.cpp" + - ".github/workflows/doxygen.yml" + - "Doxyfile" push: - branches: [master] paths: - - '*.h' - - '*.md' - - 'docs/**' - - '!**README.md' - - 'examples**.cpp' - - '.github/workflows/doxygen.yml' - - 'Doxyfile' + - "*.h" + - "*.md" + - "docs/**" + - "!**README.md" + - "examples**.cpp" + - ".github/workflows/doxygen.yml" + - "Doxyfile" release: branches: [master] types: [published, edited] From 461cb2cabb1ee9351b78de55f8f3927aa52608ed Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 12 Jun 2021 16:33:11 -0700 Subject: [PATCH 20/24] gimme that badge --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e93d102..fab59df 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Linux build](https://github.com/nRF24/RF24Gateway/actions/workflows/build_linux.yml/badge.svg)](https://github.com/nRF24/RF24Gateway/actions/workflows/build_linux.yml) + ## RF24Gateway A complimentary library to RF24Ethernet, for RPi/Linux devices. @@ -12,4 +14,4 @@ http://nRF24.github.io/RF24Gateway http://nRF24.github.io/RF24Ethernet -All: http://tmrh20.github.io \ No newline at end of file +All: http://tmrh20.github.io From 501d9eab059d3df8c439f0eb5a1a42ce01c3b34e Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 18 Jun 2021 15:15:00 -0700 Subject: [PATCH 21/24] use CMake CLI to change debugging level --- CMakeLists.txt | 9 +++++++++ RF24Gateway.cpp | 32 ++++++++++++++++---------------- RF24Gateway.h | 4 +++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ce4426..63449e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,9 @@ add_library(project_options INTERFACE) target_compile_features(project_options INTERFACE cxx_std_17) add_compile_options(-Ofast -Wall) +# allow using CMake options to adjust RF24Network_config.h without modiying source code +option(DEBUG_LEVEL "adjust the verbosity of the debugging messages" 0) + # detect CPU and add compiler flags accordingly include(cmake/detectCPU.cmake) @@ -66,6 +69,12 @@ set_target_properties( VERSION ${${LibName}_VERSION_STRING} ) +# assert the appropriate preprocessor macros for RF24Network_config.h +if(DEBUG_LEVEL GREATER 0) + message(STATUS "DEBUG_LEVEL set to ${DEBUG_LEVEL}") + target_compile_definitions(${LibTargetName} PUBLIC DEBUG_LEVEL=${DEBUG_LEVEL}) +endif() + ########################### # target install rules for the RF24Log lib ########################### diff --git a/RF24Gateway.cpp b/RF24Gateway.cpp index 46a87d6..86bba72 100644 --- a/RF24Gateway.cpp +++ b/RF24Gateway.cpp @@ -34,7 +34,7 @@ void RF24Gateway::begin(uint16_t address, uint8_t _channel, rf24_datarate_e data bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8_t mesh_nodeID, rf24_datarate_e data_rate, uint8_t _channel) { - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) printf("GW Begin\n"); printf("Config Device address 0%o nodeID %d\n", address, mesh_nodeID); #endif @@ -81,7 +81,7 @@ bool RF24Gateway::begin(bool configTUN, bool meshEnable, uint16_t address, uint8 } network.multicastRelay = 1; - //#if (DEBUG >= 1) + //#if (DEBUG_LEVEL >= 1) radio.printDetails(); //#endif @@ -165,7 +165,7 @@ int RF24Gateway::configDevice(uint16_t address) flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE; } tunFd = allocateTunDevice(tunName, flags, address); - #if DEBUG >= 1 + #if DEBUG_LEVEL >= 1 if (tunFd >= 0) { std::cout << "RF24Gw: Successfully attached to tun/tap device " << tunTapDevice << std::endl; } @@ -200,7 +200,7 @@ int RF24Gateway::allocateTunDevice(char *dev, int flags, uint16_t address) // Create device if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) { //close(fd); - //#if (DEBUG >= 1) + //#if (DEBUG_LEVEL >= 1) std::cerr << "RF24Gw: Error: enabling TUNSETIFF" << std::endl; std::cerr << "RF24Gw: If changing from TAP/TUN, run 'sudo ip link delete tun_nrf24' to remove the interface" << std::endl; return -1; @@ -209,7 +209,7 @@ int RF24Gateway::allocateTunDevice(char *dev, int flags, uint16_t address) //Make persistent if (ioctl(fd, TUNSETPERSIST, 1) < 0) { - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) std::cerr << "RF24Gw: Error: enabling TUNSETPERSIST" << std::endl; #endif return -1; @@ -229,7 +229,7 @@ int RF24Gateway::allocateTunDevice(char *dev, int flags, uint16_t address) memcpy((char *)&ifr.ifr_hwaddr, (char *)&sap, sizeof(struct sockaddr)); if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { - #if DEBUG >= 1 + #if DEBUG_LEVEL >= 1 fprintf(stderr, "RF24Gw: Failed to set MAC address\n"); #endif } @@ -396,10 +396,10 @@ void RF24Gateway::handleRadioIn() memcpy(&msg.message, &f.message_buffer, bytesRead); msg.size = bytesRead; - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) std::cout << "Radio: Received " << bytesRead << " bytes ... " << std::endl; #endif - #if (DEBUG >= 3) + #if (DEBUG_LEVEL >= 3) //printPayload(msg.getPayloadStr(),"radio RX"); std::cout << "TunRead: " << std::endl; for (size_t i = 0; i < msg.size; i++) { @@ -465,11 +465,11 @@ void RF24Gateway::handleRadioOut() msgStruct *msgTx = &txQueue.front(); - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) std::cout << "Radio: Sending " << msgTx->size << " bytes ... "; std::cout << std::endl; #endif - #if (DEBUG >= 3) + #if (DEBUG_LEVEL >= 3) //PrintDebug == 1 does not have an endline. //printPayload(msg.getPayloadStr(),"radio TX"); #endif @@ -602,10 +602,10 @@ void RF24Gateway::handleRX(uint32_t waitDelay) if (FD_ISSET(tunFd, &socketSet)) { if ((nread = read(tunFd, buffer, MAX_PAYLOAD_SIZE)) >= 0) { - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) std::cout << "Tun: Successfully read " << nread << " bytes from tun device" << std::endl; #endif - #if (DEBUG >= 3) + #if (DEBUG_LEVEL >= 3) std::cout << "TunRead: " << std::endl; for (int i = 0; i < nread; i++) { @@ -624,7 +624,7 @@ void RF24Gateway::handleRX(uint32_t waitDelay) } } else { - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) std::cerr << "Tun: Error while reading from tun/tap interface." << std::endl; #endif } @@ -657,18 +657,18 @@ void RF24Gateway::handleTX() if (writtenBytes != msg->size) { //std::cerr << "Tun: Less bytes written to tun/tap device then requested." << std::endl; - #if DEBUG >= 1 + #if DEBUG_LEVEL >= 1 printf("Tun: Less bytes written %d to tun/tap device then requested %d.", writtenBytes, msg->size); #endif } else { - #if (DEBUG >= 1) + #if (DEBUG_LEVEL >= 1) std::cout << "Tun: Successfully wrote " << writtenBytes << " bytes to tun device" << std::endl; #endif } - #if (DEBUG >= 3) + #if (DEBUG_LEVEL >= 3) //printPayload(msg.message,"tun write"); std::cout << "TunRead: " << std::endl; for (size_t i = 0; i < msg->size; i++) { diff --git a/RF24Gateway.h b/RF24Gateway.h index e4d35c0..7a8c900 100644 --- a/RF24Gateway.h +++ b/RF24Gateway.h @@ -34,7 +34,9 @@ #define IFF_MULTI_QUEUE 0x0100 #endif -#define DEBUG 0 +#ifndef DEBUG_LEVEL + #define DEBUG_LEVEL 0 +#endif // DEBUG_LEVEL #define BACKLOG 10 /* Passed to listen() */ From 9ea06ee5a45cd7d0be1128fd0f3238fc05478e2d Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Fri, 18 Jun 2021 15:18:22 -0700 Subject: [PATCH 22/24] limit Doxygen CI trigger during open PR --- .github/workflows/doxygen.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index c73ac2b..8301e94 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -2,6 +2,7 @@ name: DoxyGen build on: pull_request: + types: [opened, reopened] paths: - "*.h" - "*.md" From fecc698e2f595d4266312a182a2df39cbe5204b1 Mon Sep 17 00:00:00 2001 From: 2bndy5 <2bndy5@gmail.com> Date: Thu, 5 Aug 2021 12:35:53 -0700 Subject: [PATCH 23/24] Update mqttLogger.py --- examples/addons/mqttLogger.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/addons/mqttLogger.py b/examples/addons/mqttLogger.py index d653ac3..682b3a2 100644 --- a/examples/addons/mqttLogger.py +++ b/examples/addons/mqttLogger.py @@ -7,12 +7,16 @@ Simple MQTT data logger, listens for UDP output from RF24Gateway & logs to an MQTT topic For use with RF24Mesh nodes that are not able to communicate directly via TCP/IP etc See RF24Gateway examples: - RF24NetworkFrame frame = RF24NetworkFrame(header,buf,size); - gw.sendUDP(mesh.getNodeID(header.from_node),frame); + RF24NetworkFrame frame = RF24NetworkFrame(header, buf, size); + gw.sendUDP(mesh.getNodeID(header.from_node), frame); """ import paho.mqtt.client as mqtt import socket -import sys + +try: #python 2 to 3 hack + unicode("") # all strings are unicode in python3 +except NameError: + unicode = str # does the same thing as python2's builtin unicode() ### Setup the MQTT host IP & topic to publish to mqttHost = "10.10.2.2" @@ -38,4 +42,4 @@ mqttc.connect(mqttHost, 1883) data = unicode(data, errors="replace") mqttc.publish(topic, data) - mqttc.loop(2) \ No newline at end of file + mqttc.loop(2) From f35b2930032c8351c5d28ecc5a00ec87682967ae Mon Sep 17 00:00:00 2001 From: 2bndy5 <2bndy5@gmail.com> Date: Sun, 14 Nov 2021 16:04:28 -0800 Subject: [PATCH 24/24] [CI] use RF24* master; save doc builds as artifact --- .github/workflows/build_linux.yml | 2 -- .github/workflows/doxygen.yml | 58 ++++++++++++++++++------------- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index e75a5dd..265916e 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -91,7 +91,6 @@ jobs: uses: actions/checkout@v2 with: repository: nRF24/RF24Network - ref: CMake-4-Linux - name: build & install RF24Network run: | @@ -106,7 +105,6 @@ jobs: uses: actions/checkout@v2 with: repository: nRF24/RF24Mesh - ref: CMake-4-Linux - name: build & install RF24Mesh run: | diff --git a/.github/workflows/doxygen.yml b/.github/workflows/doxygen.yml index 8301e94..b06d67d 100644 --- a/.github/workflows/doxygen.yml +++ b/.github/workflows/doxygen.yml @@ -1,4 +1,4 @@ -name: DoxyGen build +name: build Docs on: pull_request: @@ -29,26 +29,36 @@ jobs: runs-on: ubuntu-latest steps: - - name: get latest release version number - id: latest_ver - uses: pozetroninc/github-action-get-latest-release@master - with: - repository: nRF24/RF24Gateway - - name: checkout - uses: actions/checkout@v2 - - name: overwrite doxygen tags - run: | - touch doxygenAction - echo "PROJECT_NUMBER = ${{ steps.latest_ver.outputs.release }}" >> doxygenAction - echo "@INCLUDE = doxygenAction" >> Doxyfile - - name: build doxygen - uses: mattnotmitt/doxygen-action@v1 - with: - working-directory: '.' - doxyfile-path: './Doxyfile' - - name: upload to github pages - if: ${{ github.event_name == 'release'}} - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs/html \ No newline at end of file + - name: get latest release version number + id: latest_ver + uses: pozetroninc/github-action-get-latest-release@master + with: + repository: nRF24/RF24Gateway + + - name: checkout + uses: actions/checkout@v2 + + - name: overwrite doxygen tags + run: | + touch doxygenAction + echo "PROJECT_NUMBER = ${{ steps.latest_ver.outputs.release }}" >> doxygenAction + echo "@INCLUDE = doxygenAction" >> Doxyfile + + - name: build doxygen + uses: mattnotmitt/doxygen-action@v1 + with: + working-directory: '.' + doxyfile-path: './Doxyfile' + + - name: Save doxygen docs as artifact + uses: actions/upload-artifact@v2 + with: + name: "RF24Gateway_doxygen_docs" + path: ${{ github.workspace }}/docs/html + + - name: upload to github pages + if: ${{ github.event_name == 'release'}} + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs/html \ No newline at end of file