Conversation
Added SMCE_Client, a terminal interface for libSMCE.
Implemented a way to handle more then one input, to make it possible for example sending message
NOT WORKING! KNOWN BUG.
Move SMCE_Client to its own folder, created a CMakeLists that installs SMCE_Client.exe and copys the SMCE.dll from the path of enviroment variable SMCE_ROOT.
Added GPIO functionality to libSMCE client
Fixed bugg with recompile causing thread to crash. Added termcolor library to set color for uart messages. Added mute for uart messages.
Added functionality to set Arduino root folder Added functionality to set SMCE_RESOURCE at runtime
Added so incoming uart messages can be written to a file instead of console. Set at start by setting the start argument -u or --file to true.
Codecov Report
@@ Coverage Diff @@
## master #51 +/- ##
===========================================
+ Coverage 40.08% 63.26% +23.18%
===========================================
Files 33 82 +49
Lines 1497 2986 +1489
===========================================
+ Hits 600 1889 +1289
- Misses 897 1097 +200
Continue to review full report at Codecov.
|
AeroStun
left a comment
There was a problem hiding this comment.
This code is barely readable; reformat it (ClangFormat is your friend).
Also the general conditional complexity in main tends to be overwhelming; try factorizing it out using lookup tables, functions, etc...
| ) | ||
|
|
||
|
|
||
| add_library (objSMCE OBJECT) |
| include/SMCE/SketchConf.hpp | ||
| include/SMCE/internal/BoardDeviceSpecification.hpp | ||
| ) | ||
|
|
client/CMakeLists.txt
Outdated
| ) | ||
| FetchContent_MakeAvailable(Termcolor Lyra) | ||
|
|
||
| include_directories(${PROJECT_SOURCE_DIR}/src) |
There was a problem hiding this comment.
Never use global include_directories; see target_include_directories for a pure alternative
| target_include_directories (${PROJECT_NAME} PUBLIC | ||
| "${termcolor_SOURCE_DIR}/include/termcolor" | ||
| "${lyra_SOURCE_DIR}/include/lyra" | ||
| ) |
There was a problem hiding this comment.
I would be incredibly surprised that the termcolor::termcolor and bfg::Lyra targets don't already provide those directories in their interface properties
client/README.md
Outdated
| To be able to build SMCE_client, the enviroment variable SMCE_ROOT needs to point to a current installed release of libSMCE. | ||
| These can be found under releases on git. Or it can be build directly from the source code with the commands below. | ||
| These should be ran in the libSMCE folder. | ||
| ```shell | ||
| cmake -S . -B build/ | ||
| cmake --build build/ | ||
| cmake --build build/ --config Release | ||
| cmake --install build/ --prefix <path to installation folder> |
There was a problem hiding this comment.
These instructions are both wrong and misplaced; this README is in a subfolder of the libSMCE project, so it stands to reason that readers have already read the top-level README
client/SMCE_Client.cpp
Outdated
|
|
||
| }else if (input.starts_with("-ra ")){ | ||
| bool read = true; | ||
| int index_pin = stoi(input.substr(3)); |
client/SMCE_Client.cpp
Outdated
|
|
||
| }else if (input.starts_with("-rd ")){ | ||
| bool read = true; | ||
| int index_pin = stoi(input.substr(3)); |
client/src/UartToFile.cpp
Outdated
| @@ -0,0 +1,28 @@ | |||
| #include <UartToFile.hpp> | |||
| #include <ctime> | |||
client/src/UartToFile.cpp
Outdated
| #include <fstream> | ||
| #include <iostream> | ||
|
|
||
| using namespace std; |
There was a problem hiding this comment.
If you are trying to give me a heart attack, this is definitely the way to go
| int uart_to_file(std::string message, std::string path){ | ||
| ofstream file; | ||
| file.open(path, std::ios_base::app); | ||
| file << get_time() +": " +message + "\n"; | ||
| file.close(); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
Opening/closing a file every time you need to write to it should be a definition of inefficiency.
RuthgerD
left a comment
There was a problem hiding this comment.
Focus on parting everything into components, just constantly ask yourself, "how would I test this", "could someone reuse this code as a library" and stuff like that.
| - Sketch path: Relative or absolute path to the sketch to run | ||
|
|
||
| ### Start arguments | ||
| -f,--fqbn <fqbn> -> <fqbn> = Fully qualified board name |
There was a problem hiding this comment.
just a note in general, fqbn is basically deprecated, so I would default this parameter
| std::string get_time(){ | ||
| time_t currentTime; | ||
| struct tm *localTime; | ||
|
|
||
| time( ¤tTime ); | ||
| localTime = localtime( ¤tTime ); | ||
|
|
||
| int hour = localTime->tm_hour; | ||
| int min = localTime->tm_min; | ||
| int sec = localTime->tm_sec; | ||
| return(to_string(hour)+":"+to_string(min)+":"+to_string(sec)); | ||
| } |
There was a problem hiding this comment.
this use the way better library:
https://en.cppreference.com/w/cpp/chrono#Clocks
client/src/UartToFile.cpp
Outdated
| #include <fstream> | ||
| #include <iostream> | ||
|
|
||
| using namespace std; |
There was a problem hiding this comment.
using std is a bad practice
| int uart_to_file(std::string message, std::string path){ | ||
| ofstream file; | ||
| file.open(path, std::ios_base::app); | ||
| file << get_time() +": " +message + "\n"; | ||
| file.close(); | ||
| return 0; | ||
| } |
There was a problem hiding this comment.
this is a highly specifically named module and a highly specifically named function name even though all it does write to a file. I would generalize this, also, this is one of the cases where you might want to keep the file open for the duration of the program as constantly opening a file is not very nice.
client/SMCE_Client.cpp
Outdated
| void print_help(const char* argv0){ | ||
| std::cout << "Usage: " << argv0 << " <fully-qualified-board-name> <path-to-sketch>" << std::endl; | ||
| } |
There was a problem hiding this comment.
stuff like this can just be in the main function
client/SMCE_Client.cpp
Outdated
| print_menu(); | ||
|
|
||
| }else if (input == "-p"){ //pause or resume | ||
| if(!suspended){ |
There was a problem hiding this comment.
better read the state from the board instead of keeping track of it yourself
client/SMCE_Client.cpp
Outdated
| }else if (input == "-rc"){ //recompile | ||
| std::cout << "Recompiling.." << std::endl; | ||
| t_lock.lock(); // aquire lock before recompiling, so uart_listener is forced to wait | ||
| compile_and_start(sketch,toolchain,board,arduino_root_dir); |
There was a problem hiding this comment.
a function like this just makes things opaque imo, why not have a compile function and a start function that you just calls after each other? they dont need to be composed.
client/SMCE_Client.cpp
Outdated
| std::cout << "Complete" << std::endl; | ||
|
|
||
| }else if (input.starts_with("-m ")){ //send message on uart | ||
| std::string message = input.substr(3); |
client/SMCE_Client.cpp
Outdated
| if(!apin.exists()){ | ||
| std::cout << "Pin does not exist!" << std::endl; | ||
| write=false; | ||
| } | ||
| if(!apin.can_write()){ | ||
| std::cout << "Can't write to pin!" << std::endl; | ||
| write=false; | ||
| } | ||
| if(write){ | ||
| apin.write(value); | ||
| } |
There was a problem hiding this comment.
if () else if() else { ::write }
client/SMCE_Client.cpp
Outdated
| if(value == 0){ | ||
| apin.write(false); | ||
| }else if(value == 1){ | ||
| apin.write(true); | ||
| }else{ | ||
| std::cout << "Value must be 0 or 1 for digital pins" << std::endl; | ||
| } |
There was a problem hiding this comment.
tbh apin.write(value > 0), it works like this internally as well
client/SMCE_Client.cpp
Outdated
| static std::atomic_bool mute_uart = false; | ||
| static std::mutex t_lock; | ||
| //Listen to the uart input from board, writes what it read to terminal | ||
| void uart_listener(smce::VirtualUart uart,bool file_write,std::string path){ |
There was a problem hiding this comment.
yeah as discussed, taking the VirtualUart by value and reusing it across recompilations is completely wrong and likely reads invalid memory
Focused on the smaller problems from the pull request review. Still has several bugs / changes that needs to be done.
| }else if (input.starts_with("-rd ")){ | ||
| bool read = true; | ||
| int index_pin = stoi(input.substr(3)); | ||
| }else if (!pin.can_read()) { |
There was a problem hiding this comment.
Just because the board cannot read does not mean the user should not be able to see the value
| std::cout << "Pin does not exist!" << std::endl; | ||
| read=false; | ||
| } | ||
| if(!pin.can_read()){ | ||
| }else if (!pin.can_read()) { | ||
| std::cout << "Can't read from pin!" << std::endl; |
| } else if (input == "-q") { // power off and quit | ||
| std::cout << "Quitting..." << std::endl; | ||
| run_threads = false; | ||
| board.stop(); |
We are aware that the code is in need of refactoring, but we are not sure how we should go about it and also what to prioritize.