diff --git a/.gitignore b/.gitignore index 562ed72..f9b09a9 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ Thumbs.db *.pyc build/ +build_armhf/ doc/ .idea/ cmake-build-debug/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 5446560..c4aaf72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,13 @@ endif() # to correctly compile the codebase despite this line being in the # downstream CMake files. set (CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi") + +option(GCC_DIAG_COLORS "Enable GCC Diagnostic Colors" ON) +if (GCC_DIAG_COLORS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") +endif() LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules) diff --git a/appendages/include/appendages/exceptions.hpp b/appendages/include/appendages/exceptions.hpp index c7ddb44..e2a7b23 100644 --- a/appendages/include/appendages/exceptions.hpp +++ b/appendages/include/appendages/exceptions.hpp @@ -17,8 +17,8 @@ * \$$ $$ | $$ | $$ \$$\ | $$ | $$| $$ \| $$ * \$$$$$$ \$$ \$$ \$$ \$$ \$$ \$$$$$$ \$$ */ -#ifndef EXCEPTIONS_HPP -#define EXCEPTIONS_HPP +#ifndef APPENDAGES_EXCEPTIONS_HPP +#define APPENDAGES_EXCEPTIONS_HPP #include namespace rip @@ -28,7 +28,9 @@ namespace rip NEW_EX(CommandNotFound) NEW_EX(AppendageWithoutType) NEW_EX(AppendageWithoutLabel) - NEW_EX(AppendageWithId) + NEW_EX(AppendageWithoutId) + NEW_EX(AppendageMissingField) + NEW_EX(AppendageNotImplemented) } } -#endif // EXCEPTIONS_HPP +#endif // APPENDAGES_EXCEPTIONS_HPP diff --git a/appendages/include/appendages/roboclaw.hpp b/appendages/include/appendages/roboclaw.hpp new file mode 100644 index 0000000..782946d --- /dev/null +++ b/appendages/include/appendages/roboclaw.hpp @@ -0,0 +1,68 @@ +#ifndef ROBOCLAW_HPP +#define ROBOCLAW_HPP + +#include +#include +#include +#include + +#include "appendages/appendage.hpp" +#include "appendages/appendage_factory.hpp" + +#include + +namespace rip +{ + namespace appendages + { + class Roboclaw : public Appendage + { + public: + void SetSpeed(int32_t speed1, int32_t speed2); + void SetSpeedAccel(int32_t accel, int32_t speed1, int32_t speed2); + std::tuple ReadEncoders(); + void SetDuty(int16_t duty1, int16_t duty2); + void SetVelocityPID(uint8_t motor, float Kp, float Ki, float Kd, uint32_t qpps); + + /** + * Stop + */ + virtual void stop() override; + + virtual bool diagnostic() override; + + protected: + friend class AppendageFactory; + + /** + * Function wrapper for the constructor so it can be pointed to + * + * @param config The config from arduino gen + * @param command_map A map of the name of the commands to their enumerations + * @param device The connection to the device + */ + static std::shared_ptr create(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device); + + private: + /** + * Constructor + * + * @param config The config from arduino gen + * @param command_map A map of the name of the commands to their enumerations + * @param device The connection to the device + */ + Roboclaw(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device); + + uint8_t m_address; + + std::shared_ptr m_set_speed; + std::shared_ptr m_set_speed_accel; + std::shared_ptr m_read_encoders; + std::shared_ptr m_read_encoders_result; + std::shared_ptr m_set_duty; + std::shared_ptr m_set_velocity_pid; + }; + } +} + +#endif // ROBOCLAW_HPP diff --git a/appendages/include/appendages/servo.hpp b/appendages/include/appendages/servo.hpp index 30ccd70..4e4f203 100644 --- a/appendages/include/appendages/servo.hpp +++ b/appendages/include/appendages/servo.hpp @@ -25,6 +25,8 @@ namespace rip */ void write(int value); + void attach(bool state); + /** * Stop */ @@ -55,6 +57,7 @@ namespace rip Servo(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device); std::shared_ptr m_write; + std::shared_ptr m_attach; }; } } diff --git a/appendages/json/roboclaw.json b/appendages/json/roboclaw.json new file mode 100644 index 0000000..eb28aa1 --- /dev/null +++ b/appendages/json/roboclaw.json @@ -0,0 +1,8 @@ +{ + "serial": "string", + "baudrate": "int", + "address": "int", + "core": [ + "address" + ] +} diff --git a/appendages/json/servo.json b/appendages/json/servo.json new file mode 100644 index 0000000..d91013b --- /dev/null +++ b/appendages/json/servo.json @@ -0,0 +1,4 @@ +{ + "pin": "int", + "initialValue": "int" +} diff --git a/appendages/json/ultrasonic.json b/appendages/json/ultrasonic.json new file mode 100644 index 0000000..111bc0c --- /dev/null +++ b/appendages/json/ultrasonic.json @@ -0,0 +1,5 @@ +{ + "triggerPin": "int", + "echoPin": "int", + "minSleepMs": "int" +} diff --git a/appendages/src/appendage.cpp b/appendages/src/appendage.cpp index 081fa4d..ddc98a4 100644 --- a/appendages/src/appendage.cpp +++ b/appendages/src/appendage.cpp @@ -48,15 +48,23 @@ namespace rip if (config.find("label") == config.end()) { - throw AppendageWithoutLabel(fmt::format("appendage missing label")); + throw AppendageWithoutLabel(fmt::format("appendage of type {} is missing label", m_type)); } m_label = config["label"]; + if (config.find("id") == config.end() && config.find("index") == config.end()) + { + throw AppendageWithoutId(fmt::format("appendage labeled {} is missing an id or index", m_label)); + } + if (config.find("id") == config.end()) { - throw AppendageWithId(fmt::format("appendage missing id")); + m_id = config["index"]; + } + else + { + m_id = config["id"]; } - m_id = config["id"]; } } } diff --git a/appendages/src/appendage_factory.cpp b/appendages/src/appendage_factory.cpp index ae785d3..40b4c27 100644 --- a/appendages/src/appendage_factory.cpp +++ b/appendages/src/appendage_factory.cpp @@ -5,6 +5,9 @@ // Appendages #include "appendages/digital_input.hpp" #include "appendages/analog_input.hpp" +#include "appendages/roboclaw.hpp" +#include "appendages/servo.hpp" +#include "appendages/ultrasonic.hpp" #include "appendages/exceptions.hpp" @@ -29,8 +32,14 @@ namespace rip { throw AppendageWithoutType(fmt::format("appendage missing type")); } - - return m_constructors["type"](config, command_map, device); + std::string appendage_type = config["type"]; + if (m_constructors.find(appendage_type) == m_constructors.end()) + { + // we probably don't have this appendage type available to the factory + throw AppendageNotImplemented(fmt::format("Factory: no Constructor for appendage type {} !", appendage_type)); + } + misc::Logger::getInstance()->debug(fmt::format("Factory: Constructing an appendage of type {} ...", appendage_type)); + return m_constructors[appendage_type](config, command_map, device); } void AppendageFactory::registerAppendage(const std::string& type, std::function(const nlohmann::json&, @@ -45,6 +54,9 @@ namespace rip { registerAppendage("Digital Input", &DigitalInput::create); registerAppendage("Analog Input", &AnalogInput::create); + registerAppendage("Roboclaw", &Roboclaw::create); + registerAppendage("Servo", &Servo::create); + registerAppendage("Ultrasonic", &Ultrasonic::create); } } } diff --git a/appendages/src/roboclaw.cpp b/appendages/src/roboclaw.cpp new file mode 100644 index 0000000..9185ad7 --- /dev/null +++ b/appendages/src/roboclaw.cpp @@ -0,0 +1,183 @@ +#include "appendages/roboclaw.hpp" +#include +#include +#include +#include +#include +#include +#include + +#include "appendages/exceptions.hpp" + +namespace rip +{ + namespace appendages + { + Roboclaw::Roboclaw(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device) + : Appendage(config, device), + m_set_speed( + createCommand( + "kSetSpeed", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType + >() + ) + ), + m_set_speed_accel( + createCommand( + "kSetSpeedAccel", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType + >() + ) + ), + m_read_encoders( + createCommand( + "kReadEncoders", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType + >() + ) + ), + m_read_encoders_result(createCommand( + "kReadEncodersResult", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType + >() + ) + ), + m_set_duty( + createCommand( + "kSetDuty", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::UnsignedIntegerType, + cmdmessenger::ArduinoCmdMessenger::UnsignedIntegerType>() + ) + ), + m_set_velocity_pid( + createCommand( + "kSetVelocityPID", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::FloatType, + cmdmessenger::ArduinoCmdMessenger::FloatType, + cmdmessenger::ArduinoCmdMessenger::FloatType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType>() + ) + ) + { + if (config.find("address") == config.end()) + { + throw AppendageMissingField(fmt::format("Roboclaw: missing config field 'address'")); + } + m_address = config["address"]; + } + + std::shared_ptr Roboclaw::create(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device) + { + return std::dynamic_pointer_cast(std::shared_ptr(new Roboclaw(config, command_map, device))); + } + + void Roboclaw::SetSpeed(int32_t speed1, int32_t speed2) + { + cmdmessenger::ArduinoCmdMessenger messenger; + messenger.send< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType + >(m_device, m_set_speed, m_id, m_address, speed1, speed2); + } + + void Roboclaw::SetSpeedAccel(int32_t accel, int32_t speed1, int32_t speed2) + { + cmdmessenger::ArduinoCmdMessenger messenger; + messenger.send< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType, + cmdmessenger::ArduinoCmdMessenger::UnsignedLongType + >(m_device, m_set_speed_accel, m_id, m_address, accel, speed1, speed2); + } + + std::tuple Roboclaw::ReadEncoders() + { + cmdmessenger::ArduinoCmdMessenger messenger; + messenger.send< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::CharType + >( + m_device, + m_read_encoders, + m_id, + m_address + ); + return messenger.receive(m_read_encoders_result); + } + + void Roboclaw::SetDuty(int16_t duty1, int16_t duty2) + { + cmdmessenger::ArduinoCmdMessenger messenger; + messenger.send(m_device, m_set_duty, m_id, m_address, duty1, duty2); + } + + void Roboclaw::SetVelocityPID(uint8_t motor, float Kp, float Ki, float Kd, uint32_t qpps) + { + cmdmessenger::ArduinoCmdMessenger messenger; + messenger.send(m_device, m_set_velocity_pid, m_address, motor, Kp, Ki, Kd, qpps); + } + + void Roboclaw::stop() { + misc::Logger::getInstance()->debug("Setting roboclaw duty to zero."); + SetDuty(0, 0); + } + + bool Roboclaw::diagnostic() + { + std::chrono::time_point start_time = std::chrono::system_clock::now(); + misc::Logger::getInstance()->debug("Roboclaw appendage diagnostics start"); + + misc::Logger::getInstance()->debug("Read encoders for 5s in a loop"); + while(std::chrono::duration_cast(std::chrono::system_clock::now() - start_time).count() < 5000) + { + misc::Logger::getInstance()->debug(fmt::format("Encoder 1 Ticks: {} | Encoder 2 Ticks: {}", std::get<0>(ReadEncoders()), std::get<1>(ReadEncoders()))); + } + misc::Logger::getInstance()->debug("Setting Duty to ~1/2 Power, forward for 5 seconds"); + misc::Logger::getInstance()->debug(fmt::format("Encoder 1 Ticks: {} | Encoder 2 Ticks: {}", std::get<0>(ReadEncoders()), std::get<1>(ReadEncoders()))); + SetDuty(16000, 16000); + start_time = std::chrono::system_clock::now(); + while(std::chrono::duration_cast(std::chrono::system_clock::now() - start_time).count() < 5000) + {} + misc::Logger::getInstance()->debug(fmt::format("Encoder 1 Ticks: {} | Encoder 2 Ticks: {}", std::get<0>(ReadEncoders()), std::get<1>(ReadEncoders()))); + stop(); + misc::Logger::getInstance()->debug("Setting speed accel drive (5s)"); + misc::Logger::getInstance()->debug(fmt::format("Encoder 1 Ticks: {} | Encoder 2 Ticks: {}", std::get<0>(ReadEncoders()), std::get<1>(ReadEncoders()))); + SetSpeedAccel(12000, 12000, 12000); + start_time = std::chrono::system_clock::now(); + while(std::chrono::duration_cast(std::chrono::system_clock::now() - start_time).count() < 5000) + {} + misc::Logger::getInstance()->debug(fmt::format("Encoder 1 Ticks: {} | Encoder 2 Ticks: {}", std::get<0>(ReadEncoders()), std::get<1>(ReadEncoders()))); + stop(); + misc::Logger::getInstance()->debug(fmt::format("Encoder 1 Ticks: {} | Encoder 2 Ticks: {}", std::get<0>(ReadEncoders()), std::get<1>(ReadEncoders()))); + } + } +} diff --git a/appendages/src/servo.cpp b/appendages/src/servo.cpp index e20d711..0990b14 100644 --- a/appendages/src/servo.cpp +++ b/appendages/src/servo.cpp @@ -12,7 +12,24 @@ namespace rip { Servo::Servo(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device) : Appendage(config, device) - , m_write(createCommand("kServoWrite", command_map, cmdmessenger::ArduinoCmdMessenger::makeArgumentString())) + , m_write( + createCommand( + "kSetServo", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::IntegerType>() + ) + ) + , m_attach( + createCommand( + "kAttachServo", + command_map, + cmdmessenger::ArduinoCmdMessenger::makeArgumentString< + cmdmessenger::ArduinoCmdMessenger::IntegerType, + cmdmessenger::ArduinoCmdMessenger::BooleanType>() + ) + ) { } @@ -24,12 +41,38 @@ namespace rip void Servo::stop() { + attach(false); + } + void Servo::attach(bool state) + { + cmdmessenger::ArduinoCmdMessenger messenger; + messenger.send(m_device, m_attach, m_id, state); } bool Servo::diagnostic() { - return true; + int new_val = 0; + std::cout << " === DIAG CONTROLS: === " << '\n'; + std::cout << " '-1': Quit." << '\n'; + std::cout << " '-2': Detach servo." << '\n'; + std::cout << " '0-180': Set servo position." << '\n'; + while (new_val != -1) { + // write(0); + std::cout << " >>> Please enter a servo value (int) to write (-1 quits): "; + std::cin >> new_val; + std::cout << " >>> Working...\n"; + if (new_val == -1) break; + else if (new_val == -2) + { + attach(false); + } + else + { + write(new_val); + } + } + return true; } std::shared_ptr Servo::create(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device) diff --git a/appendages/src/ultrasonic.cpp b/appendages/src/ultrasonic.cpp index 20270b5..cdcfe8e 100644 --- a/appendages/src/ultrasonic.cpp +++ b/appendages/src/ultrasonic.cpp @@ -3,6 +3,10 @@ #include #include #include +#include +#include + +#include #include @@ -12,8 +16,8 @@ namespace rip { Ultrasonic::Ultrasonic(const nlohmann::json& config, const std::map& command_map, std::shared_ptr device) : Appendage(config, device) - , m_read(createCommand("kUltrasonicRead", command_map, cmdmessenger::ArduinoCmdMessenger::makeArgumentString())) - , m_read_result(createCommand("kUltrasonicReadResult", command_map, cmdmessenger::ArduinoCmdMessenger::makeArgumentString())) + , m_read(createCommand("kReadUltrasonic", command_map, cmdmessenger::ArduinoCmdMessenger::makeArgumentString())) + , m_read_result(createCommand("kReadUltrasonicResult", command_map, cmdmessenger::ArduinoCmdMessenger::makeArgumentString())) { } @@ -26,11 +30,20 @@ namespace rip void Ultrasonic::stop() { - + // don't need to do anything. } bool Ultrasonic::diagnostic() { + std::chrono::time_point start_time = std::chrono::system_clock::now(); + misc::Logger::getInstance()->info("Reading the ultrasonic value for 10s."); + + while(std::chrono::duration_cast(std::chrono::system_clock::now() - start_time).count() < 10000) + { + misc::Logger::getInstance()->info(fmt::format("Distance: {} cm", read().to(units::cm))); + } + + misc::Logger::getInstance()->info("Ultrasonic diag finished."); return true; } diff --git a/appendages/xml/roboclaw.xml b/appendages/xml/roboclaw.xml new file mode 100644 index 0000000..eda1329 --- /dev/null +++ b/appendages/xml/roboclaw.xml @@ -0,0 +1,90 @@ + + + RoboClaw.h + + + + + + + + + roboclaws[$i$].begin($baudrate$); + + + + + + + + if (!roboclaws[indexNum].SpeedM1M2(address, speed1, speed2)) // TODO: Check return value + { + cmdMessenger.sendBinCmd(kError, kSetSpeed); + } + + + + + + + + + if (!roboclaws[indexNum].SpeedAccelM1M2(address, accel, speed1, speed2)) // TODO: Check return value + { + cmdMessenger.sendBinCmd(kError, kSetSpeedAccel); + } + + + + + + + + if (!roboclaws[indexNum].ReadEncoders(address, enc1, enc2)) // TODO: Check return value + { + cmdMessenger.sendBinCmd(kError, kReadEncoders); + } + + + + + + + + if (!roboclaws[indexNum].DutyM1M2(address, duty1, duty2)) // TODO: Check return value + { + cmdMessenger.sendBinCmd(kError, kSetDuty); + } + + + + + + + + + + + bool result; + + switch (motor) + { + case 1: + result = roboclaws[indexNum].SetM1VelocityPID(address, Kp, Ki, Kd, qpps); + break; + case 2: + result = roboclaws[indexNum].SetM2VelocityPID(address, Kp, Ki, Kd, qpps); + break; + default: + result = false; + break; + } + + if (!result) // TODO: Double check return values + { + cmdMessenger.sendBinCmd(kError, kSetVelocityPID); + } + + + + diff --git a/appendages/xml/servo.xml b/appendages/xml/servo.xml new file mode 100644 index 0000000..5ae10c7 --- /dev/null +++ b/appendages/xml/servo.xml @@ -0,0 +1,46 @@ + + + Servo.h + + + + + + + + + + + + + servos[$i$].attach($pin$); + servos[$i$].write($initialValue$); + delay(500); + servos[$i$].detach(); + + + // Servo pin: $pin$ + + + + + + if (!servos[indexNum].attached()) { + servos[indexNum].attach(servo_pins[indexNum]); + } + servos[indexNum].write(value); + + + + + + if (state) { + servos[indexNum].attach(servo_pins[indexNum]); + } + else { + servos[indexNum].detach(); + } + + + + diff --git a/appendages/xml/ultrasonic.xml b/appendages/xml/ultrasonic.xml new file mode 100644 index 0000000..5789321 --- /dev/null +++ b/appendages/xml/ultrasonic.xml @@ -0,0 +1,43 @@ + + + NewPing.h + + + + + + + + + + + + + + + + + + + // Ultrasonic triggerPin: $triggerPin$ + + + // Ultrasonic echoPin: $echoPin$ + + + + + + unsigned long curtime = millis(); + if (curtime < sonar_prevtime[indexNum]+sonar_timeouts[indexNum]) + { + delay(sonar_prevtime[indexNum]+sonar_timeouts[indexNum] - curtime ); + } + //rv = sonar[indexNum].ping_cm(); + unsigned long median_time = sonar[indexNum].ping_median(sonar_ping_medians[indexNum]); + rv = NewPing::convert_cm(median_time); + sonar_prevtime[indexNum] = millis(); + + + + diff --git a/arduino_gen/code_template.txt b/arduino_gen/code_template.txt index 2ccebfb..45b0607 100644 --- a/arduino_gen/code_template.txt +++ b/arduino_gen/code_template.txt @@ -10,7 +10,7 @@ const char LED = 13; {constructors} -enum +enum RIPenum : int16_t {{ {command_enums} }}; @@ -57,7 +57,7 @@ void attachCommandCallbacks() // Called when a received command has no attached function void unknownCommand() {{ - cmdMessenger.sendCmd(kError, kUnknown); + cmdMessenger.sendBinCmd(kError, kUnknown); }} // Called upon initialization of Spine to check connection diff --git a/arduino_gen/include/arduino_gen/appendage.hpp b/arduino_gen/include/arduino_gen/appendage.hpp index 9bc0c21..c1f64cb 100644 --- a/arduino_gen/include/arduino_gen/appendage.hpp +++ b/arduino_gen/include/arduino_gen/appendage.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -89,13 +90,15 @@ namespace rip * @exception ParameterInvalid This exception is thrown if a parameter is missing, * included but not in the template, or has the wrong type. */ - void testType() const; + void testType(); nlohmann::json m_data; - static std::map< std::string, std::map< std::string, std::string > > m_type_cache; + static std::map< std::string, nlohmann::json > m_type_cache; std::string m_appendage_data_folder; + + std::vector m_core_fields; }; } } diff --git a/arduino_gen/include/arduino_gen/argument.hpp b/arduino_gen/include/arduino_gen/argument.hpp index 30e6481..aaae0fe 100644 --- a/arduino_gen/include/arduino_gen/argument.hpp +++ b/arduino_gen/include/arduino_gen/argument.hpp @@ -56,6 +56,8 @@ namespace rip std::string m_name; std::string m_type; std::string m_value; + std::string m_prefix; + std::string m_suffix; }; } // arduinogen } diff --git a/arduino_gen/include/arduino_gen/exceptions.hpp b/arduino_gen/include/arduino_gen/exceptions.hpp index 3a1c97e..6642034 100644 --- a/arduino_gen/include/arduino_gen/exceptions.hpp +++ b/arduino_gen/include/arduino_gen/exceptions.hpp @@ -1,5 +1,5 @@ -#ifndef EXCEPTIONS_HPP -#define EXCEPTIONS_HPP +#ifndef ARDUINO_GEN_EXCEPTIONS_HPP +#define ARDUINO_GEN_EXCEPTIONS_HPP #include #include @@ -45,4 +45,4 @@ namespace rip } } -#endif // EXCEPTIONS_HPP +#endif // ARDUINO_GEN_EXCEPTIONS_HPP diff --git a/arduino_gen/src/appendage.cpp b/arduino_gen/src/appendage.cpp index 5ea1382..b291952 100644 --- a/arduino_gen/src/appendage.cpp +++ b/arduino_gen/src/appendage.cpp @@ -11,8 +11,7 @@ namespace rip { namespace arduinogen { - std::map< std::string, std::map< std::string, std::string> > Appendage::m_type_cache = - std::map< std::string, std::map< std::string, std::string> >(); + std::map< std::string, nlohmann::json > Appendage::m_type_cache = std::map< std::string, nlohmann::json >(); Appendage::Appendage(nlohmann::json j, std::multimap< std::string, std::shared_ptr >& appendages, @@ -109,7 +108,7 @@ namespace rip } } - void Appendage::testType() const + void Appendage::testType() { std::string type = getType(); @@ -149,69 +148,83 @@ namespace rip nlohmann::json j; (*type_template.createInputStream()) >> j; - std::map< std::string, std::string > temp; - for (nlohmann::json::iterator it = j.begin(); it != j.end(); ++it) { - temp[it.key()] = it.value(); - } - m_type_cache[type] = temp; + m_type_cache[type] = j; } - std::map< std::string, std::string >& type_check = m_type_cache[type]; + nlohmann::json& type_check = m_type_cache[type]; // Check if the appendage has all the parameters specified by the tempate // and that they are the correct type - for(std::pair< std::string, std::string> type_parameter : type_check) + for (nlohmann::json::iterator type_parameter = type_check.begin(); type_parameter != type_check.end(); ++type_parameter) { - if(m_data.find(type_parameter.first) == m_data.end()) + if (type_parameter.key() != "core" && m_data.find(type_parameter.key()) == m_data.end()) { - throw AppendageDataException(fmt::format("{} missing on {}", type_parameter.first, label)); + throw AppendageDataException(fmt::format("{} missing on {}", type_parameter.key(), label)); } - nlohmann::json parameter = m_data[type_parameter.first]; + nlohmann::json parameter = m_data[type_parameter.key()]; + + if (type_parameter.key() == "core") + { + if (!type_parameter.value().is_array()) + { + throw AppendageDataException(fmt::format("Core field is not an array for type {}", type)); + } - if(type_parameter.second == "int") + nlohmann::json& core_keys = type_parameter.value(); + for (nlohmann::json::iterator core_key = core_keys.begin(); core_key != core_keys.end(); ++core_key) + { + if (m_data.find(core_key.value().get()) == m_data.end()) + { + throw AppendageDataException(fmt::format("{} missing core field {}", label, core_key.value().get())); + } + + m_core_fields.emplace_back(core_key.value().get()); + } + } + else if(type_parameter.value() == "int") { if(!parameter.is_number_integer()) { throw AppendageDataException(fmt::format("Incorrect type for {} on {}. Should be an integer.", - type_parameter.first, label)); + type_parameter.key(), label)); } } - else if(type_parameter.second == "float") + else if(type_parameter.value() == "float") { if(!parameter.is_number_float()) { throw AppendageDataException(fmt::format("Incorrect type for {} on {}. Should be an integer.", - type_parameter.first, label)); + type_parameter.key(), label)); } } - else if(type_parameter.second == "string") + else if(type_parameter.value() == "string") { if(!parameter.is_string()) { throw AppendageDataException(fmt::format("Incorrect type for {} on {}. Should be a string.", - type_parameter.first, label)); + type_parameter.key(), label)); } } - else if(type_parameter.second == "bool") + else if(type_parameter.value() == "bool") { if(!parameter.is_boolean()) { throw AppendageDataException(fmt::format("Incorrect type for {} on {}. Should be a bool.", - type_parameter.first, label)); + type_parameter.key(), label)); } } - else if(type_parameter.second == "object") + else if(type_parameter.value() == "object") { if(!parameter.is_object()) { throw AppendageDataException(fmt::format("Incorrect type for {} on {}. Should be an object.", - type_parameter.first, label)); + type_parameter.key(), label)); } } else { - throw AppendageDataException(fmt::format("Unknown Type in template file for {}", type_parameter.first, + throw AppendageDataException(fmt::format("Unknown Type in template file for {}", type_parameter.key(), label)); } } @@ -234,6 +247,11 @@ namespace rip json["label"] = m_data["label"]; json["index"] = index; + for (std::string core_key : m_core_fields) + { + json[core_key] = m_data[core_key]; + } + return json; } } diff --git a/arduino_gen/src/arduino_gen.cpp b/arduino_gen/src/arduino_gen.cpp index 8051a65..5cf28b5 100644 --- a/arduino_gen/src/arduino_gen.cpp +++ b/arduino_gen/src/arduino_gen.cpp @@ -117,64 +117,94 @@ namespace rip { device_folder.removeDirectoryRec(); } - device_folder.createDirectory(); - device_folder.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | - FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + if (!device_folder.createDirectory()) + { + throw FileIoException(fmt::format("Could not create device folder: \"{}\"", device_folder.path())); + } + // device_folder.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | + // FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | + // FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); // Create src dir FileHandle source_folder = fs::open(fmt::format("{}/{}/{}", m_parent_folder, m_arduino, "src")); - source_folder.createDirectory(); - source_folder.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | - FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + if (!source_folder.createDirectory()) + { + throw FileIoException(fmt::format("Could not create source folder: \"{}\"", source_folder.path())); + } + // source_folder.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | + // FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | + // FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); // Create ino file FileHandle source = fs::open(fmt::format("{0}/{1}/src/{1}.ino", m_parent_folder, m_arduino)); - source.writeFile(getArduinoCode()); + if (!source.writeFile(getArduinoCode())) + { + throw FileIoException(fmt::format("Could not create source file: \"{}\"", source.path())); + } source.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); // Create config file FileHandle json_config = fs::open(fmt::format("{0}/{1}/{1}.json", m_parent_folder, m_arduino)); - json_config.writeFile(config); + if (!json_config.writeFile(config)) + { + throw FileIoException(fmt::format("Could not create json config: \"{}\"", json_config.path())); + } json_config.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); // Create core file FileHandle core_config = fs::open(fmt::format("{0}/{1}/{1}_core.json", m_parent_folder, m_arduino)); - core_config.writeFile(getCoreConfig()); + if (!core_config.writeFile(getCoreConfig())) + { + throw FileIoException(fmt::format("Could not create core config: \"{}\"", core_config.path())); + } core_config.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); // Create platformio.ini FileHandle platformio_ini = fs::open(fmt::format("{}/{}/platformio.ini", m_parent_folder, m_arduino)); - platformio_ini.writeFile(platformio_str); + if (!platformio_ini.writeFile(platformio_str)) + { + throw FileIoException(fmt::format("Could not create platformio.ini: \"{}\"", platformio_ini.path())); + } platformio_ini.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); // Create serial script FileHandle serial = fs::open(fmt::format("{0}/{1}/serial.sh", m_parent_folder, m_arduino)); - serial.writeFile(serial_str); + if (!serial.writeFile(serial_str)) + { + throw FileIoException(fmt::format("Could not create serial.sh: \"{}\"", serial.path())); + } serial.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); // Create upload script FileHandle upload = fs::open(fmt::format("{0}/{1}/upload.sh", m_parent_folder, m_arduino)); - upload.writeFile(upload_str); + if (!upload.writeFile(upload_str)) + { + throw FileIoException(fmt::format("Could not create upload.sh: \"{}\"", upload.path())); + } upload.setPermissions(FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); } std::string ArduinoGen::getArduinoCode() { - std::unique_ptr code_template_istream = cppfs::fs::open("code_template.txt").createInputStream(); + cppfs::FileHandle code_template_fh = cppfs::fs::open("code_template.txt"); + if (!code_template_fh.exists() || !code_template_fh.isFile()) + { + throw FileIoException("code_template.txt does not exist"); + } + + std::unique_ptr code_template_istream = code_template_fh.createInputStream(); std::string code_template(std::istreambuf_iterator(*code_template_istream), {}); return fmt::format(code_template, diff --git a/arduino_gen/src/argument.cpp b/arduino_gen/src/argument.cpp index f8d6640..38f672a 100644 --- a/arduino_gen/src/argument.cpp +++ b/arduino_gen/src/argument.cpp @@ -27,10 +27,31 @@ namespace rip m_value = ""; } + m_prefix = ""; + m_suffix = ""; + if (m_type == "string_literal") + { + try + { + m_prefix = getAttribute("prefix")->Value(); + } + catch (AttributeException) + { } + + try + { + m_suffix = getAttribute("suffix")->Value(); + } + catch (AttributeException) + { } + } + if(m_type != "float" && m_type != "int" && m_type != "bool" && - m_type != "string") + m_type != "string" && + m_type != "long" && + m_type != "string_literal") { throw AttributeException(fmt::format("Constructor argument unknown type on line number {}", xml->GetLineNum())); @@ -53,13 +74,13 @@ namespace rip std::string Argument::toString(std::shared_ptr appendage) const { - if (appendage->has(m_name)) - { - if(!appendage->isType(m_name, m_type)) - { - // TODO(Andrew): throw exception - } - return appendage->getString(m_name); + if (appendage->has(m_name)) + { + if (!appendage->isType(m_name, m_type == "string_literal" ? "string" : m_type)) + { + // TODO(Andrew): throw exception + } + return m_prefix + appendage->getString(m_name) + m_suffix; } else { diff --git a/arduino_gen/src/constructor.cpp b/arduino_gen/src/constructor.cpp index 806ac3b..aaa095e 100644 --- a/arduino_gen/src/constructor.cpp +++ b/arduino_gen/src/constructor.cpp @@ -66,10 +66,10 @@ namespace rip { if (appendage->has(argument.getName())) { - if (appendage->isType(argument.getName(), "string")) - { - rv += fmt::format("\"{}\"", argument.toString(appendage)); - } + if (argument.getType() == "string") + { + rv += fmt::format("\"{}\"", argument.toString(appendage)); + } else { rv += argument.toString(appendage); diff --git a/arduino_gen/src/main.cpp b/arduino_gen/src/main.cpp index 69920f6..11c025b 100644 --- a/arduino_gen/src/main.cpp +++ b/arduino_gen/src/main.cpp @@ -6,7 +6,11 @@ #include #include +#include "misc/exception_base.hpp" #include "arduino_gen/arduino_gen.hpp" +#include "misc/exception_base.hpp" + +#include int main(int argc, char* argv[]) { @@ -96,7 +100,7 @@ int main(int argc, char* argv[]) { ag.readConfig(args::get(config)); } - catch (std::exception e) + catch (rip::utilities::ExceptionBase e) { std::cerr << "ArduinoGen failed to read the config file.\n" << e.what() << std::endl; return EXIT_FAILURE; @@ -106,7 +110,7 @@ int main(int argc, char* argv[]) { ag.generateOutput(!args::get(noCopy)); } - catch (std::exception e) + catch (rip::utilities::ExceptionBase e) { std::cerr << "ArduinoGen failed to generate the output.\n" << e.what() << std::endl; return EXIT_FAILURE; @@ -140,5 +144,7 @@ int main(int argc, char* argv[]) } } + std::system(fmt::format("chmod -R g+w {}/{}", args::get(parent_folder), args::get(arduino)).c_str()); + return EXIT_SUCCESS; } diff --git a/arduino_gen/test/test_arduino_gen.cpp b/arduino_gen/test/test_arduino_gen.cpp index e04bef8..be13f6a 100644 --- a/arduino_gen/test/test_arduino_gen.cpp +++ b/arduino_gen/test/test_arduino_gen.cpp @@ -594,7 +594,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -689,7 +689,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -788,7 +788,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -902,7 +902,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -1024,7 +1024,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -1395,7 +1395,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -1548,30 +1548,31 @@ namespace rip // Check the file permissions #ifndef _WIN32 - EXPECT_EQ(device_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | - FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); - EXPECT_EQ(source_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | - FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + // TODO setGID support + // EXPECT_EQ(device_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | + // FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | + // FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + // EXPECT_EQ(source_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | + // FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | + // FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); EXPECT_EQ(source.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); EXPECT_EQ(config.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); EXPECT_EQ(core.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); EXPECT_EQ(upload.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); EXPECT_EQ(serial.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); EXPECT_EQ(platformio.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); #endif // Change the platformio.ini file @@ -1704,7 +1705,7 @@ namespace rip "// Called when a received command has no attached function\n" "void unknownCommand()\n" "{\n" - "\tcmdMessenger.sendCmd(kError, kUnknown);\n" + "\tcmdMessenger.sendBinCmd(kError, kUnknown);\n" "}\n" "\n" "// Called upon initialization of Spine to check connection\n" @@ -1857,30 +1858,31 @@ namespace rip // Check the file permissions #ifndef _WIN32 - EXPECT_EQ(device_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | - FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); - EXPECT_EQ(source_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | - FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + // TODO setGID special bit support + // EXPECT_EQ(device_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | + // FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | + // FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + // EXPECT_EQ(source_folder.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | + // FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | + // FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); EXPECT_EQ(source.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); EXPECT_EQ(config.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); EXPECT_EQ(core.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); EXPECT_EQ(upload.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); EXPECT_EQ(serial.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::UserExec | FilePermissions::GroupRead | FilePermissions::GroupWrite | FilePermissions::GroupExec | - FilePermissions::OtherRead | FilePermissions::OtherWrite | FilePermissions::OtherExec); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite | FilePermissions::OtherExec); EXPECT_EQ(platformio.permissions(), FilePermissions::UserRead | FilePermissions::UserWrite | FilePermissions::GroupRead | FilePermissions::GroupWrite | - FilePermissions::OtherRead | FilePermissions::OtherWrite); + FilePermissions::OtherRead);// | FilePermissions::OtherWrite); #endif // Cleanup diff --git a/build-linux.sh b/build-linux.sh index 51bda5a..f974f7a 100755 --- a/build-linux.sh +++ b/build-linux.sh @@ -1,30 +1,72 @@ #!/bin/zsh set -E +BUILDDIR="build" +ENABLE_TESTING="ON" + +if [[ "$(dpkg --print-architecture)" == "armhf" ]]; then + BUILDDIR="${BUILDDIR}_armhf" +fi + while [[ "$1" != "" ]]; do case "$1" in - "--help"|"-h") - echo "$0